*/
#include "avcodec.h"
+#include "bytestream.h"
#include "vp56.h"
#include "vp56data.h"
static void vp56_add_predictors_dc(vp56_context_t *s, vp56_frame_t ref_frame)
{
int idx = s->scantable.permutated[0];
- int i;
+ int b;
- for (i=0; i<6; i++) {
- vp56_ref_dc_t *ab = &s->above_blocks[s->above_block_idx[i]];
- vp56_ref_dc_t *lb = &s->left_block[vp56_b6to4[i]];
+ for (b=0; b<6; b++) {
+ vp56_ref_dc_t *ab = &s->above_blocks[s->above_block_idx[b]];
+ vp56_ref_dc_t *lb = &s->left_block[vp56_b6to4[b]];
int count = 0;
int dc = 0;
+ int i;
if (ref_frame == lb->ref_frame) {
dc += lb->dc_coeff;
dc += ab->dc_coeff;
count++;
}
- if (s->avctx->codec->id == CODEC_ID_VP5) {
- if (count < 2 && ref_frame == ab[-1].ref_frame) {
- dc += ab[-1].dc_coeff;
- count++;
- }
- if (count < 2 && ref_frame == ab[1].ref_frame) {
- dc += ab[1].dc_coeff;
- count++;
- }
- }
+ if (s->avctx->codec->id == CODEC_ID_VP5)
+ for (i=0; i<2; i++)
+ if (count < 2 && ref_frame == ab[-1+2*i].ref_frame) {
+ dc += ab[-1+2*i].dc_coeff;
+ count++;
+ }
if (count == 0)
- dc = s->prev_dc[vp56_b2p[i]][ref_frame];
+ dc = s->prev_dc[vp56_b2p[b]][ref_frame];
else if (count == 2)
dc /= 2;
- s->block_coeff[i][idx] += dc;
- s->prev_dc[vp56_b2p[i]][ref_frame] = s->block_coeff[i][idx];
- ab->dc_coeff = s->block_coeff[i][idx];
+ s->block_coeff[b][idx] += dc;
+ s->prev_dc[vp56_b2p[b]][ref_frame] = s->block_coeff[b][idx];
+ ab->dc_coeff = s->block_coeff[b][idx];
ab->ref_frame = ref_frame;
- lb->dc_coeff = s->block_coeff[i][idx];
+ lb->dc_coeff = s->block_coeff[b][idx];
lb->ref_frame = ref_frame;
- s->block_coeff[i][idx] *= s->dequant_dc;
+ s->block_coeff[b][idx] *= s->dequant_dc;
}
}
}
}
-static void vp56_decode_mb(vp56_context_t *s, int row, int col)
+static void vp56_decode_mb(vp56_context_t *s, int row, int col, int is_alpha)
{
AVFrame *frame_current, *frame_ref;
vp56_mb_t mb_type;
vp56_frame_t ref_frame;
- int b, plan, off;
+ int b, ab, b_max, plane, off;
if (s->framep[VP56_FRAME_CURRENT]->key_frame)
mb_type = VP56_MB_INTRA;
frame_current = s->framep[VP56_FRAME_CURRENT];
frame_ref = s->framep[ref_frame];
+ ab = 6*is_alpha;
+ b_max = 6 - 2*is_alpha;
+
switch (mb_type) {
case VP56_MB_INTRA:
- for (b=0; b<6; b++) {
- plan = vp56_b2p[b];
- s->dsp.idct_put(frame_current->data[plan] + s->block_offset[b],
- s->stride[plan], s->block_coeff[b]);
+ for (b=0; b<b_max; b++) {
+ plane = vp56_b2p[b+ab];
+ s->dsp.idct_put(frame_current->data[plane] + s->block_offset[b],
+ s->stride[plane], s->block_coeff[b]);
}
break;
case VP56_MB_INTER_NOVEC_PF:
case VP56_MB_INTER_NOVEC_GF:
- for (b=0; b<6; b++) {
- plan = vp56_b2p[b];
+ for (b=0; b<b_max; b++) {
+ plane = vp56_b2p[b+ab];
off = s->block_offset[b];
- s->dsp.put_pixels_tab[1][0](frame_current->data[plan] + off,
- frame_ref->data[plan] + off,
- s->stride[plan], 8);
- s->dsp.idct_add(frame_current->data[plan] + off,
- s->stride[plan], s->block_coeff[b]);
+ s->dsp.put_pixels_tab[1][0](frame_current->data[plane] + off,
+ frame_ref->data[plane] + off,
+ s->stride[plane], 8);
+ s->dsp.idct_add(frame_current->data[plane] + off,
+ s->stride[plane], s->block_coeff[b]);
}
break;
case VP56_MB_INTER_4V:
case VP56_MB_INTER_V1_GF:
case VP56_MB_INTER_V2_GF:
- for (b=0; b<6; b++) {
+ 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;
- plan = vp56_b2p[b];
- vp56_mc(s, b, plan, frame_ref->data[plan], s->stride[plan],
+ plane = vp56_b2p[b+ab];
+ vp56_mc(s, b, plane, frame_ref->data[plane], s->stride[plane],
16*col+x_off, 16*row+y_off);
- s->dsp.idct_add(frame_current->data[plan] + s->block_offset[b],
- s->stride[plan], s->block_coeff[b]);
+ s->dsp.idct_add(frame_current->data[plane] + s->block_offset[b],
+ s->stride[plane], s->block_coeff[b]);
}
break;
}
int stride = s->framep[VP56_FRAME_CURRENT]->linesize[0];
int i;
- s->plane_width[0] = avctx->coded_width;
+ s->plane_width[0] = s->plane_width[3] = avctx->coded_width;
s->plane_width[1] = s->plane_width[2] = avctx->coded_width/2;
- s->plane_height[0] = avctx->coded_height;
+ s->plane_height[0] = s->plane_height[3] = avctx->coded_height;
s->plane_height[1] = s->plane_height[2] = avctx->coded_height/2;
- for (i=0; i<3; i++)
+ for (i=0; i<4; i++)
s->stride[i] = s->flip * s->framep[VP56_FRAME_CURRENT]->linesize[i];
s->mb_width = (avctx->coded_width +15) / 16;
{
vp56_context_t *s = avctx->priv_data;
AVFrame *const p = s->framep[VP56_FRAME_CURRENT];
- int mb_row, mb_col, mb_row_flip, mb_offset = 0;
- int block, y, uv, stride_y, stride_uv;
- int golden_frame = 0;
- int res;
+ int is_alpha, alpha_offset;
- s->modelp = &s->models;
+ if (s->has_alpha) {
+ alpha_offset = bytestream_get_be24(&buf);
+ buf_size -= 3;
+ }
- res = s->parse_header(s, buf, buf_size, &golden_frame);
- if (!res)
- return -1;
+ for (is_alpha=0; is_alpha < 1+s->has_alpha; is_alpha++) {
+ int mb_row, mb_col, mb_row_flip, mb_offset = 0;
+ int block, y, uv, stride_y, stride_uv;
+ int golden_frame = 0;
+ int res;
- p->reference = 1;
- if (avctx->get_buffer(avctx, p) < 0) {
- av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
- return -1;
- }
+ s->modelp = &s->models[is_alpha];
- if (res == 2)
- if (vp56_size_changed(avctx)) {
- avctx->release_buffer(avctx, p);
+ res = s->parse_header(s, buf, buf_size, &golden_frame);
+ if (!res)
return -1;
- }
- if (p->key_frame) {
- p->pict_type = FF_I_TYPE;
- s->default_models_init(s);
- for (block=0; block<s->mb_height*s->mb_width; block++)
- s->macroblocks[block].type = VP56_MB_INTRA;
- } else {
- p->pict_type = FF_P_TYPE;
- vp56_parse_mb_type_models(s);
- s->parse_vector_models(s);
- s->mb_type = VP56_MB_INTER_NOVEC_PF;
- }
+ if (!is_alpha) {
+ p->reference = 1;
+ if (avctx->get_buffer(avctx, p) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return -1;
+ }
- s->parse_coeff_models(s);
+ if (res == 2)
+ if (vp56_size_changed(avctx)) {
+ avctx->release_buffer(avctx, p);
+ return -1;
+ }
+ }
- 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;
+ if (p->key_frame) {
+ p->pict_type = FF_I_TYPE;
+ s->default_models_init(s);
+ for (block=0; block<s->mb_height*s->mb_width; block++)
+ s->macroblocks[block].type = VP56_MB_INTRA;
+ } else {
+ p->pict_type = FF_P_TYPE;
+ vp56_parse_mb_type_models(s);
+ s->parse_vector_models(s);
+ s->mb_type = VP56_MB_INTER_NOVEC_PF;
+ }
- for (block=0; block < 4*s->mb_width+6; block++) {
- s->above_blocks[block].ref_frame = -1;
- s->above_blocks[block].dc_coeff = 0;
- s->above_blocks[block].not_null_dc = 0;
- }
- s->above_blocks[2*s->mb_width + 2].ref_frame = 0;
- s->above_blocks[3*s->mb_width + 4].ref_frame = 0;
+ s->parse_coeff_models(s);
- stride_y = p->linesize[0];
- stride_uv = p->linesize[1];
+ 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;
- if (s->flip < 0)
- mb_offset = 7;
+ for (block=0; block < 4*s->mb_width+6; block++) {
+ s->above_blocks[block].ref_frame = -1;
+ s->above_blocks[block].dc_coeff = 0;
+ s->above_blocks[block].not_null_dc = 0;
+ }
+ s->above_blocks[2*s->mb_width + 2].ref_frame = 0;
+ s->above_blocks[3*s->mb_width + 4].ref_frame = 0;
- /* main macroblocks loop */
- for (mb_row=0; mb_row<s->mb_height; mb_row++) {
- if (s->flip < 0)
- mb_row_flip = s->mb_height - mb_row - 1;
- else
- mb_row_flip = mb_row;
+ stride_y = p->linesize[0];
+ stride_uv = p->linesize[1];
- for (block=0; block<4; block++) {
- s->left_block[block].ref_frame = -1;
- s->left_block[block].dc_coeff = 0;
- s->left_block[block].not_null_dc = 0;
- memset(s->coeff_ctx[block], 0, 64*sizeof(s->coeff_ctx[block][0]));
- }
- memset(s->coeff_ctx_last, 24, sizeof(s->coeff_ctx_last));
-
- s->above_block_idx[0] = 1;
- s->above_block_idx[1] = 2;
- s->above_block_idx[2] = 1;
- s->above_block_idx[3] = 2;
- s->above_block_idx[4] = 2*s->mb_width + 2 + 1;
- s->above_block_idx[5] = 3*s->mb_width + 4 + 1;
-
- s->block_offset[s->frbi] = (mb_row_flip*16 + mb_offset) * stride_y;
- s->block_offset[s->srbi] = s->block_offset[s->frbi] + 8*stride_y;
- s->block_offset[1] = s->block_offset[0] + 8;
- s->block_offset[3] = s->block_offset[2] + 8;
- s->block_offset[4] = (mb_row_flip*8 + mb_offset) * stride_uv;
- s->block_offset[5] = s->block_offset[4];
-
- for (mb_col=0; mb_col<s->mb_width; mb_col++) {
- vp56_decode_mb(s, mb_row, mb_col);
-
- for (y=0; y<4; y++) {
- s->above_block_idx[y] += 2;
- s->block_offset[y] += 16;
+ if (s->flip < 0)
+ mb_offset = 7;
+
+ /* main macroblocks loop */
+ for (mb_row=0; mb_row<s->mb_height; mb_row++) {
+ if (s->flip < 0)
+ mb_row_flip = s->mb_height - mb_row - 1;
+ else
+ mb_row_flip = mb_row;
+
+ for (block=0; block<4; block++) {
+ s->left_block[block].ref_frame = -1;
+ s->left_block[block].dc_coeff = 0;
+ s->left_block[block].not_null_dc = 0;
}
+ memset(s->coeff_ctx, 0, sizeof(s->coeff_ctx));
+ memset(s->coeff_ctx_last, 24, sizeof(s->coeff_ctx_last));
+
+ s->above_block_idx[0] = 1;
+ s->above_block_idx[1] = 2;
+ s->above_block_idx[2] = 1;
+ s->above_block_idx[3] = 2;
+ s->above_block_idx[4] = 2*s->mb_width + 2 + 1;
+ s->above_block_idx[5] = 3*s->mb_width + 4 + 1;
+
+ s->block_offset[s->frbi] = (mb_row_flip*16 + mb_offset) * stride_y;
+ s->block_offset[s->srbi] = s->block_offset[s->frbi] + 8*stride_y;
+ s->block_offset[1] = s->block_offset[0] + 8;
+ s->block_offset[3] = s->block_offset[2] + 8;
+ s->block_offset[4] = (mb_row_flip*8 + mb_offset) * stride_uv;
+ s->block_offset[5] = s->block_offset[4];
+
+ for (mb_col=0; mb_col<s->mb_width; mb_col++) {
+ vp56_decode_mb(s, mb_row, mb_col, is_alpha);
+
+ for (y=0; y<4; y++) {
+ s->above_block_idx[y] += 2;
+ s->block_offset[y] += 16;
+ }
- for (uv=4; uv<6; uv++) {
- s->above_block_idx[uv] += 1;
- s->block_offset[uv] += 8;
+ for (uv=4; uv<6; uv++) {
+ s->above_block_idx[uv] += 1;
+ s->block_offset[uv] += 8;
+ }
}
}
+
+ if (p->key_frame || golden_frame) {
+ if (s->framep[VP56_FRAME_GOLDEN]->data[0] &&
+ s->framep[VP56_FRAME_GOLDEN] != s->framep[VP56_FRAME_GOLDEN2])
+ avctx->release_buffer(avctx, s->framep[VP56_FRAME_GOLDEN]);
+ s->framep[VP56_FRAME_GOLDEN] = p;
+ }
+
+ if (s->has_alpha) {
+ FFSWAP(AVFrame *, s->framep[VP56_FRAME_GOLDEN],
+ s->framep[VP56_FRAME_GOLDEN2]);
+ buf += alpha_offset;
+ buf_size -= alpha_offset;
+ }
}
- if (s->framep[VP56_FRAME_PREVIOUS] == s->framep[VP56_FRAME_GOLDEN])
- FFSWAP(AVFrame *, s->framep[VP56_FRAME_PREVIOUS],
- s->framep[VP56_FRAME_UNUSED]);
- else if (s->framep[VP56_FRAME_PREVIOUS]->data[0])
+ if (s->framep[VP56_FRAME_PREVIOUS] == s->framep[VP56_FRAME_GOLDEN] ||
+ s->framep[VP56_FRAME_PREVIOUS] == s->framep[VP56_FRAME_GOLDEN2]) {
+ if (s->framep[VP56_FRAME_UNUSED] != s->framep[VP56_FRAME_GOLDEN] &&
+ s->framep[VP56_FRAME_UNUSED] != s->framep[VP56_FRAME_GOLDEN2])
+ FFSWAP(AVFrame *, s->framep[VP56_FRAME_PREVIOUS],
+ s->framep[VP56_FRAME_UNUSED]);
+ else
+ FFSWAP(AVFrame *, s->framep[VP56_FRAME_PREVIOUS],
+ s->framep[VP56_FRAME_UNUSED2]);
+ } else if (s->framep[VP56_FRAME_PREVIOUS]->data[0])
avctx->release_buffer(avctx, s->framep[VP56_FRAME_PREVIOUS]);
- if (p->key_frame || golden_frame) {
- if (s->framep[VP56_FRAME_GOLDEN]->data[0])
- avctx->release_buffer(avctx, s->framep[VP56_FRAME_GOLDEN]);
- s->framep[VP56_FRAME_GOLDEN] = p;
- }
FFSWAP(AVFrame *, s->framep[VP56_FRAME_CURRENT],
s->framep[VP56_FRAME_PREVIOUS]);
return buf_size;
}
-void vp56_init(AVCodecContext *avctx, int flip)
+void vp56_init(AVCodecContext *avctx, int flip, int has_alpha)
{
vp56_context_t *s = avctx->priv_data;
int i;
s->avctx = avctx;
- avctx->pix_fmt = PIX_FMT_YUV420P;
+ avctx->pix_fmt = has_alpha ? PIX_FMT_YUVA420P : PIX_FMT_YUV420P;
if (avctx->idct_algo == FF_IDCT_AUTO)
avctx->idct_algo = FF_IDCT_VP3;
avcodec_set_dimensions(avctx, 0, 0);
- for (i=0; i<3; i++)
+ for (i=0; i<4; i++)
s->framep[i] = &s->frames[i];
s->framep[VP56_FRAME_UNUSED] = s->framep[VP56_FRAME_GOLDEN];
+ s->framep[VP56_FRAME_UNUSED2] = s->framep[VP56_FRAME_GOLDEN2];
s->edge_emu_buffer_alloc = NULL;
s->above_blocks = NULL;
s->filter = NULL;
+ s->has_alpha = has_alpha;
if (flip) {
s->flip = -1;
s->frbi = 2;
av_free(s->edge_emu_buffer_alloc);
if (s->framep[VP56_FRAME_GOLDEN]->data[0])
avctx->release_buffer(avctx, s->framep[VP56_FRAME_GOLDEN]);
+ if (s->framep[VP56_FRAME_GOLDEN2]->data[0])
+ avctx->release_buffer(avctx, s->framep[VP56_FRAME_GOLDEN2]);
if (s->framep[VP56_FRAME_PREVIOUS]->data[0])
avctx->release_buffer(avctx, s->framep[VP56_FRAME_PREVIOUS]);
return 0;