Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
brainfood
/
videojs-contrib-hls
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Graphs
Network
Create a new issue
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
bce88a18
authored
2015-11-02 16:09:32 -0500
by
jrivera
Committed by
David LaPalomento
2015-11-02 16:09:32 -0500
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
buffer at the current time range end instead of incrementing a variable. closes #423
1 parent
c7d5b626
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
208 additions
and
108 deletions
CHANGELOG.md
package.json
src/playlist-loader.js
src/videojs-hls.js
test/playlist-loader_test.js
test/videojs-hls_test.js
CHANGELOG.md
View file @
bce88a1
...
...
@@ -2,7 +2,7 @@ CHANGELOG
=========
## HEAD (Unreleased)
_(none)_
*
buffer at the current time range end instead of incrementing a variable. (
[
view
](
https://github.com/videojs/videojs-contrib-hls/pull/423
)
)
--------------------
...
...
package.json
View file @
bce88a1
...
...
@@ -44,7 +44,7 @@
"karma-sauce-launcher"
:
"~0.1.8"
,
"qunitjs"
:
"^1.18.0"
,
"sinon"
:
"1.10.2"
,
"video.js"
:
"^5.
0.0-rc.96
"
"video.js"
:
"^5.
1.0
"
},
"dependencies"
:
{
"pkcs7"
:
"^0.2.2"
,
...
...
src/playlist-loader.js
View file @
bce88a1
...
...
@@ -367,7 +367,17 @@
* closest playback position that is currently available.
*/
PlaylistLoader
.
prototype
.
getMediaIndexForTime_
=
function
(
time
)
{
var
i
,
j
,
segment
,
targetDuration
;
var
i
,
segment
,
originalTime
=
time
,
targetDuration
=
this
.
media_
.
targetDuration
||
10
,
numSegments
=
this
.
media_
.
segments
.
length
,
lastSegment
=
numSegments
-
1
,
startIndex
,
endIndex
,
knownStart
,
knownEnd
;
if
(
!
this
.
media_
)
{
return
0
;
...
...
@@ -379,57 +389,105 @@
return
0
;
}
// 1) Walk backward until we find the
late
st segment with timeline
// 1) Walk backward until we find the
fir
st segment with timeline
// information that is earlier than `time`
targetDuration
=
this
.
media_
.
targetDuration
||
10
;
i
=
this
.
media_
.
segments
.
length
;
while
(
i
--
)
{
for
(
i
=
lastSegment
;
i
>=
0
;
i
--
)
{
segment
=
this
.
media_
.
segments
[
i
];
if
(
segment
.
end
!==
undefined
&&
segment
.
end
<=
time
)
{
time
-=
segment
.
end
;
startIndex
=
i
+
1
;
knownStart
=
segment
.
end
;
if
(
startIndex
>=
numSegments
)
{
// The last segment claims to end *before* the time we are
// searching for so just return it
return
numSegments
;
}
break
;
}
if
(
segment
.
start
!==
undefined
&&
segment
.
start
<
time
)
{
if
(
segment
.
start
!==
undefined
&&
segment
.
start
<=
time
)
{
if
(
segment
.
end
!==
undefined
&&
segment
.
end
>
time
)
{
// we've found the target segment exactly
return
i
;
}
startIndex
=
i
;
knownStart
=
segment
.
start
;
break
;
}
}
// 2) Walk forward until we find the first segment with timeline
// information that is greater than `time`
for
(
i
=
0
;
i
<
numSegments
;
i
++
)
{
segment
=
this
.
media_
.
segments
[
i
];
if
(
segment
.
start
!==
undefined
&&
segment
.
start
>
time
)
{
endIndex
=
i
-
1
;
knownEnd
=
segment
.
start
;
if
(
endIndex
<
0
)
{
// The first segment claims to start *after* the time we are
// searching for so just return it
return
-
1
;
}
break
;
}
if
(
segment
.
end
!==
undefined
&&
segment
.
end
>
time
)
{
endIndex
=
i
;
knownEnd
=
segment
.
end
;
break
;
}
}
time
-=
segment
.
start
;
if
(
startIndex
!==
undefined
)
{
// We have a known-start point that is before our desired time so
// walk from that point forwards
time
=
time
-
knownStart
;
for
(
i
=
startIndex
;
i
<
(
endIndex
||
numSegments
);
i
++
)
{
segment
=
this
.
media_
.
segments
[
i
];
time
-=
segment
.
duration
||
targetDuration
;
if
(
time
<
0
)
{
// the segment with start information is also our best guess
// for the momment
return
i
;
}
break
;
}
if
(
i
===
endIndex
)
{
// We haven't found a segment but we did hit a known end point
// so fallback to "Algorithm Jon" - try to interpolate the segment
// index based on the known span of the timeline we are dealing with
// and the number of segments inside that span
return
startIndex
+
Math
.
floor
(
((
originalTime
-
knownStart
)
/
(
knownEnd
-
knownStart
))
*
(
endIndex
-
startIndex
));
}
i
++
;
// 2) Walk forward, testing each segment to see if `time` falls within it
for
(
j
=
i
;
j
<
this
.
media_
.
segments
.
length
;
j
++
)
{
segment
=
this
.
media_
.
segments
[
j
];
// We _still_ haven't found a segment so load the last one
return
lastSegment
;
}
else
if
(
endIndex
!==
undefined
)
{
// We _only_ have a known-end point that is after our desired time so
// walk from that point backwards
time
=
knownEnd
-
time
;
for
(
i
=
endIndex
;
i
>=
0
;
i
--
)
{
segment
=
this
.
media_
.
segments
[
i
];
time
-=
segment
.
duration
||
targetDuration
;
if
(
time
<
0
)
{
return
j
;
return
i
;
}
// 2a) If we discover a segment that has timeline information
// before finding the result segment, the playlist information
// must have been inaccurate. Start a binary search for the
// segment which contains `time`. If the guess turns out to be
// incorrect, we'll have more info to work with next time.
if
(
segment
.
start
!==
undefined
||
segment
.
end
!==
undefined
)
{
return
Math
.
floor
((
j
-
i
)
*
0.5
);
}
// We haven't found a segment so load the first one
return
0
;
}
else
{
// We known nothing so use "Algorithm A" - walk from the front
// of the playlist naively subtracking durations until we find
// a segment that contains time and return it
for
(
i
=
0
;
i
<
numSegments
;
i
++
)
{
segment
=
this
.
media_
.
segments
[
i
];
time
-=
segment
.
duration
||
targetDuration
;
if
(
time
<
0
)
{
return
i
;
}
}
// the playback position is outside the range of available
// segments so return the length
return
this
.
media_
.
segments
.
length
;
// We are out of possible candidates so load the last one...
// The last one is the least likely to overlap a buffer and therefore
// the one most likely to tell us something about the timeline
return
lastSegment
;
}
};
videojs
.
Hls
.
PlaylistLoader
=
PlaylistLoader
;
...
...
src/videojs-hls.js
View file @
bce88a1
...
...
@@ -304,13 +304,26 @@ videojs.Hls.prototype.setupSourceBuffer_ = function() {
// transition the sourcebuffer to the ended state if we've hit the end of
// the playlist
this
.
sourceBuffer
.
addEventListener
(
'updateend'
,
function
()
{
var
segmentInfo
=
this
.
pendingSegment_
,
segment
,
currentBuffered
,
timelineUpdates
;
var
segmentInfo
=
this
.
pendingSegment_
,
segment
,
playlist
,
currentMediaIndex
,
currentBuffered
,
timelineUpdates
;
// stop here if the update errored or was aborted
if
(
!
segmentInfo
)
{
return
;
}
this
.
pendingSegment_
=
null
;
// if we've buffered to the end of the video, let the MediaSource know
currentBuffered
=
this
.
findCurrentBuffered_
();
if
(
currentBuffered
.
length
&&
this
.
duration
()
===
currentBuffered
.
end
(
0
))
{
if
(
currentBuffered
.
length
&&
this
.
duration
()
===
currentBuffered
.
end
(
0
)
&&
this
.
mediaSource
.
readyState
===
'open'
)
{
this
.
mediaSource
.
endOfStream
();
}
...
...
@@ -319,26 +332,46 @@ videojs.Hls.prototype.setupSourceBuffer_ = function() {
return
;
}
// if we switched renditions don't try to add segment timeline
// information to the playlist
if
(
segmentInfo
.
playlist
.
uri
!==
this
.
playlists
.
media
().
uri
)
{
return
this
.
fillBuffer
();
}
playlist
=
this
.
playlists
.
media
();
currentMediaIndex
=
segmentInfo
.
mediaIndex
+
(
segmentInfo
.
mediaSequence
-
playlist
.
mediaSequence
);
// annotate the segment with any start and end time information
// added by the media processing
segment
=
segmentInfo
.
playlist
.
segments
[
segmentInfo
.
mediaIndex
];
segment
=
playlist
.
segments
[
currentMediaIndex
];
timelineUpdates
=
videojs
.
Hls
.
bufferedAdditions_
(
segmentInfo
.
buffered
,
this
.
tech_
.
buffered
());
timelineUpdates
.
forEach
(
function
(
update
)
{
timelineUpdates
.
forEach
(
function
(
update
)
{
if
(
segment
)
{
if
(
update
.
start
!==
undefined
)
{
segment
.
start
=
update
.
start
;
}
if
(
update
.
end
!==
undefined
)
{
segment
.
end
=
update
.
end
;
}
}
});
if
(
timelineUpdates
.
length
)
{
this
.
updateDuration
(
segmentInfo
.
playlist
);
this
.
updateDuration
(
playlist
);
// check if it's time to download the next segment
this
.
fillBuffer
();
return
;
}
// check if it's time to download the next segment
this
.
checkBuffer_
();
// the last segment append must have been entirely in the
// already buffered time ranges. just buffer forward until we
// find a segment that adds to the buffered time ranges and
// improves subsequent media index calculations.
this
.
fillBuffer
(
currentMediaIndex
+
1
);
return
;
}.
bind
(
this
));
};
...
...
@@ -426,11 +459,8 @@ videojs.Hls.prototype.setCurrentTime = function(currentTime) {
this
.
cancelKeyXhr
();
}
// clear out the segment being processed
this
.
pendingSegment_
=
null
;
// begin filling the buffer at the new position
this
.
fillBuffer
(
currentTime
);
this
.
fillBuffer
(
this
.
playlists
.
getMediaIndexForTime_
(
currentTime
)
);
};
videojs
.
Hls
.
prototype
.
duration
=
function
()
{
...
...
@@ -465,15 +495,25 @@ videojs.Hls.prototype.updateDuration = function(playlist) {
this
.
mediaSource
.
duration
=
newDuration
;
this
.
tech_
.
trigger
(
'durationchange'
);
this
.
mediaSource
.
removeEventListener
(
'sourceopen'
,
setDuration
);
}.
bind
(
this
);
}.
bind
(
this
),
seekable
=
this
.
seekable
();
// TODO: Move to videojs-contrib-media-sources
if
(
seekable
.
length
&&
newDuration
===
Infinity
)
{
if
(
isNaN
(
oldDuration
))
{
oldDuration
=
0
;
}
newDuration
=
Math
.
max
(
oldDuration
,
seekable
.
end
(
0
)
+
playlist
.
targetDuration
*
3
);
}
// if the duration has changed, invalidate the cached value
if
(
oldDuration
!==
newDuration
)
{
if
(
this
.
mediaSource
.
readyState
===
'open'
)
{
if
(
this
.
mediaSource
.
readyState
!==
'open'
)
{
this
.
mediaSource
.
addEventListener
(
'sourceopen'
,
setDuration
);
}
else
if
(
!
this
.
sourceBuffer
||
!
this
.
sourceBuffer
.
updating
)
{
this
.
mediaSource
.
duration
=
newDuration
;
this
.
tech_
.
trigger
(
'durationchange'
);
}
else
{
this
.
mediaSource
.
addEventListener
(
'sourceopen'
,
setDuration
);
}
}
};
...
...
@@ -507,6 +547,8 @@ videojs.Hls.prototype.cancelSegmentXhr = function() {
this
.
segmentXhr_
.
abort
();
this
.
segmentXhr_
=
null
;
}
// clear out the segment being processed
this
.
pendingSegment_
=
null
;
};
/**
...
...
@@ -667,11 +709,17 @@ videojs.Hls.prototype.stopCheckingBuffer_ = function() {
*/
videojs
.
Hls
.
prototype
.
findCurrentBuffered_
=
function
()
{
var
tech
=
this
.
tech_
,
currentTime
=
tech
.
currentTime
(),
buffered
=
this
.
tech_
.
buffered
(),
ranges
,
i
;
i
,
tech
=
this
.
tech_
,
// !!The order of the next two lines is important!!
// `currentTime` must be equal-to or greater-than the start of the
// buffered range. Flash executes out-of-process so, every value can
// change behind the scenes from line-to-line. By reading `currentTime`
// after `buffered`, we ensure that it is always a current or later
// value during playback.
buffered
=
tech
.
buffered
(),
currentTime
=
tech
.
currentTime
();
if
(
buffered
&&
buffered
.
length
)
{
// Search for a range containing the play-head
...
...
@@ -697,13 +745,13 @@ videojs.Hls.prototype.findCurrentBuffered_ = function() {
* @param seekToTime (optional) {number} the offset into the downloaded segment
* to seek to, in seconds
*/
videojs
.
Hls
.
prototype
.
fillBuffer
=
function
(
seekToTime
)
{
videojs
.
Hls
.
prototype
.
fillBuffer
=
function
(
mediaIndex
)
{
var
tech
=
this
.
tech_
,
currentTime
=
tech
.
currentTime
(),
currentBuffered
=
this
.
findCurrentBuffered_
(),
currentBufferedEnd
=
0
,
bufferedTime
=
0
,
mediaIndex
=
0
,
segment
,
segmentInfo
;
...
...
@@ -739,39 +787,46 @@ videojs.Hls.prototype.fillBuffer = function(seekToTime) {
return
;
}
// find the next segment to download
if
(
typeof
seekToTime
===
'number'
)
{
mediaIndex
=
this
.
playlists
.
getMediaIndexForTime_
(
seekToTime
);
}
else
if
(
currentBuffered
&&
currentBuffered
.
length
)
{
mediaIndex
=
this
.
playlists
.
getMediaIndexForTime_
(
currentBuffered
.
end
(
0
));
bufferedTime
=
Math
.
max
(
0
,
currentBuffered
.
end
(
0
)
-
currentTime
);
if
(
mediaIndex
===
undefined
)
{
if
(
currentBuffered
&&
currentBuffered
.
length
)
{
currentBufferedEnd
=
currentBuffered
.
end
(
0
);
mediaIndex
=
this
.
playlists
.
getMediaIndexForTime_
(
currentBufferedEnd
);
bufferedTime
=
Math
.
max
(
0
,
currentBufferedEnd
-
currentTime
);
// if there is plenty of content in the buffer and we're not
// seeking, relax for awhile
if
(
bufferedTime
>=
videojs
.
Hls
.
GOAL_BUFFER_LENGTH
)
{
return
;
}
}
else
{
mediaIndex
=
this
.
playlists
.
getMediaIndexForTime_
(
this
.
tech_
.
currentTime
());
}
}
segment
=
this
.
playlists
.
media
().
segments
[
mediaIndex
];
// if the video has finished downloading
, stop trying to buffer
// if the video has finished downloading
if
(
!
segment
)
{
return
;
}
//
if there is plenty of content in the buffer and we're not
//
seeking, relax for awhile
if
(
t
ypeof
seekToTime
!==
'number'
&&
bufferedTime
>=
videojs
.
Hls
.
GOAL_BUFFER_LENGTH
)
{
return
;
//
we have entered a state where we are fetching the same segment,
//
try to walk forward
if
(
t
his
.
lastSegmentLoaded_
&&
this
.
lastSegmentLoaded_
===
this
.
playlistUriToUrl
(
segment
.
uri
)
)
{
return
this
.
fillBuffer
(
mediaIndex
+
1
)
;
}
// package up all the work to append the segment
segmentInfo
=
{
// resolve the segment URL relative to the playlist
uri
:
this
.
playlistUriToUrl
(
segment
.
uri
),
// the segment's mediaIndex
at the time it was receiv
ed
// the segment's mediaIndex
& mediaSequence at the time it was request
ed
mediaIndex
:
mediaIndex
,
mediaSequence
:
this
.
playlists
.
media
().
mediaSequence
,
// the segment's playlist
playlist
:
this
.
playlists
.
media
(),
//
optionally, a time offset to seek to within the segment
offset
:
seekToTime
,
//
The state of the buffer when this segment was requested
currentBufferedEnd
:
currentBufferedEnd
,
// unencrypted bytes of the segment
bytes
:
null
,
// when a key is defined for this segment, the encrypted bytes
...
...
@@ -856,6 +911,7 @@ videojs.Hls.prototype.loadSegment = function(segmentInfo) {
return
;
}
self
.
lastSegmentLoaded_
=
segmentInfo
.
uri
;
self
.
setBandwidth
(
request
);
if
(
segment
.
key
)
{
...
...
@@ -944,41 +1000,33 @@ videojs.Hls.prototype.drainBuffer = function(event) {
event
=
event
||
{};
if
(
segmentInfo
.
mediaIndex
>
0
)
{
segmentTimestampOffset
=
videojs
.
Hls
.
Playlist
.
duration
(
segmentInfo
.
playlist
,
playlist
.
mediaSequence
+
segmentInfo
.
mediaIndex
);
}
// If we have seeked into a non-buffered time-range, remove all buffered
// time-ranges because they could have been incorrectly placed originally
if
(
this
.
tech_
.
seeking
()
&&
outsideBufferedRanges
)
{
if
(
hasBufferedContent
)
{
// In Chrome, it seems that too many independent buffered time-ranges can
// cause playback to fail to resume when seeking so just kill all of them
this
.
sourceBuffer
.
remove
(
0
,
Infinity
);
return
;
}
// If there are discontinuities in the playlist, we can't be sure of anything
// related to time so we reset the timestamp offset and start appending data
// anew on every seek
if
(
segmentInfo
.
playlist
.
discontinuityStarts
.
length
)
{
if
(
segmentInfo
.
mediaIndex
>
0
)
{
segmentTimestampOffset
=
videojs
.
Hls
.
Playlist
.
duration
(
segmentInfo
.
playlist
,
segmentInfo
.
mediaIndex
);
}
// Now that the forward buffer is clear, we have to set timestamp offset to
// the start of the buffered region
this
.
sourceBuffer
.
timestampOffset
=
segmentTimestampOffset
;
}
}
else
if
(
segment
.
discontinuity
)
{
}
else
if
(
segment
.
discontinuity
&&
currentBuffered
.
length
)
{
// If we aren't seeking and are crossing a discontinuity, we should set
// timestampOffset for new segments to be appended the end of the current
// buffered time-range
this
.
sourceBuffer
.
timestampOffset
=
currentBuffered
.
end
(
0
);
}
else
if
(
!
hasBufferedContent
&&
this
.
tech_
.
currentTime
()
>
0.05
)
{
// If we are trying to play at a position that is not zero but we aren't
// currently seeking according to the video element
this
.
sourceBuffer
.
timestampOffset
=
segmentTimestampOffset
;
}
if
(
currentBuffered
.
length
)
{
// Chrome 45 stalls if appends overlap the playhead
this
.
sourceBuffer
.
appendWindowStart
=
Math
.
min
(
this
.
tech_
.
currentTime
(),
currentBuffered
.
end
(
0
));
}
else
{
this
.
sourceBuffer
.
appendWindowStart
=
0
;
}
this
.
pendingSegment_
.
buffered
=
this
.
tech_
.
buffered
();
// the segment is asynchronously added to the current buffered data
...
...
test/playlist-loader_test.js
View file @
bce88a1
...
...
@@ -653,8 +653,8 @@
equal
(
loader
.
getMediaIndexForTime_
(
3
),
0
,
'time three is index zero'
);
equal
(
loader
.
getMediaIndexForTime_
(
10
),
2
,
'time 10 is index 2'
);
equal
(
loader
.
getMediaIndexForTime_
(
22
),
3
,
'time greater than the length is index
3
'
);
2
,
'time greater than the length is index
2
'
);
});
test
(
'returns the lower index when calculating for a segment boundary'
,
function
()
{
...
...
@@ -683,9 +683,9 @@
'1002.ts\n'
);
loader
.
media
().
segments
[
0
].
start
=
150
;
equal
(
loader
.
getMediaIndexForTime_
(
0
),
0
,
'the lowest returned value is zero
'
);
equal
(
loader
.
getMediaIndexForTime_
(
45
),
0
,
'expired content returns zero
'
);
equal
(
loader
.
getMediaIndexForTime_
(
75
),
0
,
'expired content returns zero
'
);
equal
(
loader
.
getMediaIndexForTime_
(
0
),
-
1
,
'the lowest returned value is negative one
'
);
equal
(
loader
.
getMediaIndexForTime_
(
45
),
-
1
,
'expired content returns negative one
'
);
equal
(
loader
.
getMediaIndexForTime_
(
75
),
-
1
,
'expired content returns negative one
'
);
equal
(
loader
.
getMediaIndexForTime_
(
50
+
100
),
0
,
'calculates the earliest available position'
);
equal
(
loader
.
getMediaIndexForTime_
(
50
+
100
+
2
),
0
,
'calculates within the first segment'
);
equal
(
loader
.
getMediaIndexForTime_
(
50
+
100
+
2
),
0
,
'calculates within the first segment'
);
...
...
test/videojs-hls_test.js
View file @
bce88a1
...
...
@@ -218,6 +218,7 @@ module('HLS', {
var
el
=
document
.
createElement
(
'div'
);
el
.
id
=
'vjs_mock_flash_'
+
nextId
++
;
el
.
className
=
'vjs-tech vjs-mock-flash'
;
el
.
duration
=
Infinity
;
el
.
vjs_load
=
function
()
{};
el
.
vjs_getProperty
=
function
(
attr
)
{
if
(
attr
===
'buffered'
)
{
...
...
@@ -1131,7 +1132,7 @@ test('buffers based on the correct TimeRange if multiple ranges exist', function
return
videojs
.
createTimeRange
(
buffered
);
};
currentTime
=
8
;
buffered
=
[[
0
,
10
],
[
20
,
4
0
]];
buffered
=
[[
0
,
10
],
[
20
,
3
0
]];
standardXHRResponse
(
requests
[
0
]);
standardXHRResponse
(
requests
[
1
]);
...
...
@@ -1144,14 +1145,9 @@ test('buffers based on the correct TimeRange if multiple ranges exist', function
currentTime
=
22
;
player
.
tech_
.
hls
.
sourceBuffer
.
trigger
(
'updateend'
);
player
.
tech_
.
hls
.
checkBuffer_
();
strictEqual
(
requests
.
length
,
2
,
'made no additional requests'
);
buffered
=
[[
0
,
10
],
[
20
,
30
]];
player
.
tech_
.
hls
.
checkBuffer_
();
standardXHRResponse
(
requests
[
2
]);
strictEqual
(
requests
.
length
,
3
,
'made three requests'
);
strictEqual
(
requests
[
2
].
url
,
absoluteUrl
(
'manifest/media-0000
4
.ts'
),
absoluteUrl
(
'manifest/media-0000
3
.ts'
),
'made segment request'
);
});
...
...
@@ -1381,7 +1377,7 @@ test('seeking in an empty playlist is a non-erroring noop', function() {
equal
(
requests
.
length
,
requestsLength
,
'made no additional requests'
);
});
test
(
'
duration i
s Infinity for live playlists'
,
function
()
{
test
(
'
tech\'s duration report
s Infinity for live playlists'
,
function
()
{
player
.
src
({
src
:
'http://example.com/manifest/missingEndlist.m3u8'
,
type
:
'application/vnd.apple.mpegurl'
...
...
@@ -1390,9 +1386,13 @@ test('duration is Infinity for live playlists', function() {
standardXHRResponse
(
requests
[
0
]);
strictEqual
(
player
.
tech_
.
hls
.
mediaSource
.
duration
,
strictEqual
(
player
.
tech_
.
duration
(),
Infinity
,
'duration on the tech is infinity'
);
notEqual
(
player
.
tech_
.
hls
.
mediaSource
.
duration
,
Infinity
,
'duration
is
infinity'
);
'duration
on the mediaSource is not
infinity'
);
});
test
(
'live playlist starts three target durations before live'
,
function
()
{
...
...
@@ -1644,7 +1644,7 @@ test('calls mediaSource\'s timestampOffset on discontinuity', function() {
});
test
(
'sets timestampOffset when seeking with discontinuities'
,
function
()
{
var
removes
=
[],
timeRange
=
videojs
.
createTimeRange
(
0
,
10
);
var
timeRange
=
videojs
.
createTimeRange
(
0
,
10
);
player
.
src
({
src
:
'discontinuity.m3u8'
,
...
...
@@ -1670,18 +1670,12 @@ test('sets timestampOffset when seeking with discontinuities', function() {
'3.ts\n'
+
'#EXT-X-ENDLIST\n'
);
player
.
tech_
.
hls
.
sourceBuffer
.
timestampOffset
=
0
;
player
.
tech_
.
hls
.
sourceBuffer
.
remove
=
function
(
start
,
end
)
{
timeRange
=
videojs
.
createTimeRange
();
removes
.
push
([
start
,
end
]);
};
player
.
currentTime
(
21
);
clock
.
tick
(
1
);
equal
(
requests
.
shift
().
aborted
,
true
,
'aborted first request'
);
standardXHRResponse
(
requests
.
pop
());
// 3.ts
clock
.
tick
(
1000
);
equal
(
player
.
tech_
.
hls
.
sourceBuffer
.
timestampOffset
,
20
,
'timestampOffset starts at zero'
);
equal
(
removes
.
length
,
1
,
'remove was called'
);
});
test
(
'can seek before the source buffer opens'
,
function
()
{
...
...
Please
register
or
sign in
to post a comment