7a41ceb5 by David LaPalomento

Segment parser finishes with the example TS segment

The parser can process the example TS but it doesn't appear to be correctly formed. The player does seem to correctly interpret the video duration, but the display area is black and there is no audio.
1 parent c09dfad4
1 /<!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <title>video.js HLS Plugin Example</title>
6
7 <link href="http://vjs.zencdn.net/4.0/video-js.css" rel="stylesheet">
8
9 <!-- video.js -->
10 <script src="libs/video-js/src/js/core.js"></script>
11 <script src="libs/video-js/src/js/core-object.js"></script>
12 <script src="libs/video-js/src/js/events.js"></script>
13 <script src="libs/video-js/src/js/lib.js"></script>
14 <script src="libs/video-js/src/js/component.js"></script>
15 <script src="libs/video-js/src/js/button.js"></script>
16 <script src="libs/video-js/src/js/slider.js"></script>
17 <script src="libs/video-js/src/js/menu.js"></script>
18 <script src="libs/video-js/src/js/player.js"></script>
19 <script src="libs/video-js/src/js/control-bar/control-bar.js"></script>
20 <script src="libs/video-js/src/js/control-bar/play-toggle.js"></script>
21 <script src="libs/video-js/src/js/control-bar/time-display.js"></script>
22 <script src="libs/video-js/src/js/control-bar/fullscreen-toggle.js"></script>
23 <script src="libs/video-js/src/js/control-bar/progress-control.js"></script>
24 <script src="libs/video-js/src/js/control-bar/volume-control.js"></script>
25 <script src="libs/video-js/src/js/control-bar/mute-toggle.js"></script>
26 <script src="libs/video-js/src/js/control-bar/volume-menu-button.js"></script>
27 <script src="libs/video-js/src/js/poster.js"></script>
28 <script src="libs/video-js/src/js/loading-spinner.js"></script>
29 <script src="libs/video-js/src/js/big-play-button.js"></script>
30 <script src="libs/video-js/src/js/media/media.js"></script>
31 <script src="libs/video-js/src/js/media/html5.js"></script>
32 <script src="libs/video-js/src/js/media/flash.js"></script>
33 <script src="libs/video-js/src/js/media/loader.js"></script>
34 <script src="libs/video-js/src/js/tracks.js"></script>
35 <script src="libs/video-js/src/js/json.js"></script>
36 <script src="libs/video-js/src/js/setup.js"></script>
37 <script src="libs/video-js/src/js/plugins.js"></script>
38
39 <!-- Media Sources plugin -->
40 <script src="libs/videojs-media-sources.js"></script>
41 <!-- HLS plugin -->
42 <script src="src/video-js-hls.js"></script>
43 <script src="src/flv-tag.js"></script>
44 <script src="src/exp-golomb.js"></script>
45 <script src="src/h264-stream.js"></script>
46 <script src="src/aac-stream.js"></script>
47 <script src="src/segment-parser.js"></script>
48 <!-- an example MPEG2-TS segment -->
49 <script src="test/tsSegment.js"></script>
50
51 </head>
52 <body>
53 <video id='video'
54 class="video-js vjs-default-skin"
55 height="300"
56 width="600"
57 controls>
58 </video>
59 <script>
60 var video, mediaSource;
61
62 // initialize the player
63 videojs.options.flash.swf = "libs/video-js.swf";
64 video = videojs('video');
65
66 // create a media source
67 mediaSource = new videojs.MediaSource();
68
69 mediaSource.addEventListener('sourceopen', function(event){
70 var tag, bytes, parser;
71
72 // feed parsed bytes into the player
73 var sourceBuffer = mediaSource.addSourceBuffer('video/flv; codecs="vp6,aac"');
74 parser = new videojs.hls.SegmentParser();
75 var header = parser.getFlvHeader();
76 sourceBuffer.appendBuffer(header);
77
78 parser.parseSegmentBinaryData(window.testSegment);
79 while (parser.tagsAvailable()) {
80 tag = parser.getNextTag();
81 console.log('sending bytes', tag.length);
82 sourceBuffer.appendBuffer(tag.bytes.subarray(0, tag.length), video);
83 }
84 }, false);
85
86 url = videojs.URL.createObjectURL(mediaSource);
87
88 video.src({
89 src: url,
90 type: "video/flv"
91 });
92 </script>
93 </body>
94 </html>
...@@ -7,9 +7,216 @@ ...@@ -7,9 +7,216 @@
7 */ 7 */
8 8
9 (function(window) { 9 (function(window) {
10 var
11 FlvTag = window.videojs.hls.FlvTag,
12 adtsSampleingRates = [
13 96000, 88200,
14 64000, 48000,
15 44100, 32000,
16 24000, 22050,
17 16000, 12000
18 ];
19
20 window.videojs.hls.AacStream = function() {
21 var
22 next_pts, // :uint
23 pts_delta = -1, // :int
24 state, // :uint
25 pes_length, // :int
26
27 adtsProtectionAbsent, // :Boolean
28 adtsObjectType, // :int
29 adtsSampleingIndex, // :int
30 adtsChanelConfig, // :int
31 adtsFrameSize, // :int
32 adtsSampleCount, // :int
33 adtsDuration, // :int
34
35 aacFrame, // :FlvTag = null;
36 extraData; // :uint;
10 37
11 window.videojs.hls.AacStream = function(){
12 this.tags = []; 38 this.tags = [];
39
40 // (pts:uint, pes_size:int, dataAligned:Boolean):void
41 this.setNextTimeStamp = function(pts, pes_size, dataAligned) {
42 if (0 > pts_delta) {
43 // We assume the very firts pts is less than 0x80000000
44 pts_delta = pts;
45 }
46
47 next_pts = pts - pts_delta;
48 pes_length = pes_size;
49
50 // If data is aligned, flush all internal buffers
51 if (dataAligned) {
52 state = 0;
53 }
54 };
55
56 // (pData:ByteArray, o:int = 0, l:int = 0):void
57 this.writeBytes = function(pData, o, l) {
58 var
59 e, // :int
60 newExtraData, // :uint
61 bytesToCopy; // :int
62
63 // default arguments
64 o = o || 0;
65 l = l || 0;
66
67 // Do not allow more that 'pes_length' bytes to be written
68 l = (pes_length < l ? pes_length : l);
69 pes_length -= l;
70 e = o + l;
71 while(o < e) {
72 switch (state) {
73 default:
74 state = 0;
75 break;
76 case 0:
77 if (o >= e) {
78 return;
79 }
80 if (0xFF !== pData[o]) {
81 console.log("Error no ATDS header found");
82 o += 1;
83 state = 0;
84 return;
85 }
86
87 o += 1;
88 state = 1;
89 break;
90 case 1:
91 if (o >= e) {
92 return;
93 }
94 if (0xF0 !== (pData[o] & 0xF0)) {
95 console.log("Error no ATDS header found");
96 o +=1;
97 state = 0;
98 return;
99 }
100
101 adtsProtectionAbsent = !!(pData[o] & 0x01);
102
103 o += 1;
104 state = 2;
105 break;
106 case 2:
107 if (o >= e) {
108 return;
109 }
110 adtsObjectType = ((pData[o] & 0xC0) >>> 6) + 1;
111 adtsSampleingIndex = ((pData[o] & 0x3C) >>> 2);
112 adtsChanelConfig = ((pData[o] & 0x01) << 2);
113
114 o += 1;
115 state = 3;
116 break;
117 case 3:
118 if (o >= e) {
119 return;
120 }
121 adtsChanelConfig |= ((pData[o] & 0xC0) >>> 6);
122 adtsFrameSize = ((pData[o] & 0x03) << 11);
123
124 o += 1;
125 state = 4;
126 break;
127 case 4:
128 if (o >= e) {
129 return;
130 }
131 adtsFrameSize |= (pData[o] << 3);
132
133 o += 1;
134 state = 5;
135 break;
136 case 5:
137 if(o >= e) {
138 return;
139 }
140 adtsFrameSize |= ((pData[o] & 0xE0) >>> 5);
141 adtsFrameSize -= (adtsProtectionAbsent ? 7 : 9);
142
143 o += 1;
144 state = 6;
145 break;
146 case 6:
147 if (o >= e) {
148 return;
149 }
150 adtsSampleCount = ((pData[o] & 0x03) + 1) * 1024;
151 adtsDuration = (adtsSampleCount * 1000) / adtsSampleingRates[adtsSampleingIndex];
152
153 newExtraData = (adtsObjectType << 11) |
154 (adtsSampleingIndex << 7) |
155 (adtsChanelConfig << 3);
156 if (newExtraData !== extraData) {
157 aacFrame = new FlvTag(FlvTag.METADATA_TAG);
158 aacFrame.pts = next_pts;
159 aacFrame.dts = next_pts;
160
161 // AAC is always 10
162 aacFrame.writeMetaDataDouble("audiocodecid", 10);
163 aacFrame.writeMetaDataBoolean("stereo", 2 === adtsChanelConfig);
164 aacFrame.writeMetaDataDouble ("audiosamplerate", adtsSampleingRates[adtsSampleingIndex]);
165 // Is AAC always 16 bit?
166 aacFrame.writeMetaDataDouble ("audiosamplesize", 16);
167
168 this.tags.push(aacFrame);
169
170 extraData = newExtraData;
171 aacFrame = new FlvTag(FlvTag.AUDIO_TAG, true);
172 aacFrame.pts = aacFrame.dts;
173 // For audio, DTS is always the same as PTS. We want to set the DTS
174 // however so we can compare with video DTS to determine approximate
175 // packet order
176 aacFrame.pts = next_pts;
177 aacFrame.view.setUint16(aacFrame.position, newExtraData);
178 aacFrame.position += 2;
179
180 this.tags.push(aacFrame);
181 }
182
183 // Skip the checksum if there is one
184 o += 1;
185 state = 7;
186 break;
187 case 7:
188 if (!adtsProtectionAbsent) {
189 if (2 > (e - o)) {
190 return;
191 } else {
192 o += 2;
193 }
194 }
195
196 aacFrame = new FlvTag(FlvTag.AUDIO_TAG);
197 aacFrame.pts = next_pts;
198 aacFrame.dts = next_pts;
199 state = 8;
200 break;
201 case 8:
202 while (adtsFrameSize) {
203 if (o >= e) {
204 return;
205 }
206 bytesToCopy = (e - o) < adtsFrameSize ? (e - o) : adtsFrameSize;
207 aacFrame.writeBytes( pData, o, bytesToCopy );
208 o += bytesToCopy;
209 adtsFrameSize -= bytesToCopy;
210 }
211
212 this.tags.push(aacFrame);
213
214 // finished with this frame
215 state = 0;
216 next_pts += adtsDuration;
217 }
218 }
219 };
13 }; 220 };
14 221
15 })(this); 222 })(this);
......
1 (function() { 1 (function(window) {
2 2
3 window.videojs.hls.ExpGolomb = function() {}; 3 window.videojs.hls.ExpGolomb = function(workingData) {
4 4 var
5 /* 5 // the number of bytes left to examine in workingData
6 public class ExpGolomb 6 workingBytesAvailable = workingData.byteLength,
7 { 7
8 private var workingData:ByteArray; 8 // the current word being examined
9 private var workingWord:uint; 9 workingWord, // :uint
10 private var workingbBitsAvailable:uint; 10
11 11 // the number of bits left to examine in the current word
12 public function ExpGolomb(pData:ByteArray) 12 workingBitsAvailable; // :uint;
13 { 13
14 workingData = pData; 14 // ():uint
15 workingData.position = 0; 15 this.length = function() {
16 loadWord(); 16 return (8 * workingBytesAvailable);
17 } 17 };
18 18
19 public function length():uint 19 // ():uint
20 { 20 this.bitsAvailable = function() {
21 return ( 8 * workingData.length ); 21 return (8 * workingBytesAvailable) + workingBitsAvailable;
22 } 22 };
23 23
24 public function bitsAvailable():uint 24 // ():void
25 { 25 this.loadWord = function() {
26 return ( 8 * workingData.bytesAvailable ) + workingbBitsAvailable; 26 var
27 } 27 workingBytes = new Uint8Array(4),
28 28 availableBytes = Math.min(4, workingBytesAvailable);
29 private function loadWord():void 29
30 { 30 // console.assert(availableBytes > 0);
31 workingWord = 0; workingbBitsAvailable = 0; 31
32 switch( workingData.bytesAvailable ) 32 workingBytes.set(workingData.subarray(0, availableBytes));
33 { 33 workingWord = new DataView(workingBytes.buffer).getUint32(0);
34 case 0: workingbBitsAvailable = 0; break; 34
35 default: // not 0, but greater than 4 35 // track the amount of workingData that has been processed
36 case 4: workingWord = workingData.readUnsignedByte(); workingbBitsAvailable = 8; 36 workingBitsAvailable = availableBytes * 8;
37 case 3: workingWord = ( workingWord << 8 ) | workingData.readUnsignedByte(); workingbBitsAvailable += 8; 37 workingBytesAvailable -= availableBytes;
38 case 2: workingWord = ( workingWord << 8 ) | workingData.readUnsignedByte(); workingbBitsAvailable += 8; 38 };
39 case 1: workingWord = ( workingWord << 8 ) | workingData.readUnsignedByte(); workingbBitsAvailable += 8; 39
40 } 40 // (size:int):void
41 41 this.skipBits = function(size) {
42 workingWord <<= (32 - workingbBitsAvailable); 42 var skipBytes; // :int
43 } 43 if (workingBitsAvailable > size) {
44 44 workingWord <<= size;
45 public function skipBits(size:int):void 45 workingBitsAvailable -= size;
46 { 46 } else {
47 if ( workingbBitsAvailable > size ) 47 size -= workingBitsAvailable;
48 { 48 skipBytes = size / 8;
49 workingWord <<= size; 49
50 workingbBitsAvailable -= size; 50 size -= (skipBytes * 8);
51 } 51 workingData.position += skipBytes;
52 else 52
53 { 53 this.loadWord();
54 size -= workingbBitsAvailable; 54
55 var skipBytes:int = size / 8; 55 workingWord <<= size;
56 56 workingBitsAvailable -= size;
57 size -= ( skipBytes * 8 );
58 workingData.position += skipBytes;
59
60 loadWord();
61
62 workingWord <<= size;
63 workingbBitsAvailable -= size;
64 }
65 }
66
67 public function readBits(size:int):uint
68 {
69 // if ( 32 < size )
70 // throw new Error("Can not read more than 32 bits at a time");
71
72 var bits:uint = ( workingbBitsAvailable < size ? workingbBitsAvailable : size);
73 var valu:uint = workingWord >>> (32 - bits);
74
75 workingbBitsAvailable -= bits;
76 if ( 0 < workingbBitsAvailable )
77 workingWord <<= bits;
78 else
79 loadWord();
80
81 bits = size - bits;
82 if ( 0 < bits )
83 return valu << bits | readBits( bits );
84 else
85 return valu;
86 }
87
88 private function skipLeadingZeros():uint
89 {
90 for( var clz:uint = 0 ; clz < workingbBitsAvailable ; ++clz )
91 {
92 if( 0 != ( workingWord & ( 0x80000000 >>> clz ) ) )
93 {
94 workingWord <<= clz;
95 workingbBitsAvailable -= clz;
96 return clz;
97 }
98 }
99
100 loadWord(); // we exhausted workingWord and still have not found a 1
101 return clz + skipLeadingZeros();
102 }
103
104 public function skipUnsignedExpGolomb():void
105 {
106 skipBits(1 + skipLeadingZeros() );
107 }
108
109 public function skipExpGolomb():void
110 {
111 skipBits(1 + skipLeadingZeros() );
112 }
113
114 public function readUnsignedExpGolomb():uint
115 {
116 var clz:uint = skipLeadingZeros();
117 return readBits(clz+1) - 1;
118 }
119
120 public function readExpGolomb():int
121 {
122 var valu:int = readUnsignedExpGolomb();
123 if ( 0x01 & valu ) // the number is odd if the low order bit is set
124 return (1 + valu) >>> 1; // add 1 to make it even, and devide by 2
125 else
126 return -1 * (valu >>> 1); // devide by two then make it negative
127 }
128
129 // Some convenience functions
130 public function readBoolean():Boolean
131 {
132 return 1 == readBits(1);
133 }
134
135 public function readUnsignedByte():int
136 {
137 return readBits(8);
138 }
139 } 57 }
140 */ 58 };
141 })(); 59
60 // (size:int):uint
61 this.readBits = function(size) {
62 var
63 bits = Math.min(workingBitsAvailable, size), // :uint
64 valu = workingWord >>> (32 - bits); // :uint
65
66 console.assert(32 > size, 'Cannot read more than 32 bits at a time');
67
68 workingBitsAvailable -= bits;
69 if (0 < workingBitsAvailable) {
70 workingWord <<= bits;
71 } else {
72 this.loadWord();
73 }
74
75 bits = size - bits;
76 if (0 < bits) {
77 return valu << bits | this.readBits(bits);
78 } else {
79 return valu;
80 }
81 };
82
83 // ():uint
84 this.skipLeadingZeros = function() {
85 var clz; // :uint
86 for (clz = 0 ; clz < workingBitsAvailable ; ++clz) {
87 if (0 !== (workingWord & (0x80000000 >>> clz))) {
88 workingWord <<= clz;
89 workingBitsAvailable -= clz;
90 return clz;
91 }
92 }
93
94 // we exhausted workingWord and still have not found a 1
95 this.loadWord();
96 return clz + this.skipLeadingZeros();
97 };
98
99 // ():void
100 this.skipUnsignedExpGolomb = function() {
101 this.skipBits(1 + this.skipLeadingZeros());
102 };
103
104 // ():void
105 this.skipExpGolomb = function() {
106 this.skipBits(1 + this.skipLeadingZeros());
107 };
108
109 // ():uint
110 this.readUnsignedExpGolomb = function() {
111 var clz = this.skipLeadingZeros(); // :uint
112 return this.readBits(clz + 1) - 1;
113 };
114
115 // ():int
116 this.readExpGolomb = function() {
117 var valu = this.readUnsignedExpGolomb(); // :int
118 if (0x01 & valu) {
119 // the number is odd if the low order bit is set
120 return (1 + valu) >>> 1; // add 1 to make it even, and divide by 2
121 } else {
122 return -1 * (valu >>> 1); // divide by two then make it negative
123 }
124 };
125
126 // Some convenience functions
127 // :Boolean
128 this.readBoolean = function() {
129 return 1 === this.readBits(1);
130 };
131
132 // ():int
133 this.readUnsignedByte = function() {
134 return this.readBits(8);
135 };
136
137 this.loadWord();
138
139 };
140 })(this);
......
...@@ -187,7 +187,7 @@ ...@@ -187,7 +187,7 @@
187 } 187 }
188 188
189 // attempt to parse a m2ts packet 189 // attempt to parse a m2ts packet
190 if (parseTSPacket(data.subarray(dataPosition, m2tsPacketSize))) { 190 if (parseTSPacket(data.subarray(dataPosition, dataPosition + m2tsPacketSize))) {
191 dataPosition += m2tsPacketSize; 191 dataPosition += m2tsPacketSize;
192 } else { 192 } else {
193 // If there was an error parsing a TS packet. it could be 193 // If there was an error parsing a TS packet. it could be
...@@ -203,7 +203,7 @@ ...@@ -203,7 +203,7 @@
203 // packet! 203 // packet!
204 parseTSPacket = function(data) { // :ByteArray):Boolean { 204 parseTSPacket = function(data) { // :ByteArray):Boolean {
205 var 205 var
206 s = data.position, //:uint 206 s = 0, //:uint
207 o = s, // :uint 207 o = s, // :uint
208 e = o + m2tsPacketSize, // :uint 208 e = o + m2tsPacketSize, // :uint
209 209
...@@ -211,10 +211,10 @@ ...@@ -211,10 +211,10 @@
211 // parseSegmentBinaryData() 211 // parseSegmentBinaryData()
212 212
213 // Payload Unit Start Indicator 213 // Payload Unit Start Indicator
214 pusi = !!(data[o+1] & 0x40), 214 pusi = !!(data[o + 1] & 0x40), // mask: 0100 0000
215 215
216 // PacketId 216 // PacketId
217 pid = (data[o + 1] & 0x1F) << 8 | data[o+2], 217 pid = (data[o + 1] & 0x1F) << 8 | data[o + 2], // mask: 0001 1111
218 afflag = (data[o + 3] & 0x30 ) >>> 4, 218 afflag = (data[o + 3] & 0x30 ) >>> 4,
219 219
220 aflen, // :uint 220 aflen, // :uint
...@@ -259,7 +259,7 @@ ...@@ -259,7 +259,7 @@
259 259
260 console.assert(0x00 === patTableId, 'patTableId should be 0x00'); 260 console.assert(0x00 === patTableId, 'patTableId should be 0x00');
261 261
262 patCurrentNextIndicator = !!(data[o+5] & 0x01); 262 patCurrentNextIndicator = !!(data[o + 5] & 0x01);
263 if (patCurrentNextIndicator) { 263 if (patCurrentNextIndicator) {
264 patSectionLength = (data[o + 1] & 0x0F) << 8 | data[o + 2]; 264 patSectionLength = (data[o + 1] & 0x0F) << 8 | data[o + 2];
265 o += 8; // skip past PSI header 265 o += 8; // skip past PSI header
...@@ -280,10 +280,10 @@ ...@@ -280,10 +280,10 @@
280 } else if (videoPid === pid || audioPid === pid) { 280 } else if (videoPid === pid || audioPid === pid) {
281 if (pusi) { 281 if (pusi) {
282 // comment out for speed 282 // comment out for speed
283 // if( 0x00 != data[o+0] || 0x00 != data[o+1] || 0x01 != data[o+2] ) 283 if (0x00 !== data[o + 0] || 0x00 !== data[o + 1] || 0x01 !== data[o + 2]) {
284 // {// look for PES start code 284 // look for PES start code
285 // throw new Error("PES did not begin with start code"); 285 throw new Error("PES did not begin with start code");
286 // } 286 }
287 287
288 // var sid:int = data[o+3]; // StreamID 288 // var sid:int = data[o+3]; // StreamID
289 pesPacketSize = (data[o + 4] << 8) | data[o + 5]; 289 pesPacketSize = (data[o + 4] << 8) | data[o + 5];
...@@ -334,14 +334,14 @@ ...@@ -334,14 +334,14 @@
334 } 334 }
335 335
336 if (audioPid === pid) { 336 if (audioPid === pid) {
337 aacStream.writeBytes(data,o,e-o); 337 aacStream.writeBytes(data, o, e - o);
338 } else if (videoPid === pid) { 338 } else if (videoPid === pid) {
339 h264Stream.writeBytes(data,o,e-o); 339 h264Stream.writeBytes(data, o, e - o);
340 } 340 }
341 } else if (pmtPid === pid) { 341 } else if (pmtPid === pid) {
342 // TODO sanity check data[o] 342 // TODO sanity check data[o]
343 // if pusi is set we must skip X bytes (PSI pointer field) 343 // if pusi is set we must skip X bytes (PSI pointer field)
344 o += ( pusi ? 1 + data[o] : 0 ); 344 o += (pusi ? 1 + data[o] : 0);
345 pmtTableId = data[o]; 345 pmtTableId = data[o];
346 346
347 console.assert(0x02 === pmtTableId); 347 console.assert(0x02 === pmtTableId);
...@@ -349,7 +349,7 @@ ...@@ -349,7 +349,7 @@
349 pmtCurrentNextIndicator = !!(data[o + 5] & 0x01); 349 pmtCurrentNextIndicator = !!(data[o + 5] & 0x01);
350 if (pmtCurrentNextIndicator) { 350 if (pmtCurrentNextIndicator) {
351 audioPid = videoPid = 0; 351 audioPid = videoPid = 0;
352 pmtSectionLength = (data[o + 1] & 0x0F ) << 8 | data[o + 2]; 352 pmtSectionLength = (data[o + 1] & 0x0F) << 8 | data[o + 2];
353 // skip CRC and PSI data we dont care about 353 // skip CRC and PSI data we dont care about
354 pmtSectionLength -= 13; 354 pmtSectionLength -= 13;
355 355
...@@ -357,7 +357,7 @@ ...@@ -357,7 +357,7 @@
357 while (0 < pmtSectionLength) { 357 while (0 < pmtSectionLength) {
358 streamType = data[o + 0]; 358 streamType = data[o + 0];
359 elementaryPID = (data[o + 1] & 0x1F) << 8 | data[o + 2]; 359 elementaryPID = (data[o + 1] & 0x1F) << 8 | data[o + 2];
360 ESInfolength = (data[o + 3] & 0x0F ) << 8 | data[o + 4]; 360 ESInfolength = (data[o + 3] & 0x0F) << 8 | data[o + 4];
361 o += 5 + ESInfolength; 361 o += 5 + ESInfolength;
362 pmtSectionLength -= 5 + ESInfolength; 362 pmtSectionLength -= 5 + ESInfolength;
363 363
......
No preview for this file type
No preview for this file type
This diff could not be displayed because it is too large.
...@@ -39,9 +39,10 @@ ...@@ -39,9 +39,10 @@
39 39
40 <!-- HLS plugin --> 40 <!-- HLS plugin -->
41 <script src="../src/video-js-hls.js"></script> 41 <script src="../src/video-js-hls.js"></script>
42 <script src="../src/flv-tag.js"></script>
43 <script src="../src/exp-golomb.js"></script>
42 <script src="../src/h264-stream.js"></script> 44 <script src="../src/h264-stream.js"></script>
43 <script src="../src/aac-stream.js"></script> 45 <script src="../src/aac-stream.js"></script>
44 <script src="../src/flv-tag.js"></script>
45 <script src="../src/segment-parser.js"></script> 46 <script src="../src/segment-parser.js"></script>
46 <!-- an example MPEG2-TS segment --> 47 <!-- an example MPEG2-TS segment -->
47 <script src="tsSegment.js"></script> 48 <script src="tsSegment.js"></script>
......
...@@ -19,7 +19,13 @@ ...@@ -19,7 +19,13 @@
19 notStrictEqual(actual, expected, [message]) 19 notStrictEqual(actual, expected, [message])
20 throws(block, [expected], [message]) 20 throws(block, [expected], [message])
21 */ 21 */
22 var parser; 22 var
23 parser,
24
25 expectedHeader = [
26 0x46, 0x4c, 0x56, 0x01, 0x05, 0x00, 0x00, 0x00,
27 0x09, 0x00, 0x00, 0x00, 0x00
28 ];
23 29
24 module('environment'); 30 module('environment');
25 31
...@@ -35,17 +41,20 @@ ...@@ -35,17 +41,20 @@
35 }); 41 });
36 42
37 test('creates an flv header', function() { 43 test('creates an flv header', function() {
38 var header = parser.getFlvHeader(); 44 var header = Array.prototype.slice.call(parser.getFlvHeader());
39 ok(header, 'the header is truthy'); 45 ok(header, 'the header is truthy');
40 equal(9 + 4, header.byteLength, 'the header length is correct'); 46 equal(9 + 4, header.length, 'the header length is correct');
41 equal(header[0], 'F'.charCodeAt(0), 'the signature is correct'); 47 equal(header[0], 'F'.charCodeAt(0), 'the signature is correct');
42 equal(header[1], 'L'.charCodeAt(0), 'the signature is correct'); 48 equal(header[1], 'L'.charCodeAt(0), 'the signature is correct');
43 equal(header[2], 'V'.charCodeAt(0), 'the signature is correct'); 49 equal(header[2], 'V'.charCodeAt(0), 'the signature is correct');
50
51 deepEqual(expectedHeader, header, 'the rest of the header is correct');
44 }); 52 });
45 53
46 test('parses the first bipbop segment', function() { 54 test('parses the first bipbop segment', function() {
55 var tag, bytes;
47 parser.parseSegmentBinaryData(window.testSegment); 56 parser.parseSegmentBinaryData(window.testSegment);
48 57
49 ok(parser.tagsAvailable(), 'tags should be available'); 58 ok(parser.tagsAvailable(), 'tags are available');
50 }); 59 });
51 })(this); 60 })(this);
......