[HLS] Support AVERAGE-BANDWIDTH

Issue #361

Change-Id: Id8eb8283675cba5ec7234d13c4ac235f34e3bec9
This commit is contained in:
KongQun Yang 2018-05-31 14:27:21 -07:00
parent f97413bf6e
commit 99a2ad03af
32 changed files with 229 additions and 157 deletions

View File

@ -38,7 +38,7 @@ These are the available fields:
:bandwidth (bw): :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) stream, in bits/sec. If specified, this value is propagated to (HLS)
EXT-X-STREAM-INF:BANDWIDTH or (DASH) Representation@bandwidth and the EXT-X-STREAM-INF:BANDWIDTH or (DASH) Representation@bandwidth and the
$Bandwidth$ template parameter for segment names. If not specified, the $Bandwidth$ template parameter for segment names. If not specified, the

View File

@ -67,7 +67,7 @@ const char kUsage[] =
" split into multiple files. Its presence should be consistent across\n" " split into multiple files. Its presence should be consistent across\n"
" streams.\n" " streams.\n"
" - bandwidth (bw): Optional value which contains a user-specified\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" " value is propagated to (HLS) EXT-X-STREAM-INF:BANDWIDTH or (DASH)\n"
" Representation@bandwidth and the $Bandwidth$ template parameter for\n" " Representation@bandwidth and the $Bandwidth$ template parameter for\n"
" segment names. If not specified, the bandwidth value is estimated\n" " segment names. If not specified, the bandwidth value is estimated\n"

View File

@ -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-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 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"

View File

@ -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-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 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"

View File

@ -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-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 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"

View File

@ -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-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 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"

View File

@ -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-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 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"

View File

@ -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-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 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"

View File

@ -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-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 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"

View File

@ -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-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 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"

View File

@ -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-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 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"

View File

@ -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-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 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"

View File

@ -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-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 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"

View File

@ -1,7 +1,7 @@
#EXTM3U #EXTM3U
## Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test> ## Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>
#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 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"

View File

@ -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-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 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"

View File

@ -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-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 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"

View File

@ -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-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 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"

View File

@ -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-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 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"

View File

@ -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-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 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"

View File

@ -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-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 video/video.m3u8

View File

@ -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-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 stream_2.m3u8

View File

@ -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-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 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"

View File

@ -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-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 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"

View File

@ -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-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 stream_1.m3u8

View File

@ -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-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 stream_1.m3u8

View File

@ -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-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 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"

View File

@ -34,18 +34,36 @@ void AppendVersionString(std::string* content) {
GetPackagerProjectUrl().c_str(), version.c_str()); 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 { struct Variant {
std::set<std::string> audio_codecs; std::set<std::string> audio_codecs;
std::set<std::string> text_codecs; std::set<std::string> text_codecs;
const std::string* audio_group_id = nullptr; const std::string* audio_group_id = nullptr;
const std::string* text_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<const MediaPlaylist*> playlists) { uint64_t GetMaximumMaxBitrate(const std::list<const MediaPlaylist*> playlists) {
uint64_t max = 0; uint64_t max = 0;
for (const auto& playlist : playlists) { 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<const MediaPlaylist*> playlists) {
uint64_t max = 0;
for (const auto& playlist : playlists) {
max = std::max(max, playlist->AvgBitrate());
} }
return max; return max;
} }
@ -78,7 +96,8 @@ std::list<Variant> AudioGroupsToVariants(
for (const auto& group : groups) { for (const auto& group : groups) {
Variant variant; Variant variant;
variant.audio_group_id = &group.first; 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); variant.audio_codecs = GetGroupCodecString(group.second);
variants.push_back(variant); variants.push_back(variant);
@ -153,7 +172,8 @@ std::list<Variant> BuildVariants(
variant.text_codecs = subtitle_variant.text_codecs; variant.text_codecs = subtitle_variant.text_codecs;
variant.audio_group_id = audio_variant.audio_group_id; variant.audio_group_id = audio_variant.audio_group_id;
variant.text_group_id = subtitle_variant.text_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); merged.push_back(variant);
} }
@ -185,8 +205,9 @@ void BuildStreamInfTag(const MediaPlaylist& playlist,
} }
Tag tag(tag_name, out); Tag tag(tag_name, out);
const uint64_t bitrate = playlist.Bitrate() + variant.audio_bitrate; tag.AddNumber("BANDWIDTH", playlist.MaxBitrate() + variant.max_audio_bitrate);
tag.AddNumber("BANDWIDTH", bitrate); tag.AddNumber("AVERAGE-BANDWIDTH",
playlist.AvgBitrate() + variant.avg_audio_bitrate);
std::vector<std::string> all_codecs; std::vector<std::string> all_codecs;
all_codecs.push_back(playlist.codec()); all_codecs.push_back(playlist.codec());

View File

@ -35,7 +35,8 @@ const uint32_t kHeight = 600;
std::unique_ptr<MockMediaPlaylist> CreateVideoPlaylist( std::unique_ptr<MockMediaPlaylist> CreateVideoPlaylist(
const std::string& filename, const std::string& filename,
const std::string& codec, const std::string& codec,
uint64_t bitrate) { uint64_t max_bitrate,
uint64_t avg_bitrate) {
const char kNoName[] = ""; const char kNoName[] = "";
const char kNoGroup[] = ""; const char kNoGroup[] = "";
@ -46,9 +47,12 @@ std::unique_ptr<MockMediaPlaylist> CreateVideoPlaylist(
MediaPlaylist::MediaPlaylistStreamType::kVideo); MediaPlaylist::MediaPlaylistStreamType::kVideo);
playlist->SetCodecForTesting(codec); playlist->SetCodecForTesting(codec);
EXPECT_CALL(*playlist, Bitrate()) EXPECT_CALL(*playlist, MaxBitrate())
.Times(AtLeast(1)) .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())) EXPECT_CALL(*playlist, GetDisplayResolution(NotNull(), NotNull()))
.WillRepeatedly(DoAll(SetArgPointee<0>(kWidth), SetArgPointee<1>(kHeight), .WillRepeatedly(DoAll(SetArgPointee<0>(kWidth), SetArgPointee<1>(kHeight),
Return(true))); Return(true)));
@ -59,8 +63,10 @@ std::unique_ptr<MockMediaPlaylist> CreateVideoPlaylist(
std::unique_ptr<MockMediaPlaylist> CreateIframePlaylist( std::unique_ptr<MockMediaPlaylist> CreateIframePlaylist(
const std::string& filename, const std::string& filename,
const std::string& codec, const std::string& codec,
uint64_t bitrate) { uint64_t max_bitrate,
auto playlist = CreateVideoPlaylist(filename, codec, bitrate); uint64_t avg_bitrate) {
auto playlist =
CreateVideoPlaylist(filename, codec, max_bitrate, avg_bitrate);
playlist->SetStreamTypeForTesting( playlist->SetStreamTypeForTesting(
MediaPlaylist::MediaPlaylistStreamType::kVideoIFramesOnly); MediaPlaylist::MediaPlaylistStreamType::kVideoIFramesOnly);
return playlist; return playlist;
@ -73,7 +79,8 @@ std::unique_ptr<MockMediaPlaylist> CreateAudioPlaylist(
const std::string& codec, const std::string& codec,
const std::string& language, const std::string& language,
uint64_t channels, uint64_t channels,
uint64_t bitrate) { uint64_t max_bitrate,
uint64_t avg_bitrate) {
std::unique_ptr<MockMediaPlaylist> playlist( std::unique_ptr<MockMediaPlaylist> playlist(
new MockMediaPlaylist(filename, name, group)); new MockMediaPlaylist(filename, name, group));
@ -84,9 +91,12 @@ std::unique_ptr<MockMediaPlaylist> CreateAudioPlaylist(
playlist->SetCodecForTesting(codec); playlist->SetCodecForTesting(codec);
playlist->SetLanguageForTesting(language); playlist->SetLanguageForTesting(language);
EXPECT_CALL(*playlist, Bitrate()) EXPECT_CALL(*playlist, MaxBitrate())
.Times(AtLeast(1)) .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); EXPECT_CALL(*playlist, GetDisplayResolution(NotNull(), NotNull())).Times(0);
return playlist; return playlist;
@ -128,10 +138,11 @@ class MasterPlaylistTest : public ::testing::Test {
}; };
TEST_F(MasterPlaylistTest, WriteMasterPlaylistOneVideo) { TEST_F(MasterPlaylistTest, WriteMasterPlaylistOneVideo) {
const uint64_t kBitRate = 435889; const uint64_t kMaxBitrate = 435889;
const uint64_t kAvgBitrate = 235889;
std::unique_ptr<MockMediaPlaylist> mock_playlist = std::unique_ptr<MockMediaPlaylist> mock_playlist =
CreateVideoPlaylist("media1.m3u8", "avc1", kBitRate); CreateVideoPlaylist("media1.m3u8", "avc1", kMaxBitrate, kAvgBitrate);
const char kBaseUrl[] = "http://myplaylistdomain.com/"; const char kBaseUrl[] = "http://myplaylistdomain.com/";
EXPECT_TRUE(master_playlist_.WriteMasterPlaylist(kBaseUrl, test_output_dir_, 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 " "## Generated with https://github.com/google/shaka-packager version "
"test\n" "test\n"
"\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"; "http://myplaylistdomain.com/media1.m3u8\n";
ASSERT_EQ(expected, actual); ASSERT_EQ(expected, actual);
} }
TEST_F(MasterPlaylistTest, WriteMasterPlaylistOneIframePlaylist) { TEST_F(MasterPlaylistTest, WriteMasterPlaylistOneIframePlaylist) {
const uint64_t kBitRate = 435889; const uint64_t kMaxBitrate = 435889;
const uint64_t kAvgBitrate = 235889;
std::unique_ptr<MockMediaPlaylist> mock_playlist = std::unique_ptr<MockMediaPlaylist> mock_playlist =
CreateIframePlaylist("media1.m3u8", "avc1", kBitRate); CreateIframePlaylist("media1.m3u8", "avc1", kMaxBitrate, kAvgBitrate);
const char kBaseUrl[] = "http://myplaylistdomain.com/"; const char kBaseUrl[] = "http://myplaylistdomain.com/";
EXPECT_TRUE(master_playlist_.WriteMasterPlaylist(kBaseUrl, test_output_dir_, 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 " "## Generated with https://github.com/google/shaka-packager version "
"test\n" "test\n"
"\n" "\n"
"#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=435889,CODECS=\"avc1\",RESOLUTION=" "#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=435889,AVERAGE-BANDWIDTH=235889,"
"800x600,URI=\"http://myplaylistdomain.com/media1.m3u8\"\n"; "CODECS=\"avc1\",RESOLUTION=800x600,"
"URI=\"http://myplaylistdomain.com/media1.m3u8\"\n";
ASSERT_EQ(expected, actual); ASSERT_EQ(expected, actual);
} }
TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndAudio) { TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndAudio) {
const uint64_t kVideo1BitRate = 300000; const uint64_t kVideo1MaxBitrate = 300000;
const uint64_t kVideo2BitRate = 700000; const uint64_t kVideo1AvgBitrate = 200000;
const uint64_t kVideo2MaxBitrate = 700000;
const uint64_t kVideo2AvgBitrate = 400000;
const uint64_t kAudio1BitRate = 50000; const uint64_t kAudio1MaxBitrate = 50000;
const uint64_t kAudio2BitRate = 60000; const uint64_t kAudio1AvgBitrate = 40000;
const uint64_t kAudio2MaxBitrate = 60000;
const uint64_t kAudio2AvgBitrate = 30000;
const uint64_t kAudio1Channels = 2; const uint64_t kAudio1Channels = 2;
const uint64_t kAudio2Channels = 5; const uint64_t kAudio2Channels = 5;
// First video, sd.m3u8. // First video, sd.m3u8.
std::unique_ptr<MockMediaPlaylist> sd_video_playlist = std::unique_ptr<MockMediaPlaylist> sd_video_playlist = CreateVideoPlaylist(
CreateVideoPlaylist("sd.m3u8", "sdvideocodec", kVideo1BitRate); "sd.m3u8", "sdvideocodec", kVideo1MaxBitrate, kVideo1AvgBitrate);
// Second video, hd.m3u8. // Second video, hd.m3u8.
std::unique_ptr<MockMediaPlaylist> hd_video_playlist = std::unique_ptr<MockMediaPlaylist> hd_video_playlist = CreateVideoPlaylist(
CreateVideoPlaylist("hd.m3u8", "hdvideocodec", kVideo2BitRate); "hd.m3u8", "hdvideocodec", kVideo2MaxBitrate, kVideo2AvgBitrate);
// First audio, english.m3u8. // First audio, english.m3u8.
std::unique_ptr<MockMediaPlaylist> english_playlist = std::unique_ptr<MockMediaPlaylist> english_playlist = CreateAudioPlaylist(
CreateAudioPlaylist("eng.m3u8", "english", "audiogroup", "audiocodec", "eng.m3u8", "english", "audiogroup", "audiocodec", "en", kAudio1Channels,
"en", kAudio1Channels, kAudio1BitRate); kAudio1MaxBitrate, kAudio1AvgBitrate);
// Second audio, spanish.m3u8. // Second audio, spanish.m3u8.
std::unique_ptr<MockMediaPlaylist> spanish_playlist = std::unique_ptr<MockMediaPlaylist> spanish_playlist = CreateAudioPlaylist(
CreateAudioPlaylist("spa.m3u8", "espanol", "audiogroup", "audiocodec", "spa.m3u8", "espanol", "audiogroup", "audiocodec", "es", kAudio2Channels,
"es", kAudio2Channels, kAudio2BitRate); kAudio2MaxBitrate, kAudio2AvgBitrate);
const char kBaseUrl[] = "http://playlists.org/"; const char kBaseUrl[] = "http://playlists.org/";
EXPECT_TRUE(master_playlist_.WriteMasterPlaylist( EXPECT_TRUE(master_playlist_.WriteMasterPlaylist(
@ -224,10 +242,12 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndAudio) {
"GROUP-ID=\"audiogroup\",LANGUAGE=\"es\",NAME=\"espanol\"," "GROUP-ID=\"audiogroup\",LANGUAGE=\"es\",NAME=\"espanol\","
"AUTOSELECT=YES,CHANNELS=\"5\"\n" "AUTOSELECT=YES,CHANNELS=\"5\"\n"
"\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" "RESOLUTION=800x600,AUDIO=\"audiogroup\"\n"
"http://playlists.org/sd.m3u8\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" "RESOLUTION=800x600,AUDIO=\"audiogroup\"\n"
"http://playlists.org/hd.m3u8\n"; "http://playlists.org/hd.m3u8\n";
@ -235,27 +255,30 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndAudio) {
} }
TEST_F(MasterPlaylistTest, WriteMasterPlaylistMultipleAudioGroups) { 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 kAudio1MaxBitrate = 50000;
const uint64_t kAudio2BitRate = 100000; const uint64_t kAudio1AvgBitrate = 40000;
const uint64_t kAudio2MaxBitrate = 100000;
const uint64_t kAudio2AvgBitrate = 70000;
const uint64_t kAudio1Channels = 1; const uint64_t kAudio1Channels = 1;
const uint64_t kAudio2Channels = 8; const uint64_t kAudio2Channels = 8;
// First video, sd.m3u8. // First video, sd.m3u8.
std::unique_ptr<MockMediaPlaylist> video_playlist = std::unique_ptr<MockMediaPlaylist> video_playlist = CreateVideoPlaylist(
CreateVideoPlaylist("video.m3u8", "videocodec", kVideoBitRate); "video.m3u8", "videocodec", kVideoMaxBitrate, kVideoAvgBitrate);
// First audio, eng_lo.m3u8. // First audio, eng_lo.m3u8.
std::unique_ptr<MockMediaPlaylist> eng_lo_playlist = CreateAudioPlaylist( std::unique_ptr<MockMediaPlaylist> eng_lo_playlist = CreateAudioPlaylist(
"eng_lo.m3u8", "english_lo", "audio_lo", "audiocodec_lo", "en", "eng_lo.m3u8", "english_lo", "audio_lo", "audiocodec_lo", "en",
kAudio1Channels, kAudio1BitRate); kAudio1Channels, kAudio1MaxBitrate, kAudio1AvgBitrate);
// Second audio, eng_hi.m3u8. // Second audio, eng_hi.m3u8.
std::unique_ptr<MockMediaPlaylist> eng_hi_playlist = CreateAudioPlaylist( std::unique_ptr<MockMediaPlaylist> eng_hi_playlist = CreateAudioPlaylist(
"eng_hi.m3u8", "english_hi", "audio_hi", "audiocodec_hi", "en", "eng_hi.m3u8", "english_hi", "audio_hi", "audiocodec_hi", "en",
kAudio2Channels, kAudio2BitRate); kAudio2Channels, kAudio2MaxBitrate, kAudio2AvgBitrate);
const char kBaseUrl[] = "http://anydomain.com/"; const char kBaseUrl[] = "http://anydomain.com/";
EXPECT_TRUE(master_playlist_.WriteMasterPlaylist( EXPECT_TRUE(master_playlist_.WriteMasterPlaylist(
@ -277,11 +300,13 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistMultipleAudioGroups) {
"GROUP-ID=\"audio_lo\",LANGUAGE=\"en\",NAME=\"english_lo\"," "GROUP-ID=\"audio_lo\",LANGUAGE=\"en\",NAME=\"english_lo\","
"DEFAULT=YES,AUTOSELECT=YES,CHANNELS=\"1\"\n" "DEFAULT=YES,AUTOSELECT=YES,CHANNELS=\"1\"\n"
"\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" "RESOLUTION=800x600,AUDIO=\"audio_hi\"\n"
"http://anydomain.com/video.m3u8\n" "http://anydomain.com/video.m3u8\n"
"\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" "RESOLUTION=800x600,AUDIO=\"audio_lo\"\n"
"http://anydomain.com/video.m3u8\n"; "http://anydomain.com/video.m3u8\n";
@ -291,14 +316,14 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistMultipleAudioGroups) {
TEST_F(MasterPlaylistTest, WriteMasterPlaylistSameAudioGroupSameLanguage) { TEST_F(MasterPlaylistTest, WriteMasterPlaylistSameAudioGroupSameLanguage) {
// First video, video.m3u8. // First video, video.m3u8.
std::unique_ptr<MockMediaPlaylist> video_playlist = std::unique_ptr<MockMediaPlaylist> video_playlist =
CreateVideoPlaylist("video.m3u8", "videocodec", 300000); CreateVideoPlaylist("video.m3u8", "videocodec", 300000, 200000);
// First audio, eng_lo.m3u8. // First audio, eng_lo.m3u8.
std::unique_ptr<MockMediaPlaylist> eng_lo_playlist = CreateAudioPlaylist( std::unique_ptr<MockMediaPlaylist> 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<MockMediaPlaylist> eng_hi_playlist = CreateAudioPlaylist( std::unique_ptr<MockMediaPlaylist> 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/"; const char kBaseUrl[] = "http://anydomain.com/";
EXPECT_TRUE(master_playlist_.WriteMasterPlaylist( 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\"," "#EXT-X-MEDIA:TYPE=AUDIO,URI=\"http://anydomain.com/eng_hi.m3u8\","
"GROUP-ID=\"audio\",LANGUAGE=\"en\",NAME=\"english\",CHANNELS=\"8\"\n" "GROUP-ID=\"audio\",LANGUAGE=\"en\",NAME=\"english\",CHANNELS=\"8\"\n"
"\n" "\n"
"#EXT-X-STREAM-INF:BANDWIDTH=400000,CODECS=\"videocodec,audiocodec\"," "#EXT-X-STREAM-INF:BANDWIDTH=400000,AVERAGE-BANDWIDTH=280000,"
"RESOLUTION=800x600,AUDIO=\"audio\"\n" "CODECS=\"videocodec,audiocodec\",RESOLUTION=800x600,AUDIO=\"audio\"\n"
"http://anydomain.com/video.m3u8\n"; "http://anydomain.com/video.m3u8\n";
ASSERT_EQ(expected, actual); ASSERT_EQ(expected, actual);
@ -329,11 +354,11 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistSameAudioGroupSameLanguage) {
TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideosAndTexts) { TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideosAndTexts) {
// Video, sd.m3u8. // Video, sd.m3u8.
std::unique_ptr<MockMediaPlaylist> video1 = std::unique_ptr<MockMediaPlaylist> video1 =
CreateVideoPlaylist("sd.m3u8", "sdvideocodec", 300000); CreateVideoPlaylist("sd.m3u8", "sdvideocodec", 300000, 200000);
// Video, hd.m3u8. // Video, hd.m3u8.
std::unique_ptr<MockMediaPlaylist> video2 = std::unique_ptr<MockMediaPlaylist> video2 =
CreateVideoPlaylist("hd.m3u8", "sdvideocodec", 600000); CreateVideoPlaylist("hd.m3u8", "sdvideocodec", 600000, 500000);
// Text, eng.m3u8. // Text, eng.m3u8.
std::unique_ptr<MockMediaPlaylist> text_eng = std::unique_ptr<MockMediaPlaylist> text_eng =
@ -362,11 +387,13 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideosAndTexts) {
"#EXT-X-MEDIA:TYPE=SUBTITLES,URI=\"http://playlists.org/fr.m3u8\"," "#EXT-X-MEDIA:TYPE=SUBTITLES,URI=\"http://playlists.org/fr.m3u8\","
"GROUP-ID=\"textgroup\",LANGUAGE=\"fr\",NAME=\"french\",AUTOSELECT=YES\n" "GROUP-ID=\"textgroup\",LANGUAGE=\"fr\",NAME=\"french\",AUTOSELECT=YES\n"
"\n" "\n"
"#EXT-X-STREAM-INF:BANDWIDTH=300000,CODECS=\"sdvideocodec,textcodec\"," "#EXT-X-STREAM-INF:BANDWIDTH=300000,AVERAGE-BANDWIDTH=200000,"
"RESOLUTION=800x600,SUBTITLES=\"textgroup\"\n" "CODECS=\"sdvideocodec,textcodec\",RESOLUTION=800x600,"
"SUBTITLES=\"textgroup\"\n"
"http://playlists.org/sd.m3u8\n" "http://playlists.org/sd.m3u8\n"
"#EXT-X-STREAM-INF:BANDWIDTH=600000,CODECS=\"sdvideocodec,textcodec\"," "#EXT-X-STREAM-INF:BANDWIDTH=600000,AVERAGE-BANDWIDTH=500000,"
"RESOLUTION=800x600,SUBTITLES=\"textgroup\"\n" "CODECS=\"sdvideocodec,textcodec\",RESOLUTION=800x600,"
"SUBTITLES=\"textgroup\"\n"
"http://playlists.org/hd.m3u8\n"; "http://playlists.org/hd.m3u8\n";
ASSERT_EQ(expected, actual); ASSERT_EQ(expected, actual);
@ -375,7 +402,7 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideosAndTexts) {
TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndTextGroups) { TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndTextGroups) {
// Video, sd.m3u8. // Video, sd.m3u8.
std::unique_ptr<MockMediaPlaylist> video = std::unique_ptr<MockMediaPlaylist> video =
CreateVideoPlaylist("sd.m3u8", "sdvideocodec", 300000); CreateVideoPlaylist("sd.m3u8", "sdvideocodec", 300000, 200000);
// Text, eng.m3u8. // Text, eng.m3u8.
std::unique_ptr<MockMediaPlaylist> text_eng = CreateTextPlaylist( std::unique_ptr<MockMediaPlaylist> text_eng = CreateTextPlaylist(
@ -405,12 +432,14 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndTextGroups) {
"GROUP-ID=\"fr-text-group\",LANGUAGE=\"fr\",NAME=\"french\"," "GROUP-ID=\"fr-text-group\",LANGUAGE=\"fr\",NAME=\"french\","
"AUTOSELECT=YES\n" "AUTOSELECT=YES\n"
"\n" "\n"
"#EXT-X-STREAM-INF:BANDWIDTH=300000,CODECS=\"sdvideocodec,textcodec\"," "#EXT-X-STREAM-INF:BANDWIDTH=300000,AVERAGE-BANDWIDTH=200000,"
"RESOLUTION=800x600,SUBTITLES=\"en-text-group\"\n" "CODECS=\"sdvideocodec,textcodec\",RESOLUTION=800x600,"
"SUBTITLES=\"en-text-group\"\n"
"http://playlists.org/sd.m3u8\n" "http://playlists.org/sd.m3u8\n"
"\n" "\n"
"#EXT-X-STREAM-INF:BANDWIDTH=300000,CODECS=\"sdvideocodec,textcodec\"," "#EXT-X-STREAM-INF:BANDWIDTH=300000,AVERAGE-BANDWIDTH=200000,"
"RESOLUTION=800x600,SUBTITLES=\"fr-text-group\"\n" "CODECS=\"sdvideocodec,textcodec\",RESOLUTION=800x600,"
"SUBTITLES=\"fr-text-group\"\n"
"http://playlists.org/sd.m3u8\n"; "http://playlists.org/sd.m3u8\n";
ASSERT_EQ(expected, actual); ASSERT_EQ(expected, actual);
@ -419,11 +448,11 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndTextGroups) {
TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndAudioAndText) { TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndAudioAndText) {
// Video, sd.m3u8. // Video, sd.m3u8.
std::unique_ptr<MockMediaPlaylist> video = std::unique_ptr<MockMediaPlaylist> video =
CreateVideoPlaylist("sd.m3u8", "sdvideocodec", 300000); CreateVideoPlaylist("sd.m3u8", "sdvideocodec", 300000, 200000);
// Audio, english.m3u8. // Audio, english.m3u8.
std::unique_ptr<MockMediaPlaylist> audio = CreateAudioPlaylist( std::unique_ptr<MockMediaPlaylist> audio = CreateAudioPlaylist(
"eng.m3u8", "english", "audiogroup", "audiocodec", "en", 2, 50000); "eng.m3u8", "english", "audiogroup", "audiocodec", "en", 2, 50000, 30000);
// Text, english.m3u8. // Text, english.m3u8.
std::unique_ptr<MockMediaPlaylist> text = std::unique_ptr<MockMediaPlaylist> text =
@ -449,9 +478,9 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndAudioAndText) {
"GROUP-ID=\"textgroup\",LANGUAGE=\"en\",NAME=\"english\",DEFAULT=YES," "GROUP-ID=\"textgroup\",LANGUAGE=\"en\",NAME=\"english\",DEFAULT=YES,"
"AUTOSELECT=YES\n" "AUTOSELECT=YES\n"
"\n" "\n"
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec," "#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=230000,"
"textcodec\",RESOLUTION=800x600,AUDIO=\"audiogroup\",SUBTITLES=" "CODECS=\"sdvideocodec,audiocodec,textcodec\",RESOLUTION=800x600,"
"\"textgroup\"\n" "AUDIO=\"audiogroup\",SUBTITLES=\"textgroup\"\n"
"http://playlists.org/sd.m3u8\n"; "http://playlists.org/sd.m3u8\n";
ASSERT_EQ(expected, actual); ASSERT_EQ(expected, actual);
@ -459,16 +488,21 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndAudioAndText) {
TEST_F(MasterPlaylistTest, WriteMasterPlaylistMixedPlaylistsDifferentGroups) { TEST_F(MasterPlaylistTest, WriteMasterPlaylistMixedPlaylistsDifferentGroups) {
const uint64_t kAudioChannels = 2; const uint64_t kAudioChannels = 2;
const uint64_t kAudioBitRate = 50000; const uint64_t kAudioMaxBitrate = 50000;
const uint64_t kVideoBitRate = 300000; const uint64_t kAudioAvgBitrate = 30000;
const uint64_t kIframeBitRate = 100000; const uint64_t kVideoMaxBitrate = 300000;
const uint64_t kVideoAvgBitrate = 100000;
const uint64_t kIframeMaxBitrate = 100000;
const uint64_t kIframeAvgBitrate = 80000;
std::unique_ptr<MockMediaPlaylist> media_playlists[] = { std::unique_ptr<MockMediaPlaylist> media_playlists[] = {
// AUDIO // AUDIO
CreateAudioPlaylist("audio-1.m3u8", "audio 1", "audio-group-1", 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", CreateAudioPlaylist("audio-2.m3u8", "audio 2", "audio-group-2",
"audiocodec", "en", kAudioChannels, kAudioBitRate), "audiocodec", "en", kAudioChannels, kAudioMaxBitrate,
kAudioAvgBitrate),
// SUBTITLES // SUBTITLES
CreateTextPlaylist("text-1.m3u8", "text 1", "text-group-1", "textcodec", CreateTextPlaylist("text-1.m3u8", "text 1", "text-group-1", "textcodec",
@ -477,12 +511,16 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistMixedPlaylistsDifferentGroups) {
"en"), "en"),
// VIDEO // VIDEO
CreateVideoPlaylist("video-1.m3u8", "sdvideocodec", kVideoBitRate), CreateVideoPlaylist("video-1.m3u8", "sdvideocodec", kVideoMaxBitrate,
CreateVideoPlaylist("video-2.m3u8", "sdvideocodec", kVideoBitRate), kVideoAvgBitrate),
CreateVideoPlaylist("video-2.m3u8", "sdvideocodec", kVideoMaxBitrate,
kVideoAvgBitrate),
// I-Frame // I-Frame
CreateIframePlaylist("iframe-1.m3u8", "sdvideocodec", kIframeBitRate), CreateIframePlaylist("iframe-1.m3u8", "sdvideocodec", kIframeMaxBitrate,
CreateIframePlaylist("iframe-2.m3u8", "sdvideocodec", kIframeBitRate), kIframeAvgBitrate),
CreateIframePlaylist("iframe-2.m3u8", "sdvideocodec", kIframeMaxBitrate,
kIframeAvgBitrate),
}; };
// Add all the media playlists to the master playlist. // 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\"," "GROUP-ID=\"text-group-2\",LANGUAGE=\"en\",NAME=\"text 2\","
"DEFAULT=YES,AUTOSELECT=YES\n" "DEFAULT=YES,AUTOSELECT=YES\n"
"\n" "\n"
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec," "#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=130000,"
"textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-1\",SUBTITLES=\"text-" "CODECS=\"sdvideocodec,audiocodec,textcodec\",RESOLUTION=800x600,"
"group-1\"\n" "AUDIO=\"audio-group-1\",SUBTITLES=\"text-group-1\"\n"
"http://playlists.org/video-1.m3u8\n" "http://playlists.org/video-1.m3u8\n"
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec," "#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=130000,"
"textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-1\",SUBTITLES=\"text-" "CODECS=\"sdvideocodec,audiocodec,textcodec\",RESOLUTION=800x600,"
"group-1\"\n" "AUDIO=\"audio-group-1\",SUBTITLES=\"text-group-1\"\n"
"http://playlists.org/video-2.m3u8\n" "http://playlists.org/video-2.m3u8\n"
"\n" "\n"
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec," "#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=130000,"
"textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-1\",SUBTITLES=\"text-" "CODECS=\"sdvideocodec,audiocodec,textcodec\",RESOLUTION=800x600,"
"group-2\"\n" "AUDIO=\"audio-group-1\",SUBTITLES=\"text-group-2\"\n"
"http://playlists.org/video-1.m3u8\n" "http://playlists.org/video-1.m3u8\n"
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec," "#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=130000,"
"textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-1\",SUBTITLES=\"text-" "CODECS=\"sdvideocodec,audiocodec,textcodec\",RESOLUTION=800x600,"
"group-2\"\n" "AUDIO=\"audio-group-1\",SUBTITLES=\"text-group-2\"\n"
"http://playlists.org/video-2.m3u8\n" "http://playlists.org/video-2.m3u8\n"
"\n" "\n"
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec," "#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=130000,"
"textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-2\",SUBTITLES=\"text-" "CODECS=\"sdvideocodec,audiocodec,textcodec\",RESOLUTION=800x600,"
"group-1\"\n" "AUDIO=\"audio-group-2\",SUBTITLES=\"text-group-1\"\n"
"http://playlists.org/video-1.m3u8\n" "http://playlists.org/video-1.m3u8\n"
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec," "#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=130000,"
"textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-2\",SUBTITLES=\"text-" "CODECS=\"sdvideocodec,audiocodec,textcodec\",RESOLUTION=800x600,"
"group-1\"\n" "AUDIO=\"audio-group-2\",SUBTITLES=\"text-group-1\"\n"
"http://playlists.org/video-2.m3u8\n" "http://playlists.org/video-2.m3u8\n"
"\n" "\n"
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec," "#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=130000,"
"textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-2\",SUBTITLES=\"text-" "CODECS=\"sdvideocodec,audiocodec,textcodec\",RESOLUTION=800x600,"
"group-2\"\n" "AUDIO=\"audio-group-2\",SUBTITLES=\"text-group-2\"\n"
"http://playlists.org/video-1.m3u8\n" "http://playlists.org/video-1.m3u8\n"
"#EXT-X-STREAM-INF:BANDWIDTH=350000,CODECS=\"sdvideocodec,audiocodec," "#EXT-X-STREAM-INF:BANDWIDTH=350000,AVERAGE-BANDWIDTH=130000,"
"textcodec\",RESOLUTION=800x600,AUDIO=\"audio-group-2\",SUBTITLES=\"text-" "CODECS=\"sdvideocodec,audiocodec,textcodec\",RESOLUTION=800x600,"
"group-2\"\n" "AUDIO=\"audio-group-2\",SUBTITLES=\"text-group-2\"\n"
"http://playlists.org/video-2.m3u8\n" "http://playlists.org/video-2.m3u8\n"
"\n" "\n"
"#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=100000,CODECS=\"sdvideocodec\"," "#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=100000,AVERAGE-BANDWIDTH=80000,"
"RESOLUTION=800x600,URI=\"http://playlists.org/iframe-1.m3u8\"\n" "CODECS=\"sdvideocodec\",RESOLUTION=800x600,"
"#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=100000,CODECS=\"sdvideocodec\"," "URI=\"http://playlists.org/iframe-1.m3u8\"\n"
"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-2.m3u8\"\n";
ASSERT_EQ(expected, actual); ASSERT_EQ(expected, actual);
} }

View File

@ -460,12 +460,16 @@ bool MediaPlaylist::WriteToFile(const std::string& file_path) {
return true; return true;
} }
uint64_t MediaPlaylist::Bitrate() const { uint64_t MediaPlaylist::MaxBitrate() const {
if (media_info_.has_bandwidth()) if (media_info_.has_bandwidth())
return media_info_.bandwidth(); return media_info_.bandwidth();
return bandwidth_estimator_.Max(); return bandwidth_estimator_.Max();
} }
uint64_t MediaPlaylist::AvgBitrate() const {
return bandwidth_estimator_.Estimate();
}
double MediaPlaylist::GetLongestSegmentDuration() const { double MediaPlaylist::GetLongestSegmentDuration() const {
return longest_segment_duration_; return longest_segment_duration_;
} }

View File

@ -152,8 +152,13 @@ class MediaPlaylist {
/// If bitrate is specified in MediaInfo then it will use that value. /// If bitrate is specified in MediaInfo then it will use that value.
/// Otherwise, returns the max bitrate. /// Otherwise, returns the max bitrate.
/// @return the bitrate (in bits per second) of this MediaPlaylist. /// @return the max bitrate (in bits per second) of this MediaPlaylist.
virtual uint64_t Bitrate() const; 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 segments duration. This will return 0 if no /// @return the longest segments duration. This will return 0 if no
/// segments have been added. /// segments have been added.

View File

@ -248,7 +248,7 @@ TEST_F(MediaPlaylistMultiSegmentTest, WriteToFile) {
TEST_F(MediaPlaylistMultiSegmentTest, UseBitrateInMediaInfo) { TEST_F(MediaPlaylistMultiSegmentTest, UseBitrateInMediaInfo) {
valid_video_media_info_.set_bandwidth(8191); valid_video_media_info_.set_bandwidth(8191);
ASSERT_TRUE(media_playlist_->SetMediaInfo(valid_video_media_info_)); 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 // If bitrate (bandwidth) is not set in the MediaInfo, then calculate from the
@ -263,7 +263,8 @@ TEST_F(MediaPlaylistMultiSegmentTest, GetBitrateFromSegments) {
kZeroByteOffset, 5 * kMBytes); kZeroByteOffset, 5 * kMBytes);
// Max bitrate is 2000Kb/s. // 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) { TEST_F(MediaPlaylistMultiSegmentTest, GetLongestSegmentDuration) {

View File

@ -43,7 +43,8 @@ class MockMediaPlaylist : public MediaPlaylist {
const std::string& key_format_versions)); const std::string& key_format_versions));
MOCK_METHOD0(AddPlacementOpportunity, void()); MOCK_METHOD0(AddPlacementOpportunity, void());
MOCK_METHOD1(WriteToFile, bool(const std::string& file_path)); 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_CONST_METHOD0(GetLongestSegmentDuration, double());
MOCK_METHOD1(SetTargetDuration, void(uint32_t target_duration)); MOCK_METHOD1(SetTargetDuration, void(uint32_t target_duration));
MOCK_CONST_METHOD0(GetNumChannels, int()); MOCK_CONST_METHOD0(GetNumChannels, int());