diff options
author | Mark Goodman <mark.goodman@gmail.com> | 2010-11-22 20:35:07 +0000 |
---|---|---|
committer | Reimar Döffinger <Reimar.Doeffinger@gmx.de> | 2010-11-22 20:35:07 +0000 |
commit | 83cd91122a8d8e4a13bddc82b74054a0978be24f (patch) | |
tree | 24e224bf3cf1e2925bee5071b6f820e679fd32ba | |
parent | fb3d8c23cc20efac83a66120821fc91697b52a0c (diff) | |
download | ffmpeg-83cd91122a8d8e4a13bddc82b74054a0978be24f.tar.gz |
Support PGS subtitles with RLE data split over mutiple packets.
Patch by Mark Goodman [mark goodman gmail com] with some modifications by me.
Originally committed as revision 25796 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r-- | libavcodec/pgssubdec.c | 38 |
1 files changed, 25 insertions, 13 deletions
diff --git a/libavcodec/pgssubdec.c b/libavcodec/pgssubdec.c index 50be170d87..197582f285 100644 --- a/libavcodec/pgssubdec.c +++ b/libavcodec/pgssubdec.c @@ -54,6 +54,7 @@ typedef struct PGSSubPicture { int h; uint8_t *rle; unsigned int rle_buffer_size, rle_data_len; + unsigned int rle_remaining_len; } PGSSubPicture; typedef struct PGSSubContext { @@ -159,6 +160,10 @@ static int parse_picture_segment(AVCodecContext *avctx, uint8_t sequence_desc; unsigned int rle_bitmap_len, width, height; + if (buf_size <= 4) + return -1; + buf_size -= 4; + /* skip 3 unknown bytes: Object ID (2 bytes), Version Number */ buf += 3; @@ -166,20 +171,22 @@ static int parse_picture_segment(AVCodecContext *avctx, sequence_desc = bytestream_get_byte(&buf); if (!(sequence_desc & 0x80)) { - av_log(avctx, AV_LOG_ERROR, "Decoder does not support object data over multiple packets.\n"); - return -1; - } + /* Additional RLE data */ + if (buf_size > ctx->picture.rle_remaining_len) + return -1; - /* Decode rle bitmap length */ - rle_bitmap_len = bytestream_get_be24(&buf); + memcpy(ctx->picture.rle + ctx->picture.rle_data_len, buf, buf_size); + ctx->picture.rle_data_len += buf_size; - /* Check to ensure we have enough data for rle_bitmap_length if just a single packet */ - if (rle_bitmap_len > buf_size - 7) { - av_log(avctx, AV_LOG_ERROR, "Not enough RLE data for specified length of %d.\n", rle_bitmap_len); - return -1; + return 0; } - ctx->picture.rle_data_len = rle_bitmap_len; + if (buf_size <= 7) + return -1; + buf_size -= 7; + + /* Decode rle bitmap length, stored size includes width/height data */ + rle_bitmap_len = bytestream_get_be24(&buf) - 2*2; /* Get bitmap dimensions from data */ width = bytestream_get_be16(&buf); @@ -199,7 +206,9 @@ static int parse_picture_segment(AVCodecContext *avctx, if (!ctx->picture.rle) return -1; - memcpy(ctx->picture.rle, buf, rle_bitmap_len); + memcpy(ctx->picture.rle, buf, buf_size); + ctx->picture.rle_data_len = buf_size; + ctx->picture.rle_remaining_len = rle_bitmap_len - buf_size; return 0; } @@ -364,10 +373,13 @@ static int display_end_segment(AVCodecContext *avctx, void *data, /* Process bitmap */ sub->rects[0]->pict.linesize[0] = ctx->picture.w; - if (ctx->picture.rle) + if (ctx->picture.rle) { + if (ctx->picture.rle_remaining_len) + av_log(avctx, AV_LOG_ERROR, "RLE data length %u is %u bytes shorter than expected\n", + ctx->picture.rle_data_len, ctx->picture.rle_remaining_len); if(decode_rle(avctx, sub, ctx->picture.rle, ctx->picture.rle_data_len) < 0) return 0; - + } /* Allocate memory for colors */ sub->rects[0]->nb_colors = 256; sub->rects[0]->pict.data[1] = av_mallocz(AVPALETTE_SIZE); |