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
aac49993
authored
2016-02-09 10:26:52 -0500
by
jrivera
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Tests for endOfStream and segment.duration tracking behavior in updateEndHandler
1 parent
cf295e56
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
137 additions
and
17 deletions
src/videojs-hls.js
test/videojs-hls_test.js
src/videojs-hls.js
View file @
aac4999
...
...
@@ -298,7 +298,7 @@ videojs.Hls.findSoleUncommonTimeRangesEnd_ = function(original, update) {
};
/**
* Updates segment with information about it
'
s end-point in time and, optionally,
* Updates segment with information about its end-point in time and, optionally,
* the segment duration if we have enough information to determine a segment duration
* accurately.
* @param playlist {object} a media playlist object
...
...
@@ -322,7 +322,7 @@ videojs.HlsHandler.prototype.updateSegmentMetadata_ = function(playlist, segment
// fix up segment durations based on segment end data
if
(
!
previousSegment
)
{
// first segment is always has a start time of 0 making it
'
s duration
// first segment is always has a start time of 0 making its duration
// equal to the segment end
segment
.
duration
=
segment
.
end
;
}
else
if
(
previousSegment
.
end
)
{
...
...
@@ -337,9 +337,9 @@ videojs.HlsHandler.prototype.updateSegmentMetadata_ = function(playlist, segment
* @param playlist {object} a media playlist object
* @param segmentIndex {number} the index of segment we last appended
* @param currentBuffered {object} the buffered region that currentTime resides in
* @return {boolean} whether
or not endOfStream was called
on the MediaSource
* @return {boolean} whether
the calling function should call endOfStream
on the MediaSource
*/
videojs
.
HlsHandler
.
prototype
.
maybe
EndOfStream_
=
function
(
playlist
,
segmentIndex
,
currentBuffered
)
{
videojs
.
HlsHandler
.
prototype
.
is
EndOfStream_
=
function
(
playlist
,
segmentIndex
,
currentBuffered
)
{
var
segments
=
playlist
.
segments
,
appendedLastSegment
,
...
...
@@ -358,14 +358,9 @@ videojs.HlsHandler.prototype.maybeEndOfStream_ = function(playlist, segmentIndex
// if we've buffered to the end of the video, we need to call endOfStream
// so that MediaSources can trigger the `ended` event when it runs out of
// buffered data instead of waiting for me
if
(
playlist
.
endList
&&
this
.
mediaSource
.
readyState
===
'open'
&&
(
appendedLastSegment
||
bufferedToEnd
))
{
this
.
mediaSource
.
endOfStream
();
return
true
;
}
return
false
;
return
playlist
.
endList
&&
this
.
mediaSource
.
readyState
===
'open'
&&
(
appendedLastSegment
||
bufferedToEnd
);
};
var
parseCodecs
=
function
(
codecs
)
{
...
...
@@ -1310,7 +1305,8 @@ videojs.HlsHandler.prototype.updateEndHandler_ = function () {
currentMediaIndex
,
currentBuffered
,
seekable
,
timelineUpdate
;
timelineUpdate
,
isEndOfStream
;
// stop here if the update errored or was aborted
if
(
!
segmentInfo
)
{
...
...
@@ -1330,10 +1326,14 @@ videojs.HlsHandler.prototype.updateEndHandler_ = function () {
segments
=
playlist
.
segments
;
currentMediaIndex
=
segmentInfo
.
mediaIndex
+
(
segmentInfo
.
mediaSequence
-
playlist
.
mediaSequence
);
currentBuffered
=
this
.
findBufferedRange_
();
isEndOfStream
=
this
.
isEndOfStream_
(
playlist
,
currentMediaIndex
,
currentBuffered
);
// if we switched renditions don't try to add segment timeline
// information to the playlist
if
(
segmentInfo
.
playlist
.
uri
!==
this
.
playlists
.
media
().
uri
)
{
if
(
isEndOfStream
)
{
return
this
.
mediaSource
.
endOfStream
();
}
return
this
.
fillBuffer
();
}
...
...
@@ -1366,8 +1366,8 @@ videojs.HlsHandler.prototype.updateEndHandler_ = function () {
// If we decide to signal the end of stream, then we can return instead
// of trying to fetch more segments
if
(
this
.
maybeEndOfStream_
(
playlist
,
currentMediaIndex
,
currentBuffered
)
)
{
return
;
if
(
isEndOfStream
)
{
return
this
.
mediaSource
.
endOfStream
()
;
}
if
(
timelineUpdate
!==
null
||
...
...
test/videojs-hls_test.js
View file @
aac4999
...
...
@@ -2144,6 +2144,79 @@ test('tracks segment end times as they are buffered', function() {
equal
(
player
.
tech_
.
hls
.
mediaSource
.
duration
,
10
+
9.5
,
'updated duration'
);
});
test
(
'updates first segment duration as it is buffered'
,
function
()
{
var
bufferEnd
=
0
;
player
.
src
({
src
:
'media.m3u8'
,
type
:
'application/x-mpegURL'
});
openMediaSource
(
player
);
// as new segments are downloaded, the buffer end is updated
player
.
tech_
.
buffered
=
function
()
{
return
videojs
.
createTimeRange
(
0
,
bufferEnd
);
};
requests
.
shift
().
respond
(
200
,
null
,
'#EXTM3U\n'
+
'#EXTINF:10,\n'
+
'0.ts\n'
+
'#EXTINF:10,\n'
+
'1.ts\n'
+
'#EXT-X-ENDLIST\n'
);
// 0.ts is shorter than advertised
standardXHRResponse
(
requests
.
shift
());
equal
(
player
.
tech_
.
hls
.
mediaSource
.
duration
,
20
,
'original duration is from the m3u8'
);
equal
(
player
.
tech_
.
hls
.
playlists
.
media
().
segments
[
0
].
duration
,
10
,
'segment duration initially based on playlist'
);
bufferEnd
=
9.5
;
player
.
tech_
.
hls
.
sourceBuffer
.
trigger
(
'update'
);
player
.
tech_
.
hls
.
sourceBuffer
.
trigger
(
'updateend'
);
equal
(
player
.
tech_
.
hls
.
playlists
.
media
().
segments
[
0
].
duration
,
9.5
,
'updated segment duration'
);
});
test
(
'updates segment durations as they are buffered'
,
function
()
{
var
bufferEnd
=
0
;
player
.
src
({
src
:
'media.m3u8'
,
type
:
'application/x-mpegURL'
});
openMediaSource
(
player
);
// as new segments are downloaded, the buffer end is updated
player
.
tech_
.
buffered
=
function
()
{
return
videojs
.
createTimeRange
(
0
,
bufferEnd
);
};
requests
.
shift
().
respond
(
200
,
null
,
'#EXTM3U\n'
+
'#EXTINF:10,\n'
+
'0.ts\n'
+
'#EXTINF:10,\n'
+
'1.ts\n'
+
'#EXT-X-ENDLIST\n'
);
// 0.ts is shorter than advertised
standardXHRResponse
(
requests
.
shift
());
equal
(
player
.
tech_
.
hls
.
mediaSource
.
duration
,
20
,
'original duration is from the m3u8'
);
equal
(
player
.
tech_
.
hls
.
playlists
.
media
().
segments
[
1
].
duration
,
10
,
'segment duration initially based on playlist'
);
bufferEnd
=
9.5
;
player
.
tech_
.
hls
.
sourceBuffer
.
trigger
(
'update'
);
player
.
tech_
.
hls
.
sourceBuffer
.
trigger
(
'updateend'
);
clock
.
tick
(
1
);
standardXHRResponse
(
requests
.
shift
());
bufferEnd
=
19
;
player
.
tech_
.
hls
.
sourceBuffer
.
trigger
(
'update'
);
player
.
tech_
.
hls
.
sourceBuffer
.
trigger
(
'updateend'
);
equal
(
player
.
tech_
.
hls
.
playlists
.
media
().
segments
[
1
].
duration
,
9.5
,
'updated segment duration'
);
});
QUnit
.
skip
(
'seeking does not fail when targeted between segments'
,
function
()
{
var
currentTime
,
segmentUrl
;
player
.
src
({
...
...
@@ -2428,7 +2501,7 @@ test('can be disposed before finishing initialization', function() {
}
});
test
(
'calls end
ed() on the media source at the end of a playlis
t'
,
function
()
{
test
(
'calls end
OfStream on the media source after appending the last segmen
t'
,
function
()
{
var
endOfStreams
=
0
,
buffered
=
[[]];
player
.
src
({
src
:
'http://example.com/media.m3u8'
,
...
...
@@ -2441,11 +2514,15 @@ test('calls ended() on the media source at the end of a playlist', function() {
player
.
tech_
.
hls
.
mediaSource
.
endOfStream
=
function
()
{
endOfStreams
++
;
};
player
.
currentTime
(
20
);
clock
.
tick
(
1
);
// playlist response
requests
.
shift
().
respond
(
200
,
null
,
'#EXTM3U\n'
+
'#EXTINF:10,\n'
+
'0.ts\n'
+
'#EXTINF:10,\n'
+
'1.ts\n'
+
'#EXT-X-ENDLIST\n'
);
// segment response
requests
[
0
].
response
=
new
ArrayBuffer
(
17
);
...
...
@@ -2454,7 +2531,50 @@ test('calls ended() on the media source at the end of a playlist', function() {
buffered
=
[[
0
,
10
]];
player
.
tech_
.
hls
.
sourceBuffer
.
trigger
(
'updateend'
);
strictEqual
(
endOfStreams
,
1
,
'ended media source'
);
strictEqual
(
endOfStreams
,
1
,
'called endOfStream on the media source'
);
});
test
(
'calls endOfStream on the media source when the current buffer ends at duration'
,
function
()
{
var
endOfStreams
=
0
,
buffered
=
[[]];
player
.
src
({
src
:
'http://example.com/media.m3u8'
,
type
:
'application/vnd.apple.mpegurl'
});
openMediaSource
(
player
);
player
.
tech_
.
buffered
=
function
()
{
return
videojs
.
createTimeRanges
(
buffered
);
};
player
.
tech_
.
hls
.
mediaSource
.
endOfStream
=
function
()
{
endOfStreams
++
;
};
player
.
currentTime
(
19
);
clock
.
tick
(
1
);
// playlist response
requests
.
shift
().
respond
(
200
,
null
,
'#EXTM3U\n'
+
'#EXTINF:10,\n'
+
'0.ts\n'
+
'#EXTINF:10,\n'
+
'1.ts\n'
+
'#EXT-X-ENDLIST\n'
);
// segment response
requests
[
0
].
response
=
new
ArrayBuffer
(
17
);
requests
.
shift
().
respond
(
200
,
null
,
''
);
strictEqual
(
endOfStreams
,
0
,
'waits for the buffer update to finish'
);
buffered
=
[[
10
,
20
]];
player
.
tech_
.
hls
.
sourceBuffer
.
trigger
(
'updateend'
);
player
.
currentTime
(
5
);
clock
.
tick
(
1
);
// segment response
requests
[
0
].
response
=
new
ArrayBuffer
(
17
);
requests
.
shift
().
respond
(
200
,
null
,
''
);
buffered
=
[[
0
,
20
]];
player
.
tech_
.
hls
.
sourceBuffer
.
trigger
(
'updateend'
);
strictEqual
(
endOfStreams
,
2
,
'called endOfStream on the media source twice'
);
});
test
(
'calling play() at the end of a video replays'
,
function
()
{
...
...
Please
register
or
sign in
to post a comment