diff options
author | Reimar Döffinger <Reimar.Doeffinger@gmx.de> | 2007-08-05 16:11:09 +0400 |
---|---|---|
committer | Reimar Döffinger <Reimar.Doeffinger@gmx.de> | 2007-08-05 16:11:09 +0400 |
commit | 7e2643ae8d04ba6270b25c42f733ba5bfa76174a (patch) | |
tree | cee18405ace22430e13968b409a81206230621df /libavcodec/xsubdec.c | |
parent | 6b05eb31176ff3d0493a08ccb13d7e52736d2045 (diff) |
First version of xsub decoder, not yet tested
Originally committed as revision 9933 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/xsubdec.c')
-rw-r--r-- | libavcodec/xsubdec.c | 86 |
1 files changed, 86 insertions, 0 deletions
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, +}; |