index.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /**
  2. * mux.js
  3. *
  4. * Copyright (c) 2016 Brightcove
  5. * All rights reserved.
  6. *
  7. * A stream-based aac to mp4 converter. This utility can be used to
  8. * deliver mp4s to a SourceBuffer on platforms that support native
  9. * Media Source Extensions.
  10. */
  11. 'use strict';
  12. var Stream = require('../utils/stream.js');
  13. // Constants
  14. var AacStream;
  15. /**
  16. * Splits an incoming stream of binary data into ADTS and ID3 Frames.
  17. */
  18. AacStream = function() {
  19. var
  20. everything = new Uint8Array(),
  21. timeStamp = 0;
  22. AacStream.prototype.init.call(this);
  23. this.setTimestamp = function(timestamp) {
  24. timeStamp = timestamp;
  25. };
  26. this.parseId3TagSize = function(header, byteIndex) {
  27. var
  28. returnSize = (header[byteIndex + 6] << 21) |
  29. (header[byteIndex + 7] << 14) |
  30. (header[byteIndex + 8] << 7) |
  31. (header[byteIndex + 9]),
  32. flags = header[byteIndex + 5],
  33. footerPresent = (flags & 16) >> 4;
  34. if (footerPresent) {
  35. return returnSize + 20;
  36. }
  37. return returnSize + 10;
  38. };
  39. this.parseAdtsSize = function(header, byteIndex) {
  40. var
  41. lowThree = (header[byteIndex + 5] & 0xE0) >> 5,
  42. middle = header[byteIndex + 4] << 3,
  43. highTwo = header[byteIndex + 3] & 0x3 << 11;
  44. return (highTwo | middle) | lowThree;
  45. };
  46. this.push = function(bytes) {
  47. var
  48. frameSize = 0,
  49. byteIndex = 0,
  50. bytesLeft,
  51. chunk,
  52. packet,
  53. tempLength;
  54. // If there are bytes remaining from the last segment, prepend them to the
  55. // bytes that were pushed in
  56. if (everything.length) {
  57. tempLength = everything.length;
  58. everything = new Uint8Array(bytes.byteLength + tempLength);
  59. everything.set(everything.subarray(0, tempLength));
  60. everything.set(bytes, tempLength);
  61. } else {
  62. everything = bytes;
  63. }
  64. while (everything.length - byteIndex >= 3) {
  65. if ((everything[byteIndex] === 'I'.charCodeAt(0)) &&
  66. (everything[byteIndex + 1] === 'D'.charCodeAt(0)) &&
  67. (everything[byteIndex + 2] === '3'.charCodeAt(0))) {
  68. // Exit early because we don't have enough to parse
  69. // the ID3 tag header
  70. if (everything.length - byteIndex < 10) {
  71. break;
  72. }
  73. // check framesize
  74. frameSize = this.parseId3TagSize(everything, byteIndex);
  75. // Exit early if we don't have enough in the buffer
  76. // to emit a full packet
  77. if (frameSize > everything.length) {
  78. break;
  79. }
  80. chunk = {
  81. type: 'timed-metadata',
  82. data: everything.subarray(byteIndex, byteIndex + frameSize)
  83. };
  84. this.trigger('data', chunk);
  85. byteIndex += frameSize;
  86. continue;
  87. } else if ((everything[byteIndex] & 0xff === 0xff) &&
  88. ((everything[byteIndex + 1] & 0xf0) === 0xf0)) {
  89. // Exit early because we don't have enough to parse
  90. // the ADTS frame header
  91. if (everything.length - byteIndex < 7) {
  92. break;
  93. }
  94. frameSize = this.parseAdtsSize(everything, byteIndex);
  95. // Exit early if we don't have enough in the buffer
  96. // to emit a full packet
  97. if (frameSize > everything.length) {
  98. break;
  99. }
  100. packet = {
  101. type: 'audio',
  102. data: everything.subarray(byteIndex, byteIndex + frameSize),
  103. pts: timeStamp,
  104. dts: timeStamp
  105. };
  106. this.trigger('data', packet);
  107. byteIndex += frameSize;
  108. continue;
  109. }
  110. byteIndex++;
  111. }
  112. bytesLeft = everything.length - byteIndex;
  113. if (bytesLeft > 0) {
  114. everything = everything.subarray(byteIndex);
  115. } else {
  116. everything = new Uint8Array();
  117. }
  118. };
  119. };
  120. AacStream.prototype = new Stream();
  121. module.exports = AacStream;