[FFmpeg-devel] [PATCH] avcodec/vp56: decode interlace content

Peter Ross pross at xvid.org
Wed Oct 9 08:35:08 EEST 2024


Modification of patch submitted by Aurelien Jacobs (November 2007).

Fixes ticket #5581.
---
 libavcodec/vp5.c     |  5 +----
 libavcodec/vp56.c    | 32 +++++++++++++++++++++++++++++++-
 libavcodec/vp56.h    |  6 ++++++
 libavcodec/vp6.c     | 11 ++++++-----
 libavcodec/vp6data.h | 11 +++++++++++
 5 files changed, 55 insertions(+), 10 deletions(-)

diff --git a/libavcodec/vp5.c b/libavcodec/vp5.c
index 78d4b38ce3..77b479471b 100644
--- a/libavcodec/vp5.c
+++ b/libavcodec/vp5.c
@@ -58,10 +58,7 @@ static int vp5_parse_header(VP56Context *s, const uint8_t *buf, int buf_size)
         if(vp56_rac_gets(c, 5) > 5)
             return AVERROR_INVALIDDATA;
         vp56_rac_gets(c, 2);
-        if (vpx_rac_get(c)) {
-            avpriv_report_missing_feature(s->avctx, "Interlacing");
-            return AVERROR_PATCHWELCOME;
-        }
+        s->interlaced = vp56_rac_gets(c, 1);
         rows = vp56_rac_gets(c, 8);  /* number of stored macroblock rows */
         cols = vp56_rac_gets(c, 8);  /* number of stored macroblock cols */
         if (!rows || !cols) {
diff --git a/libavcodec/vp56.c b/libavcodec/vp56.c
index 1da47ca43f..298d81c436 100644
--- a/libavcodec/vp56.c
+++ b/libavcodec/vp56.c
@@ -428,6 +428,7 @@ static void vp56_idct_add(VP56Context *s, uint8_t * dest, ptrdiff_t stride, int1
 
 static av_always_inline void vp56_render_mb(VP56Context *s, int row, int col, int is_alpha, VP56mb mb_type)
 {
+    ptrdiff_t ref_stride[4];
     int b, ab, b_max, plane, off;
     AVFrame *frame_current, *frame_ref;
     VP56Frame ref_frame = ff_vp56_reference_frame[mb_type];
@@ -439,6 +440,13 @@ static av_always_inline void vp56_render_mb(VP56Context *s, int row, int col, in
     if (mb_type != VP56_MB_INTRA && !frame_ref->data[0])
         return;
 
+    memcpy(ref_stride, s->stride, sizeof(s->stride));
+    if (s->interlaced && s->il_block) {
+        s->block_offset[2] -= s->stride[0] * 7;
+        s->block_offset[3] -= s->stride[0] * 7;
+        s->stride[0] *= 2;
+    }
+
     ab = 6*is_alpha;
     b_max = 6 - 2*is_alpha;
 
@@ -475,7 +483,7 @@ static av_always_inline void vp56_render_mb(VP56Context *s, int row, int col, in
                 int x_off = b==1 || b==3 ? 8 : 0;
                 int y_off = b==2 || b==3 ? 8 : 0;
                 plane = ff_vp56_b2p[b+ab];
-                vp56_mc(s, b, plane, frame_ref->data[plane], s->stride[plane],
+                vp56_mc(s, b, plane, frame_ref->data[plane], ref_stride[plane],
                         16*col+x_off, 16*row+y_off);
                 vp56_idct_add(s, frame_current->data[plane] + s->block_offset[b],
                               s->stride[plane], s->block_coeff[b], s->idct_selector[b]);
@@ -487,6 +495,12 @@ static av_always_inline void vp56_render_mb(VP56Context *s, int row, int col, in
         s->block_coeff[4][0] = 0;
         s->block_coeff[5][0] = 0;
     }
+
+    if (s->interlaced && s->il_block) {
+        s->stride[0] /= 2;
+        s->block_offset[2] += s->stride[0] * 7;
+        s->block_offset[3] += s->stride[0] * 7;
+    }
 }
 
 static int vp56_decode_mb(VP56Context *s, int row, int col, int is_alpha)
@@ -494,6 +508,19 @@ static int vp56_decode_mb(VP56Context *s, int row, int col, int is_alpha)
     VP56mb mb_type;
     int ret;
 
+    if (s->interlaced) {
+        int prob = s->il_prob;
+
+        if (col > 0) {
+            if (s->il_block)
+                prob -= prob >> 1;
+            else
+                prob += (256 - prob) >> 1;  /* can be simplified/combined */
+        }
+
+        s->il_block = vpx_rac_get_prob(&s->c, prob);
+    }
+
     if (s->frames[VP56_FRAME_CURRENT]->flags & AV_FRAME_FLAG_KEY)
         mb_type = VP56_MB_INTRA;
     else
@@ -686,6 +713,9 @@ static int ff_vp56_decode_mbs(AVCodecContext *avctx, void *data,
     if (s->parse_coeff_models(s))
         goto next;
 
+    if (s->interlaced)
+       s->il_prob = vp56_rac_gets(&s->c, 8);
+
     memset(s->prev_dc, 0, sizeof(s->prev_dc));
     s->prev_dc[1][VP56_FRAME_CURRENT] = 128;
     s->prev_dc[2][VP56_FRAME_CURRENT] = 128;
diff --git a/libavcodec/vp56.h b/libavcodec/vp56.h
index 9dc0b9c7ad..87b7e06e0b 100644
--- a/libavcodec/vp56.h
+++ b/libavcodec/vp56.h
@@ -151,6 +151,7 @@ struct vp56_context {
     VP56Macroblock *macroblocks;
     DECLARE_ALIGNED(16, int16_t, block_coeff)[6][64];
     int idct_selector[6];
+    const uint8_t *def_coeff_reorder;/* used in vp6 only */
 
     /* motion vectors */
     VP56mv mv[6];  /* vectors for each block in MB */
@@ -171,6 +172,11 @@ struct vp56_context {
 
     int has_alpha;
 
+    /* interlacing params */
+    int interlaced;
+    int il_prob;
+    int il_block;
+
     /* upside-down flipping hints */
     int flip;  /* are we flipping ? */
     int frbi;  /* first row block index in MB */
diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c
index 97d63a5870..73d117c871 100644
--- a/libavcodec/vp6.c
+++ b/libavcodec/vp6.c
@@ -68,10 +68,11 @@ static int vp6_parse_header(VP56Context *s, const uint8_t *buf, int buf_size)
         if (sub_version > 8)
             return AVERROR_INVALIDDATA;
         s->filter_header = buf[1] & 0x06;
-        if (buf[1] & 1) {
-            avpriv_report_missing_feature(s->avctx, "Interlacing");
-            return AVERROR_PATCHWELCOME;
-        }
+        s->interlaced = buf[1] & 1;
+        if (s->interlaced)
+            s->def_coeff_reorder = vp6_il_coeff_reorder;
+        else
+            s->def_coeff_reorder = vp6_def_coeff_reorder;
         if (separated_coeff || !s->filter_header) {
             coeff_offset = AV_RB16(buf+2) - 2;
             buf += 2;
@@ -228,7 +229,7 @@ static void vp6_default_models_init(VP56Context *s)
     memcpy(model->vector_fdv, vp6_def_fdv_vector_model, sizeof(model->vector_fdv));
     memcpy(model->vector_pdv, vp6_def_pdv_vector_model, sizeof(model->vector_pdv));
     memcpy(model->coeff_runv, vp6_def_runv_coeff_model, sizeof(model->coeff_runv));
-    memcpy(model->coeff_reorder, vp6_def_coeff_reorder, sizeof(model->coeff_reorder));
+    memcpy(model->coeff_reorder, s->def_coeff_reorder, sizeof(model->coeff_reorder));
 
     vp6_coeff_order_table_init(s);
 }
diff --git a/libavcodec/vp6data.h b/libavcodec/vp6data.h
index 539e19a627..be6e86919d 100644
--- a/libavcodec/vp6data.h
+++ b/libavcodec/vp6data.h
@@ -51,6 +51,17 @@ static const uint8_t vp6_def_coeff_reorder[] = {
     14, 14, 15, 15, 15, 15, 15, 15,
 };
 
+static const uint8_t vp6_il_coeff_reorder[] = {
+     0,  1,  0,  1,  1,  2,  5,  3,
+     2,  2,  2,  2,  4,  7,  8, 10,
+     9,  7,  5,  4,  2,  3,  5,  6,
+     8,  9, 11, 12, 13, 12, 11, 10,
+     9,  7,  5,  4,  6,  7,  9, 11,
+    12, 12, 13, 13, 14, 12, 11,  9,
+     7,  9, 11, 12, 14, 14, 14, 15,
+    13, 11, 13, 15, 15, 15, 15, 15,
+};
+
 static const uint8_t vp6_def_runv_coeff_model[2][14] = {
     { 198, 197, 196, 146, 198, 204, 169, 142, 130, 136, 149, 149, 191, 249 },
     { 135, 201, 181, 154,  98, 117, 132, 126, 146, 169, 184, 240, 246, 254 },
-- 
2.45.2

-- Peter
(A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 195 bytes
Desc: not available
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20241009/e639b666/attachment.sig>


More information about the ffmpeg-devel mailing list