On Fri, Apr 08, 2011 at 07:07:30PM +0200, Alberto Delmás wrote:
> 

> From fbaf5be431d60dd6e52b3da9fb0e9f42864629e6 Mon Sep 17 00:00:00 2001
> From: Alberto Delmas <[email protected]>
> Date: Fri, 8 Apr 2011 18:49:40 +0200
> Subject: [PATCH] Parse sprite data for WMVP and WVP2, and decode sprites for 
> the latter
> 
> ---
>  libavcodec/vc1.c     |    3 -
>  libavcodec/vc1.h     |    6 ++
>  libavcodec/vc1dec.c  |  126 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  libavcodec/version.h |    2 +-
>  libavformat/riff.c   |    1 +
>  5 files changed, 131 insertions(+), 7 deletions(-)
> 
[...]
> diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c
> index cde284d..551d2d6 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]; // scale_1, unused?, off_1, unused?, scale_2, off_2, 
> opacity

please remove this comment

> +    vc1_sprite_parse_transform(v, gb, coefs[0]);
> +    av_log(v->s.avctx, AV_LOG_INFO, "S1:");
> +    for (i = 0; i < 7; i++)
> +        av_log(v->s.avctx, AV_LOG_INFO, " %.3f", coefs[0][i]);
> +    av_log(v->s.avctx, AV_LOG_INFO, "\n");
> +
> +    if (v->two_sprites){

please use either "if (x) {" or "if(x){" (the former is better) everywhere,
now it's weird

> +        vc1_sprite_parse_transform(v, gb, coefs[1]);
> +        av_log(v->s.avctx, AV_LOG_INFO, "S2:");
> +        for (i = 0; i < 7; i++)
> +            av_log(v->s.avctx, AV_LOG_INFO, " %.3f", coefs[1][i]);
> +        av_log(v->s.avctx, AV_LOG_INFO, "\n");
> +    }

please use AV_LOG_DEBUG as level here and below for all transform information

> +    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_INFO, "Effect: %d; params: ", 
> effect_type);
> +            for (i = 0; i < effect_pcount1; i++)
> +                av_log(v->s.avctx, AV_LOG_INFO, " %.3f", effect_params1[i]);
> +            av_log(v->s.avctx, AV_LOG_INFO, "\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_INFO, "Effect params 2: ");
> +            while (i < effect_pcount2){
> +                effect_params2[i] = get_float_val(gb);
> +                av_log(v->s.avctx, AV_LOG_INFO, " %.3f", effect_params2[i]);
> +                i++;
> +            }
> +            av_log(v->s.avctx, AV_LOG_INFO, "\n");
> +        }
> +    }
> +    if (effect_flag = get_bits1(gb))
> +        av_log(v->s.avctx, AV_LOG_INFO, "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,13 @@ 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;

I'd put "goto end;" on the next line

> +    }
> +
>      // do parse frame header
>      if(v->profile < PROFILE_ADVANCED) {
>          if(vc1_parse_frame_header(v, &s->gb) == -1) {
> @@ -3370,8 +3488,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 +3573,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);
[...]

In general - very good work, thanks.
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to