[FFmpeg-cvslog] r15356 - in trunk/libavcodec: Makefile aasc.c msrle.c msrledec.c msrledec.h tscc.c

kostya subversion
Thu Sep 18 07:20:55 CEST 2008


Author: kostya
Date: Thu Sep 18 07:20:54 2008
New Revision: 15356

Log:
Factorize out code used for MS RLE format decoding in different decoders.


Added:
   trunk/libavcodec/msrledec.c
      - copied, changed from r15355, /trunk/libavcodec/tscc.c
   trunk/libavcodec/msrledec.h
Modified:
   trunk/libavcodec/Makefile
   trunk/libavcodec/aasc.c
   trunk/libavcodec/msrle.c
   trunk/libavcodec/tscc.c

Modified: trunk/libavcodec/Makefile
==============================================================================
--- trunk/libavcodec/Makefile	(original)
+++ trunk/libavcodec/Makefile	Thu Sep 18 07:20:54 2008
@@ -26,7 +26,7 @@ HEADERS = avcodec.h opt.h
 OBJS-$(CONFIG_ENCODERS)                += faandct.o jfdctfst.o jfdctint.o
 
 OBJS-$(CONFIG_AAC_DECODER)             += aac.o aactab.o mdct.o fft.o
-OBJS-$(CONFIG_AASC_DECODER)            += aasc.o
+OBJS-$(CONFIG_AASC_DECODER)            += aasc.o msrledec.o
 OBJS-$(CONFIG_AC3_DECODER)             += eac3dec.o ac3dec.o ac3tab.o ac3dec_data.o ac3.o mdct.o fft.o
 OBJS-$(CONFIG_AC3_ENCODER)             += ac3enc.o ac3tab.o ac3.o
 OBJS-$(CONFIG_ALAC_DECODER)            += alac.o
@@ -136,7 +136,7 @@ OBJS-$(CONFIG_MSMPEG4V2_DECODER)       +
 OBJS-$(CONFIG_MSMPEG4V2_ENCODER)       += msmpeg4.o msmpeg4data.o mpegvideo_enc.o motion_est.o ratecontrol.o h263.o mpeg12data.o mpegvideo.o error_resilience.o
 OBJS-$(CONFIG_MSMPEG4V3_DECODER)       += msmpeg4.o msmpeg4data.o h263dec.o h263.o mpeg12data.o mpegvideo.o error_resilience.o
 OBJS-$(CONFIG_MSMPEG4V3_ENCODER)       += msmpeg4.o msmpeg4data.o mpegvideo_enc.o motion_est.o ratecontrol.o h263.o mpeg12data.o mpegvideo.o error_resilience.o
-OBJS-$(CONFIG_MSRLE_DECODER)           += msrle.o
+OBJS-$(CONFIG_MSRLE_DECODER)           += msrle.o msrledec.o
 OBJS-$(CONFIG_MSVIDEO1_DECODER)        += msvideo1.o
 OBJS-$(CONFIG_MSZH_DECODER)            += lcldec.o
 OBJS-$(CONFIG_NELLYMOSER_DECODER)      += nellymoserdec.o nellymoser.o mdct.o fft.o
@@ -197,7 +197,7 @@ OBJS-$(CONFIG_TIFF_ENCODER)            +
 OBJS-$(CONFIG_TRUEMOTION1_DECODER)     += truemotion1.o
 OBJS-$(CONFIG_TRUEMOTION2_DECODER)     += truemotion2.o
 OBJS-$(CONFIG_TRUESPEECH_DECODER)      += truespeech.o
-OBJS-$(CONFIG_TSCC_DECODER)            += tscc.o
+OBJS-$(CONFIG_TSCC_DECODER)            += tscc.o msrledec.o
 OBJS-$(CONFIG_TTA_DECODER)             += tta.o
 OBJS-$(CONFIG_TXD_DECODER)             += txd.o s3tc.o
 OBJS-$(CONFIG_ULTI_DECODER)            += ulti.o

Modified: trunk/libavcodec/aasc.c
==============================================================================
--- trunk/libavcodec/aasc.c	(original)
+++ trunk/libavcodec/aasc.c	Thu Sep 18 07:20:54 2008
@@ -30,6 +30,7 @@
 
 #include "avcodec.h"
 #include "dsputil.h"
+#include "msrledec.h"
 
 typedef struct AascContext {
     AVCodecContext *avctx;
@@ -61,13 +62,6 @@ static int aasc_decode_frame(AVCodecCont
                               const uint8_t *buf, int buf_size)
 {
     AascContext *s = avctx->priv_data;
-    int stream_ptr = 4;
-    unsigned char rle_code;
-    unsigned char stream_byte;
-    int pixel_ptr = 0;
-    int row_dec, row_ptr;
-    int frame_size;
-    int i;
 
     s->frame.reference = 1;
     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
@@ -76,72 +70,7 @@ static int aasc_decode_frame(AVCodecCont
         return -1;
     }
 
-    row_dec = s->frame.linesize[0];
-    row_ptr = (s->avctx->height - 1) * row_dec;
-    frame_size = row_dec * s->avctx->height;
-
-    while (row_ptr >= 0) {
-        FETCH_NEXT_STREAM_BYTE();
-        rle_code = stream_byte;
-        if (rle_code == 0) {
-            /* fetch the next byte to see how to handle escape code */
-            FETCH_NEXT_STREAM_BYTE();
-            if (stream_byte == 0) {
-                /* line is done, goto the next one */
-                row_ptr -= row_dec;
-                pixel_ptr = 0;
-            } else if (stream_byte == 1) {
-                /* decode is done */
-                break;
-            } else if (stream_byte == 2) {
-                /* reposition frame decode coordinates */
-                FETCH_NEXT_STREAM_BYTE();
-                pixel_ptr += stream_byte;
-                FETCH_NEXT_STREAM_BYTE();
-                row_ptr -= stream_byte * row_dec;
-            } else {
-                /* copy pixels from encoded stream */
-                if ((pixel_ptr + stream_byte > avctx->width * 3) ||
-                    (row_ptr < 0)) {
-                    av_log(s->avctx, AV_LOG_ERROR, " AASC: frame ptr just went out of bounds (copy1)\n");
-                    break;
-                }
-
-                rle_code = stream_byte;
-                if (stream_ptr + rle_code > buf_size) {
-                    av_log(s->avctx, AV_LOG_ERROR, " AASC: stream ptr just went out of bounds (copy2)\n");
-                    break;
-                }
-
-                for (i = 0; i < rle_code; i++) {
-                    FETCH_NEXT_STREAM_BYTE();
-                    s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
-                    pixel_ptr++;
-                }
-                if (rle_code & 1)
-                    stream_ptr++;
-            }
-        } else {
-            /* decode a run of data */
-            if ((pixel_ptr + rle_code > avctx->width * 3) ||
-                (row_ptr < 0)) {
-                av_log(s->avctx, AV_LOG_ERROR, " AASC: frame ptr just went out of bounds (run1)\n");
-                break;
-            }
-
-            FETCH_NEXT_STREAM_BYTE();
-
-            while(rle_code--) {
-                s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
-                pixel_ptr++;
-            }
-        }
-    }
-
-    /* one last sanity check on the way out */
-    if (stream_ptr < buf_size)
-        av_log(s->avctx, AV_LOG_ERROR, " AASC: ended frame decode with bytes left over (%d < %d)\n",
-            stream_ptr, buf_size);
+    ff_msrle_decode(avctx, &s->frame, 8, buf, buf_size);
 
     *data_size = sizeof(AVFrame);
     *(AVFrame*)data = s->frame;

Modified: trunk/libavcodec/msrle.c
==============================================================================
--- trunk/libavcodec/msrle.c	(original)
+++ trunk/libavcodec/msrle.c	Thu Sep 18 07:20:54 2008
@@ -38,6 +38,7 @@
 
 #include "avcodec.h"
 #include "dsputil.h"
+#include "msrledec.h"
 
 typedef struct MsrleContext {
     AVCodecContext *avctx;
@@ -48,194 +49,6 @@ typedef struct MsrleContext {
 
 } MsrleContext;
 
-#define FETCH_NEXT_STREAM_BYTE() \
-    if (stream_ptr >= s->size) \
-    { \
-      av_log(s->avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (1)\n"); \
-      return; \
-    } \
-    stream_byte = s->buf[stream_ptr++];
-
-static void msrle_decode_pal4(MsrleContext *s)
-{
-    int stream_ptr = 0;
-    unsigned char rle_code;
-    unsigned char extra_byte, odd_pixel;
-    unsigned char stream_byte;
-    int pixel_ptr = 0;
-    int row_dec = s->frame.linesize[0];
-    int row_ptr = (s->avctx->height - 1) * row_dec;
-    int frame_size = row_dec * s->avctx->height;
-    int i;
-
-    /* make the palette available */
-    memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
-    if (s->avctx->palctrl->palette_changed) {
-        s->frame.palette_has_changed = 1;
-        s->avctx->palctrl->palette_changed = 0;
-    }
-
-    while (row_ptr >= 0) {
-        FETCH_NEXT_STREAM_BYTE();
-        rle_code = stream_byte;
-        if (rle_code == 0) {
-            /* fetch the next byte to see how to handle escape code */
-            FETCH_NEXT_STREAM_BYTE();
-            if (stream_byte == 0) {
-                /* line is done, goto the next one */
-                row_ptr -= row_dec;
-                pixel_ptr = 0;
-            } else if (stream_byte == 1) {
-                /* decode is done */
-                return;
-            } else if (stream_byte == 2) {
-                /* reposition frame decode coordinates */
-                FETCH_NEXT_STREAM_BYTE();
-                pixel_ptr += stream_byte;
-                FETCH_NEXT_STREAM_BYTE();
-                row_ptr -= stream_byte * row_dec;
-        } else {
-            // copy pixels from encoded stream
-            odd_pixel =  stream_byte & 1;
-            rle_code = (stream_byte + 1) / 2;
-            extra_byte = rle_code & 0x01;
-            if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
-                (row_ptr < 0)) {
-                av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
-                return;
-            }
-
-            for (i = 0; i < rle_code; i++) {
-                if (pixel_ptr >= s->avctx->width)
-                    break;
-                FETCH_NEXT_STREAM_BYTE();
-                s->frame.data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
-                pixel_ptr++;
-                if (i + 1 == rle_code && odd_pixel)
-                    break;
-                if (pixel_ptr >= s->avctx->width)
-                    break;
-                s->frame.data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
-                pixel_ptr++;
-            }
-
-            // if the RLE code is odd, skip a byte in the stream
-            if (extra_byte)
-              stream_ptr++;
-            }
-        } else {
-            // decode a run of data
-            if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
-                (row_ptr < 0)) {
-                av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
-                return;
-            }
-            FETCH_NEXT_STREAM_BYTE();
-            for (i = 0; i < rle_code; i++) {
-                if (pixel_ptr >= s->avctx->width)
-                    break;
-                if ((i & 1) == 0)
-                    s->frame.data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
-                else
-                    s->frame.data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
-                pixel_ptr++;
-            }
-        }
-    }
-
-    /* one last sanity check on the way out */
-    if (stream_ptr < s->size)
-        av_log(s->avctx, AV_LOG_ERROR, " MS RLE: ended frame decode with bytes left over (%d < %d)\n",
-            stream_ptr, s->size);
-}
-
-
-
-static void msrle_decode_pal8(MsrleContext *s)
-{
-    int stream_ptr = 0;
-    unsigned char rle_code;
-    unsigned char extra_byte;
-    unsigned char stream_byte;
-    int pixel_ptr = 0;
-    int row_dec = s->frame.linesize[0];
-    int row_ptr = (s->avctx->height - 1) * row_dec;
-    int frame_size = row_dec * s->avctx->height;
-
-    /* make the palette available */
-    memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
-    if (s->avctx->palctrl->palette_changed) {
-        s->frame.palette_has_changed = 1;
-        s->avctx->palctrl->palette_changed = 0;
-    }
-
-    while (row_ptr >= 0) {
-        FETCH_NEXT_STREAM_BYTE();
-        rle_code = stream_byte;
-        if (rle_code == 0) {
-            /* fetch the next byte to see how to handle escape code */
-            FETCH_NEXT_STREAM_BYTE();
-            if (stream_byte == 0) {
-                /* line is done, goto the next one */
-                row_ptr -= row_dec;
-                pixel_ptr = 0;
-            } else if (stream_byte == 1) {
-                /* decode is done */
-                return;
-            } else if (stream_byte == 2) {
-                /* reposition frame decode coordinates */
-                FETCH_NEXT_STREAM_BYTE();
-                pixel_ptr += stream_byte;
-                FETCH_NEXT_STREAM_BYTE();
-                row_ptr -= stream_byte * row_dec;
-            } else {
-                /* copy pixels from encoded stream */
-                if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
-                    (row_ptr < 0)) {
-                    av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
-                    return;
-                }
-
-                rle_code = stream_byte;
-                extra_byte = stream_byte & 0x01;
-                if (stream_ptr + rle_code + extra_byte > s->size) {
-                    av_log(s->avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (2)\n");
-                    return;
-                }
-
-                while (rle_code--) {
-                    FETCH_NEXT_STREAM_BYTE();
-                    s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
-                    pixel_ptr++;
-                }
-
-                /* if the RLE code is odd, skip a byte in the stream */
-                if (extra_byte)
-                    stream_ptr++;
-            }
-        } else {
-            /* decode a run of data */
-            if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
-                (row_ptr < 0)) {
-                av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (2)\n");
-                return;
-            }
-
-            FETCH_NEXT_STREAM_BYTE();
-
-            while(rle_code--) {
-                s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
-                pixel_ptr++;
-            }
-        }
-    }
-
-    /* one last sanity check on the way out */
-    if (stream_ptr < s->size)
-        av_log(s->avctx, AV_LOG_ERROR, " MS RLE: ended frame decode with bytes left over (%d < %d)\n",
-            stream_ptr, s->size);
-}
-
 static av_cold int msrle_decode_init(AVCodecContext *avctx)
 {
     MsrleContext *s = avctx->priv_data;
@@ -264,18 +77,15 @@ static int msrle_decode_frame(AVCodecCon
         return -1;
     }
 
-    switch (avctx->bits_per_coded_sample) {
-        case 8:
-            msrle_decode_pal8(s);
-            break;
-        case 4:
-            msrle_decode_pal4(s);
-            break;
-        default:
-            av_log(avctx, AV_LOG_ERROR, "Don't know how to decode depth %u.\n",
-                   avctx->bits_per_coded_sample);
+    /* make the palette available */
+    memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
+    if (s->avctx->palctrl->palette_changed) {
+        s->frame.palette_has_changed = 1;
+        s->avctx->palctrl->palette_changed = 0;
     }
 
+    ff_msrle_decode(avctx, &s->frame, avctx->bits_per_coded_sample, buf, buf_size);
+
     *data_size = sizeof(AVFrame);
     *(AVFrame*)data = s->frame;
 

Copied: trunk/libavcodec/msrledec.c (from r15355, /trunk/libavcodec/tscc.c)
==============================================================================
--- /trunk/libavcodec/tscc.c	(original)
+++ trunk/libavcodec/msrledec.c	Thu Sep 18 07:20:54 2008
@@ -1,6 +1,6 @@
 /*
- * TechSmith Camtasia decoder
- * Copyright (c) 2004 Konstantin Shishkov
+ * Micrsoft RLE Decoder
+ * Copyright (C) 2008 Konstantin Shishkov
  *
  * This file is part of FFmpeg.
  *
@@ -20,74 +20,131 @@
  */
 
 /**
- * @file tscc.c
- * TechSmith Camtasia decoder
- *
- * Fourcc: TSCC
- *
- * Codec is very simple:
- *  it codes picture (picture difference, really)
- *  with algorithm almost identical to Windows RLE8,
- *  only without padding and with greater pixel sizes,
- *  then this coded picture is packed with ZLib
- *
- * Supports: BGR8,BGR555,BGR24 - only BGR8 and BGR555 tested
- *
+ * @file msrledec.c
+ * MS RLE Decoder based on decoder by Mike Melanson and my own for TSCC
+ * For more information about the MS RLE format, visit:
+ *   http://www.multimedia.cx/msrle.txt
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-
 #include "avcodec.h"
 
-#ifdef CONFIG_ZLIB
-#include <zlib.h>
-#endif
+#define FETCH_NEXT_STREAM_BYTE() \
+    if (stream_ptr >= data_size) \
+    { \
+      av_log(avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (1)\n"); \
+      return -1; \
+    } \
+    stream_byte = data[stream_ptr++];
 
+static int msrle_decode_pal4(AVCodecContext *avctx, AVPicture *pic,
+                              const uint8_t *data, int data_size)
+{
+    int stream_ptr = 0;
+    unsigned char rle_code;
+    unsigned char extra_byte, odd_pixel;
+    unsigned char stream_byte;
+    int pixel_ptr = 0;
+    int row_dec = pic->linesize[0];
+    int row_ptr = (avctx->height - 1) * row_dec;
+    int frame_size = row_dec * avctx->height;
+    int i;
 
-/*
- * Decoder context
- */
-typedef struct TsccContext {
+    while (row_ptr >= 0) {
+        FETCH_NEXT_STREAM_BYTE();
+        rle_code = stream_byte;
+        if (rle_code == 0) {
+            /* fetch the next byte to see how to handle escape code */
+            FETCH_NEXT_STREAM_BYTE();
+            if (stream_byte == 0) {
+                /* line is done, goto the next one */
+                row_ptr -= row_dec;
+                pixel_ptr = 0;
+            } else if (stream_byte == 1) {
+                /* decode is done */
+                return 0;
+            } else if (stream_byte == 2) {
+                /* reposition frame decode coordinates */
+                FETCH_NEXT_STREAM_BYTE();
+                pixel_ptr += stream_byte;
+                FETCH_NEXT_STREAM_BYTE();
+                row_ptr -= stream_byte * row_dec;
+        } else {
+            // copy pixels from encoded stream
+            odd_pixel =  stream_byte & 1;
+            rle_code = (stream_byte + 1) / 2;
+            extra_byte = rle_code & 0x01;
+            if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
+                (row_ptr < 0)) {
+                av_log(avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
+                return -1;
+            }
 
-    AVCodecContext *avctx;
-    AVFrame pic;
+            for (i = 0; i < rle_code; i++) {
+                if (pixel_ptr >= avctx->width)
+                    break;
+                FETCH_NEXT_STREAM_BYTE();
+                pic->data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
+                pixel_ptr++;
+                if (i + 1 == rle_code && odd_pixel)
+                    break;
+                if (pixel_ptr >= avctx->width)
+                    break;
+                pic->data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
+                pixel_ptr++;
+            }
 
-    // Bits per pixel
-    int bpp;
-    // Decompressed data size
-    unsigned int decomp_size;
-    // Decompression buffer
-    unsigned char* decomp_buf;
-    int height;
-#ifdef CONFIG_ZLIB
-    z_stream zstream;
-#endif
-} CamtasiaContext;
+            // if the RLE code is odd, skip a byte in the stream
+            if (extra_byte)
+              stream_ptr++;
+            }
+        } else {
+            // decode a run of data
+            if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
+                (row_ptr < 0)) {
+                av_log(avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
+                return -1;
+            }
+            FETCH_NEXT_STREAM_BYTE();
+            for (i = 0; i < rle_code; i++) {
+                if (pixel_ptr >= avctx->width)
+                    break;
+                if ((i & 1) == 0)
+                    pic->data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
+                else
+                    pic->data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
+                pixel_ptr++;
+            }
+        }
+    }
 
-/*
- *
- * Decode RLE - almost identical to Windows BMP RLE8
- *              and enhanced to bigger color depths
- *
- */
+    /* one last sanity check on the way out */
+    if (stream_ptr < data_size) {
+        av_log(avctx, AV_LOG_ERROR, " MS RLE: ended frame decode with bytes left over (%d < %d)\n",
+            stream_ptr, data_size);
+        return -1;
+    }
 
-static int decode_rle(CamtasiaContext *c, unsigned int srcsize)
+    return 0;
+}
+
+
+static int msrle_decode_8_16_24_32(AVCodecContext *avctx, AVPicture *pic, int depth,
+                                    const uint8_t *data, int srcsize)
 {
-    unsigned char *src = c->decomp_buf;
-    unsigned char *output, *output_end;
-    int p1, p2, line=c->height, pos=0, i;
+    uint8_t *output, *output_end;
+    const uint8_t* src = data;
+    int p1, p2, line=avctx->height, pos=0, i;
     uint16_t pix16;
     uint32_t pix32;
 
-    output = c->pic.data[0] + (c->height - 1) * c->pic.linesize[0];
-    output_end = c->pic.data[0] + (c->height) * c->pic.linesize[0];
-    while(src < c->decomp_buf + srcsize) {
+    output = pic->data[0] + (avctx->height - 1) * pic->linesize[0];
+    output_end = pic->data[0] + (avctx->height) * pic->linesize[0];
+    while(src < data + srcsize) {
         p1 = *src++;
         if(p1 == 0) { //Escape code
             p2 = *src++;
             if(p2 == 0) { //End-of-line
-                output = c->pic.data[0] + (--line) * c->pic.linesize[0];
+                output = pic->data[0] + (--line) * pic->linesize[0];
                 if (line < 0)
                     return -1;
                 pos = 0;
@@ -101,30 +158,30 @@ static int decode_rle(CamtasiaContext *c
                 if (line < 0)
                     return -1;
                 pos += p1;
-                output = c->pic.data[0] + line * c->pic.linesize[0] + pos * (c->bpp / 8);
+                output = pic->data[0] + line * pic->linesize[0] + pos * (depth >> 3);
                 continue;
             }
             // Copy data
-            if (output + p2 * (c->bpp / 8) > output_end) {
-                src += p2 * (c->bpp / 8);
+            if (output + p2 * (depth >> 3) > output_end) {
+                src += p2 * (depth >> 3);
                 continue;
             }
-            if ((c->bpp == 8) || (c->bpp == 24)) {
-                for(i = 0; i < p2 * (c->bpp / 8); i++) {
+            if ((depth == 8) || (depth == 24)) {
+                for(i = 0; i < p2 * (depth >> 3); i++) {
                     *output++ = *src++;
                 }
                 // RLE8 copy is actually padded - and runs are not!
-                if(c->bpp == 8 && (p2 & 1)) {
+                if(depth == 8 && (p2 & 1)) {
                     src++;
                 }
-            } else if (c->bpp == 16) {
+            } else if (depth == 16) {
                 for(i = 0; i < p2; i++) {
                     pix16 = AV_RL16(src);
                     src += 2;
                     *(uint16_t*)output = pix16;
                     output += 2;
                 }
-            } else if (c->bpp == 32) {
+            } else if (depth == 32) {
                 for(i = 0; i < p2; i++) {
                     pix32 = AV_RL32(src);
                     src += 4;
@@ -135,7 +192,7 @@ static int decode_rle(CamtasiaContext *c
             pos += p2;
         } else { //Run of pixels
             int pix[4]; //original pixel
-            switch(c->bpp){
+            switch(depth){
             case  8: pix[0] = *src++;
                      break;
             case 16: pix16 = AV_RL16(src);
@@ -151,10 +208,10 @@ static int decode_rle(CamtasiaContext *c
                      *(uint32_t*)pix = pix32;
                      break;
             }
-            if (output + p1 * (c->bpp / 8) > output_end)
+            if (output + p1 * (depth >> 3) > output_end)
                 continue;
             for(i = 0; i < p1; i++) {
-                switch(c->bpp){
+                switch(depth){
                 case  8: *output++ = pix[0];
                          break;
                 case 16: *(uint16_t*)output = pix16;
@@ -173,174 +230,25 @@ static int decode_rle(CamtasiaContext *c
         }
     }
 
-    av_log(c->avctx, AV_LOG_ERROR, "Camtasia warning: no End-of-picture code\n");
-    return 1;
-}
-
-/*
- *
- * Decode a frame
- *
- */
-static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, const uint8_t *buf, int buf_size)
-{
-    CamtasiaContext * const c = avctx->priv_data;
-    const unsigned char *encoded = buf;
-    unsigned char *outptr;
-#ifdef CONFIG_ZLIB
-    int zret; // Zlib return code
-#endif
-    int len = buf_size;
-
-    if(c->pic.data[0])
-            avctx->release_buffer(avctx, &c->pic);
-
-    c->pic.reference = 1;
-    c->pic.buffer_hints = FF_BUFFER_HINTS_VALID;
-    if(avctx->get_buffer(avctx, &c->pic) < 0){
-        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
-        return -1;
-    }
-
-    outptr = c->pic.data[0]; // Output image pointer
-
-#ifdef CONFIG_ZLIB
-    zret = inflateReset(&(c->zstream));
-    if (zret != Z_OK) {
-        av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret);
-        return -1;
-    }
-    c->zstream.next_in = encoded;
-    c->zstream.avail_in = len;
-    c->zstream.next_out = c->decomp_buf;
-    c->zstream.avail_out = c->decomp_size;
-    zret = inflate(&(c->zstream), Z_FINISH);
-    // Z_DATA_ERROR means empty picture
-    if ((zret != Z_OK) && (zret != Z_STREAM_END) && (zret != Z_DATA_ERROR)) {
-        av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", zret);
-        return -1;
-    }
-
-
-    if(zret != Z_DATA_ERROR)
-        decode_rle(c, c->zstream.avail_out);
-
-    /* make the palette available on the way out */
-    if (c->avctx->pix_fmt == PIX_FMT_PAL8) {
-        memcpy(c->pic.data[1], c->avctx->palctrl->palette, AVPALETTE_SIZE);
-        if (c->avctx->palctrl->palette_changed) {
-            c->pic.palette_has_changed = 1;
-            c->avctx->palctrl->palette_changed = 0;
-        }
-    }
-
-#else
-    av_log(avctx, AV_LOG_ERROR, "BUG! Zlib support not compiled in frame decoder.\n");
-    return -1;
-#endif
-
-    *data_size = sizeof(AVFrame);
-    *(AVFrame*)data = c->pic;
-
-    /* always report that the buffer was completely consumed */
-    return buf_size;
+    av_log(avctx, AV_LOG_WARNING, "MS RLE warning: no End-of-picture code\n");
+    return 0;
 }
 
 
-
-/*
- *
- * Init tscc decoder
- *
- */
-static av_cold int decode_init(AVCodecContext *avctx)
+int ff_msrle_decode(AVCodecContext *avctx, AVPicture *pic, int depth,
+                    const uint8_t* data, int data_size)
 {
-    CamtasiaContext * const c = avctx->priv_data;
-    int zret; // Zlib return code
-
-    c->avctx = avctx;
-
-    c->pic.data[0] = NULL;
-    c->height = avctx->height;
-
-    if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
-        return 1;
-    }
-
-#ifdef CONFIG_ZLIB
-    // Needed if zlib unused or init aborted before inflateInit
-    memset(&(c->zstream), 0, sizeof(z_stream));
-#else
-    av_log(avctx, AV_LOG_ERROR, "Zlib support not compiled.\n");
-    return 1;
-#endif
-    switch(avctx->bits_per_coded_sample){
-    case  8: avctx->pix_fmt = PIX_FMT_PAL8; break;
-    case 16: avctx->pix_fmt = PIX_FMT_RGB555; break;
+    switch(depth){
+    case  4:
+        return msrle_decode_pal4(avctx, pic, data, data_size);
+    case  8:
+    case 16:
     case 24:
-             avctx->pix_fmt = PIX_FMT_BGR24;
-             break;
-    case 32: avctx->pix_fmt = PIX_FMT_RGB32; break;
-    default: av_log(avctx, AV_LOG_ERROR, "Camtasia error: unknown depth %i bpp\n", avctx->bits_per_coded_sample);
-             return -1;
-    }
-    c->bpp = avctx->bits_per_coded_sample;
-    c->decomp_size = (avctx->width * c->bpp + (avctx->width + 254) / 255 + 2) * avctx->height + 2;//RLE in the 'best' case
-
-    /* Allocate decompression buffer */
-    if (c->decomp_size) {
-        if ((c->decomp_buf = av_malloc(c->decomp_size)) == NULL) {
-            av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n");
-            return 1;
-        }
-    }
-
-#ifdef CONFIG_ZLIB
-    c->zstream.zalloc = Z_NULL;
-    c->zstream.zfree = Z_NULL;
-    c->zstream.opaque = Z_NULL;
-    zret = inflateInit(&(c->zstream));
-    if (zret != Z_OK) {
-        av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret);
-        return 1;
+    case 32:
+        return msrle_decode_8_16_24_32(avctx, pic, depth, data, data_size);
+    default:
+        av_log(avctx, AV_LOG_ERROR, "Unknown depth %d\n", depth);
+        return -1;
     }
-#endif
-
-    return 0;
 }
 
-
-
-/*
- *
- * Uninit tscc decoder
- *
- */
-static av_cold int decode_end(AVCodecContext *avctx)
-{
-    CamtasiaContext * const c = avctx->priv_data;
-
-    av_freep(&c->decomp_buf);
-
-    if (c->pic.data[0])
-        avctx->release_buffer(avctx, &c->pic);
-#ifdef CONFIG_ZLIB
-    inflateEnd(&(c->zstream));
-#endif
-
-    return 0;
-}
-
-AVCodec tscc_decoder = {
-        "camtasia",
-        CODEC_TYPE_VIDEO,
-        CODEC_ID_TSCC,
-        sizeof(CamtasiaContext),
-        decode_init,
-        NULL,
-        decode_end,
-        decode_frame,
-        CODEC_CAP_DR1,
-        .long_name = NULL_IF_CONFIG_SMALL("TechSmith Screen Capture Codec"),
-};
-

Added: trunk/libavcodec/msrledec.h
==============================================================================
--- (empty file)
+++ trunk/libavcodec/msrledec.h	Thu Sep 18 07:20:54 2008
@@ -0,0 +1,40 @@
+/*
+ * Micrsoft RLE Decoder
+ * Copyright (C) 2008 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
+ */
+
+#ifndef AVCODEC_MSRLEDEC_H
+#define AVCODEC_MSRLEDEC_H
+
+#include "avcodec.h"
+
+/**
+ * decode stream in MS RLE format into frame
+ *
+ * @param avctx     codec context
+ * @param pic       destination frame
+ * @param depth     bit depth
+ * @param data      input stream
+ * @param data_size input size
+ */
+int ff_msrle_decode(AVCodecContext *avctx, AVPicture *pic, int depth,
+                    const uint8_t* data, int data_size);
+
+#endif /* AVCODEC_MSRLEDEC_H */
+

Modified: trunk/libavcodec/tscc.c
==============================================================================
--- trunk/libavcodec/tscc.c	(original)
+++ trunk/libavcodec/tscc.c	Thu Sep 18 07:20:54 2008
@@ -39,6 +39,7 @@
 #include <stdlib.h>
 
 #include "avcodec.h"
+#include "msrledec.h"
 
 #ifdef CONFIG_ZLIB
 #include <zlib.h>
@@ -67,118 +68,6 @@ typedef struct TsccContext {
 
 /*
  *
- * Decode RLE - almost identical to Windows BMP RLE8
- *              and enhanced to bigger color depths
- *
- */
-
-static int decode_rle(CamtasiaContext *c, unsigned int srcsize)
-{
-    unsigned char *src = c->decomp_buf;
-    unsigned char *output, *output_end;
-    int p1, p2, line=c->height, pos=0, i;
-    uint16_t pix16;
-    uint32_t pix32;
-
-    output = c->pic.data[0] + (c->height - 1) * c->pic.linesize[0];
-    output_end = c->pic.data[0] + (c->height) * c->pic.linesize[0];
-    while(src < c->decomp_buf + srcsize) {
-        p1 = *src++;
-        if(p1 == 0) { //Escape code
-            p2 = *src++;
-            if(p2 == 0) { //End-of-line
-                output = c->pic.data[0] + (--line) * c->pic.linesize[0];
-                if (line < 0)
-                    return -1;
-                pos = 0;
-                continue;
-            } else if(p2 == 1) { //End-of-picture
-                return 0;
-            } else if(p2 == 2) { //Skip
-                p1 = *src++;
-                p2 = *src++;
-                line -= p2;
-                if (line < 0)
-                    return -1;
-                pos += p1;
-                output = c->pic.data[0] + line * c->pic.linesize[0] + pos * (c->bpp / 8);
-                continue;
-            }
-            // Copy data
-            if (output + p2 * (c->bpp / 8) > output_end) {
-                src += p2 * (c->bpp / 8);
-                continue;
-            }
-            if ((c->bpp == 8) || (c->bpp == 24)) {
-                for(i = 0; i < p2 * (c->bpp / 8); i++) {
-                    *output++ = *src++;
-                }
-                // RLE8 copy is actually padded - and runs are not!
-                if(c->bpp == 8 && (p2 & 1)) {
-                    src++;
-                }
-            } else if (c->bpp == 16) {
-                for(i = 0; i < p2; i++) {
-                    pix16 = AV_RL16(src);
-                    src += 2;
-                    *(uint16_t*)output = pix16;
-                    output += 2;
-                }
-            } else if (c->bpp == 32) {
-                for(i = 0; i < p2; i++) {
-                    pix32 = AV_RL32(src);
-                    src += 4;
-                    *(uint32_t*)output = pix32;
-                    output += 4;
-                }
-            }
-            pos += p2;
-        } else { //Run of pixels
-            int pix[4]; //original pixel
-            switch(c->bpp){
-            case  8: pix[0] = *src++;
-                     break;
-            case 16: pix16 = AV_RL16(src);
-                     src += 2;
-                     *(uint16_t*)pix = pix16;
-                     break;
-            case 24: pix[0] = *src++;
-                     pix[1] = *src++;
-                     pix[2] = *src++;
-                     break;
-            case 32: pix32 = AV_RL32(src);
-                     src += 4;
-                     *(uint32_t*)pix = pix32;
-                     break;
-            }
-            if (output + p1 * (c->bpp / 8) > output_end)
-                continue;
-            for(i = 0; i < p1; i++) {
-                switch(c->bpp){
-                case  8: *output++ = pix[0];
-                         break;
-                case 16: *(uint16_t*)output = pix16;
-                         output += 2;
-                         break;
-                case 24: *output++ = pix[0];
-                         *output++ = pix[1];
-                         *output++ = pix[2];
-                         break;
-                case 32: *(uint32_t*)output = pix32;
-                         output += 4;
-                         break;
-                }
-            }
-            pos += p1;
-        }
-    }
-
-    av_log(c->avctx, AV_LOG_ERROR, "Camtasia warning: no End-of-picture code\n");
-    return 1;
-}
-
-/*
- *
  * Decode a frame
  *
  */
@@ -223,7 +112,7 @@ static int decode_frame(AVCodecContext *
 
 
     if(zret != Z_DATA_ERROR)
-        decode_rle(c, c->zstream.avail_out);
+        ff_msrle_decode(avctx, &c->pic, c->bpp, c->decomp_buf, c->zstream.avail_out);
 
     /* make the palette available on the way out */
     if (c->avctx->pix_fmt == PIX_FMT_PAL8) {




More information about the ffmpeg-cvslog mailing list