adts.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /**
  2. * mux.js
  3. *
  4. * Copyright (c) Brightcove
  5. * Licensed Apache-2.0 https://github.com/videojs/mux.js/blob/master/LICENSE
  6. */
  7. 'use strict';
  8. var Stream = require('../utils/stream.js');
  9. var ONE_SECOND_IN_TS = require('../utils/clock').ONE_SECOND_IN_TS;
  10. var _AdtsStream;
  11. var ADTS_SAMPLING_FREQUENCIES = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];
  12. /*
  13. * Accepts a ElementaryStream and emits data events with parsed
  14. * AAC Audio Frames of the individual packets. Input audio in ADTS
  15. * format is unpacked and re-emitted as AAC frames.
  16. *
  17. * @see http://wiki.multimedia.cx/index.php?title=ADTS
  18. * @see http://wiki.multimedia.cx/?title=Understanding_AAC
  19. */
  20. _AdtsStream = function AdtsStream(handlePartialSegments) {
  21. var buffer,
  22. frameNum = 0;
  23. _AdtsStream.prototype.init.call(this);
  24. this.skipWarn_ = function (start, end) {
  25. this.trigger('log', {
  26. level: 'warn',
  27. message: "adts skiping bytes " + start + " to " + end + " in frame " + frameNum + " outside syncword"
  28. });
  29. };
  30. this.push = function (packet) {
  31. var i = 0,
  32. frameLength,
  33. protectionSkipBytes,
  34. frameEnd,
  35. oldBuffer,
  36. sampleCount,
  37. adtsFrameDuration;
  38. if (!handlePartialSegments) {
  39. frameNum = 0;
  40. }
  41. if (packet.type !== 'audio') {
  42. // ignore non-audio data
  43. return;
  44. } // Prepend any data in the buffer to the input data so that we can parse
  45. // aac frames the cross a PES packet boundary
  46. if (buffer && buffer.length) {
  47. oldBuffer = buffer;
  48. buffer = new Uint8Array(oldBuffer.byteLength + packet.data.byteLength);
  49. buffer.set(oldBuffer);
  50. buffer.set(packet.data, oldBuffer.byteLength);
  51. } else {
  52. buffer = packet.data;
  53. } // unpack any ADTS frames which have been fully received
  54. // for details on the ADTS header, see http://wiki.multimedia.cx/index.php?title=ADTS
  55. var skip; // We use i + 7 here because we want to be able to parse the entire header.
  56. // If we don't have enough bytes to do that, then we definitely won't have a full frame.
  57. while (i + 7 < buffer.length) {
  58. // Look for the start of an ADTS header..
  59. if (buffer[i] !== 0xFF || (buffer[i + 1] & 0xF6) !== 0xF0) {
  60. if (typeof skip !== 'number') {
  61. skip = i;
  62. } // If a valid header was not found, jump one forward and attempt to
  63. // find a valid ADTS header starting at the next byte
  64. i++;
  65. continue;
  66. }
  67. if (typeof skip === 'number') {
  68. this.skipWarn_(skip, i);
  69. skip = null;
  70. } // The protection skip bit tells us if we have 2 bytes of CRC data at the
  71. // end of the ADTS header
  72. protectionSkipBytes = (~buffer[i + 1] & 0x01) * 2; // Frame length is a 13 bit integer starting 16 bits from the
  73. // end of the sync sequence
  74. // NOTE: frame length includes the size of the header
  75. frameLength = (buffer[i + 3] & 0x03) << 11 | buffer[i + 4] << 3 | (buffer[i + 5] & 0xe0) >> 5;
  76. sampleCount = ((buffer[i + 6] & 0x03) + 1) * 1024;
  77. adtsFrameDuration = sampleCount * ONE_SECOND_IN_TS / ADTS_SAMPLING_FREQUENCIES[(buffer[i + 2] & 0x3c) >>> 2]; // If we don't have enough data to actually finish this ADTS frame,
  78. // then we have to wait for more data
  79. if (buffer.byteLength - i < frameLength) {
  80. break;
  81. } // Otherwise, deliver the complete AAC frame
  82. this.trigger('data', {
  83. pts: packet.pts + frameNum * adtsFrameDuration,
  84. dts: packet.dts + frameNum * adtsFrameDuration,
  85. sampleCount: sampleCount,
  86. audioobjecttype: (buffer[i + 2] >>> 6 & 0x03) + 1,
  87. channelcount: (buffer[i + 2] & 1) << 2 | (buffer[i + 3] & 0xc0) >>> 6,
  88. samplerate: ADTS_SAMPLING_FREQUENCIES[(buffer[i + 2] & 0x3c) >>> 2],
  89. samplingfrequencyindex: (buffer[i + 2] & 0x3c) >>> 2,
  90. // assume ISO/IEC 14496-12 AudioSampleEntry default of 16
  91. samplesize: 16,
  92. // data is the frame without it's header
  93. data: buffer.subarray(i + 7 + protectionSkipBytes, i + frameLength)
  94. });
  95. frameNum++;
  96. i += frameLength;
  97. }
  98. if (typeof skip === 'number') {
  99. this.skipWarn_(skip, i);
  100. skip = null;
  101. } // remove processed bytes from the buffer.
  102. buffer = buffer.subarray(i);
  103. };
  104. this.flush = function () {
  105. frameNum = 0;
  106. this.trigger('done');
  107. };
  108. this.reset = function () {
  109. buffer = void 0;
  110. this.trigger('reset');
  111. };
  112. this.endTimeline = function () {
  113. buffer = void 0;
  114. this.trigger('endedtimeline');
  115. };
  116. };
  117. _AdtsStream.prototype = new Stream();
  118. module.exports = _AdtsStream;