Do not use harmonic mean in bandwidth calculation

Instead, caclulating average bandwidth by dividing the sum of the
sizes of every segment by the sum of the durations of every segment.
This aligns with the requirement in HLS spec:
https://tools.ietf.org/html/draft-pantos-http-live-streaming-23 4.1.

BandwidthEstimator is also simplified to handle all blocks only.

Fixes #361

Change-Id: I89e7d415a841f4d4048f199de8dae7ffa250467b
This commit is contained in:
KongQun Yang 2018-06-22 16:19:30 -07:00
parent 99a2ad03af
commit 5dd21179ec
31 changed files with 83 additions and 245 deletions

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,AVERAGE-BANDWIDTH=1109509,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" #EXT-X-STREAM-INF:BANDWIDTH=1217520,AVERAGE-BANDWIDTH=1117320,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,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=157213,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,AVERAGE-BANDWIDTH=1109509,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" #EXT-X-STREAM-INF:BANDWIDTH=1217520,AVERAGE-BANDWIDTH=1117320,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,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=157213,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,AVERAGE-BANDWIDTH=1046257,CODECS="avc1.64001e,ac-3",RESOLUTION=640x360,AUDIO="default-audio-group" #EXT-X-STREAM-INF:BANDWIDTH=1168321,AVERAGE-BANDWIDTH=1053216,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,AVERAGE-BANDWIDTH=153342,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-ac3-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=214292,AVERAGE-BANDWIDTH=156327,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,AVERAGE-BANDWIDTH=1142132,CODECS="avc1.64001e,ac-3",RESOLUTION=640x360,AUDIO="default-audio-group" #EXT-X-STREAM-INF:BANDWIDTH=1242863,AVERAGE-BANDWIDTH=1148679,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,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-ac3-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=157213,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,AVERAGE-BANDWIDTH=1142132,CODECS="avc1.64001e,ac-3",RESOLUTION=640x360,AUDIO="default-audio-group" #EXT-X-STREAM-INF:BANDWIDTH=1242863,AVERAGE-BANDWIDTH=1148679,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,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-ac3-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=157213,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,AVERAGE-BANDWIDTH=1046205,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" #EXT-X-STREAM-INF:BANDWIDTH=1154999,AVERAGE-BANDWIDTH=1054750,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,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=157213,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,AVERAGE-BANDWIDTH=1115973,CODECS="avc1.64001e,ac-3",RESOLUTION=640x360,AUDIO="default-audio-group" #EXT-X-STREAM-INF:BANDWIDTH=1216578,AVERAGE-BANDWIDTH=1122532,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,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-ac3-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=157213,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,AVERAGE-BANDWIDTH=1109509,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" #EXT-X-STREAM-INF:BANDWIDTH=1217520,AVERAGE-BANDWIDTH=1117320,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,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=157213,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,AVERAGE-BANDWIDTH=1109509,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" #EXT-X-STREAM-INF:BANDWIDTH=1217520,AVERAGE-BANDWIDTH=1117320,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,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=157213,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,AVERAGE-BANDWIDTH=1109509,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" #EXT-X-STREAM-INF:BANDWIDTH=1217520,AVERAGE-BANDWIDTH=1117320,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,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=157213,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,AVERAGE-BANDWIDTH=1109509,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" #EXT-X-STREAM-INF:BANDWIDTH=1217520,AVERAGE-BANDWIDTH=1117320,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,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=157213,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,AVERAGE-BANDWIDTH=80147,CODECS="avc1.64001f",RESOLUTION=1024x436 #EXT-X-STREAM-INF:BANDWIDTH=1183949,AVERAGE-BANDWIDTH=390289,CODECS="avc1.64001f",RESOLUTION=1024x436
sintel-1024x436-video.m3u8 sintel-1024x436-video.m3u8
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=447591,AVERAGE-BANDWIDTH=6232,CODECS="avc1.64001f",RESOLUTION=1024x436,URI="sintel-1024x436-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=447591,AVERAGE-BANDWIDTH=40358,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,AVERAGE-BANDWIDTH=1109509,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" #EXT-X-STREAM-INF:BANDWIDTH=1217520,AVERAGE-BANDWIDTH=1117320,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,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=157213,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,AVERAGE-BANDWIDTH=1030678,CODECS="avc1.64001e,ec-3",RESOLUTION=640x360,AUDIO="default-audio-group" #EXT-X-STREAM-INF:BANDWIDTH=1174214,AVERAGE-BANDWIDTH=1040768,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,AVERAGE-BANDWIDTH=155992,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-ec3-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=218705,AVERAGE-BANDWIDTH=159315,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,AVERAGE-BANDWIDTH=1095969,CODECS="avc1.64001e,ec-3",RESOLUTION=640x360,AUDIO="default-audio-group" #EXT-X-STREAM-INF:BANDWIDTH=1216655,AVERAGE-BANDWIDTH=1104925,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,AVERAGE-BANDWIDTH=153967,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-ec3-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=217180,AVERAGE-BANDWIDTH=157213,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,AVERAGE-BANDWIDTH=986776,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" #EXT-X-STREAM-INF:BANDWIDTH=1152421,AVERAGE-BANDWIDTH=987816,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,AVERAGE-BANDWIDTH=155643,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=218705,AVERAGE-BANDWIDTH=159070,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,AVERAGE-BANDWIDTH=983710,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group",SUBTITLES="default-text-group" #EXT-X-STREAM-INF:BANDWIDTH=1150006,AVERAGE-BANDWIDTH=984507,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,AVERAGE-BANDWIDTH=153342,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=214292,AVERAGE-BANDWIDTH=156327,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,AVERAGE-BANDWIDTH=974563,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" #EXT-X-STREAM-INF:BANDWIDTH=1105131,AVERAGE-BANDWIDTH=983986,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,AVERAGE-BANDWIDTH=974563,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group",SUBTITLES="default-text-group" #EXT-X-STREAM-INF:BANDWIDTH=1105131,AVERAGE-BANDWIDTH=983986,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,AVERAGE-BANDWIDTH=986776,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" #EXT-X-STREAM-INF:BANDWIDTH=1152421,AVERAGE-BANDWIDTH=987816,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,AVERAGE-BANDWIDTH=155643,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=218705,AVERAGE-BANDWIDTH=159070,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,AVERAGE-BANDWIDTH=977986,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" #EXT-X-STREAM-INF:BANDWIDTH=1111149,AVERAGE-BANDWIDTH=987362,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,AVERAGE-BANDWIDTH=155643,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=218705,AVERAGE-BANDWIDTH=159070,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,AVERAGE-BANDWIDTH=974563,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group" #EXT-X-STREAM-INF:BANDWIDTH=55555,AVERAGE-BANDWIDTH=983986,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,AVERAGE-BANDWIDTH=378244,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=412719,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,AVERAGE-BANDWIDTH=983710,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="default-audio-group",SUBTITLES="default-text-group" #EXT-X-STREAM-INF:BANDWIDTH=1150006,AVERAGE-BANDWIDTH=984507,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,AVERAGE-BANDWIDTH=153342,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8" #EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=214292,AVERAGE-BANDWIDTH=156327,CODECS="avc1.64001e",RESOLUTION=640x360,URI="bear-640x360-video-iframe.m3u8"

View File

@ -330,8 +330,7 @@ MediaPlaylist::MediaPlaylist(const HlsParams& hls_params,
: hls_params_(hls_params), : hls_params_(hls_params),
file_name_(file_name), file_name_(file_name),
name_(name), name_(name),
group_id_(group_id), group_id_(group_id) {}
bandwidth_estimator_(BandwidthEstimator::kUseAllBlocks) {}
MediaPlaylist::~MediaPlaylist() {} MediaPlaylist::~MediaPlaylist() {}

View File

@ -262,9 +262,8 @@ TEST_F(MediaPlaylistMultiSegmentTest, GetBitrateFromSegments) {
media_playlist_->AddSegment("file2.ts", 10 * kTimeScale, 20 * kTimeScale, media_playlist_->AddSegment("file2.ts", 10 * kTimeScale, 20 * kTimeScale,
kZeroByteOffset, 5 * kMBytes); kZeroByteOffset, 5 * kMBytes);
// Max bitrate is 2000Kb/s.
EXPECT_EQ(2000000u, media_playlist_->MaxBitrate()); EXPECT_EQ(2000000u, media_playlist_->MaxBitrate());
EXPECT_EQ(1142858u, media_playlist_->AvgBitrate()); EXPECT_EQ(1600000u, media_playlist_->AvgBitrate());
} }
TEST_F(MediaPlaylistMultiSegmentTest, GetLongestSegmentDuration) { TEST_F(MediaPlaylistMultiSegmentTest, GetLongestSegmentDuration) {

View File

@ -6,71 +6,41 @@
#include "packager/mpd/base/bandwidth_estimator.h" #include "packager/mpd/base/bandwidth_estimator.h"
#include <algorithm>
#include <cmath> #include <cmath>
#include "packager/base/logging.h" #include "packager/base/logging.h"
namespace shaka { namespace shaka {
BandwidthEstimator::BandwidthEstimator(size_t num_blocks) BandwidthEstimator::BandwidthEstimator() = default;
: sliding_queue_(num_blocks) {} BandwidthEstimator::~BandwidthEstimator() = default;
BandwidthEstimator::~BandwidthEstimator() {}
void BandwidthEstimator::AddBlock(uint64_t size, double duration) { void BandwidthEstimator::AddBlock(uint64_t size_in_bytes, double duration) {
if (size == 0 || duration == 0) { if (size_in_bytes == 0 || duration == 0) {
LOG(WARNING) << "Ignore block with size=" << size LOG(WARNING) << "Ignore block with size=" << size_in_bytes
<< ", duration=" << duration; << ", duration=" << duration;
return; return;
} }
const int kBitsInByte = 8; const int kBitsInByte = 8;
const double bits_per_second_reciprocal = duration / (kBitsInByte * size); const uint64_t size_in_bits = size_in_bytes * kBitsInByte;
sliding_queue_.Add(bits_per_second_reciprocal); total_size_in_bits_ += size_in_bits;
total_duration_ += duration;
const uint64_t bitrate = static_cast<uint64_t>(ceil(size_in_bits / duration));
max_bitrate_ = std::max(bitrate, max_bitrate_);
} }
uint64_t BandwidthEstimator::Estimate() const { uint64_t BandwidthEstimator::Estimate() const {
return sliding_queue_.size() == 0 if (total_duration_ == 0)
? 0 return 0;
: static_cast<uint64_t>( return static_cast<uint64_t>(ceil(total_size_in_bits_ / total_duration_));
ceil(sliding_queue_.size() / sliding_queue_.sum()));
} }
uint64_t BandwidthEstimator::Max() const { uint64_t BandwidthEstimator::Max() const {
// The first element has minimum "bits per second reciprocal", thus the return max_bitrate_;
// reverse is maximum "bits per second".
return sliding_queue_.size() == 0
? 0
: static_cast<uint64_t>(ceil(1 / sliding_queue_.min()));
}
BandwidthEstimator::SlidingQueue::SlidingQueue(size_t window_size)
: window_size_(window_size) {}
void BandwidthEstimator::SlidingQueue::Add(double value) {
// Remove elements if needed to form a monotonic non-decreasing sequence.
while (!min_.empty() && min_.back() > value)
min_.pop_back();
min_.push_back(value);
if (window_size_ == kUseAllBlocks) {
size_++;
sum_ += value;
min_.resize(1); // Keep only the minimum one.
return;
}
window_.push_back(value);
sum_ += value;
if (window_.size() <= window_size_) {
size_++;
return;
}
if (min_.front() == window_.front())
min_.pop_front();
sum_ -= window_.front();
window_.pop_front();
} }
} // namespace shaka } // namespace shaka

View File

@ -7,27 +7,23 @@
#ifndef MPD_BASE_BANDWIDTH_ESTIMATOR_H_ #ifndef MPD_BASE_BANDWIDTH_ESTIMATOR_H_
#define MPD_BASE_BANDWIDTH_ESTIMATOR_H_ #define MPD_BASE_BANDWIDTH_ESTIMATOR_H_
#include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <deque>
namespace shaka { namespace shaka {
class BandwidthEstimator { class BandwidthEstimator {
public: public:
/// @param num_blocks is the number of latest blocks to use. 0 uses all. BandwidthEstimator();
static constexpr size_t kUseAllBlocks = 0;
explicit BandwidthEstimator(size_t num_blocks);
~BandwidthEstimator(); ~BandwidthEstimator();
/// @param size is the size of the block in bytes. Should be positive. /// @param size is the size of the block in bytes. Should be positive.
/// @param duration is the length in seconds. Should be positive. /// @param duration is the length in seconds. Should be positive.
void AddBlock(uint64_t size, double duration); void AddBlock(uint64_t size_in_bytes, double duration);
/// @return The estimate bandwidth, in bits per second, from the harmonic mean /// @return The estimate bandwidth, in bits per second, calculated from the
/// of the number of blocks specified in the constructor. The value is /// sum of the sizes of every block, divided by the sum of durations
/// rounded up to the nearest integer. /// of every block, of the number of blocks specified in the
/// constructor. The value is rounded up to the nearest integer.
uint64_t Estimate() const; uint64_t Estimate() const;
/// @return The max bandwidth, in bits per second, of the number of blocks /// @return The max bandwidth, in bits per second, of the number of blocks
@ -39,45 +35,9 @@ class BandwidthEstimator {
BandwidthEstimator(const BandwidthEstimator&) = delete; BandwidthEstimator(const BandwidthEstimator&) = delete;
BandwidthEstimator& operator=(const BandwidthEstimator&) = delete; BandwidthEstimator& operator=(const BandwidthEstimator&) = delete;
// A sliding queue that provide convenient functions to get the minimum value uint64_t total_size_in_bits_ = 0;
// and the sum when window slides. double total_duration_ = 0;
class SlidingQueue { uint64_t max_bitrate_ = 0;
public:
// |window_size| defines the size of the sliding window. 0 uses all.
explicit SlidingQueue(size_t window_size);
// Add a new value. Old values may be moved out.
void Add(double value);
// Return the sum of the values in the sliding window.
double sum() const { return sum_; }
// Return the number of values in the sliding window.
double size() const { return size_; }
// Return the minimum value of the values in the sliding window.
double min() const { return min_.front(); }
private:
SlidingQueue(const SlidingQueue&) = delete;
SlidingQueue& operator=(const SlidingQueue&) = delete;
const size_t window_size_;
size_t size_ = 0;
double sum_ = 0;
// Keeps track of the values in the sliding window. Not needed if
// |window_size| is kUseAllBlocks.
std::deque<double> window_;
// Keeps track of a monotonic non-decreasing sequence of values, i.e.
// local minimum values in the sliding window. The front() is always the
// global minimum, i.e. the minimum value in the sliding window.
// This is achieved through:
// (1) New value is added to the back with the original values before it
// that are larger removed as they are no longer useful.
// (2) When a value is removed from |window_|, if it is the minimum value,
// it is also removed from |min_|; if it is not, it means the value is not
// present in |min_|.
std::deque<double> min_;
};
SlidingQueue sliding_queue_;
}; };
} // namespace shaka } // namespace shaka

View File

@ -4,116 +4,31 @@
// license that can be found in the LICENSE file or at // license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd // https://developers.google.com/open-source/licenses/bsd
#include <gtest/gtest.h>
#include <cmath>
#include "packager/base/macros.h"
#include "packager/mpd/base/bandwidth_estimator.h" #include "packager/mpd/base/bandwidth_estimator.h"
#include <gtest/gtest.h>
namespace shaka { namespace shaka {
namespace { namespace {
const size_t kNumBlocksForEstimate = 5;
const uint64_t kBitsInByte = 8; const uint64_t kBitsInByte = 8;
const int kEstimateRoundError = 1;
struct Bandwidth {
uint64_t average;
uint64_t max;
};
} // namespace } // namespace
// Make sure that averaging of 5 blocks works, and also when there aren't all 5
// blocks.
TEST(BandwidthEstimatorTest, FiveBlocksFiveBlocksAdded) {
BandwidthEstimator be(kNumBlocksForEstimate);
const double kDuration = 1.0;
const Bandwidth kExpectedResults[] = {
// Harmonic mean of [1 * 8], [1 * 8, 2 * 8], ...
// 8 is the number of bits in a byte and 1, 2, ... is from the loop
// counter below.
// Note that these are rounded up.
{8, 8}, {11, 2 * 8}, {14, 3 * 8}, {16, 4 * 8}, {18, 5 * 8},
};
static_assert(kNumBlocksForEstimate == arraysize(kExpectedResults),
"incorrect_number_of_expectations");
for (uint64_t i = 1; i <= arraysize(kExpectedResults); ++i) {
be.AddBlock(i, kDuration);
EXPECT_EQ(kExpectedResults[i - 1].average, be.Estimate());
EXPECT_EQ(kExpectedResults[i - 1].max, be.Max());
}
}
// More practical situation where a lot of blocks get added but only the last 5
// are considered for the estimate.
TEST(BandwidthEstimatorTest, FiveBlocksNormal) {
BandwidthEstimator be(kNumBlocksForEstimate);
const double kDuration = 10.0;
const uint64_t kNumBlocksToAdd = 200;
const uint64_t kExptectedEstimate = 800;
// Doesn't matter what gets passed to the estimator except for the last 5
// blocks which we add kExptectedEstimate / 8 bytes per second so that the
// estimate becomes kExptectedEstimate.
for (uint64_t i = 1; i <= kNumBlocksToAdd; ++i) {
if (i > kNumBlocksToAdd - kNumBlocksForEstimate) {
be.AddBlock(kExptectedEstimate * kDuration / kBitsInByte, kDuration);
} else {
be.AddBlock(i, kDuration);
}
}
EXPECT_NEAR(kExptectedEstimate, be.Estimate(), kEstimateRoundError);
// All blocks are of the same bitrate, so Max is the same as average.
EXPECT_NEAR(kExptectedEstimate, be.Max(), kEstimateRoundError);
}
TEST(BandwidthEstimatorTest, AllBlocks) { TEST(BandwidthEstimatorTest, AllBlocks) {
BandwidthEstimator be(BandwidthEstimator::kUseAllBlocks); BandwidthEstimator be;
const uint64_t kNumBlocksToAdd = 100; const uint64_t kNumBlocksToAdd = 100;
const double kDuration = 1.0; const double kDuration = 1.0;
for (uint64_t i = 1; i <= kNumBlocksToAdd; ++i) uint64_t total_bytes = 0;
for (uint64_t i = 1; i <= kNumBlocksToAdd; ++i) {
be.AddBlock(i, kDuration); be.AddBlock(i, kDuration);
total_bytes += i;
}
// The harmonic mean of 8, 16, ... , 800; rounded up. const uint64_t kExptectedEstimate =
const uint64_t kExptectedEstimate = 155; total_bytes * kBitsInByte / kNumBlocksToAdd;
EXPECT_EQ(kExptectedEstimate, be.Estimate()); EXPECT_EQ(kExptectedEstimate, be.Estimate());
const uint64_t kMax = 100 * 8; const uint64_t kMax = kNumBlocksToAdd * kBitsInByte;
EXPECT_EQ(kMax, be.Max()); EXPECT_EQ(kMax, be.Max());
} }
TEST(BandwidthEstimatorTest, MaxWithSlidingWindow) {
BandwidthEstimator be(kNumBlocksForEstimate);
const double kDuration = 1.0 * kBitsInByte;
// clang-format off
const uint64_t kSizes[] = {
// Sequence 1: Monotonic decreasing.
10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
// Sequence 2: Monotonic increasing.
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
// Sequence 3: Random sequence.
10, 1, 9, 6, 9, 5, 4, 9, 7, 8,
};
const uint64_t kExpectedMaxes[] = {
// Sequence 1.
10, 10, 10, 10, 10, 9, 8, 7, 6, 5,
// Sequence 2.
4, 3, 3, 4, 5, 6, 7, 8, 9, 10,
// Sequence 3.
10, 10, 10, 10, 10, 9, 9, 9, 9, 9,
};
// clang-format on
static_assert(arraysize(kSizes) == arraysize(kExpectedMaxes),
"incorrect_number_of_expectations");
for (size_t i = 0; i < arraysize(kSizes); ++i) {
be.AddBlock(kSizes[i], kDuration);
EXPECT_EQ(kExpectedMaxes[i], be.Max());
}
}
} // namespace shaka } // namespace shaka

View File

@ -115,7 +115,6 @@ Representation::Representation(
std::unique_ptr<RepresentationStateChangeListener> state_change_listener) std::unique_ptr<RepresentationStateChangeListener> state_change_listener)
: media_info_(media_info), : media_info_(media_info),
id_(id), id_(id),
bandwidth_estimator_(BandwidthEstimator::kUseAllBlocks),
mpd_options_(mpd_options), mpd_options_(mpd_options),
state_change_listener_(std::move(state_change_listener)), state_change_listener_(std::move(state_change_listener)),
allow_approximate_segment_timeline_( allow_approximate_segment_timeline_(

View File

@ -441,10 +441,6 @@ std::string GetDefaultMediaInfo() {
class SegmentTemplateTest : public RepresentationTest { class SegmentTemplateTest : public RepresentationTest {
public: public:
SegmentTemplateTest()
: bandwidth_estimator_(BandwidthEstimator::kUseAllBlocks) {}
~SegmentTemplateTest() override {}
void SetUp() override { void SetUp() override {
mpd_options_.mpd_type = MpdType::kDynamic; mpd_options_.mpd_type = MpdType::kDynamic;
representation_ = representation_ =