diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c index 1fe58c8050..262ef5aa39 100644 --- a/libavcodec/evc_parse.c +++ b/libavcodec/evc_parse.c @@ -187,6 +187,77 @@ static int evc_parse_slice_header(EVCParserContext *ctx, EVCParserSliceHeader *s return 0; } +int ff_evc_derive_poc(const EVCParamSets *ps, const EVCParserSliceHeader *sh, + EVCParserPoc *poc, enum EVCNALUnitType nalu_type, int tid) +{ + const EVCParserPPS *pps = ps->pps[sh->slice_pic_parameter_set_id]; + const EVCParserSPS *sps; + + if (!pps) + return AVERROR_INVALIDDATA; + + sps = ps->sps[pps->pps_seq_parameter_set_id]; + if (!sps) + return AVERROR_INVALIDDATA; + + if (sps->sps_pocs_flag) { + int PicOrderCntMsb = 0; + poc->prevPicOrderCntVal = poc->PicOrderCntVal; + + if (nalu_type == EVC_IDR_NUT) + PicOrderCntMsb = 0; + else { + int MaxPicOrderCntLsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + int prevPicOrderCntLsb = poc->PicOrderCntVal & (MaxPicOrderCntLsb - 1); + int prevPicOrderCntMsb = poc->PicOrderCntVal - prevPicOrderCntLsb; + + if ((sh->slice_pic_order_cnt_lsb < prevPicOrderCntLsb) && + ((prevPicOrderCntLsb - sh->slice_pic_order_cnt_lsb) >= (MaxPicOrderCntLsb / 2))) + PicOrderCntMsb = prevPicOrderCntMsb + MaxPicOrderCntLsb; + else if ((sh->slice_pic_order_cnt_lsb > prevPicOrderCntLsb) && + ((sh->slice_pic_order_cnt_lsb - prevPicOrderCntLsb) > (MaxPicOrderCntLsb / 2))) + PicOrderCntMsb = prevPicOrderCntMsb - MaxPicOrderCntLsb; + else + PicOrderCntMsb = prevPicOrderCntMsb; + } + poc->PicOrderCntVal = PicOrderCntMsb + sh->slice_pic_order_cnt_lsb; + } else { + if (nalu_type == EVC_IDR_NUT) { + poc->PicOrderCntVal = 0; + poc->DocOffset = -1; + } else { + int SubGopLength = (int)pow(2.0, sps->log2_sub_gop_length); + if (tid == 0) { + poc->PicOrderCntVal = poc->prevPicOrderCntVal + SubGopLength; + poc->DocOffset = 0; + poc->prevPicOrderCntVal = poc->PicOrderCntVal; + } else { + int ExpectedTemporalId; + int PocOffset; + int prevDocOffset = poc->DocOffset; + + poc->DocOffset = (prevDocOffset + 1) % SubGopLength; + if (poc->DocOffset == 0) { + poc->prevPicOrderCntVal += SubGopLength; + ExpectedTemporalId = 0; + } else + ExpectedTemporalId = 1 + (int)log2(poc->DocOffset); + while (tid != ExpectedTemporalId) { + poc->DocOffset = (poc->DocOffset + 1) % SubGopLength; + if (poc->DocOffset == 0) + ExpectedTemporalId = 0; + else + ExpectedTemporalId = 1 + (int)log2(poc->DocOffset); + } + PocOffset = (int)(SubGopLength * ((2.0 * poc->DocOffset + 1) / (int)pow(2.0, tid) - 2)); + poc->PicOrderCntVal = poc->prevPicOrderCntVal + PocOffset; + } + } + } + + return 0; +} + int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_size, void *logctx) { int nalu_type, nalu_size; @@ -299,8 +370,6 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz case EVC_IDR_NUT: // Coded slice of a IDR or non-IDR picture case EVC_NOIDR_NUT: { EVCParserSliceHeader sh; - const EVCParserSPS *sps; - const EVCParserPPS *pps; int ret; ret = evc_parse_slice_header(ctx, &sh, data, nalu_size); @@ -331,72 +400,9 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz // POC (picture order count of the current picture) derivation // @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for picture order count - pps = ctx->ps.pps[sh.slice_pic_parameter_set_id]; - sps = ctx->ps.sps[pps->pps_seq_parameter_set_id]; - av_assert0(sps && pps); - - if (sps->sps_pocs_flag) { - - int PicOrderCntMsb = 0; - ctx->poc.prevPicOrderCntVal = ctx->poc.PicOrderCntVal; - - if (nalu_type == EVC_IDR_NUT) - PicOrderCntMsb = 0; - else { - int MaxPicOrderCntLsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); - - int prevPicOrderCntLsb = ctx->poc.PicOrderCntVal & (MaxPicOrderCntLsb - 1); - int prevPicOrderCntMsb = ctx->poc.PicOrderCntVal - prevPicOrderCntLsb; - - - if ((sh.slice_pic_order_cnt_lsb < prevPicOrderCntLsb) && - ((prevPicOrderCntLsb - sh.slice_pic_order_cnt_lsb) >= (MaxPicOrderCntLsb / 2))) - - PicOrderCntMsb = prevPicOrderCntMsb + MaxPicOrderCntLsb; - - else if ((sh.slice_pic_order_cnt_lsb > prevPicOrderCntLsb) && - ((sh.slice_pic_order_cnt_lsb - prevPicOrderCntLsb) > (MaxPicOrderCntLsb / 2))) - - PicOrderCntMsb = prevPicOrderCntMsb - MaxPicOrderCntLsb; - - else - PicOrderCntMsb = prevPicOrderCntMsb; - } - ctx->poc.PicOrderCntVal = PicOrderCntMsb + sh.slice_pic_order_cnt_lsb; - - } else { - if (nalu_type == EVC_IDR_NUT) { - ctx->poc.PicOrderCntVal = 0; - ctx->poc.DocOffset = -1; - } else { - int SubGopLength = (int)pow(2.0, sps->log2_sub_gop_length); - if (tid == 0) { - ctx->poc.PicOrderCntVal = ctx->poc.prevPicOrderCntVal + SubGopLength; - ctx->poc.DocOffset = 0; - ctx->poc.prevPicOrderCntVal = ctx->poc.PicOrderCntVal; - } else { - int ExpectedTemporalId; - int PocOffset; - int prevDocOffset = ctx->poc.DocOffset; - - ctx->poc.DocOffset = (prevDocOffset + 1) % SubGopLength; - if (ctx->poc.DocOffset == 0) { - ctx->poc.prevPicOrderCntVal += SubGopLength; - ExpectedTemporalId = 0; - } else - ExpectedTemporalId = 1 + (int)log2(ctx->poc.DocOffset); - while (tid != ExpectedTemporalId) { - ctx->poc.DocOffset = (ctx->poc.DocOffset + 1) % SubGopLength; - if (ctx->poc.DocOffset == 0) - ExpectedTemporalId = 0; - else - ExpectedTemporalId = 1 + (int)log2(ctx->poc.DocOffset); - } - PocOffset = (int)(SubGopLength * ((2.0 * ctx->poc.DocOffset + 1) / (int)pow(2.0, tid) - 2)); - ctx->poc.PicOrderCntVal = ctx->poc.prevPicOrderCntVal + PocOffset; - } - } - } + ret = ff_evc_derive_poc(&ctx->ps, &sh, &ctx->poc, nalu_type, tid); + if (ret < 0) + return ret; ctx->output_picture_number = ctx->poc.PicOrderCntVal; ctx->key_frame = (nalu_type == EVC_IDR_NUT) ? 1 : 0; diff --git a/libavcodec/evc_parse.h b/libavcodec/evc_parse.h index 2748f8dfbf..97825efcd5 100644 --- a/libavcodec/evc_parse.h +++ b/libavcodec/evc_parse.h @@ -159,4 +159,9 @@ int ff_evc_get_temporal_id(const uint8_t *bits, int bits_size, void *logctx); int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_size, void *logctx); +// POC (picture order count of the current picture) derivation +// @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for picture order count +int ff_evc_derive_poc(const EVCParamSets *ps, const EVCParserSliceHeader *sh, + EVCParserPoc *poc, enum EVCNALUnitType nalu_type, int tid); + #endif /* AVCODEC_EVC_PARSE_H */