diff --git a/libavcodec/vc1.c b/libavcodec/vc1.c index 77e71db778..b058a38c40 100644 --- a/libavcodec/vc1.c +++ b/libavcodec/vc1.c @@ -605,9 +605,6 @@ int vc1_parse_frame_header(VC1Context *v, GetBitContext* gb) { int pqindex, lowquant, status; - if(v->res_sprite) { - skip_bits(gb, 2); //not yet deciphered - } if(v->finterpflag) v->interpfrm = get_bits1(gb); skip_bits(gb, 2); //framecnt unused v->rangeredfrm = 0; diff --git a/libavcodec/vc1.h b/libavcodec/vc1.h index 00dcfbf1d2..d0c0cccfb0 100644 --- a/libavcodec/vc1.h +++ b/libavcodec/vc1.h @@ -306,6 +306,12 @@ typedef struct VC1Context{ uint8_t range_mapuv; //@} + /** Frame decoding info for sprite modes */ + //@{ + int new_sprite; + int two_sprites; + //@} + int p_frame_skipped; int bi_type; int x8_type; diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index cde284dac2..8200cde0ff 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -3097,6 +3097,116 @@ static void vc1_decode_blocks(VC1Context *v, int mby_start, int mby_end) } } +static inline float get_float_val(GetBitContext* gb) +{ + return (float)get_bits_long(gb, 30) / (1<<15) - (1<<14); +} + +static void vc1_sprite_parse_transform(VC1Context *v, GetBitContext* gb, float c[7]) +{ + c[1] = c[3] = 0.0f; + + switch (get_bits(gb, 2)) { + case 0: + c[0] = 1.0f; + c[2] = get_float_val(gb); + c[4] = 1.0f; + break; + case 1: + c[0] = c[4] = get_float_val(gb); + c[2] = get_float_val(gb); + break; + case 2: + c[0] = get_float_val(gb); + c[2] = get_float_val(gb); + c[4] = get_float_val(gb); + break; + case 3: + av_log_ask_for_sample(v->s.avctx, NULL); + c[0] = get_float_val(gb); + c[1] = get_float_val(gb); + c[2] = get_float_val(gb); + c[3] = get_float_val(gb); + c[4] = get_float_val(gb); + break; + } + c[5] = get_float_val(gb); + if (get_bits1(gb)) + c[6] = get_float_val(gb); + else + c[6] = 1.0f; +} + +static void vc1_parse_sprites(VC1Context *v, GetBitContext* gb) +{ + int effect_type, effect_flag, effect_pcount1, effect_pcount2, i; + float effect_params1[14], effect_params2[10]; + + float coefs[2][7]; + vc1_sprite_parse_transform(v, gb, coefs[0]); + av_log(v->s.avctx, AV_LOG_DEBUG, "S1:"); + for (i = 0; i < 7; i++) + av_log(v->s.avctx, AV_LOG_DEBUG, " %.3f", coefs[0][i]); + av_log(v->s.avctx, AV_LOG_DEBUG, "\n"); + + if (v->two_sprites) { + vc1_sprite_parse_transform(v, gb, coefs[1]); + av_log(v->s.avctx, AV_LOG_DEBUG, "S2:"); + for (i = 0; i < 7; i++) + av_log(v->s.avctx, AV_LOG_DEBUG, " %.3f", coefs[1][i]); + av_log(v->s.avctx, AV_LOG_DEBUG, "\n"); + } + skip_bits(gb, 2); + if (effect_type = get_bits_long(gb, 30)){ + switch (effect_pcount1 = get_bits(gb, 4)) { + case 2: + effect_params1[0] = get_float_val(gb); + effect_params1[1] = get_float_val(gb); + break; + case 7: + vc1_sprite_parse_transform(v, gb, effect_params1); + break; + case 14: + vc1_sprite_parse_transform(v, gb, effect_params1); + vc1_sprite_parse_transform(v, gb, &effect_params1[7]); + break; + default: + av_log_ask_for_sample(v->s.avctx, NULL); + return; + } + if (effect_type != 13 || effect_params1[0] != coefs[0][6]) { + // effect 13 is simple alpha blending and matches the opacity above + av_log(v->s.avctx, AV_LOG_DEBUG, "Effect: %d; params: ", effect_type); + for (i = 0; i < effect_pcount1; i++) + av_log(v->s.avctx, AV_LOG_DEBUG, " %.3f", effect_params1[i]); + av_log(v->s.avctx, AV_LOG_DEBUG, "\n"); + } + + effect_pcount2 = get_bits(gb, 16); + if (effect_pcount2 > 10) { + av_log(v->s.avctx, AV_LOG_ERROR, "Too many effect parameters\n"); + return; + } else if (effect_pcount2) { + i = 0; + av_log(v->s.avctx, AV_LOG_DEBUG, "Effect params 2: "); + while (i < effect_pcount2){ + effect_params2[i] = get_float_val(gb); + av_log(v->s.avctx, AV_LOG_DEBUG, " %.3f", effect_params2[i]); + i++; + } + av_log(v->s.avctx, AV_LOG_DEBUG, "\n"); + } + } + if (effect_flag = get_bits1(gb)) + av_log(v->s.avctx, AV_LOG_DEBUG, "Effect flag set\n"); + + if (get_bits_count(gb) >= gb->size_in_bits + + (v->s.avctx->codec_id == CODEC_ID_WMV3 ? 64 : 0)) + av_log(v->s.avctx, AV_LOG_ERROR, "Buffer overrun\n"); + if (get_bits_count(gb) < gb->size_in_bits - 8) + av_log(v->s.avctx, AV_LOG_WARNING, "Buffer not fully read\n"); +} + /** Initialize a VC1/WMV3 decoder * @todo TODO: Handle VC-1 IDUs (Transport level?) * @todo TODO: Decypher remaining bits in extra_data @@ -3160,7 +3270,7 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx) { av_log(avctx, AV_LOG_INFO, "Read %i bits in overflow\n", -count); } - } else { // VC1/WVC1 + } else { // VC1/WVC1/WVP2 const uint8_t *start = avctx->extradata; uint8_t *end = avctx->extradata + avctx->extradata_size; const uint8_t *next; @@ -3204,6 +3314,7 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "Incomplete extradata\n"); return -1; } + v->res_sprite = (avctx->codec_tag == MKTAG('W','V','P','2')); } avctx->profile = v->profile; if (v->profile == PROFILE_ADVANCED) @@ -3359,6 +3470,14 @@ static int vc1_decode_frame(AVCodecContext *avctx, init_get_bits(&s->gb, buf2, buf_size2*8); } else init_get_bits(&s->gb, buf, buf_size*8); + + if (v->res_sprite) { + v->new_sprite = !get_bits1(&s->gb); + v->two_sprites = get_bits1(&s->gb); + if (!v->new_sprite) + goto end; + } + // do parse frame header if(v->profile < PROFILE_ADVANCED) { if(vc1_parse_frame_header(v, &s->gb) == -1) { @@ -3370,8 +3489,8 @@ static int vc1_decode_frame(AVCodecContext *avctx, } } - if(v->res_sprite && (s->pict_type!=FF_I_TYPE)){ - goto err; + if (v->res_sprite && s->pict_type!=FF_I_TYPE) { + av_log(v->s.avctx, AV_LOG_WARNING, "Sprite decoder: expected I-frame\n"); } // for skipping the frame @@ -3455,6 +3574,8 @@ assert(s->current_picture.pict_type == s->pict_type); } end: + if (v->res_sprite) + vc1_parse_sprites(v, &s->gb); av_free(buf2); for (i = 0; i < n_slices; i++) av_free(slices[i].buf); diff --git a/libavcodec/version.h b/libavcodec/version.h index b60e264d7f..e40d4e5531 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -22,7 +22,7 @@ #define LIBAVCODEC_VERSION_MAJOR 52 #define LIBAVCODEC_VERSION_MINOR 117 -#define LIBAVCODEC_VERSION_MICRO 0 +#define LIBAVCODEC_VERSION_MICRO 1 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ diff --git a/libavformat/riff.c b/libavformat/riff.c index f490b47eb4..792c206678 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -232,6 +232,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { CODEC_ID_WMV3, MKTAG('W', 'M', 'V', 'P') }, { CODEC_ID_VC1, MKTAG('W', 'V', 'C', '1') }, { CODEC_ID_VC1, MKTAG('W', 'M', 'V', 'A') }, + { CODEC_ID_VC1, MKTAG('W', 'V', 'P', '2') }, { CODEC_ID_LOCO, MKTAG('L', 'O', 'C', 'O') }, { CODEC_ID_WNV1, MKTAG('W', 'N', 'V', '1') }, { CODEC_ID_AASC, MKTAG('A', 'A', 'S', 'C') },