|
@@ -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;
|