[Ffmpeg-devel] [RFC] .tga decoder
Michael Niedermayer
michaelni
Tue Oct 10 09:32:47 CEST 2006
Hi
On Mon, Oct 09, 2006 at 02:08:20PM +0300, Kostya wrote:
> Here is my Targa files decoder. It tested to work on .tga files
> created with ImageMagick and on movs with different depth which can
> be found here: http://www.openquicktime.org/files.php (named aletrek-*.mov)
[...]
> +static void targa_decode_rle(AVCodecContext *avctx, TargaContext *s, uint8_t *src, uint8_t *dst, int w, int h, int stride, int bpp)
> +{
> + int i, x, y;
> + int depth = (bpp + 1) / 8;
> + int type, count;
> + int diff;
> +
> + diff = stride - w * depth;
> + x = y = 0;
> + while(y < h){
> + type = *src++;
> + count = (type & 0x7F) + 1;
> + if((x + count > w) && (y + (x + count + 1)/w > h)){
x + count + 1 > (h - y)*w
avoids the /
> + av_log(avctx, AV_LOG_ERROR, "Packet went out of bounds: position (%i,%i) size %i\n", x, y, count);
> + return;
> + }
> + if(type & 0x80){ // RLE
> + for(i = 0; i < count; i++){
> + switch(depth){
> + case 1:
> + *dst = *src;
> + break;
> + case 2:
> + *((uint16_t*)dst) = LE_16(src);
> + break;
> + case 3:
> + dst[0] = src[0];
> + dst[1] = src[1];
> + dst[2] = src[2];
> + break;
> + }
> + dst += depth;
> + x++;
> + if(x == w){
> + x = 0;
> + y++;
> + dst += diff;
> + }
> + }
> + src += depth;
> + }else{ // copy
> + for(i = 0; i < count; i++){
> + switch(depth){
> + case 1:
> + *dst++ = *src++;
> + break;
> + case 2:
> + *((uint16_t*)dst) = LE_16(src);
> + dst += 2; src += 2;
> + break;
> + case 3:
> + *dst++ = *src++;
> + *dst++ = *src++;
> + *dst++ = *src++;
> + break;
> + }
> + x++;
> + if(x == w){
> + x = 0;
> + y++;
> + dst += diff;
> + }
> + }
> + }
for(i = 0; i < count; i++){
switch(depth){
case 1:
*dst = *src;
break;
case 2:
*((uint16_t*)dst) = LE_16(src);
break;
case 3:
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
break;
}
dst += depth;
if(!(type & 0x80))
src += depth;
x++;
if(x == w){
x = 0;
y++;
dst += diff;
}
}
and if speed matters then an always_inline function which has type&0x80 and
depth as "constant" arguments should help
[...]
> + uint16_t *dst16;
> + for(y = 0; y < s->height; y++){
> + switch(s->bpp){
> + case 8:
> + memcpy(dst, buf, s->width);
> + break;
> + case 15:
> + case 16:
> + dst16 = (uint16_t*)dst;
> + for(x = 0; x < s->width; x++)
> + dst16[x] = LE_16(buf + x*2);
> + break;
> + case 24:
> + memcpy(dst, buf, s->width * 3);
> + break;
> + }
> + dst += stride;
> + buf += s->width * ((s->bpp + 1) >> 3);
> + }
#ifdef WORDS_BIGENDIAN
if(s->bpp>>3 == 2){
uint16_t *dst16 = (uint16_t*)dst;
for(x = 0; x < s->width; x++)
dst16[x] = LE_16(buf + x*2);
}else
#endif
memcpy(dst, buf, s->width*(s->bpp>>3));
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
In the past you could go to a library and read, borrow or copy any book
Today you'd get arrested for mere telling someone where the library is
More information about the ffmpeg-devel
mailing list