ffmpeg | branch: master | Andreas Rheinhardt <andreas.rheinha...@outlook.com> | 
Mon Mar  3 00:21:04 2025 +0100| [5df8c86b247f39195d96d7a5b8d0f6c9113a401d] | 
committer: Andreas Rheinhardt

avcodec/mpeg4video: Split ff_mpeg4_pred_dc()

It currently does two things: a) Get a prediction for the dc
and the dc direction and b) process said prediction. Processing
the prediction differs for encoding (getting a diff) and decoding
(getting the level via diff+prediction). So having a common function
performing b) makes no sense.

Even worse, there is a decoding mode where the dc coefficient (diff)
is not coded specially and therefore unavailable before entering
the block decoding loop, so that one can only perform a). Before
this commit, the decoder simply called ff_mpeg4_pred_dc() twice;
the results of the b) part of the call before the loop were ignored
(but the compiler could not elide them because they involved error
messages) and a) was also performed twice.

This commit changes this by splitting b) out of ff_mpeg4_pred_dc()
and moving this code to decoder and encoder.

Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=5df8c86b247f39195d96d7a5b8d0f6c9113a401d
---

 libavcodec/mpeg4video.h    | 47 ++++-----------------------------------------
 libavcodec/mpeg4videodec.c | 48 +++++++++++++++++++++++++++++++++++++++++-----
 libavcodec/mpeg4videoenc.c | 10 ++++++++--
 3 files changed, 55 insertions(+), 50 deletions(-)

diff --git a/libavcodec/mpeg4video.h b/libavcodec/mpeg4video.h
index 29b11eb92e..9ac18943a2 100644
--- a/libavcodec/mpeg4video.h
+++ b/libavcodec/mpeg4video.h
@@ -44,24 +44,15 @@ int ff_mpeg4_set_direct_mv(MpegEncContext *s, int mx, int 
my);
 
 /**
  * Predict the dc.
- * encoding quantized level -> quantized diff
- * decoding quantized diff -> quantized level
  * @param n block index (0-3 are luma, 4-5 are chroma)
  * @param dir_ptr pointer to an integer where the prediction direction will be 
stored
  */
-static inline int ff_mpeg4_pred_dc(MpegEncContext *s, int n, int level,
-                                   int *dir_ptr, int encoding)
+static inline int ff_mpeg4_pred_dc(MpegEncContext *s, int n, int *dir_ptr)
 {
-    int a, b, c, wrap, pred, scale, ret;
-    int16_t *dc_val;
+    int a, b, c, wrap, pred;
+    const int16_t *dc_val;
 
     /* find prediction */
-    if (n < 4)
-        scale = s->y_dc_scale;
-    else
-        scale = s->c_dc_scale;
-    if (IS_3IV1)
-        scale = 8;
 
     wrap   = s->block_wrap[n];
     dc_val = s->dc_val[0] + s->block_index[n];
@@ -93,37 +84,7 @@ static inline int ff_mpeg4_pred_dc(MpegEncContext *s, int n, 
int level,
         pred     = a;
         *dir_ptr = 0; /* left */
     }
-    /* we assume pred is positive */
-    pred = FASTDIV((pred + (scale >> 1)), scale);
-
-    if (encoding) {
-        ret = level - pred;
-    } else {
-        level += pred;
-        ret    = level;
-    }
-    level *= scale;
-    if (level & (~2047)) {
-        if (!s->encoding && (s->avctx->err_recognition & (AV_EF_BITSTREAM | 
AV_EF_AGGRESSIVE))) {
-            if (level < 0) {
-                av_log(s->avctx, AV_LOG_ERROR,
-                       "dc<0 at %dx%d\n", s->mb_x, s->mb_y);
-                return AVERROR_INVALIDDATA;
-            }
-            if (level > 2048 + scale) {
-                av_log(s->avctx, AV_LOG_ERROR,
-                       "dc overflow at %dx%d\n", s->mb_x, s->mb_y);
-                return AVERROR_INVALIDDATA;
-            }
-        }
-        if (level < 0)
-            level = 0;
-        else if (!(s->workaround_bugs & FF_BUG_DC_CLIP))
-            level = 2047;
-    }
-    dc_val[0] = level;
-
-    return ret;
+    return pred;
 }
 
 #endif /* AVCODEC_MPEG4VIDEO_H */
diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index 2a340ea682..31d00dd0b9 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -880,6 +880,43 @@ static inline int get_amv(Mpeg4DecContext *ctx, int n)
     return sum;
 }
 
+static inline int mpeg4_get_level_dc(MpegEncContext *s, int n, int pred, int 
level)
+{
+    int scale = n < 4 ? s->y_dc_scale : s->c_dc_scale;
+    int ret;
+
+    if (IS_3IV1)
+        scale = 8;
+
+    /* we assume pred is positive */
+    pred = FASTDIV((pred + (scale >> 1)), scale);
+
+    level += pred;
+    ret    = level;
+    level *= scale;
+    if (level & (~2047)) {
+        if (s->avctx->err_recognition & (AV_EF_BITSTREAM | AV_EF_AGGRESSIVE)) {
+            if (level < 0) {
+                av_log(s->avctx, AV_LOG_ERROR,
+                       "dc<0 at %dx%d\n", s->mb_x, s->mb_y);
+                return AVERROR_INVALIDDATA;
+            }
+            if (level > 2048 + scale) {
+                av_log(s->avctx, AV_LOG_ERROR,
+                       "dc overflow at %dx%d\n", s->mb_x, s->mb_y);
+                return AVERROR_INVALIDDATA;
+            }
+        }
+        if (level < 0)
+            level = 0;
+        else if (!(s->workaround_bugs & FF_BUG_DC_CLIP))
+            level = 2047;
+    }
+    s->dc_val[0][s->block_index[n]] = level;
+
+    return ret;
+}
+
 /**
  * Decode the dc value.
  * @param n block index (0-3 are luma, 4-5 are chroma)
@@ -888,7 +925,7 @@ static inline int get_amv(Mpeg4DecContext *ctx, int n)
  */
 static inline int mpeg4_decode_dc(MpegEncContext *s, int n, int *dir_ptr)
 {
-    int level, code;
+    int level, code, pred;
 
     if (n < 4)
         code = get_vlc2(&s->gb, dc_lum, DC_VLC_BITS, 1);
@@ -926,7 +963,8 @@ static inline int mpeg4_decode_dc(MpegEncContext *s, int n, 
int *dir_ptr)
         }
     }
 
-    return ff_mpeg4_pred_dc(s, n, level, dir_ptr, 0);
+    pred = ff_mpeg4_pred_dc(s, n, dir_ptr);
+    return mpeg4_get_level_dc(s, n, pred, level);
 }
 
 /**
@@ -1290,7 +1328,7 @@ static inline int mpeg4_decode_block(Mpeg4DecContext 
*ctx, int16_t *block,
                                      int use_intra_dc_vlc, int rvlc)
 {
     MpegEncContext *s = &ctx->m;
-    int level, i, last, run, qmul, qadd;
+    int level, i, last, run, qmul, qadd, pred;
     int av_uninit(dc_pred_dir);
     const RLTable *rl;
     const RL_VLC_ELEM *rl_vlc;
@@ -1317,7 +1355,7 @@ static inline int mpeg4_decode_block(Mpeg4DecContext 
*ctx, int16_t *block,
             i        = 0;
         } else {
             i = -1;
-            ff_mpeg4_pred_dc(s, n, 0, &dc_pred_dir, 0);
+            pred = ff_mpeg4_pred_dc(s, n, &dc_pred_dir);
         }
         if (!coded)
             goto not_coded;
@@ -1540,7 +1578,7 @@ static inline int mpeg4_decode_block(Mpeg4DecContext 
*ctx, int16_t *block,
 not_coded:
     if (intra) {
         if (!use_intra_dc_vlc) {
-            block[0] = ff_mpeg4_pred_dc(s, n, block[0], &dc_pred_dir, 0);
+            block[0] = mpeg4_get_level_dc(s, n, pred, block[0]);
 
             i -= i >> 31;  // if (i == -1) i = 0;
         }
diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c
index 64fb96a0cf..26f9b40ff7 100644
--- a/libavcodec/mpeg4videoenc.c
+++ b/libavcodec/mpeg4videoenc.c
@@ -806,8 +806,14 @@ void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t 
block[6][64],
         const uint8_t *scan_table[6];
         int i;
 
-        for (i = 0; i < 6; i++)
-            dc_diff[i] = ff_mpeg4_pred_dc(s, i, block[i][0], &dir[i], 1);
+        for (int i = 0; i < 6; i++) {
+            int pred  = ff_mpeg4_pred_dc(s, i, &dir[i]);
+            int scale = i < 4 ? s->y_dc_scale : s->c_dc_scale;
+
+            pred = FASTDIV((pred + (scale >> 1)), scale);
+            dc_diff[i] = block[i][0] - pred;
+            s->dc_val[0][s->block_index[i]] = av_clip_uintp2(block[i][0] * 
scale, 11);
+        }
 
         if (s->avctx->flags & AV_CODEC_FLAG_AC_PRED) {
             s->ac_pred = decide_ac_pred(s, block, dir, scan_table, 
zigzag_last_index);

_______________________________________________
ffmpeg-cvslog mailing list
ffmpeg-cvslog@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-cvslog

To unsubscribe, visit link above, or email
ffmpeg-cvslog-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to