1 /*****************************************************************
2 |
3 | AP4 - dac4 Atoms
4 |
5 | Copyright 2002-2018 Axiomatic Systems, LLC
6 |
7 |
8 | This file is part of Bento4/AP4 (MP4 Atom Processing Library).
9 |
10 | Unless you have obtained Bento4 under a difference license,
11 | this version of Bento4 is Bento4|GPL.
12 | Bento4|GPL is free software; you can redistribute it and/or modify
13 | it under the terms of the GNU General Public License as published by
14 | the Free Software Foundation; either version 2, or (at your option)
15 | any later version.
16 |
17 | Bento4|GPL is distributed in the hope that it will be useful,
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | GNU General Public License for more details.
21 |
22 | You should have received a copy of the GNU General Public License
23 | along with Bento4|GPL; see the file COPYING. If not, write to the
24 | Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 | 02111-1307, USA.
26 |
27 ****************************************************************/
28
29 /*----------------------------------------------------------------------
30 | includes
31 +---------------------------------------------------------------------*/
32 #include "Ap4Dac4Atom.h"
33 #include "Ap4AtomFactory.h"
34 #include "Ap4Utils.h"
35 #include "Ap4Types.h"
36
37 #include <cmath>
38
39 /*----------------------------------------------------------------------
40 | dynamic cast support
41 +---------------------------------------------------------------------*/
AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_Dac4Atom)42 AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_Dac4Atom)
43
44 /*----------------------------------------------------------------------
45 | AP4_Dac4Atom::Create
46 +---------------------------------------------------------------------*/
47 AP4_Dac4Atom*
48 AP4_Dac4Atom::Create(AP4_Size size, AP4_ByteStream& stream)
49 {
50 // read the raw bytes in a buffer
51 unsigned int payload_size = size-AP4_ATOM_HEADER_SIZE;
52 AP4_DataBuffer payload_data(payload_size);
53 AP4_Result result = stream.Read(payload_data.UseData(), payload_size);
54 if (AP4_FAILED(result)) return NULL;
55
56 // check the version
57 const AP4_UI08* payload = payload_data.GetData();
58 return new AP4_Dac4Atom(size, payload);
59 }
60
61 /*----------------------------------------------------------------------
62 | AP4_Dac4Atom::AP4_Dac4Atom
63 +---------------------------------------------------------------------*/
AP4_Dac4Atom(AP4_UI32 size,const Ac4Dsi * ac4Dsi)64 AP4_Dac4Atom::AP4_Dac4Atom(AP4_UI32 size, const Ac4Dsi* ac4Dsi):
65 AP4_Atom(AP4_ATOM_TYPE_DAC4, AP4_ATOM_HEADER_SIZE){
66 AP4_BitWriter bits(size);
67 bits.Write(ac4Dsi->ac4_dsi_version, 3);
68 bits.Write(ac4Dsi->d.v1.bitstream_version, 7);
69 bits.Write(ac4Dsi->d.v1.fs_index, 1);
70 bits.Write(ac4Dsi->d.v1.frame_rate_index, 4);
71
72 // IMS presentation shall has the legacy presentation
73 unsigned int add_n_presentations = 0;
74 for (unsigned int idx = 0; idx < ac4Dsi->d.v1.n_presentations; idx++){
75 if (ac4Dsi->d.v1.presentations[idx].presentation_version == 2) {
76 add_n_presentations++;
77 }
78 }
79
80 // Assume the total presentation numbers is less than 512 after adding legacy presentation
81 bits.Write(ac4Dsi->d.v1.n_presentations + add_n_presentations, 9);
82
83 if (ac4Dsi->d.v1.bitstream_version > 1){
84 bits.Write(ac4Dsi->d.v1.b_program_id, 1);
85 if (ac4Dsi->d.v1.b_program_id == 1){
86 bits.Write(ac4Dsi->d.v1.short_program_id, 16);
87 bits.Write(ac4Dsi->d.v1.b_uuid, 1);
88 if (ac4Dsi->d.v1.b_uuid == 1) {
89 for (unsigned int idx = 0; idx < 16; idx ++) {
90 bits.Write(ac4Dsi->d.v1.program_uuid[idx], 8);
91 }
92 }
93 }
94 }
95 // ac4_bitrate_dsi()
96 AP4_Dac4Atom::Ac4Dsi::Ac4BitrateDsi ac4_bitrate_dsi = ac4Dsi->d.v1.ac4_bitrate_dsi;
97 ac4_bitrate_dsi.WriteBitrateDsi(bits);
98
99 AP4_ByteAlign(bits);
100 for (unsigned int idx = 0; idx < ac4Dsi->d.v1.n_presentations; idx ++) {
101 unsigned int default_pres_bytes = 36; // random value
102 AP4_Dac4Atom::Ac4Dsi::PresentationV1 &presentation = ac4Dsi->d.v1.presentations[idx];
103 bits.Write(presentation.presentation_version, 8);
104 bits.Write(default_pres_bytes, 8); // pres_bytes, need to be updated later
105 //TODO: if (pres_bytes == 255), shall not happen now. Need the memory move function for bits
106 unsigned int pres_bytes_idx = bits.GetBitCount() / 8 - 1;
107 if (ac4Dsi->d.v1.n_presentations != 1 && presentation.d.v1.b_presentation_id == 0 && presentation.d.v1.b_extended_presentation_id == 0) {
108 fprintf(stderr, "WARN: Need presentation_id for multiple presnetaion signal. The presentation of Presentation Index (PI) is %d miss presentation_id.\n", idx + 1);
109 }
110 if (presentation.presentation_version == 0){
111 // TODO: support presentation version = 0
112 }else if (presentation.presentation_version == 1 || presentation.presentation_version == 2){
113 presentation.WritePresentationV1Dsi(bits);
114 Ap4_Ac4UpdatePresBytes(bits.GetData(), pres_bytes_idx, bits.GetBitCount()/8 - pres_bytes_idx - 1);
115 } else {
116 Ap4_Ac4UpdatePresBytes(bits.GetData(), pres_bytes_idx, 0);
117 }
118
119 //legacy presentation for IMS
120 if (presentation.presentation_version == 2) {
121 AP4_Dac4Atom::Ac4Dsi::PresentationV1 legacy_presentation = presentation;
122 if (legacy_presentation.d.v1.b_presentation_id == 0 && legacy_presentation.d.v1.b_extended_presentation_id == 0) {
123 fprintf(stderr, "WARN: Need presentation_id for IMS signal.\n");
124 }
125 legacy_presentation.presentation_version = 1;
126 legacy_presentation.d.v1.b_pre_virtualized = 0;
127 legacy_presentation.d.v1.dolby_atmos_indicator = 0;
128
129 bits.Write(legacy_presentation.presentation_version, 8);
130 bits.Write(default_pres_bytes, 8); // pres_bytes, need to be updated later
131 //TODO: if (pres_bytes == 255), shall not happen now
132 unsigned int pres_bytes_idx = bits.GetBitCount() / 8 - 1;
133 legacy_presentation.WritePresentationV1Dsi(bits);
134 Ap4_Ac4UpdatePresBytes(bits.GetData(), pres_bytes_idx, bits.GetBitCount()/8 - pres_bytes_idx - 1);
135 }
136 }
137 m_RawBytes.SetData(bits.GetData(), bits.GetBitCount() / 8);
138 m_Size32 += m_RawBytes.GetDataSize();
139 // clear the DSI
140 AP4_SetMemory(&m_Dsi, 0, sizeof(m_Dsi));
141 m_Dsi.ac4_dsi_version = -1;
142 }
143
144 /*----------------------------------------------------------------------
145 | AP4_Dac4Atom::AP4_Dac4Atom
146 +---------------------------------------------------------------------*/
AP4_Dac4Atom(AP4_UI32 size,const AP4_UI08 * payload)147 AP4_Dac4Atom::AP4_Dac4Atom(AP4_UI32 size, const AP4_UI08* payload) :
148 AP4_Atom(AP4_ATOM_TYPE_DAC4, size)
149 {
150 // clear the DSI
151 AP4_SetMemory(&m_Dsi, 0, sizeof(m_Dsi));
152
153 // make a copy of our configuration bytes
154 unsigned int payload_size = size-AP4_ATOM_HEADER_SIZE;
155 m_RawBytes.SetData(payload, payload_size);
156
157 // sanity check
158 if (payload_size < 11) return;
159
160 // parse the `ac4_dsi` or `ac4_dsi_v1` bits
161 AP4_BitReader bits(payload, payload_size);
162 m_Dsi.ac4_dsi_version = bits.ReadBits(3);
163 if (m_Dsi.ac4_dsi_version == 0) {
164 m_Dsi.d.v0.bitstream_version = bits.ReadBits(7);
165 m_Dsi.d.v0.fs_index = bits.ReadBits(1);
166 m_Dsi.d.v0.frame_rate_index = bits.ReadBits(4);
167 m_Dsi.d.v0.n_presentations = bits.ReadBits(9);
168
169 // fill in computed fields
170 m_Dsi.d.v0.fs = m_Dsi.d.v0.fs_index == 0 ? 44100 : 48000;
171 } else if (m_Dsi.ac4_dsi_version == 1) {
172 m_Dsi.d.v1.bitstream_version = bits.ReadBits(7);
173 m_Dsi.d.v1.fs_index = bits.ReadBits(1);
174 m_Dsi.d.v1.frame_rate_index = bits.ReadBits(4);
175 m_Dsi.d.v1.n_presentations = bits.ReadBits(9);
176 if (m_Dsi.d.v1.bitstream_version > 1) {
177 if (bits.ReadBit()) {
178 m_Dsi.d.v1.short_program_id = bits.ReadBits(16);
179 if (bits.ReadBit()) {
180 for (unsigned int i = 0; i < 16; i ++) {
181 m_Dsi.d.v1.program_uuid[i] = bits.ReadBits(8);
182 }
183 }
184 }
185 }
186 m_Dsi.d.v1.ac4_bitrate_dsi.bit_rate_mode = bits.ReadBits(2);
187 m_Dsi.d.v1.ac4_bitrate_dsi.bit_rate = bits.ReadBits(32);
188 m_Dsi.d.v1.ac4_bitrate_dsi.bit_rate_precision = bits.ReadBits(32);
189
190 // byte align
191 if (bits.GetBitsRead() % 8) {
192 bits.SkipBits(8 - (bits.GetBitsRead() % 8));
193 }
194
195 // parse the presentations
196 m_Dsi.d.v1.presentations = new Ac4Dsi::PresentationV1[m_Dsi.d.v1.n_presentations];
197 AP4_SetMemory(m_Dsi.d.v1.presentations, 0, m_Dsi.d.v1.n_presentations * sizeof(m_Dsi.d.v1.presentations[0]));
198 for (unsigned int i = 0; i < m_Dsi.d.v1.n_presentations; i++) {
199 Ac4Dsi::PresentationV1& presentation = m_Dsi.d.v1.presentations[i];
200
201 presentation.presentation_version = bits.ReadBits(8);
202 unsigned int pres_bytes = bits.ReadBits(8);
203 if (pres_bytes == 255) {
204 pres_bytes += bits.ReadBits(16);
205 }
206 unsigned int bits_read_before_presentation = bits.GetBitsRead();
207 if (presentation.presentation_version == 0) {
208 presentation.d.v0.presentation_config = bits.ReadBits(5);
209 //bool b_add_emdf_substreams = false;
210 if (presentation.d.v0.presentation_config == 0x06) {
211 //b_add_emdf_substreams = true;
212 } else {
213 presentation.d.v0.mdcompat = bits.ReadBits(3);
214 if (bits.ReadBit()) { // b_presentation_id
215 presentation.d.v0.presentation_id = bits.ReadBits(5);
216 }
217 presentation.d.v0.dsi_frame_rate_multiply_info = bits.ReadBits(2);
218 presentation.d.v0.presentation_emdf_version = bits.ReadBits(5);
219 presentation.d.v0.presentation_key_id = bits.ReadBits(10);
220 presentation.d.v0.presentation_channel_mask = bits.ReadBits(24);
221 }
222 // some fields skipped
223 if (bits.GetBitsRead() % 8) {
224 bits.SkipBits(8 - (bits.GetBitsRead() % 8));
225 }
226 } else if (presentation.presentation_version == 1 || presentation.presentation_version == 2) {
227 presentation.d.v1.presentation_config_v1 = bits.ReadBits(5);
228 if (presentation.d.v1.presentation_config_v1 == 0x06) {
229 presentation.d.v1.b_add_emdf_substreams = 1;
230 } else {
231 presentation.d.v1.mdcompat = bits.ReadBits(3);
232 presentation.d.v1.b_presentation_id = bits.ReadBit();
233 if (presentation.d.v1.b_presentation_id) {
234 presentation.d.v1.presentation_id = bits.ReadBits(5);
235 }
236 presentation.d.v1.dsi_frame_rate_multiply_info = bits.ReadBits(2);
237 presentation.d.v1.dsi_frame_rate_fraction_info = bits.ReadBits(2);
238 presentation.d.v1.presentation_emdf_version = bits.ReadBits(5);
239 presentation.d.v1.presentation_key_id = bits.ReadBits(10);
240 presentation.d.v1.b_presentation_channel_coded = bits.ReadBit();
241 if (presentation.d.v1.b_presentation_channel_coded) {
242 presentation.d.v1.dsi_presentation_ch_mode = bits.ReadBits(5);
243 if (presentation.d.v1.dsi_presentation_ch_mode == 11 ||
244 presentation.d.v1.dsi_presentation_ch_mode == 12 ||
245 presentation.d.v1.dsi_presentation_ch_mode == 13 ||
246 presentation.d.v1.dsi_presentation_ch_mode == 14) {
247 presentation.d.v1.pres_b_4_back_channels_present = bits.ReadBit();
248 presentation.d.v1.pres_top_channel_pairs = bits.ReadBits(2);
249 }
250 presentation.d.v1.presentation_channel_mask_v1 = bits.ReadBits(24);
251 }else {
252 presentation.d.v1.presentation_channel_mask_v1 = 0x800000;
253 }
254 presentation.d.v1.b_presentation_core_differs = bits.ReadBit();
255 if (presentation.d.v1.b_presentation_core_differs) {
256 presentation.d.v1.b_presentation_core_channel_coded = bits.ReadBit();
257 if (presentation.d.v1.b_presentation_core_channel_coded) {
258 presentation.d.v1.dsi_presentation_channel_mode_core = bits.ReadBits(2);
259 }
260 }
261 presentation.d.v1.b_presentation_filter = bits.ReadBit();
262 if (presentation.d.v1.b_presentation_filter) {
263 presentation.d.v1.b_enable_presentation = bits.ReadBit();
264 presentation.d.v1.n_filter_bytes = bits.ReadBits(8);
265 for (int idx = 0; idx < presentation.d.v1.n_filter_bytes; idx ++) { bits.SkipBits(8); }
266 }
267 bool parse_substream_groups = true;
268 if (presentation.d.v1.presentation_config_v1 == 0x1f){
269 presentation.d.v1.n_substream_groups = 1;
270 } else {
271 presentation.d.v1.b_multi_pid = bits.ReadBit();
272 switch (presentation.d.v1.presentation_config_v1){
273 case 0:
274 case 1:
275 case 2:
276 presentation.d.v1.n_substream_groups = 2;
277 break;
278 case 3:
279 case 4:
280 presentation.d.v1.n_substream_groups = 3;
281 break;
282 case 5:
283 presentation.d.v1.n_substream_groups = bits.ReadBits(3) + 2;
284 break;
285 default:
286 parse_substream_groups = false;
287 presentation.d.v1.n_skip_bytes = bits.ReadBits(7);
288 for (int idx = 0; idx < presentation.d.v1.n_skip_bytes; idx ++) { bits.SkipBits(8); }
289 }
290
291 }
292 // Start to parse substream_groups
293 if (parse_substream_groups) {
294 presentation.d.v1.substream_groups = new Ac4Dsi::SubStreamGroupV1[presentation.d.v1.n_substream_groups];
295 AP4_SetMemory(presentation.d.v1.substream_groups, 0, presentation.d.v1.n_substream_groups * sizeof(presentation.d.v1.substream_groups[0]));
296 for (int cnt = 0; cnt < presentation.d.v1.n_substream_groups; cnt ++){
297 Ac4Dsi::SubStreamGroupV1& substreamgroup = presentation.d.v1.substream_groups[cnt];
298 substreamgroup.d.v1.b_substreams_present = bits.ReadBit();
299 substreamgroup.d.v1.b_hsf_ext = bits.ReadBit();
300 substreamgroup.d.v1.b_channel_coded = bits.ReadBit();
301 substreamgroup.d.v1.n_substreams = bits.ReadBits(8);
302
303 substreamgroup.d.v1.substreams = new Ac4Dsi::SubStream[substreamgroup.d.v1.n_substreams];
304 AP4_SetMemory(substreamgroup.d.v1.substreams, 0, substreamgroup.d.v1.n_substreams * sizeof(substreamgroup.d.v1.substreams[0]));
305 for (int sus = 0; sus < substreamgroup.d.v1.n_substreams; sus ++){
306 Ac4Dsi::SubStream& substream = substreamgroup.d.v1.substreams[sus];
307 substream.dsi_sf_multiplier = bits.ReadBits(2);
308 substream.b_substream_bitrate_indicator = bits.ReadBit();
309 if (substream.b_substream_bitrate_indicator) {
310 substream.substream_bitrate_indicator = bits.ReadBits(5);
311 }
312 if (substreamgroup.d.v1.b_channel_coded){
313 substream.dsi_substream_channel_mask = bits.ReadBits(24);
314 } else {
315 substream.b_ajoc = bits.ReadBit();
316 if (substream.b_ajoc) {
317 substream.b_static_dmx = bits.ReadBit();
318 if (substream.b_static_dmx == 0) {
319 substream.n_dmx_objects_minus1 = bits.ReadBits(4);
320 }
321 substream.n_umx_objects_minus1 = bits.ReadBits(6);
322 }
323 substream.b_substream_contains_bed_objects = bits.ReadBit();
324 substream.b_substream_contains_dynamic_objects = bits.ReadBit();
325 substream.b_substream_contains_ISF_objects = bits.ReadBit();
326 bits.SkipBit(); // reserved
327 }
328 }
329 substreamgroup.d.v1.b_content_type = bits.ReadBit();
330 if (substreamgroup.d.v1.b_content_type) {
331 substreamgroup.d.v1.content_classifier = bits.ReadBits(3);
332 substreamgroup.d.v1.b_language_indicator = bits.ReadBit();
333 if (substreamgroup.d.v1.b_language_indicator) {
334 substreamgroup.d.v1.n_language_tag_bytes = bits.ReadBits(6);
335 for (int l = 0; l < substreamgroup.d.v1.n_language_tag_bytes; l++) {
336 substreamgroup.d.v1.language_tag_bytes[l] = bits.ReadBits(8);
337 }
338 }
339 }
340 }
341 }
342 presentation.d.v1.b_pre_virtualized = bits.ReadBit();
343 presentation.d.v1.b_add_emdf_substreams = bits.ReadBit();
344 }
345 if (presentation.d.v1.b_add_emdf_substreams) {
346 presentation.d.v1.n_add_emdf_substreams = bits.ReadBits(7);
347 for (int j = 0; j < presentation.d.v1.n_add_emdf_substreams; j ++) {
348 presentation.d.v1.substream_emdf_version[j] = bits.ReadBits(5);
349 presentation.d.v1.substream_key_id[j] = bits.ReadBits(10);
350 }
351 }
352 presentation.d.v1.b_presentation_bitrate_info = bits.ReadBit();
353 if (presentation.d.v1.b_presentation_bitrate_info) {
354 presentation.d.v1.ac4_bitrate_dsi.bit_rate_mode = bits.ReadBits(2);
355 presentation.d.v1.ac4_bitrate_dsi.bit_rate = bits.ReadBits(32);
356 presentation.d.v1.ac4_bitrate_dsi.bit_rate_precision = bits.ReadBits(32);
357 }
358 presentation.d.v1.b_alternative = bits.ReadBit();
359 if (presentation.d.v1.b_alternative) {
360 // byte align
361 if (bits.GetBitsRead() % 8) {
362 bits.SkipBits(8 - (bits.GetBitsRead() % 8));
363 }
364
365 presentation.d.v1.alternative_info.name_len = bits.ReadBits(16);
366 for (int n = 0; n < presentation.d.v1.alternative_info.name_len; n++) {
367 presentation.d.v1.alternative_info.presentation_name[n] = bits.ReadBits(8);
368 }
369 presentation.d.v1.alternative_info.n_targets = bits.ReadBits(5);
370 for (int t = 0; t < presentation.d.v1.alternative_info.n_targets; t++ ){
371 presentation.d.v1.alternative_info.target_md_compat[t] = bits.ReadBits(3);
372 presentation.d.v1.alternative_info.target_device_category[t] = bits.ReadBits(8);
373 }
374 }
375 // byte align
376 if (bits.GetBitsRead() % 8) {
377 bits.SkipBits(8 - (bits.GetBitsRead() % 8));
378 }
379 presentation.d.v1.de_indicator = bits.ReadBit();
380 presentation.d.v1.dolby_atmos_indicator = bits.ReadBit();
381 bits.SkipBits(4);
382 presentation.d.v1.b_extended_presentation_id = bits.ReadBit();
383 if (presentation.d.v1.b_extended_presentation_id){
384 presentation.d.v1.extended_presentation_id = bits.ReadBits(9);
385 } else {
386 bits.SkipBit();
387 }
388 }
389 unsigned int bits_read_after_presentation = bits.GetBitsRead();
390 unsigned int presentation_bytes = (bits_read_after_presentation - bits_read_before_presentation) / 8;
391 if (pres_bytes < presentation_bytes) {
392 break;
393 }
394 unsigned int skip_bytes = pres_bytes - presentation_bytes;
395 for (unsigned int skip = 0; skip < skip_bytes; skip++) {
396 bits.SkipBits(8);
397 }
398 }
399
400 // fill in computed fields
401 m_Dsi.d.v1.fs = m_Dsi.d.v1.fs_index == 0 ? 44100 : 48000;
402 } else {
403 // not supported
404 return;
405 }
406 }
407
408 /*----------------------------------------------------------------------
409 | AP4_Dac4Atom::~AP4_Dac4Atom
410 +---------------------------------------------------------------------*/
~AP4_Dac4Atom()411 AP4_Dac4Atom::~AP4_Dac4Atom()
412 {
413 if (m_Dsi.ac4_dsi_version == 0) {
414 //delete[] m_Dsi.d.v0.presentations;
415 } else if (m_Dsi.ac4_dsi_version == 1) {
416 for (int i = 0; i < m_Dsi.d.v1.n_presentations; i++) {
417 for (int j = 0; j < m_Dsi.d.v1.presentations[i].d.v1.n_substream_groups; j++) {
418 delete[] m_Dsi.d.v1.presentations[i].d.v1.substream_groups[j].d.v1.substreams;
419 }
420 delete[] m_Dsi.d.v1.presentations[i].d.v1.substream_groups;
421 }
422 delete[] m_Dsi.d.v1.presentations;
423 }
424 }
425
426 /*----------------------------------------------------------------------
427 | AP4_Dac4Atom::WriteFields
428 +---------------------------------------------------------------------*/
429 AP4_Result
WriteFields(AP4_ByteStream & stream)430 AP4_Dac4Atom::WriteFields(AP4_ByteStream& stream)
431 {
432 return stream.Write(m_RawBytes.GetData(), m_RawBytes.GetDataSize());
433 }
434
435 /*----------------------------------------------------------------------
436 | AP4_Dac4Atom::GetCodecString
437 +---------------------------------------------------------------------*/
438 void
GetCodecString(AP4_String & codec)439 AP4_Dac4Atom::GetCodecString(AP4_String& codec)
440 {
441 AP4_UI08 bitstream_version = 0;
442 AP4_UI08 presentation_version = 0;
443 AP4_UI08 mdcompat = 0;
444 if (m_Dsi.ac4_dsi_version == 0) {
445 bitstream_version = m_Dsi.d.v0.bitstream_version;
446 } else if (m_Dsi.ac4_dsi_version == 1) {
447 bitstream_version = m_Dsi.d.v1.bitstream_version;
448 if (m_Dsi.d.v1.n_presentations) {
449 presentation_version = m_Dsi.d.v1.presentations[0].presentation_version;
450 if (presentation_version == 0) {
451 mdcompat = m_Dsi.d.v1.presentations[0].d.v0.mdcompat;
452 } else if (presentation_version == 1 || presentation_version == 2) {
453 mdcompat = m_Dsi.d.v1.presentations[0].d.v1.mdcompat;
454 for (int idx = 0; idx < m_Dsi.d.v1.n_presentations; idx ++){
455 if (mdcompat > m_Dsi.d.v1.presentations[idx].d.v1.mdcompat) {
456 mdcompat = m_Dsi.d.v1.presentations[idx].d.v1.mdcompat;
457 }
458 }
459 }
460 }
461 }
462 char string[64];
463 AP4_FormatString(string,
464 sizeof(string),
465 "ac-4.%02x.%02x.%02x",
466 bitstream_version,
467 presentation_version,
468 mdcompat);
469 codec = string;
470 }
471
472 /*----------------------------------------------------------------------
473 | AP4_Dac4Atom::InspectFields
474 +---------------------------------------------------------------------*/
475 AP4_Result
InspectFields(AP4_AtomInspector & inspector)476 AP4_Dac4Atom::InspectFields(AP4_AtomInspector& inspector)
477 {
478 inspector.AddField("ac4_dsi_version", m_Dsi.ac4_dsi_version);
479 if (m_Dsi.ac4_dsi_version == 0) {
480 inspector.AddField("bitstream_version", m_Dsi.d.v0.bitstream_version);
481 inspector.AddField("fs_index", m_Dsi.d.v0.fs_index);
482 inspector.AddField("fs", m_Dsi.d.v0.fs);
483 inspector.AddField("frame_rate_index", m_Dsi.d.v0.frame_rate_index);
484 } else if (m_Dsi.ac4_dsi_version == 1) {
485 inspector.AddField("bitstream_version", m_Dsi.d.v1.bitstream_version);
486 inspector.AddField("fs_index", m_Dsi.d.v1.fs_index);
487 inspector.AddField("fs", m_Dsi.d.v1.fs);
488 inspector.AddField("frame_rate_index", m_Dsi.d.v1.frame_rate_index);
489 if (m_Dsi.d.v1.bitstream_version > 1) {
490 inspector.AddField("short_program_id", m_Dsi.d.v1.short_program_id);
491 inspector.AddField("program_uuid", m_Dsi.d.v1.program_uuid, 16, AP4_AtomInspector::HINT_HEX);
492 }
493 inspector.AddField("bit_rate_mode", m_Dsi.d.v1.ac4_bitrate_dsi.bit_rate_mode);
494 inspector.AddField("bit_rate", m_Dsi.d.v1.ac4_bitrate_dsi.bit_rate);
495 inspector.AddField("bit_rate_precision", m_Dsi.d.v1.ac4_bitrate_dsi.bit_rate_precision);
496
497 for (unsigned int i = 0; i < m_Dsi.d.v1.n_presentations; i++) {
498 Ac4Dsi::PresentationV1& presentation = m_Dsi.d.v1.presentations[i];
499 char field_name[64];
500 AP4_FormatString(field_name, sizeof(field_name), "[%02d].presentation_version", i);
501 inspector.AddField(field_name, presentation.presentation_version);
502 if (presentation.presentation_version == 0) {
503 AP4_FormatString(field_name, sizeof(field_name), "[%02d].presentation_config", i);
504 inspector.AddField(field_name, presentation.d.v0.presentation_config);
505 AP4_FormatString(field_name, sizeof(field_name), "[%02d].mdcompat", i);
506 inspector.AddField(field_name, presentation.d.v0.mdcompat);
507 AP4_FormatString(field_name, sizeof(field_name), "[%02d].presentation_id", i);
508 inspector.AddField(field_name, presentation.d.v0.presentation_id);
509 AP4_FormatString(field_name, sizeof(field_name), "[%02d].dsi_frame_rate_multiply_info", i);
510 inspector.AddField(field_name, presentation.d.v0.dsi_frame_rate_multiply_info);
511 AP4_FormatString(field_name, sizeof(field_name), "[%02d].presentation_emdf_version", i);
512 inspector.AddField(field_name, presentation.d.v0.presentation_emdf_version);
513 AP4_FormatString(field_name, sizeof(field_name), "[%02d].presentation_key_id", i);
514 inspector.AddField(field_name, presentation.d.v0.presentation_key_id);
515 AP4_FormatString(field_name, sizeof(field_name), "[%02d].presentation_channel_mask", i);
516 inspector.AddField(field_name, presentation.d.v0.presentation_channel_mask, AP4_AtomInspector::HINT_HEX);
517 } else if (presentation.presentation_version == 1 || presentation.presentation_version == 2) {
518 AP4_FormatString(field_name, sizeof(field_name), "[%02d].presentation_config_v1", i);
519 inspector.AddField(field_name, presentation.d.v1.presentation_config_v1);
520 AP4_FormatString(field_name, sizeof(field_name), "[%02d].mdcompat", i);
521 inspector.AddField(field_name, presentation.d.v1.mdcompat);
522 AP4_FormatString(field_name, sizeof(field_name), "[%02d].presentation_id", i);
523 inspector.AddField(field_name, presentation.d.v1.presentation_id);
524 AP4_FormatString(field_name, sizeof(field_name), "[%02d].dsi_frame_rate_multiply_info", i);
525 inspector.AddField(field_name, presentation.d.v1.dsi_frame_rate_multiply_info);
526 AP4_FormatString(field_name, sizeof(field_name), "[%02d].dsi_frame_rate_fraction_info", i);
527 inspector.AddField(field_name, presentation.d.v1.dsi_frame_rate_fraction_info);
528 AP4_FormatString(field_name, sizeof(field_name), "[%02d].presentation_emdf_version", i);
529 inspector.AddField(field_name, presentation.d.v1.presentation_emdf_version);
530 AP4_FormatString(field_name, sizeof(field_name), "[%02d].presentation_key_id", i);
531 inspector.AddField(field_name, presentation.d.v1.presentation_key_id);
532 AP4_FormatString(field_name, sizeof(field_name), "[%02d].b_presentation_channel_coded", i);
533 inspector.AddField(field_name, presentation.d.v1.b_presentation_channel_coded);
534 AP4_FormatString(field_name, sizeof(field_name), "[%02d].dsi_presentation_ch_mode", i);
535 inspector.AddField(field_name, presentation.d.v1.dsi_presentation_ch_mode);
536 AP4_FormatString(field_name, sizeof(field_name), "[%02d].pres_b_4_back_channels_present", i);
537 inspector.AddField(field_name, presentation.d.v1.pres_b_4_back_channels_present);
538 AP4_FormatString(field_name, sizeof(field_name), "[%02d].pres_top_channel_pairs", i);
539 inspector.AddField(field_name, presentation.d.v1.pres_top_channel_pairs);
540 AP4_FormatString(field_name, sizeof(field_name), "[%02d].presentation_channel_mask_v1", i);
541 inspector.AddField(field_name, presentation.d.v1.presentation_channel_mask_v1, AP4_AtomInspector::HINT_HEX);
542 }
543 }
544 }
545 return AP4_SUCCESS;
546 }
547
548 /*----------------------------------------------------------------------
549 | AP4_Dac4Atom::Ac4Dsi::Ac4BitrateDsi::WriteBitrateDsi
550 +---------------------------------------------------------------------*/
551 AP4_Result
WriteBitrateDsi(AP4_BitWriter & bits)552 AP4_Dac4Atom::Ac4Dsi::Ac4BitrateDsi::WriteBitrateDsi(AP4_BitWriter &bits)
553 {
554 bits.Write(bit_rate_mode, 2);
555 bits.Write(bit_rate, 32);
556 bits.Write(bit_rate_precision, 32);
557 return AP4_SUCCESS;
558 }
559
560 /*----------------------------------------------------------------------
561 | AP4_Dac4Atom::Ac4Dsi::Ac4AlternativeInfo::WriteAlternativeInfo
562 +---------------------------------------------------------------------*/
563 AP4_Result
WriteAlternativeInfo(AP4_BitWriter & bits)564 AP4_Dac4Atom::Ac4Dsi::Ac4AlternativeInfo::WriteAlternativeInfo(AP4_BitWriter &bits)
565 {
566 bits.Write(name_len, 16);
567 for (unsigned int l = 0; l < name_len; l ++) {
568 bits.Write(presentation_name[l], 8);
569 }
570 bits.Write(n_targets, 5);
571 for (unsigned int t = 0; t < n_targets; t ++) {
572 bits.Write(target_md_compat[t], 3);
573 bits.Write(target_device_category[t], 8);
574 }
575 return AP4_SUCCESS;
576 }
577
578 /*----------------------------------------------------------------------
579 | AP4_Dac4Atom::Ac4Dsi::SubStream::ParseSubstreamInfoChan
580 +---------------------------------------------------------------------*/
581 AP4_Result
ParseSubstreamInfoChan(AP4_BitReader & bits,unsigned int presentation_version,unsigned char defalut_presentation_flag,unsigned int fs_idx,unsigned int & speaker_index_mask,unsigned int frame_rate_factor,unsigned int b_substreams_present,unsigned char & dolby_atmos_indicator)582 AP4_Dac4Atom::Ac4Dsi::SubStream::ParseSubstreamInfoChan(AP4_BitReader &bits,
583 unsigned int presentation_version,
584 unsigned char defalut_presentation_flag,
585 unsigned int fs_idx,
586 unsigned int &speaker_index_mask,
587 unsigned int frame_rate_factor,
588 unsigned int b_substreams_present,
589 unsigned char &dolby_atmos_indicator)
590 {
591 ch_mode = ParseChMode(bits, presentation_version, dolby_atmos_indicator);
592 int substreamSpeakerGroupIndexMask = AC4_SPEAKER_GROUP_INDEX_MASK_BY_CH_MODE[ch_mode];
593 if ((ch_mode >= CH_MODE_7_0_4) && (ch_mode <= CH_MODE_9_1_4)) {
594 if (!(b_4_back_channels_present = bits.ReadBit())) { // b_4_back_channels_present false
595 substreamSpeakerGroupIndexMask &= ~0x8; // Remove back channels (Lb,Rb) from mask
596 }
597 if (!(b_centre_present = bits.ReadBit())) { // b_centre_present false
598 substreamSpeakerGroupIndexMask &= ~0x2; // Remove centre channel (C) from mask
599 }
600 switch (top_channels_present = bits.ReadBits(2)) { // top_channels_present
601 case 0:
602 substreamSpeakerGroupIndexMask &= ~0x30; // Remove top channels (Tfl,Tfr,Tbl,Tbr) from mask
603 break;
604 case 1:
605 case 2:
606 substreamSpeakerGroupIndexMask &= ~0x30; // Remove top channels (Tfl,Tfr,Tbl,Tbr) from mask
607 substreamSpeakerGroupIndexMask |= 0x80; // Add top channels (Tl, Tr) from mask;
608 break;
609 }
610 }
611 dsi_substream_channel_mask = substreamSpeakerGroupIndexMask;
612 // Only combine channel masks of substream groups that are part of the first/default presentation
613 if (defalut_presentation_flag) {
614 speaker_index_mask |= substreamSpeakerGroupIndexMask;
615 }
616
617 ParseDsiSfMutiplier(bits, fs_idx);
618
619 b_substream_bitrate_indicator = bits.ReadBit();
620 if (b_substream_bitrate_indicator) { // b_bitrate_info
621 // bitrate_indicator()
622 ParseBitrateIndicator(bits);
623 }
624
625 if (ch_mode >= CH_MODE_70_52 && ch_mode <= CH_MODE_71_322) {
626 bits.ReadBit(); // add_ch_base
627 }
628 for (unsigned int i = 0; i < frame_rate_factor; i++) {
629 bits.ReadBit(); // b_audio_ndot
630 }
631
632 ParseSubstreamIdxInfo(bits, b_substreams_present);
633
634 return AP4_SUCCESS;
635 }
636
637 /*----------------------------------------------------------------------
638 | AP4_Dac4Atom::Ac4Dsi::SubStream::ParseSubStreamInfoAjoc
639 +---------------------------------------------------------------------*/
640 AP4_Result
ParseSubStreamInfoAjoc(AP4_BitReader & bits,unsigned int & channel_count,unsigned char defalut_presentation_flag,unsigned int fs_idx,unsigned int frame_rate_factor,unsigned int b_substreams_present)641 AP4_Dac4Atom::Ac4Dsi::SubStream::ParseSubStreamInfoAjoc(AP4_BitReader &bits,
642 unsigned int &channel_count,
643 unsigned char defalut_presentation_flag,
644 unsigned int fs_idx,
645 unsigned int frame_rate_factor,
646 unsigned int b_substreams_present)
647 {
648 b_lfe = bits.ReadBit(); // b_lfe
649 b_static_dmx = bits.ReadBit();
650 if (b_static_dmx) { // b_static_dmx
651 if (defalut_presentation_flag) {
652 channel_count += 5;
653 }
654 } else {
655 n_dmx_objects_minus1 = bits.ReadBits(4);
656 unsigned int nFullbandDmxSignals = n_dmx_objects_minus1 + 1;
657 BedDynObjAssignment(bits, nFullbandDmxSignals, false);
658 if (defalut_presentation_flag) {
659 channel_count += nFullbandDmxSignals;
660 }
661 }
662 if (bits.ReadBit()) { // b_oamd_common_data_present
663 // oamd_common_data()
664 ParseOamdCommonData(bits);
665 }
666 n_umx_objects_minus1 = bits.ReadBits(4);
667 int nFullbandUpmixSignals = n_umx_objects_minus1 + 1;
668 if (nFullbandUpmixSignals == 16) {
669 nFullbandUpmixSignals += AP4_Ac4VariableBits(bits, 3);
670 }
671
672 BedDynObjAssignment(bits, nFullbandUpmixSignals, true);
673 ParseDsiSfMutiplier(bits, fs_idx);
674
675 b_substream_bitrate_indicator = bits.ReadBit();
676 if (b_substream_bitrate_indicator) { // b_bitrate_info
677 ParseBitrateIndicator(bits);
678 }
679 for (unsigned int i = 0; i< frame_rate_factor; i++) {
680 bits.ReadBit(); // b_audio_ndot
681 }
682 ParseSubstreamIdxInfo(bits, b_substreams_present);
683 return AP4_SUCCESS;
684 }
685
686 /*----------------------------------------------------------------------
687 | AP4_Dac4Atom::Ac4Dsi::SubStream::ParseSubstreamInfoObj
688 +---------------------------------------------------------------------*/
689 AP4_Result
ParseSubstreamInfoObj(AP4_BitReader & bits,unsigned int & channel_count,unsigned char defalut_presentation_flag,unsigned int fs_idx,unsigned int frame_rate_factor,unsigned int b_substreams_present)690 AP4_Dac4Atom::Ac4Dsi::SubStream::ParseSubstreamInfoObj(AP4_BitReader &bits,
691 unsigned int &channel_count,
692 unsigned char defalut_presentation_flag,
693 unsigned int fs_idx,
694 unsigned int frame_rate_factor,
695 unsigned int b_substreams_present)
696 {
697 int nObjectsCode = bits.ReadBits(3);
698 if (defalut_presentation_flag) {
699 switch (nObjectsCode) {
700 case 0:
701 case 1:
702 case 2:
703 case 3:
704 channel_count += nObjectsCode;
705 break;
706 case 4:
707 channel_count += 5;
708 break;
709 default:
710 break;
711 //TODO: Error
712 }
713 }
714 if (bits.ReadBit()) { // b_dynamic_objects
715 b_substream_contains_dynamic_objects = 1;
716 unsigned int b_lfe = bits.ReadBit(); // b_lfe
717 if (defalut_presentation_flag && b_lfe) { channel_count += 1; }
718 }else {
719 if (bits.ReadBit()) { // b_bed_objects
720 b_substream_contains_bed_objects = 1;
721 if (bits.ReadBit()) { // b_bed_start
722 if (bits.ReadBit()) { // b_ch_assign_code
723 bits.ReadBits(3); // bed_chan_assign_code
724 }
725 else {
726 if (bits.ReadBit()) { // b_nonstd_bed_channel_assignment
727 bits.ReadBits(17); // nonstd_bed_channel_assignment_mask
728 }
729 else {
730 bits.ReadBits(10); // std_bed_channel_assignment_mask
731 }
732 }
733 }
734 }else {
735 if (bits.ReadBit()) { // b_isf
736 b_substream_contains_ISF_objects = 1;
737 if (bits.ReadBit()) { // b_isf_start
738 bits.ReadBits(3); // isf_config
739 }
740 }else {
741 int resBytes = bits.ReadBits(4);
742 bits.ReadBits(resBytes * 8);
743 }
744 }
745 }
746
747 ParseDsiSfMutiplier(bits, fs_idx);
748
749 b_substream_bitrate_indicator = bits.ReadBit();
750 if (b_substream_bitrate_indicator) { // b_bitrate_info
751 ParseBitrateIndicator(bits);
752 }
753 for (unsigned int i = 0; i< frame_rate_factor; i++) {
754 bits.ReadBit(); // b_audio_ndot
755 }
756 ParseSubstreamIdxInfo(bits, b_substreams_present);
757 return AP4_SUCCESS;
758 }
759
760 /*----------------------------------------------------------------------
761 | AP4_Dac4Atom::Ac4Dsi::SubStream::WriteSubstreamDsi
762 +---------------------------------------------------------------------*/
763 AP4_Result
WriteSubstreamDsi(AP4_BitWriter & bits,unsigned char b_channel_coded)764 AP4_Dac4Atom::Ac4Dsi::SubStream::WriteSubstreamDsi(AP4_BitWriter &bits, unsigned char b_channel_coded)
765 {
766 bits.Write(dsi_sf_multiplier, 2);
767 bits.Write(b_substream_bitrate_indicator, 1);
768 if (b_substream_bitrate_indicator == 1) {
769 bits.Write(substream_bitrate_indicator, 5);
770 }
771 if (b_channel_coded == 1) {
772 bits.Write(dsi_substream_channel_mask, 24);
773 }else {
774 bits.Write(b_ajoc, 1);
775 if (b_ajoc == 1) {
776 bits.Write(b_static_dmx, 1);
777 if (b_static_dmx == 0) {
778 bits.Write(n_dmx_objects_minus1, 4);
779 }
780 bits.Write(n_umx_objects_minus1, 6);
781 }
782 // substream composition information
783 bits.Write(b_substream_contains_bed_objects, 1);
784 bits.Write(b_substream_contains_dynamic_objects, 1);
785 bits.Write(b_substream_contains_ISF_objects, 1);
786 bits.Write(0, 1); //reserved bit
787 }
788 return AP4_SUCCESS;
789 }
790
791 /*----------------------------------------------------------------------
792 | AP4_Dac4Atom::Ac4Dsi::SubStream::ParseChMode
793 +---------------------------------------------------------------------*/
794 AP4_Result
ParseChMode(AP4_BitReader & bits,int presentationVersion,unsigned char & dolby_atmos_indicator)795 AP4_Dac4Atom::Ac4Dsi::SubStream::ParseChMode(AP4_BitReader &bits, int presentationVersion, unsigned char &dolby_atmos_indicator)
796 {
797 int channel_mode_code = 0;
798
799 channel_mode_code = bits.ReadBit();
800 if (channel_mode_code == 0) { // Mono 0b0
801 return CH_MODE_MONO;
802 }
803 channel_mode_code = (channel_mode_code << 1) | bits.ReadBit();
804 if (channel_mode_code == 2) { // Stereo 0b10
805 return CH_MODE_STEREO;
806 }
807 channel_mode_code = (channel_mode_code << 2) | bits.ReadBits(2);
808 switch (channel_mode_code) {
809 case 12: // 3.0 0b1100
810 return CH_MODE_3_0;
811 case 13: // 5.0 0b1101
812 return CH_MODE_5_0;
813 case 14: // 5.1 0b1110
814 return CH_MODE_5_1;
815 }
816 channel_mode_code = (channel_mode_code << 3) | bits.ReadBits(3);
817 switch (channel_mode_code) {
818 case 120: // 0b1111000
819 if (presentationVersion == 2) { // IMS (all content)
820 return CH_MODE_STEREO;
821 }
822 else { // 7.0: 3/4/0
823 return CH_MODE_70_34;
824 }
825 case 121: // 0b1111001
826 if (presentationVersion == 2) { // IMS (Atmos content)
827 dolby_atmos_indicator |= 1;
828 return CH_MODE_STEREO;
829 }
830 else { // 7.1: 3/4/0.1
831 return CH_MODE_71_34;
832 }
833 case 122: // 7.0: 5/2/0 0b1111010
834 return CH_MODE_70_52;
835 case 123: // 7.1: 5/2/0.1 0b1111011
836 return CH_MODE_71_52;
837 case 124: // 7.0: 3/2/2 0b1111100
838 return CH_MODE_70_322;
839 case 125: // 7.1: 3/2/2.1 0b1111101
840 return CH_MODE_71_322;
841 }
842 channel_mode_code = (channel_mode_code << 1) | bits.ReadBit();
843 switch (channel_mode_code) {
844 case 252: // 7.0.4 0b11111100
845 return CH_MODE_7_0_4;
846 case 253: // 7.1.4 0b11111101
847 return CH_MODE_7_1_4;
848 }
849 channel_mode_code = (channel_mode_code << 1) | bits.ReadBit();
850 switch (channel_mode_code) {
851 case 508: // 9.0.4 0b111111100
852 return CH_MODE_9_0_4;
853 case 509: // 9.1.4 0b111111101
854 return CH_MODE_9_1_4;
855 case 510: // 22.2 0b111111110
856 return CH_MODE_22_2;
857 case 511: // Reserved, escape value 0b111111111
858 default:
859 AP4_Ac4VariableBits(bits, 2);
860 return CH_MODE_RESERVED;
861 }
862 }
863
864 /*----------------------------------------------------------------------
865 | AP4_Dac4Atom::Ac4Dsi::SubStream::ParseDsiSfMutiplier
866 +---------------------------------------------------------------------*/
867 AP4_Result
ParseDsiSfMutiplier(AP4_BitReader & bits,unsigned int fs_idx)868 AP4_Dac4Atom::Ac4Dsi::SubStream::ParseDsiSfMutiplier(AP4_BitReader &bits,
869 unsigned int fs_idx)
870 {
871 if (fs_idx == 1) {
872 if (bits.ReadBit()) { // b_sf_miultiplier
873 // 96 kHz or 192 kHz
874 dsi_sf_multiplier = bits.ReadBit() + 1; // sf_multiplier
875 }else{
876 // 48 kHz
877 dsi_sf_multiplier = 0;
878 }
879 }
880 return AP4_SUCCESS;
881 }
882
883 /*----------------------------------------------------------------------
884 | AP4_Dac4Atom::Ac4Dsi::SubStream::BedDynObjAssignment
885 +---------------------------------------------------------------------*/
886 AP4_Result
BedDynObjAssignment(AP4_BitReader & bits,unsigned int nSignals,bool is_upmix)887 AP4_Dac4Atom::Ac4Dsi::SubStream::BedDynObjAssignment(AP4_BitReader &bits,
888 unsigned int nSignals,
889 bool is_upmix)
890 {
891 if (!bits.ReadBit()) { // b_dyn_objects_only
892 if (bits.ReadBit()) { // b_isf
893 unsigned char isf_config = bits.ReadBits(3);
894 if (is_upmix) {
895 b_substream_contains_ISF_objects |= 1;
896 if (nSignals > ObjNumFromIsfConfig(isf_config)) {
897 b_substream_contains_dynamic_objects |= 1;
898 }
899 }
900 }else {
901 if (bits.ReadBit()) { // b_ch_assign_code
902 unsigned char bed_chan_assign_code = bits.ReadBits(3);
903 if (is_upmix) {
904 b_substream_contains_bed_objects |= 1;
905 if (nSignals > BedNumFromAssignCode(bed_chan_assign_code)) {
906 b_substream_contains_dynamic_objects |= 1;
907 }
908 }
909 }else {
910 if (bits.ReadBit()) { // b_chan_assign_mask
911 if (bits.ReadBit()) { // b_nonstd_bed_channel_assignment
912 unsigned int nonstd_bed_channel_assignment_mask = bits.ReadBits(17);
913 if (is_upmix) {
914 unsigned int bed_num = BedNumFromNonStdMask(nonstd_bed_channel_assignment_mask);
915 if (bed_num > 0) { b_substream_contains_bed_objects |= 1; }
916 if (nSignals > bed_num) {
917 b_substream_contains_dynamic_objects |= 1;
918 }
919 }
920 }
921 else {
922 unsigned int std_bed_channel_assignment_mask = bits.ReadBits(10);
923 if (is_upmix) {
924 unsigned int bed_num = BedNumFromStdMask(std_bed_channel_assignment_mask);
925 if (bed_num > 0) { b_substream_contains_bed_objects |= 1; }
926 if (nSignals > bed_num) {
927 b_substream_contains_dynamic_objects |= 1;
928 }
929 }
930 }
931 }else {
932 unsigned int nBedSignals = 0;
933 if (nSignals > 1) {
934 int bedChBits = (int) ceil(log((float)nSignals)/log((float)2));
935 nBedSignals = bits.ReadBits(bedChBits) + 1;
936 }
937 else {
938 nBedSignals = 1;
939 }
940 for (unsigned int b = 0; b < nBedSignals; b++) {
941 bits.ReadBits(4); // nonstd_bed_channel_assignment
942 }
943 if (is_upmix) {
944 b_substream_contains_bed_objects |= 1;
945 if (nSignals > nBedSignals){ b_substream_contains_dynamic_objects |= 1; }
946 }
947 }
948 }
949 }
950 }else {
951 if (is_upmix) {
952 b_substream_contains_dynamic_objects |= 1;
953 b_substream_contains_bed_objects |= 0;
954 b_substream_contains_ISF_objects |= 0;
955 }
956 }
957 return AP4_SUCCESS;
958 }
959
960 /*----------------------------------------------------------------------
961 | AP4_Dac4Atom::Ac4Dsi::SubStream::ParseSubstreamIdxInfo
962 +---------------------------------------------------------------------*/
963 AP4_Result
ParseSubstreamIdxInfo(AP4_BitReader & bits,unsigned int b_substreams_present)964 AP4_Dac4Atom::Ac4Dsi::SubStream::ParseSubstreamIdxInfo(AP4_BitReader &bits, unsigned int b_substreams_present)
965 {
966 if (b_substreams_present == 1) {
967 if (bits.ReadBits(2) == 3) { // substream_index
968 AP4_Ac4VariableBits(bits, 2);
969 }
970 }
971 return AP4_SUCCESS;
972 }
973
974 /*----------------------------------------------------------------------
975 | AP4_Dac4Atom::Ac4Dsi::SubStream::ParseBitrateIndicator
976 +---------------------------------------------------------------------*/
977 AP4_Result
ParseBitrateIndicator(AP4_BitReader & bits)978 AP4_Dac4Atom::Ac4Dsi::SubStream::ParseBitrateIndicator(AP4_BitReader &bits)
979 {
980 substream_bitrate_indicator = bits.ReadBits(3);
981 if ((substream_bitrate_indicator & 0x1) == 1) { // bitrate_indicator
982 substream_bitrate_indicator = (substream_bitrate_indicator << 2) + bits.ReadBits(2);
983 }
984 return AP4_SUCCESS;
985 }
986
987 /*----------------------------------------------------------------------
988 | AP4_Dac4Atom::Ac4Dsi::SubStream::ParseOamdCommonData
989 +---------------------------------------------------------------------*/
990 AP4_Result
ParseOamdCommonData(AP4_BitReader & bits)991 AP4_Dac4Atom::Ac4Dsi::SubStream::ParseOamdCommonData(AP4_BitReader &bits)
992 {
993 if (bits.ReadBit() == 0) { // b_default_screen_size_ratio
994 bits.ReadBits(5); // master_screen_size_ratio_code
995 }
996 bits.ReadBit(); // b_bed_object_chan_distribute
997 if (bits.ReadBit()) { // b_additional_data
998 int addDataBytes = bits.ReadBit() + 1;
999 if (addDataBytes == 2) {
1000 addDataBytes += AP4_Ac4VariableBits(bits, 2);
1001 }
1002 unsigned int bits_used = Trim(bits);
1003 bits_used += BedRendeInfo(bits);
1004 bits.ReadBits(addDataBytes * 8 - bits_used);
1005 }
1006 return AP4_SUCCESS;
1007 }
1008
1009 /*----------------------------------------------------------------------
1010 | AP4_Dac4Atom::Ac4Dsi::SubStream::Trim
1011 +---------------------------------------------------------------------*/
1012 AP4_Result
Trim(AP4_BitReader & bits)1013 AP4_Dac4Atom::Ac4Dsi::SubStream::Trim(AP4_BitReader &bits)
1014 {
1015 return AP4_SUCCESS;
1016 }
1017
1018 /*----------------------------------------------------------------------
1019 | AP4_Dac4Atom::Ac4Dsi::SubStream::BedRendeInfo
1020 +---------------------------------------------------------------------*/
1021 AP4_Result
BedRendeInfo(AP4_BitReader & bits)1022 AP4_Dac4Atom::Ac4Dsi::SubStream::BedRendeInfo(AP4_BitReader &bits)
1023 {
1024 return AP4_SUCCESS;
1025 }
1026
1027 /*----------------------------------------------------------------------
1028 | AP4_Dac4Atom::Ac4Dsi::SubStream::ObjNumFromIsfConfig
1029 +---------------------------------------------------------------------*/
1030 AP4_UI32
ObjNumFromIsfConfig(unsigned char isf_config)1031 AP4_Dac4Atom::Ac4Dsi::SubStream::ObjNumFromIsfConfig(unsigned char isf_config)
1032 {
1033 unsigned int obj_num = 0;
1034 switch (isf_config){
1035 case 0: obj_num = 4 ; break;
1036 case 1: obj_num = 8 ; break;
1037 case 2: obj_num = 10; break;
1038 case 3: obj_num = 14; break;
1039 case 4: obj_num = 15; break;
1040 case 5: obj_num = 30; break;
1041 default: obj_num = 0;
1042 }
1043 return obj_num;
1044 }
1045
1046 /*----------------------------------------------------------------------
1047 | AP4_Dac4Atom::Ac4Dsi::SubStream::BedNumFromAssignCode
1048 +---------------------------------------------------------------------*/
1049 AP4_UI32
BedNumFromAssignCode(unsigned char assign_code)1050 AP4_Dac4Atom::Ac4Dsi::SubStream::BedNumFromAssignCode(unsigned char assign_code)
1051 {
1052 unsigned int bed_num = 0;
1053 switch (assign_code){
1054 case 0: bed_num = 2 ; break;
1055 case 1: bed_num = 3 ; break;
1056 case 2: bed_num = 6 ; break;
1057 case 3: bed_num = 8 ; break;
1058 case 4: bed_num = 10; break;
1059 case 5: bed_num = 8 ; break;
1060 case 6: bed_num = 10; break;
1061 case 7: bed_num = 12; break;
1062 default: bed_num = 0;
1063 }
1064 return bed_num;
1065 }
1066
1067 /*----------------------------------------------------------------------
1068 | AP4_Dac4Atom::Ac4Dsi::SubStream::BedNumFromNonStdMask
1069 +---------------------------------------------------------------------*/
1070 AP4_UI32
BedNumFromNonStdMask(unsigned int non_std_mask)1071 AP4_Dac4Atom::Ac4Dsi::SubStream::BedNumFromNonStdMask(unsigned int non_std_mask)
1072 {
1073 unsigned int bed_num = 0;
1074 // Table 85: nonstd_bed_channel_assignment AC-4 part-2 v1.2.1
1075 for (unsigned int idx = 0; idx < 17; idx ++) {
1076 if ((non_std_mask >> idx) & 0x1){
1077 bed_num ++;
1078 }
1079 }
1080 return bed_num;
1081 }
1082
1083 /*----------------------------------------------------------------------
1084 | AP4_Dac4Atom::Ac4Dsi::SubStream::BedNumFromStdMask
1085 +---------------------------------------------------------------------*/
1086 AP4_UI32
BedNumFromStdMask(unsigned int std_mask)1087 AP4_Dac4Atom::Ac4Dsi::SubStream::BedNumFromStdMask(unsigned int std_mask)
1088 {
1089 unsigned int bed_num = 0;
1090 // Table 86 std_bed_channel_assignment_flag[] AC-4 part-2 v1.2.1
1091 for (unsigned int idx = 0; idx < 10; idx ++) {
1092 if ((std_mask >> idx) & 0x1){
1093 if ((idx == 1) || (idx == 2) || (idx == 9)) { bed_num ++;}
1094 else { bed_num += 2; }
1095 }
1096 }
1097 return bed_num;
1098 }
1099
1100 /*----------------------------------------------------------------------
1101 | AP4_Dac4Atom::Ac4Dsi::SubStream::GetChModeCore
1102 +---------------------------------------------------------------------*/
1103 AP4_Result
GetChModeCore(unsigned char b_channel_coded)1104 AP4_Dac4Atom::Ac4Dsi::SubStream::GetChModeCore(unsigned char b_channel_coded)
1105 {
1106 int ch_mode_core = -1;
1107 if (b_channel_coded == 0 &&
1108 b_ajoc == 1 &&
1109 b_static_dmx == 1 &&
1110 b_lfe == 0){
1111 ch_mode_core = 3 ;
1112 }else if (b_channel_coded == 0 &&
1113 b_ajoc == 1 &&
1114 b_static_dmx == 1 &&
1115 b_lfe == 1){
1116 ch_mode_core = 4 ;
1117 }else if ((b_channel_coded == 1) &&
1118 (ch_mode == 11 || ch_mode == 13)){
1119 ch_mode_core = 5 ;
1120 }else if ((b_channel_coded == 1) &&
1121 (ch_mode == 12 || ch_mode == 14)){
1122 ch_mode_core = 6 ;
1123 }
1124 return ch_mode_core;
1125 }
1126
1127 /*----------------------------------------------------------------------
1128 | AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1::ParseSubstreamGroupInfo
1129 +---------------------------------------------------------------------*/
1130 AP4_Result
ParseSubstreamGroupInfo(AP4_BitReader & bits,unsigned int bitstream_version,unsigned int presentation_version,unsigned char defalut_presentation_flag,unsigned int frame_rate_factor,unsigned int fs_idx,unsigned int & channel_count,unsigned int & speaker_index_mask,unsigned int & b_obj_or_Ajoc)1131 AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1::ParseSubstreamGroupInfo(AP4_BitReader& bits,
1132 unsigned int bitstream_version,
1133 unsigned int presentation_version,
1134 unsigned char defalut_presentation_flag,
1135 unsigned int frame_rate_factor,
1136 unsigned int fs_idx,
1137 unsigned int& channel_count,
1138 unsigned int& speaker_index_mask,
1139 unsigned int& b_obj_or_Ajoc)
1140 {
1141 d.v1.b_substreams_present = bits.ReadBit();
1142 d.v1.b_hsf_ext = bits.ReadBit();
1143 if (bits.ReadBit()) {
1144 d.v1.n_substreams = 1;
1145 } else{
1146 d.v1.n_substreams = bits.ReadBits(2) + 2;
1147 if (d.v1.n_substreams == 5) {
1148 d.v1.n_substreams += AP4_Ac4VariableBits(bits, 2);
1149 }
1150 }
1151 d.v1.substreams = new AP4_Dac4Atom::Ac4Dsi::SubStream[d.v1.n_substreams];
1152 AP4_SetMemory(d.v1.substreams, 0, d.v1.n_substreams * sizeof(d.v1.substreams[0]));
1153 d.v1.b_channel_coded = bits.ReadBit();
1154 if (d.v1.b_channel_coded) {
1155 for (unsigned int sus = 0; sus < d.v1.n_substreams; sus++) {
1156 AP4_Dac4Atom::Ac4Dsi::SubStream& substream = d.v1.substreams[sus];
1157 if (bitstream_version == 1) {
1158 bits.ReadBit(); // sus_ver
1159 }
1160
1161 // ac4_substream_info_chan()
1162 substream.ParseSubstreamInfoChan(bits,
1163 presentation_version,
1164 defalut_presentation_flag,
1165 fs_idx,
1166 speaker_index_mask,
1167 frame_rate_factor,
1168 d.v1.b_substreams_present,
1169 d.v1.dolby_atmos_indicator);
1170
1171 if (d.v1.b_hsf_ext) {
1172 // ac4_hsf_ext_substream_info()
1173 ParseHsfExtSubstreamInfo(bits);
1174 }
1175 }
1176 } else { // b_channel_coded == 0
1177 b_obj_or_Ajoc = 1;
1178 if (bits.ReadBit()) { // b_oamd_substream
1179 //oamd_substream_info()
1180 ParseOamdSubstreamInfo(bits);
1181 }
1182 for (int sus = 0; sus < d.v1.n_substreams; sus++) {
1183 AP4_Dac4Atom::Ac4Dsi::SubStream& substream = d.v1.substreams[sus];
1184 substream.b_ajoc = bits.ReadBit();
1185 unsigned int local_channel_count = 0;
1186 if (substream.b_ajoc) { // b_ajoc
1187 // ac4_substream_info_ajoc()
1188 substream.ParseSubStreamInfoAjoc(bits,
1189 local_channel_count,
1190 defalut_presentation_flag,
1191 fs_idx,
1192 frame_rate_factor,
1193 d.v1.b_substreams_present);
1194
1195 if (d.v1.b_hsf_ext) {
1196 // ac4_hsf_ext_substream_info()
1197 ParseHsfExtSubstreamInfo(bits);
1198 }
1199 }else {
1200 // ac4_substream_info_obj()
1201 substream.ParseSubstreamInfoObj(bits,
1202 local_channel_count,
1203 defalut_presentation_flag,
1204 fs_idx,
1205 frame_rate_factor,
1206 d.v1.b_substreams_present);
1207
1208 if (d.v1.b_hsf_ext) {
1209 // ac4_hsf_ext_substream_info()
1210 ParseHsfExtSubstreamInfo(bits);
1211 }
1212 }
1213 if (channel_count < local_channel_count) { channel_count = local_channel_count;}
1214 }
1215 }
1216
1217 d.v1.b_content_type = bits.ReadBit();
1218 if (d.v1.b_content_type) {
1219 // content_type()
1220 ParseContentType(bits);
1221 }
1222 return AP4_SUCCESS;
1223 }
1224
1225 /*----------------------------------------------------------------------
1226 | AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1::WriteSubstreamGroupDsi
1227 +---------------------------------------------------------------------*/
1228 AP4_Result
WriteSubstreamGroupDsi(AP4_BitWriter & bits)1229 AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1::WriteSubstreamGroupDsi(AP4_BitWriter &bits)
1230 {
1231 bits.Write(d.v1.b_substreams_present, 1);
1232 bits.Write(d.v1.b_hsf_ext, 1);
1233 bits.Write(d.v1.b_channel_coded, 1);
1234 bits.Write(d.v1.n_substreams, 8);
1235 for (unsigned int sg = 0; sg < d.v1.n_substreams; sg++ ){
1236 d.v1.substreams[sg].WriteSubstreamDsi(bits, d.v1.b_channel_coded);
1237 }
1238 WriteContentType(bits);
1239 return AP4_SUCCESS;
1240 }
1241
1242 /*----------------------------------------------------------------------
1243 | AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1::ParseOamdSubstreamInfo
1244 +---------------------------------------------------------------------*/
1245 AP4_Result
ParseOamdSubstreamInfo(AP4_BitReader & bits)1246 AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1::ParseOamdSubstreamInfo(AP4_BitReader &bits)
1247 {
1248 bits.ReadBit(); // b_oamd_ndot
1249 if (d.v1.b_substreams_present == 1) {
1250 if (bits.ReadBits(2) == 3) { // substream_index
1251 AP4_Ac4VariableBits(bits, 2);
1252 }
1253 }
1254 return AP4_SUCCESS;
1255 }
1256
1257 /*----------------------------------------------------------------------
1258 | AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1::ParseHsfExtSubstreamInfo
1259 +---------------------------------------------------------------------*/
1260 AP4_Result
ParseHsfExtSubstreamInfo(AP4_BitReader & bits)1261 AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1::ParseHsfExtSubstreamInfo(AP4_BitReader &bits)
1262 {
1263 if (d.v1.b_substreams_present == 1) {
1264 if (bits.ReadBits(2) == 3) { // substream_index
1265 AP4_Ac4VariableBits(bits, 2);
1266 }
1267 }
1268 return AP4_SUCCESS;
1269 }
1270
1271 /*----------------------------------------------------------------------
1272 | AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1::ParseContentType
1273 +---------------------------------------------------------------------*/
1274 AP4_Result
ParseContentType(AP4_BitReader & bits)1275 AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1::ParseContentType(AP4_BitReader &bits)
1276 {
1277 d.v1.content_classifier = bits.ReadBits(3); // content_classifier
1278 d.v1.b_language_indicator = bits.ReadBit();
1279 if (d.v1.b_language_indicator == 1) { // b_language_indicator
1280 if (bits.ReadBit()) { // b_serialized_language_tag
1281 bits.ReadBits(17); // b_start_tag, language_tag_chunk
1282 }
1283 else {
1284 d.v1.n_language_tag_bytes= bits.ReadBits(6);
1285 for (unsigned int l = 0; l < d.v1.n_language_tag_bytes; l++){
1286 d.v1.language_tag_bytes[l] = bits.ReadBits(8);
1287 }
1288 }
1289 }
1290 return AP4_SUCCESS;
1291 }
1292
1293 /*----------------------------------------------------------------------
1294 | AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1::WriteContentType
1295 +---------------------------------------------------------------------*/
1296 AP4_Result
WriteContentType(AP4_BitWriter & bits)1297 AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1::WriteContentType(AP4_BitWriter &bits)
1298 {
1299 bits.Write(d.v1.b_content_type, 1);
1300 if (d.v1.b_content_type == 1){
1301 bits.Write(d.v1.content_classifier, 3);
1302 bits.Write(d.v1.b_language_indicator, 1);
1303 if (d.v1.b_language_indicator == 1){
1304 bits.Write(d.v1.n_language_tag_bytes, 6);
1305 for (unsigned int idx = 0; idx < d.v1.n_language_tag_bytes; idx++ ){
1306 bits.Write(d.v1.language_tag_bytes[idx], 8);
1307 }
1308 }
1309 }
1310 return AP4_SUCCESS;
1311 }
1312
1313 /*----------------------------------------------------------------------
1314 | AP4_Dac4Atom::Ac4Dsi::PresentationV1::Parse
1315 +---------------------------------------------------------------------*/
1316 AP4_Result
ParsePresentationV1Info(AP4_BitReader & bits,unsigned int bitstream_version,unsigned int frame_rate_idx,unsigned int pres_idx,unsigned int & max_group_index,unsigned int ** first_pres_sg_index,unsigned int & first_pres_sg_num)1317 AP4_Dac4Atom::Ac4Dsi::PresentationV1::ParsePresentationV1Info(AP4_BitReader &bits,
1318 unsigned int bitstream_version,
1319 unsigned int frame_rate_idx,
1320 unsigned int pres_idx,
1321 unsigned int &max_group_index,
1322 unsigned int **first_pres_sg_index,
1323 unsigned int &first_pres_sg_num)
1324 {
1325 unsigned int *substreamGroupIndexes = new unsigned int[AP4_AC4_SUBSTREAM_GROUP_NUM];
1326 unsigned int b_single_substream_group = bits.ReadBit();
1327 if (b_single_substream_group != 1){
1328 d.v1.presentation_config_v1 = bits.ReadBits(3);
1329 if (d.v1.presentation_config_v1 == 7) {
1330 d.v1.presentation_config_v1 += AP4_Ac4VariableBits(bits, 2);
1331 }
1332 }else {
1333 d.v1.presentation_config_v1 = 0x1f;
1334 }
1335
1336 // presentation_version()
1337 ParsePresentationVersion(bits, bitstream_version);
1338
1339 AP4_Ac4EmdfInfo tmp_emdf_info;
1340 if (b_single_substream_group != 1 && d.v1.presentation_config_v1 == 6){
1341 d.v1.b_add_emdf_substreams = 1;
1342 }else{
1343 if (bitstream_version != 1){
1344 d.v1.mdcompat = bits.ReadBits(3);
1345 }
1346 d.v1.b_presentation_id = bits.ReadBit();
1347 if (d.v1.b_presentation_id) {
1348 d.v1.presentation_id = AP4_Ac4VariableBits(bits, 2);
1349 }
1350 // frame_rate_multiply_info()
1351 ParseDSIFrameRateMultiplyInfo(bits, frame_rate_idx);
1352
1353 // frame_rate_fractions_info()
1354 ParseDSIFrameRateFractionsInfo(bits, frame_rate_idx);
1355
1356 // emdf_info()
1357 ParseEmdInfo(bits, tmp_emdf_info);
1358 d.v1.presentation_emdf_version = tmp_emdf_info.emdf_version;
1359 d.v1.presentation_key_id = tmp_emdf_info.key_id;
1360
1361 // b_presentation_filter
1362 d.v1.b_presentation_filter = bits.ReadBit();
1363 if (d.v1.b_presentation_filter == 1){
1364 d.v1.b_enable_presentation = bits.ReadBit();
1365 }
1366 if (b_single_substream_group == 1){
1367 substreamGroupIndexes[0] = ParseAc4SgiSpecifier(bits, bitstream_version);
1368 max_group_index = AP4_SetMaxGroupIndex(substreamGroupIndexes[0], max_group_index);
1369 d.v1.n_substream_groups = 1;
1370 d.v1.substream_group_indexs = substreamGroupIndexes;
1371 }else {
1372 d.v1.b_multi_pid = bits.ReadBit();
1373 switch (d.v1.presentation_config_v1){
1374 case 0: // M&E + D
1375 case 2: // Main + Assoc
1376 substreamGroupIndexes[0] = ParseAc4SgiSpecifier(bits, bitstream_version);
1377 substreamGroupIndexes[1] = ParseAc4SgiSpecifier(bits, bitstream_version);
1378 max_group_index = AP4_SetMaxGroupIndex(substreamGroupIndexes[0], max_group_index);
1379 max_group_index = AP4_SetMaxGroupIndex(substreamGroupIndexes[1], max_group_index);
1380 d.v1.n_substream_groups = 2;
1381 d.v1.substream_group_indexs = substreamGroupIndexes;
1382 break;
1383 case 1: // Main + DE
1384 // shall return same substream group index, need stream to verify
1385 substreamGroupIndexes[0] = ParseAc4SgiSpecifier(bits, bitstream_version);
1386 substreamGroupIndexes[1] = ParseAc4SgiSpecifier(bits, bitstream_version);
1387 max_group_index = AP4_SetMaxGroupIndex(substreamGroupIndexes[0], max_group_index);
1388 max_group_index = AP4_SetMaxGroupIndex(substreamGroupIndexes[1], max_group_index);
1389 d.v1.n_substream_groups = 2;
1390 d.v1.substream_group_indexs = substreamGroupIndexes;
1391 break;
1392 case 3: // M&E + D + Assoc
1393 substreamGroupIndexes[0] = ParseAc4SgiSpecifier(bits, bitstream_version);
1394 substreamGroupIndexes[1] = ParseAc4SgiSpecifier(bits, bitstream_version);
1395 substreamGroupIndexes[2] = ParseAc4SgiSpecifier(bits, bitstream_version);
1396 max_group_index = AP4_SetMaxGroupIndex(substreamGroupIndexes[0], max_group_index);
1397 max_group_index = AP4_SetMaxGroupIndex(substreamGroupIndexes[1], max_group_index);
1398 max_group_index = AP4_SetMaxGroupIndex(substreamGroupIndexes[2], max_group_index);
1399 d.v1.n_substream_groups = 3;
1400 d.v1.substream_group_indexs = substreamGroupIndexes;
1401 break;
1402 case 4: // Main + DE + Assoc
1403 // shall return only two substream group index, need stream to verify
1404 substreamGroupIndexes[0] = ParseAc4SgiSpecifier(bits, bitstream_version);
1405 substreamGroupIndexes[1] = ParseAc4SgiSpecifier(bits, bitstream_version);
1406 substreamGroupIndexes[2] = ParseAc4SgiSpecifier(bits, bitstream_version);
1407 max_group_index = AP4_SetMaxGroupIndex(substreamGroupIndexes[0], max_group_index);
1408 max_group_index = AP4_SetMaxGroupIndex(substreamGroupIndexes[1], max_group_index);
1409 max_group_index = AP4_SetMaxGroupIndex(substreamGroupIndexes[2], max_group_index);
1410 d.v1.n_substream_groups = 3;
1411 d.v1.substream_group_indexs = substreamGroupIndexes;
1412 break;
1413 case 5:
1414 d.v1.n_substream_groups = bits.ReadBits(2) + 2;
1415 if (d.v1.n_substream_groups == 5) {
1416 d.v1.n_substream_groups += AP4_Ac4VariableBits(bits, 2);
1417 }
1418 delete[] substreamGroupIndexes;
1419 substreamGroupIndexes = new unsigned int[d.v1.n_substream_groups];
1420 for (unsigned int sg = 0; sg < d.v1.n_substream_groups; sg ++){
1421 substreamGroupIndexes[sg] = ParseAc4SgiSpecifier(bits, bitstream_version);
1422 max_group_index = AP4_SetMaxGroupIndex(substreamGroupIndexes[sg], max_group_index);
1423 }
1424 d.v1.substream_group_indexs = substreamGroupIndexes;
1425 break;
1426 default:
1427 // presentation_config_ext_info()
1428 ParsePresentationConfigExtInfo(bits, bitstream_version);
1429 break;
1430 }
1431 }
1432 // b_pre_virtualized
1433 d.v1.b_pre_virtualized = bits.ReadBit();
1434 d.v1.b_add_emdf_substreams = bits.ReadBit();
1435 // ac4_presentation_substream_info()
1436 ParsePresentationSubstreamInfo(bits);
1437 }
1438
1439 if (d.v1.b_add_emdf_substreams){
1440 d.v1.n_add_emdf_substreams = bits.ReadBits(2);
1441 if (d.v1.n_add_emdf_substreams == 0){
1442 d.v1.n_add_emdf_substreams = AP4_Ac4VariableBits(bits, 2) + 4;
1443 }
1444 for (unsigned int cnt = 0; cnt < d.v1.n_add_emdf_substreams; cnt ++){
1445 ParseEmdInfo(bits, tmp_emdf_info);
1446 d.v1.substream_emdf_version[cnt] = tmp_emdf_info.emdf_version;
1447 d.v1.substream_key_id[cnt] = tmp_emdf_info.key_id;
1448 }
1449 }
1450 if (pres_idx == 0){
1451 *first_pres_sg_index = substreamGroupIndexes;
1452 first_pres_sg_num = d.v1.n_substream_groups;
1453 }
1454 return AP4_SUCCESS;
1455 }
1456
1457 /*----------------------------------------------------------------------
1458 | AP4_Dac4Atom::Ac4Dsi::PresentationV1::WritePresentationV1Dsi
1459 +---------------------------------------------------------------------*/
1460 AP4_Result
WritePresentationV1Dsi(AP4_BitWriter & bits)1461 AP4_Dac4Atom::Ac4Dsi::PresentationV1::WritePresentationV1Dsi(AP4_BitWriter &bits)
1462 {
1463 bits.Write(d.v1.presentation_config_v1, 5);
1464 if (d.v1.presentation_config_v1 == 0x06) {
1465 d.v1.b_add_emdf_substreams = 1;
1466 }else {
1467 bits.Write(d.v1.mdcompat, 3);
1468 bits.Write(d.v1.b_presentation_id, 1);
1469 if (d.v1.b_presentation_id == 1){
1470 bits.Write(d.v1.presentation_id, 5);
1471 }
1472 bits.Write(d.v1.dsi_frame_rate_multiply_info, 2);
1473 bits.Write(d.v1.dsi_frame_rate_fraction_info, 2);
1474 bits.Write(d.v1.presentation_emdf_version, 5);
1475 bits.Write(d.v1.presentation_key_id, 10);
1476 d.v1.b_presentation_channel_coded = ((GetPresentationChMode() == -1) ? 0: 1);
1477 bits.Write(d.v1.b_presentation_channel_coded, 1);
1478 if (d.v1.b_presentation_channel_coded == 1) {
1479 d.v1.dsi_presentation_ch_mode = GetPresentationChMode();
1480 bits.Write(d.v1.dsi_presentation_ch_mode, 5);
1481 if (d.v1.dsi_presentation_ch_mode >= 11 && d.v1.dsi_presentation_ch_mode <= 14){
1482 GetPresB4BackChannelsPresent();
1483 GetPresTopChannelPairs();
1484 bits.Write(d.v1.pres_b_4_back_channels_present, 1);
1485 bits.Write(d.v1.pres_top_channel_pairs, 2);
1486 if (d.v1.pres_top_channel_pairs) {
1487 d.v1.dolby_atmos_indicator = 1;
1488 }
1489 }
1490 d.v1.presentation_channel_mask_v1 = GetPresentationChannelMask();
1491 bits.Write(d.v1.presentation_channel_mask_v1, 24);
1492 }
1493 int pres_ch_mode_core = GetBPresentationCoreDiffers();
1494 bits.Write(d.v1.b_presentation_core_differs = ((pres_ch_mode_core == -1) ? 0: 1), 1);
1495 if (d.v1.b_presentation_core_differs == 1) {
1496 bits.Write(d.v1.b_presentation_core_channel_coded = ((pres_ch_mode_core == -1) ? 0: 1), 1);
1497 if (d.v1.b_presentation_core_channel_coded == 1) {
1498 bits.Write(d.v1.dsi_presentation_channel_mode_core = (pres_ch_mode_core - 3), 2);
1499 }
1500 }
1501 bits.Write(d.v1.b_presentation_filter, 1);
1502 if (d.v1.b_presentation_filter == 1) {
1503 bits.Write(d.v1.b_enable_presentation, 1);
1504 // Encoders implemented according to the present document shall write the value 0
1505 d.v1.n_filter_bytes = 0;
1506 bits.Write(d.v1.n_filter_bytes, 8);
1507 //TODO: filter_data if n_filter_bytes > 0
1508 }
1509
1510 if (d.v1.presentation_config_v1 == 0x1f){
1511 d.v1.substream_groups[0].WriteSubstreamGroupDsi(bits);
1512 }else {
1513 bits.Write(d.v1.b_multi_pid, 1);
1514 if (d.v1.presentation_config_v1 <= 2){
1515 d.v1.substream_groups[0].WriteSubstreamGroupDsi(bits);
1516 d.v1.substream_groups[1].WriteSubstreamGroupDsi(bits);
1517 }
1518 if (d.v1.presentation_config_v1 >= 3 && d.v1.presentation_config_v1 <= 4){
1519 d.v1.substream_groups[0].WriteSubstreamGroupDsi(bits);
1520 d.v1.substream_groups[1].WriteSubstreamGroupDsi(bits);
1521 d.v1.substream_groups[2].WriteSubstreamGroupDsi(bits);
1522 }
1523 if (d.v1.presentation_config_v1 == 5) {
1524 bits.Write(d.v1.n_substream_groups - 2, 3);
1525 for (unsigned int sg = 0; sg < d.v1.n_substream_groups; sg ++) {
1526 d.v1.substream_groups[sg].WriteSubstreamGroupDsi(bits);
1527 }
1528 }
1529 if (d.v1.presentation_config_v1 > 5) {
1530 d.v1.n_skip_bytes = 0;
1531 bits.Write(d.v1.n_skip_bytes, 7);
1532 //TODO: skip_data if n_skip_bytes > 0
1533 }
1534 }
1535
1536 // IMS shall set the b_pre_virtualized = 1
1537 if (presentation_version == 2) {
1538 d.v1.b_pre_virtualized = 1;
1539 }
1540 bits.Write(d.v1.b_pre_virtualized, 1);
1541 bits.Write(d.v1.b_add_emdf_substreams, 1);
1542 }
1543 if (d.v1.b_add_emdf_substreams == 1){
1544 bits.Write(d.v1.n_add_emdf_substreams, 7);
1545 for (unsigned int j = 0; j < d.v1.n_add_emdf_substreams; j++){
1546 bits.Write(d.v1.substream_emdf_version[j], 5);
1547 bits.Write(d.v1.substream_key_id[j], 10);
1548 }
1549 }
1550 // TODO: Not implement, can't get the informaiton from TOC, need calcuate by the muxer
1551 bits.Write(d.v1.b_presentation_bitrate_info, 1);
1552 if (d.v1.b_presentation_bitrate_info == 1) {
1553 d.v1.ac4_bitrate_dsi.WriteBitrateDsi(bits);
1554 }
1555
1556 bits.Write(d.v1.b_alternative, 1);
1557 if (d.v1.b_alternative == 1) {
1558 AP4_ByteAlign(bits);
1559 // TODO: Not implement, need the information from ac4_presentation_substream
1560 d.v1.alternative_info.WriteAlternativeInfo(bits);
1561 }
1562 AP4_ByteAlign(bits);
1563
1564 /*
1565 * TODO: Not implement, need the information from ac4_substream.
1566 * Currently just set the value to 1 according to Dolby's internal discussion.
1567 */
1568 d.v1.de_indicator = 1;
1569 bits.Write(d.v1.de_indicator, 1);
1570
1571 bits.Write(d.v1.dolby_atmos_indicator, 1);
1572 bits.Write(0, 4); //reserved bits
1573
1574 if (d.v1.presentation_id > 31) {
1575 d.v1.b_extended_presentation_id = 1;
1576 d.v1.extended_presentation_id = d.v1.presentation_id;
1577 }
1578 bits.Write(d.v1.b_extended_presentation_id, 1);
1579 if (d.v1.b_extended_presentation_id == 1) {
1580 bits.Write(d.v1.extended_presentation_id, 9);
1581 }else {
1582 bits.Write(0, 1); //reserved bit
1583 }
1584 return AP4_SUCCESS;
1585 }
1586
1587 /*----------------------------------------------------------------------
1588 | AP4_Dac4Atom::Ac4Dsi::PresentationV1::ParsePresentationVersion
1589 +---------------------------------------------------------------------*/
1590 AP4_Result
ParsePresentationVersion(AP4_BitReader & bits,unsigned int bitstream_version)1591 AP4_Dac4Atom::Ac4Dsi::PresentationV1::ParsePresentationVersion(AP4_BitReader& bits, unsigned int bitstream_version)
1592 {
1593 presentation_version = 0;
1594 if (bitstream_version != 1){
1595 while(bits.ReadBit() == 1){
1596 presentation_version ++;
1597 }
1598 }
1599 return AP4_SUCCESS;
1600 }
1601
1602 /*----------------------------------------------------------------------
1603 | AP4_Dac4Atom::Ac4Dsi::PresentationV1::ParsePresentationConfigExtInfo
1604 +---------------------------------------------------------------------*/
1605 AP4_Result
ParsePresentationConfigExtInfo(AP4_BitReader & bits,unsigned int bitstream_version)1606 AP4_Dac4Atom::Ac4Dsi::PresentationV1::ParsePresentationConfigExtInfo(AP4_BitReader &bits, unsigned int bitstream_version)
1607 {
1608 unsigned int nSkipBytes = bits.ReadBits(5);
1609 if (bits.ReadBit()) { // b_more_skip_bytes
1610 nSkipBytes += (AP4_Ac4VariableBits(bits, 2) << 5);
1611 }
1612 if (bitstream_version == 1 && d.v1.presentation_config_v1 == 7) {
1613 // TODO: refer to chapte 6.2.1.5 - TS 103 190-2
1614 }
1615 bits.ReadBits(nSkipBytes * 8);
1616 return AP4_SUCCESS;
1617 }
1618
1619 /*----------------------------------------------------------------------
1620 | AP4_Dac4Atom::Ac4Dsi::PresentationV1::ParseAc4SgiSpecifier
1621 +---------------------------------------------------------------------*/
1622 AP4_UI32
ParseAc4SgiSpecifier(AP4_BitReader & bits,unsigned int bitstream_version)1623 AP4_Dac4Atom::Ac4Dsi::PresentationV1::ParseAc4SgiSpecifier(AP4_BitReader &bits, unsigned int bitstream_version)
1624 {
1625 if (bitstream_version == 1) {
1626 // Error
1627 return 0;
1628 } else{
1629 unsigned int groupIndex = bits.ReadBits(3);
1630 if (groupIndex == 7) {
1631 groupIndex += AP4_Ac4VariableBits(bits, 2);
1632 }
1633 return groupIndex;
1634 }
1635 }
1636
1637 /*----------------------------------------------------------------------
1638 | AP4_Dac4Atom::Ac4Dsi::PresentationV1::ParseDSIFrameRateMultiplyInfo
1639 +---------------------------------------------------------------------*/
1640 AP4_Result
ParseDSIFrameRateMultiplyInfo(AP4_BitReader & bits,unsigned int frame_rate_idx)1641 AP4_Dac4Atom::Ac4Dsi::PresentationV1::ParseDSIFrameRateMultiplyInfo(AP4_BitReader &bits, unsigned int frame_rate_idx)
1642 {
1643 switch (frame_rate_idx) {
1644 case 2:
1645 case 3:
1646 case 4:
1647 if (bits.ReadBit()) { // b_multiplier
1648 unsigned int multiplier_bit = bits.ReadBit(); //multiplier_bit
1649 d.v1.dsi_frame_rate_multiply_info = (multiplier_bit == 0)? 1: 2;
1650 }
1651 else {
1652 d.v1.dsi_frame_rate_multiply_info = 0;
1653 }
1654 break;
1655 case 0:
1656 case 1:
1657 case 7:
1658 case 8:
1659 case 9:
1660 if (bits.ReadBit()) {
1661 d.v1.dsi_frame_rate_multiply_info = 1;
1662 }else {
1663 d.v1.dsi_frame_rate_multiply_info = 0;
1664 }
1665 break;
1666 default:
1667 d.v1.dsi_frame_rate_multiply_info = 0;
1668 break;
1669 }
1670 return AP4_SUCCESS;
1671 }
1672
1673
1674 /*----------------------------------------------------------------------
1675 | AP4_Dac4Atom::Ac4Dsi::PresentationV1::ParseDSIFrameRateFractionsInfo
1676 +---------------------------------------------------------------------*/
1677 AP4_Result
ParseDSIFrameRateFractionsInfo(AP4_BitReader & bits,unsigned int frame_rate_idx)1678 AP4_Dac4Atom::Ac4Dsi::PresentationV1::ParseDSIFrameRateFractionsInfo(AP4_BitReader &bits, unsigned int frame_rate_idx)
1679 {
1680 if (frame_rate_idx >= 5 && frame_rate_idx <= 9) {
1681 if (bits.ReadBit() == 1) { // b_frame_rate_fraction
1682 d.v1.dsi_frame_rate_fraction_info = 1;
1683 }else{
1684 d.v1.dsi_frame_rate_fraction_info = 0;
1685 }
1686 }else if (frame_rate_idx >= 10 && frame_rate_idx <= 12){
1687 if (bits.ReadBit() == 1) { // b_frame_rate_fraction
1688 if (bits.ReadBit() == 1) { // b_frame_rate_fraction_is_4
1689 d.v1.dsi_frame_rate_fraction_info = 2;
1690 } else {
1691 d.v1.dsi_frame_rate_fraction_info = 1;
1692 }
1693
1694 }else{
1695 d.v1.dsi_frame_rate_fraction_info = 0;
1696 }
1697 }
1698 return AP4_SUCCESS;
1699 }
1700
1701 /*----------------------------------------------------------------------
1702 | AP4_Dac4Atom::Ac4Dsi::PresentationV1::ParseEmdInfo
1703 +---------------------------------------------------------------------*/
1704 AP4_Result
ParseEmdInfo(AP4_BitReader & bits,AP4_Ac4EmdfInfo & emdf_info)1705 AP4_Dac4Atom::Ac4Dsi::PresentationV1::ParseEmdInfo(AP4_BitReader &bits, AP4_Ac4EmdfInfo &emdf_info)
1706 {
1707 emdf_info.emdf_version = bits.ReadBits(2);
1708 if (emdf_info.emdf_version == 3) {
1709 emdf_info.emdf_version += AP4_Ac4VariableBits(bits, 2);
1710 }
1711 emdf_info.key_id = bits.ReadBits(3);
1712 if (emdf_info.key_id == 7) {
1713 emdf_info.key_id += AP4_Ac4VariableBits(bits, 3);
1714 }
1715 emdf_info.b_emdf_payloads_substream_info = bits.ReadBit();
1716 if (emdf_info.b_emdf_payloads_substream_info == 1) {
1717 // emdf_payloads_substream_info ()
1718 if (bits.ReadBits(2) == 3) { // substream_index
1719 AP4_Ac4VariableBits(bits, 2);
1720 }
1721 }
1722 emdf_info.protectionLengthPrimary = bits.ReadBits(2);
1723 emdf_info.protectionLengthSecondary = bits.ReadBits(2);
1724 // protection_bits_primary
1725 switch (emdf_info.protectionLengthPrimary) {
1726 case 1:
1727 emdf_info.protection_bits_primary[0] = bits.ReadBits(8);
1728 break;
1729 case 2:
1730 for (unsigned idx = 0; idx < 4; idx ++) { emdf_info.protection_bits_primary[idx] = bits.ReadBits(8); }
1731 break;
1732 case 3:
1733 for (unsigned idx = 0; idx < 16; idx ++) { emdf_info.protection_bits_primary[idx] = bits.ReadBits(8); }
1734 break;
1735 default:
1736 // Error
1737 break;
1738 }
1739 // protection_bits_secondary
1740 switch (emdf_info.protectionLengthSecondary) {
1741 case 0:
1742 break;
1743 case 1:
1744 emdf_info.protection_bits_Secondary[0] = bits.ReadBits(8);
1745 break;
1746 case 2:
1747 for (unsigned idx = 0; idx < 4; idx ++) { emdf_info.protection_bits_Secondary[idx] = bits.ReadBits(8); }
1748 break;
1749 case 3:
1750 for (unsigned idx = 0; idx < 16; idx ++) { emdf_info.protection_bits_Secondary[idx] = bits.ReadBits(8); }
1751 break;
1752 default:
1753 // TODO: Error
1754 break;
1755 }
1756 return AP4_SUCCESS;
1757 }
1758
1759 /*----------------------------------------------------------------------
1760 | AP4_Dac4Atom::Ac4Dsi::PresentationV1::ParsePresentationSubstreamInfo
1761 +---------------------------------------------------------------------*/
1762 AP4_Result
ParsePresentationSubstreamInfo(AP4_BitReader & bits)1763 AP4_Dac4Atom::Ac4Dsi::PresentationV1::ParsePresentationSubstreamInfo(AP4_BitReader &bits)
1764 {
1765 d.v1.b_alternative = bits.ReadBit();
1766 /* unsigned int b_pres_ndot = */ bits.ReadBit(); // b_pres_ndot;
1767 unsigned int substream_index = bits.ReadBits(2); //substream_index
1768 if (substream_index == 3){
1769 AP4_Ac4VariableBits(bits, 2);
1770 }
1771 return AP4_SUCCESS;
1772 }
1773
1774 /*----------------------------------------------------------------------
1775 | AP4_Dac4Atom::Ac4Dsi::PresentationV1::GetPresentationChMode
1776 +---------------------------------------------------------------------*/
1777 AP4_Result
GetPresentationChMode()1778 AP4_Dac4Atom::Ac4Dsi::PresentationV1::GetPresentationChMode()
1779 {
1780 int pres_ch_mode = -1;
1781 char b_obj_or_ajoc = 0;
1782 // TODO: n_substream_groups
1783 for (unsigned int sg = 0; sg < d.v1.n_substream_groups; sg++){
1784 AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1 &substream_group = d.v1.substream_groups[sg];
1785 unsigned int n_substreams = d.v1.substream_groups[sg].d.v1.n_substreams;
1786 for (unsigned int sus = 0; sus < n_substreams; sus++){
1787 AP4_Dac4Atom::Ac4Dsi::SubStream &substream = substream_group.d.v1.substreams[sus];
1788 if (substream_group.d.v1.b_channel_coded){
1789 pres_ch_mode = AP4_Ac4SuperSet(pres_ch_mode, substream.ch_mode);
1790 }else {
1791 b_obj_or_ajoc = 1;
1792 }
1793 }
1794 }
1795 if (b_obj_or_ajoc == 1) { pres_ch_mode = -1; }
1796 return pres_ch_mode;
1797 }
1798
1799 /*----------------------------------------------------------------------
1800 | AP4_Dac4Atom::Ac4Dsi::PresentationV1::GetPresentationChannelMask
1801 +---------------------------------------------------------------------*/
1802 AP4_Result
GetPresentationChannelMask()1803 AP4_Dac4Atom::Ac4Dsi::PresentationV1::GetPresentationChannelMask()
1804 {
1805 unsigned int channel_mask = 0;
1806 char b_obj_or_ajoc = 0;
1807 // TODO: n_substream_groups
1808 for (unsigned int sg = 0; sg < d.v1.n_substream_groups; sg ++){
1809 AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1 &substream_group = d.v1.substream_groups[sg];
1810 unsigned int n_substreams = d.v1.substream_groups[sg].d.v1.n_substreams;
1811 for (unsigned int sus = 0; sus < n_substreams; sus ++){
1812 AP4_Dac4Atom::Ac4Dsi::SubStream &substream = substream_group.d.v1.substreams[sus];
1813 if (substream_group.d.v1.b_channel_coded){
1814 channel_mask |= substream.dsi_substream_channel_mask;
1815 }else {
1816 b_obj_or_ajoc = 1;
1817 }
1818 }
1819 }
1820 //Modify the mask for headphone presentation with b_pre_virtualized = 1
1821 /*
1822 if (presentation_version == 2 || d.v1.b_pre_virtualized == 1){
1823 if (channel_mask == 0x03) { channel_mask = 0x01;}
1824 }
1825 */
1826 // TODO: temporary solution according to Dolby's internal discussion
1827 if (channel_mask == 0x03) { channel_mask = 0x01;}
1828
1829 // If one substream contains Tfl, Tfr, Tbl, Tbr, Tl and Tr shall be removed.
1830 if ((channel_mask & 0x30) && (channel_mask & 0x80)) { channel_mask &= ~0x80;}
1831
1832 // objective channel mask
1833 if (b_obj_or_ajoc == 1) { channel_mask = 0x800000; }
1834 return channel_mask;
1835 }
1836
1837 /*----------------------------------------------------------------------
1838 | AP4_Dac4Atom::Ac4Dsi::PresentationV1::GetPresB4BackChannelsPresent
1839 +---------------------------------------------------------------------*/
1840 AP4_Result
GetPresB4BackChannelsPresent()1841 AP4_Dac4Atom::Ac4Dsi::PresentationV1::GetPresB4BackChannelsPresent()
1842 {
1843 for (unsigned int sg = 0; sg < d.v1.n_substream_groups; sg ++){
1844 AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1 &substream_group = d.v1.substream_groups[sg];
1845 for (unsigned int sus = 0; sus < substream_group.d.v1.n_substreams; sus ++){
1846 d.v1.pres_b_4_back_channels_present |= substream_group.d.v1.substreams[sus].b_4_back_channels_present;
1847 }
1848 }
1849 return AP4_SUCCESS;
1850 }
1851
1852 /*----------------------------------------------------------------------
1853 | AP4_Dac4Atom::Ac4Dsi::PresentationV1::GetPresTopChannelPairs
1854 +---------------------------------------------------------------------*/
1855 AP4_Result
GetPresTopChannelPairs()1856 AP4_Dac4Atom::Ac4Dsi::PresentationV1::GetPresTopChannelPairs()
1857 {
1858 unsigned char tmp_pres_top_channel_pairs = 0;
1859 for (unsigned int sg = 0; sg < d.v1.n_substream_groups; sg ++){
1860 AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1 &substream_group = d.v1.substream_groups[sg];
1861 for (unsigned int sus = 0; sus < substream_group.d.v1.n_substreams; sus ++){
1862 if (tmp_pres_top_channel_pairs < substream_group.d.v1.substreams[sus].top_channels_present) {
1863 tmp_pres_top_channel_pairs = substream_group.d.v1.substreams[sus].top_channels_present;
1864 }
1865 }
1866 }
1867 switch (tmp_pres_top_channel_pairs){
1868 case 0:
1869 d.v1.pres_top_channel_pairs = 0; break;
1870 case 1:
1871 case 2:
1872 d.v1.pres_top_channel_pairs = 1; break;
1873 case 3:
1874 d.v1.pres_top_channel_pairs = 2; break;
1875 default:
1876 d.v1.pres_top_channel_pairs = 0; break;
1877 }
1878 return AP4_SUCCESS;
1879 }
1880
1881
1882 /*----------------------------------------------------------------------
1883 | AP4_Dac4Atom::Ac4Dsi::PresentationV1::GetBPresentationCoreDiffers
1884 +---------------------------------------------------------------------*/
1885 AP4_Result
GetBPresentationCoreDiffers()1886 AP4_Dac4Atom::Ac4Dsi::PresentationV1::GetBPresentationCoreDiffers()
1887 {
1888 int pres_ch_mode_core = -1;
1889 char b_obj_or_ajoc_adaptive = 0;
1890 for (unsigned int sg = 0; sg < d.v1.n_substream_groups; sg ++){
1891 AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1 &substream_group = d.v1.substream_groups[sg];
1892 unsigned int n_substreams = d.v1.substream_groups[sg].d.v1.n_substreams;
1893 for (unsigned int sus = 0; sus < n_substreams; sus ++){
1894 AP4_Dac4Atom::Ac4Dsi::SubStream &substream = substream_group.d.v1.substreams[sus];
1895 if (substream_group.d.v1.b_channel_coded){
1896 pres_ch_mode_core = AP4_Ac4SuperSet(pres_ch_mode_core, substream.GetChModeCore(substream_group.d.v1.b_channel_coded));
1897 }else {
1898 if (substream.b_ajoc){
1899 if (substream.b_static_dmx){
1900 pres_ch_mode_core = AP4_Ac4SuperSet(pres_ch_mode_core, substream.GetChModeCore(substream_group.d.v1.b_channel_coded));
1901 }else{
1902 b_obj_or_ajoc_adaptive = 1;
1903 }
1904 }else{
1905 b_obj_or_ajoc_adaptive = 1;
1906 }
1907 }
1908 }
1909 }
1910 if (b_obj_or_ajoc_adaptive) {
1911 pres_ch_mode_core = -1;
1912 }
1913 if (pres_ch_mode_core == GetPresentationChMode()) {
1914 pres_ch_mode_core = -1;
1915 }
1916 return pres_ch_mode_core;
1917 }
1918