DASH Media Packaging SDK
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
ec3_audio_util.cc
1 // Copyright 2016 Google Inc. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 
7 #include "packager/media/base/bit_reader.h"
8 #include "packager/media/base/rcheck.h"
9 #include "packager/media/filters/ec3_audio_util.h"
10 
11 namespace shaka {
12 namespace media {
13 
14 namespace {
15 
16 // Channels bit map. 16 bits.
17 // Bit, Location
18 // 0(MSB), Left
19 // 1, Center
20 // 2, Right
21 // 3, Left Surround
22 // 4, Right Surround
23 // 5, Left center/Right center pair
24 // 6, Left rear surround/Right rear surround pair
25 // 7, Center surround
26 // 8, Top center surround
27 // 9, Left surround direct/Right surround direct pair
28 // 10, Left wide/Right wide pair
29 // 11, Lvertical height/Right vertical height pair
30 // 12, Center vertical height
31 // 13, Lts/Rts pair
32 // 14, LFE2
33 // 15, LFE
34 enum kEC3AudioChannelMap {
35  kLeft = 0x8000,
36  kCenter = 0x4000,
37  kRight = 0x2000,
38  kLeftSurround = 0x1000,
39  kRightSurround = 0x800,
40  kLcRcPair = 0x400,
41  kLrsRrsPair = 0x200,
42  kCenterSurround = 0x100,
43  kTopCenterSurround = 0x80,
44  kLsdRsdPair = 0x40,
45  kLwRwPair = 0x20,
46  kLvhRvhPair = 0x10,
47  kCenterVerticalHeight = 0x8,
48  kLtsRtsPair = 0x4,
49  kLFE2 = 0x2,
50  kLFEScreen = 0x1
51 };
52 
53 // EC3 Audio coding mode map (acmod) to determine EC3 audio channel layout. The
54 // value stands for the existence of Left, Center, Right, Left surround, and
55 // Right surround.
56 const uint16_t kEC3AudioCodingModeMap[] = {
57  kLeft | kRight,
58  kCenter,
59  kLeft | kRight,
60  kLeft | kCenter | kRight,
61  kLeft | kRight | kLeftSurround | kRightSurround,
62  kLeft | kCenter | kRight | kLeftSurround | kRightSurround,
63  kLeft | kRight | kLeftSurround | kRightSurround,
64  kLeft | kCenter | kRight | kLeftSurround | kRightSurround,
65 };
66 
67 // Reverse bit order.
68 uint8_t ReverseBits8(uint8_t n) {
69  n = ((n >> 1) & 0x55) | ((n & 0x55) << 1);
70  n = ((n >> 2) & 0x33) | ((n & 0x33) << 2);
71  return ((n >> 4) & 0x0f) | ((n & 0x0f) << 4);
72 }
73 
74 bool ExtractEc3Data(const std::vector<uint8_t>& ec3_data,
75  uint8_t* audio_coding_mode,
76  bool* lfe_channel_on,
77  uint16_t* dependent_substreams_layout) {
78  BitReader bit_reader(ec3_data.data(), ec3_data.size());
79  // Read number of independent substreams and parse the independent substreams.
80  uint8_t number_independent_substreams;
81  RCHECK(bit_reader.SkipBits(13) &&
82  bit_reader.ReadBits(3, &number_independent_substreams));
83  // The value of this field is one less than the number of independent
84  // substreams present.
85  ++number_independent_substreams;
86 
87  // Parse audio_coding_mode, dependent_substreams_layout and lfe_channel_on
88  // from the first independent substream.
89  // Independent substream in EC3Specific box:
90  // fscod: 2 bits
91  // bsid: 5 bits
92  // reserved_1: 1 bit
93  // asvc: 1 bit
94  // bsmod: 3 bits
95  // acmod: 3 bits
96  // lfeon: 1 bit
97  // reserved_2: 3 bits
98  // num_dep_sub: 4 bits
99  // If num_dep_sub > 0, chan_loc is present and the size is 9 bits.
100  // Otherwise, reserved_3 is present and the size is 1 bit.
101  // chan_loc: 9 bits
102  // reserved_3: 1 bit
103  RCHECK(bit_reader.SkipBits(12));
104  RCHECK(bit_reader.ReadBits(3, audio_coding_mode));
105  RCHECK(bit_reader.ReadBits(1, lfe_channel_on));
106 
107  uint8_t number_dependent_substreams = 0;
108  RCHECK(bit_reader.SkipBits(3));
109  RCHECK(bit_reader.ReadBits(4, &number_dependent_substreams));
110 
111  *dependent_substreams_layout = 0;
112  if (number_dependent_substreams > 0) {
113  RCHECK(bit_reader.ReadBits(9, dependent_substreams_layout));
114  }
115 
116  return true;
117 }
118 
119 } // namespace
120 
121 bool CalculateEC3ChannelMap(const std::vector<uint8_t>& ec3_data, uint32_t* channel_map) {
122  uint8_t audio_coding_mode;
123  bool lfe_channel_on;
124  uint16_t dependent_substreams_layout;
125  if (!ExtractEc3Data(ec3_data, &audio_coding_mode, &lfe_channel_on,
126  &dependent_substreams_layout))
127  return false;
128 
129  // Dependent substreams layout bit map:
130  // Bit, Location
131  // 0, Lc/Rc pair
132  // 1, Lrs/Rrs pair
133  // 2, Cs
134  // 3, Ts
135  // 4, Lsd/Rsd pair
136  // 5, Lw/Rw pair
137  // 6, Lvh/Rvh pair
138  // 7, Cvh
139  // 8(MSB), LFE2
140  // Reverse bit order of dependent substreams channel layout (LFE2 not
141  // included) to apply on channel_map bit 5 - 12.
142  const uint8_t reversed_dependent_substreams_layout =
143  ReverseBits8(dependent_substreams_layout & 0xFF);
144 
145  *channel_map = kEC3AudioCodingModeMap[audio_coding_mode] |
146  (reversed_dependent_substreams_layout << 3);
147  if (dependent_substreams_layout & 0x100)
148  *channel_map |= kLFE2;
149  if (lfe_channel_on)
150  *channel_map |= kLFEScreen;
151  return true;
152 }
153 
154 } // namespace media
155 } // namespace shaka