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
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
108 additions
and
56 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
;
}
}
time
-=
segment
.
start
;
time
-=
segment
.
duration
||
targetDuration
;
if
(
time
<
0
)
{
// the segment with start information is also our best guess
// for the momment
return
i
;
// 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
;
}
}
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
];
time
-=
segment
.
duration
||
targetDuration
;
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
)
{
return
i
;
}
}
if
(
time
<
0
)
{
return
j
;
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
));
}
// 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 _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
i
;
}
}
// 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
;
}
}
// 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
;
}
// the playback position is outside the range of available
// segments so return the length
return
this
.
media_
.
segments
.
length
;
};
videojs
.
Hls
.
PlaylistLoader
=
PlaylistLoader
;
...
...
src/videojs-hls.js
View file @
bce88a1
This diff is collapsed.
Click to expand it.
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