hack week progress
Showing
10 changed files
with
602 additions
and
2 deletions
src/m3u8/m3u8-parser.js
0 → 100644
1 | (function(window) { | ||
2 | var M3U8 = window.videojs.hls.M3U8; | ||
3 | |||
4 | window.videojs.hls.M3U8Parser = function() { | ||
5 | |||
6 | var self = this; | ||
7 | var tagTypes = window.videojs.hls.m3u8TagType; | ||
8 | var lines = []; | ||
9 | var data; | ||
10 | |||
11 | self.getTagType = function( lineData ) { | ||
12 | for ( var s in tagTypes ) | ||
13 | { | ||
14 | if (lineData.indexOf(tagTypes[s]) == 0) | ||
15 | { | ||
16 | return tagTypes[s]; | ||
17 | } | ||
18 | } | ||
19 | } | ||
20 | |||
21 | self.getTagValue = function ( lineData ) { | ||
22 | for ( var s in tagTypes ) | ||
23 | { | ||
24 | if (lineData.indexOf(tagTypes[s]) == 0) | ||
25 | { | ||
26 | return lineData.substr(tagTypes[s].length); | ||
27 | } | ||
28 | } | ||
29 | } | ||
30 | |||
31 | self.parse = function( rawDataString ) { | ||
32 | data = new M3U8(); | ||
33 | |||
34 | if( rawDataString != undefined && rawDataString.toString().length > 0 ) | ||
35 | { | ||
36 | lines = rawDataString.split('\n'); | ||
37 | |||
38 | lines.forEach( | ||
39 | function(value,index) { | ||
40 | switch( self.getTagType(value) ) | ||
41 | { | ||
42 | case tagTypes.EXTM3U: | ||
43 | data.hasValidM3UTag = (index == 0); | ||
44 | if(!data.hasValidM3UTag) | ||
45 | { | ||
46 | data.invalidReasons.push("Invalid EXTM3U Tag"); | ||
47 | } | ||
48 | break; | ||
49 | |||
50 | case tagTypes.DISCONTINUITY: | ||
51 | break; | ||
52 | |||
53 | case tagTypes.PLAYLIST_TYPE: | ||
54 | if(self.getTagValue(value) == "VOD" || self.getTagValue(value) == "EVENT") | ||
55 | { | ||
56 | data.playlistType = self.getTagValue(value); | ||
57 | data.isPlaylist = true; | ||
58 | } else { | ||
59 | data.invalidReasons.push("Invalid Playlist Type Value"); | ||
60 | } | ||
61 | break; | ||
62 | |||
63 | case tagTypes.EXTINF: | ||
64 | var segment = {url: "unknown", byterange: -1, targetDuration: data.targetDuration }; | ||
65 | |||
66 | if( self.getTagType(lines[index+1]) == tagTypes.BYTERANGE ) | ||
67 | { | ||
68 | segment.byterange = self.getTagValue(lines[index+1]).split('@'); | ||
69 | segment.url = lines[index+2]; | ||
70 | } else | ||
71 | { | ||
72 | segment.url = lines[index+1]; | ||
73 | } | ||
74 | |||
75 | data.mediaItems.push(segment); | ||
76 | |||
77 | break; | ||
78 | |||
79 | case tagTypes.STREAM_INF: | ||
80 | var rendition = {}; | ||
81 | var attributes = value.substr(tagTypes.STREAM_INF.length).split(','); | ||
82 | |||
83 | attributes.forEach(function(attr_value,attr_index) { | ||
84 | if(isNaN(attr_value.split('=')[1])){ | ||
85 | rendition[attr_value.split('=')[0].toLowerCase()] = attr_value.split('=')[1]; | ||
86 | |||
87 | if(rendition[attr_value.split('=')[0].toLowerCase()].split('x').length = 2) | ||
88 | { | ||
89 | rendition.resolution = { | ||
90 | width: Number(rendition[attr_value.split('=')[0].toLowerCase()].split('x')[0]), | ||
91 | height: Number(rendition[attr_value.split('=')[0].toLowerCase()].split('x')[1]) | ||
92 | } | ||
93 | } | ||
94 | |||
95 | } else { | ||
96 | rendition[attr_value.split('=')[0].toLowerCase()] = Number(attr_value.split('=')[1]); | ||
97 | } | ||
98 | }); | ||
99 | |||
100 | |||
101 | if( self.getTagType(lines[index+1]) == tagTypes.BYTERANGE ) | ||
102 | { | ||
103 | rendition.byterange = self.getTagValue(lines[index+1]).split('@'); | ||
104 | rendition.url = lines[index+2]; | ||
105 | } else | ||
106 | { | ||
107 | rendition.url = lines[index+1]; | ||
108 | } | ||
109 | |||
110 | data.isPlaylist = true; | ||
111 | data.playlistItems.push(rendition); | ||
112 | break; | ||
113 | |||
114 | case tagTypes.TARGETDURATION: | ||
115 | data.targetDuration = Number(self.getTagValue(value).split(',')[0]); | ||
116 | break; | ||
117 | |||
118 | case tagTypes.ZEN_TOTAL_DURATION: | ||
119 | data.totalDuration = self.getTagValue(value); | ||
120 | break; | ||
121 | |||
122 | case tagTypes.VERSION: | ||
123 | data.version = Number(self.getTagValue(value)); | ||
124 | break; | ||
125 | |||
126 | case tagTypes.MEDIA_SEQUENCE: | ||
127 | data.mediaSequence = parseInt(self.getTagValue(value)); | ||
128 | break; | ||
129 | |||
130 | case tagTypes.ALLOW_CACHE: | ||
131 | if(self.getTagValue(value) == "YES" || self.getTagValue(value) == "NO") | ||
132 | { | ||
133 | data.allowCache = self.getTagValue(value); | ||
134 | } else { | ||
135 | data.invalidReasons.push("Invalid ALLOW_CACHE Value"); | ||
136 | } | ||
137 | break; | ||
138 | |||
139 | case tagTypes.ENDLIST: | ||
140 | data.hasEndTag = true; | ||
141 | break; | ||
142 | } | ||
143 | } | ||
144 | ) | ||
145 | } else { | ||
146 | data.invalidReasons.push("Empty Manifest"); | ||
147 | } | ||
148 | |||
149 | return data; | ||
150 | |||
151 | }; | ||
152 | }; | ||
153 | |||
154 | })(this); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
src/m3u8/m3u8-tag-types.js
0 → 100644
1 | window.videojs.hls.m3u8TagType = { | ||
2 | /* | ||
3 | * Derived from V8: http://tools.ietf.org/html/draft-pantos-http-live-streaming-08 | ||
4 | */ | ||
5 | |||
6 | /** | ||
7 | * Identifies manifest as Extended M3U - must be present on first line! | ||
8 | */ | ||
9 | EXTM3U:"#EXTM3U", | ||
10 | |||
11 | /** | ||
12 | * Specifies duration. | ||
13 | * Syntax: #EXTINF:<duration>,<title> | ||
14 | * Example: #EXTINF:10, | ||
15 | */ | ||
16 | EXTINF:"#EXTINF:", | ||
17 | |||
18 | /** | ||
19 | * Indicates that a media segment is a sub-range of the resource identified by its media URI. | ||
20 | * Syntax: #EXT-X-BYTERANGE:<n>[@o] | ||
21 | */ | ||
22 | BYTERANGE:"#EXT-X-BYTERANGE:", | ||
23 | |||
24 | /** | ||
25 | * Specifies the maximum media segment duration - applies to entire manifest. | ||
26 | * Syntax: #EXT-X-TARGETDURATION:<s> | ||
27 | * Example: #EXT-X-TARGETDURATION:10 | ||
28 | */ | ||
29 | TARGETDURATION:"#EXT-X-TARGETDURATION:", | ||
30 | |||
31 | /** | ||
32 | * Specifies the sequence number of the first URI in a manifest. | ||
33 | * Syntax: #EXT-X-MEDIA-SEQUENCE:<i> | ||
34 | * Example: #EXT-X-MEDIA-SEQUENCE:50 | ||
35 | */ | ||
36 | MEDIA_SEQUENCE:"#EXT-X-MEDIA-SEQUENCE:", | ||
37 | |||
38 | /** | ||
39 | * Specifies a method by which media segments can be decrypted, if encryption is present. | ||
40 | * Syntax: #EXT-X-KEY:<attribute-list> | ||
41 | * Note: This is likely irrelevant in the context of the Flash Player. | ||
42 | */ | ||
43 | KEY:"#EXT-X-KEY:", | ||
44 | |||
45 | /** | ||
46 | * Associates the first sample of a media segment with an absolute date and/or time. Applies only to the next media URI. | ||
47 | * Syntax: #EXT-X-PROGRAM-DATE-TIME:<YYYY-MM-DDThh:mm:ssZ> | ||
48 | * Example: #EXT-X-PROGRAM-DATE-TIME:2010-02-19T14:54:23.031+08:00 | ||
49 | */ | ||
50 | PROGRAM_DATE_TIME:"#EXT-X-PROGRAM-DATE-TIME:", | ||
51 | |||
52 | /** | ||
53 | * Indicates whether the client MAY or MUST NOT cache downloaded media segments for later replay. | ||
54 | * Syntax: #EXT-X-ALLOW-CACHE:<YES|NO> | ||
55 | * Note: This is likely irrelevant in the context of the Flash Player. | ||
56 | */ | ||
57 | ALLOW_CACHE:"#EXT-X-ALLOW_CACHE:", | ||
58 | |||
59 | /** | ||
60 | * Provides mutability information about the manifest. | ||
61 | * Syntax: #EXT-X-PLAYLIST-TYPE:<EVENT|VOD> | ||
62 | */ | ||
63 | PLAYLIST_TYPE:"#EXT-X-PLAYLIST-TYPE:", | ||
64 | |||
65 | /** | ||
66 | * Indicates that no more media segments will be added to the manifest. May occur ONCE, anywhere in the mainfest file. | ||
67 | */ | ||
68 | ENDLIST:"#EXT-X-ENDLIST", | ||
69 | |||
70 | /** | ||
71 | * Used to relate Playlists that contain alternative renditions of the same content. | ||
72 | * Syntax: #EXT-X-MEDIA:<attribute-list> | ||
73 | */ | ||
74 | MEDIA:"#EXT-X-MEDIA:", | ||
75 | |||
76 | /** | ||
77 | * Identifies a media URI as a Playlist file containing a multimedia presentation and provides information about that presentation. | ||
78 | * Syntax: #EXT-X-STREAM-INF:<attribute-list> | ||
79 | * <URI> | ||
80 | */ | ||
81 | STREAM_INF:"#EXT-X-STREAM-INF:", | ||
82 | |||
83 | /** | ||
84 | * Indicates an encoding discontinuity between the media segment that follows it and the one that preceded it. | ||
85 | */ | ||
86 | DISCONTINUITY:"#EXT-X-DISCONTINUITY", | ||
87 | |||
88 | /** | ||
89 | * Indicates that each media segment in the manifest describes a single I-frame. | ||
90 | */ | ||
91 | I_FRAMES_ONLY:"#EXT-X-I-FRAMES-ONLY", | ||
92 | |||
93 | /** | ||
94 | * Identifies a manifest file containing the I-frames of a multimedia presentation. It stands alone, in that it does not apply to a particular URI in the manifest. | ||
95 | * Syntax: #EXT-X-I-FRAME-STREAM-INF:<attribute-list> | ||
96 | */ | ||
97 | I_FRAME_STREAM_INF:"#EXT-X-I-FRAME-STREAM-INF:", | ||
98 | |||
99 | /** | ||
100 | * Indicates the compatibility version of the Playlist file. | ||
101 | * Syntax: #EXT-X-VERSION:<n> | ||
102 | */ | ||
103 | VERSION:"#EXT-X-VERSION:", | ||
104 | |||
105 | /** | ||
106 | * Indicates the total duration as reported by Zencoder. | ||
107 | * Syntax: #ZEN-TOTAL-DURATION:<n> | ||
108 | */ | ||
109 | ZEN_TOTAL_DURATION: "#ZEN-TOTAL-DURATION:" | ||
110 | |||
111 | }; | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
src/m3u8/m3u8.js
0 → 100644
1 | (function(window) { | ||
2 | window.videojs.hls.M3U8 = function() { | ||
3 | this.allowCache = "NO"; | ||
4 | this.playlistItems = []; | ||
5 | this.mediaItems = []; | ||
6 | this.iFrameItems = []; | ||
7 | this.invalidReasons = []; | ||
8 | this.hasValidM3UTag = false; | ||
9 | this.hasEndTag = false; | ||
10 | this.targetDuration = -1; | ||
11 | this.totalDuration = -1; | ||
12 | this.isPlaylist = false; | ||
13 | this.playlistType = ""; | ||
14 | this.mediaSequence = -1; | ||
15 | this.version = -1; | ||
16 | } | ||
17 | })(this); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
src/manifest-controller.js
0 → 100644
1 | (function(window) { | ||
2 | var M3U8 = window.videojs.hls.M3U8; | ||
3 | var M3U8Parser = window.videojs.hls.M3U8Parser; | ||
4 | var M3U8TagTypes = window.videojs.hls.m3u8TagType; | ||
5 | |||
6 | window.videojs.hls.ManifestController = function(){ | ||
7 | |||
8 | var self = this; | ||
9 | var parser; | ||
10 | var data; | ||
11 | |||
12 | var onDataCallback; | ||
13 | var onErrorCallback; | ||
14 | var onUpdateCallback; | ||
15 | |||
16 | self.loadManifest = function ( manifestUrl, onDataCallback, onErrorCallback, onUpdateCallback ) { | ||
17 | self.onDataCallback = onDataCallback; | ||
18 | self.onErrorCallback = onErrorCallback; | ||
19 | self.onUpdateCallback = onUpdateCallback; | ||
20 | |||
21 | vjs.get(manifestUrl, self.onManifestLoadComplete, self.onManifestLoadError); | ||
22 | }; | ||
23 | |||
24 | self.parseManifest = function ( dataAsString ) { | ||
25 | self.parser = new M3U8Parser(); | ||
26 | self.data = self.parser.parse( dataAsString ); | ||
27 | |||
28 | return self.data; | ||
29 | }; | ||
30 | |||
31 | self.onManifestLoadComplete = function(response) { | ||
32 | var output = self.parseManifest(response); | ||
33 | |||
34 | if(self.onDataCallback != undefined) | ||
35 | { | ||
36 | self.onDataCallback(output); | ||
37 | } | ||
38 | }; | ||
39 | |||
40 | self.onManifestLoadError = function(err) { | ||
41 | if(err) | ||
42 | { | ||
43 | console.log(err.message); | ||
44 | } | ||
45 | |||
46 | if(self.onErrorCallback != undefined) | ||
47 | { | ||
48 | onErrorCallback((err != undefined) ? err : null); | ||
49 | } | ||
50 | }; | ||
51 | } | ||
52 | })(this); | ||
53 | |||
54 | /* | ||
55 | mc = new window.videojs.hls.ManifestController('myM3u8.m3u8', { | ||
56 | onData: function(){}, | ||
57 | onError: function(){}, | ||
58 | onUpdate: function(){} | ||
59 | }); | ||
60 | */ | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
test/manifest/brightcove_playlist_m3u8.js
0 → 100644
1 | window.brightcove_playlist_data = '#EXTM3U\n'+ | ||
2 | '#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=240000,RESOLUTION=396x224\n'+ | ||
3 | 'http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824686811001&videoId=1824650741001\n'+ | ||
4 | '#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=40000\n'+ | ||
5 | 'http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824683759001&videoId=1824650741001\n'+ | ||
6 | '#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=440000,RESOLUTION=396x224\n'+ | ||
7 | 'http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824686593001&videoId=1824650741001\n'+ | ||
8 | '#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1928000,RESOLUTION=960x540\n'+ | ||
9 | 'http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824687660001&videoId=1824650741001' | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
test/manifest/playlist.m3u8
0 → 100644
1 | #EXTM3U | ||
2 | #EXT-X-TARGETDURATION:10 | ||
3 | #EXT-X-VERSION:4 | ||
4 | #EXT-X-MEDIA-SEQUENCE:0 | ||
5 | #EXT-X-PLAYLIST-TYPE:VOD | ||
6 | #EXTINF:10, | ||
7 | #EXT-X-BYTERANGE:522828@0 | ||
8 | hls_450k_video.ts | ||
9 | #EXTINF:10, | ||
10 | #EXT-X-BYTERANGE:587500@522828 | ||
11 | hls_450k_video.ts | ||
12 | #EXTINF:10, | ||
13 | #EXT-X-BYTERANGE:713084@1110328 | ||
14 | hls_450k_video.ts | ||
15 | #EXTINF:10, | ||
16 | #EXT-X-BYTERANGE:476580@1823412 | ||
17 | hls_450k_video.ts | ||
18 | #EXTINF:10, | ||
19 | #EXT-X-BYTERANGE:535612@2299992 | ||
20 | hls_450k_video.ts | ||
21 | #EXTINF:10, | ||
22 | #EXT-X-BYTERANGE:207176@2835604 | ||
23 | hls_450k_video.ts | ||
24 | #EXTINF:10, | ||
25 | #EXT-X-BYTERANGE:455900@3042780 | ||
26 | hls_450k_video.ts | ||
27 | #EXTINF:10, | ||
28 | #EXT-X-BYTERANGE:657248@3498680 | ||
29 | hls_450k_video.ts | ||
30 | #EXTINF:10, | ||
31 | #EXT-X-BYTERANGE:571708@4155928 | ||
32 | hls_450k_video.ts | ||
33 | #EXTINF:10, | ||
34 | #EXT-X-BYTERANGE:485040@4727636 | ||
35 | hls_450k_video.ts | ||
36 | #EXTINF:10, | ||
37 | #EXT-X-BYTERANGE:709136@5212676 | ||
38 | hls_450k_video.ts | ||
39 | #EXTINF:10, | ||
40 | #EXT-X-BYTERANGE:730004@5921812 | ||
41 | hls_450k_video.ts | ||
42 | #EXTINF:10, | ||
43 | #EXT-X-BYTERANGE:456276@6651816 | ||
44 | hls_450k_video.ts | ||
45 | #EXTINF:10, | ||
46 | #EXT-X-BYTERANGE:468684@7108092 | ||
47 | hls_450k_video.ts | ||
48 | #EXTINF:10, | ||
49 | #EXT-X-BYTERANGE:444996@7576776 | ||
50 | hls_450k_video.ts | ||
51 | #EXTINF:10, | ||
52 | #EXT-X-BYTERANGE:331444@8021772 | ||
53 | hls_450k_video.ts | ||
54 | #EXTINF:1.4167, | ||
55 | #EXT-X-BYTERANGE:44556@8353216 | ||
56 | hls_450k_video.ts | ||
57 | #EXT-X-ENDLIST |
test/manifest/playlistM3U8data.js
0 → 100644
1 | window.playlistData = '#EXTM3U\n'+ | ||
2 | '#EXT-X-TARGETDURATION:10\n' + | ||
3 | '#EXT-X-VERSION:4\n' + | ||
4 | '#EXT-X-MEDIA-SEQUENCE:0\n' + | ||
5 | '#EXT-X-PLAYLIST-TYPE:VOD\n' + | ||
6 | '#EXTINF:10,\n' + | ||
7 | '#EXT-X-BYTERANGE:522828@0\n' + | ||
8 | 'hls_450k_video.ts\n' + | ||
9 | '#EXTINF:10,\n' + | ||
10 | '#EXT-X-BYTERANGE:587500@522828\n' + | ||
11 | 'hls_450k_video.ts\n' + | ||
12 | '#EXTINF:10,\n' + | ||
13 | '#EXT-X-BYTERANGE:713084@1110328\n' + | ||
14 | 'hls_450k_video.ts\n' + | ||
15 | '#EXTINF:10,\n' + | ||
16 | '#EXT-X-BYTERANGE:476580@1823412\n' + | ||
17 | 'hls_450k_video.ts\n' + | ||
18 | '#EXTINF:10,\n' + | ||
19 | '#EXT-X-BYTERANGE:535612@2299992\n' + | ||
20 | 'hls_450k_video.ts\n' + | ||
21 | '#EXTINF:10,\n' + | ||
22 | '#EXT-X-BYTERANGE:207176@2835604\n' + | ||
23 | 'hls_450k_video.ts\n' + | ||
24 | '#EXTINF:10,\n' + | ||
25 | '#EXT-X-BYTERANGE:455900@3042780\n' + | ||
26 | 'hls_450k_video.ts\n' + | ||
27 | '#EXTINF:10,\n' + | ||
28 | '#EXT-X-BYTERANGE:657248@3498680\n' + | ||
29 | 'hls_450k_video.ts\n' + | ||
30 | '#EXTINF:10,\n' + | ||
31 | '#EXT-X-BYTERANGE:571708@4155928\n' + | ||
32 | 'hls_450k_video.ts\n' + | ||
33 | '#EXTINF:10,\n' + | ||
34 | '#EXT-X-BYTERANGE:485040@4727636\n' + | ||
35 | 'hls_450k_video.ts\n' + | ||
36 | '#EXTINF:10,\n' + | ||
37 | '#EXT-X-BYTERANGE:709136@5212676\n' + | ||
38 | 'hls_450k_video.ts\n' + | ||
39 | '#EXTINF:10,\n' + | ||
40 | '#EXT-X-BYTERANGE:730004@5921812\n' + | ||
41 | 'hls_450k_video.ts\n' + | ||
42 | '#EXTINF:10,\n' + | ||
43 | '#EXT-X-BYTERANGE:456276@6651816\n' + | ||
44 | 'hls_450k_video.ts\n' + | ||
45 | '#EXTINF:10,\n' + | ||
46 | '#EXT-X-BYTERANGE:468684@7108092\n' + | ||
47 | 'hls_450k_video.ts' + | ||
48 | '#EXTINF:10,\n' + | ||
49 | '#EXT-X-BYTERANGE:444996@7576776\n' + | ||
50 | 'hls_450k_video.ts\n' + | ||
51 | '#EXTINF:10,\n' + | ||
52 | '#EXT-X-BYTERANGE:331444@8021772\n' + | ||
53 | 'hls_450k_video.ts\n' + | ||
54 | '#EXTINF:1.4167,\n' + | ||
55 | '#EXT-X-BYTERANGE:44556@8353216\n' + | ||
56 | 'hls_450k_video.ts\n' + | ||
57 | '#EXT-X-ENDLIST'; | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
... | @@ -44,12 +44,30 @@ | ... | @@ -44,12 +44,30 @@ |
44 | <script src="../src/h264-stream.js"></script> | 44 | <script src="../src/h264-stream.js"></script> |
45 | <script src="../src/aac-stream.js"></script> | 45 | <script src="../src/aac-stream.js"></script> |
46 | <script src="../src/segment-parser.js"></script> | 46 | <script src="../src/segment-parser.js"></script> |
47 | <!-- an example MPEG2-TS segment --> | 47 | |
48 | <!-- M3U8 --> | ||
49 | <script src="../src/m3u8/m3u8.js"></script> | ||
50 | <script src="../src/m3u8/m3u8-tag-types.js"></script> | ||
51 | <script src="../src/m3u8/m3u8-parser.js"></script> | ||
52 | <script src="../src/manifest-controller.js"></script> | ||
53 | <!-- M3U8 TEST DATA --> | ||
54 | <script src="manifest/playlistM3U8data.js"></script> | ||
55 | <script src="manifest/brightcove_playlist_m3u8.js"></script> | ||
56 | <!-- M3U8 --> | ||
57 | |||
58 | |||
59 | <!-- an example MPEG2-TS segment --> | ||
48 | <!-- <script src="tsSegment.js"></script> --> | 60 | <!-- <script src="tsSegment.js"></script> --> |
49 | <script src="tsSegment-bc.js"></script> | 61 | <script src="tsSegment-bc.js"></script> |
50 | 62 | ||
63 | |||
51 | <script src="../src/bin-utils.js"></script> | 64 | <script src="../src/bin-utils.js"></script> |
52 | 65 | ||
66 | |||
67 | |||
68 | |||
69 | |||
70 | |||
53 | <script src="video-js-hls_test.js"></script> | 71 | <script src="video-js-hls_test.js"></script> |
54 | </head> | 72 | </head> |
55 | <body> | 73 | <body> | ... | ... |
... | @@ -20,6 +20,8 @@ | ... | @@ -20,6 +20,8 @@ |
20 | throws(block, [expected], [message]) | 20 | throws(block, [expected], [message]) |
21 | */ | 21 | */ |
22 | var | 22 | var |
23 | manifestController, | ||
24 | m3u8parser, | ||
23 | parser, | 25 | parser, |
24 | 26 | ||
25 | expectedHeader = [ | 27 | expectedHeader = [ |
... | @@ -102,7 +104,6 @@ | ... | @@ -102,7 +104,6 @@ |
102 | packetType = tag.bytes[12], | 104 | packetType = tag.bytes[12], |
103 | compositionTime = (tag.view.getInt32(13) & 0xFFFFFF00) >> 8; | 105 | compositionTime = (tag.view.getInt32(13) & 0xFFFFFF00) >> 8; |
104 | 106 | ||
105 | console.log(frameType); | ||
106 | 107 | ||
107 | // XXX: I'm not sure that frame types 3-5 are invalid | 108 | // XXX: I'm not sure that frame types 3-5 are invalid |
108 | ok(frameType === 1 || frameType === 2, | 109 | ok(frameType === 1 || frameType === 2, |
... | @@ -221,4 +222,111 @@ | ... | @@ -221,4 +222,111 @@ |
221 | 'the size of the previous tag is correct'); | 222 | 'the size of the previous tag is correct'); |
222 | } | 223 | } |
223 | }); | 224 | }); |
225 | |||
226 | /* | ||
227 | M3U8 Test Suite | ||
228 | */ | ||
229 | |||
230 | module('m3u8 parser', { | ||
231 | setup: function() { | ||
232 | m3u8parser = new window.videojs.hls.M3U8Parser(); | ||
233 | } | ||
234 | }); | ||
235 | |||
236 | test('should create my parser', function() { | ||
237 | ok(m3u8parser != undefined); | ||
238 | } | ||
239 | ); | ||
240 | |||
241 | test('should successfully parse manifest data', function() { | ||
242 | var parsedData = m3u8parser.parse(window.playlistData); | ||
243 | ok(parsedData); | ||
244 | } | ||
245 | ); | ||
246 | |||
247 | test('test for expected results', function() { | ||
248 | var data = m3u8parser.parse(window.playlistData); | ||
249 | |||
250 | notEqual(data, null, 'data is not NULL'); | ||
251 | equal(data.invalidReasons.length, 0,'data has 0 invalid reasons'); | ||
252 | equal(data.hasValidM3UTag, true, 'data has valid EXTM3U'); | ||
253 | equal(data.targetDuration, 10, 'data has correct TARGET DURATION'); | ||
254 | equal(data.allowCache, "NO", 'acceptable ALLOW CACHE'); | ||
255 | equal(data.isPlaylist, true, 'data is parsed as a PLAYLIST as expected'); | ||
256 | equal(data.playlistType, "VOD", 'acceptable PLAYLIST TYPE'); | ||
257 | equal(data.mediaItems.length, 16, 'acceptable mediaItem count'); | ||
258 | equal(data.mediaSequence, 0, 'MEDIA SEQUENCE is correct'); | ||
259 | equal(data.totalDuration, -1, "ZEN TOTAL DURATION is unknown as expected"); | ||
260 | equal(data.hasEndTag, true, 'should have ENDLIST tag'); | ||
261 | } | ||
262 | ); | ||
263 | |||
264 | module('brightcove playlist', { | ||
265 | setup: function() { | ||
266 | m3u8parser = new window.videojs.hls.M3U8Parser(); | ||
267 | } | ||
268 | }); | ||
269 | |||
270 | test('should parse a brightcove manifest data', function() { | ||
271 | var data = m3u8parser.parse(window.brightcove_playlist_data); | ||
272 | |||
273 | ok(data); | ||
274 | equal(data.playlistItems.length, 4, 'Has correct rendition count'); | ||
275 | equal(data.playlistItems[0].bandwidth, 240000, 'First rendition index bandwidth is correct' ); | ||
276 | equal(data.playlistItems[0]["program-id"], 1, 'First rendition index program-id is correct' ); | ||
277 | equal(data.playlistItems[0].resolution.width, 396, 'First rendition index resolution width is correct' ); | ||
278 | equal(data.playlistItems[0].resolution.height, 224, 'First rendition index resolution height is correct' ); | ||
279 | |||
280 | } | ||
281 | ); | ||
282 | |||
283 | module('manifest controller', { | ||
284 | setup: function() { | ||
285 | manifestController = new window.videojs.hls.ManifestController(); | ||
286 | this.vjsget = vjs.get; | ||
287 | vjs.get = function(url, success, error){ | ||
288 | console.log(url); | ||
289 | success(window.brightcove_playlist_data); | ||
290 | }; | ||
291 | }, | ||
292 | teardown: function() { | ||
293 | vjs.get = this.vjsget; | ||
294 | } | ||
295 | }); | ||
296 | |||
297 | test('should create', function() { | ||
298 | ok(manifestController); | ||
299 | }); | ||
300 | |||
301 | test('should return a parsed object', function() { | ||
302 | var data = manifestController.parseManifest(window.brightcove_playlist_data); | ||
303 | |||
304 | ok(data); | ||
305 | |||
306 | equal(data.playlistItems.length, 4, 'Has correct rendition count'); | ||
307 | equal(data.playlistItems[0].bandwidth, 240000, 'First rendition index bandwidth is correct' ); | ||
308 | equal(data.playlistItems[0]["program-id"], 1, 'First rendition index program-id is correct' ); | ||
309 | equal(data.playlistItems[0].resolution.width, 396, 'First rendition index resolution width is correct' ); | ||
310 | equal(data.playlistItems[0].resolution.height, 224, 'First rendition index resolution height is correct' ); | ||
311 | }) | ||
312 | |||
313 | test('should get a manifest from hermes', function() { | ||
314 | var hermesUrl = "http://localhost:7070/test/basic-playback/brightcove/16x9-master.m3u8"; | ||
315 | |||
316 | manifestController.loadManifest( | ||
317 | hermesUrl, | ||
318 | function(responseData){ | ||
319 | console.log('got response data'); | ||
320 | ok(true); | ||
321 | }, | ||
322 | function(errorData){ | ||
323 | console.log('got error data') | ||
324 | }, | ||
325 | function(updateData){ | ||
326 | console.log('got update data') | ||
327 | } | ||
328 | ) | ||
329 | |||
330 | }) | ||
331 | |||
224 | })(this); | 332 | })(this); | ... | ... |
video-js-hls.iml
0 → 100644
-
Please register or sign in to post a comment