From 0c1959b056f6ccaa2eee2c824352ba93c8e36d52 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 1 May 2014 10:43:10 +0200 Subject: lavf: add AVFMT_FLAG_BITEXACT. Use it instead of checking CODEC_FLAG_BITEXACT in the first stream's codec context. Using codec options inside lavf is fragile and can easily break when the muxing codec context is not the encoding context. --- libavformat/avformat.h | 7 +++++++ libavformat/flacenc.c | 2 +- libavformat/matroskaenc.c | 2 +- libavformat/movenc.c | 2 +- libavformat/mux.c | 7 ++++++- libavformat/mxfenc.c | 4 ++-- libavformat/oggenc.c | 10 +++++----- libavformat/options_table.h | 1 + libavformat/version.h | 5 ++++- 9 files changed, 28 insertions(+), 12 deletions(-) (limited to 'libavformat') diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 1ce3eba675..8d134a0945 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1004,6 +1004,13 @@ typedef struct AVFormatContext { #define AVFMT_FLAG_CUSTOM_IO 0x0080 ///< The caller has supplied a custom AVIOContext, don't avio_close() it. #define AVFMT_FLAG_DISCARD_CORRUPT 0x0100 ///< Discard frames marked corrupted #define AVFMT_FLAG_FLUSH_PACKETS 0x0200 ///< Flush the AVIOContext every packet. +/** + * When muxing, try to avoid writing any random/volatile data to the output. + * This includes any random IDs, real-time timestamps/dates, muxer version, etc. + * + * This flag is mainly intended for testing. + */ +#define AVFMT_FLAG_BITEXACT 0x0400 /** * Maximum size of the data read from input for determining diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c index 83ddf441e0..8a23163772 100644 --- a/libavformat/flacenc.c +++ b/libavformat/flacenc.c @@ -84,7 +84,7 @@ static int flac_write_header(struct AVFormatContext *s) return ret; ret = flac_write_block_comment(s->pb, &s->metadata, 0, - codec->flags & CODEC_FLAG_BITEXACT); + s->flags & AVFMT_FLAG_BITEXACT); if (ret) return ret; diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index d2e3ae4979..c71b32d411 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -970,7 +970,7 @@ static int mkv_write_header(AVFormatContext *s) put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000); if ((tag = av_dict_get(s->metadata, "title", NULL, 0))) put_ebml_string(pb, MATROSKA_ID_TITLE, tag->value); - if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) { + if (!(s->flags & AVFMT_FLAG_BITEXACT)) { uint32_t segment_uid[4]; AVLFG lfg; diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 73fbddc451..9087438998 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -2024,7 +2024,7 @@ static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov, uint8_t *buf; for (i = 0; i < s->nb_streams; i++) - if (mov->tracks[i].enc->flags & CODEC_FLAG_BITEXACT) { + if (s->flags & AVFMT_FLAG_BITEXACT) { return 0; } diff --git a/libavformat/mux.c b/libavformat/mux.c index 59f9c42cf1..33257ea147 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -149,6 +149,11 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) if ((ret = av_opt_set_dict(s, &tmp)) < 0) goto fail; +#if FF_API_LAVF_BITEXACT + if (s->nb_streams && s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT) + s->flags |= AVFMT_FLAG_BITEXACT; +#endif + // some sanity checks if (s->nb_streams == 0 && !(of->flags & AVFMT_NOSTREAMS)) { av_log(s, AV_LOG_ERROR, "no streams\n"); @@ -252,7 +257,7 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) } /* set muxer identification string */ - if (s->nb_streams && !(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) { + if (!(s->flags & AVFMT_FLAG_BITEXACT)) { av_dict_set(&s->metadata, "encoder", LIBAVFORMAT_IDENT, 0); } diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 4fd5687beb..66beec2940 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -507,7 +507,7 @@ static void mxf_write_identification(AVFormatContext *s) mxf_write_metadata_key(pb, 0x013000); PRINT_KEY(s, "identification key", pb->buf_ptr - 16); - version = s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT ? + version = s->flags & AVFMT_FLAG_BITEXACT ? "0.0.0" : AV_STRINGIFY(LIBAVFORMAT_VERSION); length = 84 + (strlen(company)+strlen(product)+strlen(version))*2; // utf-16 klv_encode_ber_length(pb, length); @@ -1512,7 +1512,7 @@ static int mxf_write_header(AVFormatContext *s) mxf->essence_container_count = 1; } - if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) + if (!(s->flags & AVFMT_FLAG_BITEXACT)) mxf_gen_umid(s); for (i = 0; i < s->nb_streams; i++) { diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c index fd102c86ad..c52368dde3 100644 --- a/libavformat/oggenc.c +++ b/libavformat/oggenc.c @@ -425,7 +425,7 @@ static int ogg_write_header(AVFormatContext *s) oggstream = av_mallocz(sizeof(*oggstream)); oggstream->page.stream_index = i; - if (!(st->codec->flags & CODEC_FLAG_BITEXACT)) + if (!(s->flags & AVFMT_FLAG_BITEXACT)) do { serial_num = av_get_random_seed(); for (j = 0; j < i; j++) { @@ -439,7 +439,7 @@ static int ogg_write_header(AVFormatContext *s) st->priv_data = oggstream; if (st->codec->codec_id == AV_CODEC_ID_FLAC) { int err = ogg_build_flac_headers(st->codec, oggstream, - st->codec->flags & CODEC_FLAG_BITEXACT, + s->flags & AVFMT_FLAG_BITEXACT, &s->metadata); if (err) { av_log(s, AV_LOG_ERROR, "Error writing FLAC headers\n"); @@ -448,7 +448,7 @@ static int ogg_write_header(AVFormatContext *s) } } else if (st->codec->codec_id == AV_CODEC_ID_SPEEX) { int err = ogg_build_speex_headers(st->codec, oggstream, - st->codec->flags & CODEC_FLAG_BITEXACT, + s->flags & AVFMT_FLAG_BITEXACT, &s->metadata); if (err) { av_log(s, AV_LOG_ERROR, "Error writing Speex headers\n"); @@ -457,7 +457,7 @@ static int ogg_write_header(AVFormatContext *s) } } else if (st->codec->codec_id == AV_CODEC_ID_OPUS) { int err = ogg_build_opus_headers(st->codec, oggstream, - st->codec->flags & CODEC_FLAG_BITEXACT, + s->flags & AVFMT_FLAG_BITEXACT, &s->metadata); if (err) { av_log(s, AV_LOG_ERROR, "Error writing Opus headers\n"); @@ -478,7 +478,7 @@ static int ogg_write_header(AVFormatContext *s) return -1; } - p = ogg_write_vorbiscomment(7, st->codec->flags & CODEC_FLAG_BITEXACT, + p = ogg_write_vorbiscomment(7, s->flags & AVFMT_FLAG_BITEXACT, &oggstream->header_len[1], &s->metadata, framing_bit); oggstream->header[1] = p; diff --git a/libavformat/options_table.h b/libavformat/options_table.h index cc84e1c02f..70194202d7 100644 --- a/libavformat/options_table.h +++ b/libavformat/options_table.h @@ -42,6 +42,7 @@ static const AVOption avformat_options[] = { {"igndts", "ignore dts", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_IGNDTS }, INT_MIN, INT_MAX, D, "fflags"}, {"discardcorrupt", "discard corrupted frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_DISCARD_CORRUPT }, INT_MIN, INT_MAX, D, "fflags"}, {"nobuffer", "reduce the latency introduced by optional buffering", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_NOBUFFER }, 0, INT_MAX, D, "fflags"}, +{"bitexact", "do not write random/volatile data", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_BITEXACT }, 0, 0, E, "fflags" }, {"analyzeduration", "how many microseconds are analyzed to estimate duration", OFFSET(max_analyze_duration), AV_OPT_TYPE_INT, {.i64 = 5*AV_TIME_BASE }, 0, INT_MAX, D}, {"cryptokey", "decryption key", OFFSET(key), AV_OPT_TYPE_BINARY, {.dbl = 0}, 0, 0, D}, {"indexmem", "max memory used for timestamp index (per stream)", OFFSET(max_index_size), AV_OPT_TYPE_INT, {.i64 = 1<<20 }, 0, INT_MAX, D}, diff --git a/libavformat/version.h b/libavformat/version.h index b09d49c818..248ecdfd6c 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFORMAT_VERSION_MAJOR 55 -#define LIBAVFORMAT_VERSION_MINOR 16 +#define LIBAVFORMAT_VERSION_MINOR 17 #define LIBAVFORMAT_VERSION_MICRO 0 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ @@ -51,5 +51,8 @@ #ifndef FF_API_REFERENCE_DTS #define FF_API_REFERENCE_DTS (LIBAVFORMAT_VERSION_MAJOR < 56) #endif +#ifndef FF_API_LAVF_BITEXACT +#define FF_API_LAVF_BITEXACT (LIBAVFORMAT_VERSION_MAJOR < 56) +#endif #endif /* AVFORMAT_VERSION_H */ -- cgit v1.2.3