a72ed64c by David LaPalomento

Do not calculate totalDuration at parse time

Unless a comment specifies the total duration, do not add the property to the parsed manifest object. Also, do not default it to zero if it is not defined in the manifest. Instead, calculate the total duration from the target duration and segment metadata whenever a new playlist is selected.
1 parent 162eb81e
......@@ -298,8 +298,7 @@
// the manifest is empty until the parse stream begins delivering data
this.manifest = {
allowCache: true,
totalDuration: 0
allowCache: true
};
// update the manifest with the m3u8 entry from the parse stream
......@@ -406,24 +405,6 @@
return;
}
this.manifest.totalDuration = entry.duration;
},
'endlist': function() {
var i, calculatedDuration = 0;
if (this.manifest.totalDuration === 0) {
for (i = 0; i < this.manifest.segments.length; i++) {
if (this.manifest.segments[i].duration) {
calculatedDuration += this.manifest.segments[i].duration;
} else if (this.manifest.targetDuration > 0) {
calculatedDuration += this.manifest.targetDuration;
} else {
calculatedDuration += 0;
}
}
this.manifest.totalDuration = calculatedDuration;
this.trigger('info', {
message: 'updating total duration to use a calculated value'
});
}
}
})[entry.tagType] || noop).call(self);
},
......
......@@ -39,7 +39,7 @@ var
* @param time
* @returns int
*/
getMediaIndexByTime = function (playlist, time) {
getMediaIndexByTime = function(playlist, time) {
var index, counter, timeRanges, currentSegmentRange;
timeRanges = [];
......@@ -59,7 +59,7 @@ var
return -1;
},
getPtsByTime = function (segmentParser, time) {
getPtsByTime = function(segmentParser, time) {
var index = 0;
for (index; index<segmentParser.getTags().length; index++) {
......@@ -74,6 +74,23 @@ var
},
/**
* Calculate the total duration for a playlist based on segment metadata.
* @param playlist {object} a media playlist object
* @return {number} the currently known duration, in seconds
*/
totalDuration = function(playlist) {
var
duration = 0,
i = playlist.segments.length,
segment;
while (i--) {
segment = playlist.segments[i];
duration += segment.duration || playlist.targetDuration || 0;
}
return duration;
},
/**
* Constructs a new URI by interpreting a path relative to another
* URI.
* @param basePath {string} a relative or absolute URI
......@@ -254,6 +271,8 @@ var
player.duration(parser.manifest.totalDuration);
// Notify the flash layer
//player.el().querySelector('.vjs-tech').vjs_setProperty('duration',parser.manifest.totalDuration);
} else {
player.duration(totalDuration(parser.manifest));
}
player.trigger('loadedmanifest');
player.trigger('loadedmetadata');
......@@ -266,9 +285,11 @@ var
downloadPlaylist(resolveUrl(srcUrl, playlist.uri));
} else {
player.hls.media = playlist;
if (parser.manifest.totalDuration) {
if (player.hls.media.totalDuration) {
// update the duration
player.duration(parser.manifest.totalDuration);
player.duration(player.hls.media.totalDuration);
} else {
player.duration(totalDuration(player.hls.media));
}
}
......
......@@ -20,6 +20,5 @@
"uri": "http://example.com/00004.ts"
}
],
"targetDuration": 10,
"totalDuration": 40
"targetDuration": 10
}
\ No newline at end of file
......
......@@ -140,6 +140,5 @@
"uri": "hls_450k_video.ts"
}
],
"targetDuration": 10,
"totalDuration": 161.4167
"targetDuration": 10
}
\ No newline at end of file
......
......@@ -12,6 +12,5 @@
"uri": "hls_450k_video.ts"
}
],
"targetDuration": 10,
"totalDuration": 10
"targetDuration": 10
}
\ No newline at end of file
......
{
"allowCache": true,
"totalDuration": 0,
"playlists": [{
"attributes": {
"PROGRAM-ID": 1,
......
......@@ -136,6 +136,5 @@
"uri": "hls_450k_video.ts"
}
],
"targetDuration": 10,
"totalDuration": 161.4167
"targetDuration": 10
}
\ No newline at end of file
......
......@@ -12,6 +12,5 @@
"uri": "hls_450k_video.ts"
}
],
"targetDuration": 10,
"totalDuration": 10
"targetDuration": 10
}
\ No newline at end of file
......
......@@ -20,6 +20,5 @@
"uri": "/00004.ts"
}
],
"targetDuration": 10,
"totalDuration": 40
"targetDuration": 10
}
\ No newline at end of file
......
......@@ -12,6 +12,5 @@
"uri": "hls_450k_video.ts"
}
],
"targetDuration": 10,
"totalDuration": 10
"targetDuration": 10
}
\ No newline at end of file
......
......@@ -20,6 +20,5 @@
"uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts"
}
],
"targetDuration": 8,
"totalDuration": 24.32
"targetDuration": 8
}
\ No newline at end of file
......
......@@ -28,6 +28,5 @@
"uri": "/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00006.ts"
}
],
"targetDuration": 10,
"totalDuration": 58
"targetDuration": 10
}
\ No newline at end of file
......
{
"allowCache": true,
"totalDuration": 0,
"playlists": [{
"attributes": {
"PROGRAM-ID": 1,
......
......@@ -28,6 +28,5 @@
"uri": "/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00006.ts"
}
],
"targetDuration": 10,
"totalDuration": 58
"targetDuration": 10
}
\ No newline at end of file
......
......@@ -8,6 +8,5 @@
"uri": "/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts"
}
],
"targetDuration": 8,
"totalDuration": 6.64
"targetDuration": 8
}
\ No newline at end of file
......
......@@ -138,6 +138,5 @@
"uri": "hls_450k_video.ts"
}
],
"targetDuration": 10,
"totalDuration": 164.7
"targetDuration": 10
}
\ No newline at end of file
......
......@@ -12,6 +12,5 @@
"uri": "hls_450k_video.ts"
}
],
"targetDuration": 10,
"totalDuration": 10
"targetDuration": 10
}
\ No newline at end of file
......
......@@ -20,6 +20,5 @@
"uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts"
}
],
"targetDuration": 8,
"totalDuration": 24.32
"targetDuration": 8
}
\ No newline at end of file
......
......@@ -28,6 +28,5 @@
"uri": "/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00006.ts"
}
],
"targetDuration": 10,
"totalDuration": 58
"targetDuration": 10
}
\ No newline at end of file
......
......@@ -139,6 +139,5 @@
"duration": 1.4167,
"uri": "hls_450k_video.ts"
}
],
"totalDuration": 161.4167
]
}
\ No newline at end of file
......
{
"allowCache": true,
"mediaSequence": 0,
"playlistType": "VOD",
"segments": [
{
"duration": 6.64,
"uri": "/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts"
},
{
"uri": "/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts"
},
{
"uri": "/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts"
}
],
"targetDuration": 8
}
\ No newline at end of file
#EXTM3U
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:8
#EXTINF:6.640,{}
/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts
/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts
/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts
......@@ -7,6 +7,5 @@
"duration": 10,
"uri": "/test/ts-files/zencoder/gogo/00001.ts"
}
],
"totalDuration": 10
]
}
\ No newline at end of file
......
......@@ -24,6 +24,5 @@
"uri": "/test/ts-files/zencoder/gogo/00005.ts"
}
],
"targetDuration": 10,
"totalDuration": 30
"targetDuration": 10
}
\ No newline at end of file
......
......@@ -8,6 +8,5 @@
"uri": "/test/ts-files/zencoder/gogo/00001.ts"
}
],
"targetDuration": 10,
"totalDuration": 10
"targetDuration": 10
}
\ No newline at end of file
......
{
"allowCache": true,
"totalDuration": 0,
"playlists": [{
"attributes": {
"PROGRAM-ID": 1,
......
......@@ -20,6 +20,5 @@
"uri": "00004.ts"
}
],
"targetDuration": 10,
"totalDuration": 40
"targetDuration": 10
}
\ No newline at end of file
......
......@@ -20,6 +20,5 @@
"uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts"
}
],
"targetDuration": 8,
"totalDuration": 24.32
"targetDuration": 8
}
\ No newline at end of file
......
......@@ -15,6 +15,5 @@
"uri": "hls_450k_video.ts"
}
],
"targetDuration": 10,
"totalDuration": 30
"targetDuration": 10
}
\ No newline at end of file
......
......@@ -20,6 +20,5 @@
"uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts"
}
],
"targetDuration": 8,
"totalDuration": 24.32
"targetDuration": 8
}
\ No newline at end of file
......
......@@ -17,6 +17,5 @@
"uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts"
}
],
"targetDuration": 8,
"totalDuration": 30.64
"targetDuration": 8
}
\ No newline at end of file
......
......@@ -20,6 +20,5 @@
"uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts"
}
],
"targetDuration": 8,
"totalDuration": 24.32
"targetDuration": 8
}
\ No newline at end of file
......
......@@ -140,6 +140,5 @@
"uri": "hls_450k_video.ts"
}
],
"targetDuration": 10,
"totalDuration": 161.4167
"targetDuration": 10
}
\ No newline at end of file
......
......@@ -8,6 +8,5 @@
"uri": "/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts"
}
],
"targetDuration": 8,
"totalDuration": 6.64
"targetDuration": 8
}
\ No newline at end of file
......
{
"allowCache": true,
"totalDuration": 0,
"playlists": [
{
"attributes": {
......
......@@ -20,6 +20,5 @@
"uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts"
}
],
"targetDuration": 8,
"totalDuration": 24.32
"targetDuration": 8
}
\ No newline at end of file
......
......@@ -8,6 +8,5 @@
"uri": "hls_450k_video.ts"
}
],
"targetDuration": 10,
"totalDuration": 10
"targetDuration": 10
}
\ No newline at end of file
......
......@@ -124,6 +124,23 @@ test('sets the duration if one is available on the playlist', function() {
strictEqual(1, calls, 'duration is set');
});
test('calculates the duration if needed', function() {
var durations = [];
player.duration = function(duration) {
if (duration === undefined) {
return 0;
}
durations.push(duration);
};
player.hls('manifest/liveMissingSegmentDuration.m3u8');
videojs.mediaSources[player.currentSrc()].trigger({
type: 'sourceopen'
});
strictEqual(durations.length, 1, 'duration is set');
strictEqual(durations[0], 6.64 + (2 * 8), 'duration is calculated');
});
test('starts downloading a segment on loadedmetadata', function() {
player.hls('manifest/media.m3u8');
player.buffered = function() {
......@@ -226,6 +243,32 @@ test('selects a playlist after segment downloads', function() {
strictEqual(calls, 2, 'selects after additional segments');
});
test('updates the duration after switching playlists', function() {
var
calls = 0,
selectedPlaylist = false;
player.hls('manifest/master.m3u8');
player.hls.selectPlaylist = function() {
selectPlaylist = true;
return player.hls.master.playlists[1];
};
player.duration = function(duration) {
if (duration === undefined) {
return 0;
}
// only track calls that occur after the playlist has been switched
if (player.hls.media === player.hls.master.playlists[1]) {
calls++;
}
};
videojs.mediaSources[player.currentSrc()].trigger({
type: 'sourceopen'
});
ok(selectPlaylist, 'selected playlist');
strictEqual(calls, 1, 'updates the duration');
});
test('downloads additional playlists if required', function() {
var
called = false,
......