7 #include <packager/media/codecs/ec3_audio_util.h>
9 #include <absl/log/check.h>
10 #include <absl/strings/escaping.h>
12 #include <packager/media/base/bit_reader.h>
13 #include <packager/media/base/rcheck.h>
14 #include <packager/utils/bytes_to_string_view.h>
39 enum kEC3AudioChannelMap {
43 kLeftSurround = 0x1000,
44 kRightSurround = 0x800,
47 kCenterSurround = 0x100,
48 kTopCenterSurround = 0x80,
52 kCenterVerticalHeight = 0x8,
59 const size_t kChannelCountArray[] = {
60 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1, 2, 1, 1,
62 static_assert(std::size(kChannelCountArray) == 16u,
63 "Channel count array should have 16 entries.");
68 const uint16_t kEC3AudioCodingModeMap[] = {
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,
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);
89 uint32_t EC3ChannelMaptoMPEGValue(uint32_t channel_map) {
92 switch (channel_map) {
99 case kCenter| kLeft | kRight:
102 case kCenter | kLeft | kRight | kCenterSurround:
105 case kCenter | kLeft | kRight | kLeftSurround | kRightSurround:
108 case kCenter | kLeft | kRight | kLeftSurround | kRightSurround |
112 case kCenter | kLeft | kRight | kLwRwPair | kLeftSurround | kRightSurround |
116 case kLeft | kRight | kCenterSurround:
119 case kLeft | kRight | kLeftSurround | kRightSurround:
122 case kCenter | kLeft | kRight | kLrsRrsPair | kCenterSurround | kLFEScreen:
125 case kCenter | kLeft | kRight | kLeftSurround | kRightSurround |
126 kLrsRrsPair | kLFEScreen:
129 case kCenter | kLeft | kRight | kLeftSurround | kRightSurround |
130 kLFEScreen | kLvhRvhPair:
133 case kCenter | kLeft | kRight | kLeftSurround | kRightSurround |
134 kLFEScreen | kLvhRvhPair | kLtsRtsPair:
137 case kCenter | kLeft | kRight | kLeftSurround | kRightSurround |
138 kLFEScreen | kLvhRvhPair | kCenterVerticalHeight | kLtsRtsPair |
142 case kCenter | kLeft | kRight | kLsdRsdPair | kLrsRrsPair | kLFEScreen |
143 kLvhRvhPair | kLtsRtsPair:
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());
159 uint8_t number_independent_substreams;
160 RCHECK(bit_reader.SkipBits(13) &&
161 bit_reader.ReadBits(3, &number_independent_substreams));
164 ++number_independent_substreams;
182 RCHECK(bit_reader.SkipBits(12));
183 RCHECK(bit_reader.ReadBits(3, audio_coding_mode));
184 RCHECK(bit_reader.ReadBits(1, lfe_channel_on));
186 uint8_t number_dependent_substreams = 0;
187 RCHECK(bit_reader.SkipBits(3));
188 RCHECK(bit_reader.ReadBits(4, &number_dependent_substreams));
190 *dependent_substreams_layout = 0;
191 if (number_dependent_substreams > 0) {
192 RCHECK(bit_reader.ReadBits(9, dependent_substreams_layout));
194 RCHECK(bit_reader.SkipBits(1));
196 *ec3_joc_complexity = 0;
197 if (bit_reader.bits_available() < 16) {
201 RCHECK(bit_reader.SkipBits(7));
203 RCHECK(bit_reader.ReadBits(1, &ec3_joc_flag));
205 RCHECK(bit_reader.ReadBits(8, ec3_joc_complexity));
212 bool CalculateEC3ChannelMap(
const std::vector<uint8_t>& ec3_data,
213 uint32_t* channel_map) {
214 uint8_t audio_coding_mode;
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(
239 const uint8_t reversed_dependent_substreams_layout =
240 ReverseBits8(dependent_substreams_layout & 0xFF);
242 *channel_map = kEC3AudioCodingModeMap[audio_coding_mode] |
243 (reversed_dependent_substreams_layout << 3);
244 if (dependent_substreams_layout & 0x100)
245 *channel_map |= kLFE2;
247 *channel_map |= kLFEScreen;
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))
256 *ec3_channel_mpeg_value = EC3ChannelMaptoMPEGValue(channel_map);
260 size_t GetEc3NumChannels(
const std::vector<uint8_t>& ec3_data) {
261 uint32_t channel_map;
262 if (!CalculateEC3ChannelMap(ec3_data, &channel_map))
265 size_t num_channels = 0;
267 for (
size_t channel_count : kChannelCountArray) {
268 if (channel_map & bit)
269 num_channels += channel_count;
276 bool GetEc3JocComplexity(
const std::vector<uint8_t>& ec3_data,
277 uint32_t* ec3_joc_complexity) {
278 uint8_t audio_coding_mode;
280 uint16_t dependent_substreams_layout;
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(
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.