From 3838e8fc210aa09a9f9058506c0ce80b6ad9b9c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Sun, 20 Sep 2020 15:26:42 +0300 Subject: [PATCH] avformat/movenc: implement writing of the btrt box This is utilized by various media ingests to figure out the bit rate of the content you are pushing towards it, so write it for video, audio and subtitle tracks in case at least one nonzero value is available. It is only mentioned for timed metadata sample descriptions in QTFF, so limit it only to ISOBMFF (MODE_MP4) mode. Updates the FATE tests which have their results changed due to the 20 extra bytes being written per track. --- libavformat/movenc.c | 33 ++++++++++++++++++++++++++++++ tests/fate/mov.mak | 2 +- tests/ref/fate/copy-trac3074 | 4 ++-- tests/ref/fate/movenc | 12 +++++------ tests/ref/lavf-fate/av1.mp4 | 4 ++-- tests/ref/lavf-fate/h264.mp4 | 4 ++-- tests/ref/lavf/mp4 | 12 +++++------ tests/ref/vsynth/vsynth1-mpeg4 | 4 ++-- tests/ref/vsynth/vsynth2-mpeg4 | 4 ++-- tests/ref/vsynth/vsynth3-mpeg4 | 4 ++-- tests/ref/vsynth/vsynth_lena-mpeg4 | 4 ++-- 11 files changed, 60 insertions(+), 27 deletions(-) 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