Shaka Packager SDK
ec3_audio_util.cc
1 // Copyright 2016 Google LLC. 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/codecs/ec3_audio_util.h>
8 
9 #include <absl/log/check.h>
10 #include <absl/strings/escaping.h>
11 
12 #include <packager/media/base/bit_reader.h>
13 #include <packager/media/base/rcheck.h>
14 #include <packager/utils/bytes_to_string_view.h>
15 
16 namespace shaka {
17 namespace media {
18 
19 namespace {
20 
21 // Channels bit map. 16 bits.
22 // Bit, Location
23 // 0(MSB), Left
24 // 1, Center
25 // 2, Right
26 // 3, Left Surround
27 // 4, Right Surround
28 // 5, Left center/Right center pair
29 // 6, Left rear surround/Right rear surround pair
30 // 7, Center surround
31 // 8, Top center surround
32 // 9, Left surround direct/Right surround direct pair
33 // 10, Left wide/Right wide pair
34 // 11, Lvertical height/Right vertical height pair
35 // 12, Center vertical height
36 // 13, Lts/Rts pair
37 // 14, LFE2
38 // 15, LFE
39 enum kEC3AudioChannelMap {
40  kLeft = 0x8000,
41  kCenter = 0x4000,
42  kRight = 0x2000,
43  kLeftSurround = 0x1000,
44  kRightSurround = 0x800,
45  kLcRcPair = 0x400,
46  kLrsRrsPair = 0x200,
47  kCenterSurround = 0x100,
48  kTopCenterSurround = 0x80,
49  kLsdRsdPair = 0x40,
50  kLwRwPair = 0x20,
51  kLvhRvhPair = 0x10,
52  kCenterVerticalHeight = 0x8,
53  kLtsRtsPair = 0x4,
54  kLFE2 = 0x2,
55  kLFEScreen = 0x1
56 };
57 // Number of channels for the channel bit above. The first entry corresponds to
58 // kLeft, which has one channel. All the XxxPairs bits have two channels.
59 const size_t kChannelCountArray[] = {
60  1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1, 2, 1, 1,
61 };
62 static_assert(std::size(kChannelCountArray) == 16u,
63  "Channel count array should have 16 entries.");
64 
65 // EC3 Audio coding mode map (acmod) to determine EC3 audio channel layout. The
66 // value stands for the existence of Left, Center, Right, Left surround, and
67 // Right surround.
68 const uint16_t kEC3AudioCodingModeMap[] = {
69  kLeft | kRight,
70  kCenter,
71  kLeft | kRight,
72  kLeft | kCenter | kRight,
73  kLeft | kRight | kLeftSurround | kRightSurround,
74  kLeft | kCenter | kRight | kLeftSurround | kRightSurround,
75  kLeft | kRight | kLeftSurround | kRightSurround,
76  kLeft | kCenter | kRight | kLeftSurround | kRightSurround,
77 };
78 
79 // Reverse bit order.
80 uint8_t ReverseBits8(uint8_t n) {
81  n = ((n >> 1) & 0x55) | ((n & 0x55) << 1);
82  n = ((n >> 2) & 0x33) | ((n & 0x33) << 2);
83  return ((n >> 4) & 0x0f) | ((n & 0x0f) << 4);
84 }
85 
86 // Mapping of channel configurations to the MPEG audio value based on
87 // ETSI TS 102 366 V1.4.1 Digital Audio Compression (AC-3, Enhanced AC-3)
88 // Standard Table I.1.1
89 uint32_t EC3ChannelMaptoMPEGValue(uint32_t channel_map) {
90  uint32_t ret = 0;
91 
92  switch (channel_map) {
93  case kCenter:
94  ret = 1;
95  break;
96  case kLeft | kRight:
97  ret = 2;
98  break;
99  case kCenter| kLeft | kRight:
100  ret = 3;
101  break;
102  case kCenter | kLeft | kRight | kCenterSurround:
103  ret = 4;
104  break;
105  case kCenter | kLeft | kRight | kLeftSurround | kRightSurround:
106  ret = 5;
107  break;
108  case kCenter | kLeft | kRight | kLeftSurround | kRightSurround |
109  kLFEScreen:
110  ret = 6;
111  break;
112  case kCenter | kLeft | kRight | kLwRwPair | kLeftSurround | kRightSurround |
113  kLFEScreen:
114  ret = 7;
115  break;
116  case kLeft | kRight | kCenterSurround:
117  ret = 9;
118  break;
119  case kLeft | kRight | kLeftSurround | kRightSurround:
120  ret = 10;
121  break;
122  case kCenter | kLeft | kRight | kLrsRrsPair | kCenterSurround | kLFEScreen:
123  ret = 11;
124  break;
125  case kCenter | kLeft | kRight | kLeftSurround | kRightSurround |
126  kLrsRrsPair | kLFEScreen:
127  ret = 12;
128  break;
129  case kCenter | kLeft | kRight | kLeftSurround | kRightSurround |
130  kLFEScreen | kLvhRvhPair:
131  ret = 14;
132  break;
133  case kCenter | kLeft | kRight | kLeftSurround | kRightSurround |
134  kLFEScreen | kLvhRvhPair | kLtsRtsPair:
135  ret = 16;
136  break;
137  case kCenter | kLeft | kRight | kLeftSurround | kRightSurround |
138  kLFEScreen | kLvhRvhPair | kCenterVerticalHeight | kLtsRtsPair |
139  kTopCenterSurround:
140  ret = 17;
141  break;
142  case kCenter | kLeft | kRight | kLsdRsdPair | kLrsRrsPair | kLFEScreen |
143  kLvhRvhPair | kLtsRtsPair:
144  ret = 19;
145  break;
146  default:
147  ret = 0xFFFFFFFF;
148  }
149  return ret;
150 }
151 
152 bool ExtractEc3Data(const std::vector<uint8_t>& ec3_data,
153  uint8_t* audio_coding_mode,
154  bool* lfe_channel_on,
155  uint16_t* dependent_substreams_layout,
156  uint32_t* ec3_joc_complexity) {
157  BitReader bit_reader(ec3_data.data(), ec3_data.size());
158  // Read number of independent substreams and parse the independent substreams.
159  uint8_t number_independent_substreams;
160  RCHECK(bit_reader.SkipBits(13) &&
161  bit_reader.ReadBits(3, &number_independent_substreams));
162  // The value of this field is one less than the number of independent
163  // substreams present.
164  ++number_independent_substreams;
165 
166  // Parse audio_coding_mode, dependent_substreams_layout and lfe_channel_on
167  // from the first independent substream.
168  // Independent substream in EC3Specific box:
169  // fscod: 2 bits
170  // bsid: 5 bits
171  // reserved_1: 1 bit
172  // asvc: 1 bit
173  // bsmod: 3 bits
174  // acmod: 3 bits
175  // lfeon: 1 bit
176  // reserved_2: 3 bits
177  // num_dep_sub: 4 bits
178  // If num_dep_sub > 0, chan_loc is present and the size is 9 bits.
179  // Otherwise, reserved_3 is present and the size is 1 bit.
180  // chan_loc: 9 bits
181  // reserved_3: 1 bit
182  RCHECK(bit_reader.SkipBits(12));
183  RCHECK(bit_reader.ReadBits(3, audio_coding_mode));
184  RCHECK(bit_reader.ReadBits(1, lfe_channel_on));
185 
186  uint8_t number_dependent_substreams = 0;
187  RCHECK(bit_reader.SkipBits(3));
188  RCHECK(bit_reader.ReadBits(4, &number_dependent_substreams));
189 
190  *dependent_substreams_layout = 0;
191  if (number_dependent_substreams > 0) {
192  RCHECK(bit_reader.ReadBits(9, dependent_substreams_layout));
193  } else {
194  RCHECK(bit_reader.SkipBits(1));
195  }
196  *ec3_joc_complexity = 0;
197  if (bit_reader.bits_available() < 16) {
198  return true;
199  }
200 
201  RCHECK(bit_reader.SkipBits(7));
202  bool ec3_joc_flag;
203  RCHECK(bit_reader.ReadBits(1, &ec3_joc_flag));
204  if (ec3_joc_flag) {
205  RCHECK(bit_reader.ReadBits(8, ec3_joc_complexity));
206  }
207  return true;
208 }
209 
210 } // namespace
211 
212 bool CalculateEC3ChannelMap(const std::vector<uint8_t>& ec3_data,
213  uint32_t* channel_map) {
214  uint8_t audio_coding_mode;
215  bool lfe_channel_on;
216  uint16_t dependent_substreams_layout;
217  uint32_t ec3_joc_complexity;
218  if (!ExtractEc3Data(ec3_data, &audio_coding_mode, &lfe_channel_on,
219  &dependent_substreams_layout, &ec3_joc_complexity)) {
220  LOG(WARNING) << "Seeing invalid EC3 data: "
221  << absl::BytesToHexString(
222  byte_vector_to_string_view(ec3_data));
223  return false;
224  }
225 
226  // Dependent substreams layout bit map:
227  // Bit, Location
228  // 0, Lc/Rc pair
229  // 1, Lrs/Rrs pair
230  // 2, Cs
231  // 3, Ts
232  // 4, Lsd/Rsd pair
233  // 5, Lw/Rw pair
234  // 6, Lvh/Rvh pair
235  // 7, Cvh
236  // 8(MSB), LFE2
237  // Reverse bit order of dependent substreams channel layout (LFE2 not
238  // included) to apply on channel_map bit 5 - 12.
239  const uint8_t reversed_dependent_substreams_layout =
240  ReverseBits8(dependent_substreams_layout & 0xFF);
241 
242  *channel_map = kEC3AudioCodingModeMap[audio_coding_mode] |
243  (reversed_dependent_substreams_layout << 3);
244  if (dependent_substreams_layout & 0x100)
245  *channel_map |= kLFE2;
246  if (lfe_channel_on)
247  *channel_map |= kLFEScreen;
248  return true;
249 }
250 
251 bool CalculateEC3ChannelMPEGValue(const std::vector<uint8_t>& ec3_data,
252  uint32_t* ec3_channel_mpeg_value) {
253  uint32_t channel_map;
254  if (!CalculateEC3ChannelMap(ec3_data, &channel_map))
255  return false;
256  *ec3_channel_mpeg_value = EC3ChannelMaptoMPEGValue(channel_map);
257  return true;
258 }
259 
260 size_t GetEc3NumChannels(const std::vector<uint8_t>& ec3_data) {
261  uint32_t channel_map;
262  if (!CalculateEC3ChannelMap(ec3_data, &channel_map))
263  return 0;
264 
265  size_t num_channels = 0;
266  int bit = kLeft;
267  for (size_t channel_count : kChannelCountArray) {
268  if (channel_map & bit)
269  num_channels += channel_count;
270  bit >>= 1;
271  }
272  DCHECK_EQ(bit, 0);
273  return num_channels;
274 }
275 
276 bool GetEc3JocComplexity(const std::vector<uint8_t>& ec3_data,
277  uint32_t* ec3_joc_complexity) {
278  uint8_t audio_coding_mode;
279  bool lfe_channel_on;
280  uint16_t dependent_substreams_layout;
281 
282  if (!ExtractEc3Data(ec3_data, &audio_coding_mode, &lfe_channel_on,
283  &dependent_substreams_layout, ec3_joc_complexity)) {
284  LOG(WARNING) << "Seeing invalid EC3 data: "
285  << absl::BytesToHexString(
286  byte_vector_to_string_view(ec3_data));
287  return false;
288  }
289  return true;
290 }
291 
292 } // namespace media
293 } // namespace shaka
All the methods that are virtual are virtual for mocking.
Definition: crypto_flags.cc:66
std::string_view byte_vector_to_string_view(const std::vector< uint8_t > &bytes)
Convert byte vector to string_view.