avcodec/dvdsubdec: reconstruct incomplete SPU packets.

This commit is contained in:
Clément Bœsch 2013-09-29 22:11:51 +02:00
parent 71e0ae22ac
commit 95cafeb684
2 changed files with 50 additions and 0 deletions

View File

@ -35,6 +35,8 @@ typedef struct DVDSubContext
int has_palette;
uint8_t colormap[4];
uint8_t alpha[256];
uint8_t *buf;
int buf_size;
#ifdef DEBUG
int sub_id;
#endif
@ -230,6 +232,9 @@ static int decode_dvd_subtitles(DVDSubContext *ctx, AVSubtitle *sub_header,
cmd_pos = READ_OFFSET(buf + cmd_pos);
if (cmd_pos < 0 || cmd_pos > buf_size - 2 - offset_size)
return AVERROR(EAGAIN);
while (cmd_pos > 0 && cmd_pos < buf_size - 2 - offset_size) {
date = AV_RB16(buf + cmd_pos);
next_cmd_pos = READ_OFFSET(buf + cmd_pos + 2);
@ -485,6 +490,25 @@ static void ppm_save(const char *filename, uint8_t *bitmap, int w, int h,
}
#endif
static int append_to_cached_buf(AVCodecContext *avctx,
const uint8_t *buf, int buf_size)
{
DVDSubContext *ctx = avctx->priv_data;
if (ctx->buf_size > 0xffff - buf_size) {
av_log(avctx, AV_LOG_WARNING, "Attempt to reconstruct "
"too large SPU packets aborted.\n");
av_freep(&ctx->buf);
return AVERROR_INVALIDDATA;
}
ctx->buf = av_realloc(ctx->buf, ctx->buf_size + buf_size);
if (!ctx->buf)
return AVERROR(ENOMEM);
memcpy(ctx->buf + ctx->buf_size, buf, buf_size);
ctx->buf_size += buf_size;
return 0;
}
static int dvdsub_decode(AVCodecContext *avctx,
void *data, int *data_size,
AVPacket *avpkt)
@ -495,7 +519,21 @@ static int dvdsub_decode(AVCodecContext *avctx,
AVSubtitle *sub = data;
int is_menu;
if (ctx->buf) {
int ret = append_to_cached_buf(avctx, buf, buf_size);
if (ret < 0) {
*data_size = 0;
return ret;
}
buf = ctx->buf;
buf_size = ctx->buf_size;
}
is_menu = decode_dvd_subtitles(ctx, sub, buf, buf_size);
if (is_menu == AVERROR(EAGAIN)) {
*data_size = 0;
return append_to_cached_buf(avctx, buf, buf_size);
}
if (is_menu < 0) {
no_subtitle:
@ -519,6 +557,8 @@ static int dvdsub_decode(AVCodecContext *avctx,
}
#endif
av_freep(&ctx->buf);
ctx->buf_size = 0;
*data_size = 1;
return buf_size;
}
@ -592,6 +632,14 @@ static av_cold int dvdsub_init(AVCodecContext *avctx)
return 1;
}
static av_cold int dvdsub_close(AVCodecContext *avctx)
{
DVDSubContext *ctx = avctx->priv_data;
av_freep(&ctx->buf);
ctx->buf_size = 0;
return 0;
}
#define OFFSET(field) offsetof(DVDSubContext, field)
#define VD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM
static const AVOption options[] = {
@ -612,6 +660,7 @@ AVCodec ff_dvdsub_decoder = {
.priv_data_size = sizeof(DVDSubContext),
.init = dvdsub_init,
.decode = dvdsub_decode,
.close = dvdsub_close,
.long_name = NULL_IF_CONFIG_SMALL("DVD subtitles"),
.priv_class = &dvdsub_class,
};

View File

@ -77,6 +77,7 @@
1, 141556, 141556, 1661, 1088, 0xde20aa20, F=0x0
1, 163445, 163445, 1331, 339, 0x8bd186ef, F=0x0
1, 168049, 168049, 1900, 1312, 0x0bf20e8d, F=0x0
1, 170035, 170035, 1524, 1279, 0xb6c2dafe, F=0x0
1, 172203, 172203, 1695, 1826, 0x9a1ac769, F=0x0
1, 173947, 173947, 1934, 1474, 0xa9b03cdc, F=0x0
1, 175957, 175957, 1763, 1019, 0x20409355, F=0x0