This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 076ef3e745f961fc372611375857d79b6a17e1e7 Author: Rainbaby <[email protected]> AuthorDate: Fri Aug 28 16:18:09 2026 +0900 Commit: Peter Ross <[email protected]> CommitDate: Mon Nov 2 22:18:06 2026 +0000 avcodec/cavsdec: decode the inter macroblock layer with AEC The mv_diff contexts make the neighbouring blocks' difference a predictor, so the differences are now cached. The three per picture type macroblock loops fold into one. Signed-off-by: Rainbaby <[email protected]> --- libavcodec/cavs.c | 44 ++++- libavcodec/cavs.h | 27 +++ libavcodec/cavsdec.c | 517 +++++++++++++++++++++++++++++++++++---------------- 3 files changed, 422 insertions(+), 166 deletions(-) diff --git a/libavcodec/cavs.c b/libavcodec/cavs.c index 0fdc9daca4..cd0e28bf20 100644 --- a/libavcodec/cavs.c +++ b/libavcodec/cavs.c @@ -57,7 +57,7 @@ static const uint8_t tc_tab[64] = { /** mark block as unavailable, i.e. out of picture * or not yet decoded */ -static const cavs_vector un_mv = { 0, 0, 1, NOT_AVAIL }; +static const cavs_vector un_mv = { 0, 0, 1, NOT_AVAIL, 0 }; /** * Inverse block scan method 2 (clause 9.5.3 c), figure 23), for field @@ -594,6 +594,9 @@ void ff_cavs_mv(AVSContext *h, enum cavs_mv_loc nP, enum cavs_mv_loc nC, mvP->ref = ref; mvP->dist = h->dist[mvP->ref]; + /* a derived reference has index 0 (clause 9.4.5) */ + if (mode >= MV_PRED_PSKIP) + mvP->ref_idx = 0; if (mvC->ref == NOT_AVAIL || (nP == MV_FWD_X3) || (nP == MV_BWD_X3 )) mvC = &h->mv[nP - 5]; // set to top-left (mvD) if (mode == MV_PRED_PSKIP && @@ -623,8 +626,20 @@ void ff_cavs_mv(AVSContext *h, enum cavs_mv_loc nP, enum cavs_mv_loc nC, mv_pred_median(h, mvP, mvA, mvB, mvC); if (mode < MV_PRED_PSKIP) { - int mx = get_se_golomb(&h->gb) + (unsigned)mvP->x; - int my = get_se_golomb(&h->gb) + (unsigned)mvP->y; + int dx, dy, mx, my; + + /* under AEC mv_diff is already in the cache (aec_mv() in cavsdec.c) */ + if (h->aec_enable) { + dx = h->mvd[nP][0]; + dy = h->mvd[nP][1]; + } else { + dx = get_se_golomb(&h->gb); + dy = get_se_golomb(&h->gb); + h->mvd[nP][0] = dx; + h->mvd[nP][1] = dy; + } + mx = dx + (unsigned)mvP->x; + my = dy + (unsigned)mvP->y; if (mx != (int16_t)mx || my != (int16_t)my) { av_log(h->avctx, AV_LOG_ERROR, "MV %d %d out of supported range\n", mx, my); @@ -632,6 +647,7 @@ void ff_cavs_mv(AVSContext *h, enum cavs_mv_loc nP, enum cavs_mv_loc nC, mvP->x = mx; mvP->y = my; } + set_mvds(&h->mvd[nP], size); } set_mvs(mvP, size); } @@ -649,6 +665,11 @@ void ff_cavs_init_mb(AVSContext *h) { int i; + /* a macroblock has no mv_diff until one is decoded for it */ + memset(h->mvd[MV_FWD_X0], 0, 2 * sizeof(*h->mvd)); + memset(h->mvd[MV_FWD_X2], 0, 2 * sizeof(*h->mvd)); + memset(h->mvd[MV_BWD_X0], 0, 2 * sizeof(*h->mvd)); + memset(h->mvd[MV_BWD_X2], 0, 2 * sizeof(*h->mvd)); /* copy predictors from top line (MB B and C) into cache */ for (i = 0; i < 3; i++) { h->mv[MV_FWD_B2 + i] = h->top_mv[0][h->mbx * 2 + i]; @@ -695,8 +716,10 @@ int ff_cavs_next_mb(AVSContext *h) h->cu += 8; h->cv += 8; /* copy mvs as predictors to the left */ - for (i = 0; i <= 20; i += 4) + for (i = 0; i <= 20; i += 4) { h->mv[i] = h->mv[i + 2]; + memcpy(h->mvd[i], h->mvd[i + 2], sizeof(*h->mvd)); + } /* copy bottom mvs from cache to top line */ h->top_mv[0][h->mbx * 2 + 0] = h->mv[MV_FWD_X2]; h->top_mv[0][h->mbx * 2 + 1] = h->mv[MV_FWD_X3]; @@ -710,8 +733,10 @@ int ff_cavs_next_mb(AVSContext *h) /* clear left pred_modes */ h->pred_mode_Y[3] = h->pred_mode_Y[6] = NOT_AVAIL; /* clear left mv predictors */ - for (i = 0; i <= 20; i += 4) + for (i = 0; i <= 20; i += 4) { h->mv[i] = un_mv; + memset(h->mvd[i], 0, sizeof(*h->mvd)); + } h->mbx = 0; h->mby++; /* re-calculate sample pointers */ @@ -736,8 +761,10 @@ int ff_cavs_init_pic(AVSContext *h) int i; /* clear some predictors */ - for (i = 0; i <= 20; i += 4) + for (i = 0; i <= 20; i += 4) { h->mv[i] = un_mv; + memset(h->mvd[i], 0, sizeof(*h->mvd)); + } h->mv[MV_BWD_X0] = CAVS_DIR_MV; set_mvs(&h->mv[MV_BWD_X0], BLK_16X16); h->mv[MV_FWD_X0] = CAVS_DIR_MV; @@ -784,15 +811,17 @@ int ff_cavs_init_top_lines(AVSContext *h) h->col_type_base = av_mallocz(h->mb_width * h->mb_height); h->top_cbp = av_mallocz(h->mb_width); + h->top_mb_type = av_mallocz(h->mb_width); h->top_c_pred_mode = av_mallocz(h->mb_width); if (!h->top_qp || !h->top_mv[0] || !h->top_mv[1] || !h->top_pred_Y || - !h->top_cbp || !h->top_c_pred_mode || + !h->top_cbp || !h->top_c_pred_mode || !h->top_mb_type || !h->top_border_y || !h->top_border_u || !h->top_border_v || !h->col_mv || !h->col_type_base) { av_freep(&h->top_qp); av_freep(&h->top_cbp); av_freep(&h->top_c_pred_mode); + av_freep(&h->top_mb_type); av_freep(&h->top_mv[0]); av_freep(&h->top_mv[1]); av_freep(&h->top_pred_Y); @@ -865,6 +894,7 @@ av_cold int ff_cavs_end(AVCodecContext *avctx) av_freep(&h->top_qp); av_freep(&h->top_cbp); av_freep(&h->top_c_pred_mode); + av_freep(&h->top_mb_type); av_freep(&h->top_mv[0]); av_freep(&h->top_mv[1]); av_freep(&h->top_pred_Y); diff --git a/libavcodec/cavs.h b/libavcodec/cavs.h index d111714879..802971914e 100644 --- a/libavcodec/cavs.h +++ b/libavcodec/cavs.h @@ -24,6 +24,7 @@ #include <stddef.h> #include <stdint.h> +#include <string.h> #include "libavutil/attributes.h" #include "libavutil/frame.h" @@ -153,6 +154,11 @@ typedef struct cavs_vector { int16_t y; int16_t dist; int16_t ref; + /** + * mb_reference_index of the block, 0 when it codes none (clause 9.4.5); + * ref above is where the reference list puts it + */ + int16_t ref_idx; } cavs_vector; struct dec_2dvlc { @@ -193,6 +199,8 @@ typedef struct AVSContext { int prev_delta_qp; ///< PreviousDeltaQP of clause 9.4.8, an AEC context int left_cbp; ///< MbCBP of the macroblock to the left uint8_t *top_cbp; ///< MbCBP of the macroblock above, one per column + int left_mb_type; ///< MbType to the left, clause 8.4.4.2 b) + uint8_t *top_mb_type; ///< MbType above, one per column int left_c_pred_mode; ///< IntraChromaPredMode to the left, 8.4.4.2 e) uint8_t *top_c_pred_mode; ///< IntraChromaPredMode above, per column int loop_filter_disable; @@ -219,6 +227,8 @@ typedef struct AVSContext { the same is repeated for backward motion vectors */ DECLARE_ALIGNED(8, cavs_vector, mv)[2*4*3]; + /** mv_diff of the same blocks, for the ctxIdxInc of clause 8.4.4.2 g) */ + int16_t mvd[2*4*3][2]; cavs_vector *top_mv[2]; cavs_vector *col_mv; @@ -305,6 +315,23 @@ static inline void set_mvs(cavs_vector *mv, enum cavs_block size) { } } +/** replicate one partition's mv_diff over the 8x8 blocks it covers */ +static inline void set_mvds(int16_t (*mvd)[2], enum cavs_block size) +{ + switch (size) { + case BLK_16X16: + memcpy(mvd[MV_STRIDE ], mvd[0], sizeof(*mvd)); + memcpy(mvd[MV_STRIDE+1], mvd[0], sizeof(*mvd)); + av_fallthrough; + case BLK_16X8: + memcpy(mvd[1], mvd[0], sizeof(*mvd)); + break; + case BLK_8X16: + memcpy(mvd[MV_STRIDE], mvd[0], sizeof(*mvd)); + break; + } +} + void ff_cavs_filter(AVSContext *h, enum cavs_mb mb_type); void ff_cavs_load_intra_pred_luma(AVSContext *h, uint8_t *top, uint8_t **left, int block); diff --git a/libavcodec/cavsdec.c b/libavcodec/cavsdec.c index 4d1f1c9275..108c611da4 100644 --- a/libavcodec/cavsdec.c +++ b/libavcodec/cavsdec.c @@ -636,6 +636,148 @@ static int decode_residual_block(AVSContext *h, GetBitContext *gb, /** Table 52, priIdx as a function of lMax, which saturates at 5. */ static const uint8_t cavs_aec_pri_idx[6] = { 0, 1, 2, 3, 3, 4 }; +/** Decode mb_skip_run, table 44 unary (8.4.4.2 a)). @return SkipMbCount */ +static int aec_mb_skip_run(AVSContext *h) +{ + int v = 0; + + while (!ff_cavs_aec_decode_decision(&h->aec, + AEC_MB_SKIP_RUN + FFMIN(v, 3))) { + if (++v > h->mb_width * h->mb_height) { + av_log(h->avctx, AV_LOG_ERROR, "mb_skip_run out of range\n"); + return AVERROR_INVALIDDATA; + } + } + return v; +} + +/** Decode mb_type, table 44 unary mapped by tables 54 and 55 (9.4.2 a) 2)) */ +static int aec_mb_type_p(AVSContext *h) +{ + int v = 0; + + while (!ff_cavs_aec_decode_decision(&h->aec, AEC_MB_TYPE + FFMIN(v, 4))) { + if (++v > 5 - h->skip_mode_flag) { + av_log(h->avctx, AV_LOG_ERROR, "mb_type out of range\n"); + return AVERROR_INVALIDDATA; + } + } + return v ? v - 1 + h->skip_mode_flag : 5; +} + +/** Decode mb_type in a B picture (table 45, 8.4.4.2 b)); see table 56. */ +static int aec_mb_type_b(AVSContext *h) +{ + int a = (h->flags & A_AVAIL) && h->left_mb_type != B_SKIP && + h->left_mb_type != B_DIRECT; + int b = (h->flags & B_AVAIL) && h->top_mb_type[h->mbx] != B_SKIP && + h->top_mb_type[h->mbx] != B_DIRECT; + int v; + + if (!ff_cavs_aec_decode_decision(&h->aec, AEC_MB_TYPE + 5 + a + b)) + return h->skip_mode_flag; + for (v = 1; + !ff_cavs_aec_decode_decision(&h->aec, AEC_MB_TYPE + 7 + FFMIN(v, 7)); + v++) { + if (v >= 24 - h->skip_mode_flag) { + av_log(h->avctx, AV_LOG_ERROR, "mb_type out of range\n"); + return AVERROR_INVALIDDATA; + } + } + return v + h->skip_mode_flag; +} + +/** + * Decode mb_part_type (tables 46 and 57, 8.4.4.2 c)). + * @return MbPartType, 0 to 3 + */ +static int aec_mb_part_type(AVSContext *h) +{ + int b0 = ff_cavs_aec_decode_decision(&h->aec, AEC_MB_PART_TYPE); + int b1 = ff_cavs_aec_decode_decision(&h->aec, + AEC_MB_PART_TYPE + (b0 ? 2 : 1)); + + return (b0 << 1) | b1; +} + +/** Decode mb_reference_index, table 44 unary (8.4.3 j), 8.4.4.2 f)). */ +static int aec_ref_index(AVSContext *h, int ctx_inc, int max) +{ + if (ff_cavs_aec_decode_decision(&h->aec, + AEC_MB_REFERENCE_INDEX + ctx_inc)) + return 0; + if (h->cur.f->pict_type == AV_PICTURE_TYPE_B) + return 1; + if (ff_cavs_aec_decode_decision(&h->aec, AEC_MB_REFERENCE_INDEX + 4)) + return 1; + for (int v = 2; v <= max; v++) + if (ff_cavs_aec_decode_decision(&h->aec, AEC_MB_REFERENCE_INDEX + 5)) + return v; + av_log(h->avctx, AV_LOG_ERROR, "mb_reference_index out of range\n"); + return AVERROR_INVALIDDATA; +} + +/** + * Decode one mv_diff_x or mv_diff_y (table 49, 8.4.4.2 g)); mvda is the + * magnitude of the same component of the left block's mv_diff. + */ +static int aec_mv_diff(AVSContext *h, int base, int mvda, int *diff) +{ + int v; + + if (!ff_cavs_aec_decode_decision(&h->aec, + base + (mvda < 2 ? 0 : + mvda < 16 ? 1 : 2))) { + *diff = 0; /* mvdSign is not coded for mvdAbs 0 */ + return 0; + } + if (!ff_cavs_aec_decode_decision(&h->aec, base + 3)) { + v = 1; + } else if (!ff_cavs_aec_decode_decision(&h->aec, base + 4)) { + v = 2; + } else { + int even = ff_cavs_aec_decode_decision(&h->aec, base + 5); + int k = 0; + + while (!ff_cavs_aec_decode_bypass(&h->aec)) { + if (++k > 11) { + av_log(h->avctx, AV_LOG_ERROR, "mv_diff out of range\n"); + return AVERROR_INVALIDDATA; + } + } + v = (1 << k) - 1; + while (k--) + v += ff_cavs_aec_decode_bypass(&h->aec) << k; + v = 3 + 2 * v + even; + } + if (ff_cavs_aec_decode_bypass(&h->aec)) /* mvdSign */ + v = -v; + if (v < -4096 || v > 4095) { + av_log(h->avctx, AV_LOG_ERROR, "mv_diff %d out of range\n", v); + return AVERROR_INVALIDDATA; + } + *diff = v; + return 0; +} + +/** + * Decode a motion vector's mv_diff pair into the cache that + * ff_cavs_mv() reads and the next block takes its mvda from. + */ +static int aec_mv(AVSContext *h, enum cavs_mv_loc nP) +{ + for (int i = 0; i < 2; i++) { + int base = i ? AEC_MV_DIFF_Y : AEC_MV_DIFF_X; + int diff; + int ret = aec_mv_diff(h, base, FFABS(h->mvd[nP - 1][i]), &diff); + + if (ret < 0) + return ret; + h->mvd[nP][i] = diff; + } + return 0; +} + /** * Decode intra_luma_pred_mode (table 47) and derive IntraLumaPredMode * from predIntraPredMode per clause 9.4.4.2 a). @@ -953,22 +1095,24 @@ static inline int decode_residual_inter(AVSContext *h) { int block, ret; - /* get coded block pattern */ - int cbp = get_ue_golomb(&h->gb); - if (cbp > 63U) { - av_log(h->avctx, AV_LOG_ERROR, "illegal inter cbp %d\n", cbp); - return AVERROR_INVALIDDATA; + if (h->aec_enable) { + h->cbp = aec_cbp(h); + } else { + /* get coded block pattern */ + int cbp = get_ue_golomb(&h->gb); + if (cbp > 63U) { + av_log(h->avctx, AV_LOG_ERROR, "illegal inter cbp %d\n", cbp); + return AVERROR_INVALIDDATA; + } + h->cbp = cbp_tab[cbp][1]; } - h->cbp = cbp_tab[cbp][1]; - - /* get quantizer */ - if (h->cbp && !h->qp_fixed) - h->qp = (h->qp + (unsigned)get_se_golomb(&h->gb)) & 63; + ret = decode_mb_qp_delta(h); + if (ret < 0) + return ret; for (block = 0; block < 4; block++) if (h->cbp & (1 << block)) { - ret = decode_residual_block(h, &h->gb, inter_dec, 0, h->qp, - h->cy + h->luma_scan[block], - h->l_stride); + ret = decode_residual(h, inter_dec, 0, 0, h->qp, + h->cy + h->luma_scan[block], h->l_stride); if (ret < 0) return ret; } @@ -1003,6 +1147,8 @@ static int decode_mb_i(AVSContext *h, int cbp_code) int ret; ff_cavs_init_mb(h); + h->left_mb_type = I_8X8; + h->top_mb_type[h->mbx] = I_8X8; /* get intra prediction modes from stream */ for (block = 0; block < 4; block++) { @@ -1089,42 +1235,114 @@ static inline void set_intra_mode_default(AVSContext *h) } } +/** + * Read the mb_reference_index of a P macroblock's block (table 26, + * clauses 7.2.5 and 9.4.5). @return the reference index it selects + */ +static int decode_ref_index(AVSContext *h, enum cavs_mv_loc nP) +{ + int idx = 0; + + if (!h->ref_flag) { + if (h->aec_enable) { + /* a and b of 8.4.4.2 f); unavailable, intra and derived + * neighbours carry index 0 */ + int a = h->mv[nP - 1].ref_idx > 0; + int b = h->mv[nP - 4].ref_idx > 0; + + idx = aec_ref_index(h, a + 2 * b, 1); + if (idx < 0) + return idx; + } else { + idx = get_bits1(&h->gb); + } + } + h->mv[nP].ref = idx; + h->mv[nP].ref_idx = idx; + return idx; +} + +/** + * Decode one motion vector: under AEC its mv_diff must be read before + * ff_cavs_mv() overwrites the cache its context comes from. + */ +static int decode_mv(AVSContext *h, enum cavs_mv_loc nP, enum cavs_mv_loc nC, + enum cavs_mv_pred mode, enum cavs_block size, int ref) +{ + if (h->aec_enable && mode < MV_PRED_PSKIP) { + int ret = aec_mv(h, nP); + if (ret < 0) + return ret; + } + ff_cavs_mv(h, nP, nC, mode, size, ref); + return 0; +} + +/* what the AEC contexts of later macroblocks read about this one (8.4.4.2) */ +static void set_inter_mb_ctx(AVSContext *h, enum cavs_mb mb_type, int skip) +{ + h->left_mb_type = mb_type; + h->top_mb_type[h->mbx] = mb_type; + h->left_c_pred_mode = INTRA_C_LP; + h->top_c_pred_mode[h->mbx] = INTRA_C_LP; + if (skip) { + h->left_cbp = 0; + h->top_cbp[h->mbx] = 0; + h->prev_delta_qp = 0; + } +} + +#define MV(nP, nC, mode, size, ref) \ + do { \ + ret = decode_mv(h, nP, nC, mode, size, ref); \ + if (ret < 0) \ + return ret; \ + } while (0) + +#define REF(dst, nP) \ + do { \ + ret = decode_ref_index(h, nP); \ + if (ret < 0) \ + return ret; \ + dst = ret; \ + } while (0) + static int decode_mb_p(AVSContext *h, enum cavs_mb mb_type) { - GetBitContext *gb = &h->gb; int ref[4]; int ret; ff_cavs_init_mb(h); + set_inter_mb_ctx(h, mb_type, mb_type == P_SKIP); switch (mb_type) { case P_SKIP: - ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_PSKIP, BLK_16X16, 0); + MV(MV_FWD_X0, MV_FWD_C2, MV_PRED_PSKIP, BLK_16X16, 0); break; case P_16X16: - ref[0] = h->ref_flag ? 0 : get_bits1(gb); - ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_MEDIAN, BLK_16X16, ref[0]); + REF(ref[0], MV_FWD_X0); + MV(MV_FWD_X0, MV_FWD_C2, MV_PRED_MEDIAN, BLK_16X16, ref[0]); break; case P_16X8: - ref[0] = h->ref_flag ? 0 : get_bits1(gb); - ref[2] = h->ref_flag ? 0 : get_bits1(gb); - ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_TOP, BLK_16X8, ref[0]); - ff_cavs_mv(h, MV_FWD_X2, MV_FWD_A1, MV_PRED_LEFT, BLK_16X8, ref[2]); + REF(ref[0], MV_FWD_X0); + REF(ref[2], MV_FWD_X2); + MV(MV_FWD_X0, MV_FWD_C2, MV_PRED_TOP, BLK_16X8, ref[0]); + MV(MV_FWD_X2, MV_FWD_A1, MV_PRED_LEFT, BLK_16X8, ref[2]); break; case P_8X16: - ref[0] = h->ref_flag ? 0 : get_bits1(gb); - ref[1] = h->ref_flag ? 0 : get_bits1(gb); - ff_cavs_mv(h, MV_FWD_X0, MV_FWD_B3, MV_PRED_LEFT, BLK_8X16, ref[0]); - ff_cavs_mv(h, MV_FWD_X1, MV_FWD_C2, MV_PRED_TOPRIGHT, BLK_8X16, ref[1]); + REF(ref[0], MV_FWD_X0); + REF(ref[1], MV_FWD_X1); + MV(MV_FWD_X0, MV_FWD_B3, MV_PRED_LEFT, BLK_8X16, ref[0]); + MV(MV_FWD_X1, MV_FWD_C2, MV_PRED_TOPRIGHT, BLK_8X16, ref[1]); break; case P_8X8: - ref[0] = h->ref_flag ? 0 : get_bits1(gb); - ref[1] = h->ref_flag ? 0 : get_bits1(gb); - ref[2] = h->ref_flag ? 0 : get_bits1(gb); - ref[3] = h->ref_flag ? 0 : get_bits1(gb); - ff_cavs_mv(h, MV_FWD_X0, MV_FWD_B3, MV_PRED_MEDIAN, BLK_8X8, ref[0]); - ff_cavs_mv(h, MV_FWD_X1, MV_FWD_C2, MV_PRED_MEDIAN, BLK_8X8, ref[1]); - ff_cavs_mv(h, MV_FWD_X2, MV_FWD_X1, MV_PRED_MEDIAN, BLK_8X8, ref[2]); - ff_cavs_mv(h, MV_FWD_X3, MV_FWD_X0, MV_PRED_MEDIAN, BLK_8X8, ref[3]); + REF(ref[0], MV_FWD_X0); + REF(ref[1], MV_FWD_X1); + REF(ref[2], MV_FWD_X2); + REF(ref[3], MV_FWD_X3); + MV(MV_FWD_X0, MV_FWD_B3, MV_PRED_MEDIAN, BLK_8X8, ref[0]); + MV(MV_FWD_X1, MV_FWD_C2, MV_PRED_MEDIAN, BLK_8X8, ref[1]); + MV(MV_FWD_X2, MV_FWD_X1, MV_PRED_MEDIAN, BLK_8X8, ref[2]); + MV(MV_FWD_X3, MV_FWD_X0, MV_PRED_MEDIAN, BLK_8X8, ref[3]); break; default: av_log(h->avctx, AV_LOG_ERROR, "Invalid mb_type %d in P frame\n", @@ -1141,7 +1359,6 @@ static int decode_mb_p(AVSContext *h, enum cavs_mb mb_type) } ff_cavs_filter(h, mb_type); h->col_type_base[h->mbidx] = mb_type; - return 0; } @@ -1153,6 +1370,7 @@ static int decode_mb_b(AVSContext *h, enum cavs_mb mb_type) int ret; ff_cavs_init_mb(h); + set_inter_mb_ctx(h, mb_type, mb_type == B_SKIP); /* reset all MVs */ h->mv[MV_FWD_X0] = CAVS_DIR_MV; @@ -1173,20 +1391,24 @@ static int decode_mb_b(AVSContext *h, enum cavs_mb mb_type) &h->col_mv[h->mbidx * 4 + block]); break; case B_FWD_16X16: - ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_MEDIAN, BLK_16X16, 1); + MV(MV_FWD_X0, MV_FWD_C2, MV_PRED_MEDIAN, BLK_16X16, 1); break; case B_SYM_16X16: - ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_MEDIAN, BLK_16X16, 1); + MV(MV_FWD_X0, MV_FWD_C2, MV_PRED_MEDIAN, BLK_16X16, 1); mv_pred_sym(h, &h->mv[MV_FWD_X0], BLK_16X16); break; case B_BWD_16X16: - ff_cavs_mv(h, MV_BWD_X0, MV_BWD_C2, MV_PRED_MEDIAN, BLK_16X16, 0); + MV(MV_BWD_X0, MV_BWD_C2, MV_PRED_MEDIAN, BLK_16X16, 0); break; case B_8X8: #define TMP_UNUSED_INX 7 flags = 0; - for (block = 0; block < 4; block++) - sub_type[block] = get_bits(&h->gb, 2); + for (block = 0; block < 4; block++) { + if (h->aec_enable) + sub_type[block] = aec_mb_part_type(h); + else + sub_type[block] = get_bits(&h->gb, 2); + } for (block = 0; block < 4; block++) { switch (sub_type[block]) { case B_SUB_DIRECT: @@ -1221,12 +1443,12 @@ static int decode_mb_b(AVSContext *h, enum cavs_mb mb_type) &h->col_mv[h->mbidx * 4 + block]); break; case B_SUB_FWD: - ff_cavs_mv(h, mv_scan[block], mv_scan[block] - 3, - MV_PRED_MEDIAN, BLK_8X8, 1); + MV(mv_scan[block], mv_scan[block] - 3, + MV_PRED_MEDIAN, BLK_8X8, 1); break; case B_SUB_SYM: - ff_cavs_mv(h, mv_scan[block], mv_scan[block] - 3, - MV_PRED_MEDIAN, BLK_8X8, 1); + MV(mv_scan[block], mv_scan[block] - 3, + MV_PRED_MEDIAN, BLK_8X8, 1); mv_pred_sym(h, &h->mv[mv_scan[block]], BLK_8X8); break; } @@ -1234,9 +1456,9 @@ static int decode_mb_b(AVSContext *h, enum cavs_mb mb_type) #undef TMP_UNUSED_INX for (block = 0; block < 4; block++) { if (sub_type[block] == B_SUB_BWD) - ff_cavs_mv(h, mv_scan[block] + MV_BWD_OFFS, - mv_scan[block] + MV_BWD_OFFS - 3, - MV_PRED_MEDIAN, BLK_8X8, 0); + MV(mv_scan[block] + MV_BWD_OFFS, + mv_scan[block] + MV_BWD_OFFS - 3, + MV_PRED_MEDIAN, BLK_8X8, 0); } break; default: @@ -1248,30 +1470,30 @@ static int decode_mb_b(AVSContext *h, enum cavs_mb mb_type) flags = ff_cavs_partition_flags[mb_type]; if (mb_type & 1) { /* 16x8 macroblock types */ if (flags & FWD0) - ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_TOP, BLK_16X8, 1); + MV(MV_FWD_X0, MV_FWD_C2, MV_PRED_TOP, BLK_16X8, 1); if (flags & SYM0) mv_pred_sym(h, &h->mv[MV_FWD_X0], BLK_16X8); if (flags & FWD1) - ff_cavs_mv(h, MV_FWD_X2, MV_FWD_A1, MV_PRED_LEFT, BLK_16X8, 1); + MV(MV_FWD_X2, MV_FWD_A1, MV_PRED_LEFT, BLK_16X8, 1); if (flags & SYM1) mv_pred_sym(h, &h->mv[MV_FWD_X2], BLK_16X8); if (flags & BWD0) - ff_cavs_mv(h, MV_BWD_X0, MV_BWD_C2, MV_PRED_TOP, BLK_16X8, 0); + MV(MV_BWD_X0, MV_BWD_C2, MV_PRED_TOP, BLK_16X8, 0); if (flags & BWD1) - ff_cavs_mv(h, MV_BWD_X2, MV_BWD_A1, MV_PRED_LEFT, BLK_16X8, 0); + MV(MV_BWD_X2, MV_BWD_A1, MV_PRED_LEFT, BLK_16X8, 0); } else { /* 8x16 macroblock types */ if (flags & FWD0) - ff_cavs_mv(h, MV_FWD_X0, MV_FWD_B3, MV_PRED_LEFT, BLK_8X16, 1); + MV(MV_FWD_X0, MV_FWD_B3, MV_PRED_LEFT, BLK_8X16, 1); if (flags & SYM0) mv_pred_sym(h, &h->mv[MV_FWD_X0], BLK_8X16); if (flags & FWD1) - ff_cavs_mv(h, MV_FWD_X1, MV_FWD_C2, MV_PRED_TOPRIGHT, BLK_8X16, 1); + MV(MV_FWD_X1, MV_FWD_C2, MV_PRED_TOPRIGHT, BLK_8X16, 1); if (flags & SYM1) mv_pred_sym(h, &h->mv[MV_FWD_X1], BLK_8X16); if (flags & BWD0) - ff_cavs_mv(h, MV_BWD_X0, MV_BWD_B3, MV_PRED_LEFT, BLK_8X16, 0); + MV(MV_BWD_X0, MV_BWD_B3, MV_PRED_LEFT, BLK_8X16, 0); if (flags & BWD1) - ff_cavs_mv(h, MV_BWD_X1, MV_BWD_C2, MV_PRED_TOPRIGHT, BLK_8X16, 0); + MV(MV_BWD_X1, MV_BWD_C2, MV_PRED_TOPRIGHT, BLK_8X16, 0); } } ff_cavs_inter(h, mb_type); @@ -1286,6 +1508,59 @@ static int decode_mb_b(AVSContext *h, enum cavs_mb mb_type) return 0; } +#undef MV +#undef REF + +/** + * Decode one macroblock of a P or B coded macroblock layer, table 25. + * @param skip_count what is left of the current mb_skip_run, or -1 when the + * next macroblock position starts a new one + */ +static int decode_mb_pb_layer(AVSContext *h, int *skip_count) +{ + const int b = h->cur.f->pict_type == AV_PICTURE_TYPE_B; + const enum cavs_mb skip = b ? B_SKIP : P_SKIP; + const enum cavs_mb last = b ? B_8X8 : P_8X8; + enum cavs_mb mb_type; + int skipped, ret; + + if (h->skip_mode_flag && *skip_count < 0) { + if (h->aec_enable) { + *skip_count = aec_mb_skip_run(h); + } else { + if (get_bits_left(&h->gb) < 1) + return AVERROR_INVALIDDATA; + *skip_count = get_ue_golomb(&h->gb); + } + if (*skip_count < 0) + return AVERROR_INVALIDDATA; + } + skipped = h->skip_mode_flag && (*skip_count)--; + if (skipped) { + mb_type = skip; + } else if (h->aec_enable) { + ret = b ? aec_mb_type_b(h) : aec_mb_type_p(h); + if (ret < 0) + return ret; + mb_type = ret + skip; + } else { + if (get_bits_left(&h->gb) < 1) + return AVERROR_INVALIDDATA; + mb_type = get_ue_golomb(&h->gb) + skip + h->skip_mode_flag; + } + if (mb_type > last) + ret = decode_mb_i(h, mb_type - last - 1); + else + ret = b ? decode_mb_b(h, mb_type) : decode_mb_p(h, mb_type); + if (ret < 0) + return ret; + /* the stuffing bit follows a coded MB and the last one of a skip run */ + if (h->aec_enable && (!skipped || !*skip_count) && + ff_cavs_aec_decode_stuffing_bit(&h->aec)) + aec_end_of_slice(h); + return 0; +} + /***************************************************************************** * * slice level @@ -1380,7 +1655,6 @@ static int decode_pic(AVSContext *h) { int ret; int skip_count = -1; - enum cavs_mb mb_type; if (!h->top_qp) { av_log(h->avctx, AV_LOG_ERROR, "No sequence header decoded yet\n"); @@ -1508,112 +1782,37 @@ static int decode_pic(AVSContext *h) ret = 0; h->aec.gb = NULL; /* started by the first slice header */ h->pic_data_end = 0; - if (h->cur.f->pict_type == AV_PICTURE_TYPE_I) { - do { - ret = check_for_slice(h); - if (ret < 0) - break; - if (h->aec_enable && !h->aec.gb) { - av_log(h->avctx, AV_LOG_ERROR, - "AEC picture without a slice header\n"); - ret = AVERROR_INVALIDDATA; - break; - } - if (h->pic_data_end) { - av_log(h->avctx, AV_LOG_ERROR, - "picture data ended before MB %d\n", h->mbidx); - ret = AVERROR_INVALIDDATA; - break; - } + do { + ret = check_for_slice(h); + if (ret < 0) + break; + if (ret) + skip_count = -1; + if (h->aec_enable && !h->aec.gb) { + av_log(h->avctx, AV_LOG_ERROR, + "AEC picture without a slice header\n"); + ret = AVERROR_INVALIDDATA; + break; + } + /* past the picture's data, only a pending skip run can code MBs */ + if (h->pic_data_end && !(h->skip_mode_flag && skip_count > 0)) { + av_log(h->avctx, AV_LOG_ERROR, "picture data ended before MB %d\n", + h->mbidx); + ret = AVERROR_INVALIDDATA; + break; + } + if (h->cur.f->pict_type != AV_PICTURE_TYPE_I) { + ret = decode_mb_pb_layer(h, &skip_count); + } else { ret = decode_mb_i(h, 0); - if (ret < 0) - break; - if (h->aec_enable && ff_cavs_aec_decode_stuffing_bit(&h->aec)) + /* aec_mb_stuffing_bit is 1 on the slice's last MB (7.2.4) */ + if (ret >= 0 && h->aec_enable && + ff_cavs_aec_decode_stuffing_bit(&h->aec)) aec_end_of_slice(h); - } while (ff_cavs_next_mb(h)); - } else if (h->cur.f->pict_type == AV_PICTURE_TYPE_P) { - do { - ret = check_for_slice(h); - if (ret < 0) - break; - if (ret) - skip_count = -1; - /* past the picture's data, only a pending skip run can code MBs */ - if (h->pic_data_end && !(h->skip_mode_flag && skip_count > 0)) { - av_log(h->avctx, AV_LOG_ERROR, - "picture data ended before MB %d\n", h->mbidx); - ret = AVERROR_INVALIDDATA; - break; - } - if (h->skip_mode_flag && (skip_count < 0)) { - if (get_bits_left(&h->gb) < 1) { - ret = AVERROR_INVALIDDATA; - break; - } - skip_count = get_ue_golomb(&h->gb); - if (skip_count < 0) { - ret = AVERROR_INVALIDDATA; - break; - } - } - if (h->skip_mode_flag && skip_count--) { - ret = decode_mb_p(h, P_SKIP); - } else { - if (get_bits_left(&h->gb) < 1) { - ret = AVERROR_INVALIDDATA; - break; - } - mb_type = get_ue_golomb(&h->gb) + P_SKIP + h->skip_mode_flag; - if (mb_type > P_8X8) - ret = decode_mb_i(h, mb_type - P_8X8 - 1); - else - ret = decode_mb_p(h, mb_type); - } - if (ret < 0) - break; - } while (ff_cavs_next_mb(h)); - } else { /* AV_PICTURE_TYPE_B */ - do { - ret = check_for_slice(h); - if (ret < 0) - break; - if (ret) - skip_count = -1; - /* past the picture's data, only a pending skip run can code MBs */ - if (h->pic_data_end && !(h->skip_mode_flag && skip_count > 0)) { - av_log(h->avctx, AV_LOG_ERROR, - "picture data ended before MB %d\n", h->mbidx); - ret = AVERROR_INVALIDDATA; - break; - } - if (h->skip_mode_flag && (skip_count < 0)) { - if (get_bits_left(&h->gb) < 1) { - ret = AVERROR_INVALIDDATA; - break; - } - skip_count = get_ue_golomb(&h->gb); - if (skip_count < 0) { - ret = AVERROR_INVALIDDATA; - break; - } - } - if (h->skip_mode_flag && skip_count--) { - ret = decode_mb_b(h, B_SKIP); - } else { - if (get_bits_left(&h->gb) < 1) { - ret = AVERROR_INVALIDDATA; - break; - } - mb_type = get_ue_golomb(&h->gb) + B_SKIP + h->skip_mode_flag; - if (mb_type > B_8X8) - ret = decode_mb_i(h, mb_type - B_8X8 - 1); - else - ret = decode_mb_b(h, mb_type); - } - if (ret < 0) - break; - } while (ff_cavs_next_mb(h)); - } + } + if (ret < 0) + break; + } while (ff_cavs_next_mb(h)); if (ret >= 0 && h->cur.f->pict_type != AV_PICTURE_TYPE_B) { av_frame_unref(h->DPB[1].f); FFSWAP(AVSFrame, h->cur, h->DPB[1]); -- To stop receiving notification emails like this one, please contact [email protected]. _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
