41b4bfd5 by Tom Johnson

- Fix for duration update in parser.

- Updated test suite now looks for manifest.totalDuration.
- Implemented ZEN-TOTAL-DURATION tag recognition.
1 parent dc304941
...@@ -141,6 +141,18 @@ ...@@ -141,6 +141,18 @@
141 this.trigger('data', event); 141 this.trigger('data', event);
142 return; 142 return;
143 } 143 }
144 match = (/^#ZEN-TOTAL-DURATION:?([0-9.]*)?/).exec(line);
145 if (match) {
146 event = {
147 type: 'tag',
148 tagType: 'totalduration'
149 };
150 if (match[1]) {
151 event.duration = parseInt(match[1], 10);
152 }
153 this.trigger('data', event);
154 return;
155 }
144 match = (/^#EXT-X-VERSION:?([0-9.]*)?/).exec(line); 156 match = (/^#EXT-X-VERSION:?([0-9.]*)?/).exec(line);
145 if (match) { 157 if (match) {
146 event = { 158 event = {
...@@ -284,7 +296,8 @@ ...@@ -284,7 +296,8 @@
284 296
285 // the manifest is empty until the parse stream begins delivering data 297 // the manifest is empty until the parse stream begins delivering data
286 this.manifest = { 298 this.manifest = {
287 allowCache: true 299 allowCache: true,
300 totalDuration: 0
288 }; 301 };
289 302
290 // update the manifest with the m3u8 entry from the parse stream 303 // update the manifest with the m3u8 entry from the parse stream
...@@ -373,17 +386,34 @@ ...@@ -373,17 +386,34 @@
373 } 386 }
374 this.manifest.targetDuration = entry.duration; 387 this.manifest.targetDuration = entry.duration;
375 }, 388 },
389 'totalduration': function() {
390 if (!isFinite(entry.duration) || entry.duration < 0) {
391 this.trigger('warn', {
392 message: 'ignoring invalid total duration: ' + entry.duration
393 });
394 return;
395 }
396 this.manifest.totalDuration = entry.duration;
397 },
376 'endlist': function() { 398 'endlist': function() {
399 if(this.manifest.totalDuration === 0)
400 {
377 var calculatedDuration = 0, 401 var calculatedDuration = 0,
378 i; 402 i;
379 for( i = 0; i < this.manifest.segments.length; i++) { 403 for( i = 0; i < this.manifest.segments.length; i++) {
380 if(this.manifest.segments[i].duration) { 404 if(this.manifest.segments[i].duration) {
381 calculatedDuration += this.manifest.segments[i].duration; 405 calculatedDuration += this.manifest.segments[i].duration;
382 } else if (this.manifest.targetDuration) { 406 } else if (this.manifest.targetDuration > 0) {
383 calculatedDuration += this.manifest.targetDuration; 407 calculatedDuration += this.manifest.targetDuration;
408 } else {
409 calculatedDuration += 0;
384 } 410 }
385 } 411 }
386 this.trigger('durationUpdate', parseInt(calculatedDuration)); 412 this.manifest.totalDuration = calculatedDuration;
413 this.trigger('info', {
414 message: 'updating total duration to use a calculated value'
415 })
416 }
387 } 417 }
388 })[entry.tagType] || noop).call(self); 418 })[entry.tagType] || noop).call(self);
389 }, 419 },
......
...@@ -164,6 +164,10 @@ var ...@@ -164,6 +164,10 @@ var
164 parser.push(xhr.responseText); 164 parser.push(xhr.responseText);
165 player.hls.manifest = parser.manifest; 165 player.hls.manifest = parser.manifest;
166 166
167 if(parser.manifest.totalDuration) {
168 player.duration(parser.manifest.totalDuration);
169 }
170
167 player.trigger('loadedmanifest'); 171 player.trigger('loadedmanifest');
168 172
169 if (parser.manifest.segments) { 173 if (parser.manifest.segments) {
......
1 { 1 {
2 "allowCache": true, 2 "allowCache": true,
3 "targetDuration": 10, 3 "targetDuration": 10,
4 "totalDuration": 40,
4 "mediaSequence": 0, 5 "mediaSequence": 0,
5 "playlistType": "VOD", 6 "playlistType": "VOD",
6 "segments": [{ 7 "segments": [{
......
1 { 1 {
2 "targetDuration": 10, 2 "targetDuration": 10,
3 "totalDuration": 161.4167,
3 "allowCache": true, 4 "allowCache": true,
4 "mediaSequence": 0, 5 "mediaSequence": 0,
5 "playlistType": "VOD", 6 "playlistType": "VOD",
......
1 { 1 {
2 "allowCache": true, 2 "allowCache": true,
3 "targetDuration": 10, 3 "targetDuration": 10,
4 "totalDuration": 161.4167,
4 "mediaSequence": 0, 5 "mediaSequence": 0,
5 "playlistType": "VOD", 6 "playlistType": "VOD",
6 "segments": [{ 7 "segments": [{
......
1 { 1 {
2 "targetDuration": 10, 2 "targetDuration": 10,
3 "totalDuration": 10,
3 "allowCache": false, 4 "allowCache": false,
4 "mediaSequence": 0, 5 "mediaSequence": 0,
5 "playlistType": "VOD", 6 "playlistType": "VOD",
......
1 { 1 {
2 "allowCache": true, 2 "allowCache": true,
3 "targetDuration": 10, 3 "targetDuration": 10,
4 "totalDuration": 40,
4 "mediaSequence": 0, 5 "mediaSequence": 0,
5 "playlistType": "VOD", 6 "playlistType": "VOD",
6 "segments": [{ 7 "segments": [{
......
1 { 1 {
2 "targetDuration": 10, 2 "targetDuration": 10,
3 "totalDuration": 10,
3 "allowCache": true, 4 "allowCache": true,
4 "mediaSequence": 0, 5 "mediaSequence": 0,
5 "playlistType": "VOD", 6 "playlistType": "VOD",
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
3 "mediaSequence": 0, 3 "mediaSequence": 0,
4 "playlistType": "VOD", 4 "playlistType": "VOD",
5 "targetDuration": 8, 5 "targetDuration": 8,
6 "totalDuration": 24.32,
6 "segments": [{ 7 "segments": [{
7 "duration": 6.64, 8 "duration": 6.64,
8 "uri": "/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts" 9 "uri": "/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts"
......
1 { 1 {
2 "allowCache": true, 2 "allowCache": true,
3 "targetDuration": 10, 3 "targetDuration": 10,
4 "totalDuration": 58,
4 "mediaSequence": 0, 5 "mediaSequence": 0,
5 "playlistType": "VOD", 6 "playlistType": "VOD",
6 "segments": [{ 7 "segments": [{
......
1 { 1 {
2 "allowCache": true, 2 "allowCache": true,
3 "totalDuration": 0,
3 "playlists": [{ 4 "playlists": [{
4 "attributes": { 5 "attributes": {
5 "PROGRAM-ID": 1, 6 "PROGRAM-ID": 1,
......
1 { 1 {
2 "allowCache": true, 2 "allowCache": true,
3 "targetDuration": 10, 3 "targetDuration": 10,
4 "totalDuration": 58,
4 "mediaSequence": 0, 5 "mediaSequence": 0,
5 "playlistType": "EVENT", 6 "playlistType": "EVENT",
6 "segments": [{ 7 "segments": [{
......
1 { 1 {
2 "allowCache": true, 2 "allowCache": true,
3 "targetDuration": 10, 3 "targetDuration": 10,
4 "totalDuration": 164.7,
4 "mediaSequence": 0, 5 "mediaSequence": 0,
5 "playlistType": "VOD", 6 "playlistType": "VOD",
6 "segments": [{ 7 "segments": [{
......
1 { 1 {
2 "targetDuration": 10, 2 "targetDuration": 10,
3 "totalDuration": 10,
3 "allowCache": true, 4 "allowCache": true,
4 "mediaSequence": 0, 5 "mediaSequence": 0,
5 "playlistType": "VOD", 6 "playlistType": "VOD",
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
3 "mediaSequence": 0, 3 "mediaSequence": 0,
4 "playlistType": "VOD", 4 "playlistType": "VOD",
5 "targetDuration": 8, 5 "targetDuration": 8,
6 "totalDuration": 24.32,
6 "segments": [{ 7 "segments": [{
7 "duration": 6.64, 8 "duration": 6.64,
8 "uri": "/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts" 9 "uri": "/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts"
......
1 { 1 {
2 "allowCache": true, 2 "allowCache": true,
3 "targetDuration": 10, 3 "targetDuration": 10,
4 "totalDuration": 58,
4 "mediaSequence": 0, 5 "mediaSequence": 0,
5 "playlistType": "VOD", 6 "playlistType": "VOD",
6 "segments": [{ 7 "segments": [{
......
1 { 1 {
2 "allowCache": true, 2 "allowCache": true,
3 "mediaSequence": 0, 3 "mediaSequence": 0,
4 "totalDuration": 161.4167,
4 "playlistType": "VOD", 5 "playlistType": "VOD",
5 "segments": [{ 6 "segments": [{
6 "duration": 10, 7 "duration": 10,
......
1 { 1 {
2 "allowCache": true, 2 "allowCache": true,
3 "totalDuration": 0,
3 "playlists": [{ 4 "playlists": [{
4 "attributes": { 5 "attributes": {
5 "PROGRAM-ID": 1, 6 "PROGRAM-ID": 1,
......
1 { 1 {
2 "allowCache": true, 2 "allowCache": true,
3 "targetDuration": 10, 3 "targetDuration": 10,
4 "totalDuration": 40,
4 "mediaSequence": 0, 5 "mediaSequence": 0,
5 "playlistType": "VOD", 6 "playlistType": "VOD",
6 "segments": [{ 7 "segments": [{
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
2 "allowCache": true, 2 "allowCache": true,
3 "mediaSequence": 0, 3 "mediaSequence": 0,
4 "playlistType": "VOD", 4 "playlistType": "VOD",
5 "totalDuration": 24.32,
5 "targetDuration": 8, 6 "targetDuration": 8,
6 "segments": [{ 7 "segments": [{
7 "duration": 6.64, 8 "duration": 6.64,
......
1 { 1 {
2 "allowCache": true, 2 "allowCache": true,
3 "mediaSequence": 0, 3 "mediaSequence": 0,
4 "totalDuration": 24.32,
4 "playlistType": "VOD", 5 "playlistType": "VOD",
5 "targetDuration": 8, 6 "targetDuration": 8,
6 "segments": [{ 7 "segments": [{
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
3 "mediaSequence": 0, 3 "mediaSequence": 0,
4 "playlistType": "VOD", 4 "playlistType": "VOD",
5 "targetDuration": 8, 5 "targetDuration": 8,
6 "totalDuration": 30.64,
6 "segments": [{ 7 "segments": [{
7 "duration": 6.64, 8 "duration": 6.64,
8 "uri": "/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts" 9 "uri": "/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts"
......
1 { 1 {
2 "allowCache": true, 2 "allowCache": true,
3 "mediaSequence": -11, 3 "mediaSequence": -11,
4 "totalDuration": 24.32,
4 "playlistType": "VOD", 5 "playlistType": "VOD",
5 "targetDuration": 8, 6 "targetDuration": 8,
6 "segments": [{ 7 "segments": [{
......
1 { 1 {
2 "allowCache": true, 2 "allowCache": true,
3 "targetDuration": 10, 3 "targetDuration": 10,
4 "totalDuration": 161.4167,
4 "mediaSequence": 0, 5 "mediaSequence": 0,
5 "playlistType": "VOD", 6 "playlistType": "VOD",
6 "segments": [{ 7 "segments": [{
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
3 "mediaSequence": 11, 3 "mediaSequence": 11,
4 "playlistType": "VOD", 4 "playlistType": "VOD",
5 "targetDuration": 8, 5 "targetDuration": 8,
6 "totalDuration": 24.32,
6 "segments": [{ 7 "segments": [{
7 "duration": 6.64, 8 "duration": 6.64,
8 "uri": "/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts" 9 "uri": "/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts"
......