Mercurial > libavcodec.hg
changeset 4080:f426c81afc9e libavcodec
LZW decoder as separate module plus TIFF LZW support
author | kostya |
---|---|
date | Thu, 26 Oct 2006 04:15:48 +0000 |
parents | 00a0b18cfb92 |
children | cedb63307f3d |
files | Makefile avcodec.h gifdec.c lzw.c lzw.h tiff.c |
diffstat | 6 files changed, 342 insertions(+), 174 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Thu Oct 26 04:06:08 2006 +0000 +++ b/Makefile Thu Oct 26 04:15:48 2006 +0000 @@ -81,7 +81,7 @@ OBJS-$(CONFIG_FLIC_DECODER) += flicvideo.o OBJS-$(CONFIG_FOURXM_DECODER) += 4xm.o OBJS-$(CONFIG_FRAPS_DECODER) += fraps.o -OBJS-$(CONFIG_GIF_DECODER) += gifdec.o +OBJS-$(CONFIG_GIF_DECODER) += gifdec.o lzw.o OBJS-$(CONFIG_H261_DECODER) += h261.o OBJS-$(CONFIG_H261_ENCODER) += h261.o OBJS-$(CONFIG_H264_DECODER) += h264.o @@ -132,7 +132,7 @@ OBJS-$(CONFIG_SVQ3_DECODER) += h264.o OBJS-$(CONFIG_TARGA_DECODER) += targa.o OBJS-$(CONFIG_THEORA_DECODER) += vp3.o -OBJS-$(CONFIG_TIFF_DECODER) += tiff.o +OBJS-$(CONFIG_TIFF_DECODER) += tiff.o lzw.o OBJS-$(CONFIG_TRUEMOTION1_DECODER) += truemotion1.o OBJS-$(CONFIG_TRUEMOTION2_DECODER) += truemotion2.o OBJS-$(CONFIG_TRUESPEECH_DECODER) += truespeech.o
--- a/avcodec.h Thu Oct 26 04:06:08 2006 +0000 +++ b/avcodec.h Thu Oct 26 04:15:48 2006 +0000 @@ -37,8 +37,8 @@ #define AV_STRINGIFY(s) AV_TOSTRING(s) #define AV_TOSTRING(s) #s -#define LIBAVCODEC_VERSION_INT ((51<<16)+(21<<8)+0) -#define LIBAVCODEC_VERSION 51.21.0 +#define LIBAVCODEC_VERSION_INT ((51<<16)+(22<<8)+0) +#define LIBAVCODEC_VERSION 51.22.0 #define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT #define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION)
--- a/gifdec.c Thu Oct 26 04:06:08 2006 +0000 +++ b/gifdec.c Thu Oct 26 04:15:48 2006 +0000 @@ -24,9 +24,7 @@ #include "avcodec.h" #include "bytestream.h" - -#define MAXBITS 12 -#define SIZTABLE (1<<MAXBITS) +#include "lzw.h" #define GCE_DISPOSAL_NONE 0 #define GCE_DISPOSAL_INPLACE 1 @@ -50,175 +48,16 @@ /* LZW compatible decoder */ uint8_t *bytestream; - int eob_reached; - uint8_t *pbuf, *ebuf; - int bbits; - unsigned int bbuf; - - int cursize; /* The current code size */ - int curmask; - int codesize; - int clear_code; - int end_code; - int newcodes; /* First available code */ - int top_slot; /* Highest code for current size */ - int slot; /* Last read code */ - int fc, oc; - uint8_t *sp; - uint8_t stack[SIZTABLE]; - uint8_t suffix[SIZTABLE]; - uint16_t prefix[SIZTABLE]; + LZWState *lzw; /* aux buffers */ uint8_t global_palette[256 * 3]; uint8_t local_palette[256 * 3]; - uint8_t buf[256]; } GifState; static const uint8_t gif87a_sig[6] = "GIF87a"; static const uint8_t gif89a_sig[6] = "GIF89a"; -static const uint16_t mask[17] = -{ - 0x0000, 0x0001, 0x0003, 0x0007, - 0x000F, 0x001F, 0x003F, 0x007F, - 0x00FF, 0x01FF, 0x03FF, 0x07FF, - 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF -}; - -static void GLZWDecodeInit(GifState * s, int csize) -{ - /* read buffer */ - s->eob_reached = 0; - s->pbuf = s->buf; - s->ebuf = s->buf; - s->bbuf = 0; - s->bbits = 0; - - /* decoder */ - s->codesize = csize; - s->cursize = s->codesize + 1; - s->curmask = mask[s->cursize]; - s->top_slot = 1 << s->cursize; - s->clear_code = 1 << s->codesize; - s->end_code = s->clear_code + 1; - s->slot = s->newcodes = s->clear_code + 2; - s->oc = s->fc = 0; - s->sp = s->stack; -} - -/* XXX: optimize */ -static inline int GetCode(GifState * s) -{ - int c, sizbuf; - uint8_t *ptr; - - while (s->bbits < s->cursize) { - ptr = s->pbuf; - if (ptr >= s->ebuf) { - if (!s->eob_reached) { - sizbuf = bytestream_get_byte(&s->bytestream); - s->ebuf = s->buf + sizbuf; - s->pbuf = s->buf; - if (sizbuf > 0) { - bytestream_get_buffer(&s->bytestream, s->buf, sizbuf); - } else { - s->eob_reached = 1; - } - } - ptr = s->pbuf; - } - s->bbuf |= ptr[0] << s->bbits; - ptr++; - s->pbuf = ptr; - s->bbits += 8; - } - c = s->bbuf & s->curmask; - s->bbuf >>= s->cursize; - s->bbits -= s->cursize; - return c; -} - -/* NOTE: the algorithm here is inspired from the LZW GIF decoder - written by Steven A. Bennett in 1987. */ -/* return the number of byte decoded */ -static int GLZWDecode(GifState * s, uint8_t * buf, int len) -{ - int l, c, code, oc, fc; - uint8_t *sp; - - if (s->end_code < 0) - return 0; - - l = len; - sp = s->sp; - oc = s->oc; - fc = s->fc; - - while (sp > s->stack) { - *buf++ = *(--sp); - if ((--l) == 0) - goto the_end; - } - - for (;;) { - c = GetCode(s); - if (c == s->end_code) { - s->end_code = -1; - break; - } else if (c == s->clear_code) { - s->cursize = s->codesize + 1; - s->curmask = mask[s->cursize]; - s->slot = s->newcodes; - s->top_slot = 1 << s->cursize; - while ((c = GetCode(s)) == s->clear_code); - if (c == s->end_code) { - s->end_code = -1; - break; - } - /* test error */ - if (c >= s->slot) - c = 0; - fc = oc = c; - *buf++ = c; - if ((--l) == 0) - break; - } else { - code = c; - if (code >= s->slot) { - *sp++ = fc; - code = oc; - } - while (code >= s->newcodes) { - *sp++ = s->suffix[code]; - code = s->prefix[code]; - } - *sp++ = code; - if (s->slot < s->top_slot) { - s->suffix[s->slot] = fc = code; - s->prefix[s->slot++] = oc; - oc = c; - } - if (s->slot >= s->top_slot) { - if (s->cursize < MAXBITS) { - s->top_slot <<= 1; - s->curmask = mask[++s->cursize]; - } - } - while (sp > s->stack) { - *buf++ = *(--sp); - if ((--l) == 0) - goto the_end; - } - } - } - the_end: - s->sp = sp; - s->oc = oc; - s->fc = fc; - return len - l; -} - static int gif_read_image(GifState *s) { int left, top, width, height, bits_per_pixel, code_size, flags; @@ -267,7 +106,8 @@ /* now get the image data */ code_size = bytestream_get_byte(&s->bytestream); - GLZWDecodeInit(s, code_size); + //TODO: add proper data size + ff_lzw_decode_init(s->lzw, code_size, s->bytestream, 0, FF_LZW_GIF); /* read all the image */ linesize = s->picture.linesize[0]; @@ -276,7 +116,7 @@ pass = 0; y1 = 0; for (y = 0; y < height; y++) { - GLZWDecode(s, ptr, width); + ff_lzw_decode(s->lzw, ptr, width); if (is_interleaved) { switch(pass) { default: @@ -314,8 +154,8 @@ av_free(line); /* read the garbage data until end marker is found */ - while (!s->eob_reached) - GetCode(s); + ff_lzw_decode_tail(s->lzw); + s->bytestream = ff_lzw_cur_ptr(s->lzw); return 0; } @@ -445,6 +285,7 @@ avcodec_get_frame_defaults(&s->picture); avctx->coded_frame= &s->picture; s->picture.data[0] = NULL; + ff_lzw_decode_open(&s->lzw); return 0; } @@ -483,6 +324,7 @@ { GifState *s = avctx->priv_data; + ff_lzw_decode_close(&s->lzw); if(s->picture.data[0]) avctx->release_buffer(avctx, &s->picture); return 0;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lzw.c Thu Oct 26 04:15:48 2006 +0000 @@ -0,0 +1,262 @@ +/* + * LZW decoder + * Copyright (c) 2003 Fabrice Bellard. + * Copyright (c) 2006 Konstantin Shishkov. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file lzw.c + * @brief LZW decoding routines + * @author Fabrice Bellard + * Modified for use in TIFF by Konstantin Shishkov + */ + +#include "avcodec.h" +#include "lzw.h" + +#define LZW_MAXBITS 12 +#define LZW_SIZTABLE (1<<LZW_MAXBITS) + +static const uint16_t mask[17] = +{ + 0x0000, 0x0001, 0x0003, 0x0007, + 0x000F, 0x001F, 0x003F, 0x007F, + 0x00FF, 0x01FF, 0x03FF, 0x07FF, + 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF +}; + +struct LZWState { + int eob_reached; + uint8_t *pbuf, *ebuf; + int bbits; + unsigned int bbuf; + + int mode; ///< Decoder mode + int cursize; ///< The current code size + int curmask; + int codesize; + int clear_code; + int end_code; + int newcodes; ///< First available code + int top_slot; ///< Highest code for current size + int top_slot2; ///< Highest possible code for current size (<=top_slot) + int slot; ///< Last read code + int fc, oc; + uint8_t *sp; + uint8_t stack[LZW_SIZTABLE]; + uint8_t suffix[LZW_SIZTABLE]; + uint16_t prefix[LZW_SIZTABLE]; + int bs; ///< current buffer size for GIF +}; + +/* get one code from stream */ +static int lzw_get_code(struct LZWState * s) +{ + int c, sizbuf; + + if(s->mode == FF_LZW_GIF) { + while (s->bbits < s->cursize) { + if (!s->bs) { + sizbuf = *s->pbuf++; + s->bs = sizbuf; + if(!sizbuf) { + s->eob_reached = 1; + } + } + s->bbuf |= (*s->pbuf++) << s->bbits; + s->bbits += 8; + s->bs--; + } + c = s->bbuf & s->curmask; + s->bbuf >>= s->cursize; + } else { // TIFF + while (s->bbits < s->cursize) { + if (s->pbuf >= s->ebuf) { + s->eob_reached = 1; + } + s->bbuf = (s->bbuf << 8) | (*s->pbuf++); + s->bbits += 8; + } + c = (s->bbuf >> (s->bbits - s->cursize)) & s->curmask; + } + s->bbits -= s->cursize; + return c; +} + +uint8_t* ff_lzw_cur_ptr(LZWState *p) +{ + return ((struct LZWState*)p)->pbuf; +} + +void ff_lzw_decode_tail(LZWState *p) +{ + struct LZWState *s = (struct LZWState *)p; + while(!s->eob_reached) + lzw_get_code(s); +} + +void ff_lzw_decode_open(LZWState **p) +{ + *p = av_mallocz(sizeof(struct LZWState)); +} + +void ff_lzw_decode_close(LZWState **p) +{ + av_freep(p); +} + +/** + * Initialize LZW decoder + * @param s LZW context + * @param csize initial code size in bits + * @param buf input data + * @param buf_size input data size + * @param mode decoder working mode - either GIF or TIFF + */ +int ff_lzw_decode_init(LZWState *p, int csize, uint8_t *buf, int buf_size, int mode) +{ + struct LZWState *s = (struct LZWState *)p; + + if(csize < 1 || csize > LZW_MAXBITS) + return -1; + /* read buffer */ + s->eob_reached = 0; + s->pbuf = buf; + s->ebuf = s->pbuf + buf_size; + s->bbuf = 0; + s->bbits = 0; + s->bs = 0; + + /* decoder */ + s->codesize = csize; + s->cursize = s->codesize + 1; + s->curmask = mask[s->cursize]; + s->top_slot = 1 << s->cursize; + s->clear_code = 1 << s->codesize; + s->end_code = s->clear_code + 1; + s->slot = s->newcodes = s->clear_code + 2; + s->oc = s->fc = 0; + s->sp = s->stack; + + s->mode = mode; + switch(s->mode){ + case FF_LZW_GIF: + s->top_slot2 = s->top_slot; + break; + case FF_LZW_TIFF: + s->top_slot2 = s->top_slot - 1; + break; + default: + return -1; + } + return 0; +} + +/** + * Decode given number of bytes + * NOTE: the algorithm here is inspired from the LZW GIF decoder + * written by Steven A. Bennett in 1987. + * + * @param s LZW context + * @param buf output buffer + * @param len number of bytes to decode + * @return number of bytes decoded + */ +int ff_lzw_decode(LZWState *p, uint8_t *buf, int len){ + int l, c, code, oc, fc; + uint8_t *sp; + struct LZWState *s = (struct LZWState *)p; + + if (s->end_code < 0) + return 0; + + l = len; + sp = s->sp; + oc = s->oc; + fc = s->fc; + + while (sp > s->stack) { + *buf++ = *(--sp); + if ((--l) == 0) + goto the_end; + } + + for (;;) { + c = lzw_get_code(s); + if (c == s->end_code) { + s->end_code = -1; + break; + } else if (c == s->clear_code) { + s->cursize = s->codesize + 1; + s->curmask = mask[s->cursize]; + s->slot = s->newcodes; + s->top_slot = 1 << s->cursize; + s->top_slot2 = s->top_slot; + if(s->mode == FF_LZW_TIFF) + s->top_slot2--; + while ((c = lzw_get_code(s)) == s->clear_code); + if (c == s->end_code) { + s->end_code = -1; + break; + } + /* test error */ + if (c >= s->slot) + c = 0; + fc = oc = c; + *buf++ = c; + if ((--l) == 0) + break; + } else { + code = c; + if (code >= s->slot) { + *sp++ = fc; + code = oc; + } + while (code >= s->newcodes) { + *sp++ = s->suffix[code]; + code = s->prefix[code]; + } + *sp++ = code; + if (s->slot < s->top_slot) { + s->suffix[s->slot] = fc = code; + s->prefix[s->slot++] = oc; + oc = c; + } + if (s->slot >= s->top_slot2) { + if (s->cursize < LZW_MAXBITS) { + s->top_slot <<= 1; + s->top_slot2 = s->top_slot; + if(s->mode == FF_LZW_TIFF) + s->top_slot2--; + s->curmask = mask[++s->cursize]; + } + } + while (sp > s->stack) { + *buf++ = *(--sp); + if ((--l) == 0) + goto the_end; + } + } + } + the_end: + s->sp = sp; + s->oc = oc; + s->fc = fc; + return len - l; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lzw.h Thu Oct 26 04:15:48 2006 +0000 @@ -0,0 +1,49 @@ +/* + * LZW decoder + * Copyright (c) 2003 Fabrice Bellard. + * Copyright (c) 2006 Konstantin Shishkov. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file lzw.h + * @brief LZW decoding routines + * @author Fabrice Bellard + * Modified for use in TIFF by Konstantin Shishkov + */ + +#ifndef LZW_H +#define LZW_H + +enum FF_LZW_MODES{ + FF_LZW_GIF, + FF_LZW_TIFF +}; + +/* clients should not know what LZWState is */ +typedef void LZWState; + +/* first two functions de/allocate memory for LZWState */ +void ff_lzw_decode_open(LZWState **p); +void ff_lzw_decode_close(LZWState **p); +int ff_lzw_decode_init(LZWState *s, int csize, uint8_t *buf, int buf_size, int mode); +int ff_lzw_decode(LZWState *s, uint8_t *buf, int len); +uint8_t* ff_lzw_cur_ptr(LZWState *lzw); +void ff_lzw_decode_tail(LZWState *lzw); + +#endif
--- a/tiff.c Thu Oct 26 04:06:08 2006 +0000 +++ b/tiff.c Thu Oct 26 04:15:48 2006 +0000 @@ -23,6 +23,7 @@ #ifdef CONFIG_ZLIB #include <zlib.h> #endif +#include "lzw.h" /* abridged list of TIFF tags */ enum TiffTags{ @@ -74,6 +75,7 @@ uint8_t* stripdata; uint8_t* stripsizes; int stripsize, stripoff; + LZWState *lzw; } TiffContext; static int tget_short(uint8_t **p, int le){ @@ -126,6 +128,12 @@ return 0; } #endif + if(s->compr == TIFF_LZW){ + if(ff_lzw_decode_init(s->lzw, 8, src, size, FF_LZW_TIFF) < 0){ + av_log(s->avctx, AV_LOG_ERROR, "Error initializing LZW decoder\n"); + return -1; + } + } for(line = 0; line < lines; line++){ if(src - ssrc > size){ av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n"); @@ -160,6 +168,13 @@ } } break; + case TIFF_LZW: + pixels = ff_lzw_decode(s->lzw, dst, width); + if(pixels < width){ + av_log(s->avctx, AV_LOG_ERROR, "Decoded only %i bytes of %i\n", pixels, width); + return -1; + } + break; } dst += stride; } @@ -247,6 +262,7 @@ switch(s->compr){ case TIFF_RAW: case TIFF_PACKBITS: + case TIFF_LZW: break; case TIFF_DEFLATE: case TIFF_ADOBE_DEFLATE: @@ -256,9 +272,6 @@ av_log(s->avctx, AV_LOG_ERROR, "Deflate: ZLib not compiled in\n"); return -1; #endif - case TIFF_LZW: - av_log(s->avctx, AV_LOG_ERROR, "LZW: not implemented yet\n"); - return -1; case TIFF_G3: av_log(s->avctx, AV_LOG_ERROR, "CCITT G3 compression is not supported\n"); return -1; @@ -405,6 +418,7 @@ avcodec_get_frame_defaults((AVFrame*)&s->picture); avctx->coded_frame= (AVFrame*)&s->picture; s->picture.data[0] = NULL; + ff_lzw_decode_open(&s->lzw); return 0; } @@ -413,6 +427,7 @@ { TiffContext * const s = avctx->priv_data; + ff_lzw_decode_close(&s->lzw); if(s->picture.data[0]) avctx->release_buffer(avctx, &s->picture); return 0;