Merge pull request #184 from bc-bbay/master
Setting start position on a live stream
Showing
4 changed files
with
108 additions
and
4 deletions
... | @@ -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 | /** | ... | ... |
test/manifest/liveStart30sBefore.json
0 → 100644
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 |
test/manifest/liveStart30sBefore.m3u8
0 → 100644
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' + | ... | ... |
-
Please register or sign in to post a comment