First version of xsub decoder, not yet tested
authorReimar Döffinger <Reimar.Doeffinger@gmx.de>
Sun, 5 Aug 2007 12:11:09 +0000 (12:11 +0000)
committerReimar Döffinger <Reimar.Doeffinger@gmx.de>
Sun, 5 Aug 2007 12:11:09 +0000 (12:11 +0000)
Originally committed as revision 9933 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavcodec/Makefile
libavcodec/allcodecs.c
libavcodec/allcodecs.h
libavcodec/avcodec.h
libavcodec/xsubdec.c [new file with mode: 0644]

index 47bc9c3..76d12e7 100644 (file)
@@ -210,6 +210,7 @@ OBJS-$(CONFIG_XAN_DPCM_DECODER)        += dpcm.o
 OBJS-$(CONFIG_XAN_WC3_DECODER)         += xan.o
 OBJS-$(CONFIG_XAN_WC4_DECODER)         += xan.o
 OBJS-$(CONFIG_XL_DECODER)              += xl.o
+OBJS-$(CONFIG_XSUB_DECODER)            += xsubdec.o
 OBJS-$(CONFIG_ZLIB_DECODER)            += lcldec.o
 OBJS-$(CONFIG_ZLIB_ENCODER)            += lclenc.o
 OBJS-$(CONFIG_ZMBV_DECODER)            += zmbv.o
index 6a944e1..cb73660 100644 (file)
@@ -160,6 +160,7 @@ void avcodec_register_all(void)
     REGISTER_DECODER(WNV1, wnv1);
     REGISTER_DECODER(XAN_WC3, xan_wc3);
     REGISTER_DECODER(XL, xl);
+    REGISTER_DECODER(XSUB, xsub);
     REGISTER_ENCDEC (ZLIB, zlib);
     REGISTER_ENCDEC (ZMBV, zmbv);
 
index 98721ac..3b46256 100644 (file)
@@ -204,6 +204,7 @@ extern AVCodec ws_snd1_decoder;
 extern AVCodec xan_dpcm_decoder;
 extern AVCodec xan_wc3_decoder;
 extern AVCodec xl_decoder;
+extern AVCodec xsub_decoder;
 extern AVCodec zmbv_decoder;
 
 /* PCM codecs */
index 57bffbb..80eb3e3 100644 (file)
@@ -265,6 +265,7 @@ enum CodecID {
     CODEC_ID_DVD_SUBTITLE= 0x17000,
     CODEC_ID_DVB_SUBTITLE,
     CODEC_ID_TEXT,  /* raw UTF-8 text */
+    CODEC_ID_XSUB,
 
     CODEC_ID_MPEG2TS= 0x20000, /* _FAKE_ codec to indicate a raw MPEG-2 TS
                                 * stream (only used by libavformat) */
diff --git a/libavcodec/xsubdec.c b/libavcodec/xsubdec.c
new file mode 100644 (file)
index 0000000..d85e322
--- /dev/null
@@ -0,0 +1,86 @@
+#include "avcodec.h"
+#include "bitstream.h"
+#include "bytestream.h"
+
+static int decode_init(AVCodecContext *avctx) {
+    avctx->pix_fmt = PIX_FMT_PAL8;
+    return 0;
+}
+
+static const uint8_t runbits[8] = { 2, 2, 6, 6, 10, 10, 14, 14 };
+
+static int decode_frame(AVCodecContext *avctx, void *data, int *data_size,
+                        uint8_t *buf, int buf_size) {
+    AVSubtitle *sub = data;
+    uint8_t *buf_end = buf + buf_size;
+    uint8_t *bitmap;
+    int w, h, x, y, rlelen, i;
+    GetBitContext gb;
+
+    // check that at least header fits
+    if (buf_size < 27 + 7 * 2 + 4 * 3) {
+        av_log(avctx, AV_LOG_ERROR, "coded frame too small\n");
+        return -1;
+    }
+
+    // read header
+    w = bytestream_get_le16(&buf);
+    h = bytestream_get_le16(&buf);
+    if (avcodec_check_dimensions(avctx, w, h) < 0)
+        return -1;
+    x = bytestream_get_le16(&buf);
+    y = bytestream_get_le16(&buf);
+    // skip bottom right position, it gives no new information
+    bytestream_get_le16(&buf);
+    bytestream_get_le16(&buf);
+    rlelen = bytestream_get_le16(&buf);
+
+    // allocate sub and set values
+    if (!sub->rects) {
+        sub->rects = av_mallocz(sizeof(AVSubtitleRect));
+        sub->num_rects = 1;
+    }
+    av_freep(sub->rects[0].bitmap);
+    sub->rects[0].x = x; sub->rects[0].y = y;
+    sub->rects[0].w = w; sub->rects[0].h = h;
+    sub->rects[0].linesize = w;
+    sub->rects[0].bitmap = av_malloc(w * h);
+    sub->rects[0].nb_colors = 4;
+    sub->rects[0].rgba_palette = av_malloc(sub->rects[0].nb_colors * 4);
+
+    // read palette
+    for (i = 0; i < sub->rects[0].nb_colors; i++)
+        sub->rects[0].rgba_palette[i] = bytestream_get_be24(&buf);
+
+    // process RLE-compressed data
+    rlelen = FFMIN(rlelen, buf_end - buf);
+    init_get_bits(&gb, buf, rlelen * 8);
+    bitmap = sub->rects[0].bitmap;
+    for (y = 0; y < h; y++) {
+        for (x = 0; x < w; ) {
+            int log2 = ff_log2_tab[show_bits(&gb, 8)];
+            int run = get_bits(&gb, runbits[log2]);
+            int colour = get_bits(&gb, 2);
+            run = FFMIN(run, w - x);
+            // run length 0 means till end of row
+            if (!run) run = w - x;
+            memset(bitmap, colour, run);
+            bitmap += run;
+            x += run;
+        }
+        align_get_bits(&gb);
+    }
+    *data_size = 1;
+    return buf_size;
+}
+
+AVCodec xsub_decoder = {
+    "xsub",
+    CODEC_TYPE_SUBTITLE,
+    CODEC_ID_XSUB,
+    0,
+    decode_init,
+    NULL,
+    NULL,
+    decode_frame,
+};