[FFmpeg-devel] [PATCH 59/67] avcodec/h261dec: Unquantize coefficients while parsing them

Andreas Rheinhardt andreas.rheinhardt at outlook.com
Fri Jun 14 21:25:50 EEST 2024


This is beneficial for performance: When concatenating
the file from the vsynth1-h261 fate-test 100 times,
performance (measured by timing the codec's decode callback)
improved by 9.6%.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at outlook.com>
---
 libavcodec/h261dec.c                     | 11 +++++++++--
 libavcodec/mpegvideo_dec.c               | 11 ++++++-----
 libavcodec/mpegvideo_enc.c               |  2 +-
 libavcodec/mpv_reconstruct_mb_template.c | 24 ++++++++++++------------
 4 files changed, 28 insertions(+), 20 deletions(-)

diff --git a/libavcodec/h261dec.c b/libavcodec/h261dec.c
index f1c1e1a48a..6df8588bb6 100644
--- a/libavcodec/h261dec.c
+++ b/libavcodec/h261dec.c
@@ -244,6 +244,7 @@ static int h261_decode_block(H261DecContext *h, int16_t *block, int n, int coded
     int level, i, j, run;
     const RLTable *rl = &ff_h261_rl_tcoeff;
     const uint8_t *scan_table;
+    const int qmul = s->qscale << 1, qadd = (s->qscale - 1) | 1;
 
     /* For the variable length encoding there are two code tables, one being
      * used for the first transmitted LEVEL in INTER, INTER + MC and
@@ -265,7 +266,7 @@ static int h261_decode_block(H261DecContext *h, int16_t *block, int n, int coded
          * being coded as 1111 1111. */
         if (level == 255)
             level = 128;
-        block[0] = level;
+        block[0] = level * s->y_dc_scale;
         i        = 1;
     } else if (coded) {
         // Run  Level   Code
@@ -276,7 +277,8 @@ static int h261_decode_block(H261DecContext *h, int16_t *block, int n, int coded
         i = 0;
         if (check & 0x2) {
             skip_bits(&s->gb, 2);
-            block[0] = (check & 0x1) ? -1 : 1;
+            block[0] = qmul + qadd;
+            block[0] *= (check & 0x1) ? -1 : 1;
             i        = 1;
         }
     } else {
@@ -306,10 +308,15 @@ static int h261_decode_block(H261DecContext *h, int16_t *block, int n, int coded
             run   = SHOW_UBITS(re, &s->gb, 6) + 1;
             SKIP_CACHE(re, &s->gb, 6);
             level = SHOW_SBITS(re, &s->gb, 8);
+            if (level > 0)
+                level = level * qmul + qadd;
+            else if (level < 0)
+                level = level * qmul - qadd;
             SKIP_COUNTER(re, &s->gb, 6 + 8);
         } else if (level == 0) {
             break;
         } else {
+            level = level * qmul + qadd;
             if (SHOW_UBITS(re, &s->gb, 1))
                 level = -level;
             SKIP_COUNTER(re, &s->gb, 1);
diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c
index 684f31947c..da88a35120 100644
--- a/libavcodec/mpegvideo_dec.c
+++ b/libavcodec/mpegvideo_dec.c
@@ -927,15 +927,16 @@ void ff_mpv_reconstruct_mb(MpegEncContext *s, int16_t block[12][64])
        }
     }
 
+    av_assert2((s->out_format <= FMT_H261) == (s->out_format == FMT_H261 || s->out_format == FMT_MPEG1));
     if (!s->avctx->lowres) {
 #if !CONFIG_SMALL
-        if (s->out_format == FMT_MPEG1)
-            mpv_reconstruct_mb_internal(s, block, 0, DEFINITELY_MPEG12);
+        if (s->out_format <= FMT_H261)
+            mpv_reconstruct_mb_internal(s, block, 0, DEFINITELY_MPEG12_H261);
         else
-            mpv_reconstruct_mb_internal(s, block, 0, NOT_MPEG12);
+            mpv_reconstruct_mb_internal(s, block, 0, NOT_MPEG12_H261);
 #else
-        mpv_reconstruct_mb_internal(s, block, 0, MAY_BE_MPEG12);
+        mpv_reconstruct_mb_internal(s, block, 0, MAY_BE_MPEG12_H261);
 #endif
     } else
-        mpv_reconstruct_mb_internal(s, block, 1, MAY_BE_MPEG12);
+        mpv_reconstruct_mb_internal(s, block, 1, MAY_BE_MPEG12_H261);
 }
diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index 125d16e694..d05a93d249 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -1101,7 +1101,7 @@ static void mpv_reconstruct_mb(MpegEncContext *s, int16_t block[12][64])
        }
     }
 
-    mpv_reconstruct_mb_internal(s, block, 0, MAY_BE_MPEG12);
+    mpv_reconstruct_mb_internal(s, block, 0, MAY_BE_MPEG12_H261);
 }
 
 static int get_sae(const uint8_t *src, int ref, int stride)
diff --git a/libavcodec/mpv_reconstruct_mb_template.c b/libavcodec/mpv_reconstruct_mb_template.c
index 4b16974827..dca982ae0f 100644
--- a/libavcodec/mpv_reconstruct_mb_template.c
+++ b/libavcodec/mpv_reconstruct_mb_template.c
@@ -20,9 +20,9 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#define NOT_MPEG12        0
-#define MAY_BE_MPEG12     1
-#define DEFINITELY_MPEG12 2
+#define NOT_MPEG12_H261        0
+#define MAY_BE_MPEG12_H261     1
+#define DEFINITELY_MPEG12_H261 2
 
 /* put block[] to dest[] */
 static inline void put_dct(MpegEncContext *s,
@@ -56,14 +56,14 @@ static av_always_inline
 void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64],
                                  int lowres_flag, int is_mpeg12)
 {
-#define IS_MPEG12(s) (is_mpeg12 == MAY_BE_MPEG12 ? ((s)->out_format == FMT_MPEG1) : is_mpeg12)
+#define IS_MPEG12_H261(s) (is_mpeg12 == MAY_BE_MPEG12_H261 ? ((s)->out_format <= FMT_H261) : is_mpeg12)
     const int mb_xy = s->mb_y * s->mb_stride + s->mb_x;
 
     s->cur_pic.qscale_table[mb_xy] = s->qscale;
 
     /* update DC predictors for P macroblocks */
     if (!s->mb_intra) {
-        if (is_mpeg12 != DEFINITELY_MPEG12 && (s->h263_pred || s->h263_aic)) {
+        if (is_mpeg12 != DEFINITELY_MPEG12_H261 && (s->h263_pred || s->h263_aic)) {
             if (s->mbintra_table[mb_xy])
                 ff_clean_intra_table_entries(s);
         } else {
@@ -71,7 +71,7 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64],
             s->last_dc[1] =
             s->last_dc[2] = 128 << s->intra_dc_precision;
         }
-    } else if (is_mpeg12 != DEFINITELY_MPEG12 && (s->h263_pred || s->h263_aic))
+    } else if (is_mpeg12 != DEFINITELY_MPEG12_H261 && (s->h263_pred || s->h263_aic))
         s->mbintra_table[mb_xy] = 1;
 
 #if IS_ENCODER
@@ -110,7 +110,7 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64],
             /* decoding or more than one mb_type (MC was already done otherwise) */
 
 #if !IS_ENCODER
-            if (HAVE_THREADS && is_mpeg12 != DEFINITELY_MPEG12 &&
+            if (HAVE_THREADS && is_mpeg12 != DEFINITELY_MPEG12_H261 &&
                 s->avctx->active_thread_type & FF_THREAD_FRAME) {
                 if (s->mv_dir & MV_DIR_FORWARD) {
                     ff_thread_progress_await(&s->last_pic.ptr->progress,
@@ -136,7 +136,7 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64],
                 const op_pixels_func (*op_pix)[4];
                 const qpel_mc_func (*op_qpix)[16];
 
-                if ((is_mpeg12 == DEFINITELY_MPEG12 || !s->no_rounding) || s->pict_type == AV_PICTURE_TYPE_B) {
+                if ((is_mpeg12 == DEFINITELY_MPEG12_H261 || !s->no_rounding) || s->pict_type == AV_PICTURE_TYPE_B) {
                     op_pix = s->hdsp.put_pixels_tab;
                     op_qpix = s->qdsp.put_qpel_pixels_tab;
                 } else {
@@ -162,7 +162,7 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64],
             }
 
             /* add dct residue */
-            if (!(IS_MPEG12(s) || s->msmpeg4_version != MSMP4_UNUSED ||
+            if (!(IS_MPEG12_H261(s) || s->msmpeg4_version != MSMP4_UNUSED ||
                   (s->codec_id == AV_CODEC_ID_MPEG4 && !s->mpeg_quant)))
 #endif /* !IS_ENCODER */
             {
@@ -187,7 +187,7 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64],
                 }
             }
 #if !IS_ENCODER
-              else if (is_mpeg12 == DEFINITELY_MPEG12 || lowres_flag || (s->codec_id != AV_CODEC_ID_WMV2)) {
+              else if (is_mpeg12 == DEFINITELY_MPEG12_H261 || lowres_flag || (s->codec_id != AV_CODEC_ID_WMV2)) {
                 add_dct(s, block[0], 0, dest_y                          , dct_linesize);
                 add_dct(s, block[1], 1, dest_y              + block_size, dct_linesize);
                 add_dct(s, block[2], 2, dest_y + dct_offset             , dct_linesize);
@@ -222,12 +222,12 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64],
 #if !IS_ENCODER
             /* Only MPEG-4 Simple Studio Profile is supported in > 8-bit mode.
                TODO: Integrate 10-bit properly into mpegvideo.c so that ER works properly */
-            if (is_mpeg12 != DEFINITELY_MPEG12 && CONFIG_MPEG4_DECODER &&
+            if (is_mpeg12 != DEFINITELY_MPEG12_H261 && CONFIG_MPEG4_DECODER &&
                 /* s->codec_id == AV_CODEC_ID_MPEG4 && */
                 s->avctx->bits_per_raw_sample > 8) {
                 ff_mpeg4_decode_studio(s, dest_y, dest_cb, dest_cr, block_size,
                                        uvlinesize, dct_linesize, dct_offset);
-            } else if (!IS_MPEG12(s))
+            } else if (!IS_MPEG12_H261(s))
 #endif /* !IS_ENCODER */
             {
                 /* dct only in intra block */
-- 
2.40.1



More information about the ffmpeg-devel mailing list