diff --git a/libavcodec/assdec.c b/libavcodec/assdec.c index 5a51703e86..d79065663b 100644 --- a/libavcodec/assdec.c +++ b/libavcodec/assdec.c @@ -29,10 +29,11 @@ static av_cold int ass_decode_init(AVCodecContext *avctx) { - avctx->subtitle_header = av_malloc(avctx->extradata_size); + avctx->subtitle_header = av_malloc(avctx->extradata_size + 1); if (!avctx->subtitle_header) return AVERROR(ENOMEM); memcpy(avctx->subtitle_header, avctx->extradata, avctx->extradata_size); + avctx->subtitle_header[avctx->extradata_size] = 0; avctx->subtitle_header_size = avctx->extradata_size; avctx->priv_data = ff_ass_split(avctx->extradata); if(!avctx->priv_data) diff --git a/libavcodec/assenc.c b/libavcodec/assenc.c index 7ed21eedbc..50b89c00d6 100644 --- a/libavcodec/assenc.c +++ b/libavcodec/assenc.c @@ -28,11 +28,12 @@ static av_cold int ass_encode_init(AVCodecContext *avctx) { - avctx->extradata = av_malloc(avctx->subtitle_header_size); + avctx->extradata = av_malloc(avctx->subtitle_header_size + 1); if (!avctx->extradata) return AVERROR(ENOMEM); memcpy(avctx->extradata, avctx->subtitle_header, avctx->subtitle_header_size); avctx->extradata_size = avctx->subtitle_header_size; + avctx->extradata[avctx->extradata_size] = 0; return 0; } diff --git a/libavcodec/dvdsubenc.c b/libavcodec/dvdsubenc.c index 2e0c37da4d..352272d311 100644 --- a/libavcodec/dvdsubenc.c +++ b/libavcodec/dvdsubenc.c @@ -20,6 +20,7 @@ */ #include "avcodec.h" #include "bytestream.h" +#include "internal.h" #include "libavutil/avassert.h" #include "libavutil/bprint.h" #include "libavutil/imgutils.h" @@ -408,9 +409,9 @@ static int dvdsub_init(AVCodecContext *avctx) av_bprintf(&extradata, " %06"PRIx32"%c", dvdc->global_palette[i] & 0xFFFFFF, i < 15 ? ',' : '\n'); - if ((ret = av_bprint_finalize(&extradata, (char **)&avctx->extradata)) < 0) + ret = ff_bprint_to_extradata(avctx, &extradata); + if (ret < 0) return ret; - avctx->extradata_size = extradata.len; return 0; } diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 2d3433f434..386f6f3c26 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -201,4 +201,9 @@ int ff_codec_open2_recursive(AVCodecContext *avctx, const AVCodec *codec, AVDict */ int ff_codec_close_recursive(AVCodecContext *avctx); +/** + * Finalize buf into extradata and set its size appropriately. + */ +int ff_bprint_to_extradata(AVCodecContext *avctx, struct AVBPrint *buf); + #endif /* AVCODEC_INTERNAL_H */ diff --git a/libavcodec/utils.c b/libavcodec/utils.c index b3669950d5..a275899ff7 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -27,6 +27,7 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" +#include "libavutil/bprint.h" #include "libavutil/channel_layout.h" #include "libavutil/crc.h" #include "libavutil/mathematics.h" @@ -2684,3 +2685,21 @@ int avcodec_is_open(AVCodecContext *s) { return !!s->internal; } + +int ff_bprint_to_extradata(AVCodecContext *avctx, struct AVBPrint *buf) +{ + int ret; + char *str; + + ret = av_bprint_finalize(buf, &str); + if (ret < 0) + return ret; + avctx->extradata = str; + /* Note: the string is NUL terminated (so extradata can be read as a + * string), but the ending character is not accounted in the size (in + * binary formats you are likely not supposed to mux that character). When + * extradata is copied, it is also padded with FF_INPUT_BUFFER_PADDING_SIZE + * zeros. */ + avctx->extradata_size = buf->len; + return 0; +} diff --git a/libavformat/assdec.c b/libavformat/assdec.c index 6c4614ec47..34229cb6f9 100644 --- a/libavformat/assdec.c +++ b/libavformat/assdec.c @@ -22,6 +22,7 @@ #include "avformat.h" #include "internal.h" #include "subtitles.h" +#include "libavcodec/internal.h" #include "libavutil/bprint.h" typedef struct ASSContext{ @@ -132,12 +133,9 @@ static int ass_read_header(AVFormatContext *s) av_bprint_finalize(&line, NULL); - av_bprint_finalize(&header, (char **)&st->codec->extradata); - if (!st->codec->extradata) { - res = AVERROR(ENOMEM); + res = ff_bprint_to_extradata(st->codec, &header); + if (res < 0) goto end; - } - st->codec->extradata_size = header.len + 1; ff_subtitles_queue_finalize(&ass->q); diff --git a/libavformat/jacosubdec.c b/libavformat/jacosubdec.c index 1c58e3bf25..153da4247a 100644 --- a/libavformat/jacosubdec.c +++ b/libavformat/jacosubdec.c @@ -28,6 +28,7 @@ #include "avformat.h" #include "internal.h" #include "subtitles.h" +#include "libavcodec/internal.h" #include "libavcodec/jacosub.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" @@ -159,7 +160,7 @@ static int jacosub_read_header(AVFormatContext *s) JACOsubContext *jacosub = s->priv_data; int shift_set = 0; // only the first shift matters int merge_line = 0; - int i; + int i, ret; AVStream *st = avformat_new_stream(s, NULL); if (!st) @@ -228,8 +229,9 @@ static int jacosub_read_header(AVFormatContext *s) } /* general/essential directives in the extradata */ - av_bprint_finalize(&header, (char **)&st->codec->extradata); - st->codec->extradata_size = header.len + 1; + ret = ff_bprint_to_extradata(st->codec, &header); + if (ret < 0) + return ret; /* SHIFT and TIMERES affect the whole script so packet timing can only be * done in a second pass */ diff --git a/libavformat/samidec.c b/libavformat/samidec.c index 85fd220f4a..bdde2f466f 100644 --- a/libavformat/samidec.c +++ b/libavformat/samidec.c @@ -27,6 +27,7 @@ #include "avformat.h" #include "internal.h" #include "subtitles.h" +#include "libavcodec/internal.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" #include "libavutil/intreadwrite.h" @@ -91,13 +92,9 @@ static int sami_read_header(AVFormatContext *s) av_bprint_clear(&buf); } - st->codec->extradata_size = hdr_buf.len + 1; - av_bprint_finalize(&hdr_buf, (char **)&st->codec->extradata); - if (!st->codec->extradata) { - st->codec->extradata_size = 0; - res = AVERROR(ENOMEM); + res = ff_bprint_to_extradata(st->codec, &hdr_buf); + if (res < 0) goto end; - } ff_subtitles_queue_finalize(&sami->q); diff --git a/libavformat/subviewerdec.c b/libavformat/subviewerdec.c index 7691d82768..8ecc928817 100644 --- a/libavformat/subviewerdec.c +++ b/libavformat/subviewerdec.c @@ -27,6 +27,7 @@ #include "avformat.h" #include "internal.h" #include "subtitles.h" +#include "libavcodec/internal.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" #include "libavutil/intreadwrite.h" @@ -99,12 +100,9 @@ static int subviewer_read_header(AVFormatContext *s) av_bprintf(&header, "%s", line); if (!strncmp(line, "[END INFORMATION]", 17) || !strncmp(line, "[SUBTITLE]", 10)) { /* end of header */ - av_bprint_finalize(&header, (char **)&st->codec->extradata); - if (!st->codec->extradata) { - res = AVERROR(ENOMEM); + res = ff_bprint_to_extradata(st->codec, &header); + if (res < 0) goto end; - } - st->codec->extradata_size = header.len + 1; } else if (strncmp(line, "[INFORMATION]", 13)) { /* assume file metadata at this point */ int i, j = 0;