diff options
-rw-r--r-- | libavcodec/allcodecs.c | 1 | ||||
-rw-r--r-- | libavcodec/avcodec.h | 1 | ||||
-rw-r--r-- | libavcodec/vp5.c | 2 | ||||
-rw-r--r-- | libavcodec/vp56.c | 78 | ||||
-rw-r--r-- | libavcodec/vp56.h | 16 | ||||
-rw-r--r-- | libavcodec/vp56data.c | 2 | ||||
-rw-r--r-- | libavcodec/vp56data.h | 4 | ||||
-rw-r--r-- | libavcodec/vp6.c | 16 |
8 files changed, 87 insertions, 33 deletions
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 742f46b87d..6c6ad3be09 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -156,6 +156,7 @@ void avcodec_register_all(void) REGISTER_DECODER (VP3, vp3); REGISTER_DECODER (VP5, vp5); REGISTER_DECODER (VP6, vp6); + REGISTER_DECODER (VP6A, vp6a); REGISTER_DECODER (VP6F, vp6f); REGISTER_DECODER (VQA, vqa); REGISTER_ENCDEC (WMV1, wmv1); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 1ab1992ad7..a8b447e27b 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -166,6 +166,7 @@ enum CodecID { CODEC_ID_BETHSOFTVID, CODEC_ID_PTX, CODEC_ID_TXD, + CODEC_ID_VP6A, /* various PCM "codecs" */ CODEC_ID_PCM_S16LE= 0x10000, diff --git a/libavcodec/vp5.c b/libavcodec/vp5.c index 5441350069..8939f02c34 100644 --- a/libavcodec/vp5.c +++ b/libavcodec/vp5.c @@ -270,7 +270,7 @@ static int vp5_decode_init(AVCodecContext *avctx) { vp56_context_t *s = avctx->priv_data; - vp56_init(avctx, 1); + vp56_init(avctx, 1, 0); s->vp56_coord_div = vp5_coord_div; s->parse_vector_adjustment = vp5_parse_vector_adjustment; s->adjust = vp5_adjust; diff --git a/libavcodec/vp56.c b/libavcodec/vp56.c index 26c905f183..828c466c3c 100644 --- a/libavcodec/vp56.c +++ b/libavcodec/vp56.c @@ -22,6 +22,7 @@ */ #include "avcodec.h" +#include "bytestream.h" #include "vp56.h" #include "vp56data.h" @@ -394,12 +395,12 @@ static void vp56_mc(vp56_context_t *s, int b, int plane, uint8_t *src, } } -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, plan, off; if (s->framep[VP56_FRAME_CURRENT]->key_frame) mb_type = VP56_MB_INTRA; @@ -416,10 +417,13 @@ static void vp56_decode_mb(vp56_context_t *s, int row, int col) 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]; + for (b=0; b<b_max; b++) { + plan = vp56_b2p[b+ab]; s->dsp.idct_put(frame_current->data[plan] + s->block_offset[b], s->stride[plan], s->block_coeff[b]); } @@ -427,8 +431,8 @@ static void vp56_decode_mb(vp56_context_t *s, int row, int col) 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++) { + plan = 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, @@ -445,10 +449,10 @@ static void vp56_decode_mb(vp56_context_t *s, int row, int col) 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]; + plan = vp56_b2p[b+ab]; vp56_mc(s, b, plan, frame_ref->data[plan], s->stride[plan], 16*col+x_off, 16*row+y_off); s->dsp.idct_add(frame_current->data[plan] + s->block_offset[b], @@ -464,12 +468,12 @@ static int vp56_size_changed(AVCodecContext *avctx) 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; @@ -498,17 +502,26 @@ int vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size, { vp56_context_t *s = avctx->priv_data; AVFrame *const p = s->framep[VP56_FRAME_CURRENT]; + int is_alpha, alpha_offset; + + if (s->has_alpha) { + alpha_offset = bytestream_get_be24(&buf); + buf_size -= 3; + } + + 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; - s->modelp = &s->models; + s->modelp = &s->models[is_alpha]; res = s->parse_header(s, buf, buf_size, &golden_frame); if (!res) return -1; + if (!is_alpha) { p->reference = 1; if (avctx->get_buffer(avctx, p) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); @@ -520,6 +533,7 @@ int vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size, avctx->release_buffer(avctx, p); return -1; } + } if (p->key_frame) { p->pict_type = FF_I_TYPE; @@ -583,7 +597,7 @@ int vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size, 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); + vp56_decode_mb(s, mb_row, mb_col, is_alpha); for (y=0; y<4; y++) { s->above_block_idx[y] += 2; @@ -597,16 +611,32 @@ int vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size, } } - 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]) - avctx->release_buffer(avctx, s->framep[VP56_FRAME_PREVIOUS]); if (p->key_frame || golden_frame) { - if (s->framep[VP56_FRAME_GOLDEN]->data[0]) + 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] || + 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]); FFSWAP(AVFrame *, s->framep[VP56_FRAME_CURRENT], s->framep[VP56_FRAME_PREVIOUS]); @@ -616,13 +646,13 @@ int vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size, 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; @@ -631,9 +661,10 @@ void vp56_init(AVCodecContext *avctx, int flip) 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; @@ -643,6 +674,7 @@ void vp56_init(AVCodecContext *avctx, int flip) s->filter = NULL; + s->has_alpha = has_alpha; if (flip) { s->flip = -1; s->frbi = 2; @@ -663,6 +695,8 @@ int vp56_free(AVCodecContext *avctx) 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; diff --git a/libavcodec/vp56.h b/libavcodec/vp56.h index adae42b35f..c2a6ef8ca6 100644 --- a/libavcodec/vp56.h +++ b/libavcodec/vp56.h @@ -90,8 +90,8 @@ struct vp56_context { AVCodecContext *avctx; DSPContext dsp; ScanTable scantable; - AVFrame frames[3]; - AVFrame *framep[4]; + AVFrame frames[4]; + AVFrame *framep[6]; uint8_t *edge_emu_buffer_alloc; uint8_t *edge_emu_buffer; vp56_range_coder_t c; @@ -100,8 +100,8 @@ struct vp56_context { int sub_version; /* frame info */ - int plane_width[3]; - int plane_height[3]; + int plane_width[4]; + int plane_height[4]; int mb_width; /* number of horizontal MB */ int mb_height; /* number of vertical MB */ int block_offset[6]; @@ -137,11 +137,13 @@ struct vp56_context { uint8_t coeff_ctx[4][64]; /* used in vp5 only */ uint8_t coeff_ctx_last[4]; /* used in vp5 only */ + int has_alpha; + /* upside-down flipping hints */ int flip; /* are we flipping ? */ int frbi; /* first row block index in MB */ int srbi; /* second row block index in MB */ - int stride[3]; /* stride for each plan */ + int stride[4]; /* stride for each plan */ const uint8_t *vp56_coord_div; vp56_parse_vector_adjustment_t parse_vector_adjustment; @@ -154,11 +156,11 @@ struct vp56_context { vp56_parse_header_t parse_header; vp56_model_t *modelp; - vp56_model_t models; + vp56_model_t models[2]; }; -void vp56_init(AVCodecContext *avctx, int flip); +void vp56_init(AVCodecContext *avctx, int flip, int has_alpha); int vp56_free(AVCodecContext *avctx); void vp56_init_dequant(vp56_context_t *s, int quantizer); int vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size, diff --git a/libavcodec/vp56data.c b/libavcodec/vp56data.c index 3510eac586..8b4a03aeb9 100644 --- a/libavcodec/vp56data.c +++ b/libavcodec/vp56data.c @@ -23,7 +23,7 @@ #include "vp56data.h" -const uint8_t vp56_b2p[] = { 0, 0, 0, 0, 1, 2 }; +const uint8_t vp56_b2p[] = { 0, 0, 0, 0, 1, 2, 3, 3, 3, 3 }; const uint8_t vp56_b6to4[] = { 0, 0, 1, 1, 2, 3 }; const uint8_t vp56_coeff_parse_table[6][11] = { diff --git a/libavcodec/vp56data.h b/libavcodec/vp56data.h index 4fcdcc18f8..624b7bf4ea 100644 --- a/libavcodec/vp56data.h +++ b/libavcodec/vp56data.h @@ -30,7 +30,9 @@ typedef enum { VP56_FRAME_CURRENT = 0, VP56_FRAME_PREVIOUS = 1, VP56_FRAME_GOLDEN = 2, - VP56_FRAME_UNUSED = 3, + VP56_FRAME_GOLDEN2 = 3, + VP56_FRAME_UNUSED = 4, + VP56_FRAME_UNUSED2 = 5, } vp56_frame_t; typedef enum { diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c index 5c4b935ae5..ffd95f0cad 100644 --- a/libavcodec/vp6.c +++ b/libavcodec/vp6.c @@ -494,7 +494,8 @@ static int vp6_decode_init(AVCodecContext *avctx) { vp56_context_t *s = avctx->priv_data; - vp56_init(avctx, avctx->codec->id == CODEC_ID_VP6); + vp56_init(avctx, avctx->codec->id == CODEC_ID_VP6, + avctx->codec->id == CODEC_ID_VP6A); s->vp56_coord_div = vp6_coord_div; s->parse_vector_adjustment = vp6_parse_vector_adjustment; s->adjust = vp6_adjust; @@ -532,3 +533,16 @@ AVCodec vp6f_decoder = { vp56_decode_frame, CODEC_CAP_DR1, }; + +/* flash version, not flipped upside-down, with alpha channel */ +AVCodec vp6a_decoder = { + "vp6a", + CODEC_TYPE_VIDEO, + CODEC_ID_VP6A, + sizeof(vp56_context_t), + vp6_decode_init, + NULL, + vp56_free, + vp56_decode_frame, + CODEC_CAP_DR1, +}; |