mirror of
https://github.com/xenia-project/FFmpeg.git
synced 2024-11-27 21:40:34 +00:00
Parse sprite data for WMVP and WVP2, and decode sprites for the latter
Signed-off-by: Anton Khirnov <anton@khirnov.net>
This commit is contained in:
parent
70ff55733d
commit
768c525114
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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, \
|
||||
|
@ -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') },
|
||||
|
Loading…
Reference in New Issue
Block a user