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 <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
16namespace shaka {
17namespace media {
18
19namespace {
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
39enum 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.
59const size_t kChannelCountArray[] = {
60 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1, 2, 1, 1,
61};
62static_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.
68const 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.
80uint8_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
89uint32_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
152bool 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
212bool 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(
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
251bool 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
260size_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
276bool 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(
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.
std::string_view byte_vector_to_string_view(const std::vector< uint8_t > &bytes)
Convert byte vector to string_view.