dd4862c9 by Tom Johnson

toms intro to jshint

1 parent 0b06638f
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
3 ManifestController = window.videojs.hls.ManifestController, 3 ManifestController = window.videojs.hls.ManifestController,
4 SegmentController = window.videojs.hls.SegmentController, 4 SegmentController = window.videojs.hls.SegmentController,
5 MediaSource = window.videojs.MediaSource, 5 MediaSource = window.videojs.MediaSource,
6 SegmentParser = window.videojs.hls.SegmentParser, 6 SegmentParser = window.videojs.hls.SegmentParser;
7 M3U8 = window.videojs.hls.M3U8; 7
8 8
9 window.videojs.hls.HLSPlaybackController = function(player) { 9 window.videojs.hls.HLSPlaybackController = function(player) {
10 10
...@@ -23,14 +23,14 @@ ...@@ -23,14 +23,14 @@
23 self.loadManifest(self.currentRendition.url, self.onM3U8LoadComplete, self.onM3U8LoadError, self.onM3U8Update); 23 self.loadManifest(self.currentRendition.url, self.onM3U8LoadComplete, self.onM3U8LoadError, self.onM3U8Update);
24 }; 24 };
25 25
26 self.loadManifest = function(manifestUrl, onDataCallback, onErrorCallback, onUpdateCallback) { 26 self.loadManifest = function(manifestUrl, onDataCallback) {
27 self.mediaSource.addEventListener('sourceopen', function(event) { 27 self.mediaSource.addEventListener('sourceopen', function() {
28 // feed parsed bytes into the player 28 // feed parsed bytes into the player
29 self.sourceBuffer = self.mediaSource.addSourceBuffer('video/flv; codecs="vp6,aac"'); 29 self.sourceBuffer = self.mediaSource.addSourceBuffer('video/flv; codecs="vp6,aac"');
30 30
31 self.parser = new SegmentParser(); 31 self.parser = new SegmentParser();
32 32
33 self.sourceBuffer.appendBuffer(self.parser.getFlvHeader(), video); 33 self.sourceBuffer.appendBuffer(self.parser.getFlvHeader(), self.player);
34 34
35 if (onDataCallback) { 35 if (onDataCallback) {
36 self.manifestLoadCompleteCallback = onDataCallback; 36 self.manifestLoadCompleteCallback = onDataCallback;
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
42 }, false); 42 }, false);
43 43
44 self.player.src({ 44 self.player.src({
45 src: videojs.URL.createObjectURL(self.mediaSource), 45 src: window.videojs.URL.createObjectURL(self.mediaSource),
46 type: "video/flv" 46 type: "video/flv"
47 }); 47 });
48 }; 48 };
...@@ -65,8 +65,18 @@ ...@@ -65,8 +65,18 @@
65 } 65 }
66 }; 66 };
67 67
68 self.onM3U8LoadError = function(error) {}; 68 self.onM3U8LoadError = function(error) {
69 self.onM3U8Update = function(m3u8) {}; 69 if(error)
70 {
71 console.log(error);
72 }
73 };
74 self.onM3U8Update = function(m3u8) {
75 if(m3u8)
76 {
77 console.log(m3u8);
78 }
79 };
70 80
71 self.loadSegment = function(segment) { 81 self.loadSegment = function(segment) {
72 self.segmentController = new SegmentController(); 82 self.segmentController = new SegmentController();
...@@ -88,9 +98,14 @@ ...@@ -88,9 +98,14 @@
88 self.loadNextSegment = function() { 98 self.loadNextSegment = function() {
89 self.currentSegment++; 99 self.currentSegment++;
90 self.loadSegment(self.currentManifest.mediaItems[self.currentSegment]); 100 self.loadSegment(self.currentManifest.mediaItems[self.currentSegment]);
91 } 101 };
92 102
93 self.onSegmentLoadError = function(error) {}; 103 self.onSegmentLoadError = function(error) {
104 if(error)
105 {
106 console.log(error);
107 }
108 };
94 109
95 }; 110 };
96 })(this); 111 })(this);
......
...@@ -38,11 +38,11 @@ ...@@ -38,11 +38,11 @@
38 lines = rawDataString.split('\n'); 38 lines = rawDataString.split('\n');
39 39
40 lines.forEach(function(value,index) { 40 lines.forEach(function(value,index) {
41 var segment, rendition, attribute; 41 var segment, rendition, attributes;
42 42
43 switch (self.getTagType(value)) { 43 switch (self.getTagType(value)) {
44 case tagTypes.EXTM3U: 44 case tagTypes.EXTM3U:
45 data.hasValidM3UTag = (index == 0); 45 data.hasValidM3UTag = (index === 0);
46 if (!data.hasValidM3UTag) { 46 if (!data.hasValidM3UTag) {
47 data.invalidReasons.push("Invalid EXTM3U Tag"); 47 data.invalidReasons.push("Invalid EXTM3U Tag");
48 } 48 }
...@@ -95,12 +95,12 @@ ...@@ -95,12 +95,12 @@
95 95
96 if (rendition[attrValue.split('=')[0].toLowerCase()].split('x').length === 2) { 96 if (rendition[attrValue.split('=')[0].toLowerCase()].split('x').length === 2) {
97 rendition.resolution = { 97 rendition.resolution = {
98 width: parseInt(rendition[attrValue.split('=')[0].toLowerCase()].split('x')[0]), 98 width: parseInt(rendition[attrValue.split('=')[0].toLowerCase()].split('x')[0],10),
99 height: parseInt(rendition[attrValue.split('=')[0].toLowerCase()].split('x')[1]) 99 height: parseInt(rendition[attrValue.split('=')[0].toLowerCase()].split('x')[1],10)
100 } 100 };
101 } 101 }
102 } else { 102 } else {
103 rendition[attrValue.split('=')[0].toLowerCase()] = parseInt(attrValue.split('=')[1]); 103 rendition[attrValue.split('=')[0].toLowerCase()] = parseInt(attrValue.split('=')[1],10);
104 } 104 }
105 }); 105 });
106 106
...@@ -128,7 +128,7 @@ ...@@ -128,7 +128,7 @@
128 break; 128 break;
129 129
130 case tagTypes.MEDIA_SEQUENCE: 130 case tagTypes.MEDIA_SEQUENCE:
131 data.mediaSequence = parseInt(self.getTagValue(value)); 131 data.mediaSequence = parseInt(self.getTagValue(value),10);
132 break; 132 break;
133 133
134 case tagTypes.ALLOW_CACHE: 134 case tagTypes.ALLOW_CACHE:
......
1 (function(window) { 1 (function (window) {
2 window.videojs.hls.M3U8 = function() { 2 window.videojs.hls.M3U8 = function () {
3 this.directory = ""; 3 this.directory = "";
4 this.allowCache = "NO"; 4 this.allowCache = "NO";
5 this.playlistItems = []; 5 this.playlistItems = [];
......
1 (function (window) { 1 (function (window) {
2 var 2 var
3 M3U8 = window.videojs.hls.M3U8,
4 M3U8Parser = window.videojs.hls.M3U8Parser; 3 M3U8Parser = window.videojs.hls.M3U8Parser;
5 4
6 window.videojs.hls.ManifestController = function() { 5 window.videojs.hls.ManifestController = function() {
7 var self = this; 6 var self = this;
8 7
9 self.parser;
10 self.data;
11 self.url;
12
13 self.onDataCallback;
14 self.onErrorCallback;
15 self.onUpdateCallback;
16
17 self.loadManifest = function(manifestUrl, onDataCallback, onErrorCallback, onUpdateCallback) { 8 self.loadManifest = function(manifestUrl, onDataCallback, onErrorCallback, onUpdateCallback) {
18 self.url = manifestUrl; 9 self.url = manifestUrl;
19 10
...@@ -28,7 +19,7 @@ ...@@ -28,7 +19,7 @@
28 self.onUpdateCallback = onUpdateCallback; 19 self.onUpdateCallback = onUpdateCallback;
29 } 20 }
30 21
31 vjs.get(manifestUrl, self.onManifestLoadComplete, self.onManifestLoadError); 22 window.vjs.get(manifestUrl, self.onManifestLoadComplete, self.onManifestLoadError);
32 }; 23 };
33 24
34 self.parseManifest = function(dataAsString) { 25 self.parseManifest = function(dataAsString) {
...@@ -42,15 +33,15 @@ ...@@ -42,15 +33,15 @@
42 self.onManifestLoadComplete = function(response) { 33 self.onManifestLoadComplete = function(response) {
43 var output = self.parseManifest(response); 34 var output = self.parseManifest(response);
44 35
45 if (self.onDataCallback != undefined) { 36 if (self.onDataCallback !== undefined) {
46 self.onDataCallback(output); 37 self.onDataCallback(output);
47 } 38 }
48 }; 39 };
49 40
50 self.onManifestLoadError = function(err) { 41 self.onManifestLoadError = function(err) {
51 if (self.onErrorCallback != undefined) { 42 if (self.onErrorCallback !== undefined) {
52 self.onErrorCallback((err != undefined) ? err : null); 43 self.onErrorCallback((err !== undefined) ? err : null);
53 } 44 }
54 }; 45 };
55 } 46 };
56 })(this); 47 })(this);
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
14 14
15 request.open('GET', segmentUrl, true); 15 request.open('GET', segmentUrl, true);
16 request.responseType = 'arraybuffer'; 16 request.responseType = 'arraybuffer';
17 request.onload = function(response) { 17 request.onload = function() {
18 self.onSegmentLoadComplete(new Uint8Array(request.response)); 18 self.onSegmentLoadComplete(new Uint8Array(request.response));
19 }; 19 };
20 20
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
29 self.data.requestTimestamp = self.requestTimestamp; 29 self.data.requestTimestamp = self.requestTimestamp;
30 self.data.responseTimestamp = self.responseTimestamp; 30 self.data.responseTimestamp = self.responseTimestamp;
31 self.data.byteLength = incomingData.byteLength; 31 self.data.byteLength = incomingData.byteLength;
32 self.data.isCached = parseInt(self.responseTimestamp - self.requestTimestamp) < 75; 32 self.data.isCached = parseInt(self.responseTimestamp - self.requestTimestamp,10) < 75;
33 self.data.throughput = self.calculateThroughput(self.data.byteLength, self.requestTimestamp ,self.responseTimestamp); 33 self.data.throughput = self.calculateThroughput(self.data.byteLength, self.requestTimestamp ,self.responseTimestamp);
34 34
35 return self.data; 35 return self.data;
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
37 37
38 self.calculateThroughput = function(dataAmount, startTime, endTime) { 38 self.calculateThroughput = function(dataAmount, startTime, endTime) {
39 return Math.round(dataAmount / (endTime - startTime) * 1000) * 8; 39 return Math.round(dataAmount / (endTime - startTime) * 1000) * 8;
40 } 40 };
41 41
42 self.onSegmentLoadComplete = function(response) { 42 self.onSegmentLoadComplete = function(response) {
43 var output; 43 var output;
...@@ -57,8 +57,8 @@ ...@@ -57,8 +57,8 @@
57 } 57 }
58 58
59 if (self.onErrorCallback !== undefined) { 59 if (self.onErrorCallback !== undefined) {
60 onErrorCallback(error); 60 self.onErrorCallback(error);
61 } 61 }
62 }; 62 };
63 } 63 };
64 })(this); 64 })(this);
......
1 (function (window) { 1 (function (window) {
2 /* 2 /*
3 ======== A Handy Little QUnit Reference ======== 3 ======== A Handy Little QUnit Reference ========
4 http://api.qunitjs.com/ 4 http://api.qunitjs.com/
5 5
6 Test methods: 6 Test methods:
7 module(name, {[setup][ ,teardown]}) 7 module(name, {[setup][ ,teardown]})
8 test(name, callback) 8 test(name, callback)
9 expect(numberOfAssertions) 9 expect(numberOfAssertions)
10 stop(increment) 10 stop(increment)
11 start(decrement) 11 start(decrement)
12 Test assertions: 12 Test assertions:
13 ok(value, [message]) 13 ok(value, [message])
14 equal(actual, expected, [message]) 14 equal(actual, expected, [message])
15 notEqual(actual, expected, [message]) 15 notEqual(actual, expected, [message])
16 deepEqual(actual, expected, [message]) 16 deepEqual(actual, expected, [message])
17 notDeepEqual(actual, expected, [message]) 17 notDeepEqual(actual, expected, [message])
18 strictEqual(actual, expected, [message]) 18 strictEqual(actual, expected, [message])
19 notStrictEqual(actual, expected, [message]) 19 notStrictEqual(actual, expected, [message])
20 throws(block, [expected], [message]) 20 throws(block, [expected], [message])
21 */ 21 */
22 var 22 var
23 manifestController, 23 manifestController,
24 segmentController, 24 segmentController,
25 m3u8parser, 25 m3u8parser,
26 parser, 26 parser,
27 27
28 expectedHeader = [ 28 expectedHeader = [
29 0x46, 0x4c, 0x56, 0x01, 0x05, 0x00, 0x00, 0x00, 29 0x46, 0x4c, 0x56, 0x01, 0x05, 0x00, 0x00, 0x00,
30 0x09, 0x00, 0x00, 0x00, 0x00 30 0x09, 0x00, 0x00, 0x00, 0x00
31 ], 31 ],
32 testAudioTag, 32 testAudioTag,
33 testVideoTag, 33 testVideoTag,
34 testScriptTag, 34 testScriptTag,
35 asciiFromBytes, 35 asciiFromBytes,
36 testScriptString, 36 testScriptString,
37 testScriptEcmaArray; 37 testScriptEcmaArray;
38 38
39 module('environment'); 39 module('environment');
40 40
41 test('is sane', function () { 41 test('is sane', function () {
42 expect(1); 42 expect(1);
43 ok(true); 43 ok(true);
44 }); 44 });
45 45
46 module('segment parser', { 46 module('segment parser', {
47 setup: function () { 47 setup: function () {
48 parser = new window.videojs.hls.SegmentParser(); 48 parser = new window.videojs.hls.SegmentParser();
49 } 49 }
50 }); 50 });
51 51
52 test('creates an flv header', function () { 52 test('creates an flv header', function () {
53 var header = Array.prototype.slice.call(parser.getFlvHeader()); 53 var header = Array.prototype.slice.call(parser.getFlvHeader());
54 ok(header, 'the header is truthy'); 54 ok(header, 'the header is truthy');
55 equal(9 + 4, header.length, 'the header length is correct'); 55 equal(9 + 4, header.length, 'the header length is correct');
56 equal(header[0], 'F'.charCodeAt(0), 'the first character is "F"'); 56 equal(header[0], 'F'.charCodeAt(0), 'the first character is "F"');
57 equal(header[1], 'L'.charCodeAt(0), 'the second character is "L"'); 57 equal(header[1], 'L'.charCodeAt(0), 'the second character is "L"');
58 equal(header[2], 'V'.charCodeAt(0), 'the third character is "V"'); 58 equal(header[2], 'V'.charCodeAt(0), 'the third character is "V"');
59 59
60 deepEqual(expectedHeader, header, 'the rest of the header is correct'); 60 deepEqual(expectedHeader, header, 'the rest of the header is correct');
61 }); 61 });
62 62
63 test('parses the first bipbop segment', function () { 63 test('parses the first bipbop segment', function () {
64 var tag, bytes, i; 64 var tag, bytes, i;
65 parser.parseSegmentBinaryData(window.bcSegment); 65 parser.parseSegmentBinaryData(window.bcSegment);
66 66
67 ok(parser.tagsAvailable(), 'tags are available'); 67 ok(parser.tagsAvailable(), 'tags are available');
68 68
69 console.log('h264 tags:', parser.stats.h264Tags(), 69 console.log('h264 tags:', parser.stats.h264Tags(),
70 'aac tags:', parser.stats.aacTags()); 70 'aac tags:', parser.stats.aacTags());
71 }); 71 });
72 72
73 testAudioTag = function (tag) { 73 testAudioTag = function (tag) {
74 var 74 var
75 byte = tag.bytes[11], 75 byte = tag.bytes[11],
76 format = (byte & 0xF0) >>> 4, 76 format = (byte & 0xF0) >>> 4,
77 soundRate = byte & 0x03, 77 soundRate = byte & 0x03,
78 soundSize = (byte & 0x2) >>> 1, 78 soundSize = (byte & 0x2) >>> 1,
79 soundType = byte & 0x1, 79 soundType = byte & 0x1,
80 aacPacketType = tag.bytes[12]; 80 aacPacketType = tag.bytes[12];
81 81
82 equal(10, format, 'the audio format is aac'); 82 equal(10, format, 'the audio format is aac');
83 equal(3, soundRate, 'the sound rate is 44kHhz'); 83 equal(3, soundRate, 'the sound rate is 44kHhz');
84 equal(1, soundSize, 'the sound size is 16-bit samples'); 84 equal(1, soundSize, 'the sound size is 16-bit samples');
85 equal(1, soundType, 'the sound type is stereo'); 85 equal(1, soundType, 'the sound type is stereo');
86 86
87 ok(aacPacketType === 0 || aacPacketType === 1, 'aac packets should have a valid type'); 87 ok(aacPacketType === 0 || aacPacketType === 1, 'aac packets should have a valid type');
88 }; 88 };
89 89
90 testVideoTag = function (tag) { 90 testVideoTag = function (tag) {
91 var 91 var
92 byte = tag.bytes[11], 92 byte = tag.bytes[11],
93 frameType = (byte & 0xF0) >>> 4, 93 frameType = (byte & 0xF0) >>> 4,
94 codecId = byte & 0x0F, 94 codecId = byte & 0x0F,
95 packetType = tag.bytes[12], 95 packetType = tag.bytes[12],
96 compositionTime = (tag.view.getInt32(13) & 0xFFFFFF00) >> 8, 96 compositionTime = (tag.view.getInt32(13) & 0xFFFFFF00) >> 8,
97 nalHeader; 97 nalHeader;
98 98
99 // payload starts at tag.bytes[16] 99 // payload starts at tag.bytes[16]
100 100
101 101
102 // 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
103 ok(frameType === 1 || frameType === 2, 103 ok(frameType === 1 || frameType === 2,
104 'the frame type should be valid'); 104 'the frame type should be valid');
105 105
106 equal(7, codecId, 'the codec ID is AVC for h264'); 106 equal(7, codecId, 'the codec ID is AVC for h264');
107 ok(packetType <= 2 && packetType >= 0, 'the packet type is within [0, 2]'); 107 ok(packetType <= 2 && packetType >= 0, 'the packet type is within [0, 2]');
108 if (packetType !== 1) { 108 if (packetType !== 1) {
109 equal(0, 109 equal(0,
110 compositionTime, 110 compositionTime,
111 'the composition time is zero for non-NALU packets'); 111 'the composition time is zero for non-NALU packets');
112 } 112 }
113 113
114 // TODO: the rest of the bytes are an NLU unit 114 // TODO: the rest of the bytes are an NLU unit
115 if (packetType === 0) { 115 if (packetType === 0) {
116 // AVC decoder configuration record 116 // AVC decoder configuration record
117 } else { 117 } else {
118 // NAL units 118 // NAL units
119 testNalUnit(tag.bytes.subarray(16)); 119 testNalUnit(tag.bytes.subarray(16));
120 } 120 }
121 }; 121 };
122 122
123 testNalUnit = function (bytes) { 123 testNalUnit = function (bytes) {
124 var 124 var
125 nalHeader = bytes[0], 125 nalHeader = bytes[0],
126 unitType = nalHeader & 0x1F; 126 unitType = nalHeader & 0x1F;
127 127
128 equal(0, (nalHeader & 0x80) >>> 7, 'the first bit is always 0'); 128 equal(0, (nalHeader & 0x80) >>> 7, 'the first bit is always 0');
129 // equal(90, (nalHeader & 0x60) >>> 5, 'the NAL reference indicator is something'); 129 // equal(90, (nalHeader & 0x60) >>> 5, 'the NAL reference indicator is something');
130 // ok(unitType > 0, 'NAL unit type ' + unitType + ' is greater than 0'); 130 // ok(unitType > 0, 'NAL unit type ' + unitType + ' is greater than 0');
131 // ok(unitType < 22 , 'NAL unit type ' + unitType + ' is less than 22'); 131 // ok(unitType < 22 , 'NAL unit type ' + unitType + ' is less than 22');
132 }; 132 };
133 133
134 134
135 asciiFromBytes = function (bytes) { 135 asciiFromBytes = function (bytes) {
136 var 136 var
137 string = [], 137 string = [],
138 i = bytes.byteLength; 138 i = bytes.byteLength;
139 139
140 while (i--) { 140 while (i--) {
141 string[i] = String.fromCharCode(bytes[i]); 141 string[i] = String.fromCharCode(bytes[i]);
142 } 142 }
143 return string.join(''); 143 return string.join('');
144 }; 144 };
145 145
146 testScriptString = function (tag, offset, expected) { 146 testScriptString = function (tag, offset, expected) {
147 var 147 var
148 type = tag.bytes[offset], 148 type = tag.bytes[offset],
149 stringLength = tag.view.getUint16(offset + 1), 149 stringLength = tag.view.getUint16(offset + 1),
150 string, 150 string,
151 i = expected.length; 151 i = expected.length;
152 152
153 equal(2, type, 'the script element is of string type'); 153 equal(2, type, 'the script element is of string type');
154 equal(stringLength, expected.length, 'the script string length is correct'); 154 equal(stringLength, expected.length, 'the script string length is correct');
155 string = asciiFromBytes(tag.bytes.subarray(offset + 3, 155 string = asciiFromBytes(tag.bytes.subarray(offset + 3,
156 offset + 3 + stringLength)); 156 offset + 3 + stringLength));
157 equal(expected, string, 'the string value is "' + expected + '"'); 157 equal(expected, string, 'the string value is "' + expected + '"');
158 }; 158 };
159 159
160 testScriptEcmaArray = function (tag, start) { 160 testScriptEcmaArray = function (tag, start) {
161 var 161 var
162 numItems = tag.view.getUint32(start), 162 numItems = tag.view.getUint32(start),
163 i = numItems, 163 i = numItems,
164 offset = start + 4, 164 offset = start + 4,
165 length, 165 length,
166 type; 166 type;
167 167
168 while (i--) { 168 while (i--) {
169 length = tag.view.getUint16(offset); 169 length = tag.view.getUint16(offset);
170 170
171 // advance offset to the property value 171 // advance offset to the property value
172 offset += 2 + length; 172 offset += 2 + length;
173 173
174 type = tag.bytes[offset]; 174 type = tag.bytes[offset];
175 ok(type === 1 || type === 0, 175 ok(type === 1 || type === 0,
176 'the ecma array property value type is number or boolean'); 176 'the ecma array property value type is number or boolean');
177 offset++; 177 offset++;
178 if (type) { 178 if (type) {
179 // boolean 179 // boolean
180 ok(tag.bytes[offset] === 0 || tag.bytes[offset] === 1, 180 ok(tag.bytes[offset] === 0 || tag.bytes[offset] === 1,
181 'the script boolean value is 0 or 1'); 181 'the script boolean value is 0 or 1');
182 offset++; 182 offset++;
183 } else { 183 } else {
184 // number 184 // number
185 ok(!isNaN(tag.view.getFloat64(offset)), 'the value is not NaN'); 185 ok(!isNaN(tag.view.getFloat64(offset)), 'the value is not NaN');
186 offset += 8; 186 offset += 8;
187 } 187 }
188 } 188 }
189 equal(tag.bytes[offset], 0, 'the property array terminator is valid'); 189 equal(tag.bytes[offset], 0, 'the property array terminator is valid');
190 equal(tag.bytes[offset + 1], 0, 'the property array terminator is valid'); 190 equal(tag.bytes[offset + 1], 0, 'the property array terminator is valid');
191 equal(tag.bytes[offset + 2], 9, 'the property array terminator is valid'); 191 equal(tag.bytes[offset + 2], 9, 'the property array terminator is valid');
192 }; 192 };
193 193
194 testScriptTag = function (tag) { 194 testScriptTag = function (tag) {
195 testScriptString(tag, 11, 'onMetaData'); 195 testScriptString(tag, 11, 'onMetaData');
196 196
197 // the onMetaData object is stored as an 'ecma array', an array with non- 197 // the onMetaData object is stored as an 'ecma array', an array with non-
198 // integer indices (i.e. a dictionary or hash-map). 198 // integer indices (i.e. a dictionary or hash-map).
199 equal(8, tag.bytes[24], 'onMetaData is of ecma array type'); 199 equal(8, tag.bytes[24], 'onMetaData is of ecma array type');
200 testScriptEcmaArray(tag, 25); 200 testScriptEcmaArray(tag, 25);
201 }; 201 };
202 202
203 test('the flv tags are well-formed', function () { 203 test('the flv tags are well-formed', function () {
204 var 204 var
205 tag, 205 tag,
206 byte, 206 byte,
207 type, 207 type,
208 lastTime = 0; 208 lastTime = 0;
209 parser.parseSegmentBinaryData(window.bcSegment); 209 parser.parseSegmentBinaryData(window.bcSegment);
210 210
211 while (parser.tagsAvailable()) { 211 while (parser.tagsAvailable()) {
212 tag = parser.getNextTag(); 212 tag = parser.getNextTag();
213 type = tag.bytes[0]; 213 type = tag.bytes[0];
214 214
215 // generic flv headers 215 // generic flv headers
216 ok(type === 8 || type === 9 || type === 18, 216 ok(type === 8 || type === 9 || type === 18,
217 'the type field specifies audio, video or script'); 217 'the type field specifies audio, video or script');
218 218
219 byte = (tag.view.getUint32(1) & 0xFFFFFF00) >>> 8; 219 byte = (tag.view.getUint32(1) & 0xFFFFFF00) >>> 8;
220 equal(tag.bytes.byteLength - 11 - 4, byte, 'the size field is correct'); 220 equal(tag.bytes.byteLength - 11 - 4, byte, 'the size field is correct');
221 221
222 byte = tag.view.getUint32(5) & 0xFFFFFF00; 222 byte = tag.view.getUint32(5) & 0xFFFFFF00;
223 ok(byte >= lastTime, 'the timestamp for the tag is greater than zero'); 223 ok(byte >= lastTime, 'the timestamp for the tag is greater than zero');
224 lastTime = byte; 224 lastTime = byte;
225 225
226 // tag type-specific headers 226 // tag type-specific headers
227 ({ 227 ({
228 8: testAudioTag, 228 8: testAudioTag,
229 9: testVideoTag, 229 9: testVideoTag,
230 18: testScriptTag 230 18: testScriptTag
231 })[type](tag); 231 })[type](tag);
232 232
233 // previous tag size 233 // previous tag size
234 equal(tag.bytes.byteLength - 4, 234 equal(tag.bytes.byteLength - 4,
235 tag.view.getUint32(tag.bytes.byteLength - 4), 235 tag.view.getUint32(tag.bytes.byteLength - 4),
236 'the size of the previous tag is correct'); 236 'the size of the previous tag is correct');
237 } 237 }
238 }); 238 });
239 239
240 /* 240 /*
241 M3U8 Test Suite 241 M3U8 Test Suite
242 */ 242 */
243 243
244 module('m3u8 parser', { 244 module('m3u8 parser', {
245 setup: function () { 245 setup: function () {
246 m3u8parser = new window.videojs.hls.M3U8Parser(); 246 m3u8parser = new window.videojs.hls.M3U8Parser();
247 } 247 }
248 }); 248 });
249 249
250 test('should create my parser', function () { 250 test('should create my parser', function () {
251 ok(m3u8parser != undefined); 251 ok(m3u8parser != undefined);
252 }); 252 });
253 253
254 test('should successfully parse manifest data', function () { 254 test('should successfully parse manifest data', function () {
255 var parsedData = m3u8parser.parse(window.playlistData); 255 var parsedData = m3u8parser.parse(window.playlistData);
256 ok(parsedData); 256 ok(parsedData);
257 }); 257 });
258 258
259 test('test for expected results', function () { 259 test('test for expected results', function () {
260 var data = m3u8parser.parse(window.playlistData); 260 var data = m3u8parser.parse(window.playlistData);
261 261
262 notEqual(data, null, 'data is not NULL'); 262 notEqual(data, null, 'data is not NULL');
263 equal(data.invalidReasons.length, 0, 'data has 0 invalid reasons'); 263 equal(data.invalidReasons.length, 0, 'data has 0 invalid reasons');
264 equal(data.hasValidM3UTag, true, 'data has valid EXTM3U'); 264 equal(data.hasValidM3UTag, true, 'data has valid EXTM3U');
265 equal(data.targetDuration, 10, 'data has correct TARGET DURATION'); 265 equal(data.targetDuration, 10, 'data has correct TARGET DURATION');
266 equal(data.allowCache, "NO", 'acceptable ALLOW CACHE'); 266 equal(data.allowCache, "NO", 'acceptable ALLOW CACHE');
267 equal(data.isPlaylist, true, 'data is parsed as a PLAYLIST as expected'); 267 equal(data.isPlaylist, true, 'data is parsed as a PLAYLIST as expected');
268 equal(data.playlistType, "VOD", 'acceptable PLAYLIST TYPE'); 268 equal(data.playlistType, "VOD", 'acceptable PLAYLIST TYPE');
269 equal(data.mediaItems.length, 16, 'acceptable mediaItem count'); 269 equal(data.mediaItems.length, 16, 'acceptable mediaItem count');
270 equal(data.mediaSequence, 0, 'MEDIA SEQUENCE is correct'); 270 equal(data.mediaSequence, 0, 'MEDIA SEQUENCE is correct');
271 equal(data.totalDuration, -1, "ZEN TOTAL DURATION is unknown as expected"); 271 equal(data.totalDuration, -1, "ZEN TOTAL DURATION is unknown as expected");
272 equal(data.hasEndTag, true, 'should have ENDLIST tag'); 272 equal(data.hasEndTag, true, 'should have ENDLIST tag');
273 }); 273 });
274 274
275 module('brightcove playlist', { 275 module('brightcove playlist', {
276 setup: function () { 276 setup: function () {
277 m3u8parser = new window.videojs.hls.M3U8Parser(); 277 m3u8parser = new window.videojs.hls.M3U8Parser();
278 } 278 }
279 }); 279 });
280 280
281 test('should parse a brightcove manifest data', function () { 281 test('should parse a brightcove manifest data', function () {
282 var data = m3u8parser.parse(window.brightcove_playlist_data); 282 var data = m3u8parser.parse(window.brightcove_playlist_data);
283 283
284 ok(data); 284 ok(data);
285 equal(data.playlistItems.length, 4, 'Has correct rendition count'); 285 equal(data.playlistItems.length, 4, 'Has correct rendition count');
286 equal(data.playlistItems[0].bandwidth, 240000, 'First rendition index bandwidth is correct'); 286 equal(data.playlistItems[0].bandwidth, 240000, 'First rendition index bandwidth is correct');
287 equal(data.playlistItems[0]["program-id"], 1, 'First rendition index program-id is correct'); 287 equal(data.playlistItems[0]["program-id"], 1, 'First rendition index program-id is correct');
288 equal(data.playlistItems[0].resolution.width, 396, 'First rendition index resolution width is correct'); 288 equal(data.playlistItems[0].resolution.width, 396, 'First rendition index resolution width is correct');
289 equal(data.playlistItems[0].resolution.height, 224, 'First rendition index resolution height is correct'); 289 equal(data.playlistItems[0].resolution.height, 224, 'First rendition index resolution height is correct');
290 290
291 } 291 }
292 ); 292 );
293 293
294 module('manifest controller', { 294 module('manifest controller', {
295 setup: function () { 295 setup: function () {
296 manifestController = new window.videojs.hls.ManifestController(); 296 manifestController = new window.videojs.hls.ManifestController();
297 this.vjsget = vjs.get; 297 this.vjsget = vjs.get;
298 vjs.get = function (url, success, error) { 298 vjs.get = function (url, success, error) {
299 success(window.brightcove_playlist_data); 299 success(window.brightcove_playlist_data);
300 }; 300 };
301 }, 301 },
302 teardown: function () { 302 teardown: function () {
303 vjs.get = this.vjsget; 303 vjs.get = this.vjsget;
304 } 304 }
305 }); 305 });
306 306
307 test('should create', function () { 307 test('should create', function () {
308 ok(manifestController); 308 ok(manifestController);
309 }); 309 });
310 310
311 test('should return a parsed object', function () { 311 test('should return a parsed object', function () {
312 var data = manifestController.parseManifest(window.brightcove_playlist_data); 312 var data = manifestController.parseManifest(window.brightcove_playlist_data);
313 313
314 ok(data); 314 ok(data);
315 equal(data.playlistItems.length, 4, 'Has correct rendition count'); 315 equal(data.playlistItems.length, 4, 'Has correct rendition count');
316 equal(data.playlistItems[0].bandwidth, 240000, 'First rendition index bandwidth is correct'); 316 equal(data.playlistItems[0].bandwidth, 240000, 'First rendition index bandwidth is correct');
317 equal(data.playlistItems[0]["program-id"], 1, 'First rendition index program-id is correct'); 317 equal(data.playlistItems[0]["program-id"], 1, 'First rendition index program-id is correct');
318 equal(data.playlistItems[0].resolution.width, 396, 'First rendition index resolution width is correct'); 318 equal(data.playlistItems[0].resolution.width, 396, 'First rendition index resolution width is correct');
319 equal(data.playlistItems[0].resolution.height, 224, 'First rendition index resolution height is correct'); 319 equal(data.playlistItems[0].resolution.height, 224, 'First rendition index resolution height is correct');
320 }); 320 });
321 321
322 test('should get a manifest from hermes', function () { 322 test('should get a manifest from hermes', function () {
323 manifestController.loadManifest('http://example.com/16x9-master.m3u8', 323 manifestController.loadManifest('http://example.com/16x9-master.m3u8',
324 function(responseData) { 324 function (responseData) {
325 ok(responseData); 325 ok(responseData);
326 }, 326 },
327 function(errorData) { 327 function (errorData) {
328 ok(false, 'does not error'); 328 ok(false, 'does not error');
329 }, 329 },
330 function(updateData) {}); 330 function (updateData) {
331 }); 331 });
332 332 });
333 module('segment controller', { 333
334 setup: function () { 334 module('segment controller', {
335 segmentController = new window.videojs.hls.SegmentController(); 335 setup: function () {
336 this.vjsget = vjs.get; 336 segmentController = new window.videojs.hls.SegmentController();
337 vjs.get = function (url, success, error) { 337 this.vjsget = vjs.get;
338 console.log('load segment url', url); 338 vjs.get = function (url, success, error) {
339 success(window.bcSegment); 339 console.log('load segment url', url);
340 }; 340 success(window.bcSegment);
341 }, 341 };
342 teardown: function () { 342 },
343 vjs.get = this.vjsget; 343 teardown: function () {
344 } 344 vjs.get = this.vjsget;
345 }); 345 }
346 346 });
347 test('bandwidth calulation test', function () { 347
348 var 348 test('bandwidth calulation test', function () {
349 multiSecondData = segmentController.calculateThroughput(10000, 1000, 2000), 349 var
350 subSecondData = segmentController.calculateThroughput(10000, 1000, 1500); 350 multiSecondData = segmentController.calculateThroughput(10000, 1000, 2000),
351 equal(multiSecondData, 80000, 'MULTI-Second bits per second calculation'); 351 subSecondData = segmentController.calculateThroughput(10000, 1000, 1500);
352 equal(subSecondData, 160000, 'SUB-Second bits per second calculation'); 352 equal(multiSecondData, 80000, 'MULTI-Second bits per second calculation');
353 }); 353 equal(subSecondData, 160000, 'SUB-Second bits per second calculation');
354 });
354 })(this); 355 })(this);
......