8f6de665 by David LaPalomento

Clear buffered segments on seek

If we're approaching a discontinuity, there may be segments queued up waiting to be appended. Make sure those are cleared if we seek. Add tests.
1 parent e7fcc487
...@@ -239,6 +239,9 @@ var ...@@ -239,6 +239,9 @@ var
239 segmentXhr.abort(); 239 segmentXhr.abort();
240 } 240 }
241 241
242 // clear out any buffered segments
243 segmentBuffer = [];
244
242 // begin filling the buffer at the new position 245 // begin filling the buffer at the new position
243 fillBuffer(currentTime * 1000); 246 fillBuffer(currentTime * 1000);
244 }; 247 };
......
...@@ -1050,6 +1050,100 @@ test('does not break if the playlist has no segments', function() { ...@@ -1050,6 +1050,100 @@ test('does not break if the playlist has no segments', function() {
1050 strictEqual(requests.length, 1, 'no requests for non-existent segments were queued'); 1050 strictEqual(requests.length, 1, 'no requests for non-existent segments were queued');
1051 }); 1051 });
1052 1052
1053 test('waits until the buffer is empty before appending bytes at a discontinuity', function() {
1054 var aborts = 0, currentTime, bufferEnd;
1055
1056 player.src({
1057 src: 'disc.m3u8',
1058 type: 'application/vnd.apple.mpegurl'
1059 });
1060 player.hls.mediaSource.trigger({
1061 type: 'sourceopen'
1062 });
1063 player.currentTime = function() { return currentTime; };
1064 player.buffered = function() {
1065 return videojs.createTimeRange(0, bufferEnd);
1066 };
1067 player.hls.sourceBuffer.abort = function() {
1068 aborts++;
1069 };
1070
1071 requests.pop().respond(200, null,
1072 '#EXTM3U\n' +
1073 '#EXTINF:10,0\n' +
1074 '1.ts\n' +
1075 '#EXT-X-DISCONTINUITY\n' +
1076 '#EXTINF:10,0\n' +
1077 '2.ts\n');
1078 standardXHRResponse(requests.pop());
1079
1080 // play to 6s to trigger the next segment request
1081 currentTime = 6;
1082 bufferEnd = 10;
1083 player.trigger('timeupdate');
1084 strictEqual(aborts, 0, 'no aborts before the buffer empties');
1085
1086 standardXHRResponse(requests.pop());
1087 strictEqual(aborts, 0, 'no aborts before the buffer empties');
1088
1089 // pretend the buffer has emptied
1090 player.trigger('waiting');
1091 strictEqual(aborts, 1, 'aborted before appending the new segment');
1092 });
1093
1094 test('clears the segment buffer on seek', function() {
1095 var aborts = 0, tags = [], currentTime, bufferEnd, oldCurrentTime;
1096
1097 videojs.Hls.SegmentParser = mockSegmentParser(tags);
1098
1099 player.src({
1100 src: 'disc.m3u8',
1101 type: 'application/vnd.apple.mpegurl'
1102 });
1103 player.hls.mediaSource.trigger({
1104 type: 'sourceopen'
1105 });
1106 oldCurrentTime = player.currentTime;
1107 player.currentTime = function(time) {
1108 if (time !== undefined) {
1109 return oldCurrentTime.call(player, time);
1110 }
1111 return currentTime;
1112 };
1113 player.buffered = function() {
1114 return videojs.createTimeRange(0, bufferEnd);
1115 };
1116 player.hls.sourceBuffer.abort = function() {
1117 aborts++;
1118 };
1119
1120 requests.pop().respond(200, null,
1121 '#EXTM3U\n' +
1122 '#EXTINF:10,0\n' +
1123 '1.ts\n' +
1124 '#EXT-X-DISCONTINUITY\n' +
1125 '#EXTINF:10,0\n' +
1126 '2.ts\n');
1127 standardXHRResponse(requests.pop());
1128
1129 // play to 6s to trigger the next segment request
1130 currentTime = 6;
1131 bufferEnd = 10;
1132 player.trigger('timeupdate');
1133
1134 standardXHRResponse(requests.pop());
1135
1136 // seek back to the beginning
1137 player.currentTime(0);
1138 tags.push({ pts: 0, bytes: 0 });
1139 standardXHRResponse(requests.pop());
1140 strictEqual(aborts, 1, 'aborted once for the seek');
1141
1142 // the source buffer empties. is 2.ts still in the segment buffer?
1143 player.trigger('waiting');
1144 strictEqual(aborts, 1, 'cleared the segment buffer on a seek');
1145 });
1146
1053 test('disposes the playlist loader', function() { 1147 test('disposes the playlist loader', function() {
1054 var disposes = 0, player, loaderDispose; 1148 var disposes = 0, player, loaderDispose;
1055 player = createPlayer(); 1149 player = createPlayer();
......