[FFmpeg-devel] [PATCH] Electronic Arts TGV decoder

Michael Niedermayer michaelni
Sun Jul 13 00:12:32 CEST 2008


On Sat, Jul 12, 2008 at 04:32:20PM +1000, pross at xvid.org wrote:
> On Thu, Jul 10, 2008 at 01:00:32AM +0200, Michael Niedermayer wrote:
> > On Wed, Jul 09, 2008 at 09:18:13PM +1000, pross at xvid.org wrote:
> > > Hi!
> > > 
> > > Second video codec in the EA series.
> > > 
> > > Samples: http://samples.mplayerhq.hu/game-formats/ea-tgv/
> > > Write-up: http://wiki.multimedia.cx/index.php?title=Electronic_Arts_TGV
> > [...]
> 
> Revised patch enclosed.
[...]
> +static inline void memcpy_naive(uint8_t *dst, const uint8_t *src, size_t size)
> +{
> +    if (src+size<dst) {
> +        memcpy(dst, src, size);
> +    }else {
> +        /* when src and dst overlap, perform naive copy */
> +        int i;
> +        for(i=0; i<size; i++) dst[i] = src[i];
> +    }
> +}

This might be a duplicate of copy_backptr() from libavutil/lzo.c
factorizig the common code out into a function might be a good idea
so both can benefit from all the optimizations.


> +

> +/**
> + * Unpack buffer
> + * @return 0 on success, -1 on critical buffer underflow
> + */
> +static int unpack(const uint8_t *src, const uint8_t *src_end, unsigned char *dst, int width, int height, int stride) {
> +const uint8_t *src_start = src;
> +    unsigned char *dst_end = dst + width*stride;
> +    int size1,size2,offset;
> +    int size;
> +    int i;
> +    int x=0, y=0;
> +

> +    if ((*src & 0x01))

superflous ()

> +        src += 5;
> +    else
> +        src += 2;
> +
> +    if (src+3>src_end)
> +        return -1;
> +    size = AV_RB24(src);
> +    src += 3;
> +
> +    while(size>0 && src<src_end) {
> +
> +        /* determine size1 and size2 */
> +        size1 = (src[0] & 3);
> +        if ( src[0] & 0x80 ) {  // 1
> +            if (src[0] & 0x40 ) {  // 11
> +                if ( src[0] & 0x20 ) {  // 111
> +                    if ( src[0] < 0xFC )  // !(111111)
> +                        size1 = (((src[0] & 31) + 1) << 2);
> +                    src++;
> +                    size2 = 0;
> +                } else {  // 110

> +                    offset = -(((src[0] & 0x10) << 12) + (src[1] << 8) + src[2]) - 1;

part of that can be replaced by AV_RB16()



> +                    size2 = ((src[0] & 0xC) << 6) + src[3] + 5;
> +                    src += 4;
> +                }
> +            } else {  // 10
> +                size1 = ( ( src[1] & 0xC0) >> 6 );

> +                offset = -(((src[1] & 0x3F) << 8) + src[2]) - 1;

AV_RB16()


> +                size2 = (src[0] & 0x3F) + 4;
> +                src += 3;
> +            }
> +        } else {  // 0
> +            offset = -( ((src[0] & 0x60) << 3) + src[1] ) - 1;
> +            size2 = ((src[0] & 0x1C) >> 2) + 3;
> +            src += 2;
> +        }
> +
> +
> +        /* fetch strip from src */
> +        if (src+size1>src_end)
> +            break;
> +

> +        size -= size1;
> +        while(size1>0) {
> +            int run = FFMIN(size1, width-x);
> +            memcpy(dst + y*stride + x, src, run);
> +            src+=run;
> +            size1-=run;
> +            x+=run;
> +            if (x>=width) {
> +                x=0; y++;
> +                if (y>=height) return 0;
> +            }
> +        }

Is this more efficient than simply allocating width*height AVFrames?
It would require CODEC_CAP_DR1 to be removed though ...


> +
> +        if (size2>0) {
> +            /* convert the unstrided address in strided x,y pair */
> +            offset += y*width+x;
> +            if (offset<0)
> +                return 0;
> +            int oy = offset / width;
> +            int ox = offset % width;
> +
> +            size -= size2;
> +            while(size2>0) {

> +                int run = FFMIN(FFMIN(size2, width-x), width-ox);

FFMIN3


[...]
> +    /* read compressed blocks */
> +    for (i=0; i<num_blocks_packed; i++) {

> +        unsigned int index = AV_RL32(&buf[4]);
> +        for(j=0; j<16; j++)
> +            s->block_codebook[i][j] = buf[(index>>((15-j)*2)) & 3];
> +        buf += 8;
> +    }
> +
> +    /* read vectors and build frame */
> +    init_get_bits(&gb, buf, (buf_end-buf)<<3);


for(j=0; j<4; j++)
    tmp[j] = get_bits(8);
for(j=0; j<16; j++)
    s->block_codebook[i][j] = tmp[get_bits(2)];

(less bit / byte access switching ...)


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

No human being will ever know the Truth, for even if they happen to say it
by chance, they would not even known they had done so. -- Xenophanes
-------------- 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/20080713/a1829b85/attachment.pgp>



More information about the ffmpeg-devel mailing list