mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-21 10:55:51 +02:00
avcodec/dvdsubdec: reconstruct incomplete SPU packets.
This commit is contained in:
parent
71e0ae22ac
commit
95cafeb684
@ -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,
|
||||
};
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user