diff options
author | Peter Ross <pross@xvid.org> | 2024-10-31 17:49:48 +1100 |
---|---|---|
committer | Peter Ross <pross@xvid.org> | 2024-10-31 17:49:48 +1100 |
commit | 492a3b4b895ceac27c3ed0239e9e40940479998a (patch) | |
tree | 1207c34787ac27d0bc0ef85123760a4ae083c73b | |
parent | 44a0a0c050461abfc10de722c7e67534751ba760 (diff) | |
download | ffmpeg-492a3b4b895ceac27c3ed0239e9e40940479998a.tar.gz |
avcodec/vp56: decode interlace content
Modification of patch submitted by Aurelien Jacobs (November 2007).
Fixes ticket #5581 and #5582.
-rw-r--r-- | libavcodec/vp5.c | 5 | ||||
-rw-r--r-- | libavcodec/vp56.c | 54 | ||||
-rw-r--r-- | libavcodec/vp56.h | 6 | ||||
-rw-r--r-- | libavcodec/vp6.c | 11 | ||||
-rw-r--r-- | libavcodec/vp6data.h | 11 |
5 files changed, 72 insertions, 15 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..4f2381f64a 100644 --- a/libavcodec/vp56.c +++ b/libavcodec/vp56.c @@ -338,7 +338,7 @@ static void vp56_deblock_filter(VP56Context *s, uint8_t *yuv, } static void vp56_mc(VP56Context *s, int b, int plane, uint8_t *src, - ptrdiff_t stride, int x, int y) + ptrdiff_t stride, int x, int y, ptrdiff_t ref_stride) { uint8_t *dst = s->frames[VP56_FRAME_CURRENT]->data[plane] + s->block_offset[b]; uint8_t *src_block; @@ -364,7 +364,17 @@ static void vp56_mc(VP56Context *s, int b, int plane, uint8_t *src, x += dx - 2; y += dy - 2; - if (x<0 || x+12>=s->plane_width[plane] || + if (s->interlaced && s->il_block) { + /* extract 12*(4+16+4) block from frame (containing both fields), then treat src_block as specific field */ + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, + src + s->block_offset[b] + (dy-4)*ref_stride + (dx-2), + ref_stride, ref_stride, + 12, 24, x, y - 2, + s->plane_width[plane], + s->plane_height[plane]); + src_block = s->edge_emu_buffer; + src_offset = 2 + 4*ref_stride; + } else if (x<0 || x+12>=s->plane_width[plane] || y<0 || y+12>=s->plane_height[plane]) { s->vdsp.emulated_edge_mc(s->edge_emu_buffer, src + s->block_offset[b] + (dy-2)*stride + (dx-2), @@ -431,6 +441,7 @@ static av_always_inline void vp56_render_mb(VP56Context *s, int row, int col, in int b, ab, b_max, plane, off; AVFrame *frame_current, *frame_ref; VP56Frame ref_frame = ff_vp56_reference_frame[mb_type]; + ptrdiff_t ref_stride[4]; vp56_add_predictors_dc(s, ref_frame); @@ -439,6 +450,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; @@ -473,10 +491,10 @@ static av_always_inline void vp56_render_mb(VP56Context *s, int row, int col, in case VP56_MB_INTER_V2_GF: for (b=0; b<b_max; b++) { int x_off = b==1 || b==3 ? 8 : 0; - int y_off = b==2 || b==3 ? 8 : 0; + int y_off = b==2 || b==3 ? (s->interlaced && s->il_block ? 1 : 8) : 0; plane = ff_vp56_b2p[b+ab]; vp56_mc(s, b, plane, frame_ref->data[plane], s->stride[plane], - 16*col+x_off, 16*row+y_off); + 16*col+x_off, 16*row+y_off, ref_stride[plane]); 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 +505,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 +518,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 @@ -552,12 +589,12 @@ static int vp56_size_changed(VP56Context *s) av_reallocp_array(&s->macroblocks, s->mb_width*s->mb_height, sizeof(*s->macroblocks)); av_free(s->edge_emu_buffer_alloc); - s->edge_emu_buffer_alloc = av_malloc(16*stride); + s->edge_emu_buffer_alloc = av_malloc(16*stride*2); s->edge_emu_buffer = s->edge_emu_buffer_alloc; if (!s->above_blocks || !s->macroblocks || !s->edge_emu_buffer_alloc) return AVERROR(ENOMEM); if (s->flip < 0) - s->edge_emu_buffer += 15 * stride; + s->edge_emu_buffer += 15 * stride * 2; if (s->alpha_context) return vp56_size_changed(s->alpha_context); @@ -686,6 +723,11 @@ static int ff_vp56_decode_mbs(AVCodecContext *avctx, void *data, if (s->parse_coeff_models(s)) goto next; + if (s->interlaced) { + s->frames[VP56_FRAME_CURRENT]->flags |= AV_FRAME_FLAG_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 }, |