[FFmpeg-cvslog] avcodec/svq1dec: detect buggy FFmpeg encoder and apply correction to interframe mean symbols

Peter Ross git at videolan.org
Tue Nov 1 01:15:22 EET 2022


ffmpeg | branch: master | Peter Ross <pross at xvid.org> | Tue Nov  1 09:24:29 2022 +1100| [16af424bf983409e00a84af1c98bbe7171ddd79f] | committer: Peter Ross

avcodec/svq1dec: detect buggy FFmpeg encoder and apply correction to interframe mean symbols

The FFmpeg encoder does not increment the temporal reference field, so use
that knowledge plus the extradata field to detect buggy versions of the encoder.

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

 libavcodec/svq1dec.c | 32 +++++++++++++++++++++++---------
 1 file changed, 23 insertions(+), 9 deletions(-)

diff --git a/libavcodec/svq1dec.c b/libavcodec/svq1dec.c
index 828b38b93d..c7269456e2 100644
--- a/libavcodec/svq1dec.c
+++ b/libavcodec/svq1dec.c
@@ -73,6 +73,8 @@ typedef struct SVQ1Context {
     int height;
     int frame_code;
     int nonref;         // 1 if the current frame won't be referenced
+
+    int last_tempref;
 } SVQ1Context;
 
 static const uint8_t string_table[256] = {
@@ -229,7 +231,7 @@ static int svq1_decode_block_intra(GetBitContext *bitbuf, uint8_t *pixels,
 }
 
 static int svq1_decode_block_non_intra(GetBitContext *bitbuf, uint8_t *pixels,
-                                       ptrdiff_t pitch)
+                                       ptrdiff_t pitch, int buggy)
 {
     uint32_t bit_cache;
     uint8_t *list[63];
@@ -270,6 +272,13 @@ static int svq1_decode_block_non_intra(GetBitContext *bitbuf, uint8_t *pixels,
 
         mean = get_vlc2(bitbuf, svq1_inter_mean.table, 9, 3) - 256;
 
+        if (buggy) {
+            if (mean == -128)
+                mean = 128;
+            else if (mean == 128)
+                mean = -128;
+        }
+
         SVQ1_CALC_CODEBOOK_ENTRIES(ff_svq1_inter_codebooks);
 
         for (y = 0; y < height; y++) {
@@ -455,7 +464,7 @@ static int svq1_decode_delta_block(AVCodecContext *avctx, HpelDSPContext *hdsp,
                                    GetBitContext *bitbuf,
                                    uint8_t *current, uint8_t *previous,
                                    ptrdiff_t pitch, svq1_pmv *motion, int x, int y,
-                                   int width, int height)
+                                   int width, int height, int buggy)
 {
     uint32_t block_type;
     int result = 0;
@@ -487,7 +496,7 @@ static int svq1_decode_delta_block(AVCodecContext *avctx, HpelDSPContext *hdsp,
             ff_dlog(avctx, "Error in svq1_motion_inter_block %i\n", result);
             break;
         }
-        result = svq1_decode_block_non_intra(bitbuf, current, pitch);
+        result = svq1_decode_block_non_intra(bitbuf, current, pitch, buggy);
         break;
 
     case SVQ1_BLOCK_INTER_4V:
@@ -498,7 +507,7 @@ static int svq1_decode_delta_block(AVCodecContext *avctx, HpelDSPContext *hdsp,
             ff_dlog(avctx, "Error in svq1_motion_inter_4v_block %i\n", result);
             break;
         }
-        result = svq1_decode_block_non_intra(bitbuf, current, pitch);
+        result = svq1_decode_block_non_intra(bitbuf, current, pitch, buggy);
         break;
 
     case SVQ1_BLOCK_INTRA:
@@ -524,15 +533,18 @@ static void svq1_parse_string(GetBitContext *bitbuf, uint8_t out[257])
     out[i] = 0;
 }
 
-static int svq1_decode_frame_header(AVCodecContext *avctx, AVFrame *frame)
+static int svq1_decode_frame_header(AVCodecContext *avctx, AVFrame *frame, int * buggy)
 {
     SVQ1Context *s = avctx->priv_data;
     GetBitContext *bitbuf = &s->gb;
     int frame_size_code;
     int width  = s->width;
     int height = s->height;
+    int tempref;
 
-    skip_bits(bitbuf, 8); /* temporal_reference */
+    tempref = get_bits(bitbuf, 8); /* temporal_reference */
+    *buggy = tempref == 0 && s->last_tempref == 0 && avctx->extradata_size == 0;
+    s->last_tempref = tempref;
 
     /* frame type */
     s->nonref = 0;
@@ -624,7 +636,7 @@ static int svq1_decode_frame(AVCodecContext *avctx, AVFrame *cur,
     int buf_size       = avpkt->size;
     SVQ1Context     *s = avctx->priv_data;
     uint8_t *current;
-    int result, i, x, y, width, height;
+    int result, i, x, y, width, height, buggy;
     int ret;
 
     /* initialize bit buffer */
@@ -664,7 +676,7 @@ static int svq1_decode_frame(AVCodecContext *avctx, AVFrame *cur,
             src[i] = ((src[i] << 16) | (src[i] >> 16)) ^ src[7 - i];
     }
 
-    result = svq1_decode_frame_header(avctx, cur);
+    result = svq1_decode_frame_header(avctx, cur, &buggy);
     if (result != 0) {
         ff_dlog(avctx, "Error in svq1_decode_frame_header %i\n", result);
         return result;
@@ -734,7 +746,7 @@ static int svq1_decode_frame(AVCodecContext *avctx, AVFrame *cur,
                     result = svq1_decode_delta_block(avctx, &s->hdsp,
                                                      &s->gb, &current[x],
                                                      previous, linesize,
-                                                     s->pmv, x, y, width, height);
+                                                     s->pmv, x, y, width, height, buggy);
                     if (result != 0) {
                         ff_dlog(avctx,
                                 "Error in svq1_decode_delta_block %i\n",
@@ -820,6 +832,8 @@ static av_cold int svq1_decode_init(AVCodecContext *avctx)
 
     ff_thread_once(&init_static_once, svq1_static_init);
 
+    s->last_tempref = 0xFF;
+
     return 0;
 }
 



More information about the ffmpeg-cvslog mailing list