1cc97309 by David LaPalomento

Fix ADTS parsing over multiple events

Simplify ADTS parsing algorith to assume it is invoked at the start of a sync sequence. Track progress through the ADTS data accrately so that subsequent events carrying frames after the first are parsed correclty.
1 parent 9756fcae
...@@ -38,7 +38,7 @@ ADTS_SAMPLING_FREQUENCIES = [ ...@@ -38,7 +38,7 @@ ADTS_SAMPLING_FREQUENCIES = [
38 8000, 38 8000,
39 7350 39 7350
40 ]; 40 ];
41 41
42 mp4 = videojs.mp4; 42 mp4 = videojs.mp4;
43 43
44 /** 44 /**
...@@ -434,45 +434,27 @@ AacStream = function() { ...@@ -434,45 +434,27 @@ AacStream = function() {
434 434
435 buffer = packet.data; 435 buffer = packet.data;
436 436
437 // find ADTS frame sync sequences 437 // unpack any ADTS frames which have been fully received
438 // ADTS frames start with 12 byte-aligned ones 438 while (i + 4 < buffer.length) {
439 while (i < buffer.length) { 439 // frame length is a 13 bit integer starting 16 bits from the
440 switch (buffer[i] & 0xf0) { 440 // end of the sync sequence
441 case 0xf0: 441 frameLength = ((buffer[i + 2] & 0x03) << 11) |
442 // skip past non-sync sequences 442 (buffer[i + 3] << 3) |
443 if (buffer[i - 1] !== 0xff) { 443 ((buffer[i + 4] & 0xe0) >> 5);
444 i++; 444
445 break; 445 // deliver the AAC frame
446 } 446 this.trigger('data', {
447 447 channelcount: ((buffer[i + 1] & 1) << 3) |
448 // parse the ADTS header 448 ((buffer[i + 2] & 0xc0) >> 6),
449 449 samplerate: ADTS_SAMPLING_FREQUENCIES[(buffer[i + 1] & 0x3c) >> 2],
450 // frame length is a 13 bit integer starting 16 bits from the 450 // assume ISO/IEC 14496-12 AudioSampleEntry default of 16
451 // end of the sync sequence 451 samplesize: 16,
452 frameLength = ((buffer[i + 2] & 0x03) << 11) | 452 data: buffer.subarray(i + 6, i + frameLength - 1)
453 (buffer[i + 3] << 3) | 453 });
454 ((buffer[i + 4] & 0xe0) >> 5);
455
456 // deliver the AAC frame
457 this.trigger('data', {
458 channelcount: ((buffer[i + 1] & 1) << 3) |
459 ((buffer[i + 2] & 0xc0) >> 6),
460 samplerate: ADTS_SAMPLING_FREQUENCIES[(buffer[i + 1] & 0x3c) >> 2],
461 // assume ISO/IEC 14496-12 AudioSampleEntry default of 16
462 samplesize: 16,
463 data: buffer.subarray(i + 6, i + frameLength - 1)
464 });
465 454
466 // move to one byte beyond the frame length to continue 455 // flush the finished frame and try again
467 // searching for sync sequences 456 buffer = buffer.subarray(i + frameLength - 1);
468 i += frameLength; 457 i = 1;
469 break;
470 default:
471 // the top four bytes are not all ones so the end of the
472 // closest possible start sequence is at least two bytes ahead
473 i += 2;
474 break;
475 }
476 } 458 }
477 }; 459 };
478 }; 460 };
...@@ -514,7 +496,7 @@ AudioSegmentStream = function(track) { ...@@ -514,7 +496,7 @@ AudioSegmentStream = function(track) {
514 496
515 data.set(currentFrame.data, i); 497 data.set(currentFrame.data, i);
516 i += currentFrame.data.byteLength; 498 i += currentFrame.data.byteLength;
517 499
518 aacFrames.shift(); 500 aacFrames.shift();
519 } 501 }
520 aacFramesLength = 0; 502 aacFramesLength = 0;
...@@ -944,7 +926,7 @@ Transmuxer = function() { ...@@ -944,7 +926,7 @@ Transmuxer = function() {
944 pps, 926 pps,
945 927
946 packetStream, parseStream, elementaryStream, 928 packetStream, parseStream, elementaryStream,
947 aacStream, h264Stream, 929 aacStream, h264Stream,
948 videoSegmentStream, audioSegmentStream; 930 videoSegmentStream, audioSegmentStream;
949 931
950 Transmuxer.prototype.init.call(this); 932 Transmuxer.prototype.init.call(this);
......
...@@ -1007,6 +1007,40 @@ test('generates AAC frame events from ADTS bytes', function() { ...@@ -1007,6 +1007,40 @@ test('generates AAC frame events from ADTS bytes', function() {
1007 equal(frames[0].samplesize, 16, 'parsed samplesize'); 1007 equal(frames[0].samplesize, 16, 'parsed samplesize');
1008 }); 1008 });
1009 1009
1010 test('parses across packets', function() {
1011
1012 var frames = [];
1013 aacStream.on('data', function(frame) {
1014 frames.push(frame);
1015 });
1016 aacStream.push({
1017 type: 'audio',
1018 data: new Uint8Array([
1019 0xff, 0xf1, // no CRC
1020 0x10, // AAC Main, 44.1KHz
1021 0xbc, 0x01, 0x20, // 2 channels, frame length 9 bytes
1022 0x00, // one AAC per ADTS frame
1023 0x12, 0x34 // AAC payload 1
1024 ])
1025 });
1026 aacStream.push({
1027 type: 'audio',
1028 data: new Uint8Array([
1029 0xff, 0xf1, // no CRC
1030 0x10, // AAC Main, 44.1KHz
1031 0xbc, 0x01, 0x20, // 2 channels, frame length 9 bytes
1032 0x00, // one AAC per ADTS frame
1033 0x9a, 0xbc, // AAC payload 2
1034 0xde, 0xf0 // extra junk that should be ignored
1035 ])
1036 });
1037
1038 equal(frames.length, 2, 'parsed two frames');
1039 deepEqual(frames[1].data,
1040 new Uint8Array([0x9a, 0xbc]),
1041 'extracted the second AAC frame');
1042 });
1043
1010 // not handled: ADTS with CRC 1044 // not handled: ADTS with CRC
1011 // ADTS with payload broken across push events 1045 // ADTS with payload broken across push events
1012 1046
......