7 #include <packager/media/codecs/ac4_audio_util.h>
9 #include <absl/strings/escaping.h>
10 #include <absl/strings/str_format.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>
42 enum kAC4AudioChannelGroupIndex {
52 kTopfrontCentre = 0x200,
53 kTopbackCentre = 0x400,
57 kBottomFrontCentre = 0x4000,
59 kLscrRscrPair = 0x10000,
61 kVhlVhrPair = 0x40000,
67 uint32_t AC4ChannelMasktoMPEGValue(uint32_t channel_mask) {
70 switch (channel_mask) {
77 case kCentre | kLRPair:
80 case kCentre | kLRPair | kBackCentre:
83 case kCentre | kLRPair | kLsRsPair:
86 case kCentre | kLRPair | kLsRsPair | kLFE:
89 case kCentre | kLRPair | kLsRsPair | kLFE | kLwRw:
92 case kBackCentre | kLRPair:
95 case kLRPair | kLsRsPair:
98 case kCentre | kLRPair | kLsRsPair | kLFE | kBackCentre:
101 case kCentre | kLRPair | kLsRsPair | kLbRbPair | kLFE:
104 case kLwRw | kBackCentre | kBottomFrontCentre | kBflBfrPair | kLFE2 |
105 kTopCentre | kTopbackCentre | kTopfrontCentre | kTslTsrPair | kLFE |
106 kTblTbrPair | kTflTfrPair | kLbRbPair | kLsRsPair | kCentre | kLRPair:
107 case kVhlVhrPair | kLwRw | kBackCentre | kBottomFrontCentre | kBflBfrPair|
108 kLFE2 | kTopCentre | kTopbackCentre | kTopfrontCentre | kTslTsrPair |
109 kLFE | kTblTbrPair | kLbRbPair | kLsRsPair | kCentre | kLRPair:
112 case kLFE | kTflTfrPair | kLsRsPair | kCentre | kLRPair:
113 case kVhlVhrPair | kLFE | kCentre | kLRPair | kLsRsPair:
116 case kLFE2 | kTopbackCentre | kLFE | kTflTfrPair | kCentre | kLRPair |
117 kLsRsPair | kLbRbPair:
118 case kVhlVhrPair | kLFE2 | kTopbackCentre | kLFE | kCentre | kLRPair |
119 kLsRsPair | kLbRbPair:
122 case kLFE | kTblTbrPair | kTflTfrPair | kLsRsPair | kCentre | kLRPair:
123 case kVhlVhrPair | kLFE | kTblTbrPair | kLsRsPair | kCentre | kLRPair:
126 case kTopCentre | kTopfrontCentre | kLFE | kTblTbrPair | kTflTfrPair |
127 kLsRsPair | kCentre | kLRPair:
128 case kVhlVhrPair | kTopCentre | kTopfrontCentre | kLFE | kTblTbrPair |
129 kLsRsPair | kCentre | kLRPair:
132 case kTopCentre | kTopfrontCentre | kLFE | kTblTbrPair | kTflTfrPair |
133 kCentre | kLRPair | kLsRsPair | kLbRbPair:
134 case kVhlVhrPair | kTopCentre | kTopfrontCentre | kLFE | kTblTbrPair |
135 kCentre | kLRPair | kLsRsPair | kLbRbPair:
138 case kLFE | kTblTbrPair | kTflTfrPair | kCentre | kLRPair | kLsRsPair |
140 case kVhlVhrPair | kLFE | kTblTbrPair | kCentre | kLRPair | kLsRsPair |
144 case kLscrRscrPair | kLFE | kTblTbrPair | kTflTfrPair | kCentre | kLRPair |
145 kLsRsPair | kLbRbPair:
146 case kVhlVhrPair | kLscrRscrPair | kLFE | kTblTbrPair | kCentre | kLRPair |
147 kLsRsPair | kLbRbPair:
158 bool ParseAC4SubStreamGroupDsi(BitReader& bit_reader) {
159 bool b_substream_present;
160 RCHECK(bit_reader.ReadBits(1, &b_substream_present));
162 RCHECK(bit_reader.ReadBits(1, &b_hsf_ext));
163 bool b_channel_coded;
164 RCHECK(bit_reader.ReadBits(1, &b_channel_coded));
165 uint8_t n_substreams;
166 RCHECK(bit_reader.ReadBits(8, &n_substreams));
167 for (uint8_t i = 0; i < n_substreams; i++) {
168 RCHECK(bit_reader.SkipBits(2));
169 bool b_substream_bitrate_indicator;
170 RCHECK(bit_reader.ReadBits(1, &b_substream_bitrate_indicator));
171 if (b_substream_bitrate_indicator) {
172 RCHECK(bit_reader.SkipBits(5));
174 if (b_channel_coded) {
175 RCHECK(bit_reader.SkipBits(24));
178 RCHECK(bit_reader.ReadBits(1, &b_ajoc));
181 RCHECK(bit_reader.ReadBits(1, &b_static_dmx));
183 RCHECK(bit_reader.SkipBits(4));
185 RCHECK(bit_reader.SkipBits(6));
187 RCHECK(bit_reader.SkipBits(4));
191 RCHECK(bit_reader.ReadBits(1, &b_content_type));
192 if (b_content_type) {
193 RCHECK(bit_reader.SkipBits(3));
194 bool b_language_indicator;
195 RCHECK(bit_reader.ReadBits(1, &b_language_indicator));
196 if (b_language_indicator) {
197 uint8_t n_language_tag_bytes;
198 RCHECK(bit_reader.ReadBits(6, &n_language_tag_bytes));
199 RCHECK(bit_reader.SkipBits(n_language_tag_bytes * 8));
207 bool ParseAC4PresentationV1Dsi(BitReader& bit_reader,
210 uint32_t* presentation_channel_mask_v1,
211 bool* dolby_cbi_indicator,
212 uint8_t* dolby_atmos_indicator) {
215 const size_t presentation_start = bit_reader.bit_position();
216 uint8_t presentation_config_v1;
217 RCHECK(bit_reader.ReadBits(5, &presentation_config_v1));
218 uint8_t b_add_emdf_substreams;
221 *presentation_channel_mask_v1 = 2;
222 *dolby_cbi_indicator =
false;
223 *dolby_atmos_indicator = 0;
224 if (presentation_config_v1 == 0x06) {
225 b_add_emdf_substreams = 1;
227 RCHECK(bit_reader.ReadBits(3, mdcompat));
228 bool b_presentation_id;
229 RCHECK(bit_reader.ReadBits(1, &b_presentation_id));
230 if (b_presentation_id) {
231 RCHECK(bit_reader.SkipBits(5));
233 RCHECK(bit_reader.SkipBits(19));
234 bool b_presentation_channel_coded;
235 RCHECK(bit_reader.ReadBits(1, &b_presentation_channel_coded));
236 *presentation_channel_mask_v1 = 0;
237 if (b_presentation_channel_coded) {
238 uint8_t dsi_presentation_ch_mode;
239 RCHECK(bit_reader.ReadBits(5, &dsi_presentation_ch_mode));
240 if (dsi_presentation_ch_mode >= 11 && dsi_presentation_ch_mode <= 14) {
241 RCHECK(bit_reader.SkipBits(1));
242 uint8_t pres_top_channel_pairs;
243 RCHECK(bit_reader.ReadBits(2, &pres_top_channel_pairs));
244 if (pres_top_channel_pairs) {
245 *dolby_cbi_indicator =
true;
247 }
else if (dsi_presentation_ch_mode == 15) {
248 *dolby_cbi_indicator =
true;
250 RCHECK(bit_reader.ReadBits(24, presentation_channel_mask_v1));
252 bool b_presentation_core_differs;
253 RCHECK(bit_reader.ReadBits(1, &b_presentation_core_differs));
254 if (b_presentation_core_differs) {
255 bool b_presentation_core_channel_coded;
256 RCHECK(bit_reader.ReadBits(1, &b_presentation_core_channel_coded));
257 if (b_presentation_core_channel_coded) {
258 RCHECK(bit_reader.SkipBits(2));
261 bool b_presentation_filter;
262 RCHECK(bit_reader.ReadBits(1, &b_presentation_filter));
263 if (b_presentation_filter) {
264 RCHECK(bit_reader.SkipBits(1));
265 uint8_t n_filter_bytes;
266 RCHECK(bit_reader.ReadBits(8, &n_filter_bytes));
267 RCHECK(bit_reader.SkipBits(n_filter_bytes * 8));
269 if (presentation_config_v1 == 0x1f) {
270 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
272 RCHECK(bit_reader.SkipBits(1));
273 if (presentation_config_v1 == 0 ||
274 presentation_config_v1 == 1 ||
275 presentation_config_v1 == 2) {
276 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
277 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
279 if (presentation_config_v1 == 3 || presentation_config_v1 == 4) {
280 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
281 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
282 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
284 if (presentation_config_v1 == 5) {
285 uint8_t n_substream_groups_minus2;
286 RCHECK(bit_reader.ReadBits(3, &n_substream_groups_minus2));
287 for (uint8_t sg = 0; sg < n_substream_groups_minus2 + 2; sg++) {
288 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
291 if (presentation_config_v1 > 5) {
292 uint8_t n_skip_bytes;
293 RCHECK(bit_reader.ReadBits(7, &n_skip_bytes));
294 RCHECK(bit_reader.SkipBits(n_skip_bytes * 8));
297 RCHECK(bit_reader.SkipBits(1));
298 RCHECK(bit_reader.ReadBits(1, &b_add_emdf_substreams));
300 if (b_add_emdf_substreams) {
301 uint8_t n_add_emdf_substreams;
302 RCHECK(bit_reader.ReadBits(7, &n_add_emdf_substreams));
303 RCHECK(bit_reader.SkipBits(n_add_emdf_substreams * 15));
305 bool b_presentation_bitrate_info;
306 RCHECK(bit_reader.ReadBits(1, &b_presentation_bitrate_info));
307 if (b_presentation_bitrate_info) {
309 RCHECK(bit_reader.SkipBits(66));
312 RCHECK(bit_reader.ReadBits(1, &b_alternative));
314 bit_reader.SkipToNextByte();
317 RCHECK(bit_reader.ReadBits(16, &name_len));
318 RCHECK(bit_reader.SkipBits(name_len * 8));
320 RCHECK(bit_reader.ReadBits(5, &n_targets));
321 RCHECK(bit_reader.SkipBits(n_targets * 11));
323 bit_reader.SkipToNextByte();
324 if ((bit_reader.bit_position() - presentation_start) <=
325 (pres_bytes - 1) * 8) {
326 RCHECK(bit_reader.SkipBits(1));
327 RCHECK(bit_reader.ReadBits(1, dolby_atmos_indicator));
328 RCHECK(bit_reader.SkipBits(4));
329 bool b_extended_presentation_group_index;
330 RCHECK(bit_reader.ReadBits(1, &b_extended_presentation_group_index));
331 if (b_extended_presentation_group_index) {
332 RCHECK(bit_reader.SkipBits(9));
334 RCHECK(bit_reader.SkipBits(1));
340 bool ExtractAc4Data(
const std::vector<uint8_t>& ac4_data,
341 uint8_t* bitstream_version,
342 uint8_t* presentation_version,
344 uint32_t* presentation_channel_mask_v1,
345 bool* dolby_ims_indicator,
346 bool* dolby_cbi_indicator) {
347 BitReader bit_reader(ac4_data.data(), ac4_data.size());
349 uint16_t n_presentation;
350 RCHECK(bit_reader.SkipBits(3) && bit_reader.ReadBits(7, bitstream_version));
351 RCHECK(bit_reader.SkipBits(5) && bit_reader.ReadBits(9, &n_presentation));
353 if (*bitstream_version == 2) {
354 uint8_t b_program_id = 0;
355 RCHECK(bit_reader.ReadBits(1, &b_program_id));
357 RCHECK(bit_reader.SkipBits(16));
359 RCHECK(bit_reader.ReadBits(1, &b_uuid));
361 RCHECK(bit_reader.SkipBits(16 * 8));
364 }
else if (*bitstream_version == 0 || *bitstream_version == 1) {
365 LOG(WARNING) <<
"Bitstream version 0 or 1 is not supported";
368 LOG(WARNING) <<
"Invalid Bitstream version";
372 RCHECK(bit_reader.SkipBits(66));
373 bit_reader.SkipToNextByte();
380 const uint8_t ott_n_presentation = 1;
381 for (uint8_t i = 0; i < ott_n_presentation; i++) {
382 RCHECK(bit_reader.ReadBits(8, presentation_version));
384 if ((*presentation_version == 2 && n_presentation > 2) ||
385 (*presentation_version == 1 && n_presentation > 1) ) {
386 LOG(WARNING) <<
"Seeing multiple presentations, only single presentation "
387 <<
"(including IMS presentation) is supported";
391 RCHECK(bit_reader.ReadBits(8, &pres_bytes));
392 if (pres_bytes == 255) {
393 uint32_t add_pres_bytes;
394 RCHECK(bit_reader.ReadBits(16, &add_pres_bytes));
395 pres_bytes += add_pres_bytes;
398 size_t presentation_bits = 0;
399 *dolby_ims_indicator =
false;
400 if (*presentation_version == 0) {
401 LOG(WARNING) <<
"Presentation version 0 is not supported";
404 if (*presentation_version == 1 || *presentation_version == 2) {
405 if (*presentation_version == 2) {
406 *dolby_ims_indicator =
true;
408 const size_t presentation_start = bit_reader.bit_position();
413 uint8_t dolby_atmos_indicator;
414 if (!ParseAC4PresentationV1Dsi(bit_reader, pres_bytes, mdcompat,
415 presentation_channel_mask_v1,
417 &dolby_atmos_indicator)) {
420 const size_t presentation_end = bit_reader.bit_position();
421 presentation_bits = presentation_end - presentation_start;
423 LOG(WARNING) <<
"Invalid Presentation version";
427 size_t skip_bits = pres_bytes * 8 - presentation_bits;
428 RCHECK(bit_reader.SkipBits(skip_bits));
434 bool CalculateAC4ChannelMask(
const std::vector<uint8_t>& ac4_data,
435 uint32_t* ac4_channel_mask) {
436 uint8_t bitstream_version;
437 uint8_t presentation_version;
439 uint32_t pre_channel_mask;
440 bool dolby_ims_indicator;
441 bool dolby_cbi_indicator;
443 if (!ExtractAc4Data(ac4_data, &bitstream_version, &presentation_version,
444 &mdcompat, &pre_channel_mask, &dolby_ims_indicator,
445 &dolby_cbi_indicator)) {
446 LOG(WARNING) <<
"Seeing invalid AC4 data: "
447 << absl::BytesToHexString(
452 if (pre_channel_mask) {
453 *ac4_channel_mask = pre_channel_mask;
455 *ac4_channel_mask = 0x800000;
460 bool CalculateAC4ChannelMPEGValue(
const std::vector<uint8_t>& ac4_data,
461 uint32_t* ac4_channel_mpeg_value) {
462 uint8_t bitstream_version;
463 uint8_t presentation_version;
465 uint32_t pre_channel_mask;
466 bool dolby_ims_indicator;
467 bool dolby_cbi_indicator;
469 if (!ExtractAc4Data(ac4_data, &bitstream_version, &presentation_version,
470 &mdcompat, &pre_channel_mask, &dolby_ims_indicator,
471 &dolby_cbi_indicator)) {
472 LOG(WARNING) <<
"Seeing invalid AC4 data: "
473 << absl::BytesToHexString(
478 *ac4_channel_mpeg_value = AC4ChannelMasktoMPEGValue(pre_channel_mask);
482 bool GetAc4CodecInfo(
const std::vector<uint8_t>& ac4_data,
483 uint8_t* ac4_codec_info) {
484 uint8_t bitstream_version;
485 uint8_t presentation_version;
487 uint32_t pre_channel_mask;
488 bool dolby_ims_indicator;
489 bool dolby_cbi_indicator;
491 if (!ExtractAc4Data(ac4_data, &bitstream_version, &presentation_version,
492 &mdcompat, &pre_channel_mask, &dolby_ims_indicator,
493 &dolby_cbi_indicator)) {
494 LOG(WARNING) <<
"Seeing invalid AC4 data: "
495 << absl::BytesToHexString(
507 *ac4_codec_info = ((bitstream_version << 5) |
508 ((presentation_version << 3) & 0x1F) |
513 bool GetAc4ImmersiveInfo(
const std::vector<uint8_t>& ac4_data,
515 bool* ac4_cbi_flag) {
516 uint8_t bitstream_version;
517 uint8_t presentation_version;
519 uint32_t pre_channel_mask;
521 if (!ExtractAc4Data(ac4_data, &bitstream_version, &presentation_version,
522 &mdcompat, &pre_channel_mask, ac4_ims_flag,
524 LOG(WARNING) <<
"Seeing invalid AC4 data: "
525 << 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.