1 |
|
2 | var transmuxerWorker = (function () {
|
3 | 'use strict';
|
4 |
|
5 | |
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 | var Stream = function() {
|
16 | this.init = function() {
|
17 | var listeners = {};
|
18 | |
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 | this.on = function(type, listener) {
|
25 | if (!listeners[type]) {
|
26 | listeners[type] = [];
|
27 | }
|
28 | listeners[type] = listeners[type].concat(listener);
|
29 | };
|
30 | |
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 | this.off = function(type, listener) {
|
37 | var index;
|
38 | if (!listeners[type]) {
|
39 | return false;
|
40 | }
|
41 | index = listeners[type].indexOf(listener);
|
42 | listeners[type] = listeners[type].slice();
|
43 | listeners[type].splice(index, 1);
|
44 | return index > -1;
|
45 | };
|
46 | |
47 |
|
48 |
|
49 |
|
50 |
|
51 | this.trigger = function(type) {
|
52 | var callbacks, i, length, args;
|
53 | callbacks = listeners[type];
|
54 | if (!callbacks) {
|
55 | return;
|
56 | }
|
57 |
|
58 |
|
59 |
|
60 |
|
61 | if (arguments.length === 2) {
|
62 | length = callbacks.length;
|
63 | for (i = 0; i < length; ++i) {
|
64 | callbacks[i].call(this, arguments[1]);
|
65 | }
|
66 | } else {
|
67 | args = [];
|
68 | i = arguments.length;
|
69 | for (i = 1; i < arguments.length; ++i) {
|
70 | args.push(arguments[i]);
|
71 | }
|
72 | length = callbacks.length;
|
73 | for (i = 0; i < length; ++i) {
|
74 | callbacks[i].apply(this, args);
|
75 | }
|
76 | }
|
77 | };
|
78 | |
79 |
|
80 |
|
81 | this.dispose = function() {
|
82 | listeners = {};
|
83 | };
|
84 | };
|
85 | };
|
86 |
|
87 | |
88 |
|
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 | Stream.prototype.pipe = function(destination) {
|
97 | this.on('data', function(data) {
|
98 | destination.push(data);
|
99 | });
|
100 |
|
101 | this.on('done', function(flushSource) {
|
102 | destination.flush(flushSource);
|
103 | });
|
104 |
|
105 | this.on('partialdone', function(flushSource) {
|
106 | destination.partialFlush(flushSource);
|
107 | });
|
108 |
|
109 | this.on('endedtimeline', function(flushSource) {
|
110 | destination.endTimeline(flushSource);
|
111 | });
|
112 |
|
113 | this.on('reset', function(flushSource) {
|
114 | destination.reset(flushSource);
|
115 | });
|
116 |
|
117 | return destination;
|
118 | };
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 | Stream.prototype.push = function(data) {
|
125 | this.trigger('data', data);
|
126 | };
|
127 |
|
128 | Stream.prototype.flush = function(flushSource) {
|
129 | this.trigger('done', flushSource);
|
130 | };
|
131 |
|
132 | Stream.prototype.partialFlush = function(flushSource) {
|
133 | this.trigger('partialdone', flushSource);
|
134 | };
|
135 |
|
136 | Stream.prototype.endTimeline = function(flushSource) {
|
137 | this.trigger('endedtimeline', flushSource);
|
138 | };
|
139 |
|
140 | Stream.prototype.reset = function(flushSource) {
|
141 | this.trigger('reset', flushSource);
|
142 | };
|
143 |
|
144 | var stream = Stream;
|
145 |
|
146 | |
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 | var UINT32_MAX = Math.pow(2, 32) - 1;
|
157 |
|
158 | var box, dinf, esds, ftyp, mdat, mfhd, minf, moof, moov, mvex, mvhd,
|
159 | trak, tkhd, mdia, mdhd, hdlr, sdtp, stbl, stsd, traf, trex,
|
160 | trun, types, MAJOR_BRAND, MINOR_VERSION, AVC1_BRAND, VIDEO_HDLR,
|
161 | AUDIO_HDLR, HDLR_TYPES, VMHD, SMHD, DREF, STCO, STSC, STSZ, STTS;
|
162 |
|
163 |
|
164 | (function() {
|
165 | var i;
|
166 | types = {
|
167 | avc1: [],
|
168 | avcC: [],
|
169 | btrt: [],
|
170 | dinf: [],
|
171 | dref: [],
|
172 | esds: [],
|
173 | ftyp: [],
|
174 | hdlr: [],
|
175 | mdat: [],
|
176 | mdhd: [],
|
177 | mdia: [],
|
178 | mfhd: [],
|
179 | minf: [],
|
180 | moof: [],
|
181 | moov: [],
|
182 | mp4a: [],
|
183 | mvex: [],
|
184 | mvhd: [],
|
185 | pasp: [],
|
186 | sdtp: [],
|
187 | smhd: [],
|
188 | stbl: [],
|
189 | stco: [],
|
190 | stsc: [],
|
191 | stsd: [],
|
192 | stsz: [],
|
193 | stts: [],
|
194 | styp: [],
|
195 | tfdt: [],
|
196 | tfhd: [],
|
197 | traf: [],
|
198 | trak: [],
|
199 | trun: [],
|
200 | trex: [],
|
201 | tkhd: [],
|
202 | vmhd: []
|
203 | };
|
204 |
|
205 |
|
206 |
|
207 | if (typeof Uint8Array === 'undefined') {
|
208 | return;
|
209 | }
|
210 |
|
211 | for (i in types) {
|
212 | if (types.hasOwnProperty(i)) {
|
213 | types[i] = [
|
214 | i.charCodeAt(0),
|
215 | i.charCodeAt(1),
|
216 | i.charCodeAt(2),
|
217 | i.charCodeAt(3)
|
218 | ];
|
219 | }
|
220 | }
|
221 |
|
222 | MAJOR_BRAND = new Uint8Array([
|
223 | 'i'.charCodeAt(0),
|
224 | 's'.charCodeAt(0),
|
225 | 'o'.charCodeAt(0),
|
226 | 'm'.charCodeAt(0)
|
227 | ]);
|
228 | AVC1_BRAND = new Uint8Array([
|
229 | 'a'.charCodeAt(0),
|
230 | 'v'.charCodeAt(0),
|
231 | 'c'.charCodeAt(0),
|
232 | '1'.charCodeAt(0)
|
233 | ]);
|
234 | MINOR_VERSION = new Uint8Array([0, 0, 0, 1]);
|
235 | VIDEO_HDLR = new Uint8Array([
|
236 | 0x00,
|
237 | 0x00, 0x00, 0x00,
|
238 | 0x00, 0x00, 0x00, 0x00,
|
239 | 0x76, 0x69, 0x64, 0x65,
|
240 | 0x00, 0x00, 0x00, 0x00,
|
241 | 0x00, 0x00, 0x00, 0x00,
|
242 | 0x00, 0x00, 0x00, 0x00,
|
243 | 0x56, 0x69, 0x64, 0x65,
|
244 | 0x6f, 0x48, 0x61, 0x6e,
|
245 | 0x64, 0x6c, 0x65, 0x72, 0x00
|
246 | ]);
|
247 | AUDIO_HDLR = new Uint8Array([
|
248 | 0x00,
|
249 | 0x00, 0x00, 0x00,
|
250 | 0x00, 0x00, 0x00, 0x00,
|
251 | 0x73, 0x6f, 0x75, 0x6e,
|
252 | 0x00, 0x00, 0x00, 0x00,
|
253 | 0x00, 0x00, 0x00, 0x00,
|
254 | 0x00, 0x00, 0x00, 0x00,
|
255 | 0x53, 0x6f, 0x75, 0x6e,
|
256 | 0x64, 0x48, 0x61, 0x6e,
|
257 | 0x64, 0x6c, 0x65, 0x72, 0x00
|
258 | ]);
|
259 | HDLR_TYPES = {
|
260 | video: VIDEO_HDLR,
|
261 | audio: AUDIO_HDLR
|
262 | };
|
263 | DREF = new Uint8Array([
|
264 | 0x00,
|
265 | 0x00, 0x00, 0x00,
|
266 | 0x00, 0x00, 0x00, 0x01,
|
267 | 0x00, 0x00, 0x00, 0x0c,
|
268 | 0x75, 0x72, 0x6c, 0x20,
|
269 | 0x00,
|
270 | 0x00, 0x00, 0x01
|
271 | ]);
|
272 | SMHD = new Uint8Array([
|
273 | 0x00,
|
274 | 0x00, 0x00, 0x00,
|
275 | 0x00, 0x00,
|
276 | 0x00, 0x00
|
277 | ]);
|
278 | STCO = new Uint8Array([
|
279 | 0x00,
|
280 | 0x00, 0x00, 0x00,
|
281 | 0x00, 0x00, 0x00, 0x00
|
282 | ]);
|
283 | STSC = STCO;
|
284 | STSZ = new Uint8Array([
|
285 | 0x00,
|
286 | 0x00, 0x00, 0x00,
|
287 | 0x00, 0x00, 0x00, 0x00,
|
288 | 0x00, 0x00, 0x00, 0x00
|
289 | ]);
|
290 | STTS = STCO;
|
291 | VMHD = new Uint8Array([
|
292 | 0x00,
|
293 | 0x00, 0x00, 0x01,
|
294 | 0x00, 0x00,
|
295 | 0x00, 0x00,
|
296 | 0x00, 0x00,
|
297 | 0x00, 0x00
|
298 | ]);
|
299 | }());
|
300 |
|
301 | box = function(type) {
|
302 | var
|
303 | payload = [],
|
304 | size = 0,
|
305 | i,
|
306 | result,
|
307 | view;
|
308 |
|
309 | for (i = 1; i < arguments.length; i++) {
|
310 | payload.push(arguments[i]);
|
311 | }
|
312 |
|
313 | i = payload.length;
|
314 |
|
315 |
|
316 | while (i--) {
|
317 | size += payload[i].byteLength;
|
318 | }
|
319 | result = new Uint8Array(size + 8);
|
320 | view = new DataView(result.buffer, result.byteOffset, result.byteLength);
|
321 | view.setUint32(0, result.byteLength);
|
322 | result.set(type, 4);
|
323 |
|
324 |
|
325 | for (i = 0, size = 8; i < payload.length; i++) {
|
326 | result.set(payload[i], size);
|
327 | size += payload[i].byteLength;
|
328 | }
|
329 | return result;
|
330 | };
|
331 |
|
332 | dinf = function() {
|
333 | return box(types.dinf, box(types.dref, DREF));
|
334 | };
|
335 |
|
336 | esds = function(track) {
|
337 | return box(types.esds, new Uint8Array([
|
338 | 0x00,
|
339 | 0x00, 0x00, 0x00,
|
340 |
|
341 |
|
342 | 0x03,
|
343 | 0x19,
|
344 | 0x00, 0x00,
|
345 | 0x00,
|
346 |
|
347 |
|
348 | 0x04,
|
349 | 0x11,
|
350 | 0x40,
|
351 | 0x15,
|
352 | 0x00, 0x06, 0x00,
|
353 | 0x00, 0x00, 0xda, 0xc0,
|
354 | 0x00, 0x00, 0xda, 0xc0,
|
355 |
|
356 |
|
357 | 0x05,
|
358 | 0x02,
|
359 |
|
360 |
|
361 | (track.audioobjecttype << 3) | (track.samplingfrequencyindex >>> 1),
|
362 | (track.samplingfrequencyindex << 7) | (track.channelcount << 3),
|
363 | 0x06, 0x01, 0x02
|
364 | ]));
|
365 | };
|
366 |
|
367 | ftyp = function() {
|
368 | return box(types.ftyp, MAJOR_BRAND, MINOR_VERSION, MAJOR_BRAND, AVC1_BRAND);
|
369 | };
|
370 |
|
371 | hdlr = function(type) {
|
372 | return box(types.hdlr, HDLR_TYPES[type]);
|
373 | };
|
374 | mdat = function(data) {
|
375 | return box(types.mdat, data);
|
376 | };
|
377 | mdhd = function(track) {
|
378 | var result = new Uint8Array([
|
379 | 0x00,
|
380 | 0x00, 0x00, 0x00,
|
381 | 0x00, 0x00, 0x00, 0x02,
|
382 | 0x00, 0x00, 0x00, 0x03,
|
383 | 0x00, 0x01, 0x5f, 0x90,
|
384 |
|
385 | (track.duration >>> 24) & 0xFF,
|
386 | (track.duration >>> 16) & 0xFF,
|
387 | (track.duration >>> 8) & 0xFF,
|
388 | track.duration & 0xFF,
|
389 | 0x55, 0xc4,
|
390 | 0x00, 0x00
|
391 | ]);
|
392 |
|
393 |
|
394 |
|
395 |
|
396 | if (track.samplerate) {
|
397 | result[12] = (track.samplerate >>> 24) & 0xFF;
|
398 | result[13] = (track.samplerate >>> 16) & 0xFF;
|
399 | result[14] = (track.samplerate >>> 8) & 0xFF;
|
400 | result[15] = (track.samplerate) & 0xFF;
|
401 | }
|
402 |
|
403 | return box(types.mdhd, result);
|
404 | };
|
405 | mdia = function(track) {
|
406 | return box(types.mdia, mdhd(track), hdlr(track.type), minf(track));
|
407 | };
|
408 | mfhd = function(sequenceNumber) {
|
409 | return box(types.mfhd, new Uint8Array([
|
410 | 0x00,
|
411 | 0x00, 0x00, 0x00,
|
412 | (sequenceNumber & 0xFF000000) >> 24,
|
413 | (sequenceNumber & 0xFF0000) >> 16,
|
414 | (sequenceNumber & 0xFF00) >> 8,
|
415 | sequenceNumber & 0xFF
|
416 | ]));
|
417 | };
|
418 | minf = function(track) {
|
419 | return box(types.minf,
|
420 | track.type === 'video' ? box(types.vmhd, VMHD) : box(types.smhd, SMHD),
|
421 | dinf(),
|
422 | stbl(track));
|
423 | };
|
424 | moof = function(sequenceNumber, tracks) {
|
425 | var
|
426 | trackFragments = [],
|
427 | i = tracks.length;
|
428 |
|
429 | while (i--) {
|
430 | trackFragments[i] = traf(tracks[i]);
|
431 | }
|
432 | return box.apply(null, [
|
433 | types.moof,
|
434 | mfhd(sequenceNumber)
|
435 | ].concat(trackFragments));
|
436 | };
|
437 | |
438 |
|
439 |
|
440 |
|
441 |
|
442 | moov = function(tracks) {
|
443 | var
|
444 | i = tracks.length,
|
445 | boxes = [];
|
446 |
|
447 | while (i--) {
|
448 | boxes[i] = trak(tracks[i]);
|
449 | }
|
450 |
|
451 | return box.apply(null, [types.moov, mvhd(0xffffffff)].concat(boxes).concat(mvex(tracks)));
|
452 | };
|
453 | mvex = function(tracks) {
|
454 | var
|
455 | i = tracks.length,
|
456 | boxes = [];
|
457 |
|
458 | while (i--) {
|
459 | boxes[i] = trex(tracks[i]);
|
460 | }
|
461 | return box.apply(null, [types.mvex].concat(boxes));
|
462 | };
|
463 | mvhd = function(duration) {
|
464 | var
|
465 | bytes = new Uint8Array([
|
466 | 0x00,
|
467 | 0x00, 0x00, 0x00,
|
468 | 0x00, 0x00, 0x00, 0x01,
|
469 | 0x00, 0x00, 0x00, 0x02,
|
470 | 0x00, 0x01, 0x5f, 0x90,
|
471 | (duration & 0xFF000000) >> 24,
|
472 | (duration & 0xFF0000) >> 16,
|
473 | (duration & 0xFF00) >> 8,
|
474 | duration & 0xFF,
|
475 | 0x00, 0x01, 0x00, 0x00,
|
476 | 0x01, 0x00,
|
477 | 0x00, 0x00,
|
478 | 0x00, 0x00, 0x00, 0x00,
|
479 | 0x00, 0x00, 0x00, 0x00,
|
480 | 0x00, 0x01, 0x00, 0x00,
|
481 | 0x00, 0x00, 0x00, 0x00,
|
482 | 0x00, 0x00, 0x00, 0x00,
|
483 | 0x00, 0x00, 0x00, 0x00,
|
484 | 0x00, 0x01, 0x00, 0x00,
|
485 | 0x00, 0x00, 0x00, 0x00,
|
486 | 0x00, 0x00, 0x00, 0x00,
|
487 | 0x00, 0x00, 0x00, 0x00,
|
488 | 0x40, 0x00, 0x00, 0x00,
|
489 | 0x00, 0x00, 0x00, 0x00,
|
490 | 0x00, 0x00, 0x00, 0x00,
|
491 | 0x00, 0x00, 0x00, 0x00,
|
492 | 0x00, 0x00, 0x00, 0x00,
|
493 | 0x00, 0x00, 0x00, 0x00,
|
494 | 0x00, 0x00, 0x00, 0x00,
|
495 | 0xff, 0xff, 0xff, 0xff
|
496 | ]);
|
497 | return box(types.mvhd, bytes);
|
498 | };
|
499 |
|
500 | sdtp = function(track) {
|
501 | var
|
502 | samples = track.samples || [],
|
503 | bytes = new Uint8Array(4 + samples.length),
|
504 | flags,
|
505 | i;
|
506 |
|
507 |
|
508 |
|
509 |
|
510 | for (i = 0; i < samples.length; i++) {
|
511 | flags = samples[i].flags;
|
512 |
|
513 | bytes[i + 4] = (flags.dependsOn << 4) |
|
514 | (flags.isDependedOn << 2) |
|
515 | (flags.hasRedundancy);
|
516 | }
|
517 |
|
518 | return box(types.sdtp,
|
519 | bytes);
|
520 | };
|
521 |
|
522 | stbl = function(track) {
|
523 | return box(types.stbl,
|
524 | stsd(track),
|
525 | box(types.stts, STTS),
|
526 | box(types.stsc, STSC),
|
527 | box(types.stsz, STSZ),
|
528 | box(types.stco, STCO));
|
529 | };
|
530 |
|
531 | (function() {
|
532 | var videoSample, audioSample;
|
533 |
|
534 | stsd = function(track) {
|
535 |
|
536 | return box(types.stsd, new Uint8Array([
|
537 | 0x00,
|
538 | 0x00, 0x00, 0x00,
|
539 | 0x00, 0x00, 0x00, 0x01
|
540 | ]), track.type === 'video' ? videoSample(track) : audioSample(track));
|
541 | };
|
542 |
|
543 | videoSample = function(track) {
|
544 | var
|
545 | sps = track.sps || [],
|
546 | pps = track.pps || [],
|
547 | sequenceParameterSets = [],
|
548 | pictureParameterSets = [],
|
549 | i,
|
550 | avc1Box;
|
551 |
|
552 |
|
553 | for (i = 0; i < sps.length; i++) {
|
554 | sequenceParameterSets.push((sps[i].byteLength & 0xFF00) >>> 8);
|
555 | sequenceParameterSets.push((sps[i].byteLength & 0xFF));
|
556 | sequenceParameterSets = sequenceParameterSets.concat(Array.prototype.slice.call(sps[i]));
|
557 | }
|
558 |
|
559 |
|
560 | for (i = 0; i < pps.length; i++) {
|
561 | pictureParameterSets.push((pps[i].byteLength & 0xFF00) >>> 8);
|
562 | pictureParameterSets.push((pps[i].byteLength & 0xFF));
|
563 | pictureParameterSets = pictureParameterSets.concat(Array.prototype.slice.call(pps[i]));
|
564 | }
|
565 |
|
566 | avc1Box = [
|
567 | types.avc1, new Uint8Array([
|
568 | 0x00, 0x00, 0x00,
|
569 | 0x00, 0x00, 0x00,
|
570 | 0x00, 0x01,
|
571 | 0x00, 0x00,
|
572 | 0x00, 0x00,
|
573 | 0x00, 0x00, 0x00, 0x00,
|
574 | 0x00, 0x00, 0x00, 0x00,
|
575 | 0x00, 0x00, 0x00, 0x00,
|
576 | (track.width & 0xff00) >> 8,
|
577 | track.width & 0xff,
|
578 | (track.height & 0xff00) >> 8,
|
579 | track.height & 0xff,
|
580 | 0x00, 0x48, 0x00, 0x00,
|
581 | 0x00, 0x48, 0x00, 0x00,
|
582 | 0x00, 0x00, 0x00, 0x00,
|
583 | 0x00, 0x01,
|
584 | 0x13,
|
585 | 0x76, 0x69, 0x64, 0x65,
|
586 | 0x6f, 0x6a, 0x73, 0x2d,
|
587 | 0x63, 0x6f, 0x6e, 0x74,
|
588 | 0x72, 0x69, 0x62, 0x2d,
|
589 | 0x68, 0x6c, 0x73, 0x00,
|
590 | 0x00, 0x00, 0x00, 0x00,
|
591 | 0x00, 0x00, 0x00, 0x00,
|
592 | 0x00, 0x00, 0x00,
|
593 | 0x00, 0x18,
|
594 | 0x11, 0x11
|
595 | ]),
|
596 | box(types.avcC, new Uint8Array([
|
597 | 0x01,
|
598 | track.profileIdc,
|
599 | track.profileCompatibility,
|
600 | track.levelIdc,
|
601 | 0xff
|
602 | ].concat(
|
603 | [sps.length],
|
604 | sequenceParameterSets,
|
605 | [pps.length],
|
606 | pictureParameterSets
|
607 | ))),
|
608 | box(types.btrt, new Uint8Array([
|
609 | 0x00, 0x1c, 0x9c, 0x80,
|
610 | 0x00, 0x2d, 0xc6, 0xc0,
|
611 | 0x00, 0x2d, 0xc6, 0xc0
|
612 | ]))
|
613 | ];
|
614 |
|
615 | if (track.sarRatio) {
|
616 | var
|
617 | hSpacing = track.sarRatio[0],
|
618 | vSpacing = track.sarRatio[1];
|
619 |
|
620 | avc1Box.push(
|
621 | box(types.pasp, new Uint8Array([
|
622 | (hSpacing & 0xFF000000) >> 24,
|
623 | (hSpacing & 0xFF0000) >> 16,
|
624 | (hSpacing & 0xFF00) >> 8,
|
625 | hSpacing & 0xFF,
|
626 | (vSpacing & 0xFF000000) >> 24,
|
627 | (vSpacing & 0xFF0000) >> 16,
|
628 | (vSpacing & 0xFF00) >> 8,
|
629 | vSpacing & 0xFF
|
630 | ]))
|
631 | );
|
632 | }
|
633 |
|
634 | return box.apply(null, avc1Box);
|
635 | };
|
636 |
|
637 | audioSample = function(track) {
|
638 | return box(types.mp4a, new Uint8Array([
|
639 |
|
640 |
|
641 | 0x00, 0x00, 0x00,
|
642 | 0x00, 0x00, 0x00,
|
643 | 0x00, 0x01,
|
644 |
|
645 |
|
646 | 0x00, 0x00, 0x00, 0x00,
|
647 | 0x00, 0x00, 0x00, 0x00,
|
648 | (track.channelcount & 0xff00) >> 8,
|
649 | (track.channelcount & 0xff),
|
650 |
|
651 | (track.samplesize & 0xff00) >> 8,
|
652 | (track.samplesize & 0xff),
|
653 | 0x00, 0x00,
|
654 | 0x00, 0x00,
|
655 |
|
656 | (track.samplerate & 0xff00) >> 8,
|
657 | (track.samplerate & 0xff),
|
658 | 0x00, 0x00
|
659 |
|
660 |
|
661 | ]), esds(track));
|
662 | };
|
663 | }());
|
664 |
|
665 | tkhd = function(track) {
|
666 | var result = new Uint8Array([
|
667 | 0x00,
|
668 | 0x00, 0x00, 0x07,
|
669 | 0x00, 0x00, 0x00, 0x00,
|
670 | 0x00, 0x00, 0x00, 0x00,
|
671 | (track.id & 0xFF000000) >> 24,
|
672 | (track.id & 0xFF0000) >> 16,
|
673 | (track.id & 0xFF00) >> 8,
|
674 | track.id & 0xFF,
|
675 | 0x00, 0x00, 0x00, 0x00,
|
676 | (track.duration & 0xFF000000) >> 24,
|
677 | (track.duration & 0xFF0000) >> 16,
|
678 | (track.duration & 0xFF00) >> 8,
|
679 | track.duration & 0xFF,
|
680 | 0x00, 0x00, 0x00, 0x00,
|
681 | 0x00, 0x00, 0x00, 0x00,
|
682 | 0x00, 0x00,
|
683 | 0x00, 0x00,
|
684 | 0x01, 0x00,
|
685 | 0x00, 0x00,
|
686 | 0x00, 0x01, 0x00, 0x00,
|
687 | 0x00, 0x00, 0x00, 0x00,
|
688 | 0x00, 0x00, 0x00, 0x00,
|
689 | 0x00, 0x00, 0x00, 0x00,
|
690 | 0x00, 0x01, 0x00, 0x00,
|
691 | 0x00, 0x00, 0x00, 0x00,
|
692 | 0x00, 0x00, 0x00, 0x00,
|
693 | 0x00, 0x00, 0x00, 0x00,
|
694 | 0x40, 0x00, 0x00, 0x00,
|
695 | (track.width & 0xFF00) >> 8,
|
696 | track.width & 0xFF,
|
697 | 0x00, 0x00,
|
698 | (track.height & 0xFF00) >> 8,
|
699 | track.height & 0xFF,
|
700 | 0x00, 0x00
|
701 | ]);
|
702 |
|
703 | return box(types.tkhd, result);
|
704 | };
|
705 |
|
706 | |
707 |
|
708 |
|
709 |
|
710 | traf = function(track) {
|
711 | var trackFragmentHeader, trackFragmentDecodeTime, trackFragmentRun,
|
712 | sampleDependencyTable, dataOffset,
|
713 | upperWordBaseMediaDecodeTime, lowerWordBaseMediaDecodeTime;
|
714 |
|
715 | trackFragmentHeader = box(types.tfhd, new Uint8Array([
|
716 | 0x00,
|
717 | 0x00, 0x00, 0x3a,
|
718 | (track.id & 0xFF000000) >> 24,
|
719 | (track.id & 0xFF0000) >> 16,
|
720 | (track.id & 0xFF00) >> 8,
|
721 | (track.id & 0xFF),
|
722 | 0x00, 0x00, 0x00, 0x01,
|
723 | 0x00, 0x00, 0x00, 0x00,
|
724 | 0x00, 0x00, 0x00, 0x00,
|
725 | 0x00, 0x00, 0x00, 0x00
|
726 | ]));
|
727 |
|
728 | upperWordBaseMediaDecodeTime = Math.floor(track.baseMediaDecodeTime / (UINT32_MAX + 1));
|
729 | lowerWordBaseMediaDecodeTime = Math.floor(track.baseMediaDecodeTime % (UINT32_MAX + 1));
|
730 |
|
731 | trackFragmentDecodeTime = box(types.tfdt, new Uint8Array([
|
732 | 0x01,
|
733 | 0x00, 0x00, 0x00,
|
734 |
|
735 | (upperWordBaseMediaDecodeTime >>> 24) & 0xFF,
|
736 | (upperWordBaseMediaDecodeTime >>> 16) & 0xFF,
|
737 | (upperWordBaseMediaDecodeTime >>> 8) & 0xFF,
|
738 | upperWordBaseMediaDecodeTime & 0xFF,
|
739 | (lowerWordBaseMediaDecodeTime >>> 24) & 0xFF,
|
740 | (lowerWordBaseMediaDecodeTime >>> 16) & 0xFF,
|
741 | (lowerWordBaseMediaDecodeTime >>> 8) & 0xFF,
|
742 | lowerWordBaseMediaDecodeTime & 0xFF
|
743 | ]));
|
744 |
|
745 |
|
746 |
|
747 |
|
748 | dataOffset = (32 +
|
749 | 20 +
|
750 | 8 +
|
751 | 16 +
|
752 | 8 +
|
753 | 8);
|
754 |
|
755 |
|
756 | if (track.type === 'audio') {
|
757 | trackFragmentRun = trun(track, dataOffset);
|
758 | return box(types.traf,
|
759 | trackFragmentHeader,
|
760 | trackFragmentDecodeTime,
|
761 | trackFragmentRun);
|
762 | }
|
763 |
|
764 |
|
765 |
|
766 |
|
767 | sampleDependencyTable = sdtp(track);
|
768 | trackFragmentRun = trun(track,
|
769 | sampleDependencyTable.length + dataOffset);
|
770 | return box(types.traf,
|
771 | trackFragmentHeader,
|
772 | trackFragmentDecodeTime,
|
773 | trackFragmentRun,
|
774 | sampleDependencyTable);
|
775 | };
|
776 |
|
777 | |
778 |
|
779 |
|
780 |
|
781 |
|
782 | trak = function(track) {
|
783 | track.duration = track.duration || 0xffffffff;
|
784 | return box(types.trak,
|
785 | tkhd(track),
|
786 | mdia(track));
|
787 | };
|
788 |
|
789 | trex = function(track) {
|
790 | var result = new Uint8Array([
|
791 | 0x00,
|
792 | 0x00, 0x00, 0x00,
|
793 | (track.id & 0xFF000000) >> 24,
|
794 | (track.id & 0xFF0000) >> 16,
|
795 | (track.id & 0xFF00) >> 8,
|
796 | (track.id & 0xFF),
|
797 | 0x00, 0x00, 0x00, 0x01,
|
798 | 0x00, 0x00, 0x00, 0x00,
|
799 | 0x00, 0x00, 0x00, 0x00,
|
800 | 0x00, 0x01, 0x00, 0x01
|
801 | ]);
|
802 |
|
803 |
|
804 |
|
805 |
|
806 | if (track.type !== 'video') {
|
807 | result[result.length - 1] = 0x00;
|
808 | }
|
809 |
|
810 | return box(types.trex, result);
|
811 | };
|
812 |
|
813 | (function() {
|
814 | var audioTrun, videoTrun, trunHeader;
|
815 |
|
816 |
|
817 |
|
818 |
|
819 |
|
820 | trunHeader = function(samples, offset) {
|
821 | var durationPresent = 0, sizePresent = 0,
|
822 | flagsPresent = 0, compositionTimeOffset = 0;
|
823 |
|
824 |
|
825 | if (samples.length) {
|
826 | if (samples[0].duration !== undefined) {
|
827 | durationPresent = 0x1;
|
828 | }
|
829 | if (samples[0].size !== undefined) {
|
830 | sizePresent = 0x2;
|
831 | }
|
832 | if (samples[0].flags !== undefined) {
|
833 | flagsPresent = 0x4;
|
834 | }
|
835 | if (samples[0].compositionTimeOffset !== undefined) {
|
836 | compositionTimeOffset = 0x8;
|
837 | }
|
838 | }
|
839 |
|
840 | return [
|
841 | 0x00,
|
842 | 0x00,
|
843 | durationPresent | sizePresent | flagsPresent | compositionTimeOffset,
|
844 | 0x01,
|
845 | (samples.length & 0xFF000000) >>> 24,
|
846 | (samples.length & 0xFF0000) >>> 16,
|
847 | (samples.length & 0xFF00) >>> 8,
|
848 | samples.length & 0xFF,
|
849 | (offset & 0xFF000000) >>> 24,
|
850 | (offset & 0xFF0000) >>> 16,
|
851 | (offset & 0xFF00) >>> 8,
|
852 | offset & 0xFF
|
853 | ];
|
854 | };
|
855 |
|
856 | videoTrun = function(track, offset) {
|
857 | var bytesOffest, bytes, header, samples, sample, i;
|
858 |
|
859 | samples = track.samples || [];
|
860 | offset += 8 + 12 + (16 * samples.length);
|
861 | header = trunHeader(samples, offset);
|
862 | bytes = new Uint8Array(header.length + samples.length * 16);
|
863 | bytes.set(header);
|
864 | bytesOffest = header.length;
|
865 |
|
866 | for (i = 0; i < samples.length; i++) {
|
867 | sample = samples[i];
|
868 |
|
869 | bytes[bytesOffest++] = (sample.duration & 0xFF000000) >>> 24;
|
870 | bytes[bytesOffest++] = (sample.duration & 0xFF0000) >>> 16;
|
871 | bytes[bytesOffest++] = (sample.duration & 0xFF00) >>> 8;
|
872 | bytes[bytesOffest++] = sample.duration & 0xFF;
|
873 | bytes[bytesOffest++] = (sample.size & 0xFF000000) >>> 24;
|
874 | bytes[bytesOffest++] = (sample.size & 0xFF0000) >>> 16;
|
875 | bytes[bytesOffest++] = (sample.size & 0xFF00) >>> 8;
|
876 | bytes[bytesOffest++] = sample.size & 0xFF;
|
877 | bytes[bytesOffest++] = (sample.flags.isLeading << 2) | sample.flags.dependsOn;
|
878 | bytes[bytesOffest++] = (sample.flags.isDependedOn << 6) |
|
879 | (sample.flags.hasRedundancy << 4) |
|
880 | (sample.flags.paddingValue << 1) |
|
881 | sample.flags.isNonSyncSample;
|
882 | bytes[bytesOffest++] = sample.flags.degradationPriority & 0xF0 << 8;
|
883 | bytes[bytesOffest++] = sample.flags.degradationPriority & 0x0F;
|
884 | bytes[bytesOffest++] = (sample.compositionTimeOffset & 0xFF000000) >>> 24;
|
885 | bytes[bytesOffest++] = (sample.compositionTimeOffset & 0xFF0000) >>> 16;
|
886 | bytes[bytesOffest++] = (sample.compositionTimeOffset & 0xFF00) >>> 8;
|
887 | bytes[bytesOffest++] = sample.compositionTimeOffset & 0xFF;
|
888 | }
|
889 | return box(types.trun, bytes);
|
890 | };
|
891 |
|
892 | audioTrun = function(track, offset) {
|
893 | var bytes, bytesOffest, header, samples, sample, i;
|
894 |
|
895 | samples = track.samples || [];
|
896 | offset += 8 + 12 + (8 * samples.length);
|
897 |
|
898 | header = trunHeader(samples, offset);
|
899 | bytes = new Uint8Array(header.length + samples.length * 8);
|
900 | bytes.set(header);
|
901 | bytesOffest = header.length;
|
902 |
|
903 | for (i = 0; i < samples.length; i++) {
|
904 | sample = samples[i];
|
905 | bytes[bytesOffest++] = (sample.duration & 0xFF000000) >>> 24;
|
906 | bytes[bytesOffest++] = (sample.duration & 0xFF0000) >>> 16;
|
907 | bytes[bytesOffest++] = (sample.duration & 0xFF00) >>> 8;
|
908 | bytes[bytesOffest++] = sample.duration & 0xFF;
|
909 | bytes[bytesOffest++] = (sample.size & 0xFF000000) >>> 24;
|
910 | bytes[bytesOffest++] = (sample.size & 0xFF0000) >>> 16;
|
911 | bytes[bytesOffest++] = (sample.size & 0xFF00) >>> 8;
|
912 | bytes[bytesOffest++] = sample.size & 0xFF;
|
913 | }
|
914 |
|
915 | return box(types.trun, bytes);
|
916 | };
|
917 |
|
918 | trun = function(track, offset) {
|
919 | if (track.type === 'audio') {
|
920 | return audioTrun(track, offset);
|
921 | }
|
922 |
|
923 | return videoTrun(track, offset);
|
924 | };
|
925 | }());
|
926 |
|
927 | var mp4Generator = {
|
928 | ftyp: ftyp,
|
929 | mdat: mdat,
|
930 | moof: moof,
|
931 | moov: moov,
|
932 | initSegment: function(tracks) {
|
933 | var
|
934 | fileType = ftyp(),
|
935 | movie = moov(tracks),
|
936 | result;
|
937 |
|
938 | result = new Uint8Array(fileType.byteLength + movie.byteLength);
|
939 | result.set(fileType);
|
940 | result.set(movie, fileType.byteLength);
|
941 | return result;
|
942 | }
|
943 | };
|
944 |
|
945 | |
946 |
|
947 |
|
948 |
|
949 |
|
950 |
|
951 |
|
952 |
|
953 |
|
954 |
|
955 | var groupNalsIntoFrames = function(nalUnits) {
|
956 | var
|
957 | i,
|
958 | currentNal,
|
959 | currentFrame = [],
|
960 | frames = [];
|
961 |
|
962 |
|
963 | frames.byteLength = 0;
|
964 | frames.nalCount = 0;
|
965 | frames.duration = 0;
|
966 |
|
967 | currentFrame.byteLength = 0;
|
968 |
|
969 | for (i = 0; i < nalUnits.length; i++) {
|
970 | currentNal = nalUnits[i];
|
971 |
|
972 |
|
973 | if (currentNal.nalUnitType === 'access_unit_delimiter_rbsp') {
|
974 |
|
975 |
|
976 | if (currentFrame.length) {
|
977 | currentFrame.duration = currentNal.dts - currentFrame.dts;
|
978 |
|
979 | frames.byteLength += currentFrame.byteLength;
|
980 | frames.nalCount += currentFrame.length;
|
981 | frames.duration += currentFrame.duration;
|
982 | frames.push(currentFrame);
|
983 | }
|
984 | currentFrame = [currentNal];
|
985 | currentFrame.byteLength = currentNal.data.byteLength;
|
986 | currentFrame.pts = currentNal.pts;
|
987 | currentFrame.dts = currentNal.dts;
|
988 | } else {
|
989 |
|
990 | if (currentNal.nalUnitType === 'slice_layer_without_partitioning_rbsp_idr') {
|
991 | currentFrame.keyFrame = true;
|
992 | }
|
993 | currentFrame.duration = currentNal.dts - currentFrame.dts;
|
994 | currentFrame.byteLength += currentNal.data.byteLength;
|
995 | currentFrame.push(currentNal);
|
996 | }
|
997 | }
|
998 |
|
999 |
|
1000 |
|
1001 | if (frames.length &&
|
1002 | (!currentFrame.duration ||
|
1003 | currentFrame.duration <= 0)) {
|
1004 | currentFrame.duration = frames[frames.length - 1].duration;
|
1005 | }
|
1006 |
|
1007 |
|
1008 |
|
1009 | frames.byteLength += currentFrame.byteLength;
|
1010 | frames.nalCount += currentFrame.length;
|
1011 | frames.duration += currentFrame.duration;
|
1012 |
|
1013 | frames.push(currentFrame);
|
1014 | return frames;
|
1015 | };
|
1016 |
|
1017 |
|
1018 |
|
1019 |
|
1020 |
|
1021 | var groupFramesIntoGops = function(frames) {
|
1022 | var
|
1023 | i,
|
1024 | currentFrame,
|
1025 | currentGop = [],
|
1026 | gops = [];
|
1027 |
|
1028 |
|
1029 |
|
1030 | currentGop.byteLength = 0;
|
1031 | currentGop.nalCount = 0;
|
1032 | currentGop.duration = 0;
|
1033 | currentGop.pts = frames[0].pts;
|
1034 | currentGop.dts = frames[0].dts;
|
1035 |
|
1036 |
|
1037 | gops.byteLength = 0;
|
1038 | gops.nalCount = 0;
|
1039 | gops.duration = 0;
|
1040 | gops.pts = frames[0].pts;
|
1041 | gops.dts = frames[0].dts;
|
1042 |
|
1043 | for (i = 0; i < frames.length; i++) {
|
1044 | currentFrame = frames[i];
|
1045 |
|
1046 | if (currentFrame.keyFrame) {
|
1047 |
|
1048 |
|
1049 | if (currentGop.length) {
|
1050 | gops.push(currentGop);
|
1051 | gops.byteLength += currentGop.byteLength;
|
1052 | gops.nalCount += currentGop.nalCount;
|
1053 | gops.duration += currentGop.duration;
|
1054 | }
|
1055 |
|
1056 | currentGop = [currentFrame];
|
1057 | currentGop.nalCount = currentFrame.length;
|
1058 | currentGop.byteLength = currentFrame.byteLength;
|
1059 | currentGop.pts = currentFrame.pts;
|
1060 | currentGop.dts = currentFrame.dts;
|
1061 | currentGop.duration = currentFrame.duration;
|
1062 | } else {
|
1063 | currentGop.duration += currentFrame.duration;
|
1064 | currentGop.nalCount += currentFrame.length;
|
1065 | currentGop.byteLength += currentFrame.byteLength;
|
1066 | currentGop.push(currentFrame);
|
1067 | }
|
1068 | }
|
1069 |
|
1070 | if (gops.length && currentGop.duration <= 0) {
|
1071 | currentGop.duration = gops[gops.length - 1].duration;
|
1072 | }
|
1073 | gops.byteLength += currentGop.byteLength;
|
1074 | gops.nalCount += currentGop.nalCount;
|
1075 | gops.duration += currentGop.duration;
|
1076 |
|
1077 |
|
1078 | gops.push(currentGop);
|
1079 | return gops;
|
1080 | };
|
1081 |
|
1082 | |
1083 |
|
1084 |
|
1085 |
|
1086 |
|
1087 |
|
1088 |
|
1089 |
|
1090 |
|
1091 | var extendFirstKeyFrame = function(gops) {
|
1092 | var currentGop;
|
1093 |
|
1094 | if (!gops[0][0].keyFrame && gops.length > 1) {
|
1095 |
|
1096 | currentGop = gops.shift();
|
1097 |
|
1098 | gops.byteLength -= currentGop.byteLength;
|
1099 | gops.nalCount -= currentGop.nalCount;
|
1100 |
|
1101 |
|
1102 |
|
1103 |
|
1104 | gops[0][0].dts = currentGop.dts;
|
1105 | gops[0][0].pts = currentGop.pts;
|
1106 | gops[0][0].duration += currentGop.duration;
|
1107 | }
|
1108 |
|
1109 | return gops;
|
1110 | };
|
1111 |
|
1112 | |
1113 |
|
1114 |
|
1115 |
|
1116 | var createDefaultSample = function() {
|
1117 | return {
|
1118 | size: 0,
|
1119 | flags: {
|
1120 | isLeading: 0,
|
1121 | dependsOn: 1,
|
1122 | isDependedOn: 0,
|
1123 | hasRedundancy: 0,
|
1124 | degradationPriority: 0,
|
1125 | isNonSyncSample: 1
|
1126 | }
|
1127 | };
|
1128 | };
|
1129 |
|
1130 | |
1131 |
|
1132 |
|
1133 |
|
1134 |
|
1135 |
|
1136 |
|
1137 |
|
1138 | var sampleForFrame = function(frame, dataOffset) {
|
1139 | var sample = createDefaultSample();
|
1140 |
|
1141 | sample.dataOffset = dataOffset;
|
1142 | sample.compositionTimeOffset = frame.pts - frame.dts;
|
1143 | sample.duration = frame.duration;
|
1144 | sample.size = 4 * frame.length;
|
1145 | sample.size += frame.byteLength;
|
1146 |
|
1147 | if (frame.keyFrame) {
|
1148 | sample.flags.dependsOn = 2;
|
1149 | sample.flags.isNonSyncSample = 0;
|
1150 | }
|
1151 |
|
1152 | return sample;
|
1153 | };
|
1154 |
|
1155 |
|
1156 | var generateSampleTable = function(gops, baseDataOffset) {
|
1157 | var
|
1158 | h, i,
|
1159 | sample,
|
1160 | currentGop,
|
1161 | currentFrame,
|
1162 | dataOffset = baseDataOffset || 0,
|
1163 | samples = [];
|
1164 |
|
1165 | for (h = 0; h < gops.length; h++) {
|
1166 | currentGop = gops[h];
|
1167 |
|
1168 | for (i = 0; i < currentGop.length; i++) {
|
1169 | currentFrame = currentGop[i];
|
1170 |
|
1171 | sample = sampleForFrame(currentFrame, dataOffset);
|
1172 |
|
1173 | dataOffset += sample.size;
|
1174 |
|
1175 | samples.push(sample);
|
1176 | }
|
1177 | }
|
1178 | return samples;
|
1179 | };
|
1180 |
|
1181 |
|
1182 | var concatenateNalData = function(gops) {
|
1183 | var
|
1184 | h, i, j,
|
1185 | currentGop,
|
1186 | currentFrame,
|
1187 | currentNal,
|
1188 | dataOffset = 0,
|
1189 | nalsByteLength = gops.byteLength,
|
1190 | numberOfNals = gops.nalCount,
|
1191 | totalByteLength = nalsByteLength + 4 * numberOfNals,
|
1192 | data = new Uint8Array(totalByteLength),
|
1193 | view = new DataView(data.buffer);
|
1194 |
|
1195 |
|
1196 | for (h = 0; h < gops.length; h++) {
|
1197 | currentGop = gops[h];
|
1198 |
|
1199 |
|
1200 | for (i = 0; i < currentGop.length; i++) {
|
1201 | currentFrame = currentGop[i];
|
1202 |
|
1203 |
|
1204 | for (j = 0; j < currentFrame.length; j++) {
|
1205 | currentNal = currentFrame[j];
|
1206 |
|
1207 | view.setUint32(dataOffset, currentNal.data.byteLength);
|
1208 | dataOffset += 4;
|
1209 | data.set(currentNal.data, dataOffset);
|
1210 | dataOffset += currentNal.data.byteLength;
|
1211 | }
|
1212 | }
|
1213 | }
|
1214 | return data;
|
1215 | };
|
1216 |
|
1217 |
|
1218 | var generateSampleTableForFrame = function(frame, baseDataOffset) {
|
1219 | var
|
1220 | sample,
|
1221 | dataOffset = baseDataOffset || 0,
|
1222 | samples = [];
|
1223 |
|
1224 | sample = sampleForFrame(frame, dataOffset);
|
1225 | samples.push(sample);
|
1226 |
|
1227 | return samples;
|
1228 | };
|
1229 |
|
1230 |
|
1231 | var concatenateNalDataForFrame = function(frame) {
|
1232 | var
|
1233 | i,
|
1234 | currentNal,
|
1235 | dataOffset = 0,
|
1236 | nalsByteLength = frame.byteLength,
|
1237 | numberOfNals = frame.length,
|
1238 | totalByteLength = nalsByteLength + 4 * numberOfNals,
|
1239 | data = new Uint8Array(totalByteLength),
|
1240 | view = new DataView(data.buffer);
|
1241 |
|
1242 |
|
1243 | for (i = 0; i < frame.length; i++) {
|
1244 | currentNal = frame[i];
|
1245 |
|
1246 | view.setUint32(dataOffset, currentNal.data.byteLength);
|
1247 | dataOffset += 4;
|
1248 | data.set(currentNal.data, dataOffset);
|
1249 | dataOffset += currentNal.data.byteLength;
|
1250 | }
|
1251 |
|
1252 | return data;
|
1253 | };
|
1254 |
|
1255 | var frameUtils = {
|
1256 | groupNalsIntoFrames: groupNalsIntoFrames,
|
1257 | groupFramesIntoGops: groupFramesIntoGops,
|
1258 | extendFirstKeyFrame: extendFirstKeyFrame,
|
1259 | generateSampleTable: generateSampleTable,
|
1260 | concatenateNalData: concatenateNalData,
|
1261 | generateSampleTableForFrame: generateSampleTableForFrame,
|
1262 | concatenateNalDataForFrame: concatenateNalDataForFrame
|
1263 | };
|
1264 |
|
1265 | |
1266 |
|
1267 |
|
1268 |
|
1269 |
|
1270 |
|
1271 | var highPrefix = [33, 16, 5, 32, 164, 27];
|
1272 | var lowPrefix = [33, 65, 108, 84, 1, 2, 4, 8, 168, 2, 4, 8, 17, 191, 252];
|
1273 | var zeroFill = function(count) {
|
1274 | var a = [];
|
1275 | while (count--) {
|
1276 | a.push(0);
|
1277 | }
|
1278 | return a;
|
1279 | };
|
1280 |
|
1281 | var makeTable = function(metaTable) {
|
1282 | return Object.keys(metaTable).reduce(function(obj, key) {
|
1283 | obj[key] = new Uint8Array(metaTable[key].reduce(function(arr, part) {
|
1284 | return arr.concat(part);
|
1285 | }, []));
|
1286 | return obj;
|
1287 | }, {});
|
1288 | };
|
1289 |
|
1290 |
|
1291 | var silence;
|
1292 |
|
1293 | var silence_1 = function() {
|
1294 | if (!silence) {
|
1295 |
|
1296 | var coneOfSilence = {
|
1297 | 96000: [highPrefix, [227, 64], zeroFill(154), [56]],
|
1298 | 88200: [highPrefix, [231], zeroFill(170), [56]],
|
1299 | 64000: [highPrefix, [248, 192], zeroFill(240), [56]],
|
1300 | 48000: [highPrefix, [255, 192], zeroFill(268), [55, 148, 128], zeroFill(54), [112]],
|
1301 | 44100: [highPrefix, [255, 192], zeroFill(268), [55, 163, 128], zeroFill(84), [112]],
|
1302 | 32000: [highPrefix, [255, 192], zeroFill(268), [55, 234], zeroFill(226), [112]],
|
1303 | 24000: [highPrefix, [255, 192], zeroFill(268), [55, 255, 128], zeroFill(268), [111, 112], zeroFill(126), [224]],
|
1304 | 16000: [highPrefix, [255, 192], zeroFill(268), [55, 255, 128], zeroFill(268), [111, 255], zeroFill(269), [223, 108], zeroFill(195), [1, 192]],
|
1305 | 12000: [lowPrefix, zeroFill(268), [3, 127, 248], zeroFill(268), [6, 255, 240], zeroFill(268), [13, 255, 224], zeroFill(268), [27, 253, 128], zeroFill(259), [56]],
|
1306 | 11025: [lowPrefix, zeroFill(268), [3, 127, 248], zeroFill(268), [6, 255, 240], zeroFill(268), [13, 255, 224], zeroFill(268), [27, 255, 192], zeroFill(268), [55, 175, 128], zeroFill(108), [112]],
|
1307 | 8000: [lowPrefix, zeroFill(268), [3, 121, 16], zeroFill(47), [7]]
|
1308 | };
|
1309 | silence = makeTable(coneOfSilence);
|
1310 | }
|
1311 | return silence;
|
1312 | };
|
1313 |
|
1314 | |
1315 |
|
1316 |
|
1317 |
|
1318 |
|
1319 |
|
1320 | var
|
1321 | ONE_SECOND_IN_TS = 90000,
|
1322 | secondsToVideoTs,
|
1323 | secondsToAudioTs,
|
1324 | videoTsToSeconds,
|
1325 | audioTsToSeconds,
|
1326 | audioTsToVideoTs,
|
1327 | videoTsToAudioTs,
|
1328 | metadataTsToSeconds;
|
1329 |
|
1330 | secondsToVideoTs = function(seconds) {
|
1331 | return seconds * ONE_SECOND_IN_TS;
|
1332 | };
|
1333 |
|
1334 | secondsToAudioTs = function(seconds, sampleRate) {
|
1335 | return seconds * sampleRate;
|
1336 | };
|
1337 |
|
1338 | videoTsToSeconds = function(timestamp) {
|
1339 | return timestamp / ONE_SECOND_IN_TS;
|
1340 | };
|
1341 |
|
1342 | audioTsToSeconds = function(timestamp, sampleRate) {
|
1343 | return timestamp / sampleRate;
|
1344 | };
|
1345 |
|
1346 | audioTsToVideoTs = function(timestamp, sampleRate) {
|
1347 | return secondsToVideoTs(audioTsToSeconds(timestamp, sampleRate));
|
1348 | };
|
1349 |
|
1350 | videoTsToAudioTs = function(timestamp, sampleRate) {
|
1351 | return secondsToAudioTs(videoTsToSeconds(timestamp), sampleRate);
|
1352 | };
|
1353 |
|
1354 | |
1355 |
|
1356 |
|
1357 |
|
1358 | metadataTsToSeconds = function(timestamp, timelineStartPts, keepOriginalTimestamps) {
|
1359 | return videoTsToSeconds(keepOriginalTimestamps ? timestamp : timestamp - timelineStartPts);
|
1360 | };
|
1361 |
|
1362 | var clock = {
|
1363 | ONE_SECOND_IN_TS: ONE_SECOND_IN_TS,
|
1364 | secondsToVideoTs: secondsToVideoTs,
|
1365 | secondsToAudioTs: secondsToAudioTs,
|
1366 | videoTsToSeconds: videoTsToSeconds,
|
1367 | audioTsToSeconds: audioTsToSeconds,
|
1368 | audioTsToVideoTs: audioTsToVideoTs,
|
1369 | videoTsToAudioTs: videoTsToAudioTs,
|
1370 | metadataTsToSeconds: metadataTsToSeconds
|
1371 | };
|
1372 | var clock_2 = clock.secondsToVideoTs;
|
1373 | var clock_4 = clock.videoTsToSeconds;
|
1374 |
|
1375 | |
1376 |
|
1377 |
|
1378 |
|
1379 |
|
1380 |
|
1381 |
|
1382 |
|
1383 |
|
1384 | |
1385 |
|
1386 |
|
1387 | var sumFrameByteLengths = function(array) {
|
1388 | var
|
1389 | i,
|
1390 | currentObj,
|
1391 | sum = 0;
|
1392 |
|
1393 |
|
1394 | for (i = 0; i < array.length; i++) {
|
1395 | currentObj = array[i];
|
1396 | sum += currentObj.data.byteLength;
|
1397 | }
|
1398 |
|
1399 | return sum;
|
1400 | };
|
1401 |
|
1402 |
|
1403 |
|
1404 | var prefixWithSilence = function(
|
1405 | track,
|
1406 | frames,
|
1407 | audioAppendStartTs,
|
1408 | videoBaseMediaDecodeTime
|
1409 | ) {
|
1410 | var
|
1411 | baseMediaDecodeTimeTs,
|
1412 | frameDuration = 0,
|
1413 | audioGapDuration = 0,
|
1414 | audioFillFrameCount = 0,
|
1415 | audioFillDuration = 0,
|
1416 | silentFrame,
|
1417 | i,
|
1418 | firstFrame;
|
1419 |
|
1420 | if (!frames.length) {
|
1421 | return;
|
1422 | }
|
1423 |
|
1424 | baseMediaDecodeTimeTs =
|
1425 | clock.audioTsToVideoTs(track.baseMediaDecodeTime, track.samplerate);
|
1426 |
|
1427 | frameDuration = Math.ceil(clock.ONE_SECOND_IN_TS / (track.samplerate / 1024));
|
1428 |
|
1429 | if (audioAppendStartTs && videoBaseMediaDecodeTime) {
|
1430 |
|
1431 | audioGapDuration =
|
1432 | baseMediaDecodeTimeTs - Math.max(audioAppendStartTs, videoBaseMediaDecodeTime);
|
1433 |
|
1434 | audioFillFrameCount = Math.floor(audioGapDuration / frameDuration);
|
1435 | audioFillDuration = audioFillFrameCount * frameDuration;
|
1436 | }
|
1437 |
|
1438 |
|
1439 |
|
1440 | if (audioFillFrameCount < 1 || audioFillDuration > clock.ONE_SECOND_IN_TS / 2) {
|
1441 | return;
|
1442 | }
|
1443 |
|
1444 | silentFrame = silence_1()[track.samplerate];
|
1445 |
|
1446 | if (!silentFrame) {
|
1447 |
|
1448 |
|
1449 | silentFrame = frames[0].data;
|
1450 | }
|
1451 |
|
1452 | for (i = 0; i < audioFillFrameCount; i++) {
|
1453 | firstFrame = frames[0];
|
1454 |
|
1455 | frames.splice(0, 0, {
|
1456 | data: silentFrame,
|
1457 | dts: firstFrame.dts - frameDuration,
|
1458 | pts: firstFrame.pts - frameDuration
|
1459 | });
|
1460 | }
|
1461 |
|
1462 | track.baseMediaDecodeTime -=
|
1463 | Math.floor(clock.videoTsToAudioTs(audioFillDuration, track.samplerate));
|
1464 | };
|
1465 |
|
1466 |
|
1467 |
|
1468 |
|
1469 |
|
1470 | var trimAdtsFramesByEarliestDts = function(adtsFrames, track, earliestAllowedDts) {
|
1471 | if (track.minSegmentDts >= earliestAllowedDts) {
|
1472 | return adtsFrames;
|
1473 | }
|
1474 |
|
1475 |
|
1476 | track.minSegmentDts = Infinity;
|
1477 |
|
1478 | return adtsFrames.filter(function(currentFrame) {
|
1479 |
|
1480 | if (currentFrame.dts >= earliestAllowedDts) {
|
1481 | track.minSegmentDts = Math.min(track.minSegmentDts, currentFrame.dts);
|
1482 | track.minSegmentPts = track.minSegmentDts;
|
1483 | return true;
|
1484 | }
|
1485 |
|
1486 | return false;
|
1487 | });
|
1488 | };
|
1489 |
|
1490 |
|
1491 | var generateSampleTable$1 = function(frames) {
|
1492 | var
|
1493 | i,
|
1494 | currentFrame,
|
1495 | samples = [];
|
1496 |
|
1497 | for (i = 0; i < frames.length; i++) {
|
1498 | currentFrame = frames[i];
|
1499 | samples.push({
|
1500 | size: currentFrame.data.byteLength,
|
1501 | duration: 1024
|
1502 | });
|
1503 | }
|
1504 | return samples;
|
1505 | };
|
1506 |
|
1507 |
|
1508 | var concatenateFrameData = function(frames) {
|
1509 | var
|
1510 | i,
|
1511 | currentFrame,
|
1512 | dataOffset = 0,
|
1513 | data = new Uint8Array(sumFrameByteLengths(frames));
|
1514 |
|
1515 | for (i = 0; i < frames.length; i++) {
|
1516 | currentFrame = frames[i];
|
1517 |
|
1518 | data.set(currentFrame.data, dataOffset);
|
1519 | dataOffset += currentFrame.data.byteLength;
|
1520 | }
|
1521 | return data;
|
1522 | };
|
1523 |
|
1524 | var audioFrameUtils = {
|
1525 | prefixWithSilence: prefixWithSilence,
|
1526 | trimAdtsFramesByEarliestDts: trimAdtsFramesByEarliestDts,
|
1527 | generateSampleTable: generateSampleTable$1,
|
1528 | concatenateFrameData: concatenateFrameData
|
1529 | };
|
1530 |
|
1531 | |
1532 |
|
1533 |
|
1534 |
|
1535 |
|
1536 |
|
1537 | var ONE_SECOND_IN_TS$1 = clock.ONE_SECOND_IN_TS;
|
1538 |
|
1539 | |
1540 |
|
1541 |
|
1542 |
|
1543 |
|
1544 | var collectDtsInfo = function(track, data) {
|
1545 | if (typeof data.pts === 'number') {
|
1546 | if (track.timelineStartInfo.pts === undefined) {
|
1547 | track.timelineStartInfo.pts = data.pts;
|
1548 | }
|
1549 |
|
1550 | if (track.minSegmentPts === undefined) {
|
1551 | track.minSegmentPts = data.pts;
|
1552 | } else {
|
1553 | track.minSegmentPts = Math.min(track.minSegmentPts, data.pts);
|
1554 | }
|
1555 |
|
1556 | if (track.maxSegmentPts === undefined) {
|
1557 | track.maxSegmentPts = data.pts;
|
1558 | } else {
|
1559 | track.maxSegmentPts = Math.max(track.maxSegmentPts, data.pts);
|
1560 | }
|
1561 | }
|
1562 |
|
1563 | if (typeof data.dts === 'number') {
|
1564 | if (track.timelineStartInfo.dts === undefined) {
|
1565 | track.timelineStartInfo.dts = data.dts;
|
1566 | }
|
1567 |
|
1568 | if (track.minSegmentDts === undefined) {
|
1569 | track.minSegmentDts = data.dts;
|
1570 | } else {
|
1571 | track.minSegmentDts = Math.min(track.minSegmentDts, data.dts);
|
1572 | }
|
1573 |
|
1574 | if (track.maxSegmentDts === undefined) {
|
1575 | track.maxSegmentDts = data.dts;
|
1576 | } else {
|
1577 | track.maxSegmentDts = Math.max(track.maxSegmentDts, data.dts);
|
1578 | }
|
1579 | }
|
1580 | };
|
1581 |
|
1582 | |
1583 |
|
1584 |
|
1585 |
|
1586 | var clearDtsInfo = function(track) {
|
1587 | delete track.minSegmentDts;
|
1588 | delete track.maxSegmentDts;
|
1589 | delete track.minSegmentPts;
|
1590 | delete track.maxSegmentPts;
|
1591 | };
|
1592 |
|
1593 | |
1594 |
|
1595 |
|
1596 |
|
1597 |
|
1598 |
|
1599 |
|
1600 |
|
1601 | var calculateTrackBaseMediaDecodeTime = function(track, keepOriginalTimestamps) {
|
1602 | var
|
1603 | baseMediaDecodeTime,
|
1604 | scale,
|
1605 | minSegmentDts = track.minSegmentDts;
|
1606 |
|
1607 |
|
1608 | if (!keepOriginalTimestamps) {
|
1609 | minSegmentDts -= track.timelineStartInfo.dts;
|
1610 | }
|
1611 |
|
1612 |
|
1613 |
|
1614 | baseMediaDecodeTime = track.timelineStartInfo.baseMediaDecodeTime;
|
1615 |
|
1616 |
|
1617 | baseMediaDecodeTime += minSegmentDts;
|
1618 |
|
1619 |
|
1620 | baseMediaDecodeTime = Math.max(0, baseMediaDecodeTime);
|
1621 |
|
1622 | if (track.type === 'audio') {
|
1623 |
|
1624 |
|
1625 | scale = track.samplerate / ONE_SECOND_IN_TS$1;
|
1626 | baseMediaDecodeTime *= scale;
|
1627 | baseMediaDecodeTime = Math.floor(baseMediaDecodeTime);
|
1628 | }
|
1629 |
|
1630 | return baseMediaDecodeTime;
|
1631 | };
|
1632 |
|
1633 | var trackDecodeInfo = {
|
1634 | clearDtsInfo: clearDtsInfo,
|
1635 | calculateTrackBaseMediaDecodeTime: calculateTrackBaseMediaDecodeTime,
|
1636 | collectDtsInfo: collectDtsInfo
|
1637 | };
|
1638 |
|
1639 | |
1640 |
|
1641 |
|
1642 |
|
1643 |
|
1644 |
|
1645 |
|
1646 |
|
1647 |
|
1648 |
|
1649 |
|
1650 |
|
1651 |
|
1652 |
|
1653 |
|
1654 |
|
1655 |
|
1656 | var USER_DATA_REGISTERED_ITU_T_T35 = 4,
|
1657 | RBSP_TRAILING_BITS = 128;
|
1658 |
|
1659 | |
1660 |
|
1661 |
|
1662 |
|
1663 |
|
1664 |
|
1665 |
|
1666 |
|
1667 | var parseSei = function(bytes) {
|
1668 | var
|
1669 | i = 0,
|
1670 | result = {
|
1671 | payloadType: -1,
|
1672 | payloadSize: 0
|
1673 | },
|
1674 | payloadType = 0,
|
1675 | payloadSize = 0;
|
1676 |
|
1677 |
|
1678 | while (i < bytes.byteLength) {
|
1679 |
|
1680 | if (bytes[i] === RBSP_TRAILING_BITS) {
|
1681 | break;
|
1682 | }
|
1683 |
|
1684 |
|
1685 | while (bytes[i] === 0xFF) {
|
1686 | payloadType += 255;
|
1687 | i++;
|
1688 | }
|
1689 | payloadType += bytes[i++];
|
1690 |
|
1691 |
|
1692 | while (bytes[i] === 0xFF) {
|
1693 | payloadSize += 255;
|
1694 | i++;
|
1695 | }
|
1696 | payloadSize += bytes[i++];
|
1697 |
|
1698 |
|
1699 |
|
1700 | if (!result.payload && payloadType === USER_DATA_REGISTERED_ITU_T_T35) {
|
1701 | var userIdentifier = String.fromCharCode(
|
1702 | bytes[i + 3],
|
1703 | bytes[i + 4],
|
1704 | bytes[i + 5],
|
1705 | bytes[i + 6]);
|
1706 |
|
1707 | if (userIdentifier === 'GA94') {
|
1708 | result.payloadType = payloadType;
|
1709 | result.payloadSize = payloadSize;
|
1710 | result.payload = bytes.subarray(i, i + payloadSize);
|
1711 | break;
|
1712 | } else {
|
1713 | result.payload = void 0;
|
1714 | }
|
1715 | }
|
1716 |
|
1717 |
|
1718 | i += payloadSize;
|
1719 | payloadType = 0;
|
1720 | payloadSize = 0;
|
1721 | }
|
1722 |
|
1723 | return result;
|
1724 | };
|
1725 |
|
1726 |
|
1727 | var parseUserData = function(sei) {
|
1728 |
|
1729 |
|
1730 | if (sei.payload[0] !== 181) {
|
1731 | return null;
|
1732 | }
|
1733 |
|
1734 |
|
1735 | if (((sei.payload[1] << 8) | sei.payload[2]) !== 49) {
|
1736 | return null;
|
1737 | }
|
1738 |
|
1739 |
|
1740 | if (String.fromCharCode(sei.payload[3],
|
1741 | sei.payload[4],
|
1742 | sei.payload[5],
|
1743 | sei.payload[6]) !== 'GA94') {
|
1744 | return null;
|
1745 | }
|
1746 |
|
1747 |
|
1748 | if (sei.payload[7] !== 0x03) {
|
1749 | return null;
|
1750 | }
|
1751 |
|
1752 |
|
1753 |
|
1754 | return sei.payload.subarray(8, sei.payload.length - 1);
|
1755 | };
|
1756 |
|
1757 |
|
1758 | var parseCaptionPackets = function(pts, userData) {
|
1759 | var results = [], i, count, offset, data;
|
1760 |
|
1761 |
|
1762 | if (!(userData[0] & 0x40)) {
|
1763 | return results;
|
1764 | }
|
1765 |
|
1766 |
|
1767 | count = userData[0] & 0x1f;
|
1768 | for (i = 0; i < count; i++) {
|
1769 | offset = i * 3;
|
1770 | data = {
|
1771 | type: userData[offset + 2] & 0x03,
|
1772 | pts: pts
|
1773 | };
|
1774 |
|
1775 |
|
1776 | if (userData[offset + 2] & 0x04) {
|
1777 | data.ccData = (userData[offset + 3] << 8) | userData[offset + 4];
|
1778 | results.push(data);
|
1779 | }
|
1780 | }
|
1781 | return results;
|
1782 | };
|
1783 |
|
1784 | var discardEmulationPreventionBytes = function(data) {
|
1785 | var
|
1786 | length = data.byteLength,
|
1787 | emulationPreventionBytesPositions = [],
|
1788 | i = 1,
|
1789 | newLength, newData;
|
1790 |
|
1791 |
|
1792 | while (i < length - 2) {
|
1793 | if (data[i] === 0 && data[i + 1] === 0 && data[i + 2] === 0x03) {
|
1794 | emulationPreventionBytesPositions.push(i + 2);
|
1795 | i += 2;
|
1796 | } else {
|
1797 | i++;
|
1798 | }
|
1799 | }
|
1800 |
|
1801 |
|
1802 |
|
1803 | if (emulationPreventionBytesPositions.length === 0) {
|
1804 | return data;
|
1805 | }
|
1806 |
|
1807 |
|
1808 | newLength = length - emulationPreventionBytesPositions.length;
|
1809 | newData = new Uint8Array(newLength);
|
1810 | var sourceIndex = 0;
|
1811 |
|
1812 | for (i = 0; i < newLength; sourceIndex++, i++) {
|
1813 | if (sourceIndex === emulationPreventionBytesPositions[0]) {
|
1814 |
|
1815 | sourceIndex++;
|
1816 |
|
1817 | emulationPreventionBytesPositions.shift();
|
1818 | }
|
1819 | newData[i] = data[sourceIndex];
|
1820 | }
|
1821 |
|
1822 | return newData;
|
1823 | };
|
1824 |
|
1825 |
|
1826 | var captionPacketParser = {
|
1827 | parseSei: parseSei,
|
1828 | parseUserData: parseUserData,
|
1829 | parseCaptionPackets: parseCaptionPackets,
|
1830 | discardEmulationPreventionBytes: discardEmulationPreventionBytes,
|
1831 | USER_DATA_REGISTERED_ITU_T_T35: USER_DATA_REGISTERED_ITU_T_T35
|
1832 | };
|
1833 |
|
1834 |
|
1835 |
|
1836 |
|
1837 |
|
1838 |
|
1839 |
|
1840 |
|
1841 | var CaptionStream = function() {
|
1842 |
|
1843 | CaptionStream.prototype.init.call(this);
|
1844 |
|
1845 | this.captionPackets_ = [];
|
1846 |
|
1847 | this.ccStreams_ = [
|
1848 | new Cea608Stream(0, 0),
|
1849 | new Cea608Stream(0, 1),
|
1850 | new Cea608Stream(1, 0),
|
1851 | new Cea608Stream(1, 1)
|
1852 | ];
|
1853 |
|
1854 | this.reset();
|
1855 |
|
1856 |
|
1857 | this.ccStreams_.forEach(function(cc) {
|
1858 | cc.on('data', this.trigger.bind(this, 'data'));
|
1859 | cc.on('partialdone', this.trigger.bind(this, 'partialdone'));
|
1860 | cc.on('done', this.trigger.bind(this, 'done'));
|
1861 | }, this);
|
1862 |
|
1863 | };
|
1864 |
|
1865 | CaptionStream.prototype = new stream();
|
1866 | CaptionStream.prototype.push = function(event) {
|
1867 | var sei, userData, newCaptionPackets;
|
1868 |
|
1869 |
|
1870 | if (event.nalUnitType !== 'sei_rbsp') {
|
1871 | return;
|
1872 | }
|
1873 |
|
1874 |
|
1875 | sei = captionPacketParser.parseSei(event.escapedRBSP);
|
1876 |
|
1877 |
|
1878 | if (sei.payloadType !== captionPacketParser.USER_DATA_REGISTERED_ITU_T_T35) {
|
1879 | return;
|
1880 | }
|
1881 |
|
1882 |
|
1883 | userData = captionPacketParser.parseUserData(sei);
|
1884 |
|
1885 |
|
1886 | if (!userData) {
|
1887 | return;
|
1888 | }
|
1889 |
|
1890 |
|
1891 |
|
1892 |
|
1893 |
|
1894 |
|
1895 |
|
1896 |
|
1897 |
|
1898 | if (event.dts < this.latestDts_) {
|
1899 |
|
1900 | this.ignoreNextEqualDts_ = true;
|
1901 | return;
|
1902 | } else if ((event.dts === this.latestDts_) && (this.ignoreNextEqualDts_)) {
|
1903 | this.numSameDts_--;
|
1904 | if (!this.numSameDts_) {
|
1905 |
|
1906 | this.ignoreNextEqualDts_ = false;
|
1907 | }
|
1908 | return;
|
1909 | }
|
1910 |
|
1911 |
|
1912 | newCaptionPackets = captionPacketParser.parseCaptionPackets(event.pts, userData);
|
1913 | this.captionPackets_ = this.captionPackets_.concat(newCaptionPackets);
|
1914 | if (this.latestDts_ !== event.dts) {
|
1915 | this.numSameDts_ = 0;
|
1916 | }
|
1917 | this.numSameDts_++;
|
1918 | this.latestDts_ = event.dts;
|
1919 | };
|
1920 |
|
1921 | CaptionStream.prototype.flushCCStreams = function(flushType) {
|
1922 | this.ccStreams_.forEach(function(cc) {
|
1923 | return flushType === 'flush' ? cc.flush() : cc.partialFlush();
|
1924 | }, this);
|
1925 | };
|
1926 |
|
1927 | CaptionStream.prototype.flushStream = function(flushType) {
|
1928 |
|
1929 | if (!this.captionPackets_.length) {
|
1930 | this.flushCCStreams(flushType);
|
1931 | return;
|
1932 | }
|
1933 |
|
1934 |
|
1935 |
|
1936 | this.captionPackets_.forEach(function(elem, idx) {
|
1937 | elem.presortIndex = idx;
|
1938 | });
|
1939 |
|
1940 |
|
1941 | this.captionPackets_.sort(function(a, b) {
|
1942 | if (a.pts === b.pts) {
|
1943 | return a.presortIndex - b.presortIndex;
|
1944 | }
|
1945 | return a.pts - b.pts;
|
1946 | });
|
1947 |
|
1948 | this.captionPackets_.forEach(function(packet) {
|
1949 | if (packet.type < 2) {
|
1950 |
|
1951 | this.dispatchCea608Packet(packet);
|
1952 | }
|
1953 |
|
1954 |
|
1955 | }, this);
|
1956 |
|
1957 | this.captionPackets_.length = 0;
|
1958 | this.flushCCStreams(flushType);
|
1959 | };
|
1960 |
|
1961 | CaptionStream.prototype.flush = function() {
|
1962 | return this.flushStream('flush');
|
1963 | };
|
1964 |
|
1965 |
|
1966 | CaptionStream.prototype.partialFlush = function() {
|
1967 | return this.flushStream('partialFlush');
|
1968 | };
|
1969 |
|
1970 | CaptionStream.prototype.reset = function() {
|
1971 | this.latestDts_ = null;
|
1972 | this.ignoreNextEqualDts_ = false;
|
1973 | this.numSameDts_ = 0;
|
1974 | this.activeCea608Channel_ = [null, null];
|
1975 | this.ccStreams_.forEach(function(ccStream) {
|
1976 | ccStream.reset();
|
1977 | });
|
1978 | };
|
1979 |
|
1980 |
|
1981 | |
1982 |
|
1983 |
|
1984 |
|
1985 |
|
1986 |
|
1987 |
|
1988 |
|
1989 |
|
1990 |
|
1991 | CaptionStream.prototype.dispatchCea608Packet = function(packet) {
|
1992 |
|
1993 | if (this.setsTextOrXDSActive(packet)) {
|
1994 | this.activeCea608Channel_[packet.type] = null;
|
1995 | } else if (this.setsChannel1Active(packet)) {
|
1996 | this.activeCea608Channel_[packet.type] = 0;
|
1997 | } else if (this.setsChannel2Active(packet)) {
|
1998 | this.activeCea608Channel_[packet.type] = 1;
|
1999 | }
|
2000 | if (this.activeCea608Channel_[packet.type] === null) {
|
2001 |
|
2002 |
|
2003 |
|
2004 | return;
|
2005 | }
|
2006 | this.ccStreams_[(packet.type << 1) + this.activeCea608Channel_[packet.type]].push(packet);
|
2007 | };
|
2008 |
|
2009 | CaptionStream.prototype.setsChannel1Active = function(packet) {
|
2010 | return ((packet.ccData & 0x7800) === 0x1000);
|
2011 | };
|
2012 | CaptionStream.prototype.setsChannel2Active = function(packet) {
|
2013 | return ((packet.ccData & 0x7800) === 0x1800);
|
2014 | };
|
2015 | CaptionStream.prototype.setsTextOrXDSActive = function(packet) {
|
2016 | return ((packet.ccData & 0x7100) === 0x0100) ||
|
2017 | ((packet.ccData & 0x78fe) === 0x102a) ||
|
2018 | ((packet.ccData & 0x78fe) === 0x182a);
|
2019 | };
|
2020 |
|
2021 |
|
2022 |
|
2023 |
|
2024 |
|
2025 |
|
2026 |
|
2027 |
|
2028 |
|
2029 |
|
2030 |
|
2031 |
|
2032 | var CHARACTER_TRANSLATION = {
|
2033 | 0x2a: 0xe1,
|
2034 | 0x5c: 0xe9,
|
2035 | 0x5e: 0xed,
|
2036 | 0x5f: 0xf3,
|
2037 | 0x60: 0xfa,
|
2038 | 0x7b: 0xe7,
|
2039 | 0x7c: 0xf7,
|
2040 | 0x7d: 0xd1,
|
2041 | 0x7e: 0xf1,
|
2042 | 0x7f: 0x2588,
|
2043 | 0x0130: 0xae,
|
2044 | 0x0131: 0xb0,
|
2045 | 0x0132: 0xbd,
|
2046 | 0x0133: 0xbf,
|
2047 | 0x0134: 0x2122,
|
2048 | 0x0135: 0xa2,
|
2049 | 0x0136: 0xa3,
|
2050 | 0x0137: 0x266a,
|
2051 | 0x0138: 0xe0,
|
2052 | 0x0139: 0xa0,
|
2053 | 0x013a: 0xe8,
|
2054 | 0x013b: 0xe2,
|
2055 | 0x013c: 0xea,
|
2056 | 0x013d: 0xee,
|
2057 | 0x013e: 0xf4,
|
2058 | 0x013f: 0xfb,
|
2059 | 0x0220: 0xc1,
|
2060 | 0x0221: 0xc9,
|
2061 | 0x0222: 0xd3,
|
2062 | 0x0223: 0xda,
|
2063 | 0x0224: 0xdc,
|
2064 | 0x0225: 0xfc,
|
2065 | 0x0226: 0x2018,
|
2066 | 0x0227: 0xa1,
|
2067 | 0x0228: 0x2a,
|
2068 | 0x0229: 0x27,
|
2069 | 0x022a: 0x2014,
|
2070 | 0x022b: 0xa9,
|
2071 | 0x022c: 0x2120,
|
2072 | 0x022d: 0x2022,
|
2073 | 0x022e: 0x201c,
|
2074 | 0x022f: 0x201d,
|
2075 | 0x0230: 0xc0,
|
2076 | 0x0231: 0xc2,
|
2077 | 0x0232: 0xc7,
|
2078 | 0x0233: 0xc8,
|
2079 | 0x0234: 0xca,
|
2080 | 0x0235: 0xcb,
|
2081 | 0x0236: 0xeb,
|
2082 | 0x0237: 0xce,
|
2083 | 0x0238: 0xcf,
|
2084 | 0x0239: 0xef,
|
2085 | 0x023a: 0xd4,
|
2086 | 0x023b: 0xd9,
|
2087 | 0x023c: 0xf9,
|
2088 | 0x023d: 0xdb,
|
2089 | 0x023e: 0xab,
|
2090 | 0x023f: 0xbb,
|
2091 | 0x0320: 0xc3,
|
2092 | 0x0321: 0xe3,
|
2093 | 0x0322: 0xcd,
|
2094 | 0x0323: 0xcc,
|
2095 | 0x0324: 0xec,
|
2096 | 0x0325: 0xd2,
|
2097 | 0x0326: 0xf2,
|
2098 | 0x0327: 0xd5,
|
2099 | 0x0328: 0xf5,
|
2100 | 0x0329: 0x7b,
|
2101 | 0x032a: 0x7d,
|
2102 | 0x032b: 0x5c,
|
2103 | 0x032c: 0x5e,
|
2104 | 0x032d: 0x5f,
|
2105 | 0x032e: 0x7c,
|
2106 | 0x032f: 0x7e,
|
2107 | 0x0330: 0xc4,
|
2108 | 0x0331: 0xe4,
|
2109 | 0x0332: 0xd6,
|
2110 | 0x0333: 0xf6,
|
2111 | 0x0334: 0xdf,
|
2112 | 0x0335: 0xa5,
|
2113 | 0x0336: 0xa4,
|
2114 | 0x0337: 0x2502,
|
2115 | 0x0338: 0xc5,
|
2116 | 0x0339: 0xe5,
|
2117 | 0x033a: 0xd8,
|
2118 | 0x033b: 0xf8,
|
2119 | 0x033c: 0x250c,
|
2120 | 0x033d: 0x2510,
|
2121 | 0x033e: 0x2514,
|
2122 | 0x033f: 0x2518
|
2123 | };
|
2124 |
|
2125 | var getCharFromCode = function(code) {
|
2126 | if (code === null) {
|
2127 | return '';
|
2128 | }
|
2129 | code = CHARACTER_TRANSLATION[code] || code;
|
2130 | return String.fromCharCode(code);
|
2131 | };
|
2132 |
|
2133 |
|
2134 | var BOTTOM_ROW = 14;
|
2135 |
|
2136 |
|
2137 |
|
2138 | var ROWS = [0x1100, 0x1120, 0x1200, 0x1220, 0x1500, 0x1520, 0x1600, 0x1620,
|
2139 | 0x1700, 0x1720, 0x1000, 0x1300, 0x1320, 0x1400, 0x1420];
|
2140 |
|
2141 |
|
2142 |
|
2143 | var createDisplayBuffer = function() {
|
2144 | var result = [], i = BOTTOM_ROW + 1;
|
2145 | while (i--) {
|
2146 | result.push('');
|
2147 | }
|
2148 | return result;
|
2149 | };
|
2150 |
|
2151 | var Cea608Stream = function(field, dataChannel) {
|
2152 | Cea608Stream.prototype.init.call(this);
|
2153 |
|
2154 | this.field_ = field || 0;
|
2155 | this.dataChannel_ = dataChannel || 0;
|
2156 |
|
2157 | this.name_ = 'CC' + (((this.field_ << 1) | this.dataChannel_) + 1);
|
2158 |
|
2159 | this.setConstants();
|
2160 | this.reset();
|
2161 |
|
2162 | this.push = function(packet) {
|
2163 | var data, swap, char0, char1, text;
|
2164 |
|
2165 | data = packet.ccData & 0x7f7f;
|
2166 |
|
2167 |
|
2168 | if (data === this.lastControlCode_) {
|
2169 | this.lastControlCode_ = null;
|
2170 | return;
|
2171 | }
|
2172 |
|
2173 |
|
2174 | if ((data & 0xf000) === 0x1000) {
|
2175 | this.lastControlCode_ = data;
|
2176 | } else if (data !== this.PADDING_) {
|
2177 | this.lastControlCode_ = null;
|
2178 | }
|
2179 |
|
2180 | char0 = data >>> 8;
|
2181 | char1 = data & 0xff;
|
2182 |
|
2183 | if (data === this.PADDING_) {
|
2184 | return;
|
2185 |
|
2186 | } else if (data === this.RESUME_CAPTION_LOADING_) {
|
2187 | this.mode_ = 'popOn';
|
2188 |
|
2189 | } else if (data === this.END_OF_CAPTION_) {
|
2190 |
|
2191 |
|
2192 |
|
2193 |
|
2194 | this.mode_ = 'popOn';
|
2195 | this.clearFormatting(packet.pts);
|
2196 |
|
2197 | this.flushDisplayed(packet.pts);
|
2198 |
|
2199 |
|
2200 | swap = this.displayed_;
|
2201 | this.displayed_ = this.nonDisplayed_;
|
2202 | this.nonDisplayed_ = swap;
|
2203 |
|
2204 |
|
2205 | this.startPts_ = packet.pts;
|
2206 |
|
2207 | } else if (data === this.ROLL_UP_2_ROWS_) {
|
2208 | this.rollUpRows_ = 2;
|
2209 | this.setRollUp(packet.pts);
|
2210 | } else if (data === this.ROLL_UP_3_ROWS_) {
|
2211 | this.rollUpRows_ = 3;
|
2212 | this.setRollUp(packet.pts);
|
2213 | } else if (data === this.ROLL_UP_4_ROWS_) {
|
2214 | this.rollUpRows_ = 4;
|
2215 | this.setRollUp(packet.pts);
|
2216 | } else if (data === this.CARRIAGE_RETURN_) {
|
2217 | this.clearFormatting(packet.pts);
|
2218 | this.flushDisplayed(packet.pts);
|
2219 | this.shiftRowsUp_();
|
2220 | this.startPts_ = packet.pts;
|
2221 |
|
2222 | } else if (data === this.BACKSPACE_) {
|
2223 | if (this.mode_ === 'popOn') {
|
2224 | this.nonDisplayed_[this.row_] = this.nonDisplayed_[this.row_].slice(0, -1);
|
2225 | } else {
|
2226 | this.displayed_[this.row_] = this.displayed_[this.row_].slice(0, -1);
|
2227 | }
|
2228 | } else if (data === this.ERASE_DISPLAYED_MEMORY_) {
|
2229 | this.flushDisplayed(packet.pts);
|
2230 | this.displayed_ = createDisplayBuffer();
|
2231 | } else if (data === this.ERASE_NON_DISPLAYED_MEMORY_) {
|
2232 | this.nonDisplayed_ = createDisplayBuffer();
|
2233 |
|
2234 | } else if (data === this.RESUME_DIRECT_CAPTIONING_) {
|
2235 | if (this.mode_ !== 'paintOn') {
|
2236 |
|
2237 |
|
2238 | this.flushDisplayed(packet.pts);
|
2239 | this.displayed_ = createDisplayBuffer();
|
2240 | }
|
2241 | this.mode_ = 'paintOn';
|
2242 | this.startPts_ = packet.pts;
|
2243 |
|
2244 |
|
2245 | } else if (this.isSpecialCharacter(char0, char1)) {
|
2246 |
|
2247 |
|
2248 |
|
2249 |
|
2250 | char0 = (char0 & 0x03) << 8;
|
2251 | text = getCharFromCode(char0 | char1);
|
2252 | this[this.mode_](packet.pts, text);
|
2253 | this.column_++;
|
2254 |
|
2255 |
|
2256 | } else if (this.isExtCharacter(char0, char1)) {
|
2257 |
|
2258 |
|
2259 |
|
2260 |
|
2261 |
|
2262 |
|
2263 | if (this.mode_ === 'popOn') {
|
2264 | this.nonDisplayed_[this.row_] = this.nonDisplayed_[this.row_].slice(0, -1);
|
2265 | } else {
|
2266 | this.displayed_[this.row_] = this.displayed_[this.row_].slice(0, -1);
|
2267 | }
|
2268 |
|
2269 |
|
2270 |
|
2271 |
|
2272 |
|
2273 | char0 = (char0 & 0x03) << 8;
|
2274 | text = getCharFromCode(char0 | char1);
|
2275 | this[this.mode_](packet.pts, text);
|
2276 | this.column_++;
|
2277 |
|
2278 |
|
2279 | } else if (this.isMidRowCode(char0, char1)) {
|
2280 |
|
2281 | this.clearFormatting(packet.pts);
|
2282 |
|
2283 |
|
2284 |
|
2285 | this[this.mode_](packet.pts, ' ');
|
2286 | this.column_++;
|
2287 |
|
2288 | if ((char1 & 0xe) === 0xe) {
|
2289 | this.addFormatting(packet.pts, ['i']);
|
2290 | }
|
2291 |
|
2292 | if ((char1 & 0x1) === 0x1) {
|
2293 | this.addFormatting(packet.pts, ['u']);
|
2294 | }
|
2295 |
|
2296 |
|
2297 | } else if (this.isOffsetControlCode(char0, char1)) {
|
2298 |
|
2299 |
|
2300 |
|
2301 |
|
2302 | this.column_ += (char1 & 0x03);
|
2303 |
|
2304 |
|
2305 | } else if (this.isPAC(char0, char1)) {
|
2306 |
|
2307 |
|
2308 |
|
2309 | var row = ROWS.indexOf(data & 0x1f20);
|
2310 |
|
2311 |
|
2312 | if (this.mode_ === 'rollUp') {
|
2313 |
|
2314 |
|
2315 |
|
2316 | if (row - this.rollUpRows_ + 1 < 0) {
|
2317 | row = this.rollUpRows_ - 1;
|
2318 | }
|
2319 |
|
2320 | this.setRollUp(packet.pts, row);
|
2321 | }
|
2322 |
|
2323 | if (row !== this.row_) {
|
2324 |
|
2325 | this.clearFormatting(packet.pts);
|
2326 | this.row_ = row;
|
2327 | }
|
2328 |
|
2329 |
|
2330 | if ((char1 & 0x1) && (this.formatting_.indexOf('u') === -1)) {
|
2331 | this.addFormatting(packet.pts, ['u']);
|
2332 | }
|
2333 |
|
2334 | if ((data & 0x10) === 0x10) {
|
2335 |
|
2336 |
|
2337 |
|
2338 |
|
2339 | this.column_ = ((data & 0xe) >> 1) * 4;
|
2340 | }
|
2341 |
|
2342 | if (this.isColorPAC(char1)) {
|
2343 |
|
2344 |
|
2345 |
|
2346 |
|
2347 | if ((char1 & 0xe) === 0xe) {
|
2348 | this.addFormatting(packet.pts, ['i']);
|
2349 | }
|
2350 | }
|
2351 |
|
2352 |
|
2353 | } else if (this.isNormalChar(char0)) {
|
2354 | if (char1 === 0x00) {
|
2355 | char1 = null;
|
2356 | }
|
2357 | text = getCharFromCode(char0);
|
2358 | text += getCharFromCode(char1);
|
2359 | this[this.mode_](packet.pts, text);
|
2360 | this.column_ += text.length;
|
2361 |
|
2362 | }
|
2363 |
|
2364 | };
|
2365 | };
|
2366 | Cea608Stream.prototype = new stream();
|
2367 |
|
2368 |
|
2369 | Cea608Stream.prototype.flushDisplayed = function(pts) {
|
2370 | var content = this.displayed_
|
2371 |
|
2372 | .map(function(row) {
|
2373 | try {
|
2374 | return row.trim();
|
2375 | } catch (e) {
|
2376 |
|
2377 |
|
2378 |
|
2379 |
|
2380 | console.error('Skipping malformed caption.');
|
2381 | return '';
|
2382 | }
|
2383 | })
|
2384 |
|
2385 | .join('\n')
|
2386 |
|
2387 | .replace(/^\n+|\n+$/g, '');
|
2388 |
|
2389 | if (content.length) {
|
2390 | this.trigger('data', {
|
2391 | startPts: this.startPts_,
|
2392 | endPts: pts,
|
2393 | text: content,
|
2394 | stream: this.name_
|
2395 | });
|
2396 | }
|
2397 | };
|
2398 |
|
2399 | |
2400 |
|
2401 |
|
2402 | Cea608Stream.prototype.reset = function() {
|
2403 | this.mode_ = 'popOn';
|
2404 |
|
2405 |
|
2406 |
|
2407 |
|
2408 | this.topRow_ = 0;
|
2409 | this.startPts_ = 0;
|
2410 | this.displayed_ = createDisplayBuffer();
|
2411 | this.nonDisplayed_ = createDisplayBuffer();
|
2412 | this.lastControlCode_ = null;
|
2413 |
|
2414 |
|
2415 | this.column_ = 0;
|
2416 | this.row_ = BOTTOM_ROW;
|
2417 | this.rollUpRows_ = 2;
|
2418 |
|
2419 |
|
2420 | this.formatting_ = [];
|
2421 | };
|
2422 |
|
2423 | |
2424 |
|
2425 |
|
2426 | Cea608Stream.prototype.setConstants = function() {
|
2427 |
|
2428 |
|
2429 |
|
2430 |
|
2431 |
|
2432 |
|
2433 |
|
2434 |
|
2435 |
|
2436 |
|
2437 |
|
2438 |
|
2439 | if (this.dataChannel_ === 0) {
|
2440 | this.BASE_ = 0x10;
|
2441 | this.EXT_ = 0x11;
|
2442 | this.CONTROL_ = (0x14 | this.field_) << 8;
|
2443 | this.OFFSET_ = 0x17;
|
2444 | } else if (this.dataChannel_ === 1) {
|
2445 | this.BASE_ = 0x18;
|
2446 | this.EXT_ = 0x19;
|
2447 | this.CONTROL_ = (0x1c | this.field_) << 8;
|
2448 | this.OFFSET_ = 0x1f;
|
2449 | }
|
2450 |
|
2451 |
|
2452 |
|
2453 |
|
2454 |
|
2455 | this.PADDING_ = 0x0000;
|
2456 |
|
2457 | this.RESUME_CAPTION_LOADING_ = this.CONTROL_ | 0x20;
|
2458 | this.END_OF_CAPTION_ = this.CONTROL_ | 0x2f;
|
2459 |
|
2460 | this.ROLL_UP_2_ROWS_ = this.CONTROL_ | 0x25;
|
2461 | this.ROLL_UP_3_ROWS_ = this.CONTROL_ | 0x26;
|
2462 | this.ROLL_UP_4_ROWS_ = this.CONTROL_ | 0x27;
|
2463 | this.CARRIAGE_RETURN_ = this.CONTROL_ | 0x2d;
|
2464 |
|
2465 | this.RESUME_DIRECT_CAPTIONING_ = this.CONTROL_ | 0x29;
|
2466 |
|
2467 | this.BACKSPACE_ = this.CONTROL_ | 0x21;
|
2468 | this.ERASE_DISPLAYED_MEMORY_ = this.CONTROL_ | 0x2c;
|
2469 | this.ERASE_NON_DISPLAYED_MEMORY_ = this.CONTROL_ | 0x2e;
|
2470 | };
|
2471 |
|
2472 | |
2473 |
|
2474 |
|
2475 |
|
2476 |
|
2477 |
|
2478 |
|
2479 |
|
2480 |
|
2481 |
|
2482 |
|
2483 | Cea608Stream.prototype.isSpecialCharacter = function(char0, char1) {
|
2484 | return (char0 === this.EXT_ && char1 >= 0x30 && char1 <= 0x3f);
|
2485 | };
|
2486 |
|
2487 | |
2488 |
|
2489 |
|
2490 |
|
2491 |
|
2492 |
|
2493 |
|
2494 |
|
2495 |
|
2496 |
|
2497 |
|
2498 | Cea608Stream.prototype.isExtCharacter = function(char0, char1) {
|
2499 | return ((char0 === (this.EXT_ + 1) || char0 === (this.EXT_ + 2)) &&
|
2500 | (char1 >= 0x20 && char1 <= 0x3f));
|
2501 | };
|
2502 |
|
2503 | |
2504 |
|
2505 |
|
2506 |
|
2507 |
|
2508 |
|
2509 |
|
2510 |
|
2511 |
|
2512 |
|
2513 |
|
2514 | Cea608Stream.prototype.isMidRowCode = function(char0, char1) {
|
2515 | return (char0 === this.EXT_ && (char1 >= 0x20 && char1 <= 0x2f));
|
2516 | };
|
2517 |
|
2518 | |
2519 |
|
2520 |
|
2521 |
|
2522 |
|
2523 |
|
2524 |
|
2525 |
|
2526 |
|
2527 |
|
2528 |
|
2529 | Cea608Stream.prototype.isOffsetControlCode = function(char0, char1) {
|
2530 | return (char0 === this.OFFSET_ && (char1 >= 0x21 && char1 <= 0x23));
|
2531 | };
|
2532 |
|
2533 | |
2534 |
|
2535 |
|
2536 |
|
2537 |
|
2538 |
|
2539 |
|
2540 |
|
2541 |
|
2542 |
|
2543 |
|
2544 | Cea608Stream.prototype.isPAC = function(char0, char1) {
|
2545 | return (char0 >= this.BASE_ && char0 < (this.BASE_ + 8) &&
|
2546 | (char1 >= 0x40 && char1 <= 0x7f));
|
2547 | };
|
2548 |
|
2549 | |
2550 |
|
2551 |
|
2552 |
|
2553 |
|
2554 |
|
2555 |
|
2556 |
|
2557 |
|
2558 | Cea608Stream.prototype.isColorPAC = function(char1) {
|
2559 | return ((char1 >= 0x40 && char1 <= 0x4f) || (char1 >= 0x60 && char1 <= 0x7f));
|
2560 | };
|
2561 |
|
2562 | |
2563 |
|
2564 |
|
2565 |
|
2566 |
|
2567 |
|
2568 |
|
2569 |
|
2570 | Cea608Stream.prototype.isNormalChar = function(char) {
|
2571 | return (char >= 0x20 && char <= 0x7f);
|
2572 | };
|
2573 |
|
2574 | |
2575 |
|
2576 |
|
2577 |
|
2578 |
|
2579 |
|
2580 |
|
2581 | Cea608Stream.prototype.setRollUp = function(pts, newBaseRow) {
|
2582 |
|
2583 | if (this.mode_ !== 'rollUp') {
|
2584 | this.row_ = BOTTOM_ROW;
|
2585 | this.mode_ = 'rollUp';
|
2586 |
|
2587 | this.flushDisplayed(pts);
|
2588 | this.nonDisplayed_ = createDisplayBuffer();
|
2589 | this.displayed_ = createDisplayBuffer();
|
2590 | }
|
2591 |
|
2592 | if (newBaseRow !== undefined && newBaseRow !== this.row_) {
|
2593 |
|
2594 | for (var i = 0; i < this.rollUpRows_; i++) {
|
2595 | this.displayed_[newBaseRow - i] = this.displayed_[this.row_ - i];
|
2596 | this.displayed_[this.row_ - i] = '';
|
2597 | }
|
2598 | }
|
2599 |
|
2600 | if (newBaseRow === undefined) {
|
2601 | newBaseRow = this.row_;
|
2602 | }
|
2603 |
|
2604 | this.topRow_ = newBaseRow - this.rollUpRows_ + 1;
|
2605 | };
|
2606 |
|
2607 |
|
2608 |
|
2609 | Cea608Stream.prototype.addFormatting = function(pts, format) {
|
2610 | this.formatting_ = this.formatting_.concat(format);
|
2611 | var text = format.reduce(function(text, format) {
|
2612 | return text + '<' + format + '>';
|
2613 | }, '');
|
2614 | this[this.mode_](pts, text);
|
2615 | };
|
2616 |
|
2617 |
|
2618 |
|
2619 | Cea608Stream.prototype.clearFormatting = function(pts) {
|
2620 | if (!this.formatting_.length) {
|
2621 | return;
|
2622 | }
|
2623 | var text = this.formatting_.reverse().reduce(function(text, format) {
|
2624 | return text + '</' + format + '>';
|
2625 | }, '');
|
2626 | this.formatting_ = [];
|
2627 | this[this.mode_](pts, text);
|
2628 | };
|
2629 |
|
2630 |
|
2631 | Cea608Stream.prototype.popOn = function(pts, text) {
|
2632 | var baseRow = this.nonDisplayed_[this.row_];
|
2633 |
|
2634 |
|
2635 | baseRow += text;
|
2636 | this.nonDisplayed_[this.row_] = baseRow;
|
2637 | };
|
2638 |
|
2639 | Cea608Stream.prototype.rollUp = function(pts, text) {
|
2640 | var baseRow = this.displayed_[this.row_];
|
2641 |
|
2642 | baseRow += text;
|
2643 | this.displayed_[this.row_] = baseRow;
|
2644 |
|
2645 | };
|
2646 |
|
2647 | Cea608Stream.prototype.shiftRowsUp_ = function() {
|
2648 | var i;
|
2649 |
|
2650 | for (i = 0; i < this.topRow_; i++) {
|
2651 | this.displayed_[i] = '';
|
2652 | }
|
2653 | for (i = this.row_ + 1; i < BOTTOM_ROW + 1; i++) {
|
2654 | this.displayed_[i] = '';
|
2655 | }
|
2656 |
|
2657 | for (i = this.topRow_; i < this.row_; i++) {
|
2658 | this.displayed_[i] = this.displayed_[i + 1];
|
2659 | }
|
2660 |
|
2661 | this.displayed_[this.row_] = '';
|
2662 | };
|
2663 |
|
2664 | Cea608Stream.prototype.paintOn = function(pts, text) {
|
2665 | var baseRow = this.displayed_[this.row_];
|
2666 |
|
2667 | baseRow += text;
|
2668 | this.displayed_[this.row_] = baseRow;
|
2669 | };
|
2670 |
|
2671 |
|
2672 | var captionStream = {
|
2673 | CaptionStream: CaptionStream,
|
2674 | Cea608Stream: Cea608Stream
|
2675 | };
|
2676 |
|
2677 | |
2678 |
|
2679 |
|
2680 |
|
2681 |
|
2682 |
|
2683 |
|
2684 | var streamTypes = {
|
2685 | H264_STREAM_TYPE: 0x1B,
|
2686 | ADTS_STREAM_TYPE: 0x0F,
|
2687 | METADATA_STREAM_TYPE: 0x15
|
2688 | };
|
2689 |
|
2690 | var MAX_TS = 8589934592;
|
2691 |
|
2692 | var RO_THRESH = 4294967296;
|
2693 |
|
2694 | var TYPE_SHARED = 'shared';
|
2695 |
|
2696 | var handleRollover = function(value, reference) {
|
2697 | var direction = 1;
|
2698 |
|
2699 | if (value > reference) {
|
2700 |
|
2701 |
|
2702 |
|
2703 |
|
2704 |
|
2705 |
|
2706 |
|
2707 | direction = -1;
|
2708 | }
|
2709 |
|
2710 |
|
2711 |
|
2712 | while (Math.abs(reference - value) > RO_THRESH) {
|
2713 | value += (direction * MAX_TS);
|
2714 | }
|
2715 |
|
2716 | return value;
|
2717 | };
|
2718 |
|
2719 | var TimestampRolloverStream = function(type) {
|
2720 | var lastDTS, referenceDTS;
|
2721 |
|
2722 | TimestampRolloverStream.prototype.init.call(this);
|
2723 |
|
2724 |
|
2725 |
|
2726 |
|
2727 | this.type_ = type || TYPE_SHARED;
|
2728 |
|
2729 | this.push = function(data) {
|
2730 |
|
2731 |
|
2732 |
|
2733 | if (this.type_ !== TYPE_SHARED && data.type !== this.type_) {
|
2734 | return;
|
2735 | }
|
2736 |
|
2737 | if (referenceDTS === undefined) {
|
2738 | referenceDTS = data.dts;
|
2739 | }
|
2740 |
|
2741 | data.dts = handleRollover(data.dts, referenceDTS);
|
2742 | data.pts = handleRollover(data.pts, referenceDTS);
|
2743 |
|
2744 | lastDTS = data.dts;
|
2745 |
|
2746 | this.trigger('data', data);
|
2747 | };
|
2748 |
|
2749 | this.flush = function() {
|
2750 | referenceDTS = lastDTS;
|
2751 | this.trigger('done');
|
2752 | };
|
2753 |
|
2754 | this.endTimeline = function() {
|
2755 | this.flush();
|
2756 | this.trigger('endedtimeline');
|
2757 | };
|
2758 |
|
2759 | this.discontinuity = function() {
|
2760 | referenceDTS = void 0;
|
2761 | lastDTS = void 0;
|
2762 | };
|
2763 |
|
2764 | this.reset = function() {
|
2765 | this.discontinuity();
|
2766 | this.trigger('reset');
|
2767 | };
|
2768 | };
|
2769 |
|
2770 | TimestampRolloverStream.prototype = new stream();
|
2771 |
|
2772 | var timestampRolloverStream = {
|
2773 | TimestampRolloverStream: TimestampRolloverStream,
|
2774 | handleRollover: handleRollover
|
2775 | };
|
2776 |
|
2777 | var
|
2778 | percentEncode = function(bytes, start, end) {
|
2779 | var i, result = '';
|
2780 | for (i = start; i < end; i++) {
|
2781 | result += '%' + ('00' + bytes[i].toString(16)).slice(-2);
|
2782 | }
|
2783 | return result;
|
2784 | },
|
2785 |
|
2786 |
|
2787 | parseUtf8 = function(bytes, start, end) {
|
2788 | return decodeURIComponent(percentEncode(bytes, start, end));
|
2789 | },
|
2790 |
|
2791 |
|
2792 | parseIso88591 = function(bytes, start, end) {
|
2793 | return unescape(percentEncode(bytes, start, end));
|
2794 | },
|
2795 | parseSyncSafeInteger = function(data) {
|
2796 | return (data[0] << 21) |
|
2797 | (data[1] << 14) |
|
2798 | (data[2] << 7) |
|
2799 | (data[3]);
|
2800 | },
|
2801 | tagParsers = {
|
2802 | TXXX: function(tag) {
|
2803 | var i;
|
2804 | if (tag.data[0] !== 3) {
|
2805 |
|
2806 | return;
|
2807 | }
|
2808 |
|
2809 | for (i = 1; i < tag.data.length; i++) {
|
2810 | if (tag.data[i] === 0) {
|
2811 |
|
2812 | tag.description = parseUtf8(tag.data, 1, i);
|
2813 |
|
2814 | tag.value = parseUtf8(tag.data, i + 1, tag.data.length).replace(/\0*$/, '');
|
2815 | break;
|
2816 | }
|
2817 | }
|
2818 | tag.data = tag.value;
|
2819 | },
|
2820 | WXXX: function(tag) {
|
2821 | var i;
|
2822 | if (tag.data[0] !== 3) {
|
2823 |
|
2824 | return;
|
2825 | }
|
2826 |
|
2827 | for (i = 1; i < tag.data.length; i++) {
|
2828 | if (tag.data[i] === 0) {
|
2829 |
|
2830 | tag.description = parseUtf8(tag.data, 1, i);
|
2831 | tag.url = parseUtf8(tag.data, i + 1, tag.data.length);
|
2832 | break;
|
2833 | }
|
2834 | }
|
2835 | },
|
2836 | PRIV: function(tag) {
|
2837 | var i;
|
2838 |
|
2839 | for (i = 0; i < tag.data.length; i++) {
|
2840 | if (tag.data[i] === 0) {
|
2841 |
|
2842 | tag.owner = parseIso88591(tag.data, 0, i);
|
2843 | break;
|
2844 | }
|
2845 | }
|
2846 | tag.privateData = tag.data.subarray(i + 1);
|
2847 | tag.data = tag.privateData;
|
2848 | }
|
2849 | },
|
2850 | MetadataStream;
|
2851 |
|
2852 | MetadataStream = function(options) {
|
2853 | var
|
2854 | settings = {
|
2855 | debug: !!(options && options.debug),
|
2856 |
|
2857 |
|
2858 |
|
2859 |
|
2860 | descriptor: options && options.descriptor
|
2861 | },
|
2862 |
|
2863 | tagSize = 0,
|
2864 |
|
2865 | buffer = [],
|
2866 |
|
2867 | bufferSize = 0,
|
2868 | i;
|
2869 |
|
2870 | MetadataStream.prototype.init.call(this);
|
2871 |
|
2872 |
|
2873 |
|
2874 | this.dispatchType = streamTypes.METADATA_STREAM_TYPE.toString(16);
|
2875 | if (settings.descriptor) {
|
2876 | for (i = 0; i < settings.descriptor.length; i++) {
|
2877 | this.dispatchType += ('00' + settings.descriptor[i].toString(16)).slice(-2);
|
2878 | }
|
2879 | }
|
2880 |
|
2881 | this.push = function(chunk) {
|
2882 | var tag, frameStart, frameSize, frame, i, frameHeader;
|
2883 | if (chunk.type !== 'timed-metadata') {
|
2884 | return;
|
2885 | }
|
2886 |
|
2887 |
|
2888 |
|
2889 |
|
2890 | if (chunk.dataAlignmentIndicator) {
|
2891 | bufferSize = 0;
|
2892 | buffer.length = 0;
|
2893 | }
|
2894 |
|
2895 |
|
2896 | if (buffer.length === 0 &&
|
2897 | (chunk.data.length < 10 ||
|
2898 | chunk.data[0] !== 'I'.charCodeAt(0) ||
|
2899 | chunk.data[1] !== 'D'.charCodeAt(0) ||
|
2900 | chunk.data[2] !== '3'.charCodeAt(0))) {
|
2901 | if (settings.debug) {
|
2902 |
|
2903 | console.log('Skipping unrecognized metadata packet');
|
2904 | }
|
2905 | return;
|
2906 | }
|
2907 |
|
2908 |
|
2909 |
|
2910 | buffer.push(chunk);
|
2911 | bufferSize += chunk.data.byteLength;
|
2912 |
|
2913 |
|
2914 | if (buffer.length === 1) {
|
2915 |
|
2916 |
|
2917 |
|
2918 |
|
2919 | tagSize = parseSyncSafeInteger(chunk.data.subarray(6, 10));
|
2920 |
|
2921 |
|
2922 |
|
2923 | tagSize += 10;
|
2924 | }
|
2925 |
|
2926 |
|
2927 | if (bufferSize < tagSize) {
|
2928 | return;
|
2929 | }
|
2930 |
|
2931 |
|
2932 | tag = {
|
2933 | data: new Uint8Array(tagSize),
|
2934 | frames: [],
|
2935 | pts: buffer[0].pts,
|
2936 | dts: buffer[0].dts
|
2937 | };
|
2938 | for (i = 0; i < tagSize;) {
|
2939 | tag.data.set(buffer[0].data.subarray(0, tagSize - i), i);
|
2940 | i += buffer[0].data.byteLength;
|
2941 | bufferSize -= buffer[0].data.byteLength;
|
2942 | buffer.shift();
|
2943 | }
|
2944 |
|
2945 |
|
2946 | frameStart = 10;
|
2947 | if (tag.data[5] & 0x40) {
|
2948 |
|
2949 | frameStart += 4;
|
2950 | frameStart += parseSyncSafeInteger(tag.data.subarray(10, 14));
|
2951 |
|
2952 |
|
2953 | tagSize -= parseSyncSafeInteger(tag.data.subarray(16, 20));
|
2954 | }
|
2955 |
|
2956 |
|
2957 |
|
2958 | do {
|
2959 |
|
2960 | frameSize = parseSyncSafeInteger(tag.data.subarray(frameStart + 4, frameStart + 8));
|
2961 | if (frameSize < 1) {
|
2962 |
|
2963 | return console.log('Malformed ID3 frame encountered. Skipping metadata parsing.');
|
2964 | }
|
2965 | frameHeader = String.fromCharCode(tag.data[frameStart],
|
2966 | tag.data[frameStart + 1],
|
2967 | tag.data[frameStart + 2],
|
2968 | tag.data[frameStart + 3]);
|
2969 |
|
2970 |
|
2971 | frame = {
|
2972 | id: frameHeader,
|
2973 | data: tag.data.subarray(frameStart + 10, frameStart + frameSize + 10)
|
2974 | };
|
2975 | frame.key = frame.id;
|
2976 | if (tagParsers[frame.id]) {
|
2977 | tagParsers[frame.id](frame);
|
2978 |
|
2979 |
|
2980 |
|
2981 | if (frame.owner === 'com.apple.streaming.transportStreamTimestamp') {
|
2982 | var
|
2983 | d = frame.data,
|
2984 | size = ((d[3] & 0x01) << 30) |
|
2985 | (d[4] << 22) |
|
2986 | (d[5] << 14) |
|
2987 | (d[6] << 6) |
|
2988 | (d[7] >>> 2);
|
2989 |
|
2990 | size *= 4;
|
2991 | size += d[7] & 0x03;
|
2992 | frame.timeStamp = size;
|
2993 |
|
2994 |
|
2995 |
|
2996 |
|
2997 | if (tag.pts === undefined && tag.dts === undefined) {
|
2998 | tag.pts = frame.timeStamp;
|
2999 | tag.dts = frame.timeStamp;
|
3000 | }
|
3001 | this.trigger('timestamp', frame);
|
3002 | }
|
3003 | }
|
3004 | tag.frames.push(frame);
|
3005 |
|
3006 | frameStart += 10;
|
3007 | frameStart += frameSize;
|
3008 | } while (frameStart < tagSize);
|
3009 | this.trigger('data', tag);
|
3010 | };
|
3011 | };
|
3012 | MetadataStream.prototype = new stream();
|
3013 |
|
3014 | var metadataStream = MetadataStream;
|
3015 |
|
3016 | var TimestampRolloverStream$1 = timestampRolloverStream.TimestampRolloverStream;
|
3017 |
|
3018 |
|
3019 | var TransportPacketStream, TransportParseStream, ElementaryStream;
|
3020 |
|
3021 |
|
3022 | var
|
3023 | MP2T_PACKET_LENGTH = 188,
|
3024 | SYNC_BYTE = 0x47;
|
3025 |
|
3026 | |
3027 |
|
3028 |
|
3029 |
|
3030 | TransportPacketStream = function() {
|
3031 | var
|
3032 | buffer = new Uint8Array(MP2T_PACKET_LENGTH),
|
3033 | bytesInBuffer = 0;
|
3034 |
|
3035 | TransportPacketStream.prototype.init.call(this);
|
3036 |
|
3037 |
|
3038 |
|
3039 | |
3040 |
|
3041 |
|
3042 | this.push = function(bytes) {
|
3043 | var
|
3044 | startIndex = 0,
|
3045 | endIndex = MP2T_PACKET_LENGTH,
|
3046 | everything;
|
3047 |
|
3048 |
|
3049 |
|
3050 | if (bytesInBuffer) {
|
3051 | everything = new Uint8Array(bytes.byteLength + bytesInBuffer);
|
3052 | everything.set(buffer.subarray(0, bytesInBuffer));
|
3053 | everything.set(bytes, bytesInBuffer);
|
3054 | bytesInBuffer = 0;
|
3055 | } else {
|
3056 | everything = bytes;
|
3057 | }
|
3058 |
|
3059 |
|
3060 | while (endIndex < everything.byteLength) {
|
3061 |
|
3062 | if (everything[startIndex] === SYNC_BYTE && everything[endIndex] === SYNC_BYTE) {
|
3063 |
|
3064 |
|
3065 | this.trigger('data', everything.subarray(startIndex, endIndex));
|
3066 | startIndex += MP2T_PACKET_LENGTH;
|
3067 | endIndex += MP2T_PACKET_LENGTH;
|
3068 | continue;
|
3069 | }
|
3070 |
|
3071 |
|
3072 |
|
3073 | startIndex++;
|
3074 | endIndex++;
|
3075 | }
|
3076 |
|
3077 |
|
3078 |
|
3079 |
|
3080 | if (startIndex < everything.byteLength) {
|
3081 | buffer.set(everything.subarray(startIndex), 0);
|
3082 | bytesInBuffer = everything.byteLength - startIndex;
|
3083 | }
|
3084 | };
|
3085 |
|
3086 | |
3087 |
|
3088 |
|
3089 | this.flush = function() {
|
3090 |
|
3091 |
|
3092 |
|
3093 | if (bytesInBuffer === MP2T_PACKET_LENGTH && buffer[0] === SYNC_BYTE) {
|
3094 | this.trigger('data', buffer);
|
3095 | bytesInBuffer = 0;
|
3096 | }
|
3097 | this.trigger('done');
|
3098 | };
|
3099 |
|
3100 | this.endTimeline = function() {
|
3101 | this.flush();
|
3102 | this.trigger('endedtimeline');
|
3103 | };
|
3104 |
|
3105 | this.reset = function() {
|
3106 | bytesInBuffer = 0;
|
3107 | this.trigger('reset');
|
3108 | };
|
3109 | };
|
3110 | TransportPacketStream.prototype = new stream();
|
3111 |
|
3112 | |
3113 |
|
3114 |
|
3115 |
|
3116 | TransportParseStream = function() {
|
3117 | var parsePsi, parsePat, parsePmt, self;
|
3118 | TransportParseStream.prototype.init.call(this);
|
3119 | self = this;
|
3120 |
|
3121 | this.packetsWaitingForPmt = [];
|
3122 | this.programMapTable = undefined;
|
3123 |
|
3124 | parsePsi = function(payload, psi) {
|
3125 | var offset = 0;
|
3126 |
|
3127 |
|
3128 |
|
3129 |
|
3130 |
|
3131 |
|
3132 |
|
3133 | if (psi.payloadUnitStartIndicator) {
|
3134 | offset += payload[offset] + 1;
|
3135 | }
|
3136 |
|
3137 | if (psi.type === 'pat') {
|
3138 | parsePat(payload.subarray(offset), psi);
|
3139 | } else {
|
3140 | parsePmt(payload.subarray(offset), psi);
|
3141 | }
|
3142 | };
|
3143 |
|
3144 | parsePat = function(payload, pat) {
|
3145 | pat.section_number = payload[7];
|
3146 | pat.last_section_number = payload[8];
|
3147 |
|
3148 |
|
3149 | self.pmtPid = (payload[10] & 0x1F) << 8 | payload[11];
|
3150 | pat.pmtPid = self.pmtPid;
|
3151 | };
|
3152 |
|
3153 | |
3154 |
|
3155 |
|
3156 |
|
3157 |
|
3158 |
|
3159 |
|
3160 |
|
3161 | parsePmt = function(payload, pmt) {
|
3162 | var sectionLength, tableEnd, programInfoLength, offset;
|
3163 |
|
3164 |
|
3165 |
|
3166 |
|
3167 |
|
3168 |
|
3169 | if (!(payload[5] & 0x01)) {
|
3170 | return;
|
3171 | }
|
3172 |
|
3173 |
|
3174 | self.programMapTable = {
|
3175 | video: null,
|
3176 | audio: null,
|
3177 | 'timed-metadata': {}
|
3178 | };
|
3179 |
|
3180 |
|
3181 | sectionLength = (payload[1] & 0x0f) << 8 | payload[2];
|
3182 | tableEnd = 3 + sectionLength - 4;
|
3183 |
|
3184 |
|
3185 |
|
3186 | programInfoLength = (payload[10] & 0x0f) << 8 | payload[11];
|
3187 |
|
3188 |
|
3189 | offset = 12 + programInfoLength;
|
3190 | while (offset < tableEnd) {
|
3191 | var streamType = payload[offset];
|
3192 | var pid = (payload[offset + 1] & 0x1F) << 8 | payload[offset + 2];
|
3193 |
|
3194 |
|
3195 |
|
3196 |
|
3197 | if (streamType === streamTypes.H264_STREAM_TYPE &&
|
3198 | self.programMapTable.video === null) {
|
3199 | self.programMapTable.video = pid;
|
3200 | } else if (streamType === streamTypes.ADTS_STREAM_TYPE &&
|
3201 | self.programMapTable.audio === null) {
|
3202 | self.programMapTable.audio = pid;
|
3203 | } else if (streamType === streamTypes.METADATA_STREAM_TYPE) {
|
3204 |
|
3205 | self.programMapTable['timed-metadata'][pid] = streamType;
|
3206 | }
|
3207 |
|
3208 |
|
3209 |
|
3210 | offset += ((payload[offset + 3] & 0x0F) << 8 | payload[offset + 4]) + 5;
|
3211 | }
|
3212 |
|
3213 |
|
3214 | pmt.programMapTable = self.programMapTable;
|
3215 | };
|
3216 |
|
3217 | |
3218 |
|
3219 |
|
3220 | this.push = function(packet) {
|
3221 | var
|
3222 | result = {},
|
3223 | offset = 4;
|
3224 |
|
3225 | result.payloadUnitStartIndicator = !!(packet[1] & 0x40);
|
3226 |
|
3227 |
|
3228 | result.pid = packet[1] & 0x1f;
|
3229 | result.pid <<= 8;
|
3230 | result.pid |= packet[2];
|
3231 |
|
3232 |
|
3233 |
|
3234 |
|
3235 |
|
3236 |
|
3237 | if (((packet[3] & 0x30) >>> 4) > 0x01) {
|
3238 | offset += packet[offset] + 1;
|
3239 | }
|
3240 |
|
3241 |
|
3242 | if (result.pid === 0) {
|
3243 | result.type = 'pat';
|
3244 | parsePsi(packet.subarray(offset), result);
|
3245 | this.trigger('data', result);
|
3246 | } else if (result.pid === this.pmtPid) {
|
3247 | result.type = 'pmt';
|
3248 | parsePsi(packet.subarray(offset), result);
|
3249 | this.trigger('data', result);
|
3250 |
|
3251 |
|
3252 | while (this.packetsWaitingForPmt.length) {
|
3253 | this.processPes_.apply(this, this.packetsWaitingForPmt.shift());
|
3254 | }
|
3255 | } else if (this.programMapTable === undefined) {
|
3256 |
|
3257 |
|
3258 | this.packetsWaitingForPmt.push([packet, offset, result]);
|
3259 | } else {
|
3260 | this.processPes_(packet, offset, result);
|
3261 | }
|
3262 | };
|
3263 |
|
3264 | this.processPes_ = function(packet, offset, result) {
|
3265 |
|
3266 | if (result.pid === this.programMapTable.video) {
|
3267 | result.streamType = streamTypes.H264_STREAM_TYPE;
|
3268 | } else if (result.pid === this.programMapTable.audio) {
|
3269 | result.streamType = streamTypes.ADTS_STREAM_TYPE;
|
3270 | } else {
|
3271 |
|
3272 |
|
3273 | result.streamType = this.programMapTable['timed-metadata'][result.pid];
|
3274 | }
|
3275 |
|
3276 | result.type = 'pes';
|
3277 | result.data = packet.subarray(offset);
|
3278 | this.trigger('data', result);
|
3279 | };
|
3280 | };
|
3281 | TransportParseStream.prototype = new stream();
|
3282 | TransportParseStream.STREAM_TYPES = {
|
3283 | h264: 0x1b,
|
3284 | adts: 0x0f
|
3285 | };
|
3286 |
|
3287 | |
3288 |
|
3289 |
|
3290 |
|
3291 |
|
3292 |
|
3293 |
|
3294 |
|
3295 | ElementaryStream = function() {
|
3296 | var
|
3297 | self = this,
|
3298 |
|
3299 | video = {
|
3300 | data: [],
|
3301 | size: 0
|
3302 | },
|
3303 | audio = {
|
3304 | data: [],
|
3305 | size: 0
|
3306 | },
|
3307 | timedMetadata = {
|
3308 | data: [],
|
3309 | size: 0
|
3310 | },
|
3311 | programMapTable,
|
3312 | parsePes = function(payload, pes) {
|
3313 | var ptsDtsFlags;
|
3314 |
|
3315 |
|
3316 | pes.packetLength = 6 + ((payload[4] << 8) | payload[5]);
|
3317 |
|
3318 |
|
3319 | pes.dataAlignmentIndicator = (payload[6] & 0x04) !== 0;
|
3320 |
|
3321 |
|
3322 |
|
3323 | ptsDtsFlags = payload[7];
|
3324 |
|
3325 |
|
3326 |
|
3327 |
|
3328 |
|
3329 |
|
3330 |
|
3331 |
|
3332 |
|
3333 | if (ptsDtsFlags & 0xC0) {
|
3334 |
|
3335 |
|
3336 |
|
3337 | pes.pts = (payload[9] & 0x0E) << 27 |
|
3338 | (payload[10] & 0xFF) << 20 |
|
3339 | (payload[11] & 0xFE) << 12 |
|
3340 | (payload[12] & 0xFF) << 5 |
|
3341 | (payload[13] & 0xFE) >>> 3;
|
3342 | pes.pts *= 4;
|
3343 | pes.pts += (payload[13] & 0x06) >>> 1;
|
3344 | pes.dts = pes.pts;
|
3345 | if (ptsDtsFlags & 0x40) {
|
3346 | pes.dts = (payload[14] & 0x0E) << 27 |
|
3347 | (payload[15] & 0xFF) << 20 |
|
3348 | (payload[16] & 0xFE) << 12 |
|
3349 | (payload[17] & 0xFF) << 5 |
|
3350 | (payload[18] & 0xFE) >>> 3;
|
3351 | pes.dts *= 4;
|
3352 | pes.dts += (payload[18] & 0x06) >>> 1;
|
3353 | }
|
3354 | }
|
3355 |
|
3356 |
|
3357 |
|
3358 | pes.data = payload.subarray(9 + payload[8]);
|
3359 | },
|
3360 | |
3361 |
|
3362 |
|
3363 | flushStream = function(stream, type, forceFlush) {
|
3364 | var
|
3365 | packetData = new Uint8Array(stream.size),
|
3366 | event = {
|
3367 | type: type
|
3368 | },
|
3369 | i = 0,
|
3370 | offset = 0,
|
3371 | packetFlushable = false,
|
3372 | fragment;
|
3373 |
|
3374 |
|
3375 |
|
3376 | if (!stream.data.length || stream.size < 9) {
|
3377 | return;
|
3378 | }
|
3379 | event.trackId = stream.data[0].pid;
|
3380 |
|
3381 |
|
3382 | for (i = 0; i < stream.data.length; i++) {
|
3383 | fragment = stream.data[i];
|
3384 |
|
3385 | packetData.set(fragment.data, offset);
|
3386 | offset += fragment.data.byteLength;
|
3387 | }
|
3388 |
|
3389 |
|
3390 | parsePes(packetData, event);
|
3391 |
|
3392 |
|
3393 |
|
3394 | packetFlushable = type === 'video' || event.packetLength <= stream.size;
|
3395 |
|
3396 |
|
3397 | if (forceFlush || packetFlushable) {
|
3398 | stream.size = 0;
|
3399 | stream.data.length = 0;
|
3400 | }
|
3401 |
|
3402 |
|
3403 |
|
3404 | if (packetFlushable) {
|
3405 | self.trigger('data', event);
|
3406 | }
|
3407 | };
|
3408 |
|
3409 | ElementaryStream.prototype.init.call(this);
|
3410 |
|
3411 | |
3412 |
|
3413 |
|
3414 |
|
3415 | this.push = function(data) {
|
3416 | ({
|
3417 | pat: function() {
|
3418 |
|
3419 |
|
3420 | },
|
3421 | pes: function() {
|
3422 | var stream, streamType;
|
3423 |
|
3424 | switch (data.streamType) {
|
3425 | case streamTypes.H264_STREAM_TYPE:
|
3426 | stream = video;
|
3427 | streamType = 'video';
|
3428 | break;
|
3429 | case streamTypes.ADTS_STREAM_TYPE:
|
3430 | stream = audio;
|
3431 | streamType = 'audio';
|
3432 | break;
|
3433 | case streamTypes.METADATA_STREAM_TYPE:
|
3434 | stream = timedMetadata;
|
3435 | streamType = 'timed-metadata';
|
3436 | break;
|
3437 | default:
|
3438 |
|
3439 | return;
|
3440 | }
|
3441 |
|
3442 |
|
3443 |
|
3444 | if (data.payloadUnitStartIndicator) {
|
3445 | flushStream(stream, streamType, true);
|
3446 | }
|
3447 |
|
3448 |
|
3449 |
|
3450 | stream.data.push(data);
|
3451 | stream.size += data.data.byteLength;
|
3452 | },
|
3453 | pmt: function() {
|
3454 | var
|
3455 | event = {
|
3456 | type: 'metadata',
|
3457 | tracks: []
|
3458 | };
|
3459 |
|
3460 | programMapTable = data.programMapTable;
|
3461 |
|
3462 |
|
3463 | if (programMapTable.video !== null) {
|
3464 | event.tracks.push({
|
3465 | timelineStartInfo: {
|
3466 | baseMediaDecodeTime: 0
|
3467 | },
|
3468 | id: +programMapTable.video,
|
3469 | codec: 'avc',
|
3470 | type: 'video'
|
3471 | });
|
3472 | }
|
3473 | if (programMapTable.audio !== null) {
|
3474 | event.tracks.push({
|
3475 | timelineStartInfo: {
|
3476 | baseMediaDecodeTime: 0
|
3477 | },
|
3478 | id: +programMapTable.audio,
|
3479 | codec: 'adts',
|
3480 | type: 'audio'
|
3481 | });
|
3482 | }
|
3483 |
|
3484 | self.trigger('data', event);
|
3485 | }
|
3486 | })[data.type]();
|
3487 | };
|
3488 |
|
3489 | this.reset = function() {
|
3490 | video.size = 0;
|
3491 | video.data.length = 0;
|
3492 | audio.size = 0;
|
3493 | audio.data.length = 0;
|
3494 | this.trigger('reset');
|
3495 | };
|
3496 |
|
3497 | |
3498 |
|
3499 |
|
3500 |
|
3501 |
|
3502 |
|
3503 |
|
3504 |
|
3505 |
|
3506 | this.flushStreams_ = function() {
|
3507 |
|
3508 |
|
3509 | flushStream(video, 'video');
|
3510 | flushStream(audio, 'audio');
|
3511 | flushStream(timedMetadata, 'timed-metadata');
|
3512 | };
|
3513 |
|
3514 | this.flush = function() {
|
3515 | this.flushStreams_();
|
3516 | this.trigger('done');
|
3517 | };
|
3518 | };
|
3519 | ElementaryStream.prototype = new stream();
|
3520 |
|
3521 | var m2ts = {
|
3522 | PAT_PID: 0x0000,
|
3523 | MP2T_PACKET_LENGTH: MP2T_PACKET_LENGTH,
|
3524 | TransportPacketStream: TransportPacketStream,
|
3525 | TransportParseStream: TransportParseStream,
|
3526 | ElementaryStream: ElementaryStream,
|
3527 | TimestampRolloverStream: TimestampRolloverStream$1,
|
3528 | CaptionStream: captionStream.CaptionStream,
|
3529 | Cea608Stream: captionStream.Cea608Stream,
|
3530 | MetadataStream: metadataStream
|
3531 | };
|
3532 |
|
3533 | for (var type in streamTypes) {
|
3534 | if (streamTypes.hasOwnProperty(type)) {
|
3535 | m2ts[type] = streamTypes[type];
|
3536 | }
|
3537 | }
|
3538 |
|
3539 | var m2ts_1 = m2ts;
|
3540 |
|
3541 | var ONE_SECOND_IN_TS$2 = clock.ONE_SECOND_IN_TS;
|
3542 |
|
3543 | var AdtsStream;
|
3544 |
|
3545 | var
|
3546 | ADTS_SAMPLING_FREQUENCIES = [
|
3547 | 96000,
|
3548 | 88200,
|
3549 | 64000,
|
3550 | 48000,
|
3551 | 44100,
|
3552 | 32000,
|
3553 | 24000,
|
3554 | 22050,
|
3555 | 16000,
|
3556 | 12000,
|
3557 | 11025,
|
3558 | 8000,
|
3559 | 7350
|
3560 | ];
|
3561 |
|
3562 | |
3563 |
|
3564 |
|
3565 |
|
3566 |
|
3567 |
|
3568 |
|
3569 |
|
3570 | AdtsStream = function(handlePartialSegments) {
|
3571 | var
|
3572 | buffer,
|
3573 | frameNum = 0;
|
3574 |
|
3575 | AdtsStream.prototype.init.call(this);
|
3576 |
|
3577 | this.push = function(packet) {
|
3578 | var
|
3579 | i = 0,
|
3580 | frameLength,
|
3581 | protectionSkipBytes,
|
3582 | frameEnd,
|
3583 | oldBuffer,
|
3584 | sampleCount,
|
3585 | adtsFrameDuration;
|
3586 |
|
3587 | if (!handlePartialSegments) {
|
3588 | frameNum = 0;
|
3589 | }
|
3590 |
|
3591 | if (packet.type !== 'audio') {
|
3592 |
|
3593 | return;
|
3594 | }
|
3595 |
|
3596 |
|
3597 |
|
3598 | if (buffer) {
|
3599 | oldBuffer = buffer;
|
3600 | buffer = new Uint8Array(oldBuffer.byteLength + packet.data.byteLength);
|
3601 | buffer.set(oldBuffer);
|
3602 | buffer.set(packet.data, oldBuffer.byteLength);
|
3603 | } else {
|
3604 | buffer = packet.data;
|
3605 | }
|
3606 |
|
3607 |
|
3608 |
|
3609 | while (i + 5 < buffer.length) {
|
3610 |
|
3611 |
|
3612 | if ((buffer[i] !== 0xFF) || (buffer[i + 1] & 0xF6) !== 0xF0) {
|
3613 |
|
3614 |
|
3615 | i++;
|
3616 | continue;
|
3617 | }
|
3618 |
|
3619 |
|
3620 |
|
3621 | protectionSkipBytes = (~buffer[i + 1] & 0x01) * 2;
|
3622 |
|
3623 |
|
3624 |
|
3625 | frameLength = ((buffer[i + 3] & 0x03) << 11) |
|
3626 | (buffer[i + 4] << 3) |
|
3627 | ((buffer[i + 5] & 0xe0) >> 5);
|
3628 |
|
3629 | sampleCount = ((buffer[i + 6] & 0x03) + 1) * 1024;
|
3630 | adtsFrameDuration = (sampleCount * ONE_SECOND_IN_TS$2) /
|
3631 | ADTS_SAMPLING_FREQUENCIES[(buffer[i + 2] & 0x3c) >>> 2];
|
3632 |
|
3633 | frameEnd = i + frameLength;
|
3634 |
|
3635 |
|
3636 |
|
3637 | if (buffer.byteLength < frameEnd) {
|
3638 | return;
|
3639 | }
|
3640 |
|
3641 |
|
3642 | this.trigger('data', {
|
3643 | pts: packet.pts + (frameNum * adtsFrameDuration),
|
3644 | dts: packet.dts + (frameNum * adtsFrameDuration),
|
3645 | sampleCount: sampleCount,
|
3646 | audioobjecttype: ((buffer[i + 2] >>> 6) & 0x03) + 1,
|
3647 | channelcount: ((buffer[i + 2] & 1) << 2) |
|
3648 | ((buffer[i + 3] & 0xc0) >>> 6),
|
3649 | samplerate: ADTS_SAMPLING_FREQUENCIES[(buffer[i + 2] & 0x3c) >>> 2],
|
3650 | samplingfrequencyindex: (buffer[i + 2] & 0x3c) >>> 2,
|
3651 |
|
3652 | samplesize: 16,
|
3653 | data: buffer.subarray(i + 7 + protectionSkipBytes, frameEnd)
|
3654 | });
|
3655 |
|
3656 | frameNum++;
|
3657 |
|
3658 |
|
3659 | if (buffer.byteLength === frameEnd) {
|
3660 | buffer = undefined;
|
3661 | return;
|
3662 | }
|
3663 |
|
3664 |
|
3665 | buffer = buffer.subarray(frameEnd);
|
3666 | }
|
3667 | };
|
3668 |
|
3669 | this.flush = function() {
|
3670 | frameNum = 0;
|
3671 | this.trigger('done');
|
3672 | };
|
3673 |
|
3674 | this.reset = function() {
|
3675 | buffer = void 0;
|
3676 | this.trigger('reset');
|
3677 | };
|
3678 |
|
3679 | this.endTimeline = function() {
|
3680 | buffer = void 0;
|
3681 | this.trigger('endedtimeline');
|
3682 | };
|
3683 | };
|
3684 |
|
3685 | AdtsStream.prototype = new stream();
|
3686 |
|
3687 | var adts = AdtsStream;
|
3688 |
|
3689 | |
3690 |
|
3691 |
|
3692 |
|
3693 |
|
3694 |
|
3695 |
|
3696 | var ExpGolomb;
|
3697 |
|
3698 | |
3699 |
|
3700 |
|
3701 |
|
3702 | ExpGolomb = function(workingData) {
|
3703 | var
|
3704 |
|
3705 | workingBytesAvailable = workingData.byteLength,
|
3706 |
|
3707 |
|
3708 | workingWord = 0,
|
3709 |
|
3710 |
|
3711 | workingBitsAvailable = 0;
|
3712 |
|
3713 |
|
3714 | this.length = function() {
|
3715 | return (8 * workingBytesAvailable);
|
3716 | };
|
3717 |
|
3718 |
|
3719 | this.bitsAvailable = function() {
|
3720 | return (8 * workingBytesAvailable) + workingBitsAvailable;
|
3721 | };
|
3722 |
|
3723 |
|
3724 | this.loadWord = function() {
|
3725 | var
|
3726 | position = workingData.byteLength - workingBytesAvailable,
|
3727 | workingBytes = new Uint8Array(4),
|
3728 | availableBytes = Math.min(4, workingBytesAvailable);
|
3729 |
|
3730 | if (availableBytes === 0) {
|
3731 | throw new Error('no bytes available');
|
3732 | }
|
3733 |
|
3734 | workingBytes.set(workingData.subarray(position,
|
3735 | position + availableBytes));
|
3736 | workingWord = new DataView(workingBytes.buffer).getUint32(0);
|
3737 |
|
3738 |
|
3739 | workingBitsAvailable = availableBytes * 8;
|
3740 | workingBytesAvailable -= availableBytes;
|
3741 | };
|
3742 |
|
3743 |
|
3744 | this.skipBits = function(count) {
|
3745 | var skipBytes;
|
3746 | if (workingBitsAvailable > count) {
|
3747 | workingWord <<= count;
|
3748 | workingBitsAvailable -= count;
|
3749 | } else {
|
3750 | count -= workingBitsAvailable;
|
3751 | skipBytes = Math.floor(count / 8);
|
3752 |
|
3753 | count -= (skipBytes * 8);
|
3754 | workingBytesAvailable -= skipBytes;
|
3755 |
|
3756 | this.loadWord();
|
3757 |
|
3758 | workingWord <<= count;
|
3759 | workingBitsAvailable -= count;
|
3760 | }
|
3761 | };
|
3762 |
|
3763 |
|
3764 | this.readBits = function(size) {
|
3765 | var
|
3766 | bits = Math.min(workingBitsAvailable, size),
|
3767 | valu = workingWord >>> (32 - bits);
|
3768 |
|
3769 | workingBitsAvailable -= bits;
|
3770 | if (workingBitsAvailable > 0) {
|
3771 | workingWord <<= bits;
|
3772 | } else if (workingBytesAvailable > 0) {
|
3773 | this.loadWord();
|
3774 | }
|
3775 |
|
3776 | bits = size - bits;
|
3777 | if (bits > 0) {
|
3778 | return valu << bits | this.readBits(bits);
|
3779 | }
|
3780 | return valu;
|
3781 | };
|
3782 |
|
3783 |
|
3784 | this.skipLeadingZeros = function() {
|
3785 | var leadingZeroCount;
|
3786 | for (leadingZeroCount = 0; leadingZeroCount < workingBitsAvailable; ++leadingZeroCount) {
|
3787 | if ((workingWord & (0x80000000 >>> leadingZeroCount)) !== 0) {
|
3788 |
|
3789 | workingWord <<= leadingZeroCount;
|
3790 | workingBitsAvailable -= leadingZeroCount;
|
3791 | return leadingZeroCount;
|
3792 | }
|
3793 | }
|
3794 |
|
3795 |
|
3796 | this.loadWord();
|
3797 | return leadingZeroCount + this.skipLeadingZeros();
|
3798 | };
|
3799 |
|
3800 |
|
3801 | this.skipUnsignedExpGolomb = function() {
|
3802 | this.skipBits(1 + this.skipLeadingZeros());
|
3803 | };
|
3804 |
|
3805 |
|
3806 | this.skipExpGolomb = function() {
|
3807 | this.skipBits(1 + this.skipLeadingZeros());
|
3808 | };
|
3809 |
|
3810 |
|
3811 | this.readUnsignedExpGolomb = function() {
|
3812 | var clz = this.skipLeadingZeros();
|
3813 | return this.readBits(clz + 1) - 1;
|
3814 | };
|
3815 |
|
3816 |
|
3817 | this.readExpGolomb = function() {
|
3818 | var valu = this.readUnsignedExpGolomb();
|
3819 | if (0x01 & valu) {
|
3820 |
|
3821 | return (1 + valu) >>> 1;
|
3822 | }
|
3823 | return -1 * (valu >>> 1);
|
3824 | };
|
3825 |
|
3826 |
|
3827 |
|
3828 | this.readBoolean = function() {
|
3829 | return this.readBits(1) === 1;
|
3830 | };
|
3831 |
|
3832 |
|
3833 | this.readUnsignedByte = function() {
|
3834 | return this.readBits(8);
|
3835 | };
|
3836 |
|
3837 | this.loadWord();
|
3838 | };
|
3839 |
|
3840 | var expGolomb = ExpGolomb;
|
3841 |
|
3842 | var H264Stream, NalByteStream;
|
3843 | var PROFILES_WITH_OPTIONAL_SPS_DATA;
|
3844 |
|
3845 | |
3846 |
|
3847 |
|
3848 | NalByteStream = function() {
|
3849 | var
|
3850 | syncPoint = 0,
|
3851 | i,
|
3852 | buffer;
|
3853 | NalByteStream.prototype.init.call(this);
|
3854 |
|
3855 | |
3856 |
|
3857 |
|
3858 |
|
3859 |
|
3860 |
|
3861 |
|
3862 | this.push = function(data) {
|
3863 | var swapBuffer;
|
3864 |
|
3865 | if (!buffer) {
|
3866 | buffer = data.data;
|
3867 | } else {
|
3868 | swapBuffer = new Uint8Array(buffer.byteLength + data.data.byteLength);
|
3869 | swapBuffer.set(buffer);
|
3870 | swapBuffer.set(data.data, buffer.byteLength);
|
3871 | buffer = swapBuffer;
|
3872 | }
|
3873 | var len = buffer.byteLength;
|
3874 |
|
3875 |
|
3876 |
|
3877 |
|
3878 |
|
3879 |
|
3880 |
|
3881 |
|
3882 |
|
3883 |
|
3884 |
|
3885 |
|
3886 | for (; syncPoint < len - 3; syncPoint++) {
|
3887 | if (buffer[syncPoint + 2] === 1) {
|
3888 |
|
3889 | i = syncPoint + 5;
|
3890 | break;
|
3891 | }
|
3892 | }
|
3893 |
|
3894 | while (i < len) {
|
3895 |
|
3896 |
|
3897 | switch (buffer[i]) {
|
3898 | case 0:
|
3899 |
|
3900 | if (buffer[i - 1] !== 0) {
|
3901 | i += 2;
|
3902 | break;
|
3903 | } else if (buffer[i - 2] !== 0) {
|
3904 | i++;
|
3905 | break;
|
3906 | }
|
3907 |
|
3908 |
|
3909 | if (syncPoint + 3 !== i - 2) {
|
3910 | this.trigger('data', buffer.subarray(syncPoint + 3, i - 2));
|
3911 | }
|
3912 |
|
3913 |
|
3914 | do {
|
3915 | i++;
|
3916 | } while (buffer[i] !== 1 && i < len);
|
3917 | syncPoint = i - 2;
|
3918 | i += 3;
|
3919 | break;
|
3920 | case 1:
|
3921 |
|
3922 | if (buffer[i - 1] !== 0 ||
|
3923 | buffer[i - 2] !== 0) {
|
3924 | i += 3;
|
3925 | break;
|
3926 | }
|
3927 |
|
3928 |
|
3929 | this.trigger('data', buffer.subarray(syncPoint + 3, i - 2));
|
3930 | syncPoint = i - 2;
|
3931 | i += 3;
|
3932 | break;
|
3933 | default:
|
3934 |
|
3935 |
|
3936 | i += 3;
|
3937 | break;
|
3938 | }
|
3939 | }
|
3940 |
|
3941 | buffer = buffer.subarray(syncPoint);
|
3942 | i -= syncPoint;
|
3943 | syncPoint = 0;
|
3944 | };
|
3945 |
|
3946 | this.reset = function() {
|
3947 | buffer = null;
|
3948 | syncPoint = 0;
|
3949 | this.trigger('reset');
|
3950 | };
|
3951 |
|
3952 | this.flush = function() {
|
3953 |
|
3954 | if (buffer && buffer.byteLength > 3) {
|
3955 | this.trigger('data', buffer.subarray(syncPoint + 3));
|
3956 | }
|
3957 |
|
3958 | buffer = null;
|
3959 | syncPoint = 0;
|
3960 | this.trigger('done');
|
3961 | };
|
3962 |
|
3963 | this.endTimeline = function() {
|
3964 | this.flush();
|
3965 | this.trigger('endedtimeline');
|
3966 | };
|
3967 | };
|
3968 | NalByteStream.prototype = new stream();
|
3969 |
|
3970 |
|
3971 |
|
3972 |
|
3973 | PROFILES_WITH_OPTIONAL_SPS_DATA = {
|
3974 | 100: true,
|
3975 | 110: true,
|
3976 | 122: true,
|
3977 | 244: true,
|
3978 | 44: true,
|
3979 | 83: true,
|
3980 | 86: true,
|
3981 | 118: true,
|
3982 | 128: true,
|
3983 | 138: true,
|
3984 | 139: true,
|
3985 | 134: true
|
3986 | };
|
3987 |
|
3988 | |
3989 |
|
3990 |
|
3991 |
|
3992 | H264Stream = function() {
|
3993 | var
|
3994 | nalByteStream = new NalByteStream(),
|
3995 | self,
|
3996 | trackId,
|
3997 | currentPts,
|
3998 | currentDts,
|
3999 |
|
4000 | discardEmulationPreventionBytes,
|
4001 | readSequenceParameterSet,
|
4002 | skipScalingList;
|
4003 |
|
4004 | H264Stream.prototype.init.call(this);
|
4005 | self = this;
|
4006 |
|
4007 | |
4008 |
|
4009 |
|
4010 |
|
4011 |
|
4012 |
|
4013 |
|
4014 |
|
4015 |
|
4016 |
|
4017 |
|
4018 | this.push = function(packet) {
|
4019 | if (packet.type !== 'video') {
|
4020 | return;
|
4021 | }
|
4022 | trackId = packet.trackId;
|
4023 | currentPts = packet.pts;
|
4024 | currentDts = packet.dts;
|
4025 |
|
4026 | nalByteStream.push(packet);
|
4027 | };
|
4028 |
|
4029 | |
4030 |
|
4031 |
|
4032 |
|
4033 |
|
4034 |
|
4035 |
|
4036 |
|
4037 | nalByteStream.on('data', function(data) {
|
4038 | var
|
4039 | event = {
|
4040 | trackId: trackId,
|
4041 | pts: currentPts,
|
4042 | dts: currentDts,
|
4043 | data: data
|
4044 | };
|
4045 |
|
4046 | switch (data[0] & 0x1f) {
|
4047 | case 0x05:
|
4048 | event.nalUnitType = 'slice_layer_without_partitioning_rbsp_idr';
|
4049 | break;
|
4050 | case 0x06:
|
4051 | event.nalUnitType = 'sei_rbsp';
|
4052 | event.escapedRBSP = discardEmulationPreventionBytes(data.subarray(1));
|
4053 | break;
|
4054 | case 0x07:
|
4055 | event.nalUnitType = 'seq_parameter_set_rbsp';
|
4056 | event.escapedRBSP = discardEmulationPreventionBytes(data.subarray(1));
|
4057 | event.config = readSequenceParameterSet(event.escapedRBSP);
|
4058 | break;
|
4059 | case 0x08:
|
4060 | event.nalUnitType = 'pic_parameter_set_rbsp';
|
4061 | break;
|
4062 | case 0x09:
|
4063 | event.nalUnitType = 'access_unit_delimiter_rbsp';
|
4064 | break;
|
4065 | }
|
4066 |
|
4067 | self.trigger('data', event);
|
4068 | });
|
4069 | nalByteStream.on('done', function() {
|
4070 | self.trigger('done');
|
4071 | });
|
4072 | nalByteStream.on('partialdone', function() {
|
4073 | self.trigger('partialdone');
|
4074 | });
|
4075 | nalByteStream.on('reset', function() {
|
4076 | self.trigger('reset');
|
4077 | });
|
4078 | nalByteStream.on('endedtimeline', function() {
|
4079 | self.trigger('endedtimeline');
|
4080 | });
|
4081 |
|
4082 | this.flush = function() {
|
4083 | nalByteStream.flush();
|
4084 | };
|
4085 |
|
4086 | this.partialFlush = function() {
|
4087 | nalByteStream.partialFlush();
|
4088 | };
|
4089 |
|
4090 | this.reset = function() {
|
4091 | nalByteStream.reset();
|
4092 | };
|
4093 |
|
4094 | this.endTimeline = function() {
|
4095 | nalByteStream.endTimeline();
|
4096 | };
|
4097 |
|
4098 | |
4099 |
|
4100 |
|
4101 |
|
4102 |
|
4103 |
|
4104 |
|
4105 |
|
4106 |
|
4107 | skipScalingList = function(count, expGolombDecoder) {
|
4108 | var
|
4109 | lastScale = 8,
|
4110 | nextScale = 8,
|
4111 | j,
|
4112 | deltaScale;
|
4113 |
|
4114 | for (j = 0; j < count; j++) {
|
4115 | if (nextScale !== 0) {
|
4116 | deltaScale = expGolombDecoder.readExpGolomb();
|
4117 | nextScale = (lastScale + deltaScale + 256) % 256;
|
4118 | }
|
4119 |
|
4120 | lastScale = (nextScale === 0) ? lastScale : nextScale;
|
4121 | }
|
4122 | };
|
4123 |
|
4124 | |
4125 |
|
4126 |
|
4127 |
|
4128 |
|
4129 |
|
4130 |
|
4131 |
|
4132 | discardEmulationPreventionBytes = function(data) {
|
4133 | var
|
4134 | length = data.byteLength,
|
4135 | emulationPreventionBytesPositions = [],
|
4136 | i = 1,
|
4137 | newLength, newData;
|
4138 |
|
4139 |
|
4140 | while (i < length - 2) {
|
4141 | if (data[i] === 0 && data[i + 1] === 0 && data[i + 2] === 0x03) {
|
4142 | emulationPreventionBytesPositions.push(i + 2);
|
4143 | i += 2;
|
4144 | } else {
|
4145 | i++;
|
4146 | }
|
4147 | }
|
4148 |
|
4149 |
|
4150 |
|
4151 | if (emulationPreventionBytesPositions.length === 0) {
|
4152 | return data;
|
4153 | }
|
4154 |
|
4155 |
|
4156 | newLength = length - emulationPreventionBytesPositions.length;
|
4157 | newData = new Uint8Array(newLength);
|
4158 | var sourceIndex = 0;
|
4159 |
|
4160 | for (i = 0; i < newLength; sourceIndex++, i++) {
|
4161 | if (sourceIndex === emulationPreventionBytesPositions[0]) {
|
4162 |
|
4163 | sourceIndex++;
|
4164 |
|
4165 | emulationPreventionBytesPositions.shift();
|
4166 | }
|
4167 | newData[i] = data[sourceIndex];
|
4168 | }
|
4169 |
|
4170 | return newData;
|
4171 | };
|
4172 |
|
4173 | |
4174 |
|
4175 |
|
4176 |
|
4177 |
|
4178 |
|
4179 |
|
4180 |
|
4181 |
|
4182 | readSequenceParameterSet = function(data) {
|
4183 | var
|
4184 | frameCropLeftOffset = 0,
|
4185 | frameCropRightOffset = 0,
|
4186 | frameCropTopOffset = 0,
|
4187 | frameCropBottomOffset = 0,
|
4188 | sarScale = 1,
|
4189 | expGolombDecoder, profileIdc, levelIdc, profileCompatibility,
|
4190 | chromaFormatIdc, picOrderCntType,
|
4191 | numRefFramesInPicOrderCntCycle, picWidthInMbsMinus1,
|
4192 | picHeightInMapUnitsMinus1,
|
4193 | frameMbsOnlyFlag,
|
4194 | scalingListCount,
|
4195 | sarRatio,
|
4196 | aspectRatioIdc,
|
4197 | i;
|
4198 |
|
4199 | expGolombDecoder = new expGolomb(data);
|
4200 | profileIdc = expGolombDecoder.readUnsignedByte();
|
4201 | profileCompatibility = expGolombDecoder.readUnsignedByte();
|
4202 | levelIdc = expGolombDecoder.readUnsignedByte();
|
4203 | expGolombDecoder.skipUnsignedExpGolomb();
|
4204 |
|
4205 |
|
4206 | if (PROFILES_WITH_OPTIONAL_SPS_DATA[profileIdc]) {
|
4207 | chromaFormatIdc = expGolombDecoder.readUnsignedExpGolomb();
|
4208 | if (chromaFormatIdc === 3) {
|
4209 | expGolombDecoder.skipBits(1);
|
4210 | }
|
4211 | expGolombDecoder.skipUnsignedExpGolomb();
|
4212 | expGolombDecoder.skipUnsignedExpGolomb();
|
4213 | expGolombDecoder.skipBits(1);
|
4214 | if (expGolombDecoder.readBoolean()) {
|
4215 | scalingListCount = (chromaFormatIdc !== 3) ? 8 : 12;
|
4216 | for (i = 0; i < scalingListCount; i++) {
|
4217 | if (expGolombDecoder.readBoolean()) {
|
4218 | if (i < 6) {
|
4219 | skipScalingList(16, expGolombDecoder);
|
4220 | } else {
|
4221 | skipScalingList(64, expGolombDecoder);
|
4222 | }
|
4223 | }
|
4224 | }
|
4225 | }
|
4226 | }
|
4227 |
|
4228 | expGolombDecoder.skipUnsignedExpGolomb();
|
4229 | picOrderCntType = expGolombDecoder.readUnsignedExpGolomb();
|
4230 |
|
4231 | if (picOrderCntType === 0) {
|
4232 | expGolombDecoder.readUnsignedExpGolomb();
|
4233 | } else if (picOrderCntType === 1) {
|
4234 | expGolombDecoder.skipBits(1);
|
4235 | expGolombDecoder.skipExpGolomb();
|
4236 | expGolombDecoder.skipExpGolomb();
|
4237 | numRefFramesInPicOrderCntCycle = expGolombDecoder.readUnsignedExpGolomb();
|
4238 | for (i = 0; i < numRefFramesInPicOrderCntCycle; i++) {
|
4239 | expGolombDecoder.skipExpGolomb();
|
4240 | }
|
4241 | }
|
4242 |
|
4243 | expGolombDecoder.skipUnsignedExpGolomb();
|
4244 | expGolombDecoder.skipBits(1);
|
4245 |
|
4246 | picWidthInMbsMinus1 = expGolombDecoder.readUnsignedExpGolomb();
|
4247 | picHeightInMapUnitsMinus1 = expGolombDecoder.readUnsignedExpGolomb();
|
4248 |
|
4249 | frameMbsOnlyFlag = expGolombDecoder.readBits(1);
|
4250 | if (frameMbsOnlyFlag === 0) {
|
4251 | expGolombDecoder.skipBits(1);
|
4252 | }
|
4253 |
|
4254 | expGolombDecoder.skipBits(1);
|
4255 | if (expGolombDecoder.readBoolean()) {
|
4256 | frameCropLeftOffset = expGolombDecoder.readUnsignedExpGolomb();
|
4257 | frameCropRightOffset = expGolombDecoder.readUnsignedExpGolomb();
|
4258 | frameCropTopOffset = expGolombDecoder.readUnsignedExpGolomb();
|
4259 | frameCropBottomOffset = expGolombDecoder.readUnsignedExpGolomb();
|
4260 | }
|
4261 | if (expGolombDecoder.readBoolean()) {
|
4262 |
|
4263 | if (expGolombDecoder.readBoolean()) {
|
4264 |
|
4265 | aspectRatioIdc = expGolombDecoder.readUnsignedByte();
|
4266 | switch (aspectRatioIdc) {
|
4267 | case 1: sarRatio = [1, 1]; break;
|
4268 | case 2: sarRatio = [12, 11]; break;
|
4269 | case 3: sarRatio = [10, 11]; break;
|
4270 | case 4: sarRatio = [16, 11]; break;
|
4271 | case 5: sarRatio = [40, 33]; break;
|
4272 | case 6: sarRatio = [24, 11]; break;
|
4273 | case 7: sarRatio = [20, 11]; break;
|
4274 | case 8: sarRatio = [32, 11]; break;
|
4275 | case 9: sarRatio = [80, 33]; break;
|
4276 | case 10: sarRatio = [18, 11]; break;
|
4277 | case 11: sarRatio = [15, 11]; break;
|
4278 | case 12: sarRatio = [64, 33]; break;
|
4279 | case 13: sarRatio = [160, 99]; break;
|
4280 | case 14: sarRatio = [4, 3]; break;
|
4281 | case 15: sarRatio = [3, 2]; break;
|
4282 | case 16: sarRatio = [2, 1]; break;
|
4283 | case 255: {
|
4284 | sarRatio = [expGolombDecoder.readUnsignedByte() << 8 |
|
4285 | expGolombDecoder.readUnsignedByte(),
|
4286 | expGolombDecoder.readUnsignedByte() << 8 |
|
4287 | expGolombDecoder.readUnsignedByte() ];
|
4288 | break;
|
4289 | }
|
4290 | }
|
4291 | if (sarRatio) {
|
4292 | sarScale = sarRatio[0] / sarRatio[1];
|
4293 | }
|
4294 | }
|
4295 | }
|
4296 | return {
|
4297 | profileIdc: profileIdc,
|
4298 | levelIdc: levelIdc,
|
4299 | profileCompatibility: profileCompatibility,
|
4300 | width: Math.ceil((((picWidthInMbsMinus1 + 1) * 16) - frameCropLeftOffset * 2 - frameCropRightOffset * 2) * sarScale),
|
4301 | height: ((2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16) - (frameCropTopOffset * 2) - (frameCropBottomOffset * 2),
|
4302 | sarRatio: sarRatio
|
4303 | };
|
4304 | };
|
4305 |
|
4306 | };
|
4307 | H264Stream.prototype = new stream();
|
4308 |
|
4309 | var h264 = {
|
4310 | H264Stream: H264Stream,
|
4311 | NalByteStream: NalByteStream
|
4312 | };
|
4313 |
|
4314 | |
4315 |
|
4316 |
|
4317 |
|
4318 |
|
4319 |
|
4320 |
|
4321 |
|
4322 |
|
4323 | var ADTS_SAMPLING_FREQUENCIES$1 = [
|
4324 | 96000,
|
4325 | 88200,
|
4326 | 64000,
|
4327 | 48000,
|
4328 | 44100,
|
4329 | 32000,
|
4330 | 24000,
|
4331 | 22050,
|
4332 | 16000,
|
4333 | 12000,
|
4334 | 11025,
|
4335 | 8000,
|
4336 | 7350
|
4337 | ];
|
4338 |
|
4339 | var parseId3TagSize = function(header, byteIndex) {
|
4340 | var
|
4341 | returnSize = (header[byteIndex + 6] << 21) |
|
4342 | (header[byteIndex + 7] << 14) |
|
4343 | (header[byteIndex + 8] << 7) |
|
4344 | (header[byteIndex + 9]),
|
4345 | flags = header[byteIndex + 5],
|
4346 | footerPresent = (flags & 16) >> 4;
|
4347 |
|
4348 | if (footerPresent) {
|
4349 | return returnSize + 20;
|
4350 | }
|
4351 | return returnSize + 10;
|
4352 | };
|
4353 |
|
4354 |
|
4355 | var isLikelyAacData = function(data) {
|
4356 | var offset = 0;
|
4357 |
|
4358 | if (data.length > 10 && (data[0] === 'I'.charCodeAt(0)) &&
|
4359 | (data[1] === 'D'.charCodeAt(0)) &&
|
4360 | (data[2] === '3'.charCodeAt(0))) {
|
4361 | offset = parseId3TagSize(data, 0);
|
4362 | }
|
4363 |
|
4364 | return data.length >= offset + 2 &&
|
4365 | (data[offset] & 0xFF) === 0xFF &&
|
4366 | (data[offset + 1] & 0xF0) === 0xF0 &&
|
4367 |
|
4368 |
|
4369 | (data[offset + 1] & 0x16) === 0x10;
|
4370 | };
|
4371 |
|
4372 | var parseSyncSafeInteger$1 = function(data) {
|
4373 | return (data[0] << 21) |
|
4374 | (data[1] << 14) |
|
4375 | (data[2] << 7) |
|
4376 | (data[3]);
|
4377 | };
|
4378 |
|
4379 |
|
4380 |
|
4381 | var percentEncode$1 = function(bytes, start, end) {
|
4382 | var i, result = '';
|
4383 | for (i = start; i < end; i++) {
|
4384 | result += '%' + ('00' + bytes[i].toString(16)).slice(-2);
|
4385 | }
|
4386 | return result;
|
4387 | };
|
4388 |
|
4389 |
|
4390 |
|
4391 | var parseIso88591$1 = function(bytes, start, end) {
|
4392 | return unescape(percentEncode$1(bytes, start, end));
|
4393 | };
|
4394 |
|
4395 | var parseAdtsSize = function(header, byteIndex) {
|
4396 | var
|
4397 | lowThree = (header[byteIndex + 5] & 0xE0) >> 5,
|
4398 | middle = header[byteIndex + 4] << 3,
|
4399 | highTwo = header[byteIndex + 3] & 0x3 << 11;
|
4400 |
|
4401 | return (highTwo | middle) | lowThree;
|
4402 | };
|
4403 |
|
4404 | var parseType = function(header, byteIndex) {
|
4405 | if ((header[byteIndex] === 'I'.charCodeAt(0)) &&
|
4406 | (header[byteIndex + 1] === 'D'.charCodeAt(0)) &&
|
4407 | (header[byteIndex + 2] === '3'.charCodeAt(0))) {
|
4408 | return 'timed-metadata';
|
4409 | } else if ((header[byteIndex] & 0xff === 0xff) &&
|
4410 | ((header[byteIndex + 1] & 0xf0) === 0xf0)) {
|
4411 | return 'audio';
|
4412 | }
|
4413 | return null;
|
4414 | };
|
4415 |
|
4416 | var parseSampleRate = function(packet) {
|
4417 | var i = 0;
|
4418 |
|
4419 | while (i + 5 < packet.length) {
|
4420 | if (packet[i] !== 0xFF || (packet[i + 1] & 0xF6) !== 0xF0) {
|
4421 |
|
4422 |
|
4423 | i++;
|
4424 | continue;
|
4425 | }
|
4426 | return ADTS_SAMPLING_FREQUENCIES$1[(packet[i + 2] & 0x3c) >>> 2];
|
4427 | }
|
4428 |
|
4429 | return null;
|
4430 | };
|
4431 |
|
4432 | var parseAacTimestamp = function(packet) {
|
4433 | var frameStart, frameSize, frame, frameHeader;
|
4434 |
|
4435 |
|
4436 | frameStart = 10;
|
4437 | if (packet[5] & 0x40) {
|
4438 |
|
4439 | frameStart += 4;
|
4440 | frameStart += parseSyncSafeInteger$1(packet.subarray(10, 14));
|
4441 | }
|
4442 |
|
4443 |
|
4444 |
|
4445 | do {
|
4446 |
|
4447 | frameSize = parseSyncSafeInteger$1(packet.subarray(frameStart + 4, frameStart + 8));
|
4448 | if (frameSize < 1) {
|
4449 | return null;
|
4450 | }
|
4451 | frameHeader = String.fromCharCode(packet[frameStart],
|
4452 | packet[frameStart + 1],
|
4453 | packet[frameStart + 2],
|
4454 | packet[frameStart + 3]);
|
4455 |
|
4456 | if (frameHeader === 'PRIV') {
|
4457 | frame = packet.subarray(frameStart + 10, frameStart + frameSize + 10);
|
4458 |
|
4459 | for (var i = 0; i < frame.byteLength; i++) {
|
4460 | if (frame[i] === 0) {
|
4461 | var owner = parseIso88591$1(frame, 0, i);
|
4462 | if (owner === 'com.apple.streaming.transportStreamTimestamp') {
|
4463 | var d = frame.subarray(i + 1);
|
4464 | var size = ((d[3] & 0x01) << 30) |
|
4465 | (d[4] << 22) |
|
4466 | (d[5] << 14) |
|
4467 | (d[6] << 6) |
|
4468 | (d[7] >>> 2);
|
4469 | size *= 4;
|
4470 | size += d[7] & 0x03;
|
4471 |
|
4472 | return size;
|
4473 | }
|
4474 | break;
|
4475 | }
|
4476 | }
|
4477 | }
|
4478 |
|
4479 | frameStart += 10;
|
4480 | frameStart += frameSize;
|
4481 | } while (frameStart < packet.byteLength);
|
4482 | return null;
|
4483 | };
|
4484 |
|
4485 | var utils = {
|
4486 | isLikelyAacData: isLikelyAacData,
|
4487 | parseId3TagSize: parseId3TagSize,
|
4488 | parseAdtsSize: parseAdtsSize,
|
4489 | parseType: parseType,
|
4490 | parseSampleRate: parseSampleRate,
|
4491 | parseAacTimestamp: parseAacTimestamp
|
4492 | };
|
4493 |
|
4494 |
|
4495 | var AacStream;
|
4496 |
|
4497 | |
4498 |
|
4499 |
|
4500 |
|
4501 | AacStream = function() {
|
4502 | var
|
4503 | everything = new Uint8Array(),
|
4504 | timeStamp = 0;
|
4505 |
|
4506 | AacStream.prototype.init.call(this);
|
4507 |
|
4508 | this.setTimestamp = function(timestamp) {
|
4509 | timeStamp = timestamp;
|
4510 | };
|
4511 |
|
4512 | this.push = function(bytes) {
|
4513 | var
|
4514 | frameSize = 0,
|
4515 | byteIndex = 0,
|
4516 | bytesLeft,
|
4517 | chunk,
|
4518 | packet,
|
4519 | tempLength;
|
4520 |
|
4521 |
|
4522 |
|
4523 | if (everything.length) {
|
4524 | tempLength = everything.length;
|
4525 | everything = new Uint8Array(bytes.byteLength + tempLength);
|
4526 | everything.set(everything.subarray(0, tempLength));
|
4527 | everything.set(bytes, tempLength);
|
4528 | } else {
|
4529 | everything = bytes;
|
4530 | }
|
4531 |
|
4532 | while (everything.length - byteIndex >= 3) {
|
4533 | if ((everything[byteIndex] === 'I'.charCodeAt(0)) &&
|
4534 | (everything[byteIndex + 1] === 'D'.charCodeAt(0)) &&
|
4535 | (everything[byteIndex + 2] === '3'.charCodeAt(0))) {
|
4536 |
|
4537 |
|
4538 |
|
4539 | if (everything.length - byteIndex < 10) {
|
4540 | break;
|
4541 | }
|
4542 |
|
4543 |
|
4544 | frameSize = utils.parseId3TagSize(everything, byteIndex);
|
4545 |
|
4546 |
|
4547 |
|
4548 |
|
4549 | if (byteIndex + frameSize > everything.length) {
|
4550 | break;
|
4551 | }
|
4552 | chunk = {
|
4553 | type: 'timed-metadata',
|
4554 | data: everything.subarray(byteIndex, byteIndex + frameSize)
|
4555 | };
|
4556 | this.trigger('data', chunk);
|
4557 | byteIndex += frameSize;
|
4558 | continue;
|
4559 | } else if (((everything[byteIndex] & 0xff) === 0xff) &&
|
4560 | ((everything[byteIndex + 1] & 0xf0) === 0xf0)) {
|
4561 |
|
4562 |
|
4563 |
|
4564 | if (everything.length - byteIndex < 7) {
|
4565 | break;
|
4566 | }
|
4567 |
|
4568 | frameSize = utils.parseAdtsSize(everything, byteIndex);
|
4569 |
|
4570 |
|
4571 |
|
4572 | if (byteIndex + frameSize > everything.length) {
|
4573 | break;
|
4574 | }
|
4575 |
|
4576 | packet = {
|
4577 | type: 'audio',
|
4578 | data: everything.subarray(byteIndex, byteIndex + frameSize),
|
4579 | pts: timeStamp,
|
4580 | dts: timeStamp
|
4581 | };
|
4582 | this.trigger('data', packet);
|
4583 | byteIndex += frameSize;
|
4584 | continue;
|
4585 | }
|
4586 | byteIndex++;
|
4587 | }
|
4588 | bytesLeft = everything.length - byteIndex;
|
4589 |
|
4590 | if (bytesLeft > 0) {
|
4591 | everything = everything.subarray(byteIndex);
|
4592 | } else {
|
4593 | everything = new Uint8Array();
|
4594 | }
|
4595 | };
|
4596 |
|
4597 | this.reset = function() {
|
4598 | everything = new Uint8Array();
|
4599 | this.trigger('reset');
|
4600 | };
|
4601 |
|
4602 | this.endTimeline = function() {
|
4603 | everything = new Uint8Array();
|
4604 | this.trigger('endedtimeline');
|
4605 | };
|
4606 | };
|
4607 |
|
4608 | AacStream.prototype = new stream();
|
4609 |
|
4610 | var aac = AacStream;
|
4611 |
|
4612 |
|
4613 | var AUDIO_PROPERTIES = [
|
4614 | 'audioobjecttype',
|
4615 | 'channelcount',
|
4616 | 'samplerate',
|
4617 | 'samplingfrequencyindex',
|
4618 | 'samplesize'
|
4619 | ];
|
4620 |
|
4621 | var audioProperties = AUDIO_PROPERTIES;
|
4622 |
|
4623 | var VIDEO_PROPERTIES = [
|
4624 | 'width',
|
4625 | 'height',
|
4626 | 'profileIdc',
|
4627 | 'levelIdc',
|
4628 | 'profileCompatibility',
|
4629 | 'sarRatio'
|
4630 | ];
|
4631 |
|
4632 |
|
4633 | var videoProperties = VIDEO_PROPERTIES;
|
4634 |
|
4635 | var H264Stream$1 = h264.H264Stream;
|
4636 |
|
4637 | var isLikelyAacData$1 = utils.isLikelyAacData;
|
4638 | var ONE_SECOND_IN_TS$3 = clock.ONE_SECOND_IN_TS;
|
4639 |
|
4640 |
|
4641 |
|
4642 |
|
4643 | var VideoSegmentStream, AudioSegmentStream, Transmuxer, CoalesceStream;
|
4644 |
|
4645 | |
4646 |
|
4647 |
|
4648 | var arrayEquals = function(a, b) {
|
4649 | var
|
4650 | i;
|
4651 |
|
4652 | if (a.length !== b.length) {
|
4653 | return false;
|
4654 | }
|
4655 |
|
4656 |
|
4657 | for (i = 0; i < a.length; i++) {
|
4658 | if (a[i] !== b[i]) {
|
4659 | return false;
|
4660 | }
|
4661 | }
|
4662 |
|
4663 | return true;
|
4664 | };
|
4665 |
|
4666 | var generateVideoSegmentTimingInfo = function(
|
4667 | baseMediaDecodeTime,
|
4668 | startDts,
|
4669 | startPts,
|
4670 | endDts,
|
4671 | endPts,
|
4672 | prependedContentDuration
|
4673 | ) {
|
4674 | var
|
4675 | ptsOffsetFromDts = startPts - startDts,
|
4676 | decodeDuration = endDts - startDts,
|
4677 | presentationDuration = endPts - startPts;
|
4678 |
|
4679 |
|
4680 |
|
4681 |
|
4682 |
|
4683 | return {
|
4684 | start: {
|
4685 | dts: baseMediaDecodeTime,
|
4686 | pts: baseMediaDecodeTime + ptsOffsetFromDts
|
4687 | },
|
4688 | end: {
|
4689 | dts: baseMediaDecodeTime + decodeDuration,
|
4690 | pts: baseMediaDecodeTime + presentationDuration
|
4691 | },
|
4692 | prependedContentDuration: prependedContentDuration,
|
4693 | baseMediaDecodeTime: baseMediaDecodeTime
|
4694 | };
|
4695 | };
|
4696 |
|
4697 | |
4698 |
|
4699 |
|
4700 |
|
4701 |
|
4702 |
|
4703 |
|
4704 |
|
4705 |
|
4706 | AudioSegmentStream = function(track, options) {
|
4707 | var
|
4708 | adtsFrames = [],
|
4709 | sequenceNumber = 0,
|
4710 | earliestAllowedDts = 0,
|
4711 | audioAppendStartTs = 0,
|
4712 | videoBaseMediaDecodeTime = Infinity;
|
4713 |
|
4714 | options = options || {};
|
4715 |
|
4716 | AudioSegmentStream.prototype.init.call(this);
|
4717 |
|
4718 | this.push = function(data) {
|
4719 | trackDecodeInfo.collectDtsInfo(track, data);
|
4720 |
|
4721 | if (track) {
|
4722 | audioProperties.forEach(function(prop) {
|
4723 | track[prop] = data[prop];
|
4724 | });
|
4725 | }
|
4726 |
|
4727 |
|
4728 | adtsFrames.push(data);
|
4729 | };
|
4730 |
|
4731 | this.setEarliestDts = function(earliestDts) {
|
4732 | earliestAllowedDts = earliestDts;
|
4733 | };
|
4734 |
|
4735 | this.setVideoBaseMediaDecodeTime = function(baseMediaDecodeTime) {
|
4736 | videoBaseMediaDecodeTime = baseMediaDecodeTime;
|
4737 | };
|
4738 |
|
4739 | this.setAudioAppendStart = function(timestamp) {
|
4740 | audioAppendStartTs = timestamp;
|
4741 | };
|
4742 |
|
4743 | this.flush = function() {
|
4744 | var
|
4745 | frames,
|
4746 | moof,
|
4747 | mdat,
|
4748 | boxes,
|
4749 | frameDuration;
|
4750 |
|
4751 |
|
4752 | if (adtsFrames.length === 0) {
|
4753 | this.trigger('done', 'AudioSegmentStream');
|
4754 | return;
|
4755 | }
|
4756 |
|
4757 | frames = audioFrameUtils.trimAdtsFramesByEarliestDts(
|
4758 | adtsFrames, track, earliestAllowedDts);
|
4759 | track.baseMediaDecodeTime = trackDecodeInfo.calculateTrackBaseMediaDecodeTime(
|
4760 | track, options.keepOriginalTimestamps);
|
4761 |
|
4762 | audioFrameUtils.prefixWithSilence(
|
4763 | track, frames, audioAppendStartTs, videoBaseMediaDecodeTime);
|
4764 |
|
4765 |
|
4766 |
|
4767 | track.samples = audioFrameUtils.generateSampleTable(frames);
|
4768 |
|
4769 |
|
4770 | mdat = mp4Generator.mdat(audioFrameUtils.concatenateFrameData(frames));
|
4771 |
|
4772 | adtsFrames = [];
|
4773 |
|
4774 | moof = mp4Generator.moof(sequenceNumber, [track]);
|
4775 | boxes = new Uint8Array(moof.byteLength + mdat.byteLength);
|
4776 |
|
4777 |
|
4778 | sequenceNumber++;
|
4779 |
|
4780 | boxes.set(moof);
|
4781 | boxes.set(mdat, moof.byteLength);
|
4782 |
|
4783 | trackDecodeInfo.clearDtsInfo(track);
|
4784 |
|
4785 | frameDuration = Math.ceil(ONE_SECOND_IN_TS$3 * 1024 / track.samplerate);
|
4786 |
|
4787 |
|
4788 |
|
4789 |
|
4790 |
|
4791 | if (frames.length) {
|
4792 | this.trigger('timingInfo', {
|
4793 | start: frames[0].pts,
|
4794 | end: frames[0].pts + (frames.length * frameDuration)
|
4795 | });
|
4796 | }
|
4797 | this.trigger('data', {track: track, boxes: boxes});
|
4798 | this.trigger('done', 'AudioSegmentStream');
|
4799 | };
|
4800 |
|
4801 | this.reset = function() {
|
4802 | trackDecodeInfo.clearDtsInfo(track);
|
4803 | adtsFrames = [];
|
4804 | this.trigger('reset');
|
4805 | };
|
4806 | };
|
4807 |
|
4808 | AudioSegmentStream.prototype = new stream();
|
4809 |
|
4810 | |
4811 |
|
4812 |
|
4813 |
|
4814 |
|
4815 |
|
4816 |
|
4817 |
|
4818 |
|
4819 |
|
4820 |
|
4821 | VideoSegmentStream = function(track, options) {
|
4822 | var
|
4823 | sequenceNumber = 0,
|
4824 | nalUnits = [],
|
4825 | gopsToAlignWith = [],
|
4826 | config,
|
4827 | pps;
|
4828 |
|
4829 | options = options || {};
|
4830 |
|
4831 | VideoSegmentStream.prototype.init.call(this);
|
4832 |
|
4833 | delete track.minPTS;
|
4834 |
|
4835 | this.gopCache_ = [];
|
4836 |
|
4837 | |
4838 |
|
4839 |
|
4840 |
|
4841 |
|
4842 |
|
4843 |
|
4844 |
|
4845 | this.push = function(nalUnit) {
|
4846 | trackDecodeInfo.collectDtsInfo(track, nalUnit);
|
4847 |
|
4848 |
|
4849 | if (nalUnit.nalUnitType === 'seq_parameter_set_rbsp' && !config) {
|
4850 | config = nalUnit.config;
|
4851 | track.sps = [nalUnit.data];
|
4852 |
|
4853 | videoProperties.forEach(function(prop) {
|
4854 | track[prop] = config[prop];
|
4855 | }, this);
|
4856 | }
|
4857 |
|
4858 | if (nalUnit.nalUnitType === 'pic_parameter_set_rbsp' &&
|
4859 | !pps) {
|
4860 | pps = nalUnit.data;
|
4861 | track.pps = [nalUnit.data];
|
4862 | }
|
4863 |
|
4864 |
|
4865 | nalUnits.push(nalUnit);
|
4866 | };
|
4867 |
|
4868 | |
4869 |
|
4870 |
|
4871 |
|
4872 | this.flush = function() {
|
4873 | var
|
4874 | frames,
|
4875 | gopForFusion,
|
4876 | gops,
|
4877 | moof,
|
4878 | mdat,
|
4879 | boxes,
|
4880 | prependedContentDuration = 0,
|
4881 | firstGop,
|
4882 | lastGop;
|
4883 |
|
4884 |
|
4885 |
|
4886 | while (nalUnits.length) {
|
4887 | if (nalUnits[0].nalUnitType === 'access_unit_delimiter_rbsp') {
|
4888 | break;
|
4889 | }
|
4890 | nalUnits.shift();
|
4891 | }
|
4892 |
|
4893 |
|
4894 | if (nalUnits.length === 0) {
|
4895 | this.resetStream_();
|
4896 | this.trigger('done', 'VideoSegmentStream');
|
4897 | return;
|
4898 | }
|
4899 |
|
4900 |
|
4901 |
|
4902 |
|
4903 | frames = frameUtils.groupNalsIntoFrames(nalUnits);
|
4904 | gops = frameUtils.groupFramesIntoGops(frames);
|
4905 |
|
4906 |
|
4907 |
|
4908 |
|
4909 |
|
4910 |
|
4911 |
|
4912 |
|
4913 |
|
4914 |
|
4915 |
|
4916 |
|
4917 |
|
4918 |
|
4919 |
|
4920 |
|
4921 |
|
4922 |
|
4923 |
|
4924 | if (!gops[0][0].keyFrame) {
|
4925 |
|
4926 | gopForFusion = this.getGopForFusion_(nalUnits[0], track);
|
4927 |
|
4928 | if (gopForFusion) {
|
4929 |
|
4930 |
|
4931 | prependedContentDuration = gopForFusion.duration;
|
4932 |
|
4933 | gops.unshift(gopForFusion);
|
4934 |
|
4935 |
|
4936 | gops.byteLength += gopForFusion.byteLength;
|
4937 | gops.nalCount += gopForFusion.nalCount;
|
4938 | gops.pts = gopForFusion.pts;
|
4939 | gops.dts = gopForFusion.dts;
|
4940 | gops.duration += gopForFusion.duration;
|
4941 | } else {
|
4942 |
|
4943 | gops = frameUtils.extendFirstKeyFrame(gops);
|
4944 | }
|
4945 | }
|
4946 |
|
4947 |
|
4948 | if (gopsToAlignWith.length) {
|
4949 | var alignedGops;
|
4950 |
|
4951 | if (options.alignGopsAtEnd) {
|
4952 | alignedGops = this.alignGopsAtEnd_(gops);
|
4953 | } else {
|
4954 | alignedGops = this.alignGopsAtStart_(gops);
|
4955 | }
|
4956 |
|
4957 | if (!alignedGops) {
|
4958 |
|
4959 | this.gopCache_.unshift({
|
4960 | gop: gops.pop(),
|
4961 | pps: track.pps,
|
4962 | sps: track.sps
|
4963 | });
|
4964 |
|
4965 |
|
4966 | this.gopCache_.length = Math.min(6, this.gopCache_.length);
|
4967 |
|
4968 |
|
4969 | nalUnits = [];
|
4970 |
|
4971 |
|
4972 | this.resetStream_();
|
4973 | this.trigger('done', 'VideoSegmentStream');
|
4974 | return;
|
4975 | }
|
4976 |
|
4977 |
|
4978 |
|
4979 | trackDecodeInfo.clearDtsInfo(track);
|
4980 |
|
4981 | gops = alignedGops;
|
4982 | }
|
4983 |
|
4984 | trackDecodeInfo.collectDtsInfo(track, gops);
|
4985 |
|
4986 |
|
4987 |
|
4988 | track.samples = frameUtils.generateSampleTable(gops);
|
4989 |
|
4990 |
|
4991 | mdat = mp4Generator.mdat(frameUtils.concatenateNalData(gops));
|
4992 |
|
4993 | track.baseMediaDecodeTime = trackDecodeInfo.calculateTrackBaseMediaDecodeTime(
|
4994 | track, options.keepOriginalTimestamps);
|
4995 |
|
4996 | this.trigger('processedGopsInfo', gops.map(function(gop) {
|
4997 | return {
|
4998 | pts: gop.pts,
|
4999 | dts: gop.dts,
|
5000 | byteLength: gop.byteLength
|
5001 | };
|
5002 | }));
|
5003 |
|
5004 | firstGop = gops[0];
|
5005 | lastGop = gops[gops.length - 1];
|
5006 |
|
5007 | this.trigger(
|
5008 | 'segmentTimingInfo',
|
5009 | generateVideoSegmentTimingInfo(
|
5010 | track.baseMediaDecodeTime,
|
5011 | firstGop.dts,
|
5012 | firstGop.pts,
|
5013 | lastGop.dts + lastGop.duration,
|
5014 | lastGop.pts + lastGop.duration,
|
5015 | prependedContentDuration));
|
5016 |
|
5017 | this.trigger('timingInfo', {
|
5018 | start: gops[0].pts,
|
5019 | end: gops[gops.length - 1].pts + gops[gops.length - 1].duration
|
5020 | });
|
5021 |
|
5022 |
|
5023 | this.gopCache_.unshift({
|
5024 | gop: gops.pop(),
|
5025 | pps: track.pps,
|
5026 | sps: track.sps
|
5027 | });
|
5028 |
|
5029 |
|
5030 | this.gopCache_.length = Math.min(6, this.gopCache_.length);
|
5031 |
|
5032 |
|
5033 | nalUnits = [];
|
5034 |
|
5035 | this.trigger('baseMediaDecodeTime', track.baseMediaDecodeTime);
|
5036 | this.trigger('timelineStartInfo', track.timelineStartInfo);
|
5037 |
|
5038 | moof = mp4Generator.moof(sequenceNumber, [track]);
|
5039 |
|
5040 |
|
5041 |
|
5042 | boxes = new Uint8Array(moof.byteLength + mdat.byteLength);
|
5043 |
|
5044 |
|
5045 | sequenceNumber++;
|
5046 |
|
5047 | boxes.set(moof);
|
5048 | boxes.set(mdat, moof.byteLength);
|
5049 |
|
5050 | this.trigger('data', {track: track, boxes: boxes});
|
5051 |
|
5052 | this.resetStream_();
|
5053 |
|
5054 |
|
5055 | this.trigger('done', 'VideoSegmentStream');
|
5056 | };
|
5057 |
|
5058 | this.reset = function() {
|
5059 | this.resetStream_();
|
5060 | nalUnits = [];
|
5061 | this.gopCache_.length = 0;
|
5062 | gopsToAlignWith.length = 0;
|
5063 | this.trigger('reset');
|
5064 | };
|
5065 |
|
5066 | this.resetStream_ = function() {
|
5067 | trackDecodeInfo.clearDtsInfo(track);
|
5068 |
|
5069 |
|
5070 |
|
5071 | config = undefined;
|
5072 | pps = undefined;
|
5073 | };
|
5074 |
|
5075 |
|
5076 |
|
5077 | this.getGopForFusion_ = function(nalUnit) {
|
5078 | var
|
5079 | halfSecond = 45000,
|
5080 | allowableOverlap = 10000,
|
5081 | nearestDistance = Infinity,
|
5082 | dtsDistance,
|
5083 | nearestGopObj,
|
5084 | currentGop,
|
5085 | currentGopObj,
|
5086 | i;
|
5087 |
|
5088 |
|
5089 | for (i = 0; i < this.gopCache_.length; i++) {
|
5090 | currentGopObj = this.gopCache_[i];
|
5091 | currentGop = currentGopObj.gop;
|
5092 |
|
5093 |
|
5094 | if (!(track.pps && arrayEquals(track.pps[0], currentGopObj.pps[0])) ||
|
5095 | !(track.sps && arrayEquals(track.sps[0], currentGopObj.sps[0]))) {
|
5096 | continue;
|
5097 | }
|
5098 |
|
5099 |
|
5100 | if (currentGop.dts < track.timelineStartInfo.dts) {
|
5101 | continue;
|
5102 | }
|
5103 |
|
5104 |
|
5105 | dtsDistance = (nalUnit.dts - currentGop.dts) - currentGop.duration;
|
5106 |
|
5107 |
|
5108 |
|
5109 | if (dtsDistance >= -allowableOverlap &&
|
5110 | dtsDistance <= halfSecond) {
|
5111 |
|
5112 |
|
5113 |
|
5114 | if (!nearestGopObj ||
|
5115 | nearestDistance > dtsDistance) {
|
5116 | nearestGopObj = currentGopObj;
|
5117 | nearestDistance = dtsDistance;
|
5118 | }
|
5119 | }
|
5120 | }
|
5121 |
|
5122 | if (nearestGopObj) {
|
5123 | return nearestGopObj.gop;
|
5124 | }
|
5125 | return null;
|
5126 | };
|
5127 |
|
5128 |
|
5129 |
|
5130 | this.alignGopsAtStart_ = function(gops) {
|
5131 | var alignIndex, gopIndex, align, gop, byteLength, nalCount, duration, alignedGops;
|
5132 |
|
5133 | byteLength = gops.byteLength;
|
5134 | nalCount = gops.nalCount;
|
5135 | duration = gops.duration;
|
5136 | alignIndex = gopIndex = 0;
|
5137 |
|
5138 | while (alignIndex < gopsToAlignWith.length && gopIndex < gops.length) {
|
5139 | align = gopsToAlignWith[alignIndex];
|
5140 | gop = gops[gopIndex];
|
5141 |
|
5142 | if (align.pts === gop.pts) {
|
5143 | break;
|
5144 | }
|
5145 |
|
5146 | if (gop.pts > align.pts) {
|
5147 |
|
5148 |
|
5149 | alignIndex++;
|
5150 | continue;
|
5151 | }
|
5152 |
|
5153 |
|
5154 |
|
5155 | gopIndex++;
|
5156 | byteLength -= gop.byteLength;
|
5157 | nalCount -= gop.nalCount;
|
5158 | duration -= gop.duration;
|
5159 | }
|
5160 |
|
5161 | if (gopIndex === 0) {
|
5162 |
|
5163 | return gops;
|
5164 | }
|
5165 |
|
5166 | if (gopIndex === gops.length) {
|
5167 |
|
5168 | return null;
|
5169 | }
|
5170 |
|
5171 | alignedGops = gops.slice(gopIndex);
|
5172 | alignedGops.byteLength = byteLength;
|
5173 | alignedGops.duration = duration;
|
5174 | alignedGops.nalCount = nalCount;
|
5175 | alignedGops.pts = alignedGops[0].pts;
|
5176 | alignedGops.dts = alignedGops[0].dts;
|
5177 |
|
5178 | return alignedGops;
|
5179 | };
|
5180 |
|
5181 |
|
5182 |
|
5183 | this.alignGopsAtEnd_ = function(gops) {
|
5184 | var alignIndex, gopIndex, align, gop, alignEndIndex, matchFound;
|
5185 |
|
5186 | alignIndex = gopsToAlignWith.length - 1;
|
5187 | gopIndex = gops.length - 1;
|
5188 | alignEndIndex = null;
|
5189 | matchFound = false;
|
5190 |
|
5191 | while (alignIndex >= 0 && gopIndex >= 0) {
|
5192 | align = gopsToAlignWith[alignIndex];
|
5193 | gop = gops[gopIndex];
|
5194 |
|
5195 | if (align.pts === gop.pts) {
|
5196 | matchFound = true;
|
5197 | break;
|
5198 | }
|
5199 |
|
5200 | if (align.pts > gop.pts) {
|
5201 | alignIndex--;
|
5202 | continue;
|
5203 | }
|
5204 |
|
5205 | if (alignIndex === gopsToAlignWith.length - 1) {
|
5206 |
|
5207 |
|
5208 |
|
5209 | alignEndIndex = gopIndex;
|
5210 | }
|
5211 |
|
5212 | gopIndex--;
|
5213 | }
|
5214 |
|
5215 | if (!matchFound && alignEndIndex === null) {
|
5216 | return null;
|
5217 | }
|
5218 |
|
5219 | var trimIndex;
|
5220 |
|
5221 | if (matchFound) {
|
5222 | trimIndex = gopIndex;
|
5223 | } else {
|
5224 | trimIndex = alignEndIndex;
|
5225 | }
|
5226 |
|
5227 | if (trimIndex === 0) {
|
5228 | return gops;
|
5229 | }
|
5230 |
|
5231 | var alignedGops = gops.slice(trimIndex);
|
5232 | var metadata = alignedGops.reduce(function(total, gop) {
|
5233 | total.byteLength += gop.byteLength;
|
5234 | total.duration += gop.duration;
|
5235 | total.nalCount += gop.nalCount;
|
5236 | return total;
|
5237 | }, { byteLength: 0, duration: 0, nalCount: 0 });
|
5238 |
|
5239 | alignedGops.byteLength = metadata.byteLength;
|
5240 | alignedGops.duration = metadata.duration;
|
5241 | alignedGops.nalCount = metadata.nalCount;
|
5242 | alignedGops.pts = alignedGops[0].pts;
|
5243 | alignedGops.dts = alignedGops[0].dts;
|
5244 |
|
5245 | return alignedGops;
|
5246 | };
|
5247 |
|
5248 | this.alignGopsWith = function(newGopsToAlignWith) {
|
5249 | gopsToAlignWith = newGopsToAlignWith;
|
5250 | };
|
5251 | };
|
5252 |
|
5253 | VideoSegmentStream.prototype = new stream();
|
5254 |
|
5255 | |
5256 |
|
5257 |
|
5258 |
|
5259 |
|
5260 |
|
5261 |
|
5262 |
|
5263 | CoalesceStream = function(options, metadataStream) {
|
5264 |
|
5265 |
|
5266 |
|
5267 | this.numberOfTracks = 0;
|
5268 | this.metadataStream = metadataStream;
|
5269 |
|
5270 | options = options || {};
|
5271 |
|
5272 | if (typeof options.remux !== 'undefined') {
|
5273 | this.remuxTracks = !!options.remux;
|
5274 | } else {
|
5275 | this.remuxTracks = true;
|
5276 | }
|
5277 |
|
5278 | if (typeof options.keepOriginalTimestamps === 'boolean') {
|
5279 | this.keepOriginalTimestamps = options.keepOriginalTimestamps;
|
5280 | } else {
|
5281 | this.keepOriginalTimestamps = false;
|
5282 | }
|
5283 |
|
5284 | this.pendingTracks = [];
|
5285 | this.videoTrack = null;
|
5286 | this.pendingBoxes = [];
|
5287 | this.pendingCaptions = [];
|
5288 | this.pendingMetadata = [];
|
5289 | this.pendingBytes = 0;
|
5290 | this.emittedTracks = 0;
|
5291 |
|
5292 | CoalesceStream.prototype.init.call(this);
|
5293 |
|
5294 |
|
5295 | this.push = function(output) {
|
5296 |
|
5297 |
|
5298 | if (output.text) {
|
5299 | return this.pendingCaptions.push(output);
|
5300 | }
|
5301 |
|
5302 | if (output.frames) {
|
5303 | return this.pendingMetadata.push(output);
|
5304 | }
|
5305 |
|
5306 |
|
5307 |
|
5308 |
|
5309 | this.pendingTracks.push(output.track);
|
5310 | this.pendingBytes += output.boxes.byteLength;
|
5311 |
|
5312 |
|
5313 |
|
5314 |
|
5315 |
|
5316 |
|
5317 |
|
5318 | if (output.track.type === 'video') {
|
5319 | this.videoTrack = output.track;
|
5320 | this.pendingBoxes.push(output.boxes);
|
5321 | }
|
5322 | if (output.track.type === 'audio') {
|
5323 | this.audioTrack = output.track;
|
5324 | this.pendingBoxes.unshift(output.boxes);
|
5325 | }
|
5326 | };
|
5327 | };
|
5328 |
|
5329 | CoalesceStream.prototype = new stream();
|
5330 | CoalesceStream.prototype.flush = function(flushSource) {
|
5331 | var
|
5332 | offset = 0,
|
5333 | event = {
|
5334 | captions: [],
|
5335 | captionStreams: {},
|
5336 | metadata: [],
|
5337 | info: {}
|
5338 | },
|
5339 | caption,
|
5340 | id3,
|
5341 | initSegment,
|
5342 | timelineStartPts = 0,
|
5343 | i;
|
5344 |
|
5345 | if (this.pendingTracks.length < this.numberOfTracks) {
|
5346 | if (flushSource !== 'VideoSegmentStream' &&
|
5347 | flushSource !== 'AudioSegmentStream') {
|
5348 |
|
5349 |
|
5350 |
|
5351 | return;
|
5352 | } else if (this.remuxTracks) {
|
5353 |
|
5354 |
|
5355 | return;
|
5356 | } else if (this.pendingTracks.length === 0) {
|
5357 |
|
5358 |
|
5359 |
|
5360 |
|
5361 |
|
5362 |
|
5363 | this.emittedTracks++;
|
5364 |
|
5365 | if (this.emittedTracks >= this.numberOfTracks) {
|
5366 | this.trigger('done');
|
5367 | this.emittedTracks = 0;
|
5368 | }
|
5369 | return;
|
5370 | }
|
5371 | }
|
5372 |
|
5373 | if (this.videoTrack) {
|
5374 | timelineStartPts = this.videoTrack.timelineStartInfo.pts;
|
5375 | videoProperties.forEach(function(prop) {
|
5376 | event.info[prop] = this.videoTrack[prop];
|
5377 | }, this);
|
5378 | } else if (this.audioTrack) {
|
5379 | timelineStartPts = this.audioTrack.timelineStartInfo.pts;
|
5380 | audioProperties.forEach(function(prop) {
|
5381 | event.info[prop] = this.audioTrack[prop];
|
5382 | }, this);
|
5383 | }
|
5384 |
|
5385 | if (this.videoTrack || this.audioTrack) {
|
5386 | if (this.pendingTracks.length === 1) {
|
5387 | event.type = this.pendingTracks[0].type;
|
5388 | } else {
|
5389 | event.type = 'combined';
|
5390 | }
|
5391 |
|
5392 | this.emittedTracks += this.pendingTracks.length;
|
5393 |
|
5394 | initSegment = mp4Generator.initSegment(this.pendingTracks);
|
5395 |
|
5396 |
|
5397 | event.initSegment = new Uint8Array(initSegment.byteLength);
|
5398 |
|
5399 |
|
5400 |
|
5401 | event.initSegment.set(initSegment);
|
5402 |
|
5403 |
|
5404 | event.data = new Uint8Array(this.pendingBytes);
|
5405 |
|
5406 |
|
5407 | for (i = 0; i < this.pendingBoxes.length; i++) {
|
5408 | event.data.set(this.pendingBoxes[i], offset);
|
5409 | offset += this.pendingBoxes[i].byteLength;
|
5410 | }
|
5411 |
|
5412 |
|
5413 |
|
5414 | for (i = 0; i < this.pendingCaptions.length; i++) {
|
5415 | caption = this.pendingCaptions[i];
|
5416 | caption.startTime = clock.metadataTsToSeconds(
|
5417 | caption.startPts, timelineStartPts, this.keepOriginalTimestamps);
|
5418 | caption.endTime = clock.metadataTsToSeconds(
|
5419 | caption.endPts, timelineStartPts, this.keepOriginalTimestamps);
|
5420 |
|
5421 | event.captionStreams[caption.stream] = true;
|
5422 | event.captions.push(caption);
|
5423 | }
|
5424 |
|
5425 |
|
5426 |
|
5427 | for (i = 0; i < this.pendingMetadata.length; i++) {
|
5428 | id3 = this.pendingMetadata[i];
|
5429 | id3.cueTime = clock.metadataTsToSeconds(
|
5430 | id3.pts, timelineStartPts, this.keepOriginalTimestamps);
|
5431 |
|
5432 | event.metadata.push(id3);
|
5433 | }
|
5434 |
|
5435 |
|
5436 |
|
5437 | event.metadata.dispatchType = this.metadataStream.dispatchType;
|
5438 |
|
5439 |
|
5440 | this.pendingTracks.length = 0;
|
5441 | this.videoTrack = null;
|
5442 | this.pendingBoxes.length = 0;
|
5443 | this.pendingCaptions.length = 0;
|
5444 | this.pendingBytes = 0;
|
5445 | this.pendingMetadata.length = 0;
|
5446 |
|
5447 |
|
5448 |
|
5449 |
|
5450 | this.trigger('data', event);
|
5451 |
|
5452 |
|
5453 |
|
5454 |
|
5455 | for (i = 0; i < event.captions.length; i++) {
|
5456 | caption = event.captions[i];
|
5457 |
|
5458 | this.trigger('caption', caption);
|
5459 | }
|
5460 |
|
5461 |
|
5462 |
|
5463 |
|
5464 | for (i = 0; i < event.metadata.length; i++) {
|
5465 | id3 = event.metadata[i];
|
5466 |
|
5467 | this.trigger('id3Frame', id3);
|
5468 | }
|
5469 | }
|
5470 |
|
5471 |
|
5472 | if (this.emittedTracks >= this.numberOfTracks) {
|
5473 | this.trigger('done');
|
5474 | this.emittedTracks = 0;
|
5475 | }
|
5476 | };
|
5477 |
|
5478 | CoalesceStream.prototype.setRemux = function(val) {
|
5479 | this.remuxTracks = val;
|
5480 | };
|
5481 | |
5482 |
|
5483 |
|
5484 |
|
5485 |
|
5486 |
|
5487 | Transmuxer = function(options) {
|
5488 | var
|
5489 | self = this,
|
5490 | hasFlushed = true,
|
5491 | videoTrack,
|
5492 | audioTrack;
|
5493 |
|
5494 | Transmuxer.prototype.init.call(this);
|
5495 |
|
5496 | options = options || {};
|
5497 | this.baseMediaDecodeTime = options.baseMediaDecodeTime || 0;
|
5498 | this.transmuxPipeline_ = {};
|
5499 |
|
5500 | this.setupAacPipeline = function() {
|
5501 | var pipeline = {};
|
5502 | this.transmuxPipeline_ = pipeline;
|
5503 |
|
5504 | pipeline.type = 'aac';
|
5505 | pipeline.metadataStream = new m2ts_1.MetadataStream();
|
5506 |
|
5507 |
|
5508 | pipeline.aacStream = new aac();
|
5509 | pipeline.audioTimestampRolloverStream = new m2ts_1.TimestampRolloverStream('audio');
|
5510 | pipeline.timedMetadataTimestampRolloverStream = new m2ts_1.TimestampRolloverStream('timed-metadata');
|
5511 | pipeline.adtsStream = new adts();
|
5512 | pipeline.coalesceStream = new CoalesceStream(options, pipeline.metadataStream);
|
5513 | pipeline.headOfPipeline = pipeline.aacStream;
|
5514 |
|
5515 | pipeline.aacStream
|
5516 | .pipe(pipeline.audioTimestampRolloverStream)
|
5517 | .pipe(pipeline.adtsStream);
|
5518 | pipeline.aacStream
|
5519 | .pipe(pipeline.timedMetadataTimestampRolloverStream)
|
5520 | .pipe(pipeline.metadataStream)
|
5521 | .pipe(pipeline.coalesceStream);
|
5522 |
|
5523 | pipeline.metadataStream.on('timestamp', function(frame) {
|
5524 | pipeline.aacStream.setTimestamp(frame.timeStamp);
|
5525 | });
|
5526 |
|
5527 | pipeline.aacStream.on('data', function(data) {
|
5528 | if ((data.type !== 'timed-metadata' && data.type !== 'audio') || pipeline.audioSegmentStream) {
|
5529 | return;
|
5530 | }
|
5531 |
|
5532 | audioTrack = audioTrack || {
|
5533 | timelineStartInfo: {
|
5534 | baseMediaDecodeTime: self.baseMediaDecodeTime
|
5535 | },
|
5536 | codec: 'adts',
|
5537 | type: 'audio'
|
5538 | };
|
5539 |
|
5540 | pipeline.coalesceStream.numberOfTracks++;
|
5541 | pipeline.audioSegmentStream = new AudioSegmentStream(audioTrack, options);
|
5542 |
|
5543 | pipeline.audioSegmentStream.on('timingInfo',
|
5544 | self.trigger.bind(self, 'audioTimingInfo'));
|
5545 |
|
5546 |
|
5547 | pipeline.adtsStream
|
5548 | .pipe(pipeline.audioSegmentStream)
|
5549 | .pipe(pipeline.coalesceStream);
|
5550 |
|
5551 |
|
5552 | self.trigger('trackinfo', {
|
5553 | hasAudio: !!audioTrack,
|
5554 | hasVideo: !!videoTrack
|
5555 | });
|
5556 | });
|
5557 |
|
5558 |
|
5559 | pipeline.coalesceStream.on('data', this.trigger.bind(this, 'data'));
|
5560 |
|
5561 | pipeline.coalesceStream.on('done', this.trigger.bind(this, 'done'));
|
5562 | };
|
5563 |
|
5564 | this.setupTsPipeline = function() {
|
5565 | var pipeline = {};
|
5566 | this.transmuxPipeline_ = pipeline;
|
5567 |
|
5568 | pipeline.type = 'ts';
|
5569 | pipeline.metadataStream = new m2ts_1.MetadataStream();
|
5570 |
|
5571 |
|
5572 | pipeline.packetStream = new m2ts_1.TransportPacketStream();
|
5573 | pipeline.parseStream = new m2ts_1.TransportParseStream();
|
5574 | pipeline.elementaryStream = new m2ts_1.ElementaryStream();
|
5575 | pipeline.timestampRolloverStream = new m2ts_1.TimestampRolloverStream();
|
5576 | pipeline.adtsStream = new adts();
|
5577 | pipeline.h264Stream = new H264Stream$1();
|
5578 | pipeline.captionStream = new m2ts_1.CaptionStream();
|
5579 | pipeline.coalesceStream = new CoalesceStream(options, pipeline.metadataStream);
|
5580 | pipeline.headOfPipeline = pipeline.packetStream;
|
5581 |
|
5582 |
|
5583 | pipeline.packetStream
|
5584 | .pipe(pipeline.parseStream)
|
5585 | .pipe(pipeline.elementaryStream)
|
5586 | .pipe(pipeline.timestampRolloverStream);
|
5587 |
|
5588 |
|
5589 |
|
5590 | pipeline.timestampRolloverStream
|
5591 | .pipe(pipeline.h264Stream);
|
5592 |
|
5593 | pipeline.timestampRolloverStream
|
5594 | .pipe(pipeline.adtsStream);
|
5595 |
|
5596 | pipeline.timestampRolloverStream
|
5597 | .pipe(pipeline.metadataStream)
|
5598 | .pipe(pipeline.coalesceStream);
|
5599 |
|
5600 |
|
5601 | pipeline.h264Stream.pipe(pipeline.captionStream)
|
5602 | .pipe(pipeline.coalesceStream);
|
5603 |
|
5604 | pipeline.elementaryStream.on('data', function(data) {
|
5605 | var i;
|
5606 |
|
5607 | if (data.type === 'metadata') {
|
5608 | i = data.tracks.length;
|
5609 |
|
5610 |
|
5611 | while (i--) {
|
5612 | if (!videoTrack && data.tracks[i].type === 'video') {
|
5613 | videoTrack = data.tracks[i];
|
5614 | videoTrack.timelineStartInfo.baseMediaDecodeTime = self.baseMediaDecodeTime;
|
5615 | } else if (!audioTrack && data.tracks[i].type === 'audio') {
|
5616 | audioTrack = data.tracks[i];
|
5617 | audioTrack.timelineStartInfo.baseMediaDecodeTime = self.baseMediaDecodeTime;
|
5618 | }
|
5619 | }
|
5620 |
|
5621 |
|
5622 | if (videoTrack && !pipeline.videoSegmentStream) {
|
5623 | pipeline.coalesceStream.numberOfTracks++;
|
5624 | pipeline.videoSegmentStream = new VideoSegmentStream(videoTrack, options);
|
5625 |
|
5626 | pipeline.videoSegmentStream.on('timelineStartInfo', function(timelineStartInfo) {
|
5627 |
|
5628 |
|
5629 |
|
5630 |
|
5631 | if (audioTrack && !options.keepOriginalTimestamps) {
|
5632 | audioTrack.timelineStartInfo = timelineStartInfo;
|
5633 |
|
5634 |
|
5635 |
|
5636 |
|
5637 | pipeline.audioSegmentStream.setEarliestDts(timelineStartInfo.dts - self.baseMediaDecodeTime);
|
5638 | }
|
5639 | });
|
5640 |
|
5641 | pipeline.videoSegmentStream.on('processedGopsInfo',
|
5642 | self.trigger.bind(self, 'gopInfo'));
|
5643 | pipeline.videoSegmentStream.on('segmentTimingInfo',
|
5644 | self.trigger.bind(self, 'videoSegmentTimingInfo'));
|
5645 |
|
5646 | pipeline.videoSegmentStream.on('baseMediaDecodeTime', function(baseMediaDecodeTime) {
|
5647 | if (audioTrack) {
|
5648 | pipeline.audioSegmentStream.setVideoBaseMediaDecodeTime(baseMediaDecodeTime);
|
5649 | }
|
5650 | });
|
5651 |
|
5652 | pipeline.videoSegmentStream.on('timingInfo',
|
5653 | self.trigger.bind(self, 'videoTimingInfo'));
|
5654 |
|
5655 |
|
5656 | pipeline.h264Stream
|
5657 | .pipe(pipeline.videoSegmentStream)
|
5658 | .pipe(pipeline.coalesceStream);
|
5659 | }
|
5660 |
|
5661 | if (audioTrack && !pipeline.audioSegmentStream) {
|
5662 |
|
5663 | pipeline.coalesceStream.numberOfTracks++;
|
5664 | pipeline.audioSegmentStream = new AudioSegmentStream(audioTrack, options);
|
5665 |
|
5666 | pipeline.audioSegmentStream.on('timingInfo',
|
5667 | self.trigger.bind(self, 'audioTimingInfo'));
|
5668 |
|
5669 |
|
5670 | pipeline.adtsStream
|
5671 | .pipe(pipeline.audioSegmentStream)
|
5672 | .pipe(pipeline.coalesceStream);
|
5673 | }
|
5674 |
|
5675 |
|
5676 | self.trigger('trackinfo', {
|
5677 | hasAudio: !!audioTrack,
|
5678 | hasVideo: !!videoTrack
|
5679 | });
|
5680 | }
|
5681 | });
|
5682 |
|
5683 |
|
5684 | pipeline.coalesceStream.on('data', this.trigger.bind(this, 'data'));
|
5685 | pipeline.coalesceStream.on('id3Frame', function(id3Frame) {
|
5686 | id3Frame.dispatchType = pipeline.metadataStream.dispatchType;
|
5687 |
|
5688 | self.trigger('id3Frame', id3Frame);
|
5689 | });
|
5690 | pipeline.coalesceStream.on('caption', this.trigger.bind(this, 'caption'));
|
5691 |
|
5692 | pipeline.coalesceStream.on('done', this.trigger.bind(this, 'done'));
|
5693 | };
|
5694 |
|
5695 |
|
5696 | this.setBaseMediaDecodeTime = function(baseMediaDecodeTime) {
|
5697 | var pipeline = this.transmuxPipeline_;
|
5698 |
|
5699 | if (!options.keepOriginalTimestamps) {
|
5700 | this.baseMediaDecodeTime = baseMediaDecodeTime;
|
5701 | }
|
5702 |
|
5703 | if (audioTrack) {
|
5704 | audioTrack.timelineStartInfo.dts = undefined;
|
5705 | audioTrack.timelineStartInfo.pts = undefined;
|
5706 | trackDecodeInfo.clearDtsInfo(audioTrack);
|
5707 | if (pipeline.audioTimestampRolloverStream) {
|
5708 | pipeline.audioTimestampRolloverStream.discontinuity();
|
5709 | }
|
5710 | }
|
5711 | if (videoTrack) {
|
5712 | if (pipeline.videoSegmentStream) {
|
5713 | pipeline.videoSegmentStream.gopCache_ = [];
|
5714 | }
|
5715 | videoTrack.timelineStartInfo.dts = undefined;
|
5716 | videoTrack.timelineStartInfo.pts = undefined;
|
5717 | trackDecodeInfo.clearDtsInfo(videoTrack);
|
5718 | pipeline.captionStream.reset();
|
5719 | }
|
5720 |
|
5721 | if (pipeline.timestampRolloverStream) {
|
5722 | pipeline.timestampRolloverStream.discontinuity();
|
5723 | }
|
5724 | };
|
5725 |
|
5726 | this.setAudioAppendStart = function(timestamp) {
|
5727 | if (audioTrack) {
|
5728 | this.transmuxPipeline_.audioSegmentStream.setAudioAppendStart(timestamp);
|
5729 | }
|
5730 | };
|
5731 |
|
5732 | this.setRemux = function(val) {
|
5733 | var pipeline = this.transmuxPipeline_;
|
5734 |
|
5735 | options.remux = val;
|
5736 |
|
5737 | if (pipeline && pipeline.coalesceStream) {
|
5738 | pipeline.coalesceStream.setRemux(val);
|
5739 | }
|
5740 | };
|
5741 |
|
5742 | this.alignGopsWith = function(gopsToAlignWith) {
|
5743 | if (videoTrack && this.transmuxPipeline_.videoSegmentStream) {
|
5744 | this.transmuxPipeline_.videoSegmentStream.alignGopsWith(gopsToAlignWith);
|
5745 | }
|
5746 | };
|
5747 |
|
5748 |
|
5749 | this.push = function(data) {
|
5750 | if (hasFlushed) {
|
5751 | var isAac = isLikelyAacData$1(data);
|
5752 |
|
5753 | if (isAac && this.transmuxPipeline_.type !== 'aac') {
|
5754 | this.setupAacPipeline();
|
5755 | } else if (!isAac && this.transmuxPipeline_.type !== 'ts') {
|
5756 | this.setupTsPipeline();
|
5757 | }
|
5758 | hasFlushed = false;
|
5759 | }
|
5760 | this.transmuxPipeline_.headOfPipeline.push(data);
|
5761 | };
|
5762 |
|
5763 |
|
5764 | this.flush = function() {
|
5765 | hasFlushed = true;
|
5766 |
|
5767 | this.transmuxPipeline_.headOfPipeline.flush();
|
5768 | };
|
5769 |
|
5770 | this.endTimeline = function() {
|
5771 | this.transmuxPipeline_.headOfPipeline.endTimeline();
|
5772 | };
|
5773 |
|
5774 | this.reset = function() {
|
5775 | if (this.transmuxPipeline_.headOfPipeline) {
|
5776 | this.transmuxPipeline_.headOfPipeline.reset();
|
5777 | }
|
5778 | };
|
5779 |
|
5780 |
|
5781 | this.resetCaptions = function() {
|
5782 | if (this.transmuxPipeline_.captionStream) {
|
5783 | this.transmuxPipeline_.captionStream.reset();
|
5784 | }
|
5785 | };
|
5786 |
|
5787 | };
|
5788 | Transmuxer.prototype = new stream();
|
5789 |
|
5790 | var transmuxer = {
|
5791 | Transmuxer: Transmuxer,
|
5792 | VideoSegmentStream: VideoSegmentStream,
|
5793 | AudioSegmentStream: AudioSegmentStream,
|
5794 | AUDIO_PROPERTIES: audioProperties,
|
5795 | VIDEO_PROPERTIES: videoProperties,
|
5796 |
|
5797 | generateVideoSegmentTimingInfo: generateVideoSegmentTimingInfo
|
5798 | };
|
5799 | var transmuxer_1 = transmuxer.Transmuxer;
|
5800 |
|
5801 | |
5802 |
|
5803 |
|
5804 |
|
5805 |
|
5806 |
|
5807 | var codecs = {
|
5808 | Adts: adts,
|
5809 | h264: h264
|
5810 | };
|
5811 |
|
5812 | var ONE_SECOND_IN_TS$4 = clock.ONE_SECOND_IN_TS;
|
5813 |
|
5814 |
|
5815 | |
5816 |
|
5817 |
|
5818 |
|
5819 |
|
5820 | var AudioSegmentStream$1 = function(track, options) {
|
5821 | var
|
5822 | adtsFrames = [],
|
5823 | sequenceNumber = 0,
|
5824 | earliestAllowedDts = 0,
|
5825 | audioAppendStartTs = 0,
|
5826 | videoBaseMediaDecodeTime = Infinity,
|
5827 | segmentStartPts = null,
|
5828 | segmentEndPts = null;
|
5829 |
|
5830 | options = options || {};
|
5831 |
|
5832 | AudioSegmentStream$1.prototype.init.call(this);
|
5833 |
|
5834 | this.push = function(data) {
|
5835 | trackDecodeInfo.collectDtsInfo(track, data);
|
5836 |
|
5837 | if (track) {
|
5838 | audioProperties.forEach(function(prop) {
|
5839 | track[prop] = data[prop];
|
5840 | });
|
5841 | }
|
5842 |
|
5843 |
|
5844 | adtsFrames.push(data);
|
5845 | };
|
5846 |
|
5847 | this.setEarliestDts = function(earliestDts) {
|
5848 | earliestAllowedDts = earliestDts;
|
5849 | };
|
5850 |
|
5851 | this.setVideoBaseMediaDecodeTime = function(baseMediaDecodeTime) {
|
5852 | videoBaseMediaDecodeTime = baseMediaDecodeTime;
|
5853 | };
|
5854 |
|
5855 | this.setAudioAppendStart = function(timestamp) {
|
5856 | audioAppendStartTs = timestamp;
|
5857 | };
|
5858 |
|
5859 | this.processFrames_ = function() {
|
5860 | var
|
5861 | frames,
|
5862 | moof,
|
5863 | mdat,
|
5864 | boxes,
|
5865 | timingInfo;
|
5866 |
|
5867 |
|
5868 | if (adtsFrames.length === 0) {
|
5869 | return;
|
5870 | }
|
5871 |
|
5872 | frames = audioFrameUtils.trimAdtsFramesByEarliestDts(
|
5873 | adtsFrames, track, earliestAllowedDts);
|
5874 | if (frames.length === 0) {
|
5875 |
|
5876 |
|
5877 | return;
|
5878 | }
|
5879 |
|
5880 | track.baseMediaDecodeTime = trackDecodeInfo.calculateTrackBaseMediaDecodeTime(
|
5881 | track, options.keepOriginalTimestamps);
|
5882 |
|
5883 | audioFrameUtils.prefixWithSilence(
|
5884 | track, frames, audioAppendStartTs, videoBaseMediaDecodeTime);
|
5885 |
|
5886 |
|
5887 |
|
5888 | track.samples = audioFrameUtils.generateSampleTable(frames);
|
5889 |
|
5890 |
|
5891 | mdat = mp4Generator.mdat(audioFrameUtils.concatenateFrameData(frames));
|
5892 |
|
5893 | adtsFrames = [];
|
5894 |
|
5895 | moof = mp4Generator.moof(sequenceNumber, [track]);
|
5896 |
|
5897 |
|
5898 | sequenceNumber++;
|
5899 |
|
5900 | track.initSegment = mp4Generator.initSegment([track]);
|
5901 |
|
5902 |
|
5903 |
|
5904 | boxes = new Uint8Array(moof.byteLength + mdat.byteLength);
|
5905 |
|
5906 | boxes.set(moof);
|
5907 | boxes.set(mdat, moof.byteLength);
|
5908 |
|
5909 | trackDecodeInfo.clearDtsInfo(track);
|
5910 |
|
5911 | if (segmentStartPts === null) {
|
5912 | segmentEndPts = segmentStartPts = frames[0].pts;
|
5913 | }
|
5914 |
|
5915 | segmentEndPts += frames.length * (ONE_SECOND_IN_TS$4 * 1024 / track.samplerate);
|
5916 |
|
5917 | timingInfo = { start: segmentStartPts };
|
5918 |
|
5919 | this.trigger('timingInfo', timingInfo);
|
5920 | this.trigger('data', {track: track, boxes: boxes});
|
5921 | };
|
5922 |
|
5923 | this.flush = function() {
|
5924 | this.processFrames_();
|
5925 |
|
5926 | this.trigger('timingInfo', {
|
5927 | start: segmentStartPts,
|
5928 | end: segmentEndPts
|
5929 | });
|
5930 | this.resetTiming_();
|
5931 | this.trigger('done', 'AudioSegmentStream');
|
5932 | };
|
5933 |
|
5934 | this.partialFlush = function() {
|
5935 | this.processFrames_();
|
5936 | this.trigger('partialdone', 'AudioSegmentStream');
|
5937 | };
|
5938 |
|
5939 | this.endTimeline = function() {
|
5940 | this.flush();
|
5941 | this.trigger('endedtimeline', 'AudioSegmentStream');
|
5942 | };
|
5943 |
|
5944 | this.resetTiming_ = function() {
|
5945 | trackDecodeInfo.clearDtsInfo(track);
|
5946 | segmentStartPts = null;
|
5947 | segmentEndPts = null;
|
5948 | };
|
5949 |
|
5950 | this.reset = function() {
|
5951 | this.resetTiming_();
|
5952 | adtsFrames = [];
|
5953 | this.trigger('reset');
|
5954 | };
|
5955 | };
|
5956 |
|
5957 | AudioSegmentStream$1.prototype = new stream();
|
5958 |
|
5959 | var audioSegmentStream = AudioSegmentStream$1;
|
5960 |
|
5961 | var VideoSegmentStream$1 = function(track, options) {
|
5962 | var
|
5963 | sequenceNumber = 0,
|
5964 | nalUnits = [],
|
5965 | frameCache = [],
|
5966 |
|
5967 | config,
|
5968 | pps,
|
5969 | segmentStartPts = null,
|
5970 | segmentEndPts = null,
|
5971 | gops,
|
5972 | ensureNextFrameIsKeyFrame = true;
|
5973 |
|
5974 | options = options || {};
|
5975 |
|
5976 | VideoSegmentStream$1.prototype.init.call(this);
|
5977 |
|
5978 | this.push = function(nalUnit) {
|
5979 | trackDecodeInfo.collectDtsInfo(track, nalUnit);
|
5980 | if (typeof track.timelineStartInfo.dts === 'undefined') {
|
5981 | track.timelineStartInfo.dts = nalUnit.dts;
|
5982 | }
|
5983 |
|
5984 |
|
5985 | if (nalUnit.nalUnitType === 'seq_parameter_set_rbsp' && !config) {
|
5986 | config = nalUnit.config;
|
5987 | track.sps = [nalUnit.data];
|
5988 |
|
5989 | videoProperties.forEach(function(prop) {
|
5990 | track[prop] = config[prop];
|
5991 | }, this);
|
5992 | }
|
5993 |
|
5994 | if (nalUnit.nalUnitType === 'pic_parameter_set_rbsp' &&
|
5995 | !pps) {
|
5996 | pps = nalUnit.data;
|
5997 | track.pps = [nalUnit.data];
|
5998 | }
|
5999 |
|
6000 |
|
6001 | nalUnits.push(nalUnit);
|
6002 | };
|
6003 |
|
6004 | this.processNals_ = function(cacheLastFrame) {
|
6005 | var i;
|
6006 |
|
6007 | nalUnits = frameCache.concat(nalUnits);
|
6008 |
|
6009 |
|
6010 |
|
6011 | while (nalUnits.length) {
|
6012 | if (nalUnits[0].nalUnitType === 'access_unit_delimiter_rbsp') {
|
6013 | break;
|
6014 | }
|
6015 | nalUnits.shift();
|
6016 | }
|
6017 |
|
6018 |
|
6019 | if (nalUnits.length === 0) {
|
6020 | return;
|
6021 | }
|
6022 |
|
6023 | var frames = frameUtils.groupNalsIntoFrames(nalUnits);
|
6024 |
|
6025 | if (!frames.length) {
|
6026 | return;
|
6027 | }
|
6028 |
|
6029 |
|
6030 |
|
6031 | frameCache = frames[frames.length - 1];
|
6032 |
|
6033 | if (cacheLastFrame) {
|
6034 | frames.pop();
|
6035 | frames.duration -= frameCache.duration;
|
6036 | frames.nalCount -= frameCache.length;
|
6037 | frames.byteLength -= frameCache.byteLength;
|
6038 | }
|
6039 |
|
6040 | if (!frames.length) {
|
6041 | nalUnits = [];
|
6042 | return;
|
6043 | }
|
6044 |
|
6045 | this.trigger('timelineStartInfo', track.timelineStartInfo);
|
6046 |
|
6047 | if (ensureNextFrameIsKeyFrame) {
|
6048 | gops = frameUtils.groupFramesIntoGops(frames);
|
6049 |
|
6050 | if (!gops[0][0].keyFrame) {
|
6051 | gops = frameUtils.extendFirstKeyFrame(gops);
|
6052 |
|
6053 | if (!gops[0][0].keyFrame) {
|
6054 |
|
6055 |
|
6056 | nalUnits = ([].concat.apply([], frames)).concat(frameCache);
|
6057 | frameCache = [];
|
6058 | return;
|
6059 | }
|
6060 |
|
6061 | frames = [].concat.apply([], gops);
|
6062 | frames.duration = gops.duration;
|
6063 | }
|
6064 | ensureNextFrameIsKeyFrame = false;
|
6065 | }
|
6066 |
|
6067 | if (segmentStartPts === null) {
|
6068 | segmentStartPts = frames[0].pts;
|
6069 | segmentEndPts = segmentStartPts;
|
6070 | }
|
6071 |
|
6072 | segmentEndPts += frames.duration;
|
6073 |
|
6074 | this.trigger('timingInfo', {
|
6075 | start: segmentStartPts,
|
6076 | end: segmentEndPts
|
6077 | });
|
6078 |
|
6079 | for (i = 0; i < frames.length; i++) {
|
6080 | var frame = frames[i];
|
6081 |
|
6082 | track.samples = frameUtils.generateSampleTableForFrame(frame);
|
6083 |
|
6084 | var mdat = mp4Generator.mdat(frameUtils.concatenateNalDataForFrame(frame));
|
6085 |
|
6086 | trackDecodeInfo.clearDtsInfo(track);
|
6087 | trackDecodeInfo.collectDtsInfo(track, frame);
|
6088 |
|
6089 | track.baseMediaDecodeTime = trackDecodeInfo.calculateTrackBaseMediaDecodeTime(
|
6090 | track, options.keepOriginalTimestamps);
|
6091 |
|
6092 | var moof = mp4Generator.moof(sequenceNumber, [track]);
|
6093 |
|
6094 | sequenceNumber++;
|
6095 |
|
6096 | track.initSegment = mp4Generator.initSegment([track]);
|
6097 |
|
6098 | var boxes = new Uint8Array(moof.byteLength + mdat.byteLength);
|
6099 |
|
6100 | boxes.set(moof);
|
6101 | boxes.set(mdat, moof.byteLength);
|
6102 |
|
6103 | this.trigger('data', {
|
6104 | track: track,
|
6105 | boxes: boxes,
|
6106 | sequence: sequenceNumber,
|
6107 | videoFrameDts: frame.dts,
|
6108 | videoFramePts: frame.pts
|
6109 | });
|
6110 | }
|
6111 |
|
6112 | nalUnits = [];
|
6113 | };
|
6114 |
|
6115 | this.resetTimingAndConfig_ = function() {
|
6116 | config = undefined;
|
6117 | pps = undefined;
|
6118 | segmentStartPts = null;
|
6119 | segmentEndPts = null;
|
6120 | };
|
6121 |
|
6122 | this.partialFlush = function() {
|
6123 | this.processNals_(true);
|
6124 | this.trigger('partialdone', 'VideoSegmentStream');
|
6125 | };
|
6126 |
|
6127 | this.flush = function() {
|
6128 | this.processNals_(false);
|
6129 |
|
6130 |
|
6131 | this.resetTimingAndConfig_();
|
6132 | this.trigger('done', 'VideoSegmentStream');
|
6133 | };
|
6134 |
|
6135 | this.endTimeline = function() {
|
6136 | this.flush();
|
6137 | this.trigger('endedtimeline', 'VideoSegmentStream');
|
6138 | };
|
6139 |
|
6140 | this.reset = function() {
|
6141 | this.resetTimingAndConfig_();
|
6142 | frameCache = [];
|
6143 | nalUnits = [];
|
6144 | ensureNextFrameIsKeyFrame = true;
|
6145 | this.trigger('reset');
|
6146 | };
|
6147 | };
|
6148 |
|
6149 | VideoSegmentStream$1.prototype = new stream();
|
6150 |
|
6151 | var videoSegmentStream = VideoSegmentStream$1;
|
6152 |
|
6153 | var isLikelyAacData$2 = utils.isLikelyAacData;
|
6154 |
|
6155 |
|
6156 |
|
6157 |
|
6158 | var createPipeline = function(object) {
|
6159 | object.prototype = new stream();
|
6160 | object.prototype.init.call(object);
|
6161 |
|
6162 | return object;
|
6163 | };
|
6164 |
|
6165 | var tsPipeline = function(options) {
|
6166 | var
|
6167 | pipeline = {
|
6168 | type: 'ts',
|
6169 | tracks: {
|
6170 | audio: null,
|
6171 | video: null
|
6172 | },
|
6173 | packet: new m2ts_1.TransportPacketStream(),
|
6174 | parse: new m2ts_1.TransportParseStream(),
|
6175 | elementary: new m2ts_1.ElementaryStream(),
|
6176 | timestampRollover: new m2ts_1.TimestampRolloverStream(),
|
6177 | adts: new codecs.Adts(),
|
6178 | h264: new codecs.h264.H264Stream(),
|
6179 | captionStream: new m2ts_1.CaptionStream(),
|
6180 | metadataStream: new m2ts_1.MetadataStream()
|
6181 | };
|
6182 |
|
6183 | pipeline.headOfPipeline = pipeline.packet;
|
6184 |
|
6185 |
|
6186 | pipeline.packet
|
6187 | .pipe(pipeline.parse)
|
6188 | .pipe(pipeline.elementary)
|
6189 | .pipe(pipeline.timestampRollover);
|
6190 |
|
6191 |
|
6192 | pipeline.timestampRollover
|
6193 | .pipe(pipeline.h264);
|
6194 |
|
6195 |
|
6196 | pipeline.h264
|
6197 | .pipe(pipeline.captionStream);
|
6198 |
|
6199 | pipeline.timestampRollover
|
6200 | .pipe(pipeline.metadataStream);
|
6201 |
|
6202 |
|
6203 | pipeline.timestampRollover
|
6204 | .pipe(pipeline.adts);
|
6205 |
|
6206 | pipeline.elementary.on('data', function(data) {
|
6207 | if (data.type !== 'metadata') {
|
6208 | return;
|
6209 | }
|
6210 |
|
6211 | for (var i = 0; i < data.tracks.length; i++) {
|
6212 | if (!pipeline.tracks[data.tracks[i].type]) {
|
6213 | pipeline.tracks[data.tracks[i].type] = data.tracks[i];
|
6214 | pipeline.tracks[data.tracks[i].type].timelineStartInfo.baseMediaDecodeTime = options.baseMediaDecodeTime;
|
6215 | }
|
6216 | }
|
6217 |
|
6218 | if (pipeline.tracks.video && !pipeline.videoSegmentStream) {
|
6219 | pipeline.videoSegmentStream = new videoSegmentStream(pipeline.tracks.video, options);
|
6220 |
|
6221 | pipeline.videoSegmentStream.on('timelineStartInfo', function(timelineStartInfo) {
|
6222 | if (pipeline.tracks.audio && !options.keepOriginalTimestamps) {
|
6223 | pipeline.audioSegmentStream.setEarliestDts(timelineStartInfo.dts - options.baseMediaDecodeTime);
|
6224 | }
|
6225 | });
|
6226 |
|
6227 | pipeline.videoSegmentStream.on('timingInfo',
|
6228 | pipeline.trigger.bind(pipeline, 'videoTimingInfo'));
|
6229 |
|
6230 | pipeline.videoSegmentStream.on('data', function(data) {
|
6231 | pipeline.trigger('data', {
|
6232 | type: 'video',
|
6233 | data: data
|
6234 | });
|
6235 | });
|
6236 |
|
6237 | pipeline.videoSegmentStream.on('done',
|
6238 | pipeline.trigger.bind(pipeline, 'done'));
|
6239 | pipeline.videoSegmentStream.on('partialdone',
|
6240 | pipeline.trigger.bind(pipeline, 'partialdone'));
|
6241 | pipeline.videoSegmentStream.on('endedtimeline',
|
6242 | pipeline.trigger.bind(pipeline, 'endedtimeline'));
|
6243 |
|
6244 | pipeline.h264
|
6245 | .pipe(pipeline.videoSegmentStream);
|
6246 | }
|
6247 |
|
6248 | if (pipeline.tracks.audio && !pipeline.audioSegmentStream) {
|
6249 | pipeline.audioSegmentStream = new audioSegmentStream(pipeline.tracks.audio, options);
|
6250 |
|
6251 | pipeline.audioSegmentStream.on('data', function(data) {
|
6252 | pipeline.trigger('data', {
|
6253 | type: 'audio',
|
6254 | data: data
|
6255 | });
|
6256 | });
|
6257 |
|
6258 | pipeline.audioSegmentStream.on('done',
|
6259 | pipeline.trigger.bind(pipeline, 'done'));
|
6260 | pipeline.audioSegmentStream.on('partialdone',
|
6261 | pipeline.trigger.bind(pipeline, 'partialdone'));
|
6262 | pipeline.audioSegmentStream.on('endedtimeline',
|
6263 | pipeline.trigger.bind(pipeline, 'endedtimeline'));
|
6264 |
|
6265 | pipeline.audioSegmentStream.on('timingInfo',
|
6266 | pipeline.trigger.bind(pipeline, 'audioTimingInfo'));
|
6267 |
|
6268 | pipeline.adts
|
6269 | .pipe(pipeline.audioSegmentStream);
|
6270 | }
|
6271 |
|
6272 |
|
6273 | pipeline.trigger('trackinfo', {
|
6274 | hasAudio: !!pipeline.tracks.audio,
|
6275 | hasVideo: !!pipeline.tracks.video
|
6276 | });
|
6277 | });
|
6278 |
|
6279 | pipeline.captionStream.on('data', function(caption) {
|
6280 | var timelineStartPts;
|
6281 |
|
6282 | if (pipeline.tracks.video) {
|
6283 | timelineStartPts = pipeline.tracks.video.timelineStartInfo.pts || 0;
|
6284 | } else {
|
6285 |
|
6286 |
|
6287 |
|
6288 | timelineStartPts = 0;
|
6289 | }
|
6290 |
|
6291 |
|
6292 |
|
6293 | caption.startTime = clock.metadataTsToSeconds(caption.startPts, timelineStartPts, options.keepOriginalTimestamps);
|
6294 | caption.endTime = clock.metadataTsToSeconds(caption.endPts, timelineStartPts, options.keepOriginalTimestamps);
|
6295 |
|
6296 | pipeline.trigger('caption', caption);
|
6297 | });
|
6298 |
|
6299 | pipeline = createPipeline(pipeline);
|
6300 |
|
6301 | pipeline.metadataStream.on('data', pipeline.trigger.bind(pipeline, 'id3Frame'));
|
6302 |
|
6303 | return pipeline;
|
6304 | };
|
6305 |
|
6306 | var aacPipeline = function(options) {
|
6307 | var
|
6308 | pipeline = {
|
6309 | type: 'aac',
|
6310 | tracks: {
|
6311 | audio: null
|
6312 | },
|
6313 | metadataStream: new m2ts_1.MetadataStream(),
|
6314 | aacStream: new aac(),
|
6315 | audioRollover: new m2ts_1.TimestampRolloverStream('audio'),
|
6316 | timedMetadataRollover: new m2ts_1.TimestampRolloverStream('timed-metadata'),
|
6317 | adtsStream: new adts(true)
|
6318 | };
|
6319 |
|
6320 |
|
6321 | pipeline.headOfPipeline = pipeline.aacStream;
|
6322 |
|
6323 | pipeline.aacStream
|
6324 | .pipe(pipeline.audioRollover)
|
6325 | .pipe(pipeline.adtsStream);
|
6326 | pipeline.aacStream
|
6327 | .pipe(pipeline.timedMetadataRollover)
|
6328 | .pipe(pipeline.metadataStream);
|
6329 |
|
6330 | pipeline.metadataStream.on('timestamp', function(frame) {
|
6331 | pipeline.aacStream.setTimestamp(frame.timeStamp);
|
6332 | });
|
6333 |
|
6334 | pipeline.aacStream.on('data', function(data) {
|
6335 | if ((data.type !== 'timed-metadata' && data.type !== 'audio') || pipeline.audioSegmentStream) {
|
6336 | return;
|
6337 | }
|
6338 |
|
6339 | pipeline.tracks.audio = pipeline.tracks.audio || {
|
6340 | timelineStartInfo: {
|
6341 | baseMediaDecodeTime: options.baseMediaDecodeTime
|
6342 | },
|
6343 | codec: 'adts',
|
6344 | type: 'audio'
|
6345 | };
|
6346 |
|
6347 |
|
6348 | pipeline.audioSegmentStream = new audioSegmentStream(pipeline.tracks.audio, options);
|
6349 |
|
6350 | pipeline.audioSegmentStream.on('data', function(data) {
|
6351 | pipeline.trigger('data', {
|
6352 | type: 'audio',
|
6353 | data: data
|
6354 | });
|
6355 | });
|
6356 |
|
6357 | pipeline.audioSegmentStream.on('partialdone',
|
6358 | pipeline.trigger.bind(pipeline, 'partialdone'));
|
6359 | pipeline.audioSegmentStream.on('done', pipeline.trigger.bind(pipeline, 'done'));
|
6360 | pipeline.audioSegmentStream.on('endedtimeline',
|
6361 | pipeline.trigger.bind(pipeline, 'endedtimeline'));
|
6362 | pipeline.audioSegmentStream.on('timingInfo',
|
6363 | pipeline.trigger.bind(pipeline, 'audioTimingInfo'));
|
6364 |
|
6365 |
|
6366 | pipeline.adtsStream
|
6367 | .pipe(pipeline.audioSegmentStream);
|
6368 |
|
6369 | pipeline.trigger('trackinfo', {
|
6370 | hasAudio: !!pipeline.tracks.audio,
|
6371 | hasVideo: !!pipeline.tracks.video
|
6372 | });
|
6373 | });
|
6374 |
|
6375 |
|
6376 | pipeline = createPipeline(pipeline);
|
6377 |
|
6378 | pipeline.metadataStream.on('data', pipeline.trigger.bind(pipeline, 'id3Frame'));
|
6379 |
|
6380 | return pipeline;
|
6381 | };
|
6382 |
|
6383 | var setupPipelineListeners = function(pipeline, transmuxer) {
|
6384 | pipeline.on('data', transmuxer.trigger.bind(transmuxer, 'data'));
|
6385 | pipeline.on('done', transmuxer.trigger.bind(transmuxer, 'done'));
|
6386 | pipeline.on('partialdone', transmuxer.trigger.bind(transmuxer, 'partialdone'));
|
6387 | pipeline.on('endedtimeline', transmuxer.trigger.bind(transmuxer, 'endedtimeline'));
|
6388 | pipeline.on('audioTimingInfo', transmuxer.trigger.bind(transmuxer, 'audioTimingInfo'));
|
6389 | pipeline.on('videoTimingInfo', transmuxer.trigger.bind(transmuxer, 'videoTimingInfo'));
|
6390 | pipeline.on('trackinfo', transmuxer.trigger.bind(transmuxer, 'trackinfo'));
|
6391 | pipeline.on('id3Frame', function(event) {
|
6392 |
|
6393 | event.dispatchType = pipeline.metadataStream.dispatchType;
|
6394 |
|
6395 | event.cueTime = clock.videoTsToSeconds(event.pts);
|
6396 |
|
6397 | transmuxer.trigger('id3Frame', event);
|
6398 | });
|
6399 | pipeline.on('caption', function(event) {
|
6400 | transmuxer.trigger('caption', event);
|
6401 | });
|
6402 | };
|
6403 |
|
6404 | var Transmuxer$1 = function(options) {
|
6405 | var
|
6406 | pipeline = null,
|
6407 | hasFlushed = true;
|
6408 |
|
6409 | options = options || {};
|
6410 |
|
6411 | Transmuxer$1.prototype.init.call(this);
|
6412 | options.baseMediaDecodeTime = options.baseMediaDecodeTime || 0;
|
6413 |
|
6414 | this.push = function(bytes) {
|
6415 | if (hasFlushed) {
|
6416 | var isAac = isLikelyAacData$2(bytes);
|
6417 |
|
6418 | if (isAac && (!pipeline || pipeline.type !== 'aac')) {
|
6419 | pipeline = aacPipeline(options);
|
6420 | setupPipelineListeners(pipeline, this);
|
6421 | } else if (!isAac && (!pipeline || pipeline.type !== 'ts')) {
|
6422 | pipeline = tsPipeline(options);
|
6423 | setupPipelineListeners(pipeline, this);
|
6424 | }
|
6425 | hasFlushed = false;
|
6426 | }
|
6427 |
|
6428 | pipeline.headOfPipeline.push(bytes);
|
6429 | };
|
6430 |
|
6431 | this.flush = function() {
|
6432 | if (!pipeline) {
|
6433 | return;
|
6434 | }
|
6435 |
|
6436 | hasFlushed = true;
|
6437 | pipeline.headOfPipeline.flush();
|
6438 | };
|
6439 |
|
6440 | this.partialFlush = function() {
|
6441 | if (!pipeline) {
|
6442 | return;
|
6443 | }
|
6444 |
|
6445 | pipeline.headOfPipeline.partialFlush();
|
6446 | };
|
6447 |
|
6448 | this.endTimeline = function() {
|
6449 | if (!pipeline) {
|
6450 | return;
|
6451 | }
|
6452 |
|
6453 | pipeline.headOfPipeline.endTimeline();
|
6454 | };
|
6455 |
|
6456 | this.reset = function() {
|
6457 | if (!pipeline) {
|
6458 | return;
|
6459 | }
|
6460 |
|
6461 | pipeline.headOfPipeline.reset();
|
6462 | };
|
6463 |
|
6464 | this.setBaseMediaDecodeTime = function(baseMediaDecodeTime) {
|
6465 | if (!options.keepOriginalTimestamps) {
|
6466 | options.baseMediaDecodeTime = baseMediaDecodeTime;
|
6467 | }
|
6468 |
|
6469 | if (!pipeline) {
|
6470 | return;
|
6471 | }
|
6472 |
|
6473 | if (pipeline.tracks.audio) {
|
6474 | pipeline.tracks.audio.timelineStartInfo.dts = undefined;
|
6475 | pipeline.tracks.audio.timelineStartInfo.pts = undefined;
|
6476 | trackDecodeInfo.clearDtsInfo(pipeline.tracks.audio);
|
6477 | if (pipeline.audioRollover) {
|
6478 | pipeline.audioRollover.discontinuity();
|
6479 | }
|
6480 | }
|
6481 | if (pipeline.tracks.video) {
|
6482 | if (pipeline.videoSegmentStream) {
|
6483 | pipeline.videoSegmentStream.gopCache_ = [];
|
6484 | }
|
6485 | pipeline.tracks.video.timelineStartInfo.dts = undefined;
|
6486 | pipeline.tracks.video.timelineStartInfo.pts = undefined;
|
6487 | trackDecodeInfo.clearDtsInfo(pipeline.tracks.video);
|
6488 |
|
6489 | }
|
6490 |
|
6491 | if (pipeline.timestampRollover) {
|
6492 | pipeline.timestampRollover.discontinuity();
|
6493 |
|
6494 | }
|
6495 | };
|
6496 |
|
6497 | this.setRemux = function(val) {
|
6498 | options.remux = val;
|
6499 |
|
6500 | if (pipeline && pipeline.coalesceStream) {
|
6501 | pipeline.coalesceStream.setRemux(val);
|
6502 | }
|
6503 | };
|
6504 |
|
6505 |
|
6506 | this.setAudioAppendStart = function(audioAppendStart) {
|
6507 | if (!pipeline || !pipeline.tracks.audio || !pipeline.audioSegmentStream) {
|
6508 | return;
|
6509 | }
|
6510 |
|
6511 | pipeline.audioSegmentStream.setAudioAppendStart(audioAppendStart);
|
6512 | };
|
6513 |
|
6514 |
|
6515 |
|
6516 |
|
6517 | this.alignGopsWith = function(gopsToAlignWith) {
|
6518 | return;
|
6519 | };
|
6520 | };
|
6521 |
|
6522 | Transmuxer$1.prototype = new stream();
|
6523 |
|
6524 | var transmuxer$1 = Transmuxer$1;
|
6525 |
|
6526 | |
6527 |
|
6528 |
|
6529 |
|
6530 |
|
6531 |
|
6532 | var toUnsigned = function(value) {
|
6533 | return value >>> 0;
|
6534 | };
|
6535 |
|
6536 | var toHexString = function(value) {
|
6537 | return ('00' + value.toString(16)).slice(-2);
|
6538 | };
|
6539 |
|
6540 | var bin = {
|
6541 | toUnsigned: toUnsigned,
|
6542 | toHexString: toHexString
|
6543 | };
|
6544 |
|
6545 | var parseType$1 = function(buffer) {
|
6546 | var result = '';
|
6547 | result += String.fromCharCode(buffer[0]);
|
6548 | result += String.fromCharCode(buffer[1]);
|
6549 | result += String.fromCharCode(buffer[2]);
|
6550 | result += String.fromCharCode(buffer[3]);
|
6551 | return result;
|
6552 | };
|
6553 |
|
6554 |
|
6555 | var parseType_1 = parseType$1;
|
6556 |
|
6557 | var toUnsigned$1 = bin.toUnsigned;
|
6558 |
|
6559 |
|
6560 | var findBox = function(data, path) {
|
6561 | var results = [],
|
6562 | i, size, type, end, subresults;
|
6563 |
|
6564 | if (!path.length) {
|
6565 |
|
6566 | return null;
|
6567 | }
|
6568 |
|
6569 | for (i = 0; i < data.byteLength;) {
|
6570 | size = toUnsigned$1(data[i] << 24 |
|
6571 | data[i + 1] << 16 |
|
6572 | data[i + 2] << 8 |
|
6573 | data[i + 3]);
|
6574 |
|
6575 | type = parseType_1(data.subarray(i + 4, i + 8));
|
6576 |
|
6577 | end = size > 1 ? i + size : data.byteLength;
|
6578 |
|
6579 | if (type === path[0]) {
|
6580 | if (path.length === 1) {
|
6581 |
|
6582 |
|
6583 | results.push(data.subarray(i + 8, end));
|
6584 | } else {
|
6585 |
|
6586 | subresults = findBox(data.subarray(i + 8, end), path.slice(1));
|
6587 | if (subresults.length) {
|
6588 | results = results.concat(subresults);
|
6589 | }
|
6590 | }
|
6591 | }
|
6592 | i = end;
|
6593 | }
|
6594 |
|
6595 |
|
6596 | return results;
|
6597 | };
|
6598 |
|
6599 | var findBox_1 = findBox;
|
6600 |
|
6601 | var toUnsigned$2 = bin.toUnsigned;
|
6602 |
|
6603 | var tfdt = function(data) {
|
6604 | var result = {
|
6605 | version: data[0],
|
6606 | flags: new Uint8Array(data.subarray(1, 4)),
|
6607 | baseMediaDecodeTime: toUnsigned$2(data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7])
|
6608 | };
|
6609 | if (result.version === 1) {
|
6610 | result.baseMediaDecodeTime *= Math.pow(2, 32);
|
6611 | result.baseMediaDecodeTime += toUnsigned$2(data[8] << 24 | data[9] << 16 | data[10] << 8 | data[11]);
|
6612 | }
|
6613 | return result;
|
6614 | };
|
6615 |
|
6616 | var parseTfdt = tfdt;
|
6617 |
|
6618 | var parseSampleFlags = function(flags) {
|
6619 | return {
|
6620 | isLeading: (flags[0] & 0x0c) >>> 2,
|
6621 | dependsOn: flags[0] & 0x03,
|
6622 | isDependedOn: (flags[1] & 0xc0) >>> 6,
|
6623 | hasRedundancy: (flags[1] & 0x30) >>> 4,
|
6624 | paddingValue: (flags[1] & 0x0e) >>> 1,
|
6625 | isNonSyncSample: flags[1] & 0x01,
|
6626 | degradationPriority: (flags[2] << 8) | flags[3]
|
6627 | };
|
6628 | };
|
6629 |
|
6630 | var parseSampleFlags_1 = parseSampleFlags;
|
6631 |
|
6632 | var trun$1 = function(data) {
|
6633 | var
|
6634 | result = {
|
6635 | version: data[0],
|
6636 | flags: new Uint8Array(data.subarray(1, 4)),
|
6637 | samples: []
|
6638 | },
|
6639 | view = new DataView(data.buffer, data.byteOffset, data.byteLength),
|
6640 |
|
6641 | dataOffsetPresent = result.flags[2] & 0x01,
|
6642 | firstSampleFlagsPresent = result.flags[2] & 0x04,
|
6643 | sampleDurationPresent = result.flags[1] & 0x01,
|
6644 | sampleSizePresent = result.flags[1] & 0x02,
|
6645 | sampleFlagsPresent = result.flags[1] & 0x04,
|
6646 | sampleCompositionTimeOffsetPresent = result.flags[1] & 0x08,
|
6647 | sampleCount = view.getUint32(4),
|
6648 | offset = 8,
|
6649 | sample;
|
6650 |
|
6651 | if (dataOffsetPresent) {
|
6652 |
|
6653 | result.dataOffset = view.getInt32(offset);
|
6654 | offset += 4;
|
6655 | }
|
6656 |
|
6657 |
|
6658 |
|
6659 | if (firstSampleFlagsPresent && sampleCount) {
|
6660 | sample = {
|
6661 | flags: parseSampleFlags_1(data.subarray(offset, offset + 4))
|
6662 | };
|
6663 | offset += 4;
|
6664 | if (sampleDurationPresent) {
|
6665 | sample.duration = view.getUint32(offset);
|
6666 | offset += 4;
|
6667 | }
|
6668 | if (sampleSizePresent) {
|
6669 | sample.size = view.getUint32(offset);
|
6670 | offset += 4;
|
6671 | }
|
6672 | if (sampleCompositionTimeOffsetPresent) {
|
6673 | if (result.version === 1) {
|
6674 | sample.compositionTimeOffset = view.getInt32(offset);
|
6675 | } else {
|
6676 | sample.compositionTimeOffset = view.getUint32(offset);
|
6677 | }
|
6678 | offset += 4;
|
6679 | }
|
6680 | result.samples.push(sample);
|
6681 | sampleCount--;
|
6682 | }
|
6683 |
|
6684 | while (sampleCount--) {
|
6685 | sample = {};
|
6686 | if (sampleDurationPresent) {
|
6687 | sample.duration = view.getUint32(offset);
|
6688 | offset += 4;
|
6689 | }
|
6690 | if (sampleSizePresent) {
|
6691 | sample.size = view.getUint32(offset);
|
6692 | offset += 4;
|
6693 | }
|
6694 | if (sampleFlagsPresent) {
|
6695 | sample.flags = parseSampleFlags_1(data.subarray(offset, offset + 4));
|
6696 | offset += 4;
|
6697 | }
|
6698 | if (sampleCompositionTimeOffsetPresent) {
|
6699 | if (result.version === 1) {
|
6700 | sample.compositionTimeOffset = view.getInt32(offset);
|
6701 | } else {
|
6702 | sample.compositionTimeOffset = view.getUint32(offset);
|
6703 | }
|
6704 | offset += 4;
|
6705 | }
|
6706 | result.samples.push(sample);
|
6707 | }
|
6708 | return result;
|
6709 | };
|
6710 |
|
6711 | var parseTrun = trun$1;
|
6712 |
|
6713 | var tfhd = function(data) {
|
6714 | var
|
6715 | view = new DataView(data.buffer, data.byteOffset, data.byteLength),
|
6716 | result = {
|
6717 | version: data[0],
|
6718 | flags: new Uint8Array(data.subarray(1, 4)),
|
6719 | trackId: view.getUint32(4)
|
6720 | },
|
6721 | baseDataOffsetPresent = result.flags[2] & 0x01,
|
6722 | sampleDescriptionIndexPresent = result.flags[2] & 0x02,
|
6723 | defaultSampleDurationPresent = result.flags[2] & 0x08,
|
6724 | defaultSampleSizePresent = result.flags[2] & 0x10,
|
6725 | defaultSampleFlagsPresent = result.flags[2] & 0x20,
|
6726 | durationIsEmpty = result.flags[0] & 0x010000,
|
6727 | defaultBaseIsMoof = result.flags[0] & 0x020000,
|
6728 | i;
|
6729 |
|
6730 | i = 8;
|
6731 | if (baseDataOffsetPresent) {
|
6732 | i += 4;
|
6733 |
|
6734 | result.baseDataOffset = view.getUint32(12);
|
6735 | i += 4;
|
6736 | }
|
6737 | if (sampleDescriptionIndexPresent) {
|
6738 | result.sampleDescriptionIndex = view.getUint32(i);
|
6739 | i += 4;
|
6740 | }
|
6741 | if (defaultSampleDurationPresent) {
|
6742 | result.defaultSampleDuration = view.getUint32(i);
|
6743 | i += 4;
|
6744 | }
|
6745 | if (defaultSampleSizePresent) {
|
6746 | result.defaultSampleSize = view.getUint32(i);
|
6747 | i += 4;
|
6748 | }
|
6749 | if (defaultSampleFlagsPresent) {
|
6750 | result.defaultSampleFlags = view.getUint32(i);
|
6751 | }
|
6752 | if (durationIsEmpty) {
|
6753 | result.durationIsEmpty = true;
|
6754 | }
|
6755 | if (!baseDataOffsetPresent && defaultBaseIsMoof) {
|
6756 | result.baseDataOffsetIsMoof = true;
|
6757 | }
|
6758 | return result;
|
6759 | };
|
6760 |
|
6761 | var parseTfhd = tfhd;
|
6762 |
|
6763 | var discardEmulationPreventionBytes$1 = captionPacketParser.discardEmulationPreventionBytes;
|
6764 | var CaptionStream$1 = captionStream.CaptionStream;
|
6765 |
|
6766 |
|
6767 |
|
6768 |
|
6769 |
|
6770 | |
6771 |
|
6772 |
|
6773 |
|
6774 |
|
6775 |
|
6776 |
|
6777 |
|
6778 |
|
6779 |
|
6780 | var mapToSample = function(offset, samples) {
|
6781 | var approximateOffset = offset;
|
6782 |
|
6783 | for (var i = 0; i < samples.length; i++) {
|
6784 | var sample = samples[i];
|
6785 |
|
6786 | if (approximateOffset < sample.size) {
|
6787 | return sample;
|
6788 | }
|
6789 |
|
6790 | approximateOffset -= sample.size;
|
6791 | }
|
6792 |
|
6793 | return null;
|
6794 | };
|
6795 |
|
6796 | |
6797 |
|
6798 |
|
6799 |
|
6800 |
|
6801 |
|
6802 |
|
6803 |
|
6804 |
|
6805 |
|
6806 |
|
6807 |
|
6808 |
|
6809 |
|
6810 | var findSeiNals = function(avcStream, samples, trackId) {
|
6811 | var
|
6812 | avcView = new DataView(avcStream.buffer, avcStream.byteOffset, avcStream.byteLength),
|
6813 | result = [],
|
6814 | seiNal,
|
6815 | i,
|
6816 | length,
|
6817 | lastMatchedSample;
|
6818 |
|
6819 | for (i = 0; i + 4 < avcStream.length; i += length) {
|
6820 | length = avcView.getUint32(i);
|
6821 | i += 4;
|
6822 |
|
6823 |
|
6824 | if (length <= 0) {
|
6825 | continue;
|
6826 | }
|
6827 |
|
6828 | switch (avcStream[i] & 0x1F) {
|
6829 | case 0x06:
|
6830 | var data = avcStream.subarray(i + 1, i + 1 + length);
|
6831 | var matchingSample = mapToSample(i, samples);
|
6832 |
|
6833 | seiNal = {
|
6834 | nalUnitType: 'sei_rbsp',
|
6835 | size: length,
|
6836 | data: data,
|
6837 | escapedRBSP: discardEmulationPreventionBytes$1(data),
|
6838 | trackId: trackId
|
6839 | };
|
6840 |
|
6841 | if (matchingSample) {
|
6842 | seiNal.pts = matchingSample.pts;
|
6843 | seiNal.dts = matchingSample.dts;
|
6844 | lastMatchedSample = matchingSample;
|
6845 | } else if (lastMatchedSample) {
|
6846 |
|
6847 |
|
6848 | seiNal.pts = lastMatchedSample.pts;
|
6849 | seiNal.dts = lastMatchedSample.dts;
|
6850 | } else {
|
6851 |
|
6852 | console.log("We've encountered a nal unit without data. See mux.js#233.");
|
6853 | break;
|
6854 | }
|
6855 |
|
6856 | result.push(seiNal);
|
6857 | break;
|
6858 | }
|
6859 | }
|
6860 |
|
6861 | return result;
|
6862 | };
|
6863 |
|
6864 | |
6865 |
|
6866 |
|
6867 |
|
6868 |
|
6869 |
|
6870 |
|
6871 |
|
6872 |
|
6873 |
|
6874 |
|
6875 |
|
6876 |
|
6877 | var parseSamples = function(truns, baseMediaDecodeTime, tfhd) {
|
6878 | var currentDts = baseMediaDecodeTime;
|
6879 | var defaultSampleDuration = tfhd.defaultSampleDuration || 0;
|
6880 | var defaultSampleSize = tfhd.defaultSampleSize || 0;
|
6881 | var trackId = tfhd.trackId;
|
6882 | var allSamples = [];
|
6883 |
|
6884 | truns.forEach(function(trun) {
|
6885 |
|
6886 |
|
6887 |
|
6888 | var trackRun = parseTrun(trun);
|
6889 | var samples = trackRun.samples;
|
6890 |
|
6891 | samples.forEach(function(sample) {
|
6892 | if (sample.duration === undefined) {
|
6893 | sample.duration = defaultSampleDuration;
|
6894 | }
|
6895 | if (sample.size === undefined) {
|
6896 | sample.size = defaultSampleSize;
|
6897 | }
|
6898 | sample.trackId = trackId;
|
6899 | sample.dts = currentDts;
|
6900 | if (sample.compositionTimeOffset === undefined) {
|
6901 | sample.compositionTimeOffset = 0;
|
6902 | }
|
6903 | sample.pts = currentDts + sample.compositionTimeOffset;
|
6904 |
|
6905 | currentDts += sample.duration;
|
6906 | });
|
6907 |
|
6908 | allSamples = allSamples.concat(samples);
|
6909 | });
|
6910 |
|
6911 | return allSamples;
|
6912 | };
|
6913 |
|
6914 | |
6915 |
|
6916 |
|
6917 |
|
6918 |
|
6919 |
|
6920 |
|
6921 |
|
6922 | var parseCaptionNals = function(segment, videoTrackId) {
|
6923 |
|
6924 | var trafs = findBox_1(segment, ['moof', 'traf']);
|
6925 |
|
6926 | var mdats = findBox_1(segment, ['mdat']);
|
6927 | var captionNals = {};
|
6928 | var mdatTrafPairs = [];
|
6929 |
|
6930 |
|
6931 | mdats.forEach(function(mdat, index) {
|
6932 | var matchingTraf = trafs[index];
|
6933 | mdatTrafPairs.push({
|
6934 | mdat: mdat,
|
6935 | traf: matchingTraf
|
6936 | });
|
6937 | });
|
6938 |
|
6939 | mdatTrafPairs.forEach(function(pair) {
|
6940 | var mdat = pair.mdat;
|
6941 | var traf = pair.traf;
|
6942 | var tfhd = findBox_1(traf, ['tfhd']);
|
6943 |
|
6944 | var headerInfo = parseTfhd(tfhd[0]);
|
6945 | var trackId = headerInfo.trackId;
|
6946 | var tfdt = findBox_1(traf, ['tfdt']);
|
6947 |
|
6948 | var baseMediaDecodeTime = (tfdt.length > 0) ? parseTfdt(tfdt[0]).baseMediaDecodeTime : 0;
|
6949 | var truns = findBox_1(traf, ['trun']);
|
6950 | var samples;
|
6951 | var seiNals;
|
6952 |
|
6953 |
|
6954 | if (videoTrackId === trackId && truns.length > 0) {
|
6955 | samples = parseSamples(truns, baseMediaDecodeTime, headerInfo);
|
6956 |
|
6957 | seiNals = findSeiNals(mdat, samples, trackId);
|
6958 |
|
6959 | if (!captionNals[trackId]) {
|
6960 | captionNals[trackId] = [];
|
6961 | }
|
6962 |
|
6963 | captionNals[trackId] = captionNals[trackId].concat(seiNals);
|
6964 | }
|
6965 | });
|
6966 |
|
6967 | return captionNals;
|
6968 | };
|
6969 |
|
6970 | |
6971 |
|
6972 |
|
6973 |
|
6974 |
|
6975 |
|
6976 |
|
6977 |
|
6978 |
|
6979 |
|
6980 |
|
6981 |
|
6982 |
|
6983 |
|
6984 |
|
6985 |
|
6986 | var parseEmbeddedCaptions = function(segment, trackId, timescale) {
|
6987 | var seiNals;
|
6988 |
|
6989 |
|
6990 | if (trackId === null) {
|
6991 | return null;
|
6992 | }
|
6993 |
|
6994 | seiNals = parseCaptionNals(segment, trackId);
|
6995 |
|
6996 | return {
|
6997 | seiNals: seiNals[trackId],
|
6998 | timescale: timescale
|
6999 | };
|
7000 | };
|
7001 |
|
7002 | |
7003 |
|
7004 |
|
7005 | var CaptionParser = function() {
|
7006 | var isInitialized = false;
|
7007 | var captionStream;
|
7008 |
|
7009 |
|
7010 | var segmentCache;
|
7011 |
|
7012 | var trackId;
|
7013 |
|
7014 | var timescale;
|
7015 |
|
7016 | var parsedCaptions;
|
7017 |
|
7018 | var parsingPartial;
|
7019 |
|
7020 | |
7021 |
|
7022 |
|
7023 |
|
7024 | this.isInitialized = function() {
|
7025 | return isInitialized;
|
7026 | };
|
7027 |
|
7028 | |
7029 |
|
7030 |
|
7031 |
|
7032 | this.init = function(options) {
|
7033 | captionStream = new CaptionStream$1();
|
7034 | isInitialized = true;
|
7035 | parsingPartial = options ? options.isPartial : false;
|
7036 |
|
7037 |
|
7038 | captionStream.on('data', function(event) {
|
7039 |
|
7040 | event.startTime = event.startPts / timescale;
|
7041 | event.endTime = event.endPts / timescale;
|
7042 |
|
7043 | parsedCaptions.captions.push(event);
|
7044 | parsedCaptions.captionStreams[event.stream] = true;
|
7045 | });
|
7046 | };
|
7047 |
|
7048 | |
7049 |
|
7050 |
|
7051 |
|
7052 |
|
7053 | this.isNewInit = function(videoTrackIds, timescales) {
|
7054 | if ((videoTrackIds && videoTrackIds.length === 0) ||
|
7055 | (timescales && typeof timescales === 'object' &&
|
7056 | Object.keys(timescales).length === 0)) {
|
7057 | return false;
|
7058 | }
|
7059 |
|
7060 | return trackId !== videoTrackIds[0] ||
|
7061 | timescale !== timescales[trackId];
|
7062 | };
|
7063 |
|
7064 | |
7065 |
|
7066 |
|
7067 |
|
7068 |
|
7069 |
|
7070 |
|
7071 |
|
7072 |
|
7073 |
|
7074 | this.parse = function(segment, videoTrackIds, timescales) {
|
7075 | var parsedData;
|
7076 |
|
7077 | if (!this.isInitialized()) {
|
7078 | return null;
|
7079 |
|
7080 |
|
7081 | } else if (!videoTrackIds || !timescales) {
|
7082 | return null;
|
7083 |
|
7084 | } else if (this.isNewInit(videoTrackIds, timescales)) {
|
7085 |
|
7086 |
|
7087 | trackId = videoTrackIds[0];
|
7088 | timescale = timescales[trackId];
|
7089 |
|
7090 |
|
7091 |
|
7092 |
|
7093 | } else if (trackId === null || !timescale) {
|
7094 | segmentCache.push(segment);
|
7095 | return null;
|
7096 | }
|
7097 |
|
7098 |
|
7099 | while (segmentCache.length > 0) {
|
7100 | var cachedSegment = segmentCache.shift();
|
7101 |
|
7102 | this.parse(cachedSegment, videoTrackIds, timescales);
|
7103 | }
|
7104 |
|
7105 | parsedData = parseEmbeddedCaptions(segment, trackId, timescale);
|
7106 |
|
7107 | if (parsedData === null || !parsedData.seiNals) {
|
7108 | return null;
|
7109 | }
|
7110 |
|
7111 | this.pushNals(parsedData.seiNals);
|
7112 |
|
7113 | this.flushStream();
|
7114 |
|
7115 | return parsedCaptions;
|
7116 | };
|
7117 |
|
7118 | |
7119 |
|
7120 |
|
7121 |
|
7122 |
|
7123 |
|
7124 | this.pushNals = function(nals) {
|
7125 | if (!this.isInitialized() || !nals || nals.length === 0) {
|
7126 | return null;
|
7127 | }
|
7128 |
|
7129 | nals.forEach(function(nal) {
|
7130 | captionStream.push(nal);
|
7131 | });
|
7132 | };
|
7133 |
|
7134 | |
7135 |
|
7136 |
|
7137 |
|
7138 | this.flushStream = function() {
|
7139 | if (!this.isInitialized()) {
|
7140 | return null;
|
7141 | }
|
7142 |
|
7143 | if (!parsingPartial) {
|
7144 | captionStream.flush();
|
7145 | } else {
|
7146 | captionStream.partialFlush();
|
7147 | }
|
7148 | };
|
7149 |
|
7150 | |
7151 |
|
7152 |
|
7153 | this.clearParsedCaptions = function() {
|
7154 | parsedCaptions.captions = [];
|
7155 | parsedCaptions.captionStreams = {};
|
7156 | };
|
7157 |
|
7158 | |
7159 |
|
7160 |
|
7161 |
|
7162 | this.resetCaptionStream = function() {
|
7163 | if (!this.isInitialized()) {
|
7164 | return null;
|
7165 | }
|
7166 |
|
7167 | captionStream.reset();
|
7168 | };
|
7169 |
|
7170 | |
7171 |
|
7172 |
|
7173 |
|
7174 |
|
7175 | this.clearAllCaptions = function() {
|
7176 | this.clearParsedCaptions();
|
7177 | this.resetCaptionStream();
|
7178 | };
|
7179 |
|
7180 | |
7181 |
|
7182 |
|
7183 | this.reset = function() {
|
7184 | segmentCache = [];
|
7185 | trackId = null;
|
7186 | timescale = null;
|
7187 |
|
7188 | if (!parsedCaptions) {
|
7189 | parsedCaptions = {
|
7190 | captions: [],
|
7191 |
|
7192 | captionStreams: {}
|
7193 | };
|
7194 | } else {
|
7195 | this.clearParsedCaptions();
|
7196 | }
|
7197 |
|
7198 | this.resetCaptionStream();
|
7199 | };
|
7200 |
|
7201 | this.reset();
|
7202 | };
|
7203 |
|
7204 | var captionParser = CaptionParser;
|
7205 |
|
7206 |
|
7207 |
|
7208 | var typeFromStreamString = function typeFromStreamString(streamString) {
|
7209 | if (streamString === 'AudioSegmentStream') {
|
7210 | return 'audio';
|
7211 | }
|
7212 |
|
7213 | return streamString === 'VideoSegmentStream' ? 'video' : '';
|
7214 | };
|
7215 | |
7216 |
|
7217 |
|
7218 |
|
7219 |
|
7220 |
|
7221 |
|
7222 |
|
7223 |
|
7224 | var wireFullTransmuxerEvents = function wireFullTransmuxerEvents(self, transmuxer) {
|
7225 | transmuxer.on('data', function (segment) {
|
7226 |
|
7227 |
|
7228 |
|
7229 |
|
7230 | var initArray = segment.initSegment;
|
7231 | segment.initSegment = {
|
7232 | data: initArray.buffer,
|
7233 | byteOffset: initArray.byteOffset,
|
7234 | byteLength: initArray.byteLength
|
7235 | };
|
7236 | var typedArray = segment.data;
|
7237 | segment.data = typedArray.buffer;
|
7238 | self.postMessage({
|
7239 | action: 'data',
|
7240 | segment: segment,
|
7241 | byteOffset: typedArray.byteOffset,
|
7242 | byteLength: typedArray.byteLength
|
7243 | }, [segment.data]);
|
7244 | });
|
7245 | transmuxer.on('done', function (data) {
|
7246 | self.postMessage({
|
7247 | action: 'done'
|
7248 | });
|
7249 | });
|
7250 | transmuxer.on('gopInfo', function (gopInfo) {
|
7251 | self.postMessage({
|
7252 | action: 'gopInfo',
|
7253 | gopInfo: gopInfo
|
7254 | });
|
7255 | });
|
7256 | transmuxer.on('videoSegmentTimingInfo', function (timingInfo) {
|
7257 | var videoSegmentTimingInfo = {
|
7258 | start: {
|
7259 | decode: clock_4(timingInfo.start.dts),
|
7260 | presentation: clock_4(timingInfo.start.pts)
|
7261 | },
|
7262 | end: {
|
7263 | decode: clock_4(timingInfo.end.dts),
|
7264 | presentation: clock_4(timingInfo.end.pts)
|
7265 | },
|
7266 | baseMediaDecodeTime: clock_4(timingInfo.baseMediaDecodeTime)
|
7267 | };
|
7268 |
|
7269 | if (timingInfo.prependedContentDuration) {
|
7270 | videoSegmentTimingInfo.prependedContentDuration = clock_4(timingInfo.prependedContentDuration);
|
7271 | }
|
7272 |
|
7273 | self.postMessage({
|
7274 | action: 'videoSegmentTimingInfo',
|
7275 | videoSegmentTimingInfo: videoSegmentTimingInfo
|
7276 | });
|
7277 | });
|
7278 | transmuxer.on('id3Frame', function (id3Frame) {
|
7279 | self.postMessage({
|
7280 | action: 'id3Frame',
|
7281 | id3Frame: id3Frame
|
7282 | });
|
7283 | });
|
7284 | transmuxer.on('caption', function (caption) {
|
7285 | self.postMessage({
|
7286 | action: 'caption',
|
7287 | caption: caption
|
7288 | });
|
7289 | });
|
7290 | transmuxer.on('trackinfo', function (trackInfo) {
|
7291 | self.postMessage({
|
7292 | action: 'trackinfo',
|
7293 | trackInfo: trackInfo
|
7294 | });
|
7295 | });
|
7296 | transmuxer.on('audioTimingInfo', function (audioTimingInfo) {
|
7297 |
|
7298 | self.postMessage({
|
7299 | action: 'audioTimingInfo',
|
7300 | audioTimingInfo: {
|
7301 | start: clock_4(audioTimingInfo.start),
|
7302 | end: clock_4(audioTimingInfo.end)
|
7303 | }
|
7304 | });
|
7305 | });
|
7306 | transmuxer.on('videoTimingInfo', function (videoTimingInfo) {
|
7307 | self.postMessage({
|
7308 | action: 'videoTimingInfo',
|
7309 | videoTimingInfo: {
|
7310 | start: clock_4(videoTimingInfo.start),
|
7311 | end: clock_4(videoTimingInfo.end)
|
7312 | }
|
7313 | });
|
7314 | });
|
7315 | };
|
7316 |
|
7317 | var wirePartialTransmuxerEvents = function wirePartialTransmuxerEvents(self, transmuxer) {
|
7318 | transmuxer.on('data', function (event) {
|
7319 |
|
7320 |
|
7321 |
|
7322 |
|
7323 | var initSegment = {
|
7324 | data: event.data.track.initSegment.buffer,
|
7325 | byteOffset: event.data.track.initSegment.byteOffset,
|
7326 | byteLength: event.data.track.initSegment.byteLength
|
7327 | };
|
7328 | var boxes = {
|
7329 | data: event.data.boxes.buffer,
|
7330 | byteOffset: event.data.boxes.byteOffset,
|
7331 | byteLength: event.data.boxes.byteLength
|
7332 | };
|
7333 | var segment = {
|
7334 | boxes: boxes,
|
7335 | initSegment: initSegment,
|
7336 | type: event.type,
|
7337 | sequence: event.data.sequence
|
7338 | };
|
7339 |
|
7340 | if (typeof event.data.videoFrameDts !== 'undefined') {
|
7341 | segment.videoFrameDtsTime = clock_4(event.data.videoFrameDts);
|
7342 | }
|
7343 |
|
7344 | if (typeof event.data.videoFramePts !== 'undefined') {
|
7345 | segment.videoFramePtsTime = clock_4(event.data.videoFramePts);
|
7346 | }
|
7347 |
|
7348 | self.postMessage({
|
7349 | action: 'data',
|
7350 | segment: segment
|
7351 | }, [segment.boxes.data, segment.initSegment.data]);
|
7352 | });
|
7353 | transmuxer.on('id3Frame', function (id3Frame) {
|
7354 | self.postMessage({
|
7355 | action: 'id3Frame',
|
7356 | id3Frame: id3Frame
|
7357 | });
|
7358 | });
|
7359 | transmuxer.on('caption', function (caption) {
|
7360 | self.postMessage({
|
7361 | action: 'caption',
|
7362 | caption: caption
|
7363 | });
|
7364 | });
|
7365 | transmuxer.on('done', function (data) {
|
7366 | self.postMessage({
|
7367 | action: 'done',
|
7368 | type: typeFromStreamString(data)
|
7369 | });
|
7370 | });
|
7371 | transmuxer.on('partialdone', function (data) {
|
7372 | self.postMessage({
|
7373 | action: 'partialdone',
|
7374 | type: typeFromStreamString(data)
|
7375 | });
|
7376 | });
|
7377 | transmuxer.on('endedsegment', function (data) {
|
7378 | self.postMessage({
|
7379 | action: 'endedSegment',
|
7380 | type: typeFromStreamString(data)
|
7381 | });
|
7382 | });
|
7383 | transmuxer.on('trackinfo', function (trackInfo) {
|
7384 | self.postMessage({
|
7385 | action: 'trackinfo',
|
7386 | trackInfo: trackInfo
|
7387 | });
|
7388 | });
|
7389 | transmuxer.on('audioTimingInfo', function (audioTimingInfo) {
|
7390 |
|
7391 |
|
7392 |
|
7393 |
|
7394 | if (audioTimingInfo.start === null) {
|
7395 | self.postMessage({
|
7396 | action: 'audioTimingInfo',
|
7397 | audioTimingInfo: audioTimingInfo
|
7398 | });
|
7399 | return;
|
7400 | }
|
7401 |
|
7402 |
|
7403 | var timingInfoInSeconds = {
|
7404 | start: clock_4(audioTimingInfo.start)
|
7405 | };
|
7406 |
|
7407 | if (audioTimingInfo.end) {
|
7408 | timingInfoInSeconds.end = clock_4(audioTimingInfo.end);
|
7409 | }
|
7410 |
|
7411 | self.postMessage({
|
7412 | action: 'audioTimingInfo',
|
7413 | audioTimingInfo: timingInfoInSeconds
|
7414 | });
|
7415 | });
|
7416 | transmuxer.on('videoTimingInfo', function (videoTimingInfo) {
|
7417 | var timingInfoInSeconds = {
|
7418 | start: clock_4(videoTimingInfo.start)
|
7419 | };
|
7420 |
|
7421 | if (videoTimingInfo.end) {
|
7422 | timingInfoInSeconds.end = clock_4(videoTimingInfo.end);
|
7423 | }
|
7424 |
|
7425 | self.postMessage({
|
7426 | action: 'videoTimingInfo',
|
7427 | videoTimingInfo: timingInfoInSeconds
|
7428 | });
|
7429 | });
|
7430 | };
|
7431 | |
7432 |
|
7433 |
|
7434 |
|
7435 |
|
7436 |
|
7437 |
|
7438 |
|
7439 |
|
7440 | var MessageHandlers = function () {
|
7441 | function MessageHandlers(self, options) {
|
7442 | this.options = options || {};
|
7443 | this.self = self;
|
7444 | this.init();
|
7445 | }
|
7446 | |
7447 |
|
7448 |
|
7449 |
|
7450 |
|
7451 | var _proto = MessageHandlers.prototype;
|
7452 |
|
7453 | _proto.init = function init() {
|
7454 | if (this.transmuxer) {
|
7455 | this.transmuxer.dispose();
|
7456 | }
|
7457 |
|
7458 | this.transmuxer = this.options.handlePartialData ? new transmuxer$1(this.options) : new transmuxer_1(this.options);
|
7459 |
|
7460 | if (this.options.handlePartialData) {
|
7461 | wirePartialTransmuxerEvents(this.self, this.transmuxer);
|
7462 | } else {
|
7463 | wireFullTransmuxerEvents(this.self, this.transmuxer);
|
7464 | }
|
7465 | };
|
7466 |
|
7467 | _proto.pushMp4Captions = function pushMp4Captions(data) {
|
7468 | if (!this.captionParser) {
|
7469 | this.captionParser = new captionParser();
|
7470 | this.captionParser.init();
|
7471 | }
|
7472 |
|
7473 | var segment = new Uint8Array(data.data, data.byteOffset, data.byteLength);
|
7474 | var parsed = this.captionParser.parse(segment, data.trackIds, data.timescales);
|
7475 | this.self.postMessage({
|
7476 | action: 'mp4Captions',
|
7477 | captions: parsed && parsed.captions || [],
|
7478 | data: segment.buffer
|
7479 | }, [segment.buffer]);
|
7480 | };
|
7481 |
|
7482 | _proto.clearAllMp4Captions = function clearAllMp4Captions() {
|
7483 | if (this.captionParser) {
|
7484 | this.captionParser.clearAllCaptions();
|
7485 | }
|
7486 | };
|
7487 |
|
7488 | _proto.clearParsedMp4Captions = function clearParsedMp4Captions() {
|
7489 | if (this.captionParser) {
|
7490 | this.captionParser.clearParsedCaptions();
|
7491 | }
|
7492 | }
|
7493 | |
7494 |
|
7495 |
|
7496 |
|
7497 |
|
7498 |
|
7499 | ;
|
7500 |
|
7501 | _proto.push = function push(data) {
|
7502 |
|
7503 | var segment = new Uint8Array(data.data, data.byteOffset, data.byteLength);
|
7504 | this.transmuxer.push(segment);
|
7505 | }
|
7506 | |
7507 |
|
7508 |
|
7509 |
|
7510 | ;
|
7511 |
|
7512 | _proto.reset = function reset() {
|
7513 | this.transmuxer.reset();
|
7514 | }
|
7515 | |
7516 |
|
7517 |
|
7518 |
|
7519 |
|
7520 |
|
7521 |
|
7522 | ;
|
7523 |
|
7524 | _proto.setTimestampOffset = function setTimestampOffset(data) {
|
7525 | var timestampOffset = data.timestampOffset || 0;
|
7526 | this.transmuxer.setBaseMediaDecodeTime(Math.round(clock_2(timestampOffset)));
|
7527 | };
|
7528 |
|
7529 | _proto.setAudioAppendStart = function setAudioAppendStart(data) {
|
7530 | this.transmuxer.setAudioAppendStart(Math.ceil(clock_2(data.appendStart)));
|
7531 | };
|
7532 |
|
7533 | _proto.setRemux = function setRemux(data) {
|
7534 | this.transmuxer.setRemux(data.remux);
|
7535 | }
|
7536 | |
7537 |
|
7538 |
|
7539 |
|
7540 |
|
7541 |
|
7542 | ;
|
7543 |
|
7544 | _proto.flush = function flush(data) {
|
7545 | this.transmuxer.flush();
|
7546 |
|
7547 | self.postMessage({
|
7548 | action: 'done',
|
7549 | type: 'transmuxed'
|
7550 | });
|
7551 | };
|
7552 |
|
7553 | _proto.partialFlush = function partialFlush(data) {
|
7554 | this.transmuxer.partialFlush();
|
7555 |
|
7556 | self.postMessage({
|
7557 | action: 'partialdone',
|
7558 | type: 'transmuxed'
|
7559 | });
|
7560 | };
|
7561 |
|
7562 | _proto.endTimeline = function endTimeline() {
|
7563 | this.transmuxer.endTimeline();
|
7564 |
|
7565 |
|
7566 | self.postMessage({
|
7567 | action: 'endedtimeline',
|
7568 | type: 'transmuxed'
|
7569 | });
|
7570 | };
|
7571 |
|
7572 | _proto.alignGopsWith = function alignGopsWith(data) {
|
7573 | this.transmuxer.alignGopsWith(data.gopsToAlignWith.slice());
|
7574 | };
|
7575 |
|
7576 | return MessageHandlers;
|
7577 | }();
|
7578 | |
7579 |
|
7580 |
|
7581 |
|
7582 |
|
7583 |
|
7584 |
|
7585 |
|
7586 |
|
7587 | var TransmuxerWorker = function TransmuxerWorker(self) {
|
7588 | self.onmessage = function (event) {
|
7589 | if (event.data.action === 'init' && event.data.options) {
|
7590 | this.messageHandlers = new MessageHandlers(self, event.data.options);
|
7591 | return;
|
7592 | }
|
7593 |
|
7594 | if (!this.messageHandlers) {
|
7595 | this.messageHandlers = new MessageHandlers(self);
|
7596 | }
|
7597 |
|
7598 | if (event.data && event.data.action && event.data.action !== 'init') {
|
7599 | if (this.messageHandlers[event.data.action]) {
|
7600 | this.messageHandlers[event.data.action](event.data);
|
7601 | }
|
7602 | }
|
7603 | };
|
7604 | };
|
7605 |
|
7606 | var transmuxerWorker = new TransmuxerWorker(self);
|
7607 |
|
7608 | return transmuxerWorker;
|
7609 |
|
7610 | }());
|