Commit 83cd9112 authored by Mark Goodman's avatar Mark Goodman Committed by Reimar Döffinger

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
parent fb3d8c23
...@@ -54,6 +54,7 @@ typedef struct PGSSubPicture { ...@@ -54,6 +54,7 @@ typedef struct PGSSubPicture {
int h; int h;
uint8_t *rle; uint8_t *rle;
unsigned int rle_buffer_size, rle_data_len; unsigned int rle_buffer_size, rle_data_len;
unsigned int rle_remaining_len;
} PGSSubPicture; } PGSSubPicture;
typedef struct PGSSubContext { typedef struct PGSSubContext {
...@@ -159,6 +160,10 @@ static int parse_picture_segment(AVCodecContext *avctx, ...@@ -159,6 +160,10 @@ static int parse_picture_segment(AVCodecContext *avctx,
uint8_t sequence_desc; uint8_t sequence_desc;
unsigned int rle_bitmap_len, width, height; 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 */ /* skip 3 unknown bytes: Object ID (2 bytes), Version Number */
buf += 3; buf += 3;
...@@ -166,20 +171,22 @@ static int parse_picture_segment(AVCodecContext *avctx, ...@@ -166,20 +171,22 @@ static int parse_picture_segment(AVCodecContext *avctx,
sequence_desc = bytestream_get_byte(&buf); sequence_desc = bytestream_get_byte(&buf);
if (!(sequence_desc & 0x80)) { if (!(sequence_desc & 0x80)) {
av_log(avctx, AV_LOG_ERROR, "Decoder does not support object data over multiple packets.\n"); /* Additional RLE data */
return -1; if (buf_size > ctx->picture.rle_remaining_len)
} return -1;
/* Decode rle bitmap length */ memcpy(ctx->picture.rle + ctx->picture.rle_data_len, buf, buf_size);
rle_bitmap_len = bytestream_get_be24(&buf); ctx->picture.rle_data_len += buf_size;
/* Check to ensure we have enough data for rle_bitmap_length if just a single packet */ return 0;
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;
} }
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 */ /* Get bitmap dimensions from data */
width = bytestream_get_be16(&buf); width = bytestream_get_be16(&buf);
...@@ -199,7 +206,9 @@ static int parse_picture_segment(AVCodecContext *avctx, ...@@ -199,7 +206,9 @@ static int parse_picture_segment(AVCodecContext *avctx,
if (!ctx->picture.rle) if (!ctx->picture.rle)
return -1; 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; return 0;
} }
...@@ -364,10 +373,13 @@ static int display_end_segment(AVCodecContext *avctx, void *data, ...@@ -364,10 +373,13 @@ static int display_end_segment(AVCodecContext *avctx, void *data,
/* Process bitmap */ /* Process bitmap */
sub->rects[0]->pict.linesize[0] = ctx->picture.w; 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) if(decode_rle(avctx, sub, ctx->picture.rle, ctx->picture.rle_data_len) < 0)
return 0; return 0;
}
/* Allocate memory for colors */ /* Allocate memory for colors */
sub->rects[0]->nb_colors = 256; sub->rects[0]->nb_colors = 256;
sub->rects[0]->pict.data[1] = av_mallocz(AVPALETTE_SIZE); sub->rects[0]->pict.data[1] = av_mallocz(AVPALETTE_SIZE);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment