From 7e2643ae8d04ba6270b25c42f733ba5bfa76174a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reimar=20D=C3=B6ffinger?= Date: Sun, 5 Aug 2007 12:11:09 +0000 Subject: [PATCH] First version of xsub decoder, not yet tested Originally committed as revision 9933 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/allcodecs.h | 1 + libavcodec/avcodec.h | 1 + libavcodec/xsubdec.c | 86 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 90 insertions(+) create mode 100644 libavcodec/xsubdec.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 47bc9c3702..76d12e798b 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -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 diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 6a944e14ae..cb73660d55 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -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); diff --git a/libavcodec/allcodecs.h b/libavcodec/allcodecs.h index 98721ace5c..3b462569a3 100644 --- a/libavcodec/allcodecs.h +++ b/libavcodec/allcodecs.h @@ -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 */ diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 57bffbbda0..80eb3e350f 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -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 index 0000000000..d85e3226de --- /dev/null +++ b/libavcodec/xsubdec.c @@ -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, +};