[FFmpeg-devel] [PATCH] Unfinished GSoC qual task (16bit VQA Video Decoder)

Michael Niedermayer michaelni
Tue May 5 00:36:12 CEST 2009


On Sat, May 02, 2009 at 01:06:24AM +0200, Adam Iglewski wrote:
> Michael Niedermayer pisze:
> [...]
>>> I would be grateful for hints how to resolve problem with
>>> decoding stereo audio (also described in my previous email).
>> there are 3 options (in no particular order)
>> A. extradata (this requires that there really is a global header in the
>>    file for audio)
>> B. codec_tag (this requres that there really is a codec tag for the
>>    audio)
>> C. a seperate codec_id
>
> I think option C is the simplest. It requires only small changes
> and adds almost no new code to FFmpeg:
>
> --- ffmpeg/libavcodec/adpcm.c	2009-04-29 23:54:38.000000000 +0200
> +++ ffmpeg_work/libavcodec/adpcm.c	2009-05-02 00:30:17.000000000 +0200
> @@ -1005,6 +1005,7 @@ static int adpcm_decode_frame(AVCodecCon
>          if (cs->step_index < 0) cs->step_index = 0;
>          if (cs->step_index > 88) cs->step_index = 88;
>
> +    case CODEC_ID_ADPCM_IMA_WS_V3:
>          m= (buf_size - (src - buf))>>st;
>          for(i=0; i<m; i++) {
>              *samples++ = adpcm_ima_expand_nibble(&c->status[0], src[i] & 
> 0x0F, 4);
>
> and
>
> --- ffmpeg/libavformat/westwood.c	2009-04-20 18:35:42.000000000 +0200
> +++ ffmpeg_work/libavformat/westwood.c	2009-05-02 00:28:54.000000000 +0200
>
> @@ -254,8 +258,10 @@ static int wsvqa_read_header(AVFormatCon
>          st->codec->codec_type = CODEC_TYPE_AUDIO;
>          if (AV_RL16(&header[0]) == 1)
>              st->codec->codec_id = CODEC_ID_WESTWOOD_SND1;
> -        else
> +        else if(AV_RL16(&header[14]))
>              st->codec->codec_id = CODEC_ID_ADPCM_IMA_WS;
> +        else
> +            st->codec->codec_id = CODEC_ID_ADPCM_IMA_WS_V3;
>
> plus of course adding codec_id to avcodec.h etc.
> Is this option acceptable?

yes


[...]
>> [...]
>>> @@ -561,6 +698,20 @@ static void vqa_decode_chunk(VqaContext              
>>> s->partial_countdown = s->partial_count;
>>>          }
>>>      }
>>> +
>>> +    if(vptr_chunk != -1) {
>>> +        chunk_size = AV_RB32(&s->buf[vptr_chunk + 4]);
>> validity check missing
>>> +        vptr_chunk += CHUNK_PREAMBLE_SIZE;
>>> +        vqa_decode_hc_video_chunk(s,&s->buf[vptr_chunk],chunk_size);
>>> +    }
>>> +
>>> +    if(vprz_chunk != -1) {
>>> +        chunk_size = AV_RB32(&s->buf[vprz_chunk + 4]);
>> same
>> also the code likely can be factorized
>
> By validity check you mean checking that AV_RB32 is not
> reading outside s->buf or checking if chunk_size isn't
> bigger that s->size ? I'm asking because there is a lot
> of similar code in this function/file and there are
> no checks like this.

all things that could segfault should be checked to avoid possible
segfaults. The exception would just be code where such checks would
cause a noticeable slowdown.


>
> As for refactoring this is part of the function that you
> wanted to be rewritten to process chunks as needed.
> So maybe for now this could be as is?

only if you promisse to do that rewrite afterwards.


[...]
> @@ -291,6 +308,95 @@ static void decode_format80(const unsign
>                  dest_index, dest_size);
>  }
>  
> +static inline void vqa_copy_hc_block(uint16_t *pixels,int stride,const uint16_t *codebook,
> +                                      int block_h)
> +{

> +    int pixel_y;
> +    for (pixel_y = 0; pixel_y < block_h; pixel_y++) {

while(block_h--){


> +        memcpy(pixels,codebook,8);
> +        pixels += stride;
> +        codebook += 4;
> +    }
> +}
> +
> +static void vqa_decode_hc_video_chunk(VqaContext *s,const unsigned char *src,unsigned int src_size)
> +{
> +    int block_x, block_y;          /* block width and height iterators */
> +    int blocks_wide, blocks_high;  /* width and height in 4x4|2 blocks */
> +    int block_inc;
> +    int index_shift;
> +    int i;
> +
> +    /* decoding parameters */
> +    uint16_t *pixels,*frame_end;
> +    uint16_t *codebook = (uint16_t *)s->codebook;
> +    int stride = s->frame.linesize[0] >> 1;
> +

> +    int vptr_action_code;

int type is shorter and does not seem worse


[...]
> +                case 0x0000:
> +                    blocks_done = vptr_action_code & 0x1fff;
> +                    block_x += blocks_done;
> +                    pixels += blocks_done * block_inc;
> +                    continue;
> +
> +                case 0x2000:
> +                case 0x4000:
> +                    vector_index = (vptr_action_code & 0xff) << index_shift;
> +                    blocks_done = ((vptr_action_code & 0x1f00)+0x0100) >> 7;
> +                    if((vptr_action_code & 0xe000)==0x4000)
> +                        blocks_done++;
> +                    break;
> +
> +                case 0x6000:
> +                    blocks_done=1;
> +                case 0xa000:
> +                    vector_index = (vptr_action_code & 0x1fff) << index_shift;
> +                    if((vptr_action_code & 0xe000)==0xa000)
> +                        blocks_done = *src++;
> +                    break;

if(type==0){
   ...
}else if(type < 3){
    vector_index = (code & 0xff) << index_shift;
    blocks_done  = (code>>7) + 1 + type;
}else if(type==3 || type==5){
    vector_index =  code         << index_shift;
    if(type==3) blocks_done= 1;
    else        blocks_done= *src++;
}


[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

He who knows, does not speak. He who speaks, does not know. -- Lao Tsu
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20090505/307b6932/attachment.pgp>



More information about the ffmpeg-devel mailing list