8BPS decoder
authorRoberto Togni <r_togni@tiscali.it>
Fri, 7 Nov 2003 22:39:18 +0000 (22:39 +0000)
committerRoberto Togni <r_togni@tiscali.it>
Fri, 7 Nov 2003 22:39:18 +0000 (22:39 +0000)
Originally committed as revision 2486 to svn://svn.ffmpeg.org/ffmpeg/trunk

doc/ffmpeg-doc.texi
libavcodec/8bps.c [new file with mode: 0644]
libavcodec/Makefile
libavcodec/allcodecs.c
libavcodec/avcodec.h
libavformat/mov.c

index 4633613..2532709 100644 (file)
@@ -701,6 +701,7 @@ following image formats are supported:
 @item Microsoft Video-1      @tab     @tab  X
 @item Westwood VQA           @tab     @tab  X
 @item Id Cinematic Video     @tab     @tab  X @tab used in Quake II
+@item Planar RGB             @tab     @tab  X @tab fourcc: 8BPS
 @end multitable
 
 @code{X} means that the encoding (resp. decoding) is supported.
diff --git a/libavcodec/8bps.c b/libavcodec/8bps.c
new file mode 100644 (file)
index 0000000..9509f42
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * Quicktime Planar RGB (8BPS) Video Decoder
+ * Copyright (C) 2003 Roberto Togni
+ *
+ * This library 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 of the License, or (at your option) any later version.
+ *
+ * This library 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/**
+ * @file 8bps.c
+ * QT 8BPS Video Decoder by Roberto Togni <rtogni at bresciaonline dot it>
+ * For more information about the 8BPS format, visit:
+ *   http://www.pcisys.net/~melanson/codecs/
+ *
+ * Supports: PAL8 (RGB 8bpp, paletted)
+ *         : BGR24 (RGB 24bpp) (can also output it as RGBA32)
+ *         : RGBA32 (RGB 32bpp, 4th plane is probably alpha and it's ignored)
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "common.h"
+#include "avcodec.h"
+
+
+const enum PixelFormat pixfmt_rgb24[] = {PIX_FMT_BGR24, PIX_FMT_RGBA32, -1};
+
+/*
+ * Decoder context
+ */
+typedef struct EightBpsContext {
+
+       AVCodecContext *avctx;
+       AVFrame pic;
+
+       unsigned char planes;
+       unsigned char planemap[4];
+} EightBpsContext;
+
+
+/*
+ *
+ * Decode a frame
+ *
+ */
+static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size)
+{
+       EightBpsContext * const c = (EightBpsContext *)avctx->priv_data;
+       unsigned char *encoded = (unsigned char *)buf;
+       unsigned char *pixptr;
+       unsigned int height = avctx->height; // Real image height
+       unsigned int dlen, p, row;
+       unsigned char *lp, *dp;
+       unsigned char count;
+       unsigned int px_inc;
+       unsigned int planes = c->planes;
+       unsigned char *planemap = c->planemap;
+  
+  
+       /* no supplementary picture */
+       if (buf_size == 0)
+               return 0;
+
+       if(c->pic.data[0])
+               avctx->release_buffer(avctx, &c->pic);
+
+       c->pic.reference = 0;
+       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;
+       }
+
+       /* Set data pointer after line lengths */
+       dp = encoded + planes * (height << 1);
+
+       /* Ignore alpha plane, don't know what to do with it */
+       if (planes == 4)
+               planes--;
+
+       px_inc = planes + (avctx->pix_fmt == PIX_FMT_RGBA32);
+
+       for (p = 0; p < planes; p++) {
+               /* Lines length pointer for this plane */
+               lp = encoded + p * (height << 1);
+
+               /* Decode a plane */
+               for(row = 0; row < height; row++) {
+                       pixptr = c->pic.data[0] + row * c->pic.linesize[0] + planemap[p];
+                       dlen = be2me_16(*(unsigned short *)(lp+row*2));
+                       /* Decode a row of this plane */
+                       while(dlen > 0) {
+                               if ((count = *dp++) <= 127) {
+                                       count++;
+                                       dlen -= count + 1;
+                                       while(count--) {
+                                               *pixptr = *dp++;
+                                               pixptr += px_inc;
+                                       }
+                               } else {
+                                       count = 257 - count;
+                                       while(count--) {
+                                               *pixptr = *dp;
+                                               pixptr += px_inc;
+                                       }
+                                       dp++;
+                                       dlen -= 2;
+                               }
+                       }
+               }
+       }
+
+       if (avctx->palctrl) {
+               memcpy (c->pic.data[1], avctx->palctrl->palette, AVPALETTE_SIZE);
+               if (avctx->palctrl->palette_changed) {
+                       c->pic.palette_has_changed = 1;
+                       avctx->palctrl->palette_changed = 0;
+               } else
+                       c->pic.palette_has_changed = 0;
+       }
+
+       *data_size = sizeof(AVFrame);
+       *(AVFrame*)data = c->pic;
+
+       /* always report that the buffer was completely consumed */
+       return buf_size;
+}
+
+
+/*
+ *
+ * Init 8BPS decoder
+ *
+ */
+static int decode_init(AVCodecContext *avctx)
+{
+       EightBpsContext * const c = (EightBpsContext *)avctx->priv_data;
+
+       c->avctx = avctx;
+       avctx->has_b_frames = 0;
+
+       c->pic.data[0] = NULL;
+
+       switch (avctx->bits_per_sample) {
+               case 8:
+                       avctx->pix_fmt = PIX_FMT_PAL8;
+                       c->planes = 1;
+                       c->planemap[0] = 0; // 1st plane is palette indexes
+                       if (avctx->palctrl == NULL) {
+                               av_log(avctx, AV_LOG_ERROR, "Error: PAL8 format but no palette from demuxer.\n");
+                               return -1;
+                       }
+                       break;
+               case 24:
+                       avctx->pix_fmt = avctx->get_format(avctx, pixfmt_rgb24);
+                       c->planes = 3;
+                       c->planemap[0] = 2; // 1st plane is red
+                       c->planemap[1] = 1; // 2nd plane is green
+                       c->planemap[2] = 0; // 3rd plane is blue
+                       break;
+               case 32:
+                       avctx->pix_fmt = PIX_FMT_RGBA32;
+                       c->planes = 4;
+#ifdef WORDS_BIGENDIAN
+                       c->planemap[0] = 1; // 1st plane is red
+                       c->planemap[1] = 2; // 2nd plane is green
+                       c->planemap[2] = 3; // 3rd plane is blue
+                       c->planemap[3] = 0; // 4th plane is alpha???
+#else
+                       c->planemap[0] = 2; // 1st plane is red
+                       c->planemap[1] = 1; // 2nd plane is green
+                       c->planemap[2] = 0; // 3rd plane is blue
+                       c->planemap[3] = 3; // 4th plane is alpha???
+#endif
+                       break;
+               default:
+                       av_log(avctx, AV_LOG_ERROR, "Error: Unsupported color depth: %u.\n", avctx->bits_per_sample);
+                       return -1;
+       }
+
+  return 0;
+}
+
+
+
+
+/*
+ *
+ * Uninit 8BPS decoder
+ *
+ */
+static int decode_end(AVCodecContext *avctx)
+{
+       EightBpsContext * const c = (EightBpsContext *)avctx->priv_data;
+
+       if (c->pic.data[0])
+               avctx->release_buffer(avctx, &c->pic);
+
+       return 0;
+}
+
+
+
+AVCodec eightbps_decoder = {
+       "8bps",
+       CODEC_TYPE_VIDEO,
+       CODEC_ID_8BPS,
+       sizeof(EightBpsContext),
+       decode_init,
+       NULL,
+       decode_end,
+       decode_frame,
+       CODEC_CAP_DR1,
+};
index dc916da..6ede870 100644 (file)
@@ -18,7 +18,7 @@ OBJS= common.o utils.o mem.o allcodecs.o \
       fft.o mdct.o mace.o huffyuv.o cyuv.o opts.o raw.o h264.o golomb.o \
       vp3.o asv1.o 4xm.o cabac.o ffv1.o ra144.o ra288.o vcr1.o cljr.o \
       roqvideo.o dpcm.o interplayvideo.o xan.o rpza.o cinepak.o msrle.o \
-      msvideo1.o vqavideo.o idcinvideo.o adx.o rational.o faandct.o
+      msvideo1.o vqavideo.o idcinvideo.o adx.o rational.o faandct.o 8bps.o
 
 ifeq ($(AMR_NB),yes)
 ifeq ($(AMR_NB_FIXED),yes)
index 2626f94..ac0446a 100644 (file)
@@ -134,6 +134,7 @@ void avcodec_register_all(void)
     register_avcodec(&msvideo1_decoder);
     register_avcodec(&vqa_decoder);
     register_avcodec(&idcin_decoder);
+    register_avcodec(&eightbps_decoder);
 #ifdef CONFIG_AC3
     register_avcodec(&ac3_decoder);
 #endif
index 499633a..f7ae388 100644 (file)
@@ -83,6 +83,7 @@ enum CodecID {
     CODEC_ID_MSRLE,
     CODEC_ID_MSVIDEO1,
     CODEC_ID_IDCIN,
+    CODEC_ID_8BPS,
 
     /* various pcm "codecs" */
     CODEC_ID_PCM_S16LE,
@@ -1566,6 +1567,7 @@ extern AVCodec msrle_decoder;
 extern AVCodec msvideo1_decoder;
 extern AVCodec vqa_decoder;
 extern AVCodec idcin_decoder;
+extern AVCodec eightbps_decoder;
 extern AVCodec ra_144_decoder;
 extern AVCodec ra_288_decoder;
 extern AVCodec roq_dpcm_decoder;
index ef79808..ee4c057 100644 (file)
@@ -101,6 +101,7 @@ static const CodecTag mov_video_tags[] = {
     { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') }, /* On2 VP3 */
     { CODEC_ID_RPZA, MKTAG('r', 'p', 'z', 'a') }, /* Apple Video (RPZA) */
     { CODEC_ID_CINEPAK, MKTAG('c', 'v', 'i', 'd') }, /* Cinepak */
+    { CODEC_ID_8BPS, MKTAG('8', 'B', 'P', 'S') }, /* Planar RGB (8BPS) */
     { CODEC_ID_NONE, 0 },
 };