summaryrefslogtreecommitdiff
path: root/libavcodec/pgssubdec.c
diff options
context:
space:
mode:
authorMark Goodman <mark.goodman@gmail.com>2010-11-22 20:35:07 +0000
committerReimar Döffinger <Reimar.Doeffinger@gmx.de>2010-11-22 20:35:07 +0000
commit83cd91122a8d8e4a13bddc82b74054a0978be24f (patch)
tree24e224bf3cf1e2925bee5071b6f820e679fd32ba /libavcodec/pgssubdec.c
parentfb3d8c23cc20efac83a66120821fc91697b52a0c (diff)
downloadffmpeg-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
Diffstat (limited to 'libavcodec/pgssubdec.c')
-rw-r--r--libavcodec/pgssubdec.c38
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);