# HG changeset patch # User reimar # Date 1186315869 0 # Node ID 447409d8770f0bda7429b2f5aa6d51b5ac41d10f # Parent bba203d5c5e7cba541de48789844d8fc29adfb7f First version of xsub decoder, not yet tested diff -r bba203d5c5e7 -r 447409d8770f Makefile --- a/Makefile Sun Aug 05 05:56:34 2007 +0000 +++ b/Makefile Sun Aug 05 12:11:09 2007 +0000 @@ -210,6 +210,7 @@ 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 -r bba203d5c5e7 -r 447409d8770f allcodecs.c --- a/allcodecs.c Sun Aug 05 05:56:34 2007 +0000 +++ b/allcodecs.c Sun Aug 05 12:11:09 2007 +0000 @@ -160,6 +160,7 @@ 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 -r bba203d5c5e7 -r 447409d8770f allcodecs.h --- a/allcodecs.h Sun Aug 05 05:56:34 2007 +0000 +++ b/allcodecs.h Sun Aug 05 12:11:09 2007 +0000 @@ -204,6 +204,7 @@ 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 -r bba203d5c5e7 -r 447409d8770f avcodec.h --- a/avcodec.h Sun Aug 05 05:56:34 2007 +0000 +++ b/avcodec.h Sun Aug 05 12:11:09 2007 +0000 @@ -265,6 +265,7 @@ 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 -r bba203d5c5e7 -r 447409d8770f xsubdec.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xsubdec.c Sun Aug 05 12:11:09 2007 +0000 @@ -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, +};