From 99a2ad03af909cde95a4caef55aa658364fb9293 Mon Sep 17 00:00:00 2001 From: KongQun Yang Date: Thu, 31 May 2018 14:27:21 -0700 Subject: [PATCH] [HLS] Support AVERAGE-BANDWIDTH Issue #361 Change-Id: Id8eb8283675cba5ec7234d13c4ac235f34e3bec9 --- docs/source/options/stream_descriptors.rst | 2 +- packager/app/packager_main.cc | 2 +- .../testdata/avc-aac-ts-language/output.m3u8 | 4 +- .../app/test/testdata/avc-aac-ts/output.m3u8 | 4 +- .../testdata/avc-ac3-ts-to-mp4/output.m3u8 | 4 +- .../avc-ac3-ts-with-encryption/output.m3u8 | 4 +- .../app/test/testdata/avc-ac3-ts/output.m3u8 | 4 +- .../output.m3u8 | 4 +- .../output.m3u8 | 4 +- .../avc-ts-event-playlist/output.m3u8 | 4 +- .../output.m3u8 | 4 +- .../testdata/avc-ts-live-playlist/output.m3u8 | 4 +- .../output.m3u8 | 4 +- .../output.m3u8 | 4 +- .../avc-ts-with-encryption/output.m3u8 | 4 +- .../output.m3u8 | 4 +- .../ec3-packed-audio-encrypted/output.m3u8 | 4 +- .../output.m3u8 | 4 +- .../output.m3u8 | 4 +- .../output.m3u8 | 2 +- .../testdata/hls-segmented-webvtt/output.m3u8 | 2 +- .../output.m3u8 | 4 +- .../output.m3u8 | 4 +- .../hls-with-bandwidth-override/output.m3u8 | 2 +- .../live-profile-with-webm/output.m3u8 | 2 +- .../vtt-text-to-mp4-with-ad-cues/output.m3u8 | 4 +- packager/hls/base/master_playlist.cc | 35 ++- packager/hls/base/master_playlist_unittest.cc | 236 ++++++++++-------- packager/hls/base/media_playlist.cc | 6 +- packager/hls/base/media_playlist.h | 9 +- packager/hls/base/media_playlist_unittest.cc | 5 +- packager/hls/base/mock_media_playlist.h | 3 +- 32 files changed, 229 insertions(+), 157 deletions(-) diff --git a/docs/source/options/stream_descriptors.rst b/docs/source/options/stream_descriptors.rst index 71c9ae24bc..71677ec650 100644 --- a/docs/source/options/stream_descriptors.rst +++ b/docs/source/options/stream_descriptors.rst @@ -38,7 +38,7 @@ These are the available fields: :bandwidth (bw): - Optional value which contains a user-specified content bit rate for the + Optional value which contains a user-specified maximum bit rate for the stream, in bits/sec. If specified, this value is propagated to (HLS) EXT-X-STREAM-INF:BANDWIDTH or (DASH) Representation@bandwidth and the $Bandwidth$ template parameter for segment names. If not specified, the diff --git a/packager/app/packager_main.cc b/packager/app/packager_main.cc index 5dba8f1802..ae07c54b3e 100644 --- a/packager/app/packager_main.cc +++ b/packager/app/packager_main.cc @@ -67,7 +67,7 @@ const char kUsage[] = " split into multiple files. Its presence should be consistent across\n" " streams.\n" " - bandwidth (bw): Optional value which contains a user-specified\n" - " content bit rate for the stream, in bits/sec. If specified, this\n" + " maximum bit rate for the stream, in bits/sec. If specified, this\n" " value is propagated to (HLS) EXT-X-STREAM-INF:BANDWIDTH or (DASH)\n" " Representation@bandwidth and the $Bandwidth$ template parameter for\n" " segment names. If not specified, the bandwidth value is estimated\n" diff --git a/packager/app/test/testdata/avc-aac-ts-language/output.m3u8 b/packager/app/test/testdata/avc-aac-ts-language/output.m3u8 index c1532e8ea4..ec43e9cfdf 100644 --- a/packager/app/test/testdata/avc-aac-ts-language/output.m3u8 +++ b/packager/app/test/testdata/avc-aac-ts-language/output.m3u8 @@ -3,7 +3,7 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="bear-640x360-audio.m3u8",GROUP-ID="default-audio-group",LANGUAGE="pt",NAME="stream_0",DEFAULT=YES,AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=1217520,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=1217520,AVERAGE-BANDWIDTH=1109509,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" bear-640x360-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" diff --git a/packager/app/test/testdata/avc-aac-ts/output.m3u8 b/packager/app/test/testdata/avc-aac-ts/output.m3u8 index 02139e8baa..985fd91755 100644 --- a/packager/app/test/testdata/avc-aac-ts/output.m3u8 +++ b/packager/app/test/testdata/avc-aac-ts/output.m3u8 @@ -3,7 +3,7 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="bear-640x360-audio.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=1217520,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=1217520,AVERAGE-BANDWIDTH=1109509,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" bear-640x360-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" diff --git a/packager/app/test/testdata/avc-ac3-ts-to-mp4/output.m3u8 b/packager/app/test/testdata/avc-ac3-ts-to-mp4/output.m3u8 index 2f351dd422..5d447f0703 100644 --- a/packager/app/test/testdata/avc-ac3-ts-to-mp4/output.m3u8 +++ b/packager/app/test/testdata/avc-ac3-ts-to-mp4/output.m3u8 @@ -3,7 +3,7 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="bear-640x360-ac3-audio.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=1168321,CODECS="avc1.64001e,ac-3",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=1168321,AVERAGE-BANDWIDTH=1046257,CODECS="avc1.64001e,ac-3",RESOLUTION=640x360,AUDIO="default-audio-group" bear-640x360-ac3-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=214292,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-ac3-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=214292,AVERAGE-BANDWIDTH=153342,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-ac3-video-iframe.m3u8" diff --git a/packager/app/test/testdata/avc-ac3-ts-with-encryption/output.m3u8 b/packager/app/test/testdata/avc-ac3-ts-with-encryption/output.m3u8 index f85e7ac8b9..b6378c7e2a 100644 --- a/packager/app/test/testdata/avc-ac3-ts-with-encryption/output.m3u8 +++ b/packager/app/test/testdata/avc-ac3-ts-with-encryption/output.m3u8 @@ -3,7 +3,7 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="bear-640x360-ac3-audio.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=1242863,CODECS="avc1.64001e,ac-3",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=1242863,AVERAGE-BANDWIDTH=1142132,CODECS="avc1.64001e,ac-3",RESOLUTION=640x360,AUDIO="default-audio-group" bear-640x360-ac3-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-ac3-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-ac3-video-iframe.m3u8" diff --git a/packager/app/test/testdata/avc-ac3-ts/output.m3u8 b/packager/app/test/testdata/avc-ac3-ts/output.m3u8 index f85e7ac8b9..b6378c7e2a 100644 --- a/packager/app/test/testdata/avc-ac3-ts/output.m3u8 +++ b/packager/app/test/testdata/avc-ac3-ts/output.m3u8 @@ -3,7 +3,7 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="bear-640x360-ac3-audio.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=1242863,CODECS="avc1.64001e,ac-3",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=1242863,AVERAGE-BANDWIDTH=1142132,CODECS="avc1.64001e,ac-3",RESOLUTION=640x360,AUDIO="default-audio-group" bear-640x360-ac3-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-ac3-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-ac3-video-iframe.m3u8" diff --git a/packager/app/test/testdata/avc-ts-aac-packed-audio-with-encryption/output.m3u8 b/packager/app/test/testdata/avc-ts-aac-packed-audio-with-encryption/output.m3u8 index 4dfaf33ddb..50c768e24f 100644 --- a/packager/app/test/testdata/avc-ts-aac-packed-audio-with-encryption/output.m3u8 +++ b/packager/app/test/testdata/avc-ts-aac-packed-audio-with-encryption/output.m3u8 @@ -3,7 +3,7 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="bear-640x360-audio.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=1154999,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=1154999,AVERAGE-BANDWIDTH=1046205,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" bear-640x360-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" diff --git a/packager/app/test/testdata/avc-ts-ac3-packed-audio-with-encryption/output.m3u8 b/packager/app/test/testdata/avc-ts-ac3-packed-audio-with-encryption/output.m3u8 index c8828619bf..c0c100f97e 100644 --- a/packager/app/test/testdata/avc-ts-ac3-packed-audio-with-encryption/output.m3u8 +++ b/packager/app/test/testdata/avc-ts-ac3-packed-audio-with-encryption/output.m3u8 @@ -3,7 +3,7 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="bear-640x360-ac3-audio.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=1216578,CODECS="avc1.64001e,ac-3",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=1216578,AVERAGE-BANDWIDTH=1115973,CODECS="avc1.64001e,ac-3",RESOLUTION=640x360,AUDIO="default-audio-group" bear-640x360-ac3-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-ac3-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-ac3-video-iframe.m3u8" diff --git a/packager/app/test/testdata/avc-ts-event-playlist/output.m3u8 b/packager/app/test/testdata/avc-ts-event-playlist/output.m3u8 index 02139e8baa..985fd91755 100644 --- a/packager/app/test/testdata/avc-ts-event-playlist/output.m3u8 +++ b/packager/app/test/testdata/avc-ts-event-playlist/output.m3u8 @@ -3,7 +3,7 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="bear-640x360-audio.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=1217520,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=1217520,AVERAGE-BANDWIDTH=1109509,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" bear-640x360-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" diff --git a/packager/app/test/testdata/avc-ts-live-playlist-with-key-rotation/output.m3u8 b/packager/app/test/testdata/avc-ts-live-playlist-with-key-rotation/output.m3u8 index 02139e8baa..985fd91755 100644 --- a/packager/app/test/testdata/avc-ts-live-playlist-with-key-rotation/output.m3u8 +++ b/packager/app/test/testdata/avc-ts-live-playlist-with-key-rotation/output.m3u8 @@ -3,7 +3,7 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="bear-640x360-audio.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=1217520,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=1217520,AVERAGE-BANDWIDTH=1109509,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" bear-640x360-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" diff --git a/packager/app/test/testdata/avc-ts-live-playlist/output.m3u8 b/packager/app/test/testdata/avc-ts-live-playlist/output.m3u8 index 02139e8baa..985fd91755 100644 --- a/packager/app/test/testdata/avc-ts-live-playlist/output.m3u8 +++ b/packager/app/test/testdata/avc-ts-live-playlist/output.m3u8 @@ -3,7 +3,7 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="bear-640x360-audio.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=1217520,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=1217520,AVERAGE-BANDWIDTH=1109509,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" bear-640x360-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" diff --git a/packager/app/test/testdata/avc-ts-with-encryption-and-fairplay/output.m3u8 b/packager/app/test/testdata/avc-ts-with-encryption-and-fairplay/output.m3u8 index 02139e8baa..985fd91755 100644 --- a/packager/app/test/testdata/avc-ts-with-encryption-and-fairplay/output.m3u8 +++ b/packager/app/test/testdata/avc-ts-with-encryption-and-fairplay/output.m3u8 @@ -3,7 +3,7 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="bear-640x360-audio.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=1217520,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=1217520,AVERAGE-BANDWIDTH=1109509,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" bear-640x360-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" diff --git a/packager/app/test/testdata/avc-ts-with-encryption-exercise-emulation-prevention/output.m3u8 b/packager/app/test/testdata/avc-ts-with-encryption-exercise-emulation-prevention/output.m3u8 index 0112dd63f7..82fd728a2d 100644 --- a/packager/app/test/testdata/avc-ts-with-encryption-exercise-emulation-prevention/output.m3u8 +++ b/packager/app/test/testdata/avc-ts-with-encryption-exercise-emulation-prevention/output.m3u8 @@ -1,7 +1,7 @@ #EXTM3U ## Generated with https://github.com/google/shaka-packager version -- -#EXT-X-STREAM-INF:BANDWIDTH=1183949,CODECS="avc1.64001f",RESOLUTION=1024x436 +#EXT-X-STREAM-INF:BANDWIDTH=1183949,AVERAGE-BANDWIDTH=80147,CODECS="avc1.64001f",RESOLUTION=1024x436 sintel-1024x436-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=447591,CODECS="avc1.64001f",RESOLUTION=1024x436,URI="sintel-1024x436-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=447591,AVERAGE-BANDWIDTH=6232,CODECS="avc1.64001f",RESOLUTION=1024x436,URI="sintel-1024x436-video-iframe.m3u8" diff --git a/packager/app/test/testdata/avc-ts-with-encryption/output.m3u8 b/packager/app/test/testdata/avc-ts-with-encryption/output.m3u8 index 02139e8baa..985fd91755 100644 --- a/packager/app/test/testdata/avc-ts-with-encryption/output.m3u8 +++ b/packager/app/test/testdata/avc-ts-with-encryption/output.m3u8 @@ -3,7 +3,7 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="bear-640x360-audio.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=1217520,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=1217520,AVERAGE-BANDWIDTH=1109509,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" bear-640x360-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" diff --git a/packager/app/test/testdata/ec3-and-hls-single-segment-mp4-encrypted/output.m3u8 b/packager/app/test/testdata/ec3-and-hls-single-segment-mp4-encrypted/output.m3u8 index 610ef29f60..2393b3d8b0 100644 --- a/packager/app/test/testdata/ec3-and-hls-single-segment-mp4-encrypted/output.m3u8 +++ b/packager/app/test/testdata/ec3-and-hls-single-segment-mp4-encrypted/output.m3u8 @@ -3,7 +3,7 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="bear-640x360-ec3-audio.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=1174214,CODECS="avc1.64001e,ec-3",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=1174214,AVERAGE-BANDWIDTH=1030678,CODECS="avc1.64001e,ec-3",RESOLUTION=640x360,AUDIO="default-audio-group" bear-640x360-ec3-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=218705,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-ec3-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=218705,AVERAGE-BANDWIDTH=155992,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-ec3-video-iframe.m3u8" diff --git a/packager/app/test/testdata/ec3-packed-audio-encrypted/output.m3u8 b/packager/app/test/testdata/ec3-packed-audio-encrypted/output.m3u8 index e73d25a279..96b1d4b867 100644 --- a/packager/app/test/testdata/ec3-packed-audio-encrypted/output.m3u8 +++ b/packager/app/test/testdata/ec3-packed-audio-encrypted/output.m3u8 @@ -3,7 +3,7 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="bear-640x360-ec3-audio.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=1216655,CODECS="avc1.64001e,ec-3",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=1216655,AVERAGE-BANDWIDTH=1095969,CODECS="avc1.64001e,ec-3",RESOLUTION=640x360,AUDIO="default-audio-group" bear-640x360-ec3-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-ec3-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-ec3-video-iframe.m3u8" diff --git a/packager/app/test/testdata/encryption-and-ad-cues-split-content/output.m3u8 b/packager/app/test/testdata/encryption-and-ad-cues-split-content/output.m3u8 index 3ac3881e60..831f317e62 100644 --- a/packager/app/test/testdata/encryption-and-ad-cues-split-content/output.m3u8 +++ b/packager/app/test/testdata/encryption-and-ad-cues-split-content/output.m3u8 @@ -3,7 +3,7 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="bear-640x360-audio.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=1152421,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=1152421,AVERAGE-BANDWIDTH=986776,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" bear-640x360-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=218705,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=218705,AVERAGE-BANDWIDTH=155643,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" diff --git a/packager/app/test/testdata/hls-audio-video-text-with-ad-cues/output.m3u8 b/packager/app/test/testdata/hls-audio-video-text-with-ad-cues/output.m3u8 index ada4c0bca5..50f26c312f 100644 --- a/packager/app/test/testdata/hls-audio-video-text-with-ad-cues/output.m3u8 +++ b/packager/app/test/testdata/hls-audio-video-text-with-ad-cues/output.m3u8 @@ -5,7 +5,7 @@ #EXT-X-MEDIA:TYPE=SUBTITLES,URI="bear-subtitle-english-text.m3u8",GROUP-ID="default-text-group",NAME="stream_0",AUTOSELECT=YES -#EXT-X-STREAM-INF:BANDWIDTH=1150006,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group",SUBTITLES="default-text-group" +#EXT-X-STREAM-INF:BANDWIDTH=1150006,AVERAGE-BANDWIDTH=983710,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group",SUBTITLES="default-text-group" bear-640x360-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=214292,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=214292,AVERAGE-BANDWIDTH=153342,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" diff --git a/packager/app/test/testdata/hls-multi-segment-mp4-with-custom-path/output.m3u8 b/packager/app/test/testdata/hls-multi-segment-mp4-with-custom-path/output.m3u8 index 19c48866db..32242ca1b9 100644 --- a/packager/app/test/testdata/hls-multi-segment-mp4-with-custom-path/output.m3u8 +++ b/packager/app/test/testdata/hls-multi-segment-mp4-with-custom-path/output.m3u8 @@ -3,5 +3,5 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="audio/audio.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=1105131,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=1105131,AVERAGE-BANDWIDTH=974563,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" video/video.m3u8 diff --git a/packager/app/test/testdata/hls-segmented-webvtt/output.m3u8 b/packager/app/test/testdata/hls-segmented-webvtt/output.m3u8 index 908b5ac1ae..3ad045904b 100644 --- a/packager/app/test/testdata/hls-segmented-webvtt/output.m3u8 +++ b/packager/app/test/testdata/hls-segmented-webvtt/output.m3u8 @@ -5,5 +5,5 @@ #EXT-X-MEDIA:TYPE=SUBTITLES,URI="stream_0.m3u8",GROUP-ID="default-text-group",NAME="stream_0",AUTOSELECT=YES -#EXT-X-STREAM-INF:BANDWIDTH=1105131,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group",SUBTITLES="default-text-group" +#EXT-X-STREAM-INF:BANDWIDTH=1105131,AVERAGE-BANDWIDTH=974563,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group",SUBTITLES="default-text-group" stream_2.m3u8 diff --git a/packager/app/test/testdata/hls-single-segment-mp4-encrypted-and-ad-cues/output.m3u8 b/packager/app/test/testdata/hls-single-segment-mp4-encrypted-and-ad-cues/output.m3u8 index 3ac3881e60..831f317e62 100644 --- a/packager/app/test/testdata/hls-single-segment-mp4-encrypted-and-ad-cues/output.m3u8 +++ b/packager/app/test/testdata/hls-single-segment-mp4-encrypted-and-ad-cues/output.m3u8 @@ -3,7 +3,7 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="bear-640x360-audio.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=1152421,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=1152421,AVERAGE-BANDWIDTH=986776,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" bear-640x360-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=218705,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=218705,AVERAGE-BANDWIDTH=155643,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" diff --git a/packager/app/test/testdata/hls-single-segment-mp4-encrypted/output.m3u8 b/packager/app/test/testdata/hls-single-segment-mp4-encrypted/output.m3u8 index 81e0373df7..33e03086fd 100644 --- a/packager/app/test/testdata/hls-single-segment-mp4-encrypted/output.m3u8 +++ b/packager/app/test/testdata/hls-single-segment-mp4-encrypted/output.m3u8 @@ -3,7 +3,7 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="bear-640x360-audio.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=1111149,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=1111149,AVERAGE-BANDWIDTH=977986,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" bear-640x360-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=218705,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=218705,AVERAGE-BANDWIDTH=155643,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" diff --git a/packager/app/test/testdata/hls-with-bandwidth-override/output.m3u8 b/packager/app/test/testdata/hls-with-bandwidth-override/output.m3u8 index b07bc3df19..e701b3517a 100644 --- a/packager/app/test/testdata/hls-with-bandwidth-override/output.m3u8 +++ b/packager/app/test/testdata/hls-with-bandwidth-override/output.m3u8 @@ -3,5 +3,5 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="stream_0.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=55555,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=55555,AVERAGE-BANDWIDTH=974563,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" stream_1.m3u8 diff --git a/packager/app/test/testdata/live-profile-with-webm/output.m3u8 b/packager/app/test/testdata/live-profile-with-webm/output.m3u8 index e6178dc617..9c96fbd47c 100644 --- a/packager/app/test/testdata/live-profile-with-webm/output.m3u8 +++ b/packager/app/test/testdata/live-profile-with-webm/output.m3u8 @@ -3,5 +3,5 @@ #EXT-X-MEDIA:TYPE=AUDIO,URI="stream_0.m3u8",GROUP-ID="default-audio-group",NAME="stream_0",AUTOSELECT=YES,CHANNELS="2" -#EXT-X-STREAM-INF:BANDWIDTH=556353,CODECS="vp08.00.10.08.01.02.02.02.00,vorbis",RESOLUTION=640x360,AUDIO="default-audio-group" +#EXT-X-STREAM-INF:BANDWIDTH=556353,AVERAGE-BANDWIDTH=378244,CODECS="vp08.00.10.08.01.02.02.02.00,vorbis",RESOLUTION=640x360,AUDIO="default-audio-group" stream_1.m3u8 diff --git a/packager/app/test/testdata/vtt-text-to-mp4-with-ad-cues/output.m3u8 b/packager/app/test/testdata/vtt-text-to-mp4-with-ad-cues/output.m3u8 index ada4c0bca5..50f26c312f 100644 --- a/packager/app/test/testdata/vtt-text-to-mp4-with-ad-cues/output.m3u8 +++ b/packager/app/test/testdata/vtt-text-to-mp4-with-ad-cues/output.m3u8 @@ -5,7 +5,7 @@ #EXT-X-MEDIA:TYPE=SUBTITLES,URI="bear-subtitle-english-text.m3u8",GROUP-ID="default-text-group",NAME="stream_0",AUTOSELECT=YES -#EXT-X-STREAM-INF:BANDWIDTH=1150006,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group",SUBTITLES="default-text-group" +#EXT-X-STREAM-INF:BANDWIDTH=1150006,AVERAGE-BANDWIDTH=983710,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group",SUBTITLES="default-text-group" bear-640x360-video.m3u8 -#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=214292,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" +#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=214292,AVERAGE-BANDWIDTH=153342,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" diff --git a/packager/hls/base/master_playlist.cc b/packager/hls/base/master_playlist.cc index f4c82dd9b1..b00349d2b1 100644 --- a/packager/hls/base/master_playlist.cc +++ b/packager/hls/base/master_playlist.cc @@ -34,18 +34,36 @@ void AppendVersionString(std::string* content) { GetPackagerProjectUrl().c_str(), version.c_str()); } +// This structure roughly maps to the Variant stream in HLS specification. +// Each variant specifies zero or one audio group and zero or one text group. struct Variant { std::set audio_codecs; std::set text_codecs; const std::string* audio_group_id = nullptr; const std::string* text_group_id = nullptr; - uint64_t audio_bitrate = 0; + // The bitrates should be the sum of audio bitrate and text bitrate. + // However, given the contraints and assumptions, it makes sense to exclude + // text bitrate out of the calculation: + // - Text streams usually have a very small negligible bitrate. + // - Text does not have constant bitrates. To avoid fluctuation, an arbitrary + // value is assigned to the text bitrates in the parser. It does not make + // sense to take that text bitrate into account here. + uint64_t max_audio_bitrate = 0; + uint64_t avg_audio_bitrate = 0; }; -uint64_t MaxBitrate(const std::list playlists) { +uint64_t GetMaximumMaxBitrate(const std::list playlists) { uint64_t max = 0; for (const auto& playlist : playlists) { - max = std::max(max, playlist->Bitrate()); + max = std::max(max, playlist->MaxBitrate()); + } + return max; +} + +uint64_t GetMaximumAvgBitrate(const std::list playlists) { + uint64_t max = 0; + for (const auto& playlist : playlists) { + max = std::max(max, playlist->AvgBitrate()); } return max; } @@ -78,7 +96,8 @@ std::list AudioGroupsToVariants( for (const auto& group : groups) { Variant variant; variant.audio_group_id = &group.first; - variant.audio_bitrate = MaxBitrate(group.second); + variant.max_audio_bitrate = GetMaximumMaxBitrate(group.second); + variant.avg_audio_bitrate = GetMaximumAvgBitrate(group.second); variant.audio_codecs = GetGroupCodecString(group.second); variants.push_back(variant); @@ -153,7 +172,8 @@ std::list BuildVariants( variant.text_codecs = subtitle_variant.text_codecs; variant.audio_group_id = audio_variant.audio_group_id; variant.text_group_id = subtitle_variant.text_group_id; - variant.audio_bitrate = audio_variant.audio_bitrate; + variant.max_audio_bitrate = audio_variant.max_audio_bitrate; + variant.avg_audio_bitrate = audio_variant.avg_audio_bitrate; merged.push_back(variant); } @@ -185,8 +205,9 @@ void BuildStreamInfTag(const MediaPlaylist& playlist, } Tag tag(tag_name, out); - const uint64_t bitrate = playlist.Bitrate() + variant.audio_bitrate; - tag.AddNumber("BANDWIDTH", bitrate); + tag.AddNumber("BANDWIDTH", playlist.MaxBitrate() + variant.max_audio_bitrate); + tag.AddNumber("AVERAGE-BANDWIDTH", + playlist.AvgBitrate() + variant.avg_audio_bitrate); std::vector all_codecs; all_codecs.push_back(playlist.codec()); diff --git a/packager/hls/base/master_playlist_unittest.cc b/packager/hls/base/master_playlist_unittest.cc index 469f9ae04c..8e52f17d38 100644 --- a/packager/hls/base/master_playlist_unittest.cc +++ b/packager/hls/base/master_playlist_unittest.cc @@ -35,7 +35,8 @@ const uint32_t kHeight = 600; std::unique_ptr CreateVideoPlaylist( const std::string& filename, const std::string& codec, - uint64_t bitrate) { + uint64_t max_bitrate, + uint64_t avg_bitrate) { const char kNoName[] = ""; const char kNoGroup[] = ""; @@ -46,9 +47,12 @@ std::unique_ptr CreateVideoPlaylist( MediaPlaylist::MediaPlaylistStreamType::kVideo); playlist->SetCodecForTesting(codec); - EXPECT_CALL(*playlist, Bitrate()) + EXPECT_CALL(*playlist, MaxBitrate()) .Times(AtLeast(1)) - .WillRepeatedly(Return(bitrate)); + .WillRepeatedly(Return(max_bitrate)); + EXPECT_CALL(*playlist, AvgBitrate()) + .Times(AtLeast(1)) + .WillRepeatedly(Return(avg_bitrate)); EXPECT_CALL(*playlist, GetDisplayResolution(NotNull(), NotNull())) .WillRepeatedly(DoAll(SetArgPointee<0>(kWidth), SetArgPointee<1>(kHeight), Return(true))); @@ -59,8 +63,10 @@ std::unique_ptr CreateVideoPlaylist( std::unique_ptr CreateIframePlaylist( const std::string& filename, const std::string& codec, - uint64_t bitrate) { - auto playlist = CreateVideoPlaylist(filename, codec, bitrate); + uint64_t max_bitrate, + uint64_t avg_bitrate) { + auto playlist = + CreateVideoPlaylist(filename, codec, max_bitrate, avg_bitrate); playlist->SetStreamTypeForTesting( MediaPlaylist::MediaPlaylistStreamType::kVideoIFramesOnly); return playlist; @@ -73,7 +79,8 @@ std::unique_ptr CreateAudioPlaylist( const std::string& codec, const std::string& language, uint64_t channels, - uint64_t bitrate) { + uint64_t max_bitrate, + uint64_t avg_bitrate) { std::unique_ptr playlist( new MockMediaPlaylist(filename, name, group)); @@ -84,9 +91,12 @@ std::unique_ptr CreateAudioPlaylist( playlist->SetCodecForTesting(codec); playlist->SetLanguageForTesting(language); - EXPECT_CALL(*playlist, Bitrate()) + EXPECT_CALL(*playlist, MaxBitrate()) .Times(AtLeast(1)) - .WillRepeatedly(Return(bitrate)); + .WillRepeatedly(Return(max_bitrate)); + EXPECT_CALL(*playlist, AvgBitrate()) + .Times(AtLeast(1)) + .WillRepeatedly(Return(avg_bitrate)); EXPECT_CALL(*playlist, GetDisplayResolution(NotNull(), NotNull())).Times(0); return playlist; @@ -128,10 +138,11 @@ class MasterPlaylistTest : public ::testing::Test { }; TEST_F(MasterPlaylistTest, WriteMasterPlaylistOneVideo) { - const uint64_t kBitRate = 435889; + const uint64_t kMaxBitrate = 435889; + const uint64_t kAvgBitrate = 235889; std::unique_ptr mock_playlist = - CreateVideoPlaylist("media1.m3u8", "avc1", kBitRate); + CreateVideoPlaylist("media1.m3u8", "avc1", kMaxBitrate, kAvgBitrate); const char kBaseUrl[] = "http://myplaylistdomain.com/"; EXPECT_TRUE(master_playlist_.WriteMasterPlaylist(kBaseUrl, test_output_dir_, @@ -145,17 +156,19 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistOneVideo) { "## Generated with https://github.com/google/shaka-packager version " "test\n" "\n" - "#EXT-X-STREAM-INF:BANDWIDTH=435889,CODECS=\"avc1\",RESOLUTION=800x600\n" + "#EXT-X-STREAM-INF:BANDWIDTH=435889,AVERAGE-BANDWIDTH=235889," + "CODECS=\"avc1\",RESOLUTION=800x600\n" "http://myplaylistdomain.com/media1.m3u8\n"; ASSERT_EQ(expected, actual); } TEST_F(MasterPlaylistTest, WriteMasterPlaylistOneIframePlaylist) { - const uint64_t kBitRate = 435889; + const uint64_t kMaxBitrate = 435889; + const uint64_t kAvgBitrate = 235889; std::unique_ptr mock_playlist = - CreateIframePlaylist("media1.m3u8", "avc1", kBitRate); + CreateIframePlaylist("media1.m3u8", "avc1", kMaxBitrate, kAvgBitrate); const char kBaseUrl[] = "http://myplaylistdomain.com/"; EXPECT_TRUE(master_playlist_.WriteMasterPlaylist(kBaseUrl, test_output_dir_, @@ -169,39 +182,44 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistOneIframePlaylist) { "## Generated with https://github.com/google/shaka-packager version " "test\n" "\n" - "#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=435889,CODECS=\"avc1\",RESOLUTION=" - "800x600,URI=\"http://myplaylistdomain.com/media1.m3u8\"\n"; + "#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=435889,AVERAGE-BANDWIDTH=235889," + "CODECS=\"avc1\",RESOLUTION=800x600," + "URI=\"http://myplaylistdomain.com/media1.m3u8\"\n"; ASSERT_EQ(expected, actual); } TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndAudio) { - const uint64_t kVideo1BitRate = 300000; - const uint64_t kVideo2BitRate = 700000; + const uint64_t kVideo1MaxBitrate = 300000; + const uint64_t kVideo1AvgBitrate = 200000; + const uint64_t kVideo2MaxBitrate = 700000; + const uint64_t kVideo2AvgBitrate = 400000; - const uint64_t kAudio1BitRate = 50000; - const uint64_t kAudio2BitRate = 60000; + const uint64_t kAudio1MaxBitrate = 50000; + const uint64_t kAudio1AvgBitrate = 40000; + const uint64_t kAudio2MaxBitrate = 60000; + const uint64_t kAudio2AvgBitrate = 30000; const uint64_t kAudio1Channels = 2; const uint64_t kAudio2Channels = 5; // First video, sd.m3u8. - std::unique_ptr sd_video_playlist = - CreateVideoPlaylist("sd.m3u8", "sdvideocodec", kVideo1BitRate); + std::unique_ptr sd_video_playlist = CreateVideoPlaylist( + "sd.m3u8", "sdvideocodec", kVideo1MaxBitrate, kVideo1AvgBitrate); // Second video, hd.m3u8. - std::unique_ptr hd_video_playlist = - CreateVideoPlaylist("hd.m3u8", "hdvideocodec", kVideo2BitRate); + std::unique_ptr hd_video_playlist = CreateVideoPlaylist( + "hd.m3u8", "hdvideocodec", kVideo2MaxBitrate, kVideo2AvgBitrate); // First audio, english.m3u8. - std::unique_ptr english_playlist = - CreateAudioPlaylist("eng.m3u8", "english", "audiogroup", "audiocodec", - "en", kAudio1Channels, kAudio1BitRate); + std::unique_ptr english_playlist = CreateAudioPlaylist( + "eng.m3u8", "english", "audiogroup", "audiocodec", "en", kAudio1Channels, + kAudio1MaxBitrate, kAudio1AvgBitrate); // Second audio, spanish.m3u8. - std::unique_ptr spanish_playlist = - CreateAudioPlaylist("spa.m3u8", "espanol", "audiogroup", "audiocodec", - "es", kAudio2Channels, kAudio2BitRate); + std::unique_ptr spanish_playlist = CreateAudioPlaylist( + "spa.m3u8", "espanol", "audiogroup", "audiocodec", "es", kAudio2Channels, + kAudio2MaxBitrate, kAudio2AvgBitrate); const char kBaseUrl[] = "http://playlists.org/"; EXPECT_TRUE(master_playlist_.WriteMasterPlaylist( @@ -224,10 +242,12 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndAudio) { "GROUP-ID=\"audiogroup\",LANGUAGE=\"es\",NAME=\"espanol\"," "AUTOSELECT=YES,CHANNELS=\"5\"\n" "\n" - "#EXT-X-STREAM-INF:BANDWIDTH=360000,CODECS=\"sdvideocodec,audiocodec\"," + "#EXT-X-STREAM-INF:BANDWIDTH=360000,AVERAGE-BANDWIDTH=240000," + "CODECS=\"sdvideocodec,audiocodec\"," "RESOLUTION=800x600,AUDIO=\"audiogroup\"\n" "http://playlists.org/sd.m3u8\n" - "#EXT-X-STREAM-INF:BANDWIDTH=760000,CODECS=\"hdvideocodec,audiocodec\"," + "#EXT-X-STREAM-INF:BANDWIDTH=760000,AVERAGE-BANDWIDTH=440000," + "CODECS=\"hdvideocodec,audiocodec\"," "RESOLUTION=800x600,AUDIO=\"audiogroup\"\n" "http://playlists.org/hd.m3u8\n"; @@ -235,27 +255,30 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndAudio) { } TEST_F(MasterPlaylistTest, WriteMasterPlaylistMultipleAudioGroups) { - const uint64_t kVideoBitRate = 300000; + const uint64_t kVideoMaxBitrate = 300000; + const uint64_t kVideoAvgBitrate = 200000; - const uint64_t kAudio1BitRate = 50000; - const uint64_t kAudio2BitRate = 100000; + const uint64_t kAudio1MaxBitrate = 50000; + const uint64_t kAudio1AvgBitrate = 40000; + const uint64_t kAudio2MaxBitrate = 100000; + const uint64_t kAudio2AvgBitrate = 70000; const uint64_t kAudio1Channels = 1; const uint64_t kAudio2Channels = 8; // First video, sd.m3u8. - std::unique_ptr video_playlist = - CreateVideoPlaylist("video.m3u8", "videocodec", kVideoBitRate); + std::unique_ptr video_playlist = CreateVideoPlaylist( + "video.m3u8", "videocodec", kVideoMaxBitrate, kVideoAvgBitrate); // First audio, eng_lo.m3u8. std::unique_ptr eng_lo_playlist = CreateAudioPlaylist( "eng_lo.m3u8", "english_lo", "audio_lo", "audiocodec_lo", "en", - kAudio1Channels, kAudio1BitRate); + kAudio1Channels, kAudio1MaxBitrate, kAudio1AvgBitrate); // Second audio, eng_hi.m3u8. std::unique_ptr eng_hi_playlist = CreateAudioPlaylist( "eng_hi.m3u8", "english_hi", "audio_hi", "audiocodec_hi", "en", - kAudio2Channels, kAudio2BitRate); + kAudio2Channels, kAudio2MaxBitrate, kAudio2AvgBitrate); const char kBaseUrl[] = "http://anydomain.com/"; EXPECT_TRUE(master_playlist_.WriteMasterPlaylist( @@ -277,11 +300,13 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistMultipleAudioGroups) { "GROUP-ID=\"audio_lo\",LANGUAGE=\"en\",NAME=\"english_lo\"," "DEFAULT=YES,AUTOSELECT=YES,CHANNELS=\"1\"\n" "\n" - "#EXT-X-STREAM-INF:BANDWIDTH=400000,CODECS=\"videocodec,audiocodec_hi\"," + "#EXT-X-STREAM-INF:BANDWIDTH=400000,AVERAGE-BANDWIDTH=270000," + "CODECS=\"videocodec,audiocodec_hi\"," "RESOLUTION=800x600,AUDIO=\"audio_hi\"\n" "http://anydomain.com/video.m3u8\n" "\n" - "#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"videocodec,audiocodec_lo\"," + "#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=240000," + "CODECS=\"videocodec,audiocodec_lo\"," "RESOLUTION=800x600,AUDIO=\"audio_lo\"\n" "http://anydomain.com/video.m3u8\n"; @@ -291,14 +316,14 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistMultipleAudioGroups) { TEST_F(MasterPlaylistTest, WriteMasterPlaylistSameAudioGroupSameLanguage) { // First video, video.m3u8. std::unique_ptr video_playlist = - CreateVideoPlaylist("video.m3u8", "videocodec", 300000); + CreateVideoPlaylist("video.m3u8", "videocodec", 300000, 200000); // First audio, eng_lo.m3u8. std::unique_ptr eng_lo_playlist = CreateAudioPlaylist( - "eng_lo.m3u8", "english", "audio", "audiocodec", "en", 1, 50000); + "eng_lo.m3u8", "english", "audio", "audiocodec", "en", 1, 50000, 40000); std::unique_ptr eng_hi_playlist = CreateAudioPlaylist( - "eng_hi.m3u8", "english", "audio", "audiocodec", "en", 8, 100000); + "eng_hi.m3u8", "english", "audio", "audiocodec", "en", 8, 100000, 80000); const char kBaseUrl[] = "http://anydomain.com/"; EXPECT_TRUE(master_playlist_.WriteMasterPlaylist( @@ -319,8 +344,8 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistSameAudioGroupSameLanguage) { "#EXT-X-MEDIA:TYPE=AUDIO,URI=\"http://anydomain.com/eng_hi.m3u8\"," "GROUP-ID=\"audio\",LANGUAGE=\"en\",NAME=\"english\",CHANNELS=\"8\"\n" "\n" - "#EXT-X-STREAM-INF:BANDWIDTH=400000,CODECS=\"videocodec,audiocodec\"," - "RESOLUTION=800x600,AUDIO=\"audio\"\n" + "#EXT-X-STREAM-INF:BANDWIDTH=400000,AVERAGE-BANDWIDTH=280000," + "CODECS=\"videocodec,audiocodec\",RESOLUTION=800x600,AUDIO=\"audio\"\n" "http://anydomain.com/video.m3u8\n"; ASSERT_EQ(expected, actual); @@ -329,11 +354,11 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistSameAudioGroupSameLanguage) { TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideosAndTexts) { // Video, sd.m3u8. std::unique_ptr video1 = - CreateVideoPlaylist("sd.m3u8", "sdvideocodec", 300000); + CreateVideoPlaylist("sd.m3u8", "sdvideocodec", 300000, 200000); // Video, hd.m3u8. std::unique_ptr video2 = - CreateVideoPlaylist("hd.m3u8", "sdvideocodec", 600000); + CreateVideoPlaylist("hd.m3u8", "sdvideocodec", 600000, 500000); // Text, eng.m3u8. std::unique_ptr text_eng = @@ -362,11 +387,13 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideosAndTexts) { "#EXT-X-MEDIA:TYPE=SUBTITLES,URI=\"http://playlists.org/fr.m3u8\"," "GROUP-ID=\"textgroup\",LANGUAGE=\"fr\",NAME=\"french\",AUTOSELECT=YES\n" "\n" - "#EXT-X-STREAM-INF:BANDWIDTH=300000,CODECS=\"sdvideocodec,textcodec\"," - "RESOLUTION=800x600,SUBTITLES=\"textgroup\"\n" + "#EXT-X-STREAM-INF:BANDWIDTH=300000,AVERAGE-BANDWIDTH=200000," + "CODECS=\"sdvideocodec,textcodec\",RESOLUTION=800x600," + "SUBTITLES=\"textgroup\"\n" "http://playlists.org/sd.m3u8\n" - "#EXT-X-STREAM-INF:BANDWIDTH=600000,CODECS=\"sdvideocodec,textcodec\"," - "RESOLUTION=800x600,SUBTITLES=\"textgroup\"\n" + "#EXT-X-STREAM-INF:BANDWIDTH=600000,AVERAGE-BANDWIDTH=500000," + "CODECS=\"sdvideocodec,textcodec\",RESOLUTION=800x600," + "SUBTITLES=\"textgroup\"\n" "http://playlists.org/hd.m3u8\n"; ASSERT_EQ(expected, actual); @@ -375,7 +402,7 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideosAndTexts) { TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndTextGroups) { // Video, sd.m3u8. std::unique_ptr video = - CreateVideoPlaylist("sd.m3u8", "sdvideocodec", 300000); + CreateVideoPlaylist("sd.m3u8", "sdvideocodec", 300000, 200000); // Text, eng.m3u8. std::unique_ptr text_eng = CreateTextPlaylist( @@ -405,12 +432,14 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndTextGroups) { "GROUP-ID=\"fr-text-group\",LANGUAGE=\"fr\",NAME=\"french\"," "AUTOSELECT=YES\n" "\n" - "#EXT-X-STREAM-INF:BANDWIDTH=300000,CODECS=\"sdvideocodec,textcodec\"," - "RESOLUTION=800x600,SUBTITLES=\"en-text-group\"\n" + "#EXT-X-STREAM-INF:BANDWIDTH=300000,AVERAGE-BANDWIDTH=200000," + "CODECS=\"sdvideocodec,textcodec\",RESOLUTION=800x600," + "SUBTITLES=\"en-text-group\"\n" "http://playlists.org/sd.m3u8\n" "\n" - "#EXT-X-STREAM-INF:BANDWIDTH=300000,CODECS=\"sdvideocodec,textcodec\"," - "RESOLUTION=800x600,SUBTITLES=\"fr-text-group\"\n" + "#EXT-X-STREAM-INF:BANDWIDTH=300000,AVERAGE-BANDWIDTH=200000," + "CODECS=\"sdvideocodec,textcodec\",RESOLUTION=800x600," + "SUBTITLES=\"fr-text-group\"\n" "http://playlists.org/sd.m3u8\n"; ASSERT_EQ(expected, actual); @@ -419,11 +448,11 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndTextGroups) { TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndAudioAndText) { // Video, sd.m3u8. std::unique_ptr video = - CreateVideoPlaylist("sd.m3u8", "sdvideocodec", 300000); + CreateVideoPlaylist("sd.m3u8", "sdvideocodec", 300000, 200000); // Audio, english.m3u8. std::unique_ptr audio = CreateAudioPlaylist( - "eng.m3u8", "english", "audiogroup", "audiocodec", "en", 2, 50000); + "eng.m3u8", "english", "audiogroup", "audiocodec", "en", 2, 50000, 30000); // Text, english.m3u8. std::unique_ptr text = @@ -449,9 +478,9 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndAudioAndText) { "GROUP-ID=\"textgroup\",LANGUAGE=\"en\",NAME=\"english\",DEFAULT=YES," "AUTOSELECT=YES\n" "\n" - "#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec," - "textcodec\",RESOLUTION=800x600,AUDIO=\"audiogroup\",SUBTITLES=" - "\"textgroup\"\n" + "#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=230000," + "CODECS=\"sdvideocodec,audiocodec,textcodec\",RESOLUTION=800x600," + "AUDIO=\"audiogroup\",SUBTITLES=\"textgroup\"\n" "http://playlists.org/sd.m3u8\n"; ASSERT_EQ(expected, actual); @@ -459,16 +488,21 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndAudioAndText) { TEST_F(MasterPlaylistTest, WriteMasterPlaylistMixedPlaylistsDifferentGroups) { const uint64_t kAudioChannels = 2; - const uint64_t kAudioBitRate = 50000; - const uint64_t kVideoBitRate = 300000; - const uint64_t kIframeBitRate = 100000; + const uint64_t kAudioMaxBitrate = 50000; + const uint64_t kAudioAvgBitrate = 30000; + const uint64_t kVideoMaxBitrate = 300000; + const uint64_t kVideoAvgBitrate = 100000; + const uint64_t kIframeMaxBitrate = 100000; + const uint64_t kIframeAvgBitrate = 80000; std::unique_ptr media_playlists[] = { // AUDIO CreateAudioPlaylist("audio-1.m3u8", "audio 1", "audio-group-1", - "audiocodec", "en", kAudioChannels, kAudioBitRate), + "audiocodec", "en", kAudioChannels, kAudioMaxBitrate, + kAudioAvgBitrate), CreateAudioPlaylist("audio-2.m3u8", "audio 2", "audio-group-2", - "audiocodec", "en", kAudioChannels, kAudioBitRate), + "audiocodec", "en", kAudioChannels, kAudioMaxBitrate, + kAudioAvgBitrate), // SUBTITLES CreateTextPlaylist("text-1.m3u8", "text 1", "text-group-1", "textcodec", @@ -477,12 +511,16 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistMixedPlaylistsDifferentGroups) { "en"), // VIDEO - CreateVideoPlaylist("video-1.m3u8", "sdvideocodec", kVideoBitRate), - CreateVideoPlaylist("video-2.m3u8", "sdvideocodec", kVideoBitRate), + CreateVideoPlaylist("video-1.m3u8", "sdvideocodec", kVideoMaxBitrate, + kVideoAvgBitrate), + CreateVideoPlaylist("video-2.m3u8", "sdvideocodec", kVideoMaxBitrate, + kVideoAvgBitrate), // I-Frame - CreateIframePlaylist("iframe-1.m3u8", "sdvideocodec", kIframeBitRate), - CreateIframePlaylist("iframe-2.m3u8", "sdvideocodec", kIframeBitRate), + CreateIframePlaylist("iframe-1.m3u8", "sdvideocodec", kIframeMaxBitrate, + kIframeAvgBitrate), + CreateIframePlaylist("iframe-2.m3u8", "sdvideocodec", kIframeMaxBitrate, + kIframeAvgBitrate), }; // Add all the media playlists to the master playlist. @@ -517,46 +555,48 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistMixedPlaylistsDifferentGroups) { "GROUP-ID=\"text-group-2\",LANGUAGE=\"en\",NAME=\"text 2\"," "DEFAULT=YES,AUTOSELECT=YES\n" "\n" - "#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec," - "textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-1\",SUBTITLES=\"text-" - "group-1\"\n" + "#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=130000," + "CODECS=\"sdvideocodec,audiocodec,textcodec\",RESOLUTION=800x600," + "AUDIO=\"audio-group-1\",SUBTITLES=\"text-group-1\"\n" "http://playlists.org/video-1.m3u8\n" - "#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec," - "textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-1\",SUBTITLES=\"text-" - "group-1\"\n" + "#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=130000," + "CODECS=\"sdvideocodec,audiocodec,textcodec\",RESOLUTION=800x600," + "AUDIO=\"audio-group-1\",SUBTITLES=\"text-group-1\"\n" "http://playlists.org/video-2.m3u8\n" "\n" - "#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec," - "textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-1\",SUBTITLES=\"text-" - "group-2\"\n" + "#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=130000," + "CODECS=\"sdvideocodec,audiocodec,textcodec\",RESOLUTION=800x600," + "AUDIO=\"audio-group-1\",SUBTITLES=\"text-group-2\"\n" "http://playlists.org/video-1.m3u8\n" - "#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec," - "textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-1\",SUBTITLES=\"text-" - "group-2\"\n" + "#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=130000," + "CODECS=\"sdvideocodec,audiocodec,textcodec\",RESOLUTION=800x600," + "AUDIO=\"audio-group-1\",SUBTITLES=\"text-group-2\"\n" "http://playlists.org/video-2.m3u8\n" "\n" - "#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec," - "textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-2\",SUBTITLES=\"text-" - "group-1\"\n" + "#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=130000," + "CODECS=\"sdvideocodec,audiocodec,textcodec\",RESOLUTION=800x600," + "AUDIO=\"audio-group-2\",SUBTITLES=\"text-group-1\"\n" "http://playlists.org/video-1.m3u8\n" - "#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec," - "textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-2\",SUBTITLES=\"text-" - "group-1\"\n" + "#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=130000," + "CODECS=\"sdvideocodec,audiocodec,textcodec\",RESOLUTION=800x600," + "AUDIO=\"audio-group-2\",SUBTITLES=\"text-group-1\"\n" "http://playlists.org/video-2.m3u8\n" "\n" - "#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec," - "textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-2\",SUBTITLES=\"text-" - "group-2\"\n" + "#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=130000," + "CODECS=\"sdvideocodec,audiocodec,textcodec\",RESOLUTION=800x600," + "AUDIO=\"audio-group-2\",SUBTITLES=\"text-group-2\"\n" "http://playlists.org/video-1.m3u8\n" - "#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec," - "textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-2\",SUBTITLES=\"text-" - "group-2\"\n" + "#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=130000," + "CODECS=\"sdvideocodec,audiocodec,textcodec\",RESOLUTION=800x600," + "AUDIO=\"audio-group-2\",SUBTITLES=\"text-group-2\"\n" "http://playlists.org/video-2.m3u8\n" "\n" - "#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=100000,CODECS=\"sdvideocodec\"," - "RESOLUTION=800x600,URI=\"http://playlists.org/iframe-1.m3u8\"\n" - "#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=100000,CODECS=\"sdvideocodec\"," - "RESOLUTION=800x600,URI=\"http://playlists.org/iframe-2.m3u8\"\n"; + "#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=100000,AVERAGE-BANDWIDTH=80000," + "CODECS=\"sdvideocodec\",RESOLUTION=800x600," + "URI=\"http://playlists.org/iframe-1.m3u8\"\n" + "#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=100000,AVERAGE-BANDWIDTH=80000," + "CODECS=\"sdvideocodec\",RESOLUTION=800x600," + "URI=\"http://playlists.org/iframe-2.m3u8\"\n"; ASSERT_EQ(expected, actual); } diff --git a/packager/hls/base/media_playlist.cc b/packager/hls/base/media_playlist.cc index 9dc5a73b61..3e3b9bdbc0 100644 --- a/packager/hls/base/media_playlist.cc +++ b/packager/hls/base/media_playlist.cc @@ -460,12 +460,16 @@ bool MediaPlaylist::WriteToFile(const std::string& file_path) { return true; } -uint64_t MediaPlaylist::Bitrate() const { +uint64_t MediaPlaylist::MaxBitrate() const { if (media_info_.has_bandwidth()) return media_info_.bandwidth(); return bandwidth_estimator_.Max(); } +uint64_t MediaPlaylist::AvgBitrate() const { + return bandwidth_estimator_.Estimate(); +} + double MediaPlaylist::GetLongestSegmentDuration() const { return longest_segment_duration_; } diff --git a/packager/hls/base/media_playlist.h b/packager/hls/base/media_playlist.h index 134306cd51..d363f5f7cf 100644 --- a/packager/hls/base/media_playlist.h +++ b/packager/hls/base/media_playlist.h @@ -152,8 +152,13 @@ class MediaPlaylist { /// If bitrate is specified in MediaInfo then it will use that value. /// Otherwise, returns the max bitrate. - /// @return the bitrate (in bits per second) of this MediaPlaylist. - virtual uint64_t Bitrate() const; + /// @return the max bitrate (in bits per second) of this MediaPlaylist. + virtual uint64_t MaxBitrate() const; + + /// Unlike @a MaxBitrate, AvgBitrate is always computed from the segment size + /// and duration. + /// @return The average bitrate (in bits per second) of this MediaPlaylist. + virtual uint64_t AvgBitrate() const; /// @return the longest segment’s duration. This will return 0 if no /// segments have been added. diff --git a/packager/hls/base/media_playlist_unittest.cc b/packager/hls/base/media_playlist_unittest.cc index 0fd653fc9c..3f0a90fe55 100644 --- a/packager/hls/base/media_playlist_unittest.cc +++ b/packager/hls/base/media_playlist_unittest.cc @@ -248,7 +248,7 @@ TEST_F(MediaPlaylistMultiSegmentTest, WriteToFile) { TEST_F(MediaPlaylistMultiSegmentTest, UseBitrateInMediaInfo) { valid_video_media_info_.set_bandwidth(8191); ASSERT_TRUE(media_playlist_->SetMediaInfo(valid_video_media_info_)); - EXPECT_EQ(8191u, media_playlist_->Bitrate()); + EXPECT_EQ(8191u, media_playlist_->MaxBitrate()); } // If bitrate (bandwidth) is not set in the MediaInfo, then calculate from the @@ -263,7 +263,8 @@ TEST_F(MediaPlaylistMultiSegmentTest, GetBitrateFromSegments) { kZeroByteOffset, 5 * kMBytes); // Max bitrate is 2000Kb/s. - EXPECT_EQ(2000000u, media_playlist_->Bitrate()); + EXPECT_EQ(2000000u, media_playlist_->MaxBitrate()); + EXPECT_EQ(1142858u, media_playlist_->AvgBitrate()); } TEST_F(MediaPlaylistMultiSegmentTest, GetLongestSegmentDuration) { diff --git a/packager/hls/base/mock_media_playlist.h b/packager/hls/base/mock_media_playlist.h index 1ab1501230..761162dad7 100644 --- a/packager/hls/base/mock_media_playlist.h +++ b/packager/hls/base/mock_media_playlist.h @@ -43,7 +43,8 @@ class MockMediaPlaylist : public MediaPlaylist { const std::string& key_format_versions)); MOCK_METHOD0(AddPlacementOpportunity, void()); MOCK_METHOD1(WriteToFile, bool(const std::string& file_path)); - MOCK_CONST_METHOD0(Bitrate, uint64_t()); + MOCK_CONST_METHOD0(MaxBitrate, uint64_t()); + MOCK_CONST_METHOD0(AvgBitrate, uint64_t()); MOCK_CONST_METHOD0(GetLongestSegmentDuration, double()); MOCK_METHOD1(SetTargetDuration, void(uint32_t target_duration)); MOCK_CONST_METHOD0(GetNumChannels, int());