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