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>
42enum kAC4AudioChannelGroupIndex {
52 kTopfrontCentre = 0x200,
53 kTopbackCentre = 0x400,
57 kBottomFrontCentre = 0x4000,
59 kLscrRscrPair = 0x10000,
61 kVhlVhrPair = 0x40000,
67uint32_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:
158bool 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));
207bool 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 || presentation_config_v1 == 1 ||
274 presentation_config_v1 == 2) {
275 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
276 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
278 if (presentation_config_v1 == 3 || presentation_config_v1 == 4) {
279 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
280 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
281 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
283 if (presentation_config_v1 == 5) {
284 uint8_t n_substream_groups_minus2;
285 RCHECK(bit_reader.ReadBits(3, &n_substream_groups_minus2));
286 for (uint8_t sg = 0; sg < n_substream_groups_minus2 + 2; sg++) {
287 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
290 if (presentation_config_v1 > 5) {
291 uint8_t n_skip_bytes;
292 RCHECK(bit_reader.ReadBits(7, &n_skip_bytes));
293 RCHECK(bit_reader.SkipBits(n_skip_bytes * 8));
296 RCHECK(bit_reader.SkipBits(1));
297 RCHECK(bit_reader.ReadBits(1, &b_add_emdf_substreams));
299 if (b_add_emdf_substreams) {
300 uint8_t n_add_emdf_substreams;
301 RCHECK(bit_reader.ReadBits(7, &n_add_emdf_substreams));
302 RCHECK(bit_reader.SkipBits(n_add_emdf_substreams * 15));
304 bool b_presentation_bitrate_info;
305 RCHECK(bit_reader.ReadBits(1, &b_presentation_bitrate_info));
306 if (b_presentation_bitrate_info) {
308 RCHECK(bit_reader.SkipBits(66));
311 RCHECK(bit_reader.ReadBits(1, &b_alternative));
313 bit_reader.SkipToNextByte();
316 RCHECK(bit_reader.ReadBits(16, &name_len));
317 RCHECK(bit_reader.SkipBits(name_len * 8));
319 RCHECK(bit_reader.ReadBits(5, &n_targets));
320 RCHECK(bit_reader.SkipBits(n_targets * 11));
322 bit_reader.SkipToNextByte();
323 if ((bit_reader.bit_position() - presentation_start) <=
324 (pres_bytes - 1) * 8) {
325 RCHECK(bit_reader.SkipBits(1));
326 RCHECK(bit_reader.ReadBits(1, dolby_atmos_indicator));
327 RCHECK(bit_reader.SkipBits(4));
328 bool b_extended_presentation_group_index;
329 RCHECK(bit_reader.ReadBits(1, &b_extended_presentation_group_index));
330 if (b_extended_presentation_group_index) {
331 RCHECK(bit_reader.SkipBits(9));
333 RCHECK(bit_reader.SkipBits(1));
339bool ExtractAc4Data(
const std::vector<uint8_t>& ac4_data,
340 uint8_t* bitstream_version,
341 uint8_t* presentation_version,
343 uint32_t* presentation_channel_mask_v1,
344 bool* dolby_ims_indicator,
345 bool* dolby_cbi_indicator) {
346 BitReader bit_reader(ac4_data.data(), ac4_data.size());
348 uint16_t n_presentation;
349 RCHECK(bit_reader.SkipBits(3) && bit_reader.ReadBits(7, bitstream_version));
350 RCHECK(bit_reader.SkipBits(5) && bit_reader.ReadBits(9, &n_presentation));
352 if (*bitstream_version == 2) {
353 uint8_t b_program_id = 0;
354 RCHECK(bit_reader.ReadBits(1, &b_program_id));
356 RCHECK(bit_reader.SkipBits(16));
358 RCHECK(bit_reader.ReadBits(1, &b_uuid));
360 RCHECK(bit_reader.SkipBits(16 * 8));
363 }
else if (*bitstream_version == 0 || *bitstream_version == 1) {
364 LOG(WARNING) <<
"Bitstream version 0 or 1 is not supported";
367 LOG(WARNING) <<
"Invalid Bitstream version";
371 RCHECK(bit_reader.SkipBits(66));
372 bit_reader.SkipToNextByte();
379 const uint8_t ott_n_presentation = 1;
380 for (uint8_t i = 0; i < ott_n_presentation; i++) {
381 RCHECK(bit_reader.ReadBits(8, presentation_version));
383 if ((*presentation_version == 2 && n_presentation > 2) ||
384 (*presentation_version == 1 && n_presentation > 1)) {
385 LOG(WARNING) <<
"Seeing multiple presentations, only single presentation "
386 <<
"(including IMS presentation) is supported";
390 RCHECK(bit_reader.ReadBits(8, &pres_bytes));
391 if (pres_bytes == 255) {
392 uint32_t add_pres_bytes;
393 RCHECK(bit_reader.ReadBits(16, &add_pres_bytes));
394 pres_bytes += add_pres_bytes;
397 size_t presentation_bits = 0;
398 *dolby_ims_indicator =
false;
399 if (*presentation_version == 0) {
400 LOG(WARNING) <<
"Presentation version 0 is not supported";
403 if (*presentation_version == 1 || *presentation_version == 2) {
404 if (*presentation_version == 2) {
405 *dolby_ims_indicator =
true;
407 const size_t presentation_start = bit_reader.bit_position();
412 uint8_t dolby_atmos_indicator;
413 if (!ParseAC4PresentationV1Dsi(
414 bit_reader, pres_bytes, mdcompat, presentation_channel_mask_v1,
415 dolby_cbi_indicator, &dolby_atmos_indicator)) {
418 const size_t presentation_end = bit_reader.bit_position();
419 presentation_bits = presentation_end - presentation_start;
421 LOG(WARNING) <<
"Invalid Presentation version";
425 size_t skip_bits = pres_bytes * 8 - presentation_bits;
426 RCHECK(bit_reader.SkipBits(skip_bits));
432bool CalculateAC4ChannelMask(
const std::vector<uint8_t>& ac4_data,
433 uint32_t* ac4_channel_mask) {
434 uint8_t bitstream_version;
435 uint8_t presentation_version;
437 uint32_t pre_channel_mask;
438 bool dolby_ims_indicator;
439 bool dolby_cbi_indicator;
441 if (!ExtractAc4Data(ac4_data, &bitstream_version, &presentation_version,
442 &mdcompat, &pre_channel_mask, &dolby_ims_indicator,
443 &dolby_cbi_indicator)) {
444 LOG(WARNING) <<
"Seeing invalid AC4 data: "
445 << absl::BytesToHexString(
450 if (pre_channel_mask) {
451 *ac4_channel_mask = pre_channel_mask;
453 *ac4_channel_mask = 0x800000;
458bool CalculateAC4ChannelMPEGValue(
const std::vector<uint8_t>& ac4_data,
459 uint32_t* ac4_channel_mpeg_value) {
460 uint8_t bitstream_version;
461 uint8_t presentation_version;
463 uint32_t pre_channel_mask;
464 bool dolby_ims_indicator;
465 bool dolby_cbi_indicator;
467 if (!ExtractAc4Data(ac4_data, &bitstream_version, &presentation_version,
468 &mdcompat, &pre_channel_mask, &dolby_ims_indicator,
469 &dolby_cbi_indicator)) {
470 LOG(WARNING) <<
"Seeing invalid AC4 data: "
471 << absl::BytesToHexString(
476 *ac4_channel_mpeg_value = AC4ChannelMasktoMPEGValue(pre_channel_mask);
480bool GetAc4CodecInfo(
const std::vector<uint8_t>& ac4_data,
481 uint8_t* ac4_codec_info) {
482 uint8_t bitstream_version;
483 uint8_t presentation_version;
485 uint32_t pre_channel_mask;
486 bool dolby_ims_indicator;
487 bool dolby_cbi_indicator;
489 if (!ExtractAc4Data(ac4_data, &bitstream_version, &presentation_version,
490 &mdcompat, &pre_channel_mask, &dolby_ims_indicator,
491 &dolby_cbi_indicator)) {
492 LOG(WARNING) <<
"Seeing invalid AC4 data: "
493 << absl::BytesToHexString(
505 *ac4_codec_info = ((bitstream_version << 5) |
506 ((presentation_version << 3) & 0x1F) | (mdcompat & 0x7));
510bool GetAc4ImmersiveInfo(
const std::vector<uint8_t>& ac4_data,
512 bool* ac4_cbi_flag) {
513 uint8_t bitstream_version;
514 uint8_t presentation_version;
516 uint32_t pre_channel_mask;
518 if (!ExtractAc4Data(ac4_data, &bitstream_version, &presentation_version,
519 &mdcompat, &pre_channel_mask, ac4_ims_flag,
521 LOG(WARNING) <<
"Seeing invalid AC4 data: "
522 << 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.