diff --git a/libavformat/movenc.c b/libavformat/movenc.c index a4ec4d05c9..76fb251fa8 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1073,6 +1073,25 @@ static int get_samples_per_packet(MOVTrack *track) return first_duration; } +static int mov_write_btrt_tag(AVIOContext *pb, MOVTrack *track) +{ + int64_t pos = avio_tell(pb); + struct mpeg4_bit_rate_values bit_rates = calculate_mpeg4_bit_rates(track); + if (!bit_rates.max_bit_rate && !bit_rates.avg_bit_rate && + !bit_rates.buffer_size) + // no useful data to be written, skip + return 0; + + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "btrt"); + + avio_wb32(pb, bit_rates.buffer_size); + avio_wb32(pb, bit_rates.max_bit_rate); + avio_wb32(pb, bit_rates.avg_bit_rate); + + return update_size(pb, pos); +} + static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) { int64_t pos = avio_tell(pb); @@ -1221,6 +1240,10 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex return ret; } + if (track->mode == MODE_MP4 && + ((ret = mov_write_btrt_tag(pb, track)) < 0)) + return ret; + ret = update_size(pb, pos); return ret; } @@ -1736,6 +1759,7 @@ static int mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track, int field_order) static int mov_write_subtitle_tag(AVIOContext *pb, MOVTrack *track) { + int ret = AVERROR_BUG; int64_t pos = avio_tell(pb); avio_wb32(pb, 0); /* size */ avio_wl32(pb, track->tag); // store it byteswapped @@ -1748,6 +1772,10 @@ static int mov_write_subtitle_tag(AVIOContext *pb, MOVTrack *track) else if (track->par->extradata_size) avio_write(pb, track->par->extradata, track->par->extradata_size); + if (track->mode == MODE_MP4 && + ((ret = mov_write_btrt_tag(pb, track)) < 0)) + return ret; + return update_size(pb, pos); } @@ -2051,6 +2079,7 @@ static void find_compressor(char * compressor_name, int len, MOVTrack *track) static int mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) { + int ret = AVERROR_BUG; int64_t pos = avio_tell(pb); char compressor_name[32] = { 0 }; int avid = 0; @@ -2231,6 +2260,10 @@ static int mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid); } + if (track->mode == MODE_MP4 && + ((ret = mov_write_btrt_tag(pb, track)) < 0)) + return ret; + /* extra padding for avid stsd */ /* https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-61112 */ if (avid) diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index 8d3b6c7224..0fd20fef96 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -113,7 +113,7 @@ fate-mov-spherical-mono: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries str fate-mov-gpmf-remux: CMD = md5 -i $(TARGET_SAMPLES)/mov/fake-gp-media-with-real-gpmf.mp4 -map 0 -c copy -fflags +bitexact -f mp4 fate-mov-gpmf-remux: CMP = oneline -fate-mov-gpmf-remux: REF = 8f48e435ee1f6b7e173ea756141eabf3 +fate-mov-gpmf-remux: REF = 6361cf3c2b9e6962c2eafbda138125f4 fate-mov-guess-delay-1: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream=has_b_frames -select_streams v $(TARGET_SAMPLES)/h264/h264_3bf_nopyramid_nobsrestriction.mp4 fate-mov-guess-delay-2: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream=has_b_frames -select_streams v $(TARGET_SAMPLES)/h264/h264_3bf_pyramid_nobsrestriction.mp4 diff --git a/tests/ref/fate/copy-trac3074 b/tests/ref/fate/copy-trac3074 index ff66900253..b5b0b6a60b 100644 --- a/tests/ref/fate/copy-trac3074 +++ b/tests/ref/fate/copy-trac3074 @@ -1,5 +1,5 @@ -f92a201033712bda262f1e071e25544a *tests/data/fate/copy-trac3074.mp4 -333992 tests/data/fate/copy-trac3074.mp4 +620e3ab4ee6241bec55ea2ec4ef42908 *tests/data/fate/copy-trac3074.mp4 +334012 tests/data/fate/copy-trac3074.mp4 #tb 0: 1/48000 #media_type 0: audio #codec_id 0: eac3 diff --git a/tests/ref/fate/movenc b/tests/ref/fate/movenc index fb39b98165..602639106d 100644 --- a/tests/ref/fate/movenc +++ b/tests/ref/fate/movenc @@ -1,18 +1,18 @@ write_data len 36, time nopts, type header atom ftyp -write_data len 2389, time nopts, type header atom - +write_data len 2429, time nopts, type header atom - write_data len 788, time 1000000, type sync atom moof write_data len 110, time nopts, type trailer atom - -5f401347fc3c771b819e2449d69d4861 3323 non-empty-moov +6f06e338c71468d56580df40ff265066 3363 non-empty-moov write_data len 36, time nopts, type header atom ftyp -write_data len 2721, time nopts, type header atom - +write_data len 2761, time nopts, type header atom - write_data len 908, time 966667, type sync atom moof write_data len 110, time nopts, type trailer atom - -4267feee527adf8cd4f7b36ac0fc0872 3775 non-empty-moov-elst +5b6e4211a45cd5dac99c8b90752a03d7 3815 non-empty-moov-elst write_data len 36, time nopts, type header atom ftyp -write_data len 2629, time nopts, type header atom - +write_data len 2669, time nopts, type header atom - write_data len 908, time 1000000, type sync atom moof write_data len 110, time nopts, type trailer atom - -44077b9ad45f3e16fafe4e5ada54e9b0 3683 non-empty-moov-no-elst +e106084014ed245ed7c4a30f1d11a3ac 3723 non-empty-moov-no-elst write_data len 24, time nopts, type header atom ftyp write_data len 1171, time nopts, type header atom - write_data len 728, time 0, type sync atom moof diff --git a/tests/ref/lavf-fate/av1.mp4 b/tests/ref/lavf-fate/av1.mp4 index 470c767111..ef174589ba 100644 --- a/tests/ref/lavf-fate/av1.mp4 +++ b/tests/ref/lavf-fate/av1.mp4 @@ -1,3 +1,3 @@ -1461be24bed65c04aab21659d6e7a3e1 *tests/data/lavf-fate/lavf.av1.mp4 -55956 tests/data/lavf-fate/lavf.av1.mp4 +d6afef355cf1bcf1a71b9cfb98c32fba *tests/data/lavf-fate/lavf.av1.mp4 +55976 tests/data/lavf-fate/lavf.av1.mp4 tests/data/lavf-fate/lavf.av1.mp4 CRC=0x7c27cc15 diff --git a/tests/ref/lavf-fate/h264.mp4 b/tests/ref/lavf-fate/h264.mp4 index bb52f45758..a9c3823c2c 100644 --- a/tests/ref/lavf-fate/h264.mp4 +++ b/tests/ref/lavf-fate/h264.mp4 @@ -1,3 +1,3 @@ -6d158b25efe7391c803f6f61c7a80aa0 *tests/data/lavf-fate/lavf.h264.mp4 -547908 tests/data/lavf-fate/lavf.h264.mp4 +fe299ea5205b71a48281f917b1256a5d *tests/data/lavf-fate/lavf.h264.mp4 +547928 tests/data/lavf-fate/lavf.h264.mp4 tests/data/lavf-fate/lavf.h264.mp4 CRC=0x9da2c999 diff --git a/tests/ref/lavf/mp4 b/tests/ref/lavf/mp4 index 8482812380..0becfd34f5 100644 --- a/tests/ref/lavf/mp4 +++ b/tests/ref/lavf/mp4 @@ -1,9 +1,9 @@ -ebca72c186a4f3ba9bb17d9cb5b74fef *tests/data/lavf/lavf.mp4 -312457 tests/data/lavf/lavf.mp4 +71c4ff2e747fe6f8169ff29244fe181d *tests/data/lavf/lavf.mp4 +312477 tests/data/lavf/lavf.mp4 tests/data/lavf/lavf.mp4 CRC=0x9d9a638a -9944512475d82d2d601f3c96101bdf9c *tests/data/lavf/lavf.mp4 -321343 tests/data/lavf/lavf.mp4 +3c5734ad6d05e4afc2ccefef1385e882 *tests/data/lavf/lavf.mp4 +321363 tests/data/lavf/lavf.mp4 tests/data/lavf/lavf.mp4 CRC=0xe8130120 -7b3e71f294901067046c09f03a426bdc *tests/data/lavf/lavf.mp4 -312001 tests/data/lavf/lavf.mp4 +07348e31d11d92396e1eedc48ea14802 *tests/data/lavf/lavf.mp4 +312021 tests/data/lavf/lavf.mp4 tests/data/lavf/lavf.mp4 CRC=0x9d9a638a diff --git a/tests/ref/vsynth/vsynth1-mpeg4 b/tests/ref/vsynth/vsynth1-mpeg4 index 4e9b4bd03a..e5abc146bc 100644 --- a/tests/ref/vsynth/vsynth1-mpeg4 +++ b/tests/ref/vsynth/vsynth1-mpeg4 @@ -1,4 +1,4 @@ -b4e8871c504a22c8c874c7e845b73da7 *tests/data/fate/vsynth1-mpeg4.mp4 -540085 tests/data/fate/vsynth1-mpeg4.mp4 +a7e57333c57e0f8a551374b063a41d9e *tests/data/fate/vsynth1-mpeg4.mp4 +540105 tests/data/fate/vsynth1-mpeg4.mp4 f80ec173d37f2f91add031e95579a220 *tests/data/fate/vsynth1-mpeg4.out.rawvideo stddev: 7.97 PSNR: 30.10 MAXDIFF: 105 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg4 b/tests/ref/vsynth/vsynth2-mpeg4 index 85899ff88e..7857d45803 100644 --- a/tests/ref/vsynth/vsynth2-mpeg4 +++ b/tests/ref/vsynth/vsynth2-mpeg4 @@ -1,4 +1,4 @@ -adbd883d1701beabd04522d003dafab6 *tests/data/fate/vsynth2-mpeg4.mp4 -159310 tests/data/fate/vsynth2-mpeg4.mp4 +b751a2d3b4e693ca39d4fafa0175fc9d *tests/data/fate/vsynth2-mpeg4.mp4 +159330 tests/data/fate/vsynth2-mpeg4.mp4 2645405bc5350acc85ad72f3352f5135 *tests/data/fate/vsynth2-mpeg4.out.rawvideo stddev: 6.02 PSNR: 32.53 MAXDIFF: 89 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth3-mpeg4 b/tests/ref/vsynth/vsynth3-mpeg4 index 02cf68d55d..a241e929c6 100644 --- a/tests/ref/vsynth/vsynth3-mpeg4 +++ b/tests/ref/vsynth/vsynth3-mpeg4 @@ -1,4 +1,4 @@ -ddcff996543900496f0b374a2d5cae74 *tests/data/fate/vsynth3-mpeg4.mp4 -26017 tests/data/fate/vsynth3-mpeg4.mp4 +7ca3bbb8bed55d558346d258f5bea440 *tests/data/fate/vsynth3-mpeg4.mp4 +26037 tests/data/fate/vsynth3-mpeg4.mp4 fc0d8c1e58d254031e6207dfcae8f867 *tests/data/fate/vsynth3-mpeg4.out.rawvideo stddev: 9.66 PSNR: 28.43 MAXDIFF: 79 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth_lena-mpeg4 b/tests/ref/vsynth/vsynth_lena-mpeg4 index 8d8cccef40..375c3fc659 100644 --- a/tests/ref/vsynth/vsynth_lena-mpeg4 +++ b/tests/ref/vsynth/vsynth_lena-mpeg4 @@ -1,4 +1,4 @@ -4a029747434d24d128b078a5e6aa1e88 *tests/data/fate/vsynth_lena-mpeg4.mp4 -119722 tests/data/fate/vsynth_lena-mpeg4.mp4 +a0d0edee19f6658d0e93d294e32a1a6f *tests/data/fate/vsynth_lena-mpeg4.mp4 +119742 tests/data/fate/vsynth_lena-mpeg4.mp4 9a1e085d9e488c5ead0c940c9612a37a *tests/data/fate/vsynth_lena-mpeg4.out.rawvideo stddev: 5.34 PSNR: 33.57 MAXDIFF: 83 bytes: 7603200/ 7603200