[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