On Wed, 30. Oct 09:45, Andriy Gelman wrote: > On Thu, 24. Oct 20:50, Andriy Gelman wrote: > > On Tue, 15. Oct 22:50, Andriy Gelman wrote: > > > From: Andriy Gelman <andriy.gel...@gmail.com> > > > > > > Fixes #7799 > > > > > > Currently, the mp4toannexb filter always inserts the same extradata at > > > the start of the first IRAP unit. As in ticket #7799, this can lead to > > > decoding errors if modified parameter sets are signalled in-band. > > > > > > Decoding errors/visual artifacts are also present in the following > > > fate-suite/hevc-conformance datasets for hevc->mp4->hevc conversion: > > > -RAP_B_Bossen_1.bit > > > -RPS_C_ericsson_5.bit > > > -SLIST_A_Sony_4.bit > > > -SLIST_B_Sony_8.bit > > > -SLIST_C_Sony_3.bit > > > -SLIST_D_Sony_9.bit > > > -TSKIP_A_MS_2.bit > > > > > > This commit solves these errors by keeping track of VPS/SPS/PPS parameter > > > sets > > > during the conversion. The correct combination is inserted at the start > > > of the first IRAP. SEIs from extradata are inserted before each IRAP. > > > > > > This commit also makes an update to the hevc-bsf-mp4toannexb fate test > > > since the result before this patch contained duplicate parameter sets > > > in-band. > > > --- > > > libavcodec/hevc_mp4toannexb_bsf.c | 503 ++++++++++++++++++++++++++++-- > > > tests/fate/hevc.mak | 2 +- > > > 2 files changed, 472 insertions(+), 33 deletions(-) > > > > > > diff --git a/libavcodec/hevc_mp4toannexb_bsf.c > > > b/libavcodec/hevc_mp4toannexb_bsf.c > > > index 09bce5b34c..1ca5f13807 100644 > > > --- a/libavcodec/hevc_mp4toannexb_bsf.c > > > +++ b/libavcodec/hevc_mp4toannexb_bsf.c > > > @@ -23,19 +23,224 @@ > > > > > > #include "libavutil/intreadwrite.h" > > > #include "libavutil/mem.h" > > > +#include "libavutil/avassert.h" > > > > > > #include "avcodec.h" > > > #include "bsf.h" > > > #include "bytestream.h" > > > #include "hevc.h" > > > +#include "h2645_parse.h" > > > +#include "hevc_ps.h" > > > +#include "golomb.h" > > > > > > #define MIN_HEVCC_LENGTH 23 > > > +#define PROFILE_WITHOUT_IDC_BITS 88 > > > +#define IS_IRAP(s) ((s)->type >= 16 && (s)->type <= 23) > > > +#define IS_PARAMSET(s) ((s)->type >= 32 && (s)->type <= 34) > > > + > > > + /*reserved VCLs not included*/ > > > +#define IS_VCL(s) ((s)->type <= 9 || ((s)->type >= 16 > > > && (s)->type <= 21)) > > > +#define HEVC_NAL_HEADER_BITS 16 > > > + > > > +/* > > > + * Copies data from input buffer to output buffer. Appends annexb > > > startcode. > > > + * out must be allocated at least out_len + in_len + write_startcode * 4. > > > + */ > > > +#define WRITE_NAL(out, out_len, in, in_len, write_startcode) do { > > > \ > > > + if ((write_startcode)) { \ > > > + AV_WB32((out) + (out_len), 1); \ > > > + (out_len) += 4; \ > > > + } \ > > > + memcpy((out) + (out_len), (in), (in_len)); \ > > > + (out_len) += (in_len); \ > > > +} while (0) > > > + > > > +typedef struct Param { > > > + uint8_t *raw_data; /* raw data to store param set payload*/ > > > + int raw_size; /* size of raw_data*/ > > > + size_t allocated_size; /* allocated size of raw_data*/ > > > + int ref; /* stores the ref of the higher level > > > parameter set*/ > > > + int is_signalled; /* indicates whether this param has > > > already been signalled in the cvs*/ > > > +} Param; > > > + > > > +/* modified version of HEVCParamSets to store bytestream and reference > > > to previous level*/ > > > +typedef struct ParamSets { > > > + Param vps_list[HEVC_MAX_VPS_COUNT]; > > > + Param sps_list[HEVC_MAX_SPS_COUNT]; > > > + Param pps_list[HEVC_MAX_PPS_COUNT]; > > > + > > > + Param sei; /* cached SEIs from extradatat*/ > > > +} ParamSets; > > > > > > typedef struct HEVCBSFContext { > > > uint8_t length_size; > > > int extradata_parsed; > > > + ParamSets ps; /* cached VPS/SPS/PPS parameter sets + SEI from > > > extradata*/ > > > } HEVCBSFContext; > > > > > > +static int update_cached_paramset(AVBSFContext *ctx, Param *cached_param, > > > + H2645NAL *nal, int ref) > > > +{ > > > + int ret; > > > + > > > + if (cached_param->raw_data && cached_param->raw_size == > > > nal->raw_size + 4 && > > > + !memcmp(cached_param->raw_data + 4, nal->raw_data, > > > nal->raw_size)) { > > > + av_log(ctx, AV_LOG_DEBUG, "NAL unit: %d. Copy already exists in > > > parameter set.\n", nal->type); > > > + } else { > > > + if (nal->raw_size + 4 > cached_param->allocated_size) { > > > + ret = av_reallocp(&cached_param->raw_data, nal->raw_size + > > > 4); > > > + if (ret < 0) > > > + return ret; > > > + cached_param->allocated_size = nal->raw_size + 4; > > > + } > > > + cached_param->raw_size = 0; > > > + WRITE_NAL(cached_param->raw_data, cached_param->raw_size, > > > nal->raw_data, nal->raw_size, 1); > > > + cached_param->ref = ref; > > > + cached_param->is_signalled = 0; > > > + av_assert1(cached_param->raw_size == nal->raw_size + 4); > > > + } > > > + return 0; > > > +} > > > + > > > +static int parse_vps(AVBSFContext *ctx, H2645NAL *nal) > > > +{ > > > + int vps_id, ret; > > > + > > > + HEVCBSFContext *s = ctx->priv_data; > > > + ParamSets *ps = &s->ps; > > > + > > > + GetBitContext *gb = &nal->gb; > > > + > > > + vps_id = get_bits(gb, 4); > > > + > > > + if (get_bits_left(gb) < 0) { > > > + av_log(ctx, AV_LOG_ERROR, "Over-read bitstream in VPS id: %d\n", > > > vps_id); > > > + return AVERROR_INVALIDDATA; > > > + } > > > + > > > + av_log(ctx, AV_LOG_TRACE, "Updating VPS id: %d\n", vps_id); > > > + ret = update_cached_paramset(ctx, &ps->vps_list[vps_id], nal, 0); > > > + return ret; > > > +} > > > + > > > +static int parse_sps(AVBSFContext *ctx, H2645NAL *nal) > > > +{ > > > + int i, ret; > > > + int sps_id, vps_ref, max_sub_layers_minus1; > > > + > > > + HEVCBSFContext *s = ctx->priv_data; > > > + ParamSets *ps = &s->ps; > > > + > > > + uint8_t sub_layer_profile_present_flag[HEVC_MAX_SUB_LAYERS]; > > > + uint8_t sub_layer_level_present_flag[HEVC_MAX_SUB_LAYERS]; > > > + > > > + GetBitContext *gb = &nal->gb; > > > + > > > + vps_ref = get_bits(gb, 4); > > > + > > > + max_sub_layers_minus1 = get_bits(gb, 3); > > > + skip_bits1(gb); /* > > > sps_temporal_id_nesting_flag*/ > > > + skip_bits(gb, PROFILE_WITHOUT_IDC_BITS); /* profile_tier_level*/ > > > + skip_bits(gb, 8); /* general_level_idc*/ > > > + > > > + for (i = 0; i < max_sub_layers_minus1; i++) { > > > + sub_layer_profile_present_flag[i] = get_bits1(gb); > > > + sub_layer_level_present_flag[i] = get_bits1(gb); > > > + } > > > + > > > + if (max_sub_layers_minus1 > 0) > > > + for (i = max_sub_layers_minus1; i < 8; i++) > > > + skip_bits(gb, 2); /* reserved_zero_2bits[i]*/ > > > + > > > + for (i = 0; i < max_sub_layers_minus1; i++) { > > > + if (sub_layer_profile_present_flag[i]) > > > + skip_bits(gb, PROFILE_WITHOUT_IDC_BITS); /* > > > profile_tier_level*/ > > > + if (sub_layer_level_present_flag[i]) > > > + skip_bits(gb, 8); /* > > > sub_layer_level_idc*/ > > > + } > > > + > > > + /*we only need the sps_id index*/ > > > + sps_id = get_ue_golomb(gb); > > > + if (sps_id < 0 || sps_id >= HEVC_MAX_SPS_COUNT) { > > > + av_log(ctx, AV_LOG_ERROR, "SPS id out of range: %d\n", sps_id); > > > + return AVERROR_INVALIDDATA; > > > + } > > > + > > > + if (get_bits_left(gb) < 0) { > > > + av_log(ctx, AV_LOG_ERROR, "Over-read bitstream in SPS id: %d\n", > > > sps_id); > > > + return AVERROR_INVALIDDATA; > > > + } > > > + > > > + av_log(ctx, AV_LOG_TRACE, "Updating SPS id: %d, VPS ref: %d\n", > > > sps_id, vps_ref); > > > + ret = update_cached_paramset(ctx, &ps->sps_list[sps_id], nal, > > > vps_ref); > > > + return ret; > > > +} > > > + > > > +static int parse_pps(AVBSFContext *ctx, H2645NAL *nal) > > > +{ > > > + int ret; > > > + int pps_id, sps_ref; > > > + > > > + HEVCBSFContext *s = ctx->priv_data; > > > + ParamSets *ps = &s->ps; > > > + > > > + GetBitContext *gb = &nal->gb; > > > + > > > + pps_id = get_ue_golomb(gb); > > > + if (pps_id < 0 || pps_id >= HEVC_MAX_PPS_COUNT) { > > > + av_log(ctx, AV_LOG_ERROR, "PPS id out of range: %d\n", pps_id); > > > + return AVERROR_INVALIDDATA; > > > + } > > > + > > > + sps_ref = get_ue_golomb(gb); > > > + if (sps_ref < 0 || sps_ref >= HEVC_MAX_SPS_COUNT) { > > > + av_log(ctx, AV_LOG_ERROR, "SPS id out of range: %d\n", sps_ref); > > > + return AVERROR_INVALIDDATA; > > > + } > > > + > > > + if (get_bits_left(gb) < 0) { > > > + av_log(ctx, AV_LOG_ERROR, "Over-read bitstream in PPS id: %d\n", > > > pps_id); > > > + return AVERROR_INVALIDDATA; > > > + } > > > + > > > + av_log(ctx, AV_LOG_TRACE, "Updating PPS id: %d, SPS ref: %d\n", > > > pps_id, sps_ref); > > > + ret = update_cached_paramset(ctx, &ps->pps_list[pps_id], nal, > > > sps_ref); > > > + return ret; > > > +} > > > + > > > +static int append_sei_annexb(Param *sei, H2645NAL *nal) > > > +{ > > > + int ret; > > > + > > > + ret = av_reallocp(&sei->raw_data, sei->allocated_size + > > > nal->raw_size + 4); > > > + if (ret < 0) > > > + return ret; > > > + sei->allocated_size += nal->raw_size + 4; > > > + > > > + WRITE_NAL(sei->raw_data, sei->raw_size, nal->raw_data, > > > nal->raw_size, 1); > > > + av_assert1(sei->raw_size == sei->allocated_size); > > > + return 0; > > > +} > > > + > > > +static int update_paramset(AVBSFContext *ctx, H2645NAL *nal) > > > +{ > > > + int ret; > > > + switch (nal->type) { > > > + case (HEVC_NAL_VPS): > > > + if ((ret = parse_vps(ctx, nal)) < 0) > > > + return ret; > > > + break; > > > + case (HEVC_NAL_SPS): > > > + if ((ret = parse_sps(ctx, nal)) < 0) > > > + return ret; > > > + break; > > > + case (HEVC_NAL_PPS): > > > + if ((ret = parse_pps(ctx, nal)) < 0) > > > + return ret; > > > + } > > > + return 0; > > > +} > > > + > > > static int hevc_extradata_to_annexb(AVBSFContext *ctx) > > > { > > > GetByteContext gb; > > > @@ -97,6 +302,7 @@ fail: > > > static int hevc_mp4toannexb_init(AVBSFContext *ctx) > > > { > > > HEVCBSFContext *s = ctx->priv_data; > > > + H2645Packet pkt; > > > int ret; > > > > > > if (ctx->par_in->extradata_size < MIN_HEVCC_LENGTH || > > > @@ -104,77 +310,309 @@ static int hevc_mp4toannexb_init(AVBSFContext *ctx) > > > AV_RB32(ctx->par_in->extradata) == 1) { > > > av_log(ctx, AV_LOG_VERBOSE, > > > "The input looks like it is Annex B already\n"); > > > + return 0; > > > } else { > > > ret = hevc_extradata_to_annexb(ctx); > > > if (ret < 0) > > > return ret; > > > s->length_size = ret; > > > s->extradata_parsed = 1; > > > + > > > + memset(&pkt, 0, sizeof(H2645Packet)); > > > + ret = ff_h2645_packet_split(&pkt, ctx->par_out->extradata, > > > ctx->par_out->extradata_size, > > > + ctx, 0, 0, AV_CODEC_ID_HEVC, 1, 0); > > > + if (ret < 0) > > > + goto done; > > > + > > > + for (int i = 0; i < pkt.nb_nals; ++i) { > > > + H2645NAL *nal = &pkt.nals[i]; > > > + > > > + /*current segmentation algorithm includes next 0x00 from > > > next nal unit*/ > > > + if (nal->raw_data[nal->raw_size - 1] == 0x00) > > > + nal->raw_size--; > > > + > > > + if (IS_PARAMSET(nal)) { > > > + ret = update_paramset(ctx, nal); > > > + if (ret < 0) > > > + goto done; > > > + continue; > > > + } > > > + > > > + if (nal->type == HEVC_NAL_SEI_PREFIX || nal->type == > > > HEVC_NAL_SEI_SUFFIX) { > > > + ret = append_sei_annexb(&s->ps.sei, nal); > > > + if (ret < 0) > > > + goto done; > > > + } > > > + } > > > } > > > +done: > > > + ff_h2645_packet_uninit(&pkt); > > > + return ret; > > > +} > > > + > > > +static void ps_uninit(ParamSets *ps) > > > +{ > > > + int i; > > > + for (i = 0; i < FF_ARRAY_ELEMS(ps->vps_list); i++) { > > > + av_freep(&ps->vps_list[i].raw_data); > > > + ps->vps_list[i].allocated_size = 0; > > > + ps->vps_list[i].raw_size = 0; > > > + } > > > + for (i = 0; i < FF_ARRAY_ELEMS(ps->sps_list); i++) { > > > + av_freep(&ps->sps_list[i].raw_data); > > > + ps->sps_list[i].allocated_size = 0; > > > + ps->sps_list[i].raw_size = 0; > > > + } > > > + for (i = 0; i < FF_ARRAY_ELEMS(ps->pps_list); i++) { > > > + av_freep(&ps->pps_list[i].raw_data); > > > + ps->pps_list[i].allocated_size = 0; > > > + ps->pps_list[i].raw_size = 0; > > > + } > > > + av_freep(&ps->sei); > > > + ps->sei.allocated_size = 0; > > > + ps->sei.raw_size = 0; > > > +} > > > + > > > +static void hevc_mp4toannexb_close(AVBSFContext *ctx) > > > +{ > > > + HEVCBSFContext *s = ctx->priv_data; > > > + ps_uninit(&s->ps); > > > +} > > > + > > > +static int get_vcl_pps_id(AVBSFContext *ctx, H2645NAL *nal) > > > +{ > > > + GetBitContext *gb = &nal->gb; > > > + int pps_id, ret; > > > + > > > + /* re-initialize because bitstream touched in write_extradata*/ > > > + ret = init_get_bits(gb, nal->data, nal->size_bits); > > > + if (ret < 0) > > > + return ret; > > > + skip_bits(gb, HEVC_NAL_HEADER_BITS); > > > + > > > + skip_bits1(gb); /* first_slice_segment_in_pic_flag*/ > > > + > > > + if (IS_IRAP(nal)) > > > + skip_bits1(gb); /* no_output_of_prior_pics_flag*/ > > > + > > > + pps_id = get_ue_golomb(gb); > > > + if (pps_id < 0 || pps_id >= HEVC_MAX_PPS_COUNT) { > > > + av_log(ctx, AV_LOG_ERROR, "Invalid PPS id: %d\n", pps_id); > > > + return AVERROR_INVALIDDATA; > > > + } > > > + return pps_id; > > > +} > > > + > > > +static int write_vcl(AVBSFContext *ctx, AVPacket *pkt_out, int > > > *prev_size, > > > + H2645NAL *nal) > > > +{ > > > + HEVCBSFContext *s = ctx->priv_data; > > > + ParamSets *ps = &s->ps; > > > + int ret, pps_id; > > > + Param *pps; > > > + > > > + /* get frame pps*/ > > > + pps_id = get_vcl_pps_id(ctx, nal); > > > + if (pps_id < 0) > > > + return AVERROR_INVALIDDATA; > > > + av_log(ctx, AV_LOG_TRACE, "VCL PPS id: %d\n", pps_id); > > > + > > > + /* write pps if not signalled*/ > > > + pps = &ps->pps_list[pps_id]; > > > + if (!pps->raw_data) { > > > + av_log(ctx, AV_LOG_ERROR, "Invalid PPS: %d doesn't exist\n", > > > pps_id); > > > + return AVERROR_INVALIDDATA; > > > + } > > > + > > > + if (!pps->is_signalled) { > > > + av_log(ctx, AV_LOG_TRACE, "Referenced PPS: %d has not been > > > signalled. Writing PPS to output stream\n", pps_id); > > > + ret = av_grow_packet(pkt_out, pps->raw_size); > > > + if (ret < 0) > > > + return ret; > > > + WRITE_NAL(pkt_out->data, *prev_size, pps->raw_data, > > > pps->raw_size, 0); > > > + pps->is_signalled = 1; > > > + } > > > + > > > + /* write actual packet*/ > > > + ret = av_grow_packet(pkt_out, nal->raw_size + 4); > > > + if (ret < 0) > > > + return ret; > > > + WRITE_NAL(pkt_out->data, *prev_size, nal->raw_data, nal->raw_size, > > > 1); > > > > > > return 0; > > > } > > > > > > +static int write_extradata(AVBSFContext *ctx, AVPacket *pkt_out, int > > > *prev_size, > > > + H2645NAL *nal_irap) > > > +{ > > > + int ref, ret; > > > + int new_extradata_size = 0; > > > + > > > + HEVCBSFContext *s = ctx->priv_data; > > > + ParamSets *ps = &s->ps; > > > + GetBitContext *gb = &nal_irap->gb; > > > + > > > + /* active parameter sets for the new irap*/ > > > + const Param *vps; > > > + const Param *sps; > > > + Param *pps; /* non-const because we have to update flag that pps_id > > > is signalled in cvs*/ > > > + > > > + skip_bits1(gb); /* first_slice_ic_pic_flag*/ > > > + skip_bits1(gb); /* no_output_of_prior_pics_flag*/ > > > + > > > + ref = get_ue_golomb(gb); > > > + if (ref < 0 || ref >= HEVC_MAX_PPS_COUNT || > > > !ps->pps_list[ref].raw_data) { > > > + av_log(ctx, AV_LOG_ERROR, "Invalid PPS: %d\n", ref); > > > + return AVERROR_INVALIDDATA; > > > + } > > > + av_log(ctx, AV_LOG_TRACE, "Writing PPS id: %d\n", ref); > > > + pps = &ps->pps_list[ref]; > > > + new_extradata_size += pps->raw_size; > > > + ref = pps->ref; > > > + > > > + if (!ps->sps_list[ref].raw_data) { > > > + av_log(ctx, AV_LOG_ERROR, "Invalid SPS: %d\n", ref); > > > + return AVERROR_INVALIDDATA; > > > + } > > > + av_log(ctx, AV_LOG_TRACE, "Writing SPS id: %d\n", ref); > > > + sps = &ps->sps_list[ref]; > > > + new_extradata_size += sps->raw_size; > > > + ref = sps->ref; > > > + > > > + if (!ps->vps_list[ref].raw_data) { > > > + av_log(ctx, AV_LOG_ERROR, "Invalid VPS: %d\n", ref); > > > + return AVERROR_INVALIDDATA; > > > + } > > > + av_log(ctx, AV_LOG_TRACE, "Writing VPS id: %d\n", ref); > > > + vps = &ps->vps_list[ref]; > > > + new_extradata_size += vps->raw_size; > > > + > > > + if (ps->sei.raw_data) > > > + new_extradata_size += ps->sei.raw_size; > > > + > > > + ret = av_grow_packet(pkt_out, new_extradata_size); > > > + if (ret < 0) > > > + return ret; > > > + > > > + WRITE_NAL(pkt_out->data, *prev_size, vps->raw_data, vps->raw_size, > > > 0); > > > + WRITE_NAL(pkt_out->data, *prev_size, sps->raw_data, sps->raw_size, > > > 0); > > > + WRITE_NAL(pkt_out->data, *prev_size, pps->raw_data, pps->raw_size, > > > 0); > > > + pps->is_signalled = 1; > > > + > > > + if (ps->sei.raw_data) > > > + WRITE_NAL(pkt_out->data, *prev_size, ps->sei.raw_data, > > > ps->sei.raw_size, 0); > > > + > > > + av_assert1(*prev_size == pkt_out->size); > > > + return 0; > > > +} > > > + > > > +/* > > > + * Function converts mp4 access unit into annexb > > > + * Output packet structure > > > + * VPS, SPS, PPS, [SEI(from extradata)], [SEI_PREFIX(from access unit)], > > > IRAP, [SEI_SUFFIX] > > > + * or > > > + * [SEI_PREFIX (from access unit)], [PPS (if not already signalled)], > > > VCL(non-irap), [SEI_SUFFIX] > > > + */ > > > static int hevc_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out) > > > { > > > HEVCBSFContext *s = ctx->priv_data; > > > AVPacket *in; > > > - GetByteContext gb; > > > - > > > - int got_irap = 0; > > > - int i, ret = 0; > > > + H2645Packet pkt; > > > + int i, j, prev_size, ret; > > > + int irap_done; > > > > > > ret = ff_bsf_get_packet(ctx, &in); > > > if (ret < 0) > > > return ret; > > > > > > + /* output the annexb nalu if extradata is not parsed*/ > > > if (!s->extradata_parsed) { > > > av_packet_move_ref(out, in); > > > av_packet_free(&in); > > > return 0; > > > } > > > > > > - bytestream2_init(&gb, in->data, in->size); > > > + memset(&pkt, 0, sizeof(H2645Packet)); > > > + ret = ff_h2645_packet_split(&pkt, in->data, in->size, ctx, 1, > > > s->length_size, AV_CODEC_ID_HEVC, 1, 0); > > > + if (ret < 0) > > > + goto done; > > > + > > > + irap_done = 1; /* 1 means that there is no irap or the irap has > > > already been processed.*/ > > > + for (i = 0; i < pkt.nb_nals; i++) { > > > + if (IS_IRAP(&pkt.nals[i])) { > > > + irap_done = 0; > > > + break; > > > + } > > > + } > > > + > > > + prev_size = out->size; /* prev_size stores the current length of > > > output packet */ > > > + av_assert1(prev_size == 0); > > > > > > - while (bytestream2_get_bytes_left(&gb)) { > > > - uint32_t nalu_size = 0; > > > - int nalu_type; > > > - int is_irap, add_extradata, extra_size, prev_size; > > > + for (i = 0; i < pkt.nb_nals; i++) { > > > + H2645NAL *nal = &pkt.nals[i]; > > > + > > > + if (IS_PARAMSET(nal)) { > > > + ret = update_paramset(ctx, nal); > > > + if (ret < 0) > > > + goto done; > > > + continue; > > > + } > > > > > > - for (i = 0; i < s->length_size; i++) > > > - nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb); > > > + if (!irap_done && IS_IRAP(nal)) { /* append extradata and sei > > > before first irap*/ > > > > > > - nalu_type = (bytestream2_peek_byte(&gb) >> 1) & 0x3f; > > > + /* reset the pps signalled flag in this cvs*/ > > > + for (j = 0; j < HEVC_MAX_PPS_COUNT; j++) > > > + s->ps.pps_list[j].is_signalled = 0; > > > > > > - /* prepend extradata to IRAP frames */ > > > - is_irap = nalu_type >= 16 && nalu_type <= 23; > > > - add_extradata = is_irap && !got_irap; > > > - extra_size = add_extradata * ctx->par_out->extradata_size; > > > - got_irap |= is_irap; > > > + ret = write_extradata(ctx, out, &prev_size, nal); > > > + if (ret < 0) > > > + goto done; > > > + > > > + /* append any past SEI prefix nals*/ > > > + for (j = 0; j < i; j++) { > > > + H2645NAL *nal_past = &pkt.nals[j]; > > > + if (nal_past->type == HEVC_NAL_SEI_PREFIX) { > > > + ret = av_grow_packet(out, nal_past->raw_size + 4); > > > + if (ret < 0) > > > + goto done; > > > + WRITE_NAL(out->data, prev_size, nal_past->raw_data, > > > nal_past->raw_size, 1); > > > + } > > > + } > > > > > > - if (SIZE_MAX - nalu_size < 4 || > > > - SIZE_MAX - 4 - nalu_size < extra_size) { > > > - ret = AVERROR_INVALIDDATA; > > > - goto fail; > > > + /* write irap nal unit*/ > > > + ret = write_vcl(ctx, out, &prev_size, nal); > > > + if (ret < 0) > > > + goto done; > > > + irap_done = 1; > > > + continue; > > > } > > > > > > - prev_size = out->size; > > > + /* do not write any sei prefix nal units if irap exists but has > > > not been > > > + * processed*/ > > > + if (nal->type == HEVC_NAL_SEI_PREFIX && !irap_done) > > > + continue; > > > > > > - ret = av_grow_packet(out, 4 + nalu_size + extra_size); > > > - if (ret < 0) > > > - goto fail; > > > + if (IS_VCL(nal)) { > > > + ret = write_vcl(ctx, out, &prev_size, nal); > > > + if (ret < 0) > > > + goto done; > > > + continue; > > > + } > > > > > > - if (add_extradata) > > > - memcpy(out->data + prev_size, ctx->par_out->extradata, > > > extra_size); > > > - AV_WB32(out->data + prev_size + extra_size, 1); > > > - bytestream2_get_buffer(&gb, out->data + prev_size + 4 + > > > extra_size, nalu_size); > > > + /*copy any other nal units to the output - i.e. SEI_SUFFIX*/ > > > + ret = av_grow_packet(out, nal->raw_size + 4); > > > + if (ret < 0) > > > + goto done; > > > + WRITE_NAL(out->data, prev_size, nal->raw_data, nal->raw_size, 1); > > > } > > > > > > + av_assert1(prev_size == out->size); > > > + > > > ret = av_packet_copy_props(out, in); > > > - if (ret < 0) > > > - goto fail; > > > > > > -fail: > > > +done: > > > + ff_h2645_packet_uninit(&pkt); > > > + > > > if (ret < 0) > > > av_packet_unref(out); > > > av_packet_free(&in); > > > @@ -190,6 +628,7 @@ const AVBitStreamFilter ff_hevc_mp4toannexb_bsf = { > > > .name = "hevc_mp4toannexb", > > > .priv_data_size = sizeof(HEVCBSFContext), > > > .init = hevc_mp4toannexb_init, > > > + .close = hevc_mp4toannexb_close, > > > .filter = hevc_mp4toannexb_filter, > > > .codec_ids = codec_ids, > > > }; > > > diff --git a/tests/fate/hevc.mak b/tests/fate/hevc.mak > > > index 559c3898bc..4f812b0834 100644 > > > --- a/tests/fate/hevc.mak > > > +++ b/tests/fate/hevc.mak > > > @@ -238,7 +238,7 @@ FATE_HEVC-$(call ALLYES, HEVC_DEMUXER MOV_DEMUXER > > > HEVC_MP4TOANNEXB_BSF MOV_MUXER > > > fate-hevc-bsf-mp4toannexb: tests/data/hevc-mp4.mov > > > fate-hevc-bsf-mp4toannexb: CMD = md5 -i > > > $(TARGET_PATH)/tests/data/hevc-mp4.mov -c:v copy -fflags +bitexact -f hevc > > > fate-hevc-bsf-mp4toannexb: CMP = oneline > > > -fate-hevc-bsf-mp4toannexb: REF = 1873662a3af1848c37e4eb25722c8df9 > > > +fate-hevc-bsf-mp4toannexb: REF = 3c9d998a3aa2b9e0fb1c1f434952bf8b > > > > > > fate-hevc-skiploopfilter: CMD = framemd5 -skip_loop_filter nokey -i > > > $(TARGET_SAMPLES)/hevc-conformance/SAO_D_Samsung_5.bit -sws_flags bitexact > > > FATE_HEVC += fate-hevc-skiploopfilter > > > -- > > > 2.23.0 > > > > > > > ping > > > ping > ping
-- Andriy _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".