Commit 51c73fcbbb for ffmpeg

commit 51c73fcbbbccacbf57acdb7a527e87d6016d8a99
Author: Rainbaby <r@bgr.jp>
Date:   Fri Aug 28 16:18:09 2026 +0900

    avcodec/cavsdec: decode the intra macroblock layer with AEC

    The aec_mb_stuffing_bit ends a slice, after which the reader is
    repositioned on the next start code. Field pictures use the scan of
    clause 9.5.3 c).

    Signed-off-by: Rainbaby <r@bgr.jp>

diff --git a/libavcodec/cavs.c b/libavcodec/cavs.c
index 3c3b95093b..0fdc9daca4 100644
--- a/libavcodec/cavs.c
+++ b/libavcodec/cavs.c
@@ -59,6 +59,17 @@ static const uint8_t tc_tab[64] = {
  *  or not yet decoded */
 static const cavs_vector un_mv = { 0, 0, 1, NOT_AVAIL };

+/**
+ * Inverse block scan method 2 (clause 9.5.3 c), figure 23), for field
+ * coded pictures, as the inverse ff_permute_scantable() expects.
+ */
+static const uint8_t cavs_scan_field[64] = {
+     0,  8, 16,  1, 24, 32,  9, 17, 40, 48, 25,  2, 10, 56, 33, 18,
+     3, 41, 49, 26, 11, 19,  4, 57, 34, 12, 42, 27, 20, 50, 35, 28,
+     5, 13, 58, 43, 36, 21,  6, 29, 51, 44, 14, 22, 37, 59, 52, 30,
+    45, 60, 38, 53, 46, 61, 54,  7, 62, 15, 23, 31, 39, 47, 55, 63,
+};
+
 static const int8_t left_modifier_l[8] = {  0, -1,  6, -1, -1, 7, 6, 7 };
 static const int8_t top_modifier_l[8]  = { -1,  1,  5, -1, -1, 5, 7, 7 };
 static const int8_t left_modifier_c[7] = {  5, -1,  2, -1,  6, 5, 6 };
@@ -772,10 +783,16 @@ int ff_cavs_init_top_lines(AVSContext *h)
                                  4 * sizeof(*h->col_mv));
     h->col_type_base = av_mallocz(h->mb_width * h->mb_height);

+    h->top_cbp         = 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_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_mv[0]);
         av_freep(&h->top_mv[1]);
         av_freep(&h->top_pred_Y);
@@ -800,6 +817,9 @@ av_cold int ff_cavs_init(AVCodecContext *avctx)
     ff_cavsdsp_init(&h->cdsp);
     ff_init_scantable_permutation(permutation, h->cdsp.idct_perm);
     ff_permute_scantable(h->permutated_scantable, ff_zigzag_direct, permutation);
+    ff_permute_scantable(h->permutated_scantable_field, cavs_scan_field,
+                         permutation);
+    h->scantable = h->permutated_scantable;

     h->avctx       = avctx;
     avctx->pix_fmt = AV_PIX_FMT_YUV420P;
@@ -843,6 +863,8 @@ av_cold int ff_cavs_end(AVCodecContext *avctx)
     av_frame_free(&h->DPB[1].f);

     av_freep(&h->top_qp);
+    av_freep(&h->top_cbp);
+    av_freep(&h->top_c_pred_mode);
     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 213a306ed5..d111714879 100644
--- a/libavcodec/cavs.h
+++ b/libavcodec/cavs.h
@@ -30,6 +30,7 @@
 #include "libavutil/mem_internal.h"

 #include "avcodec.h"
+#include "cavs_aec.h"
 #include "cavsdsp.h"
 #include "blockdsp.h"
 #include "h264chroma.h"
@@ -185,8 +186,15 @@ typedef struct AVSContext {
     int stream_revision; ///<0 for samples from 2006, 1 for rm52j encoder
     int progressive;
     int pic_structure;
-    int skip_mode_flag; ///< select between skip_count or one skip_flag per MB
+    int skip_mode_flag;   ///< select between skip_count or one skip_flag per MB
     int aec_enable;       ///< the macroblock layer uses AEC (AVS1-P16)
+    int aec_start;        ///< byte offset of the current AEC slice's payload
+    CAVSAECContext aec;   ///< AEC decoder state and contexts, clause 8.4
+    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_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;
     int alpha_offset, beta_offset;
     int ref_flag;
@@ -228,6 +236,10 @@ typedef struct AVSContext {
     int cbp;
     DECLARE_ALIGNED(32, int16_t, block)[64];
     uint8_t permutated_scantable[64];
+    /** inverse block scan method 2 of clause 9.5.3 c), for field pictures */
+    uint8_t permutated_scantable_field[64];
+    /** the one of the two the current picture uses, selected in decode_pic() */
+    const uint8_t *scantable;

     /** intra prediction is done with un-deblocked samples
      they are saved here before deblocking the MB  */
diff --git a/libavcodec/cavsdec.c b/libavcodec/cavsdec.c
index b0e6c1361a..4d1f1c9275 100644
--- a/libavcodec/cavsdec.c
+++ b/libavcodec/cavsdec.c
@@ -528,7 +528,7 @@ static inline int dequant(AVSContext *h, int16_t *level_buf, uint8_t *run_buf,
 {
     int round = 1 << (shift - 1);
     int pos = -1;
-    const uint8_t *scantab = h->permutated_scantable;
+    const uint8_t *scantab = h->scantable;

     /* inverse scan and dequantization */
     while (--coeff_num >= 0) {
@@ -602,6 +602,255 @@ static int decode_residual_block(AVSContext *h, GetBitContext *gb,
 }


+/*****************************************************************************
+ *
+ * advanced entropy coding (AEC), clause 8.4
+ *
+ ****************************************************************************/
+
+/* Table 51: start index of each ae(v) element's context models */
+#define AEC_MB_SKIP_RUN               0
+#define AEC_MB_TYPE                   4
+#define AEC_MB_PART_TYPE             19
+#define AEC_INTRA_LUMA_PRED_MODE     22
+#define AEC_INTRA_CHROMA_PRED_MODE   26
+#define AEC_MB_REFERENCE_INDEX       30
+#define AEC_MV_DIFF_X                36
+#define AEC_MV_DIFF_Y                42
+#define AEC_CBP                      48
+#define AEC_MB_QP_DELTA              54
+#define AEC_COEFF_FRAME_LUMA         58
+#define AEC_COEFF_FRAME_CHROMA      124
+#define AEC_COEFF_FIELD_LUMA        190
+#define AEC_COEFF_FIELD_CHROMA      256
+
+/* a conforming block's quantized coefficients span -2^(n+3)..2^(n+3)-1
+ * with n the sample precision, 8 for both profiles (clause 9.6.2) */
+#define CAVS_MAX_ABS_LEVEL          2048
+
+/* one trans_coefficient set: 14 + 32 + 20 models, coeffRun from index 46 */
+#define AEC_COEFF_NUM_CTX            66
+#define AEC_COEFF_RUN                46
+#define AEC_COEFF_RUN_NUM_CTX        20
+
+/** 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 intra_luma_pred_mode (table 47) and derive IntraLumaPredMode
+ * from predIntraPredMode per clause 9.4.4.2 a).
+ */
+static int aec_intra_luma_pred_mode(AVSContext *h, int pred)
+{
+    int v = 0;
+
+    while (v < 4 &&
+           !ff_cavs_aec_decode_decision(&h->aec, AEC_INTRA_LUMA_PRED_MODE + v))
+        v++;
+
+    if (v == 0)
+        return pred;
+    if (v == 4)             /* 4 stands for 0 (9.4.4.2 a) 2)) */
+        v = 0;
+    return v < pred ? v : v + 1;
+}
+
+/**
+ * Decode intra_chroma_pred_mode (table 48, 8.4.4.2 e)).
+ * @return IntraChromaPredMode, 0 to 3 (table 60)
+ */
+static int aec_intra_chroma_pred_mode(AVSContext *h)
+{
+    /* a and b of 8.4.4.2 e); non-intra neighbours hold INTRA_C_LP */
+    const int a = (h->flags & A_AVAIL) &&
+                  h->left_c_pred_mode != INTRA_C_LP;
+    const int b = (h->flags & B_AVAIL) &&
+                  h->top_c_pred_mode[h->mbx] != INTRA_C_LP;
+    int v;
+
+    if (!ff_cavs_aec_decode_decision(&h->aec,
+                                     AEC_INTRA_CHROMA_PRED_MODE + a + b))
+        v = 0;
+    else if (!ff_cavs_aec_decode_decision(&h->aec,
+                                          AEC_INTRA_CHROMA_PRED_MODE + 3))
+        v = 1;
+    else
+        v = 2 + ff_cavs_aec_decode_decision(&h->aec,
+                                            AEC_INTRA_CHROMA_PRED_MODE + 3);
+
+    h->left_c_pred_mode        = v;
+    h->top_c_pred_mode[h->mbx] = v;
+    return v;
+}
+
+/**
+ * Decode cbp (table 50, 8.4.4.2 h), clause 9.4.7).
+ * @return MbCBP, a six bit mask over the block order numbers
+ */
+static int aec_cbp(AVSContext *h)
+{
+    const int left = (h->flags & A_AVAIL) ? ~h->left_cbp        : 0;
+    const int top  = (h->flags & B_AVAIL) ? ~h->top_cbp[h->mbx] : 0;
+    int cbp = 0;
+    int a, b;
+
+    a = (left >> 1) & 1;                        /* left macroblock, block 1 */
+    b = (top  >> 2) & 1;                        /* above macroblock, block 2 */
+    cbp |= ff_cavs_aec_decode_decision(&h->aec, AEC_CBP + a + 2 * b) << 0;
+
+    a = ~cbp & 1;                               /* this macroblock, block 0 */
+    b = (top >> 3) & 1;                         /* above macroblock, block 3 */
+    cbp |= ff_cavs_aec_decode_decision(&h->aec, AEC_CBP + a + 2 * b) << 1;
+
+    a = (left >> 3) & 1;                        /* left macroblock, block 3 */
+    b = ~cbp & 1;                               /* this macroblock, block 0 */
+    cbp |= ff_cavs_aec_decode_decision(&h->aec, AEC_CBP + a + 2 * b) << 2;
+
+    a = (~cbp >> 2) & 1;                        /* this macroblock, block 2 */
+    b = (~cbp >> 1) & 1;                        /* this macroblock, block 1 */
+    cbp |= ff_cavs_aec_decode_decision(&h->aec, AEC_CBP + a + 2 * b) << 3;
+
+    if (ff_cavs_aec_decode_decision(&h->aec, AEC_CBP + 4)) {
+        if (ff_cavs_aec_decode_decision(&h->aec, AEC_CBP + 5))
+            cbp |= 3 << 4;
+        else
+            cbp |= 1 << (4 + ff_cavs_aec_decode_decision(&h->aec, AEC_CBP + 5));
+    }
+
+    h->left_cbp        = cbp;
+    h->top_cbp[h->mbx] = cbp;
+    return cbp;
+}
+
+/**
+ * Decode mb_qp_delta (table 44 unary, 8.4.4.2 i)) and map the code
+ * number to the signed delta of clause 9.4.8.
+ */
+static int aec_mb_qp_delta(AVSContext *h, int *delta)
+{
+    int ctx = AEC_MB_QP_DELTA + (h->prev_delta_qp != 0);
+    int v   = 0;
+
+    while (!ff_cavs_aec_decode_decision(&h->aec, ctx)) {
+        v++;
+        ctx = AEC_MB_QP_DELTA + (v == 1 ? 2 : 3);
+        if (v > 64) {
+            av_log(h->avctx, AV_LOG_ERROR, "mb_qp_delta out of range\n");
+            return AVERROR_INVALIDDATA;
+        }
+    }
+
+    if (v)
+        v = (v & 1) ? (v + 1) / 2 : -((v + 1) / 2);
+    if (v < -32 || v > 31) {
+        av_log(h->avctx, AV_LOG_ERROR, "mb_qp_delta out of range\n");
+        return AVERROR_INVALIDDATA;
+    }
+    *delta = v;
+    return 0;
+}
+
+/**
+ * Decode the trans_coefficient pairs of one 8x8 block (8.4.4.2 j) and k)).
+ * @param chroma selects the chroma half of the context sets of table 51
+ */
+static int decode_residual_block_aec(AVSContext *h, int chroma, int qp,
+                                     uint8_t *dst, ptrdiff_t stride)
+{
+    int16_t level_buf[65];
+    uint8_t run_buf[65];
+    int16_t *block = h->block;
+    int lmax = 0, pos = 0, i, base, ret;
+
+    if (h->pic_structure)
+        base = chroma ? AEC_COEFF_FRAME_CHROMA : AEC_COEFF_FRAME_LUMA;
+    else
+        base = chroma ? AEC_COEFF_FIELD_CHROMA : AEC_COEFF_FIELD_LUMA;
+
+    for (i = 0; i < 65; i++) {
+        const int pri = cavs_aec_pri_idx[FFMIN(lmax, 5)];
+        int ctx_lvl = ff_cavs_aec_ctx_idx(base, AEC_COEFF_NUM_CTX,
+                                          pri * 3 - (pri != 0));
+        int ctx_run = ff_cavs_aec_ctx_idx(base + AEC_COEFF_RUN,
+                                          AEC_COEFF_RUN_NUM_CTX, pri * 4);
+        int abs_level, run_val;
+
+        if (ctx_lvl < 0 || ctx_run < 0)
+            return FFMIN(ctx_lvl, ctx_run);
+        if (get_bits_left(&h->gb) <= 0)
+            return AVERROR_INVALIDDATA;
+
+        /* coeffLevel, table 44 unary; secIdx as in IEEE 1857-2023 table 36,
+         * whose lMax == 0 column has no secIdx 2 */
+        if (!lmax) {
+            abs_level = 0;
+            if (!ff_cavs_aec_decode_decision(&h->aec, ctx_lvl)) {
+                do {
+                    abs_level++;
+                    if (abs_level >= CAVS_MAX_ABS_LEVEL) {
+                        av_log(h->avctx, AV_LOG_ERROR, "AbsLevel too large\n");
+                        return AVERROR_INVALIDDATA;
+                    }
+                } while (!ff_cavs_aec_decode_decision(&h->aec, ctx_lvl + 1));
+            }
+            abs_level++;                        /* clause 9.5.2 a) */
+        } else {
+            int ctx_w = ff_cavs_aec_ctx_idx(base, AEC_COEFF_NUM_CTX,
+                                            14 + (pos >> 1));
+            if (ctx_w < 0)
+                return ctx_w;
+            if (ff_cavs_aec_decode_decision_w(&h->aec, ctx_lvl, ctx_w))
+                break;                          /* AbsLevel 0, end of block */
+            abs_level = 1;
+            if (!ff_cavs_aec_decode_decision(&h->aec, ctx_lvl + 1)) {
+                do {
+                    abs_level++;
+                    if (abs_level > CAVS_MAX_ABS_LEVEL) {
+                        av_log(h->avctx, AV_LOG_ERROR, "AbsLevel too large\n");
+                        return AVERROR_INVALIDDATA;
+                    }
+                } while (!ff_cavs_aec_decode_decision(&h->aec, ctx_lvl + 2));
+            }
+        }
+
+        if (ff_cavs_aec_decode_bypass(&h->aec))
+            level_buf[i] = -abs_level;
+        else
+            level_buf[i] = abs_level;
+        if (level_buf[i] < -CAVS_MAX_ABS_LEVEL ||
+            level_buf[i] >= CAVS_MAX_ABS_LEVEL) {
+            av_log(h->avctx, AV_LOG_ERROR,
+                   "coefficient level out of range\n");
+            return AVERROR_INVALIDDATA;
+        }
+
+        ctx_run += abs_level > 1 ? 2 : 0;
+        run_val  = 0;
+        if (!ff_cavs_aec_decode_decision(&h->aec, ctx_run)) {
+            do {
+                run_val++;
+                if (run_val > 64) {
+                    av_log(h->avctx, AV_LOG_ERROR, "RunVal too large\n");
+                    return AVERROR_INVALIDDATA;
+                }
+            } while (!ff_cavs_aec_decode_decision(&h->aec, ctx_run + 1));
+        }
+        run_buf[i] = run_val + 1;   /* scan positions consumed, 9.5.3 b) */
+
+        /* lMax is updated with this coefficient before the next pair */
+        lmax = FFMAX(lmax, abs_level);
+        pos  = FFMIN(pos + run_val + 1, 63);
+    }
+
+    ret = dequant(h, level_buf, run_buf, block, dequant_mul[qp],
+                  dequant_shift[qp], i);
+    if (ret >= 0)
+        h->cdsp.cavs_idct8_add(dst, block, stride);
+    h->bdsp.clear_block(block);
+    return ret;
+}
+
+
 /**
  * Tell whether the byte aligned 00 00 01 at @p offset is a start code: in a
  * de-emulated payload it may be a coincidence (annex A).
@@ -626,17 +875,74 @@ static int is_start_code_offset(AVSContext *h, int offset)
     return 0;
 }

+/**
+ * Position the reader on the start code that ends an AEC slice: the first
+ * one at or after the slice's own payload. The reader position is not
+ * reliable: the arithmetic decoder's look ahead has run past it.
+ */
+static void aec_end_of_slice(AVSContext *h)
+{
+    GetBitContext *gb = &h->gb;
+    const uint8_t *buf = gb->buffer;
+    int size = gb->size_in_bits >> 3;
+    int i    = h->aec_start;
+
+    /* release gb; check_for_slice() waits for this */
+    h->aec.gb = NULL;
+
+    for (; i + 2 < size; i++)
+        if (!buf[i] && !buf[i + 1] && buf[i + 2] == 1 &&
+            is_start_code_offset(h, i))
+            break;
+    if (init_get_bits8(gb, buf, size) >= 0)
+        skip_bits_long(gb, i * 8);
+}
+
+/**
+ * Read mb_qp_delta when the macroblock has coefficients and the picture's qp
+ * is not fixed, and keep PreviousDeltaQP for the AEC contexts (clause 9.4.8).
+ */
+static int decode_mb_qp_delta(AVSContext *h)
+{
+    int delta = 0;
+
+    if (h->cbp && !h->qp_fixed) {
+        if (h->aec_enable) {
+            int ret = aec_mb_qp_delta(h, &delta);
+            if (ret < 0)
+                return ret;
+        } else {
+            delta = get_se_golomb(&h->gb);
+        }
+        h->qp = (h->qp + (unsigned)delta) & 63;
+    }
+    h->prev_delta_qp = delta;
+    return 0;
+}
+
+/** Decode one 8x8 block's residual with the picture's entropy coder. */
+static int decode_residual(AVSContext *h, const struct dec_2dvlc *r,
+                           int esc_golomb_order, int chroma, int qp,
+                           uint8_t *dst, ptrdiff_t stride)
+{
+    if (h->aec_enable)
+        return decode_residual_block_aec(h, chroma, qp, dst, stride);
+    return decode_residual_block(h, &h->gb, r, esc_golomb_order, qp, dst,
+                                 stride);
+}
+
 static inline int decode_residual_chroma(AVSContext *h)
 {
+    const int qp = ff_cavs_chroma_qp[h->qp];
+    int ret;
+
     if (h->cbp & (1 << 4)) {
-        int ret = decode_residual_block(h, &h->gb, chroma_dec, 0,
-                              ff_cavs_chroma_qp[h->qp], h->cu, h->c_stride);
+        ret = decode_residual(h, chroma_dec, 0, 1, qp, h->cu, h->c_stride);
         if (ret < 0)
             return ret;
     }
     if (h->cbp & (1 << 5)) {
-        int ret = decode_residual_block(h, &h->gb, chroma_dec, 0,
-                              ff_cavs_chroma_qp[h->qp], h->cv, h->c_stride);
+        ret = decode_residual(h, chroma_dec, 0, 1, qp, h->cv, h->c_stride);
         if (ret < 0)
             return ret;
     }
@@ -708,29 +1014,41 @@ static int decode_mb_i(AVSContext *h, int cbp_code)
         predpred = FFMIN(nA, nB);
         if (predpred == NOT_AVAIL) // if either is not available
             predpred = INTRA_L_LP;
-        if (!get_bits1(gb)) {
+        if (h->aec_enable) {
+            predpred = aec_intra_luma_pred_mode(h, predpred);
+        } else if (!get_bits1(gb)) {
             int rem_mode = get_bits(gb, 2);
             predpred     = rem_mode + (rem_mode >= predpred);
         }
         h->pred_mode_Y[pos] = predpred;
     }
-    pred_mode_uv = get_ue_golomb_31(gb);
-    if (pred_mode_uv > 6) {
-        av_log(h->avctx, AV_LOG_ERROR, "illegal intra chroma pred mode\n");
-        return AVERROR_INVALIDDATA;
+    if (h->aec_enable) {
+        pred_mode_uv = aec_intra_chroma_pred_mode(h);
+    } else {
+        pred_mode_uv = get_ue_golomb_31(gb);
+        if (pred_mode_uv > 6) {
+            av_log(h->avctx, AV_LOG_ERROR, "illegal intra chroma pred mode\n");
+            return AVERROR_INVALIDDATA;
+        }
     }
     ff_cavs_modify_mb_i(h, &pred_mode_uv);

     /* get coded block pattern */
-    if (h->cur.f->pict_type == AV_PICTURE_TYPE_I)
-        cbp_code = get_ue_golomb(gb);
-    if (cbp_code > 63U) {
-        av_log(h->avctx, AV_LOG_ERROR, "illegal intra cbp\n");
-        return AVERROR_INVALIDDATA;
+    if (h->aec_enable) {
+        /* under AEC an intra MB codes cbp too (table 26, clause 9.4.7) */
+        h->cbp = aec_cbp(h);
+    } else {
+        if (h->cur.f->pict_type == AV_PICTURE_TYPE_I)
+            cbp_code = get_ue_golomb(gb);
+        if (cbp_code > 63U) {
+            av_log(h->avctx, AV_LOG_ERROR, "illegal intra cbp\n");
+            return AVERROR_INVALIDDATA;
+        }
+        h->cbp = cbp_tab[cbp_code][0];
     }
-    h->cbp = cbp_tab[cbp_code][0];
-    if (h->cbp && !h->qp_fixed)
-        h->qp = (h->qp + (unsigned)get_se_golomb(gb)) & 63; //qp_delta
+    ret = decode_mb_qp_delta(h);
+    if (ret < 0)
+        return ret;

     /* luma intra prediction interleaved with residual decode/transform/add */
     for (block = 0; block < 4; block++) {
@@ -739,7 +1057,7 @@ static int decode_mb_i(AVSContext *h, int cbp_code)
         h->intra_pred_l[h->pred_mode_Y[scan3x3[block]]]
             (d, top, left, h->l_stride);
         if (h->cbp & (1<<block)) {
-            ret = decode_residual_block(h, gb, intra_dec, 1, h->qp, d, h->l_stride);
+            ret = decode_residual(h, intra_dec, 1, 0, h->qp, d, h->l_stride);
             if (ret < 0)
                 return ret;
         }
@@ -1014,6 +1332,9 @@ static inline int check_for_slice(AVSContext *h)

     if (h->mbx)
         return 0;
+    /* an AEC slice ends with its stuffing bit, not at a start code (7.2.4) */
+    if (h->aec_enable && h->aec.gb)
+        return 0;
     align = (-get_bits_count(gb)) & 7;
     /* check for stuffing byte */
     if (!align && (show_bits(gb, 8) == 0x80))
@@ -1037,6 +1358,13 @@ static inline int check_for_slice(AVSContext *h)
         ret = decode_slice_header(h, gb);
         if (ret < 0)
             return ret;
+        if (h->aec_enable) {
+            /* aec_byte_alignment_bit padding, then 8.4.1 */
+            align_get_bits(gb);
+            h->aec_start = get_bits_count(gb) >> 3;
+            ff_cavs_aec_init(&h->aec, gb);
+            h->prev_delta_qp = 0;   /* reset with PreviousQP, clause 9.3 */
+        }
         return 1;
     }
     return 0;
@@ -1134,6 +1462,9 @@ static int decode_pic(AVSContext *h)
     h->pic_structure = 1;
     if (!h->progressive)
         h->pic_structure = get_bits1(&h->gb);
+    /* a field coded picture uses inverse block scan method 2 (9.5.3 c)) */
+    h->scantable = h->pic_structure ? h->permutated_scantable
+                                    : h->permutated_scantable_field;
     if (!h->pic_structure && h->stc == PIC_PB_START_CODE)
         skip_bits1(&h->gb);     //advanced_pred_mode_disable
     skip_bits1(&h->gb);        //top_field_first
@@ -1175,12 +1506,19 @@ 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);
@@ -1190,6 +1528,8 @@ static int decode_pic(AVSContext *h)
             ret = decode_mb_i(h, 0);
             if (ret < 0)
                 break;
+            if (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 {