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
6ad09e5d
authored
2015-12-07 13:33:43 -0500
by
Jon-Carlos Rivera
Browse Files
Options
Browse Files
Tag
Download
Plain Diff
Merge pull request #463 from videojs/simplify-stuff
Simplify stuff
2 parents
d702ed19
b7b5d4d1
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
160 additions
and
164 deletions
src/playlist-loader.js
src/videojs-hls.js
test/playlist-loader_test.js
test/videojs-hls_test.js
src/playlist-loader.js
View file @
6ad09e5
...
...
@@ -422,7 +422,6 @@
i
,
segment
,
originalTime
=
time
,
targetDuration
=
this
.
media_
.
targetDuration
||
10
,
numSegments
=
this
.
media_
.
segments
.
length
,
lastSegment
=
numSegments
-
1
,
startIndex
,
...
...
@@ -442,70 +441,36 @@
// find segments with known timing information that bound the
// target time
// Walk backward until we find the first segment with timeline
// information that is earlier than `time`
for
(
i
=
lastSegment
;
i
>=
0
;
i
--
)
{
segment
=
this
.
media_
.
segments
[
i
];
if
(
segment
.
end
!==
undefined
&&
segment
.
end
<=
time
)
{
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
.
end
!==
undefined
&&
segment
.
end
>
time
)
{
// we've found the target segment exactly
return
i
;
}
startIndex
=
i
;
knownStart
=
segment
.
start
;
break
;
}
}
// 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 the target segment must no longer be
// available
return
-
1
;
if
(
segment
.
end
)
{
if
(
segment
.
end
>
time
)
{
knownEnd
=
segment
.
end
;
endIndex
=
i
;
break
;
}
else
{
knownStart
=
segment
.
end
;
startIndex
=
i
+
1
;
}
break
;
}
if
(
segment
.
end
!==
undefined
&&
segment
.
end
>
time
)
{
endIndex
=
i
;
knownEnd
=
segment
.
end
;
break
;
}
}
// use the bounds we just found and playlist information to
// estimate the segment that contains the time we are looking for
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
;
time
-=
segment
.
duration
;
if
(
time
<
0
)
{
return
i
;
}
}
if
(
i
==
=
endIndex
)
{
if
(
i
>
=
endIndex
)
{
// We haven't found a segment but we did hit a known end point
// so fallback to interpolating between the segment index
// based on the known span of the timeline we are dealing with
...
...
@@ -523,24 +488,32 @@
time
=
knownEnd
-
time
;
for
(
i
=
endIndex
;
i
>=
0
;
i
--
)
{
segment
=
this
.
media_
.
segments
[
i
];
time
-=
segment
.
duration
||
targetDuration
;
time
-=
segment
.
duration
;
if
(
time
<
0
)
{
return
i
;
}
}
// We haven't found a segment so load the first one
return
0
;
// We haven't found a segment so load the first one if time is zero
if
(
time
===
0
)
{
return
0
;
}
else
{
return
-
1
;
}
}
else
{
// We known nothing so walk from the front of the playlist,
// subtracting durations until we find a segment that contains
// time and return it
time
=
time
-
this
.
expired_
;
if
(
time
<
0
)
{
return
-
1
;
}
for
(
i
=
0
;
i
<
numSegments
;
i
++
)
{
segment
=
this
.
media_
.
segments
[
i
];
time
-=
segment
.
duration
||
targetDuration
;
time
-=
segment
.
duration
;
if
(
time
<
0
)
{
return
i
;
}
...
...
src/videojs-hls.js
View file @
6ad09e5
...
...
@@ -10,8 +10,8 @@ var
// A fudge factor to apply to advertised playlist bitrates to account for
// temporary flucations in client bandwidth
bandwidthVariance
=
1.2
,
blacklistDuration
=
5
*
60
*
1000
,
//
2
minute blacklist
TIME_FUDGE_FACTOR
=
1
/
6
0
,
// Fudge factor to account for TimeRanges rounding
blacklistDuration
=
5
*
60
*
1000
,
//
5
minute blacklist
TIME_FUDGE_FACTOR
=
1
/
3
0
,
// Fudge factor to account for TimeRanges rounding
Component
=
videojs
.
getComponent
(
'Component'
),
// The amount of time to wait between checking the state of the buffer
...
...
@@ -242,61 +242,57 @@ videojs.HlsHandler.prototype.handleSourceOpen = function() {
}
};
// Returns the array of time range edge objects that were additively
// modified between two TimeRanges.
videojs
.
Hls
.
bufferedAdditions_
=
function
(
original
,
update
)
{
var
result
=
[],
edges
=
[],
i
,
inOriginalRanges
;
// if original or update are falsey, return an empty list of
// additions
if
(
!
original
||
!
update
)
{
return
result
;
}
// create a sorted array of time range start and end times
for
(
i
=
0
;
i
<
original
.
length
;
i
++
)
{
edges
.
push
({
original
:
true
,
start
:
original
.
start
(
i
)
});
edges
.
push
({
original
:
true
,
end
:
original
.
end
(
i
)
});
}
for
(
i
=
0
;
i
<
update
.
length
;
i
++
)
{
edges
.
push
({
start
:
update
.
start
(
i
)
});
edges
.
push
({
end
:
update
.
end
(
i
)
});
}
edges
.
sort
(
function
(
left
,
right
)
{
var
leftTime
,
rightTime
;
leftTime
=
left
.
start
!==
undefined
?
left
.
start
:
left
.
end
;
rightTime
=
right
.
start
!==
undefined
?
right
.
start
:
right
.
end
;
// when two times are equal, ensure the original edge covers the
// update
if
(
leftTime
===
rightTime
)
{
if
(
left
.
original
)
{
return
left
.
start
!==
undefined
?
-
1
:
1
;
}
return
right
.
start
!==
undefined
?
-
1
:
1
;
}
return
leftTime
-
rightTime
;
});
// Search for a likely end time for the segment that was just appened
// based on the state of the `buffered` property before and after the
// append.
// If we found only one such uncommon end-point return it.
videojs
.
Hls
.
findSoleUncommonTimeRangesEnd_
=
function
(
original
,
update
)
{
var
i
,
start
,
end
,
result
=
[],
edges
=
[],
// In order to qualify as a possible candidate, the end point must:
// 1) Not have already existed in the `original` ranges
// 2) Not result from the shrinking of a range that already existed
// in the `original` ranges
// 3) Not be contained inside of a range that existed in `original`
overlapsCurrentEnd
=
function
(
span
)
{
return
(
span
[
0
]
<=
end
&&
span
[
1
]
>=
end
);
};
// filter out all time range edges that occur during a period that
// was already covered by `original`
inOriginalRanges
=
false
;
for
(
i
=
0
;
i
<
edges
.
length
;
i
++
)
{
// if this is a transition point for `original`, track whether
// subsequent edges are additions
if
(
edges
[
i
].
original
)
{
inOriginalRanges
=
edges
[
i
].
start
!==
undefined
;
continue
;
if
(
original
)
{
// Save all the edges in the `original` TimeRanges object
for
(
i
=
0
;
i
<
original
.
length
;
i
++
)
{
start
=
original
.
start
(
i
);
end
=
original
.
end
(
i
);
edges
.
push
([
start
,
end
]);
}
// if we're in a time range that was in `original`, ignore this edge
if
(
inOriginalRanges
)
{
continue
;
}
if
(
update
)
{
// Save any end-points in `update` that are not in the `original`
// TimeRanges object
for
(
i
=
0
;
i
<
update
.
length
;
i
++
)
{
start
=
update
.
start
(
i
);
end
=
update
.
end
(
i
);
if
(
edges
.
some
(
overlapsCurrentEnd
))
{
continue
;
}
// at this point it must be a unique non-shrinking end edge
result
.
push
(
end
);
}
// this edge occurred outside the range of `original`
result
.
push
(
edges
[
i
]);
}
return
result
;
// we err on the side of caution and return null if didn't find
// exactly *one* differing end edge in the search above
if
(
result
.
length
!==
1
)
{
return
null
;
}
return
result
[
0
];
};
var
parseCodecs
=
function
(
codecs
)
{
...
...
@@ -743,10 +739,6 @@ videojs.HlsHandler.prototype.checkBuffer_ = function() {
* append bytes into the SourceBuffer.
*/
videojs
.
HlsHandler
.
prototype
.
startCheckingBuffer_
=
function
()
{
// if the player ever stalls, check if there is video data available
// to append immediately
this
.
tech_
.
on
(
'waiting'
,
(
this
.
drainBuffer
).
bind
(
this
));
this
.
checkBuffer_
();
};
...
...
@@ -759,7 +751,6 @@ videojs.HlsHandler.prototype.stopCheckingBuffer_ = function() {
window
.
clearTimeout
(
this
.
checkBufferTimeout_
);
this
.
checkBufferTimeout_
=
null
;
}
this
.
tech_
.
off
(
'waiting'
,
this
.
drainBuffer
);
};
var
filterBufferedRanges
=
function
(
predicate
)
{
...
...
@@ -1008,6 +999,12 @@ videojs.HlsHandler.prototype.loadSegment = function(segmentInfo) {
// decrease in network performance or a server issue.
timeout
:
(
segment
.
duration
*
1.5
)
*
1000
},
function
(
error
,
request
)
{
// This is a timeout of a previously aborted segment request
// so simply ignore it
if
(
!
self
.
segmentXhr_
||
request
!==
self
.
segmentXhr_
)
{
return
;
}
// the segment request is no longer outstanding
self
.
segmentXhr_
=
null
;
...
...
@@ -1019,7 +1016,6 @@ videojs.HlsHandler.prototype.loadSegment = function(segmentInfo) {
// otherwise, trigger a network error
if
(
!
request
.
aborted
&&
error
)
{
self
.
pendingSegment_
=
null
;
return
self
.
blacklistCurrentPlaylist_
({
status
:
request
.
status
,
message
:
'HLS segment request error at URL: '
+
segmentInfo
.
uri
,
...
...
@@ -1040,7 +1036,9 @@ videojs.HlsHandler.prototype.loadSegment = function(segmentInfo) {
}
else
{
segmentInfo
.
bytes
=
new
Uint8Array
(
request
.
response
);
}
self
.
pendingSegment_
=
segmentInfo
;
self
.
tech_
.
trigger
(
'progress'
);
self
.
drainBuffer
();
...
...
@@ -1048,6 +1046,7 @@ videojs.HlsHandler.prototype.loadSegment = function(segmentInfo) {
// with the updated bandwidth information
self
.
playlists
.
media
(
self
.
selectPlaylist
());
});
};
videojs
.
HlsHandler
.
prototype
.
drainBuffer
=
function
(
event
)
{
...
...
@@ -1170,7 +1169,7 @@ videojs.HlsHandler.prototype.updateEndHandler_ = function () {
currentMediaIndex
,
currentBuffered
,
seekable
,
timelineUpdate
s
;
timelineUpdate
;
this
.
pendingSegment_
=
null
;
...
...
@@ -1211,15 +1210,13 @@ videojs.HlsHandler.prototype.updateEndHandler_ = function () {
}
}
timelineUpdates
=
videojs
.
Hls
.
bufferedAdditions_
(
segmentInfo
.
buffered
,
this
.
tech_
.
buffered
());
timelineUpdates
.
forEach
(
function
(
update
)
{
if
(
segment
)
{
if
(
update
.
end
!==
undefined
)
{
segment
.
end
=
update
.
end
;
}
}
});
timelineUpdate
=
videojs
.
Hls
.
findSoleUncommonTimeRangesEnd_
(
segmentInfo
.
buffered
,
this
.
tech_
.
buffered
());
if
(
timelineUpdate
&&
segment
)
{
segment
.
end
=
timelineUpdate
;
}
// if we've buffered to the end of the video, let the MediaSource know
if
(
this
.
playlists
.
media
().
endList
&&
...
...
@@ -1230,7 +1227,7 @@ videojs.HlsHandler.prototype.updateEndHandler_ = function () {
return
;
}
if
(
timelineUpdate
s
.
length
||
if
(
timelineUpdate
!==
null
||
segmentInfo
.
buffered
.
length
!==
this
.
tech_
.
buffered
().
length
)
{
this
.
updateDuration
(
playlist
);
// check if it's time to download the next segment
...
...
test/playlist-loader_test.js
View file @
6ad09e5
...
...
@@ -811,7 +811,7 @@
'1001.ts\n'
+
'#EXTINF:5,\n'
+
'1002.ts\n'
);
loader
.
media
().
segments
[
0
].
start
=
150
;
loader
.
media
().
segments
[
0
].
end
=
154
;
equal
(
loader
.
getMediaIndexForTime_
(
0
),
-
1
,
'the lowest returned value is negative one'
);
equal
(
loader
.
getMediaIndexForTime_
(
45
),
-
1
,
'expired content returns negative one'
);
...
...
@@ -819,6 +819,7 @@
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'
);
equal
(
loader
.
getMediaIndexForTime_
(
50
+
100
+
4
),
1
,
'calculates within the second segment'
);
equal
(
loader
.
getMediaIndexForTime_
(
50
+
100
+
4.5
),
1
,
'calculates within the second segment'
);
equal
(
loader
.
getMediaIndexForTime_
(
50
+
100
+
6
),
1
,
'calculates within the second segment'
);
});
...
...
@@ -837,9 +838,9 @@
loader
.
expired_
=
160
;
// annotate the first segment with a start time
// this number would be coming from the Source Buffer in practice
loader
.
media
().
segments
[
0
].
start
=
150
;
loader
.
media
().
segments
[
0
].
end
=
150
;
equal
(
loader
.
getMediaIndexForTime_
(
1
51
),
0
,
'prefers the value on the first segment'
);
equal
(
loader
.
getMediaIndexForTime_
(
1
49
),
0
,
'prefers the value on the first segment'
);
clock
.
tick
(
10
*
1000
);
// trigger a playlist refresh
requests
.
shift
().
respond
(
200
,
null
,
...
...
test/videojs-hls_test.js
View file @
6ad09e5
...
...
@@ -2745,47 +2745,72 @@ test('does not download segments if preload option set to none', function() {
module
(
'Buffer Inspection'
);
test
(
'detects time range edges added by updates'
,
function
()
{
var
edges
;
edges
=
videojs
.
Hls
.
bufferedAdditions_
(
videojs
.
createTimeRange
([[
0
,
10
]]),
videojs
.
createTimeRange
([[
0
,
11
]]));
deepEqual
(
edges
,
[{
end
:
11
}],
'detected a forward addition'
);
edges
=
videojs
.
Hls
.
bufferedAdditions_
(
videojs
.
createTimeRange
([[
5
,
10
]]),
videojs
.
createTimeRange
([[
0
,
10
]]));
deepEqual
(
edges
,
[{
start
:
0
}],
'detected a backward addition'
);
edges
=
videojs
.
Hls
.
bufferedAdditions_
(
videojs
.
createTimeRange
([[
5
,
10
]]),
videojs
.
createTimeRange
([[
0
,
11
]]));
deepEqual
(
edges
,
[
{
start
:
0
},
{
end
:
11
}
],
'detected forward and backward additions'
);
edges
=
videojs
.
Hls
.
bufferedAdditions_
(
videojs
.
createTimeRange
([[
0
,
10
]]),
videojs
.
createTimeRange
([[
0
,
10
]]));
deepEqual
(
edges
,
[],
'detected no addition'
);
edges
=
videojs
.
Hls
.
bufferedAdditions_
(
videojs
.
createTimeRange
([]),
videojs
.
createTimeRange
([[
0
,
10
]]));
deepEqual
(
edges
,
[
{
start
:
0
},
{
end
:
10
}
],
'detected an initial addition'
);
edges
=
videojs
.
Hls
.
bufferedAdditions_
(
videojs
.
createTimeRange
([[
0
,
10
]]),
videojs
.
createTimeRange
([[
0
,
10
],
[
20
,
30
]]));
deepEqual
(
edges
,
[
{
start
:
20
},
{
end
:
30
}
],
'detected a non-contiguous addition'
);
});
test
(
'treats null buffered ranges as no addition'
,
function
()
{
var
edges
=
videojs
.
Hls
.
bufferedAdditions_
(
null
,
videojs
.
createTimeRange
([[
0
,
11
]]));
equal
(
edges
.
length
,
0
,
'no additions'
);
test
(
'detects time range end-point changed by updates'
,
function
()
{
var
edge
;
// Single-range changes
edge
=
videojs
.
Hls
.
findSoleUncommonTimeRangesEnd_
(
videojs
.
createTimeRange
([[
0
,
10
]]),
videojs
.
createTimeRange
([[
0
,
11
]]));
strictEqual
(
edge
,
11
,
'detected a forward addition'
);
edge
=
videojs
.
Hls
.
findSoleUncommonTimeRangesEnd_
(
videojs
.
createTimeRange
([[
5
,
10
]]),
videojs
.
createTimeRange
([[
0
,
10
]]));
strictEqual
(
edge
,
null
,
'ignores backward addition'
);
edge
=
videojs
.
Hls
.
findSoleUncommonTimeRangesEnd_
(
videojs
.
createTimeRange
([[
5
,
10
]]),
videojs
.
createTimeRange
([[
0
,
11
]]));
strictEqual
(
edge
,
11
,
'detected a forward addition & ignores a backward addition'
);
edge
=
videojs
.
Hls
.
findSoleUncommonTimeRangesEnd_
(
videojs
.
createTimeRange
([[
0
,
10
]]),
videojs
.
createTimeRange
([[
0
,
9
]]));
strictEqual
(
edge
,
null
,
'ignores a backwards addition resulting from a shrinking range'
);
edge
=
videojs
.
Hls
.
findSoleUncommonTimeRangesEnd_
(
videojs
.
createTimeRange
([[
0
,
10
]]),
videojs
.
createTimeRange
([[
2
,
7
]]));
strictEqual
(
edge
,
null
,
'ignores a forward & backwards addition resulting from a shrinking range'
);
edge
=
videojs
.
Hls
.
findSoleUncommonTimeRangesEnd_
(
videojs
.
createTimeRange
([[
2
,
10
]]),
videojs
.
createTimeRange
([[
0
,
7
]]));
strictEqual
(
edge
,
null
,
'ignores a forward & backwards addition resulting from a range shifted backward'
);
edge
=
videojs
.
Hls
.
findSoleUncommonTimeRangesEnd_
(
videojs
.
createTimeRange
([[
2
,
10
]]),
videojs
.
createTimeRange
([[
5
,
15
]]));
strictEqual
(
edge
,
15
,
'detected a forwards addition resulting from a range shifted foward'
);
// Multiple-range changes
edge
=
videojs
.
Hls
.
findSoleUncommonTimeRangesEnd_
(
videojs
.
createTimeRange
([[
0
,
10
]]),
videojs
.
createTimeRange
([[
0
,
11
],
[
12
,
15
]]));
strictEqual
(
edge
,
null
,
'ignores multiple new forward additions'
);
edge
=
videojs
.
Hls
.
findSoleUncommonTimeRangesEnd_
(
videojs
.
createTimeRange
([[
0
,
10
],
[
20
,
40
]]),
videojs
.
createTimeRange
([[
20
,
50
]]));
strictEqual
(
edge
,
50
,
'detected a forward addition & ignores range removal'
);
edge
=
videojs
.
Hls
.
findSoleUncommonTimeRangesEnd_
(
videojs
.
createTimeRange
([[
0
,
10
],
[
20
,
40
]]),
videojs
.
createTimeRange
([[
0
,
50
]]));
strictEqual
(
edge
,
50
,
'detected a forward addition & ignores merges'
);
edge
=
videojs
.
Hls
.
findSoleUncommonTimeRangesEnd_
(
videojs
.
createTimeRange
([[
0
,
10
],
[
20
,
40
]]),
videojs
.
createTimeRange
([[
0
,
40
]]));
strictEqual
(
edge
,
null
,
'ignores merges'
);
// Empty input
edge
=
videojs
.
Hls
.
findSoleUncommonTimeRangesEnd_
(
videojs
.
createTimeRange
(),
videojs
.
createTimeRange
([[
0
,
11
]]));
strictEqual
(
edge
,
11
,
'handle an empty original TimeRanges object'
);
edge
=
videojs
.
Hls
.
findSoleUncommonTimeRangesEnd_
(
videojs
.
createTimeRange
([[
0
,
11
]]),
videojs
.
createTimeRange
());
strictEqual
(
edge
,
null
,
'handle an empty update TimeRanges object'
);
// Null input
edge
=
videojs
.
Hls
.
findSoleUncommonTimeRangesEnd_
(
null
,
videojs
.
createTimeRange
([[
0
,
11
]]));
strictEqual
(
edge
,
11
,
'treat null original buffer as an empty TimeRanges object'
);
edge
=
videojs
.
Hls
.
findSoleUncommonTimeRangesEnd_
(
videojs
.
createTimeRange
([[
0
,
11
]]),
null
);
strictEqual
(
edge
,
null
,
'treat null update buffer as an empty TimeRanges object'
);
});
})(
window
,
window
.
videojs
);
...
...
Please
register
or
sign in
to post a comment