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