a1799650 by David LaPalomento

Merge pull request #1 from tojohnson/master

Tom's Hack week progress
2 parents 1541a1dc 866d581d
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
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
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
1 (function(window) {
2 var M3U8 = window.videojs.hls.M3U8;
3 var M3U8Parser = window.videojs.hls.M3U8Parser;
4
5 window.videojs.hls.ManifestController = function(){
6
7 var self = this;
8 var parser;
9 var data;
10
11 var onDataCallback;
12 var onErrorCallback;
13 var onUpdateCallback;
14
15 self.loadManifest = function ( manifestUrl, onDataCallback, onErrorCallback, onUpdateCallback ) {
16 self.onDataCallback = onDataCallback;
17 self.onErrorCallback = onErrorCallback;
18 self.onUpdateCallback = onUpdateCallback;
19
20 vjs.get(manifestUrl, self.onManifestLoadComplete, self.onManifestLoadError);
21 };
22
23 self.parseManifest = function ( dataAsString ) {
24 self.parser = new M3U8Parser();
25 self.data = self.parser.parse( dataAsString );
26
27 return self.data;
28 };
29
30 self.onManifestLoadComplete = function(response) {
31 var output = self.parseManifest(response);
32
33 if(self.onDataCallback != undefined)
34 {
35 self.onDataCallback(output);
36 }
37 };
38
39 self.onManifestLoadError = function(err) {
40 if(err)
41 {
42 console.log(err.message);
43 }
44
45 if(self.onErrorCallback != undefined)
46 {
47 onErrorCallback((err != undefined) ? err : null);
48 }
49 };
50 }
51 })(this);
...\ No newline at end of file ...\ No newline at end of file
1 (function(window) {
2
3 var SegmentParser = window.videojs.hls.SegmentParser;
4
5 window.videojs.hls.SegmentController = function(){
6
7 var self = this;
8 var url;
9 var parser;
10 var requestTimestamp;
11 var responseTimestamp;
12 var data;
13
14 var onDataCallback;
15 var onErrorCallback;
16 var onUpdateCallback;
17
18 self.loadSegment = function ( segmentUrl, onDataCallback, onErrorCallback, onUpdateCallback ) {
19 self.url = segmentUrl;
20 self.onDataCallback = onDataCallback;
21 self.onErrorCallback = onErrorCallback;
22 self.onUpdateCallback = onUpdateCallback;
23 self.requestTimestamp = new Date().getTime();
24
25 vjs.get(segmentUrl, self.onSegmentLoadComplete, self.onSegmentLoadError);
26 };
27
28 self.parseSegment = function ( incomingData ) {
29 // Add David's code later //
30
31 self.data = {};
32 self.data.url = self.url;
33 self.data.isCached = false;
34 self.data.requestTimestamp = self.requestTimestamp;
35 self.data.responseTimestamp = self.responseTimestamp;
36 self.data.byteLength = incomingData.byteLength;
37 self.data.isCached = ( parseInt(self.responseTimestamp - self.requestTimestamp) < 75 );
38 self.data.throughput = self.calculateThroughput(self.data.byteLength, self.requestTimestamp ,self.responseTimestamp)
39
40 return self.data;
41 };
42
43 self.calculateThroughput = function(dataAmount, startTime, endTime) {
44 return Math.round(dataAmount/(endTime-startTime)*1000)*8;
45 }
46
47 self.onSegmentLoadComplete = function(response) {
48 self.responseTimestamp = new Date().getTime();
49
50 var output = self.parseSegment(response);
51
52 if(self.onDataCallback != undefined)
53 {
54 self.onDataCallback(output);
55 }
56 };
57
58 self.onSegmentLoadError = function(err) {
59 if(err)
60 {
61 console.log(err.message);
62 }
63
64 if(self.onErrorCallback != undefined)
65 {
66 onErrorCallback((err != undefined) ? err : null);
67 }
68 };
69 }
70 })(this);
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
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
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,15 +44,30 @@ ...@@ -44,15 +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 <!-- <script src="tsSegment.js"></script> --> 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 <!-- SEGMENT -->
49 <script src="tsSegment-bc.js"></script> 58 <script src="tsSegment-bc.js"></script>
59 <script src="../src/segment-controller.js"></script>
50 60
51 <script src="../src/bin-utils.js"></script> 61 <script src="../src/bin-utils.js"></script>
52 62
63
64
65
66
67 <script src="exp-golomb_test.js"></script>
53 <script src="video-js-hls_test.js"></script> 68 <script src="video-js-hls_test.js"></script>
54 <script src="exp-golomb_test.js"></script> 69 <script src="exp-golomb_test.js"></script>
55 <script src="flv-tag_test.js"></script> 70 <script src="flv-tag_test.js"></script>
56 </head> 71 </head>
57 <body> 72 <body>
58 <div id="qunit"></div> 73 <div id="qunit"></div>
......
...@@ -20,6 +20,9 @@ ...@@ -20,6 +20,9 @@
20 throws(block, [expected], [message]) 20 throws(block, [expected], [message])
21 */ 21 */
22 var 22 var
23 manifestController,
24 segmentController,
25 m3u8parser,
23 parser, 26 parser,
24 27
25 expectedHeader = [ 28 expectedHeader = [
...@@ -95,7 +98,6 @@ ...@@ -95,7 +98,6 @@
95 98
96 // payload starts at tag.bytes[16] 99 // payload starts at tag.bytes[16]
97 100
98 console.log(frameType);
99 101
100 // XXX: I'm not sure that frame types 3-5 are invalid 102 // XXX: I'm not sure that frame types 3-5 are invalid
101 ok(frameType === 1 || frameType === 2, 103 ok(frameType === 1 || frameType === 2,
...@@ -233,4 +235,152 @@ ...@@ -233,4 +235,152 @@
233 'the size of the previous tag is correct'); 235 'the size of the previous tag is correct');
234 } 236 }
235 }); 237 });
236 })(this); 238
239 /*
240 M3U8 Test Suite
241 */
242
243 module('m3u8 parser', {
244 setup: function() {
245 m3u8parser = new window.videojs.hls.M3U8Parser();
246 }
247 });
248
249 test('should create my parser', function() {
250 ok(m3u8parser != undefined);
251 }
252 );
253
254 test('should successfully parse manifest data', function() {
255 var parsedData = m3u8parser.parse(window.playlistData);
256 ok(parsedData);
257 }
258 );
259
260 test('test for expected results', function() {
261 var data = m3u8parser.parse(window.playlistData);
262
263 notEqual(data, null, 'data is not NULL');
264 equal(data.invalidReasons.length, 0,'data has 0 invalid reasons');
265 equal(data.hasValidM3UTag, true, 'data has valid EXTM3U');
266 equal(data.targetDuration, 10, 'data has correct TARGET DURATION');
267 equal(data.allowCache, "NO", 'acceptable ALLOW CACHE');
268 equal(data.isPlaylist, true, 'data is parsed as a PLAYLIST as expected');
269 equal(data.playlistType, "VOD", 'acceptable PLAYLIST TYPE');
270 equal(data.mediaItems.length, 16, 'acceptable mediaItem count');
271 equal(data.mediaSequence, 0, 'MEDIA SEQUENCE is correct');
272 equal(data.totalDuration, -1, "ZEN TOTAL DURATION is unknown as expected");
273 equal(data.hasEndTag, true, 'should have ENDLIST tag');
274 }
275 );
276
277 module('brightcove playlist', {
278 setup: function() {
279 m3u8parser = new window.videojs.hls.M3U8Parser();
280 }
281 });
282
283 test('should parse a brightcove manifest data', function() {
284 var data = m3u8parser.parse(window.brightcove_playlist_data);
285
286 ok(data);
287 equal(data.playlistItems.length, 4, 'Has correct rendition count');
288 equal(data.playlistItems[0].bandwidth, 240000, 'First rendition index bandwidth is correct' );
289 equal(data.playlistItems[0]["program-id"], 1, 'First rendition index program-id is correct' );
290 equal(data.playlistItems[0].resolution.width, 396, 'First rendition index resolution width is correct' );
291 equal(data.playlistItems[0].resolution.height, 224, 'First rendition index resolution height is correct' );
292
293 }
294 );
295
296 module('manifest controller', {
297 setup: function() {
298 manifestController = new window.videojs.hls.ManifestController();
299 this.vjsget = vjs.get;
300 vjs.get = function(url, success, error){
301 console.log(url);
302 success(window.brightcove_playlist_data);
303 };
304 },
305 teardown: function() {
306 vjs.get = this.vjsget;
307 }
308 });
309
310 test('should create', function() {
311 ok(manifestController);
312 });
313
314 test('should return a parsed object', function() {
315 var data = manifestController.parseManifest(window.brightcove_playlist_data);
316
317 ok(data);
318
319 equal(data.playlistItems.length, 4, 'Has correct rendition count');
320 equal(data.playlistItems[0].bandwidth, 240000, 'First rendition index bandwidth is correct' );
321 equal(data.playlistItems[0]["program-id"], 1, 'First rendition index program-id is correct' );
322 equal(data.playlistItems[0].resolution.width, 396, 'First rendition index resolution width is correct' );
323 equal(data.playlistItems[0].resolution.height, 224, 'First rendition index resolution height is correct' );
324 })
325
326 test('should get a manifest from hermes', function() {
327 var hermesUrl = "http://localhost:7070/test/basic-playback/brightcove/16x9-master.m3u8";
328
329 manifestController.loadManifest(
330 hermesUrl,
331 function(responseData){
332 ok(true);
333 },
334 function(errorData){
335 console.log('got error data');
336 },
337 function(updateData){
338 console.log('got update data');
339 }
340 )
341 });
342
343 module('segment controller', {
344 setup: function() {
345 segmentController = new window.videojs.hls.SegmentController();
346 this.vjsget = vjs.get;
347 vjs.get = function(url, success, error){
348 console.log('load segment url', url);
349 success(window.bcSegment);
350 };
351 },
352 teardown: function() {
353 vjs.get = this.vjsget;
354 }
355 });
356
357 test('should get a segment data', function() {
358 ok(true);
359 var hermesUrl = "http://localhost:7070/test/ts-files/brightcove/s-1.ts";
360
361 segmentController.loadSegment(
362 hermesUrl,
363 function(responseData){
364 console.log('got response from segment controller');
365 ok(true);
366
367 },
368 function(errorData){
369 console.log('got error data');
370 },
371 function(updateData){
372 console.log('got update data');
373 }
374 )
375 }
376 )
377
378 test('bandwidth calulation test', function() {
379 var multiSecondData = segmentController.calculateThroughput(10000,1000,2000);
380 var subSecondData = segmentController.calculateThroughput(10000,1000,1500);
381 equal(multiSecondData, 80000, 'MULTI-Second bits per second calculation');
382 equal(subSecondData, 160000, 'SUB-Second bits per second calculation');
383
384 })
385
386 })(this);
...\ No newline at end of file ...\ No newline at end of file
......
1 <?xml version="1.0" encoding="UTF-8"?>
2 <module type="WEB_MODULE" version="4">
3 <component name="NewModuleRootManager" inherit-compiler-output="true">
4 <exclude-output />
5 <content url="file://$MODULE_DIR$" />
6 <orderEntry type="sourceFolder" forTests="false" />
7 </component>
8 </module>
9