Source: lib/transmuxer/ec3.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2016 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.transmuxer.Ec3');
  7. goog.require('shaka.util.ExpGolomb');
  8. /**
  9. * EC3 utils
  10. */
  11. shaka.transmuxer.Ec3 = class {
  12. /**
  13. * @param {!Uint8Array} data
  14. * @param {!number} offset
  15. * @return {?{sampleRate: number, channelCount: number,
  16. * audioConfig: !Uint8Array, frameLength: number}}
  17. */
  18. static parseFrame(data, offset) {
  19. if (offset + 8 > data.length) {
  20. // not enough bytes left
  21. return null;
  22. }
  23. if (!shaka.transmuxer.Ec3.probe(data, offset)) {
  24. return null;
  25. }
  26. const gb = new shaka.util.ExpGolomb(data.subarray(offset + 2));
  27. // Skip stream_type
  28. gb.skipBits(2);
  29. // Skip sub_stream_id
  30. gb.skipBits(3);
  31. const frameLength = (gb.readBits(11) + 1) << 1;
  32. let samplingRateCode = gb.readBits(2);
  33. let sampleRate = null;
  34. let numBlocksCode = null;
  35. if (samplingRateCode == 0x03) {
  36. samplingRateCode = gb.readBits(2);
  37. sampleRate = [24000, 22060, 16000][samplingRateCode];
  38. numBlocksCode = 3;
  39. } else {
  40. sampleRate = [48000, 44100, 32000][samplingRateCode];
  41. numBlocksCode = gb.readBits(2);
  42. }
  43. const channelMode = gb.readBits(3);
  44. const lowFrequencyEffectsChannelOn = gb.readBits(1);
  45. const bitStreamIdentification = gb.readBits(5);
  46. if (offset + frameLength > data.byteLength) {
  47. return null;
  48. }
  49. const channelsMap = [2, 1, 2, 3, 3, 4, 4, 5];
  50. const numBlocksMap = [1, 2, 3, 6];
  51. const numBlocks = numBlocksMap[numBlocksCode];
  52. const dataRateSub =
  53. Math.floor((frameLength * sampleRate) / (numBlocks * 16));
  54. const config = new Uint8Array([
  55. ((dataRateSub & 0x1FE0) >> 5),
  56. ((dataRateSub & 0x001F) << 3), // num_ind_sub = zero
  57. (sampleRate << 6) | (bitStreamIdentification << 1) | (0 << 0),
  58. (0 << 7) | (0 << 4) |
  59. (channelMode << 1) | (lowFrequencyEffectsChannelOn << 0),
  60. (0 << 5) | (0 << 1) | (0 << 0),
  61. ]);
  62. return {
  63. sampleRate,
  64. channelCount: channelsMap[channelMode] + lowFrequencyEffectsChannelOn,
  65. audioConfig: config,
  66. frameLength,
  67. };
  68. }
  69. /**
  70. * @param {!Uint8Array} data
  71. * @param {!number} offset
  72. * @return {boolean}
  73. */
  74. static probe(data, offset) {
  75. // search 16-bit 0x0B77 syncword
  76. const syncword = (data[offset] << 8) | (data[offset + 1] << 0);
  77. if (syncword === 0x0B77) {
  78. return true;
  79. } else {
  80. return false;
  81. }
  82. }
  83. };
  84. /**
  85. * @const {number}
  86. */
  87. shaka.transmuxer.Ec3.EC3_SAMPLES_PER_FRAME = 1536;