avcodec/vp56: decode interlace content

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

Fixes ticket #5581.
This commit is contained in:
Peter Ross 2024-10-09 16:35:08 +11:00 committed by Paul B Mahol
parent 006d22e0af
commit 2a60e60f73
5 changed files with 55 additions and 10 deletions

View File

@ -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) if(vp56_rac_gets(c, 5) > 5)
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
vp56_rac_gets(c, 2); vp56_rac_gets(c, 2);
if (vpx_rac_get(c)) { s->interlaced = vp56_rac_gets(c, 1);
avpriv_report_missing_feature(s->avctx, "Interlacing");
return AVERROR_PATCHWELCOME;
}
rows = vp56_rac_gets(c, 8); /* number of stored macroblock rows */ rows = vp56_rac_gets(c, 8); /* number of stored macroblock rows */
cols = vp56_rac_gets(c, 8); /* number of stored macroblock cols */ cols = vp56_rac_gets(c, 8); /* number of stored macroblock cols */
if (!rows || !cols) { if (!rows || !cols) {

View File

@ -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) 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; int b, ab, b_max, plane, off;
AVFrame *frame_current, *frame_ref; AVFrame *frame_current, *frame_ref;
VP56Frame ref_frame = ff_vp56_reference_frame[mb_type]; 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]) if (mb_type != VP56_MB_INTRA && !frame_ref->data[0])
return; 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; ab = 6*is_alpha;
b_max = 6 - 2*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 x_off = b==1 || b==3 ? 8 : 0;
int y_off = b==2 || b==3 ? 8 : 0; int y_off = b==2 || b==3 ? 8 : 0;
plane = ff_vp56_b2p[b+ab]; 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); 16*col+x_off, 16*row+y_off);
vp56_idct_add(s, frame_current->data[plane] + s->block_offset[b], vp56_idct_add(s, frame_current->data[plane] + s->block_offset[b],
s->stride[plane], s->block_coeff[b], s->idct_selector[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[4][0] = 0;
s->block_coeff[5][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) 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; VP56mb mb_type;
int ret; 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) if (s->frames[VP56_FRAME_CURRENT]->flags & AV_FRAME_FLAG_KEY)
mb_type = VP56_MB_INTRA; mb_type = VP56_MB_INTRA;
else else
@ -686,6 +713,9 @@ static int ff_vp56_decode_mbs(AVCodecContext *avctx, void *data,
if (s->parse_coeff_models(s)) if (s->parse_coeff_models(s))
goto next; goto next;
if (s->interlaced)
s->il_prob = vp56_rac_gets(&s->c, 8);
memset(s->prev_dc, 0, sizeof(s->prev_dc)); memset(s->prev_dc, 0, sizeof(s->prev_dc));
s->prev_dc[1][VP56_FRAME_CURRENT] = 128; s->prev_dc[1][VP56_FRAME_CURRENT] = 128;
s->prev_dc[2][VP56_FRAME_CURRENT] = 128; s->prev_dc[2][VP56_FRAME_CURRENT] = 128;

View File

@ -151,6 +151,7 @@ struct vp56_context {
VP56Macroblock *macroblocks; VP56Macroblock *macroblocks;
DECLARE_ALIGNED(16, int16_t, block_coeff)[6][64]; DECLARE_ALIGNED(16, int16_t, block_coeff)[6][64];
int idct_selector[6]; int idct_selector[6];
const uint8_t *def_coeff_reorder;/* used in vp6 only */
/* motion vectors */ /* motion vectors */
VP56mv mv[6]; /* vectors for each block in MB */ VP56mv mv[6]; /* vectors for each block in MB */
@ -171,6 +172,11 @@ struct vp56_context {
int has_alpha; int has_alpha;
/* interlacing params */
int interlaced;
int il_prob;
int il_block;
/* upside-down flipping hints */ /* upside-down flipping hints */
int flip; /* are we flipping ? */ int flip; /* are we flipping ? */
int frbi; /* first row block index in MB */ int frbi; /* first row block index in MB */

View File

@ -68,10 +68,11 @@ static int vp6_parse_header(VP56Context *s, const uint8_t *buf, int buf_size)
if (sub_version > 8) if (sub_version > 8)
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
s->filter_header = buf[1] & 0x06; s->filter_header = buf[1] & 0x06;
if (buf[1] & 1) { s->interlaced = buf[1] & 1;
avpriv_report_missing_feature(s->avctx, "Interlacing"); if (s->interlaced)
return AVERROR_PATCHWELCOME; s->def_coeff_reorder = vp6_il_coeff_reorder;
} else
s->def_coeff_reorder = vp6_def_coeff_reorder;
if (separated_coeff || !s->filter_header) { if (separated_coeff || !s->filter_header) {
coeff_offset = AV_RB16(buf+2) - 2; coeff_offset = AV_RB16(buf+2) - 2;
buf += 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_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->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_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); vp6_coeff_order_table_init(s);
} }

View File

@ -51,6 +51,17 @@ static const uint8_t vp6_def_coeff_reorder[] = {
14, 14, 15, 15, 15, 15, 15, 15, 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] = { 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 }, { 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 }, { 135, 201, 181, 154, 98, 117, 132, 126, 146, 169, 184, 240, 246, 254 },