dc135fdf by David LaPalomento

Merge pull request #184 from bc-bbay/master

Setting start position on a live stream
2 parents 9e932b3b 2fcc16f3
...@@ -89,6 +89,18 @@ videojs.Hls.prototype.src = function(src) { ...@@ -89,6 +89,18 @@ videojs.Hls.prototype.src = function(src) {
89 }); 89 });
90 }; 90 };
91 91
92 videojs.Hls.setMediaIndexForLive = function(selectedPlaylist) {
93 var tailIterator = selectedPlaylist.segments.length,
94 tailDuration = 0;
95
96 while (tailDuration < 30 && tailIterator > 0) {
97 tailDuration += selectedPlaylist.segments[tailIterator - 1].duration;
98 tailIterator--;
99 }
100
101 return tailIterator;
102 };
103
92 videojs.Hls.prototype.handleSourceOpen = function() { 104 videojs.Hls.prototype.handleSourceOpen = function() {
93 // construct the video data buffer and set the appropriate MIME type 105 // construct the video data buffer and set the appropriate MIME type
94 var 106 var
...@@ -142,6 +154,11 @@ videojs.Hls.prototype.handleSourceOpen = function() { ...@@ -142,6 +154,11 @@ videojs.Hls.prototype.handleSourceOpen = function() {
142 segmentDlTime = Infinity; 154 segmentDlTime = Infinity;
143 } 155 }
144 156
157 // start live playlists 30 seconds before the current time
158 if (this.duration() === Infinity && this.mediaIndex === 0 && selectedPlaylist.segments) {
159 this.mediaIndex = videojs.Hls.setMediaIndexForLive(selectedPlaylist);
160 }
161
145 // this threshold is to account for having a high latency on the manifest 162 // this threshold is to account for having a high latency on the manifest
146 // request which is a somewhat small file. 163 // request which is a somewhat small file.
147 threshold = 10; 164 threshold = 10;
...@@ -781,14 +798,15 @@ videojs.Hls.getPlaylistTotalDuration = function(playlist) { ...@@ -781,14 +798,15 @@ videojs.Hls.getPlaylistTotalDuration = function(playlist) {
781 * playlist 798 * playlist
782 */ 799 */
783 videojs.Hls.translateMediaIndex = function(mediaIndex, original, update) { 800 videojs.Hls.translateMediaIndex = function(mediaIndex, original, update) {
784 var 801 var i,
785 i, 802 originalSegment,
786 originalSegment; 803 translatedMediaIndex;
787 804
788 // no segments have been loaded from the original playlist 805 // no segments have been loaded from the original playlist
789 if (mediaIndex === 0) { 806 if (mediaIndex === 0) {
790 return 0; 807 return 0;
791 } 808 }
809
792 if (!(update && update.segments)) { 810 if (!(update && update.segments)) {
793 // let the media index be zero when there are no segments defined 811 // let the media index be zero when there are no segments defined
794 return 0; 812 return 0;
...@@ -803,8 +821,15 @@ videojs.Hls.translateMediaIndex = function(mediaIndex, original, update) { ...@@ -803,8 +821,15 @@ videojs.Hls.translateMediaIndex = function(mediaIndex, original, update) {
803 } 821 }
804 } 822 }
805 823
824 translatedMediaIndex = (mediaIndex + (original.mediaSequence - update.mediaSequence));
825
826 if (translatedMediaIndex >= update.segments.length || translatedMediaIndex < 0) {
827 // recalculate the live point if the streams are too far out of sync
828 return videojs.Hls.setMediaIndexForLive(update) + 1;
829 }
830
806 // sync on media sequence 831 // sync on media sequence
807 return (original.mediaSequence + mediaIndex) - update.mediaSequence; 832 return translatedMediaIndex;
808 }; 833 };
809 834
810 /** 835 /**
......
1 {
2 "allowCache": true,
3 "mediaSequence": 0,
4 "segments": [
5 {
6 "duration": 10,
7 "uri": "001.ts"
8 },
9 {
10 "duration": 19,
11 "uri": "002.ts"
12 },
13 {
14 "duration": 10,
15 "uri": "003.ts"
16 },
17 {
18 "duration": 11,
19 "uri": "004.ts"
20 },
21 {
22 "duration": 10,
23 "uri": "005.ts"
24 },
25 {
26 "duration": 10,
27 "uri": "006.ts"
28 },
29 {
30 "duration": 10,
31 "uri": "007.ts"
32 },
33 {
34 "duration": 10,
35 "uri": "008.ts"
36 },
37 {
38 "duration": 16,
39 "uri": "009.ts"
40 }
41 ],
42 "targetDuration": 19
43 }
...\ No newline at end of file ...\ No newline at end of file
1 #EXTM3U
2 #EXT-X-MEDIA-SEQUENCE:0
3 #EXT-X-ALLOW-CACHE:YES
4 #EXT-X-TARGETDURATION:19
5 #EXTINF:10,0
6 001.ts
7 #EXTINF:19,0
8 002.ts
9 #EXTINF:10,0
10 003.ts
11 #EXTINF:11,0
12 004.ts
13 #EXTINF:10,0
14 005.ts
15 #EXTINF:10,0
16 006.ts
17 #EXTINF:10,0
18 007.ts
19 #EXTINF:10,0
20 008.ts
21 #EXTINF:16,0
22 009.ts
...\ No newline at end of file ...\ No newline at end of file
...@@ -1054,6 +1054,20 @@ test('updates the media index when a playlist reloads', function() { ...@@ -1054,6 +1054,20 @@ test('updates the media index when a playlist reloads', function() {
1054 strictEqual(player.hls.mediaIndex, 2, 'mediaIndex is updated after the reload'); 1054 strictEqual(player.hls.mediaIndex, 2, 'mediaIndex is updated after the reload');
1055 }); 1055 });
1056 1056
1057 test('live playlist starts 30s before live', function() {
1058 player.src({
1059 src: 'http://example.com/manifest/liveStart30sBefore.m3u8',
1060 type: 'application/vnd.apple.mpegurl'
1061 });
1062 openMediaSource(player);
1063
1064 standardXHRResponse(requests[0]);
1065
1066 player.hls.playlists.trigger('loadedmetadata');
1067
1068 strictEqual(player.hls.mediaIndex, 6, 'mediaIndex is updated after the reload');
1069 });
1070
1057 test('mediaIndex is zero before the first segment loads', function() { 1071 test('mediaIndex is zero before the first segment loads', function() {
1058 window.manifests['first-seg-load'] = 1072 window.manifests['first-seg-load'] =
1059 '#EXTM3U\n' + 1073 '#EXTM3U\n' +
......