7#include <packager/media/codecs/ac4_audio_util.h>
13#include <absl/log/log.h>
14#include <absl/strings/escaping.h>
16#include <packager/media/base/bit_reader.h>
17#include <packager/media/base/rcheck.h>
18#include <packager/utils/bytes_to_string_view.h>
46enum kAC4AudioChannelGroupIndex {
56 kTopfrontCentre = 0x200,
57 kTopbackCentre = 0x400,
61 kBottomFrontCentre = 0x4000,
63 kLscrRscrPair = 0x10000,
65 kVhlVhrPair = 0x40000,
71uint32_t AC4ChannelMasktoMPEGValue(uint32_t channel_mask) {
74 switch (channel_mask) {
81 case kCentre | kLRPair:
84 case kCentre | kLRPair | kBackCentre:
87 case kCentre | kLRPair | kLsRsPair:
90 case kCentre | kLRPair | kLsRsPair | kLFE:
93 case kCentre | kLRPair | kLsRsPair | kLFE | kLwRw:
96 case kBackCentre | kLRPair:
99 case kLRPair | kLsRsPair:
102 case kCentre | kLRPair | kLsRsPair | kLFE | kBackCentre:
105 case kCentre | kLRPair | kLsRsPair | kLbRbPair | kLFE:
108 case kLwRw | kBackCentre | kBottomFrontCentre | kBflBfrPair | kLFE2 |
109 kTopCentre | kTopbackCentre | kTopfrontCentre | kTslTsrPair | kLFE |
110 kTblTbrPair | kTflTfrPair | kLbRbPair | kLsRsPair | kCentre | kLRPair:
111 case kVhlVhrPair | kLwRw | kBackCentre | kBottomFrontCentre | kBflBfrPair |
112 kLFE2 | kTopCentre | kTopbackCentre | kTopfrontCentre | kTslTsrPair |
113 kLFE | kTblTbrPair | kLbRbPair | kLsRsPair | kCentre | kLRPair:
116 case kLFE | kTflTfrPair | kLsRsPair | kCentre | kLRPair:
117 case kVhlVhrPair | kLFE | kCentre | kLRPair | kLsRsPair:
120 case kLFE2 | kTopbackCentre | kLFE | kTflTfrPair | kCentre | kLRPair |
121 kLsRsPair | kLbRbPair:
122 case kVhlVhrPair | kLFE2 | kTopbackCentre | kLFE | kCentre | kLRPair |
123 kLsRsPair | kLbRbPair:
126 case kLFE | kTblTbrPair | kTflTfrPair | kLsRsPair | kCentre | kLRPair:
127 case kVhlVhrPair | kLFE | kTblTbrPair | kLsRsPair | kCentre | kLRPair:
130 case kTopCentre | kTopfrontCentre | kLFE | kTblTbrPair | kTflTfrPair |
131 kLsRsPair | kCentre | kLRPair:
132 case kVhlVhrPair | kTopCentre | kTopfrontCentre | kLFE | kTblTbrPair |
133 kLsRsPair | kCentre | kLRPair:
136 case kTopCentre | kTopfrontCentre | kLFE | kTblTbrPair | kTflTfrPair |
137 kCentre | kLRPair | kLsRsPair | kLbRbPair:
138 case kVhlVhrPair | kTopCentre | kTopfrontCentre | kLFE | kTblTbrPair |
139 kCentre | kLRPair | kLsRsPair | kLbRbPair:
142 case kLFE | kTblTbrPair | kTflTfrPair | kCentre | kLRPair | kLsRsPair |
144 case kVhlVhrPair | kLFE | kTblTbrPair | kCentre | kLRPair | kLsRsPair |
148 case kLscrRscrPair | kLFE | kTblTbrPair | kTflTfrPair | kCentre | kLRPair |
149 kLsRsPair | kLbRbPair:
150 case kVhlVhrPair | kLscrRscrPair | kLFE | kTblTbrPair | kCentre | kLRPair |
151 kLsRsPair | kLbRbPair:
162bool ParseAC4SubStreamGroupDsi(BitReader& bit_reader) {
163 bool b_substream_present;
164 RCHECK(bit_reader.ReadBits(1, &b_substream_present));
166 RCHECK(bit_reader.ReadBits(1, &b_hsf_ext));
167 bool b_channel_coded;
168 RCHECK(bit_reader.ReadBits(1, &b_channel_coded));
169 uint8_t n_substreams;
170 RCHECK(bit_reader.ReadBits(8, &n_substreams));
171 for (uint8_t i = 0; i < n_substreams; i++) {
172 RCHECK(bit_reader.SkipBits(2));
173 bool b_substream_bitrate_indicator;
174 RCHECK(bit_reader.ReadBits(1, &b_substream_bitrate_indicator));
175 if (b_substream_bitrate_indicator) {
176 RCHECK(bit_reader.SkipBits(5));
178 if (b_channel_coded) {
179 RCHECK(bit_reader.SkipBits(24));
182 RCHECK(bit_reader.ReadBits(1, &b_ajoc));
185 RCHECK(bit_reader.ReadBits(1, &b_static_dmx));
187 RCHECK(bit_reader.SkipBits(4));
189 RCHECK(bit_reader.SkipBits(6));
191 RCHECK(bit_reader.SkipBits(4));
195 RCHECK(bit_reader.ReadBits(1, &b_content_type));
196 if (b_content_type) {
197 RCHECK(bit_reader.SkipBits(3));
198 bool b_language_indicator;
199 RCHECK(bit_reader.ReadBits(1, &b_language_indicator));
200 if (b_language_indicator) {
201 uint8_t n_language_tag_bytes;
202 RCHECK(bit_reader.ReadBits(6, &n_language_tag_bytes));
203 RCHECK(bit_reader.SkipBits(n_language_tag_bytes * 8));
211bool ParseAC4PresentationV1Dsi(BitReader& bit_reader,
214 uint32_t* presentation_channel_mask_v1,
215 bool* dolby_cbi_indicator,
216 uint8_t* dolby_atmos_indicator) {
219 const size_t presentation_start = bit_reader.bit_position();
220 uint8_t presentation_config_v1;
221 RCHECK(bit_reader.ReadBits(5, &presentation_config_v1));
222 uint8_t b_add_emdf_substreams;
225 *presentation_channel_mask_v1 = 2;
226 *dolby_cbi_indicator =
false;
227 *dolby_atmos_indicator = 0;
228 if (presentation_config_v1 == 0x06) {
229 b_add_emdf_substreams = 1;
231 RCHECK(bit_reader.ReadBits(3, mdcompat));
232 bool b_presentation_id;
233 RCHECK(bit_reader.ReadBits(1, &b_presentation_id));
234 if (b_presentation_id) {
235 RCHECK(bit_reader.SkipBits(5));
237 RCHECK(bit_reader.SkipBits(19));
238 bool b_presentation_channel_coded;
239 RCHECK(bit_reader.ReadBits(1, &b_presentation_channel_coded));
240 *presentation_channel_mask_v1 = 0;
241 if (b_presentation_channel_coded) {
242 uint8_t dsi_presentation_ch_mode;
243 RCHECK(bit_reader.ReadBits(5, &dsi_presentation_ch_mode));
244 if (dsi_presentation_ch_mode >= 11 && dsi_presentation_ch_mode <= 14) {
245 RCHECK(bit_reader.SkipBits(1));
246 uint8_t pres_top_channel_pairs;
247 RCHECK(bit_reader.ReadBits(2, &pres_top_channel_pairs));
248 if (pres_top_channel_pairs) {
249 *dolby_cbi_indicator =
true;
251 }
else if (dsi_presentation_ch_mode == 15) {
252 *dolby_cbi_indicator =
true;
254 RCHECK(bit_reader.ReadBits(24, presentation_channel_mask_v1));
256 bool b_presentation_core_differs;
257 RCHECK(bit_reader.ReadBits(1, &b_presentation_core_differs));
258 if (b_presentation_core_differs) {
259 bool b_presentation_core_channel_coded;
260 RCHECK(bit_reader.ReadBits(1, &b_presentation_core_channel_coded));
261 if (b_presentation_core_channel_coded) {
262 RCHECK(bit_reader.SkipBits(2));
265 bool b_presentation_filter;
266 RCHECK(bit_reader.ReadBits(1, &b_presentation_filter));
267 if (b_presentation_filter) {
268 RCHECK(bit_reader.SkipBits(1));
269 uint8_t n_filter_bytes;
270 RCHECK(bit_reader.ReadBits(8, &n_filter_bytes));
271 RCHECK(bit_reader.SkipBits(n_filter_bytes * 8));
273 if (presentation_config_v1 == 0x1f) {
274 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
276 RCHECK(bit_reader.SkipBits(1));
277 if (presentation_config_v1 == 0 || presentation_config_v1 == 1 ||
278 presentation_config_v1 == 2) {
279 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
280 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
282 if (presentation_config_v1 == 3 || presentation_config_v1 == 4) {
283 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
284 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
285 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
287 if (presentation_config_v1 == 5) {
288 uint8_t n_substream_groups_minus2;
289 RCHECK(bit_reader.ReadBits(3, &n_substream_groups_minus2));
290 for (uint8_t sg = 0; sg < n_substream_groups_minus2 + 2; sg++) {
291 ret &= ParseAC4SubStreamGroupDsi(bit_reader);
294 if (presentation_config_v1 > 5) {
295 uint8_t n_skip_bytes;
296 RCHECK(bit_reader.ReadBits(7, &n_skip_bytes));
297 RCHECK(bit_reader.SkipBits(n_skip_bytes * 8));
300 RCHECK(bit_reader.SkipBits(1));
301 RCHECK(bit_reader.ReadBits(1, &b_add_emdf_substreams));
303 if (b_add_emdf_substreams) {
304 uint8_t n_add_emdf_substreams;
305 RCHECK(bit_reader.ReadBits(7, &n_add_emdf_substreams));
306 RCHECK(bit_reader.SkipBits(n_add_emdf_substreams * 15));
308 bool b_presentation_bitrate_info;
309 RCHECK(bit_reader.ReadBits(1, &b_presentation_bitrate_info));
310 if (b_presentation_bitrate_info) {
312 RCHECK(bit_reader.SkipBits(66));
315 RCHECK(bit_reader.ReadBits(1, &b_alternative));
317 bit_reader.SkipToNextByte();
320 RCHECK(bit_reader.ReadBits(16, &name_len));
321 RCHECK(bit_reader.SkipBits(name_len * 8));
323 RCHECK(bit_reader.ReadBits(5, &n_targets));
324 RCHECK(bit_reader.SkipBits(n_targets * 11));
326 bit_reader.SkipToNextByte();
327 if ((bit_reader.bit_position() - presentation_start) <=
328 (pres_bytes - 1) * 8) {
329 RCHECK(bit_reader.SkipBits(1));
330 RCHECK(bit_reader.ReadBits(1, dolby_atmos_indicator));
331 RCHECK(bit_reader.SkipBits(4));
332 bool b_extended_presentation_group_index;
333 RCHECK(bit_reader.ReadBits(1, &b_extended_presentation_group_index));
334 if (b_extended_presentation_group_index) {
335 RCHECK(bit_reader.SkipBits(9));
337 RCHECK(bit_reader.SkipBits(1));
343bool ExtractAc4Data(
const std::vector<uint8_t>& ac4_data,
344 uint8_t* bitstream_version,
345 uint8_t* presentation_version,
347 uint32_t* presentation_channel_mask_v1,
348 bool* dolby_ims_indicator,
349 bool* dolby_cbi_indicator) {
350 BitReader bit_reader(ac4_data.data(), ac4_data.size());
352 uint16_t n_presentation;
353 RCHECK(bit_reader.SkipBits(3) && bit_reader.ReadBits(7, bitstream_version));
354 RCHECK(bit_reader.SkipBits(5) && bit_reader.ReadBits(9, &n_presentation));
356 if (*bitstream_version == 2) {
357 uint8_t b_program_id = 0;
358 RCHECK(bit_reader.ReadBits(1, &b_program_id));
360 RCHECK(bit_reader.SkipBits(16));
362 RCHECK(bit_reader.ReadBits(1, &b_uuid));
364 RCHECK(bit_reader.SkipBits(16 * 8));
367 }
else if (*bitstream_version == 0 || *bitstream_version == 1) {
368 LOG(WARNING) <<
"Bitstream version 0 or 1 is not supported";
371 LOG(WARNING) <<
"Invalid Bitstream version";
375 RCHECK(bit_reader.SkipBits(66));
376 bit_reader.SkipToNextByte();
383 const uint8_t ott_n_presentation = 1;
384 for (uint8_t i = 0; i < ott_n_presentation; i++) {
385 RCHECK(bit_reader.ReadBits(8, presentation_version));
387 if ((*presentation_version == 2 && n_presentation > 2) ||
388 (*presentation_version == 1 && n_presentation > 1)) {
389 LOG(WARNING) <<
"Seeing multiple presentations, only single presentation "
390 <<
"(including IMS presentation) is supported";
394 RCHECK(bit_reader.ReadBits(8, &pres_bytes));
395 if (pres_bytes == 255) {
396 uint32_t add_pres_bytes;
397 RCHECK(bit_reader.ReadBits(16, &add_pres_bytes));
398 pres_bytes += add_pres_bytes;
401 size_t presentation_bits = 0;
402 *dolby_ims_indicator =
false;
403 if (*presentation_version == 0) {
404 LOG(WARNING) <<
"Presentation version 0 is not supported";
407 if (*presentation_version == 1 || *presentation_version == 2) {
408 if (*presentation_version == 2) {
409 *dolby_ims_indicator =
true;
411 const size_t presentation_start = bit_reader.bit_position();
416 uint8_t dolby_atmos_indicator;
417 if (!ParseAC4PresentationV1Dsi(
418 bit_reader, pres_bytes, mdcompat, presentation_channel_mask_v1,
419 dolby_cbi_indicator, &dolby_atmos_indicator)) {
422 const size_t presentation_end = bit_reader.bit_position();
423 presentation_bits = presentation_end - presentation_start;
425 LOG(WARNING) <<
"Invalid Presentation version";
429 size_t skip_bits = pres_bytes * 8 - presentation_bits;
430 RCHECK(bit_reader.SkipBits(skip_bits));
436bool CalculateAC4ChannelMask(
const std::vector<uint8_t>& ac4_data,
437 uint32_t* ac4_channel_mask) {
438 uint8_t bitstream_version;
439 uint8_t presentation_version;
441 uint32_t pre_channel_mask;
442 bool dolby_ims_indicator;
443 bool dolby_cbi_indicator;
445 if (!ExtractAc4Data(ac4_data, &bitstream_version, &presentation_version,
446 &mdcompat, &pre_channel_mask, &dolby_ims_indicator,
447 &dolby_cbi_indicator)) {
448 LOG(WARNING) <<
"Seeing invalid AC4 data: "
449 << absl::BytesToHexString(
454 if (pre_channel_mask) {
455 *ac4_channel_mask = pre_channel_mask;
457 *ac4_channel_mask = 0x800000;
462bool CalculateAC4ChannelMPEGValue(
const std::vector<uint8_t>& ac4_data,
463 uint32_t* ac4_channel_mpeg_value) {
464 uint8_t bitstream_version;
465 uint8_t presentation_version;
467 uint32_t pre_channel_mask;
468 bool dolby_ims_indicator;
469 bool dolby_cbi_indicator;
471 if (!ExtractAc4Data(ac4_data, &bitstream_version, &presentation_version,
472 &mdcompat, &pre_channel_mask, &dolby_ims_indicator,
473 &dolby_cbi_indicator)) {
474 LOG(WARNING) <<
"Seeing invalid AC4 data: "
475 << absl::BytesToHexString(
480 *ac4_channel_mpeg_value = AC4ChannelMasktoMPEGValue(pre_channel_mask);
484bool GetAc4CodecInfo(
const std::vector<uint8_t>& ac4_data,
485 uint8_t* ac4_codec_info) {
486 uint8_t bitstream_version;
487 uint8_t presentation_version;
489 uint32_t pre_channel_mask;
490 bool dolby_ims_indicator;
491 bool dolby_cbi_indicator;
493 if (!ExtractAc4Data(ac4_data, &bitstream_version, &presentation_version,
494 &mdcompat, &pre_channel_mask, &dolby_ims_indicator,
495 &dolby_cbi_indicator)) {
496 LOG(WARNING) <<
"Seeing invalid AC4 data: "
497 << absl::BytesToHexString(
509 *ac4_codec_info = ((bitstream_version << 5) |
510 ((presentation_version << 3) & 0x1F) | (mdcompat & 0x7));
514bool GetAc4ImmersiveInfo(
const std::vector<uint8_t>& ac4_data,
516 bool* ac4_cbi_flag) {
517 uint8_t bitstream_version;
518 uint8_t presentation_version;
520 uint32_t pre_channel_mask;
522 if (!ExtractAc4Data(ac4_data, &bitstream_version, &presentation_version,
523 &mdcompat, &pre_channel_mask, ac4_ims_flag,
525 LOG(WARNING) <<
"Seeing invalid AC4 data: "
526 << 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.