Browse code

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.

Anton Khirnov authored on 2014/05/01 17:43:10
Showing 15 changed files
... ...
@@ -13,6 +13,10 @@ libavutil:     2013-12-xx
13 13
 
14 14
 API changes, most recent first:
15 15
 
16
+2014-05-xx - xxxxxxx - lavf 55.17.0 - avformat.h
17
+  Add AVMFT_FLAG_BITEXACT flag. Muxers now use it instead of checking
18
+  CODEC_FLAG_BITEXACT on the first stream.
19
+
16 20
 2014-xx-xx - xxxxxxx - lavu 53.14.0 - pixfmt.h
17 21
   Add AV_PIX_FMT_VDA for new-style VDA acceleration.
18 22
 
... ...
@@ -1004,6 +1004,13 @@ typedef struct AVFormatContext {
1004 1004
 #define AVFMT_FLAG_CUSTOM_IO    0x0080 ///< The caller has supplied a custom AVIOContext, don't avio_close() it.
1005 1005
 #define AVFMT_FLAG_DISCARD_CORRUPT  0x0100 ///< Discard frames marked corrupted
1006 1006
 #define AVFMT_FLAG_FLUSH_PACKETS    0x0200 ///< Flush the AVIOContext every packet.
1007
+/**
1008
+ * When muxing, try to avoid writing any random/volatile data to the output.
1009
+ * This includes any random IDs, real-time timestamps/dates, muxer version, etc.
1010
+ *
1011
+ * This flag is mainly intended for testing.
1012
+ */
1013
+#define AVFMT_FLAG_BITEXACT         0x0400
1007 1014
 
1008 1015
     /**
1009 1016
      * Maximum size of the data read from input for determining
... ...
@@ -84,7 +84,7 @@ static int flac_write_header(struct AVFormatContext *s)
84 84
         return ret;
85 85
 
86 86
     ret = flac_write_block_comment(s->pb, &s->metadata, 0,
87
-                                   codec->flags & CODEC_FLAG_BITEXACT);
87
+                                   s->flags & AVFMT_FLAG_BITEXACT);
88 88
     if (ret)
89 89
         return ret;
90 90
 
... ...
@@ -970,7 +970,7 @@ static int mkv_write_header(AVFormatContext *s)
970 970
     put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000);
971 971
     if ((tag = av_dict_get(s->metadata, "title", NULL, 0)))
972 972
         put_ebml_string(pb, MATROSKA_ID_TITLE, tag->value);
973
-    if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) {
973
+    if (!(s->flags & AVFMT_FLAG_BITEXACT)) {
974 974
         uint32_t segment_uid[4];
975 975
         AVLFG lfg;
976 976
 
... ...
@@ -2024,7 +2024,7 @@ static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
2024 2024
     uint8_t *buf;
2025 2025
 
2026 2026
     for (i = 0; i < s->nb_streams; i++)
2027
-        if (mov->tracks[i].enc->flags & CODEC_FLAG_BITEXACT) {
2027
+        if (s->flags & AVFMT_FLAG_BITEXACT) {
2028 2028
             return 0;
2029 2029
         }
2030 2030
 
... ...
@@ -149,6 +149,11 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options)
149 149
     if ((ret = av_opt_set_dict(s, &tmp)) < 0)
150 150
         goto fail;
151 151
 
152
+#if FF_API_LAVF_BITEXACT
153
+    if (s->nb_streams && s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)
154
+        s->flags |= AVFMT_FLAG_BITEXACT;
155
+#endif
156
+
152 157
     // some sanity checks
153 158
     if (s->nb_streams == 0 && !(of->flags & AVFMT_NOSTREAMS)) {
154 159
         av_log(s, AV_LOG_ERROR, "no streams\n");
... ...
@@ -252,7 +257,7 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options)
252 252
     }
253 253
 
254 254
     /* set muxer identification string */
255
-    if (s->nb_streams && !(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) {
255
+    if (!(s->flags & AVFMT_FLAG_BITEXACT)) {
256 256
         av_dict_set(&s->metadata, "encoder", LIBAVFORMAT_IDENT, 0);
257 257
     }
258 258
 
... ...
@@ -507,7 +507,7 @@ static void mxf_write_identification(AVFormatContext *s)
507 507
     mxf_write_metadata_key(pb, 0x013000);
508 508
     PRINT_KEY(s, "identification key", pb->buf_ptr - 16);
509 509
 
510
-    version = s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT ?
510
+    version = s->flags & AVFMT_FLAG_BITEXACT ?
511 511
         "0.0.0" : AV_STRINGIFY(LIBAVFORMAT_VERSION);
512 512
     length = 84 + (strlen(company)+strlen(product)+strlen(version))*2; // utf-16
513 513
     klv_encode_ber_length(pb, length);
... ...
@@ -1512,7 +1512,7 @@ static int mxf_write_header(AVFormatContext *s)
1512 1512
         mxf->essence_container_count = 1;
1513 1513
     }
1514 1514
 
1515
-    if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT))
1515
+    if (!(s->flags & AVFMT_FLAG_BITEXACT))
1516 1516
         mxf_gen_umid(s);
1517 1517
 
1518 1518
     for (i = 0; i < s->nb_streams; i++) {
... ...
@@ -425,7 +425,7 @@ static int ogg_write_header(AVFormatContext *s)
425 425
         oggstream = av_mallocz(sizeof(*oggstream));
426 426
         oggstream->page.stream_index = i;
427 427
 
428
-        if (!(st->codec->flags & CODEC_FLAG_BITEXACT))
428
+        if (!(s->flags & AVFMT_FLAG_BITEXACT))
429 429
             do {
430 430
                 serial_num = av_get_random_seed();
431 431
                 for (j = 0; j < i; j++) {
... ...
@@ -439,7 +439,7 @@ static int ogg_write_header(AVFormatContext *s)
439 439
         st->priv_data = oggstream;
440 440
         if (st->codec->codec_id == AV_CODEC_ID_FLAC) {
441 441
             int err = ogg_build_flac_headers(st->codec, oggstream,
442
-                                             st->codec->flags & CODEC_FLAG_BITEXACT,
442
+                                             s->flags & AVFMT_FLAG_BITEXACT,
443 443
                                              &s->metadata);
444 444
             if (err) {
445 445
                 av_log(s, AV_LOG_ERROR, "Error writing FLAC headers\n");
... ...
@@ -448,7 +448,7 @@ static int ogg_write_header(AVFormatContext *s)
448 448
             }
449 449
         } else if (st->codec->codec_id == AV_CODEC_ID_SPEEX) {
450 450
             int err = ogg_build_speex_headers(st->codec, oggstream,
451
-                                              st->codec->flags & CODEC_FLAG_BITEXACT,
451
+                                              s->flags & AVFMT_FLAG_BITEXACT,
452 452
                                               &s->metadata);
453 453
             if (err) {
454 454
                 av_log(s, AV_LOG_ERROR, "Error writing Speex headers\n");
... ...
@@ -457,7 +457,7 @@ static int ogg_write_header(AVFormatContext *s)
457 457
             }
458 458
         } else if (st->codec->codec_id == AV_CODEC_ID_OPUS) {
459 459
             int err = ogg_build_opus_headers(st->codec, oggstream,
460
-                                             st->codec->flags & CODEC_FLAG_BITEXACT,
460
+                                             s->flags & AVFMT_FLAG_BITEXACT,
461 461
                                              &s->metadata);
462 462
             if (err) {
463 463
                 av_log(s, AV_LOG_ERROR, "Error writing Opus headers\n");
... ...
@@ -478,7 +478,7 @@ static int ogg_write_header(AVFormatContext *s)
478 478
                 return -1;
479 479
             }
480 480
 
481
-            p = ogg_write_vorbiscomment(7, st->codec->flags & CODEC_FLAG_BITEXACT,
481
+            p = ogg_write_vorbiscomment(7, s->flags & AVFMT_FLAG_BITEXACT,
482 482
                                         &oggstream->header_len[1], &s->metadata,
483 483
                                         framing_bit);
484 484
             oggstream->header[1] = p;
... ...
@@ -42,6 +42,7 @@ static const AVOption avformat_options[] = {
42 42
 {"igndts", "ignore dts", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_IGNDTS }, INT_MIN, INT_MAX, D, "fflags"},
43 43
 {"discardcorrupt", "discard corrupted frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_DISCARD_CORRUPT }, INT_MIN, INT_MAX, D, "fflags"},
44 44
 {"nobuffer", "reduce the latency introduced by optional buffering", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_NOBUFFER }, 0, INT_MAX, D, "fflags"},
45
+{"bitexact", "do not write random/volatile data", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_BITEXACT }, 0, 0, E, "fflags" },
45 46
 {"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},
46 47
 {"cryptokey", "decryption key", OFFSET(key), AV_OPT_TYPE_BINARY, {.dbl = 0}, 0, 0, D},
47 48
 {"indexmem", "max memory used for timestamp index (per stream)", OFFSET(max_index_size), AV_OPT_TYPE_INT, {.i64 = 1<<20 }, 0, INT_MAX, D},
... ...
@@ -30,7 +30,7 @@
30 30
 #include "libavutil/version.h"
31 31
 
32 32
 #define LIBAVFORMAT_VERSION_MAJOR 55
33
-#define LIBAVFORMAT_VERSION_MINOR 16
33
+#define LIBAVFORMAT_VERSION_MINOR 17
34 34
 #define LIBAVFORMAT_VERSION_MICRO  0
35 35
 
36 36
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
... ...
@@ -51,5 +51,8 @@
51 51
 #ifndef FF_API_REFERENCE_DTS
52 52
 #define FF_API_REFERENCE_DTS            (LIBAVFORMAT_VERSION_MAJOR < 56)
53 53
 #endif
54
+#ifndef FF_API_LAVF_BITEXACT
55
+#define FF_API_LAVF_BITEXACT            (LIBAVFORMAT_VERSION_MAJOR < 56)
56
+#endif
54 57
 
55 58
 #endif /* AVFORMAT_VERSION_H */
... ...
@@ -118,7 +118,7 @@ enc_dec_pcm(){
118 118
     avconv -f $out_fmt -i ${encfile} -c:a pcm_${pcm_fmt} -f ${dec_fmt} -
119 119
 }
120 120
 
121
-FLAGS="-flags +bitexact -sws_flags +accurate_rnd+bitexact"
121
+FLAGS="-flags +bitexact -sws_flags +accurate_rnd+bitexact -fflags +bitexact"
122 122
 DEC_OPTS="-threads $threads -idct simple $FLAGS"
123 123
 ENC_OPTS="-threads 1        -idct simple -dct fastint"
124 124
 
... ...
@@ -45,7 +45,7 @@ FATE_FILTER_CHANNELMAP += fate-filter-channelmap-one-int
45 45
 fate-filter-channelmap-one-int: tests/data/filtergraphs/channelmap_one_int
46 46
 fate-filter-channelmap-one-int: SRC = $(TARGET_PATH)/tests/data/asynth-44100-6.wav
47 47
 fate-filter-channelmap-one-int: tests/data/asynth-44100-6.wav
48
-fate-filter-channelmap-one-int: CMD = md5 -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/channelmap_one_int -f wav -flags +bitexact
48
+fate-filter-channelmap-one-int: CMD = md5 -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/channelmap_one_int -f wav -fflags +bitexact
49 49
 fate-filter-channelmap-one-int: CMP = oneline
50 50
 fate-filter-channelmap-one-int: REF = 21f1977c4f9705e2057083f84764e685
51 51
 
... ...
@@ -53,7 +53,7 @@ FATE_FILTER_CHANNELMAP += fate-filter-channelmap-one-str
53 53
 fate-filter-channelmap-one-str: tests/data/filtergraphs/channelmap_one_str
54 54
 fate-filter-channelmap-one-str: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
55 55
 fate-filter-channelmap-one-str: tests/data/asynth-44100-2.wav
56
-fate-filter-channelmap-one-str: CMD = md5 -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/channelmap_one_str -f wav -flags +bitexact
56
+fate-filter-channelmap-one-str: CMD = md5 -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/channelmap_one_str -f wav -fflags +bitexact
57 57
 fate-filter-channelmap-one-str: CMP = oneline
58 58
 fate-filter-channelmap-one-str: REF = 9fe9bc452282dfd94fd80e9491607a0c
59 59
 
... ...
@@ -176,7 +176,7 @@ FATE_SAMPLES_AVCONV-$(call DEMDEC, MSNWC_TCP, MIMIC) += fate-mimic
176 176
 fate-mimic: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/mimic/mimic2-womanloveffmpeg.cam
177 177
 
178 178
 FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, MJPEGB) += fate-mjpegb
179
-fate-mjpegb: CMD = framecrc -idct simple -flags +bitexact -i $(TARGET_SAMPLES)/mjpegb/mjpegb_part.mov -an
179
+fate-mjpegb: CMD = framecrc -idct simple -fflags +bitexact -i $(TARGET_SAMPLES)/mjpegb/mjpegb_part.mov -an
180 180
 
181 181
 FATE_SAMPLES_AVCONV-$(call DEMDEC, MVI, MOTIONPIXELS) += fate-motionpixels
182 182
 fate-motionpixels: CMD = framecrc -i $(TARGET_SAMPLES)/motion-pixels/INTRO-partial.MVI -an -pix_fmt rgb24 -vframes 111
... ...
@@ -265,7 +265,7 @@ fate-v410dec: CMD = framecrc -i $(TARGET_SAMPLES)/v410/lenav410.mov -pix_fmt yuv
265 265
 
266 266
 FATE_SAMPLES_AVCONV-$(call ENCDEC, V410 PGMYUV, AVI IMAGE2) += fate-v410enc
267 267
 fate-v410enc: $(VREF)
268
-fate-v410enc: CMD = md5 -f image2 -vcodec pgmyuv -i $(TARGET_PATH)/tests/vsynth1/%02d.pgm -flags +bitexact -vcodec v410 -f avi
268
+fate-v410enc: CMD = md5 -f image2 -vcodec pgmyuv -i $(TARGET_PATH)/tests/vsynth1/%02d.pgm -fflags +bitexact -vcodec v410 -f avi
269 269
 
270 270
 FATE_SAMPLES_AVCONV-$(call DEMDEC, SIFF, VB) += fate-vb
271 271
 fate-vb: CMD = framecrc -i $(TARGET_SAMPLES)/SIFF/INTRO_B.VB -t 3 -pix_fmt rgb24 -an
... ...
@@ -89,12 +89,12 @@ FATE_WAVPACK-$(call DEMDEC, MATROSKA, WAVPACK) += fate-wavpack-matroskamode
89 89
 fate-wavpack-matroskamode: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/special/matroska_mode.mka -f s16le
90 90
 
91 91
 FATE_WAVPACK-$(call DEMMUX, WV, MATROSKA) += fate-wavpack-matroska_mux-mono
92
-fate-wavpack-matroska_mux-mono: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/mono_16bit_int.wv -c copy -flags +bitexact -f matroska
92
+fate-wavpack-matroska_mux-mono: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/mono_16bit_int.wv -c copy -fflags +bitexact -f matroska
93 93
 fate-wavpack-matroska_mux-mono: CMP = oneline
94 94
 fate-wavpack-matroska_mux-mono: REF = 6bd769b3f0e9d7fa6261c3b73a53eb7d
95 95
 
96 96
 FATE_WAVPACK-$(call DEMMUX, WV, MATROSKA) += fate-wavpack-matroska_mux-61
97
-fate-wavpack-matroska_mux-61: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/eva_2.22_6.1_16bit-partial.wv -c copy -flags +bitexact -f matroska
97
+fate-wavpack-matroska_mux-61: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/eva_2.22_6.1_16bit-partial.wv -c copy -fflags +bitexact -f matroska
98 98
 fate-wavpack-matroska_mux-61: CMP = oneline
99 99
 fate-wavpack-matroska_mux-61: REF = 2d2f1e7f81a8b1983fcffc7f24de8a11
100 100
 
... ...
@@ -41,7 +41,7 @@ echov(){
41 41
 . $(dirname $0)/md5.sh
42 42
 
43 43
 AVCONV_OPTS="-nostats -y -cpuflags $cpuflags"
44
-COMMON_OPTS="-flags +bitexact -idct simple -sws_flags +accurate_rnd+bitexact"
44
+COMMON_OPTS="-flags +bitexact -idct simple -sws_flags +accurate_rnd+bitexact -fflags +bitexact"
45 45
 DEC_OPTS="$COMMON_OPTS -threads $threads"
46 46
 ENC_OPTS="$COMMON_OPTS -threads 1 -dct fastint"
47 47