1 /*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
2  *
3  *  Use of this source code is governed by a BSD-style license that can
4  *  be found in the License.html file in the root of the source tree.
5  */
6 
7 //---------------------------------------------------------------------------
8 // Pre-compilation
9 #include "MediaInfo/PreComp.h"
10 #ifdef __BORLANDC__
11     #pragma hdrstop
12 #endif
13 //---------------------------------------------------------------------------
14 
15 //---------------------------------------------------------------------------
16 #include "MediaInfo/Setup.h"
17 //---------------------------------------------------------------------------
18 
19 //---------------------------------------------------------------------------
20 #if defined(MEDIAINFO_MPEGH3DA_YES)
21 //---------------------------------------------------------------------------
22 
23 //---------------------------------------------------------------------------
24 #include "MediaInfo/Audio/File_Mpegh3da.h"
25 #include "MediaInfo/MediaInfo_Config_MediaInfo.h"
26 #include <cmath>
27 
28 using namespace ZenLib;
29 using namespace std;
30 //---------------------------------------------------------------------------
31 
32 namespace MediaInfoLib
33 {
34 
35 //***************************************************************************
36 // Info
37 //***************************************************************************
38 
39 extern const size_t Aac_sampling_frequency_Size_Usac; // USAC expands Aac_sampling_frequency[]
40 extern const int32u Aac_sampling_frequency[];
41 struct coreSbrFrameLengthIndex_mapping
42 {
43     int8u    sbrRatioIndex;
44     int8u    outputFrameLengthDivided256;
45 };
46 extern const size_t coreSbrFrameLengthIndex_Mapping_Size;
47 extern coreSbrFrameLengthIndex_mapping coreSbrFrameLengthIndex_Mapping[];
48 extern int8u Aac_Channels_Get(int8u ChannelLayout);
49 extern string Aac_Channels_GetString(int8u ChannelLayout);
50 extern string Aac_ChannelConfiguration_GetString(int8u ChannelLayout);
51 extern string Aac_ChannelConfiguration2_GetString(int8u ChannelLayout);
52 extern string Aac_ChannelLayout_GetString(const Aac_OutputChannel* const OutputChannels, size_t OutputChannels_Size);
53 extern string Aac_ChannelLayout_GetString(int8u ChannelLayout, bool IsMpegh3da=false);
54 extern string Aac_ChannelLayout_GetString(const vector<Aac_OutputChannel>& OutputChannels);
55 extern string Aac_ChannelMode_GetString(int8u ChannelLayout, bool IsMpegh3da=false);
56 extern string Aac_ChannelMode_GetString(const vector<Aac_OutputChannel>& OutputChannels);
57 extern string Aac_OutputChannelPosition_GetString(int8u OutputChannelPosition);
58 
59 //---------------------------------------------------------------------------
60 static const char* const Mpegh3da_Profile[]=
61 {
62     "Main",
63     "High",
64     "LC",
65     "BL",
66 };
67 static size_t Mpegh3da_Profile_Size=sizeof(Mpegh3da_Profile)/sizeof(const char* const);
Mpegh3da_Profile_Get(int8u mpegh3daProfileLevelIndication)68 extern string Mpegh3da_Profile_Get(int8u mpegh3daProfileLevelIndication)
69 {
70     if (!mpegh3daProfileLevelIndication)
71         return string();
72     if (mpegh3daProfileLevelIndication>=5*Mpegh3da_Profile_Size)
73         return Ztring::ToZtring(mpegh3daProfileLevelIndication).To_UTF8(); // Raw value
74     return string(Mpegh3da_Profile[(mpegh3daProfileLevelIndication-1)/5])+"@L"+char('1'+((mpegh3daProfileLevelIndication-1)%5));
75 }
76 
77 //---------------------------------------------------------------------------
78 static const char* const Mpegh3da_MHASPacketType[]=
79 {
80     "FILLDATA",
81     "MPEGH3DACFG",
82     "MPEGH3DAFRAME",
83     "AUDIOSCENEINFO",
84     "",
85     "",
86     "SYNC",
87     "SYNCGAP",
88     "MARKER",
89     "CRC16",
90     "CRC32",
91     "DESCRIPTOR",
92     "USERINTERACTION",
93     "LOUDNESS_DRC",
94     "BUFFERINFO",
95     "GLOBAL_CRC16",
96     "GLOBAL_CRC32",
97     "AUDIOTRUNCATION",
98     "GENDATA",
99 };
100 static const size_t Mpegh3da_MHASPacketType_Size=sizeof(Mpegh3da_MHASPacketType)/sizeof(const char* const);
101 
102 //---------------------------------------------------------------------------
103 static const char* const Mpegh3da_contentKind[]=
104 {
105     "",
106     "Complete Main",
107     "Dialogue",
108     "Music",
109     "Effect",
110     "Mixed",
111     "LFE",
112     "Voiceover",
113     "Spoken Subtitle",
114     "Visually Impaired or Audio Description",
115     "Commentary",
116     "Hearing Impaired",
117     "Emergency",
118 };
119 static const size_t Mpegh3da_contentKind_Size=sizeof(Mpegh3da_contentKind)/sizeof(const char* const);
120 
121 //---------------------------------------------------------------------------
122 static const char* const Mpegh3da_groupPresetKind[]=
123 {
124     "",
125     "Integrated TV Loudspeaker",
126     "High Quality Loudspeaker",
127     "Mobile Loudspeakers",
128     "Mobile Headphones",
129     "Hearing Impaired (light)",
130     "Hearing Impaired (heavy)",
131     "Visually Impaired or Audio Description",
132     "Spoken Subtitles",
133     "Loudness or DRC",
134 };
135 static const size_t Mpegh3da_groupPresetKind_Size=sizeof(Mpegh3da_groupPresetKind)/sizeof(const char* const);
136 
137 //---------------------------------------------------------------------------
138 static const char* const Mpegh3da_signalGroupType[]=
139 {
140     "Channels",
141     "Object",
142     "SAOC",
143     "HOA",
144 };
145 static const size_t Mpegh3da_signalGroupType_Size=sizeof(Mpegh3da_signalGroupType)/sizeof(const char* const);
146 
147 //---------------------------------------------------------------------------
148 static const char* const Mpegh3da_marker_byte[]=
149 {
150     "",
151     "Configuration change marker",
152     "Random access or Immediate playout marker",
153     "Program boundary marker",
154 };
155 static const size_t Mpegh3da_marker_byte_Size=sizeof(Mpegh3da_marker_byte)/sizeof(const char* const);
156 
157 //---------------------------------------------------------------------------
158 static const char* const Mpegh3da_usacElementType[4]=
159 {
160     "SCE",
161     "CPE",
162     "LFE",
163     "EXT",
164 };
165 
166 //---------------------------------------------------------------------------
167 static const char* const Mpegh3da_usacExtElementType[]=
168 {
169     "FILL",
170     "MPEGS",
171     "SAOC",
172     "AUDIOPREROLL",
173     "UNI_DRC",
174     "OBJ_METADATA",
175     "SAOC_3D",
176     "HOA",
177     "FMT_CNVRTR",
178     "MCT",
179     "TCC",
180     "HOA_ENH_LAYER",
181     "HREP",
182     "ENHANCED_OBJ_METADATA",
183 };
184 static const size_t Mpegh3da_usacExtElementType_Size=sizeof(Mpegh3da_usacExtElementType)/sizeof(const char* const);
185 
186 //---------------------------------------------------------------------------
187 static const char* const Mpegh3da_usacConfigExtType[]=
188 {
189     "FILL",
190     "DOWNMIX",
191     "LOUDNESS_INFO",
192     "AUDIOSCENE_INFO",
193     "HOA_MATRIX",
194     "ICG",
195     "SIG_GROUP_INFO",
196     "COMPATIBLE_PROFILE_LEVEL_SET",
197 };
198 static const size_t Mpegh3da_usacConfigExtType_Size=sizeof(Mpegh3da_usacConfigExtType)/sizeof(const char* const);
199 
200 //---------------------------------------------------------------------------
201 static const size_t Mpegh3da_SpeakerInfo_Size=43;
202 static const speaker_info Mpegh3da_SpeakerInfo[Mpegh3da_SpeakerInfo_Size]=
203 {
204     {CH_M_L030,  30, false,  0, false, false},
205     {CH_M_R030,  30, true ,  0, false, false},
206     {CH_M_000 ,   0, false,  0, false, false},
207     {CH_LFE   ,   0, false, 15, true ,  true},
208     {CH_M_L110, 110, false,  0, false, false},
209     {CH_M_R110, 110, true ,  0, false, false},
210     {CH_M_L022,  22, false,  0, false, false},
211     {CH_M_R022,  22, true ,  0, false, false},
212     {CH_M_L135, 135, false,  0, false, false},
213     {CH_M_R135, 135, true ,  0, false, false},
214     {CH_M_180 , 180, false,  0, false, false},
215     {CH_M_LSD , 135, false,  0, false, false},
216     {CH_M_RSD , 135, true ,  0, false, false},
217     {CH_M_L090,  90, false,  0, false, false},
218     {CH_M_R090,  90, true ,  0, false, false},
219     {CH_M_L060,  60, false,  0, false, false},
220     {CH_M_R060,  60, true ,  0, false, false},
221     {CH_U_L030,  30, false, 35, false, false},
222     {CH_U_R030,  30, true , 35, false, false},
223     {CH_U_000 ,   0, false, 35, false, false},
224     {CH_U_L135, 135, false, 35, false, false},
225     {CH_U_R135, 135, true , 35, false, false},
226     {CH_U_180 , 180, false, 35, false, false},
227     {CH_U_L090,  90, false, 35, false, false},
228     {CH_U_R090,  90, true , 35, false, false},
229     {CH_T_000 ,   0, false, 90, false, false},
230     {CH_LFE2  ,  45, false, 15, true ,  true},
231     {CH_L_L045,  45, false, 15, true , false},
232     {CH_L_R045,  45, true , 15, true , false},
233     {CH_L_000 ,   0, false, 15, true , false},
234     {CH_U_L110, 110, false, 35, false, false},
235     {CH_U_R110, 110, true , 35, false, false},
236     {CH_U_L045,  45, false, 35, false, false},
237     {CH_U_R045,  45, true , 35, false, false},
238     {CH_M_L045,  45, false,  0, false, false},
239     {CH_M_R045,  45, true ,  0, false, false},
240     {CH_LFE3  ,  45, true , 15, true ,  true},
241     {CH_M_LSCR,   2, false,  0, false, false},
242     {CH_M_RSCR,   2, true ,  0, false, false},
243     {CH_M_LSCH,   1, false,  0, false, false},
244     {CH_M_RSCH,   1, true ,  0, false, false},
245     {CH_M_L150, 150, false,  0, false, false},
246     {CH_M_R150, 150, true ,  0, false, false},
247 };
248 
249 //***************************************************************************
250 // Constructor/Destructor
251 //***************************************************************************
252 
253 //---------------------------------------------------------------------------
File_Mpegh3da()254 File_Mpegh3da::File_Mpegh3da()
255 :File_Usac()
256 {
257     //Configuration
258     #if MEDIAINFO_TRACE
259         Trace_Layers_Update(8); //Stream
260     #endif //MEDIAINFO_TRACE
261 
262     //In
263     MustParse_mhaC=false;
264     MustParse_mpegh3daFrame=false;
265 
266     //Temp
267     audioSceneInfoID=0;
268     isMainStream=(int8u)-1;
269 }
270 
271 //***************************************************************************
272 // Streams management
273 //***************************************************************************
274 
275 //---------------------------------------------------------------------------
Streams_Fill()276 void File_Mpegh3da::Streams_Fill()
277 {
278     Stream_Prepare(Stream_Audio);
279     Fill(Stream_Audio, 0, Audio_Format, "MPEG-H 3D Audio");
280     string Format_Profile=Mpegh3da_Profile_Get(mpegh3daProfileLevelIndication);
281     for (size_t Pos=0; Pos<mpegh3daCompatibleProfileLevelSet.size(); Pos++)
282     {
283         Format_Profile+=", ";
284         Format_Profile+=Mpegh3da_Profile_Get(mpegh3daCompatibleProfileLevelSet[Pos]);
285     }
286     Fill(Stream_Audio, 0, Audio_Format_Profile, Format_Profile);
287     Fill(Stream_Audio, 0, Audio_SamplingRate, usacSamplingFrequency);
288     Fill(Stream_Audio, 0, Audio_SamplesPerFrame, coreSbrFrameLengthIndex_Mapping[coreSbrFrameLengthIndex].outputFrameLengthDivided256<<8);
289     if (isMainStream!=(int8u)-1)
290         Fill(Stream_Audio, 0, "Type", isMainStream?"Main":"Auxiliary");
291     Fill_SetOptions(Stream_Audio, 0, "Type", "N NTY");
292     for (set<int32u>::iterator Label=MHASPacketLabels.begin(); Label!=MHASPacketLabels.end(); ++Label)
293         Fill(Stream_Audio, 0, "Label", *Label);
294     Fill_SetOptions(Stream_Audio, 0, "Label", "N NTY");
295     Ztring LabelString=Retrieve(Stream_Audio, 0, "Label");
296     const Ztring& Type=Retrieve_Const(Stream_Audio, 0, "Type");
297     if (!LabelString.empty() && !Type.empty())
298     {
299         if (!LabelString.empty())
300             LabelString+=__T(' ');
301         LabelString+=__T('(')+Type+__T(')');
302     }
303     if (LabelString.empty())
304         Fill(Stream_Audio, 0, "Label/String", LabelString);
305     Fill_SetOptions(Stream_Audio, 0, "Label/String", "Y NTN");
306     if (audioSceneInfoID)
307         Fill(Stream_Audio, 0, "AudioSceneInfoID", audioSceneInfoID);
308     Streams_Fill_ChannelLayout(string(), referenceLayout);
309     if (!GroupPresets.empty())
310     {
311         Fill(Stream_Audio, 0, "GroupPresetCount", GroupPresets.size());
312         Fill_SetOptions(Stream_Audio, 0, "GroupPresetCount", "N NIY");
313     }
314     if (!SwitchGroups.empty())
315     {
316         Fill(Stream_Audio, 0, "SwitchGroupCount", SwitchGroups.size());
317         Fill_SetOptions(Stream_Audio, 0, "SwitchGroupCount", "N NIY");
318     }
319     if (!Groups.empty())
320     {
321         Fill(Stream_Audio, 0, "GroupCount", Groups.size());
322         Fill_SetOptions(Stream_Audio, 0, "GroupCount", "N NIY");
323     }
324     if (!SignalGroups.empty())
325     {
326         Fill(Stream_Audio, 0, "SignalGroupCount", SignalGroups.size());
327         Fill_SetOptions(Stream_Audio, 0, "SignalGroupCount", "N NIY");
328     }
329 
330     // Filling
331     if (!Mpegh3da_drcInstructionsUniDrc_Data[0].empty())
332     {
333         drcInstructionsUniDrc_Data=Mpegh3da_drcInstructionsUniDrc_Data[0].begin()->second;
334         Fill_DRC();
335         drcInstructionsUniDrc_Data.clear();
336     }
337     /*
338     if (!Mpegh3da_loudnessInfo_Data[0].empty() && !GroupPresets.empty())
339     {
340         int8u ID=(int8u)-1;
341         for (size_t i=0; i<GroupPresets.size(); i++)
342         {
343             const group_preset& P=GroupPresets[i];
344             if (P.ID<ID)
345                 ID=P.ID;
346             if (Mpegh3da_loudnessInfo_Data[3][ID].Data[0].empty())
347             {
348                 Mpegh3da_loudnessInfo_Data[3][ID].Data[0]=Mpegh3da_loudnessInfo_Data[0].begin()->second.Data[0];
349                 Mpegh3da_loudnessInfo_Data[0].begin()->second.Data[0].clear();
350             }
351         }
352     }
353     */
354     bool NoLoudnesConch;
355     if (!Mpegh3da_loudnessInfo_Data[0].empty())
356     {
357         loudnessInfo_Data[0]=Mpegh3da_loudnessInfo_Data[0].begin()->second.Data[0];
358         loudnessInfo_Data[1]=Mpegh3da_loudnessInfo_Data[0].begin()->second.Data[1];
359         loudnessInfoSet_Present=true;
360         Fill_Loudness(NULL);
361         loudnessInfo_Data[0].clear();
362         loudnessInfo_Data[1].clear();
363         NoLoudnesConch=true;
364     }
365     else
366         NoLoudnesConch=false;
367 
368     for (size_t i=0; i<GroupPresets.size(); i++)
369     {
370         const group_preset& P=GroupPresets[i];
371 
372         string Summary;
373         if (!P.Description.empty())
374             Summary+=P.Description.begin()->second;
375         if (Summary.empty())
376             Summary="Yes";
377 
378         string p=string("GroupPreset")+Ztring::ToZtring(i).To_UTF8();
379         Fill(Stream_Audio, 0, p.c_str(), Summary);
380         Fill(Stream_Audio, 0, (p+" Pos").c_str(), i);
381         Fill_SetOptions(Stream_Audio, 0, (p+" Pos").c_str(), "N NIY");
382         Fill(Stream_Audio, 0, (p+" ID").c_str(), P.ID);
383         for (map<string, string>::const_iterator Desc=P.Description.begin(); Desc!=P.Description.end(); ++Desc)
384         {
385             Ztring Language=MediaInfoLib::Config.Iso639_1_Get(Ztring().From_UTF8(Desc->first));
386             if (Language.empty())
387                 Language=Ztring().From_UTF8(Desc->first);
388             Fill(Stream_Audio, 0, (p+" Title").c_str(), '('+MediaInfoLib::Config.Language_Get_Translate(__T("Language_"), Language).To_UTF8() + ") "+Desc->second);
389         }
390         if (P.Kind<Mpegh3da_groupPresetKind_Size)
391             Fill(Stream_Audio, 0, (p+" Kind").c_str(), Mpegh3da_groupPresetKind[P.Kind]);
392         if (!Mpegh3da_drcInstructionsUniDrc_Data[3].empty())
393         {
394             std::map<int8u, std::map<int16u, drc_info> >::iterator drcInstructionsUniDrc=Mpegh3da_drcInstructionsUniDrc_Data[3].find(P.ID);
395             if (drcInstructionsUniDrc!=Mpegh3da_drcInstructionsUniDrc_Data[3].end())
396             {
397                 drcInstructionsUniDrc_Data=drcInstructionsUniDrc->second;
398                 Fill_DRC(p.c_str());
399                 drcInstructionsUniDrc_Data.clear();
400             }
401         }
402         if (!Mpegh3da_loudnessInfo_Data[3].empty())
403         {
404             std::map<int8u, loudness_info_data>::iterator Loudness=Mpegh3da_loudnessInfo_Data[3].find(P.ID);
405             if (Loudness!=Mpegh3da_loudnessInfo_Data[3].end())
406             {
407                 loudnessInfo_Data[0]=Loudness->second.Data[0];
408                 loudnessInfoSet_Present=true;
409                 Fill_Loudness(p.c_str(), NoLoudnesConch);
410                 loudnessInfo_Data[0].clear();
411             }
412         }
413         /* Disabled for the moment, need more details about how to show it
414         ZtringList IDs;
415         if (P.Conditions.size()==1 && P.Conditions[0].ReferenceID==127 && !P.Conditions[0].ConditionOnOff)
416         {
417             Fill(Stream_Audio, 0, (p+" LinkedTo_Group_Pos").c_str(), "Full user interactivity");
418             Fill_SetOptions(Stream_Audio, 0, (p+" LinkedTo_Group_Pos").c_str(), "N NTY");
419             Fill(Stream_Audio, 0, (p+" LinkedTo_Group_Pos/String").c_str(), "Full user interactivity");
420             Fill_SetOptions(Stream_Audio, 0, (p+" LinkedTo_Group_Pos/String").c_str(), "Y NTN");
421         }
422         else
423         {
424             ZtringList GroupPos, GroupNum;
425             for (size_t i=0; i<P.Conditions.size(); i++)
426             {
427                 for (size_t j=0; j<Groups.size(); j++)
428                     if (Groups[j].ID==P.Conditions[i].ReferenceID)
429                     {
430                         GroupPos.push_back(Ztring::ToZtring(j));
431                         GroupNum.push_back(Ztring::ToZtring(j+1));
432                     }
433             }
434             GroupPos.Separator_Set(0, __T(" + "));
435             Fill(Stream_Audio, 0, (p+" LinkedTo_Group_Pos").c_str(), GroupPos.Read());
436             Fill_SetOptions(Stream_Audio, 0, (p+" LinkedTo_Group_Pos").c_str(), "N NTY");
437             GroupNum.Separator_Set(0, __T(" + "));
438             Fill(Stream_Audio, 0, (p+" LinkedTo_Group_Pos/String").c_str(), GroupNum.Read());
439             Fill_SetOptions(Stream_Audio, 0, (p+" LinkedTo_Group_Pos/String").c_str(), "Y NTN");
440         }
441         */
442     }
443 
444     for (size_t i=0; i<SwitchGroups.size(); i++)
445     {
446         const switch_group& S=SwitchGroups[i];
447 
448         string Summary;
449         if (!S.Description.empty())
450             Summary+=S.Description.begin()->second;
451         if (Summary.empty())
452             Summary="Yes";
453 
454         string s=string("SwitchGroup")+Ztring::ToZtring(i).To_UTF8();
455         Fill(Stream_Audio, 0, s.c_str(), Summary);
456         Fill(Stream_Audio, 0, (s+" Pos").c_str(), i);
457         Fill_SetOptions(Stream_Audio, 0, (s+" Pos").c_str(), "N NIY");
458         Fill(Stream_Audio, 0, (s+" ID").c_str(), S.ID);
459         for (map<string, string>::const_iterator Desc=S.Description.begin(); Desc!=S.Description.end(); ++Desc)
460         {
461             Ztring Language=MediaInfoLib::Config.Iso639_1_Get(Ztring().From_UTF8(Desc->first));
462             if (Language.empty())
463                 Language=Ztring().From_UTF8(Desc->first);
464             Fill(Stream_Audio, 0, (s+" Title").c_str(), '('+MediaInfoLib::Config.Language_Get_Translate(__T("Language_"), Language).To_UTF8() + ") "+Desc->second);
465         }
466         Fill(Stream_Audio, 0, (s+" Allow").c_str(), S.allowOnOff?"Yes":"No");
467         if (S.allowOnOff)
468             Fill(Stream_Audio, 0, (s+" Default").c_str(), S.defaultOnOff?"Yes":"No");
469         Fill(Stream_Audio, 0, (s+" DefaultGroupID").c_str(), S.DefaultGroupID);
470 
471         ZtringList GroupPos, GroupNum;
472         for (size_t i=0; i<S.MemberID.size(); i++)
473         {
474             for (size_t j=0; j<Groups.size(); j++)
475                 if (Groups[j].ID==S.MemberID[i])
476                 {
477                     GroupPos.push_back(Ztring::ToZtring(j));
478                     GroupNum.push_back(Ztring::ToZtring(j+1));
479                 }
480         }
481         GroupPos.Separator_Set(0, __T(" + "));
482         Fill(Stream_Audio, 0, (s+" LinkedTo_Group_Pos").c_str(), GroupPos.Read());
483         Fill_SetOptions(Stream_Audio, 0, (s+" LinkedTo_Group_Pos").c_str(), "N NTY");
484         GroupNum.Separator_Set(0, __T(" + "));
485         Fill(Stream_Audio, 0, (s+" LinkedTo_Group_Pos/String").c_str(), GroupNum.Read());
486         Fill_SetOptions(Stream_Audio, 0, (s+" LinkedTo_Group_Pos/String").c_str(), "Y NTN");
487     }
488 
489     for (size_t i=0; i<Groups.size(); i++)
490     {
491         const group& G=Groups[i];
492 
493         string Summary;
494         if (!G.Description.empty())
495             Summary+=G.Description.begin()->second;
496         if (Summary.empty())
497             Summary="Yes";
498 
499         string g=string("Group")+Ztring::ToZtring(i).To_UTF8();
500         Fill(Stream_Audio, 0, g.c_str(), Summary);
501         Fill(Stream_Audio, 0, (g+" Pos").c_str(), i);
502         Fill_SetOptions(Stream_Audio, 0, (g+" Pos").c_str(), "N NIY");
503         Fill(Stream_Audio, 0, (g+" ID").c_str(), G.ID);
504         for (map<string, string>::const_iterator Desc=G.Description.begin(); Desc!=G.Description.end(); ++Desc)
505         {
506              Ztring Language=MediaInfoLib::Config.Iso639_1_Get(Ztring().From_UTF8(Desc->first));
507             if (Language.empty())
508                 Language=Ztring().From_UTF8(Desc->first);
509             Fill(Stream_Audio, 0, (g+" Title").c_str(), '('+MediaInfoLib::Config.Language_Get_Translate(__T("Language_"), Language).To_UTF8() + ") "+Desc->second);
510         }
511         if (!G.Language.empty())
512         {
513             Fill(Stream_Audio, 0, (g+" Language").c_str(), G.Language);
514             Fill(Stream_Audio, 0, (g+" Language/String").c_str(), MediaInfoLib::Config.Iso639_Translate(Ztring().From_UTF8(G.Language)));
515             Fill_SetOptions(Stream_Audio, 0, (g+" Language").c_str(), "N NTY");
516             Fill_SetOptions(Stream_Audio, 0, (g+" Language/String").c_str(), "Y NTN");
517         }
518         if (G.Kind<Mpegh3da_contentKind_Size)
519             Fill(Stream_Audio, 0, (g+" Kind").c_str(), Mpegh3da_contentKind[G.Kind]);
520         Fill(Stream_Audio, 0, (g+" Allow").c_str(), G.allowOnOff?"Yes":"No");
521         if (G.allowOnOff)
522             Fill(Stream_Audio, 0, (g+" Default").c_str(), G.defaultOnOff?"Yes":"No");
523         if (!Mpegh3da_drcInstructionsUniDrc_Data[1].empty())
524         {
525             std::map<int8u, std::map<int16u, drc_info> >::iterator drcInstructionsUniDrc=Mpegh3da_drcInstructionsUniDrc_Data[1].find(G.ID);
526             if (drcInstructionsUniDrc!=Mpegh3da_drcInstructionsUniDrc_Data[1].end())
527             {
528                 drcInstructionsUniDrc_Data=drcInstructionsUniDrc->second;
529                 Fill_DRC(g.c_str());
530                 drcInstructionsUniDrc_Data.clear();
531             }
532         }
533         if (!Mpegh3da_loudnessInfo_Data[1].empty())
534         {
535             std::map<int8u, loudness_info_data>::iterator Loudness=Mpegh3da_loudnessInfo_Data[1].find(G.ID);
536             if (Loudness!=Mpegh3da_loudnessInfo_Data[1].end())
537             {
538                 loudnessInfo_Data[0]=Loudness->second.Data[0];
539                 loudnessInfoSet_Present=true;
540                 Fill_Loudness(g.c_str(), NoLoudnesConch);
541                 loudnessInfo_Data[0].clear();
542             }
543         }
544         if (!Mpegh3da_drcInstructionsUniDrc_Data[2].empty()) // Not sure
545         {
546             std::map<int8u, std::map<int16u, drc_info> >::iterator drcInstructionsUniDrc=Mpegh3da_drcInstructionsUniDrc_Data[2].find(G.ID);
547             if (drcInstructionsUniDrc!=Mpegh3da_drcInstructionsUniDrc_Data[2].end())
548             {
549                 drcInstructionsUniDrc_Data=drcInstructionsUniDrc->second;
550                 Fill_DRC(g.c_str());
551                 drcInstructionsUniDrc_Data.clear();
552             }
553         }
554         if (!Mpegh3da_loudnessInfo_Data[2].empty()) // Not sure
555         {
556             std::map<int8u, loudness_info_data>::iterator Loudness=Mpegh3da_loudnessInfo_Data[2].find(G.ID);
557             if (Loudness!=Mpegh3da_loudnessInfo_Data[2].end())
558             {
559                 loudnessInfo_Data[0]=Loudness->second.Data[0];
560                 loudnessInfoSet_Present=true;
561                 Fill_Loudness(g.c_str(), NoLoudnesConch);
562                 loudnessInfo_Data[0].clear();
563             }
564         }
565 
566         ZtringList GroupPos, GroupNum;
567         for (size_t i=0; i<G.MemberID.size(); i++)
568         {
569             size_t Signal_Count=0;
570             for (size_t j=0; j<SignalGroups.size(); j++)
571             {
572                 const signal_group& E=SignalGroups[j];
573                 if (Signal_Count==G.MemberID[i])
574                 {
575                     GroupPos.push_back(Ztring::ToZtring(j));
576                     GroupNum.push_back(Ztring::ToZtring(j+1));
577                 }
578                 if (Aac_Channels_Get(E.Layout.ChannelLayout))
579                     Signal_Count+=Aac_Channels_Get(E.Layout.ChannelLayout);
580                 else if (E.Layout.numSpeakers)
581                     Signal_Count+=E.Layout.numSpeakers;
582             }
583         }
584         GroupPos.Separator_Set(0, __T(" + "));
585         Fill(Stream_Audio, 0, (g+" LinkedTo_SignalGroup_Pos").c_str(), GroupPos.Read());
586         Fill_SetOptions(Stream_Audio, 0, (g+" LinkedTo_SignalGroup_Pos").c_str(), "N NTY");
587         GroupNum.Separator_Set(0, __T(" + "));
588         Fill(Stream_Audio, 0, (g+" LinkedTo_SignalGroup_Pos/String").c_str(), GroupNum.Read());
589         Fill_SetOptions(Stream_Audio, 0, (g+" LinkedTo_SignalGroup_Pos/String").c_str(), "Y NTN");
590     }
591 
592     for (size_t i=0; i<SignalGroups.size(); i++)
593     {
594         const signal_group& E=SignalGroups[i];
595 
596         string e=string("SignalGroup")+Ztring::ToZtring(i).To_UTF8();
597         Fill(Stream_Audio, 0, e.c_str(), "Yes");
598         Fill(Stream_Audio, 0, (e+" Pos").c_str(), i);
599         Fill_SetOptions(Stream_Audio, 0, (e+" Pos").c_str(), "N NIY");
600         if (E.Type<Mpegh3da_signalGroupType_Size)
601             Fill(Stream_Audio, 0, (e+" Type").c_str(), Mpegh3da_signalGroupType[E.Type]);
602         Streams_Fill_ChannelLayout(e+' ', E.Layout, E.Type);
603 
604         string Summary;
605         switch (E.Type)
606         {
607             case 0 : //Channels
608                     Summary+=Retrieve_Const(Stream_Audio, 0, (e+" Channel(s)/String").c_str()).To_UTF8();
609                     break;
610             case 1 : // Objects
611                     Summary+=Retrieve_Const(Stream_Audio, 0, (e+" NumberOfObjects/String").c_str()).To_UTF8();
612                     break;
613             default:
614                     Summary+=Mpegh3da_signalGroupType[E.Type];
615         }
616         if (!Summary.empty())
617             Fill(Stream_Audio, 0, e.c_str(), Summary, true, true);
618     }
619 }
620 
621 //---------------------------------------------------------------------------
Streams_Finish()622 void File_Mpegh3da::Streams_Finish()
623 {
624 }
625 
626 //***************************************************************************
627 // Buffer - Global
628 //***************************************************************************
629 
630 //---------------------------------------------------------------------------
Read_Buffer_Continue()631 void File_Mpegh3da::Read_Buffer_Continue()
632 {
633     if (MustParse_mhaC)
634     {
635         mhaC();
636         MustParse_mhaC=false;
637         MustParse_mpegh3daFrame=true;
638         Skip_XX(Element_Size-Element_Offset,                    "Unknown");
639         return;
640     }
641     if (MustParse_mpegh3daFrame)
642     {
643         mpegh3daFrame();
644     }
645 }
646 
647 //***************************************************************************
648 // Buffer - Per element
649 //***************************************************************************
650 
651 //---------------------------------------------------------------------------
Header_Parse()652 void File_Mpegh3da::Header_Parse()
653 {
654     //Parsing
655     int32u MHASPacketType, MHASPacketLabel, MHASPacketLength;
656     BS_Begin();
657     escapedValue(MHASPacketType, 3, 8, 8,                       "MHASPacketType");
658     escapedValue(MHASPacketLabel, 2, 8, 32,                     "MHASPacketLabel");
659     escapedValue(MHASPacketLength, 11, 24, 24,                  "MHASPacketLength");
660     BS_End();
661 
662     FILLING_BEGIN();
663         if (MHASPacketLabel)
664             MHASPacketLabels.insert(MHASPacketLabel);
665         Header_Fill_Code(MHASPacketType, MHASPacketType<Mpegh3da_MHASPacketType_Size?Ztring().From_UTF8(Mpegh3da_MHASPacketType[MHASPacketType]):Ztring().From_CC3(MHASPacketType));
666         Header_Fill_Size(Element_Offset+MHASPacketLength);
667     FILLING_END();
668 }
669 
670 //---------------------------------------------------------------------------
Data_Parse()671 void File_Mpegh3da::Data_Parse()
672 {
673     //Parsing
674     switch (Element_Code)
675     {
676         case  1 : mpegh3daConfig(); break;
677         case  2 : mpegh3daFrame(); break;
678         case  3 : BS_Begin(); mae_AudioSceneInfo(); BS_End(); break;
679         case  6 : Sync(); break;
680         case  8 : Marker(); break;
681         case  9 : Crc16(); break;
682         case 14 : BufferInfo(); break;
683         case 17 : audioTruncationInfo(); break;
684         default : Skip_XX(Element_Size-Element_Offset,          "Data");
685     }
686 
687     if (!Trusted_Get())
688         Fill(Stream_Audio, 0, "NOK", "NOK", Unlimited, true, true);
689 }
690 
691 //***************************************************************************
692 // Elements
693 //***************************************************************************
694 
695 //---------------------------------------------------------------------------
mpegh3daConfig()696 void File_Mpegh3da::mpegh3daConfig()
697 {
698     Element_Begin1("mpegh3daConfig");
699     BS_Begin();
700     int8u usacSamplingFrequencyIndex;
701     Get_S1(8, mpegh3daProfileLevelIndication, "mpegh3daProfileLevelIndication"); Param_Info1(Mpegh3da_Profile_Get(mpegh3daProfileLevelIndication));
702     Get_S1 (5, usacSamplingFrequencyIndex,                      "usacSamplingFrequencyIndex");
703     if (usacSamplingFrequencyIndex==0x1f)
704         Get_S3 (24, usacSamplingFrequency,                      "usacSamplingFrequency");
705     else
706     {
707         if (usacSamplingFrequencyIndex<Aac_sampling_frequency_Size_Usac)
708             usacSamplingFrequency=Aac_sampling_frequency[usacSamplingFrequencyIndex];
709         else
710             usacSamplingFrequency=0;
711     }
712     Get_S1 (3, coreSbrFrameLengthIndex,                         "coreSbrFrameLengthIndex");
713     Skip_SB(                                                    "cfg_reserved");
714     Skip_SB(                                                    "receiverDelayCompensation");
715     SpeakerConfig3d(referenceLayout);
716     FrameworkConfig3d();
717     mpegh3daDecoderConfig();
718     TEST_SB_SKIP(                                               "usacConfigExtensionPresent");
719         mpegh3daConfigExtension();
720     TEST_SB_END();
721     BS_End();
722     Element_End0();
723 
724     FILLING_BEGIN();
725         //Filling
726         if (!Status[IsAccepted])
727             Accept("MPEG-H 3D Audio");
728     FILLING_END();
729 }
730 
731 //---------------------------------------------------------------------------
SpeakerConfig3d(speaker_layout & Layout)732 void File_Mpegh3da::SpeakerConfig3d(speaker_layout& Layout)
733 {
734     int8u speakerLayoutType;
735     Element_Begin1("SpeakerConfig3d");
736     Get_S1(2, speakerLayoutType,                                "speakerLayoutType");
737     if (speakerLayoutType==0)
738     {
739         Get_S1 (6, Layout.ChannelLayout,                        "CICPspeakerLayoutIdx"); Param_Info2(Aac_Channels_Get(Layout.ChannelLayout), " channels");
740     }
741     else
742     {
743         int32u numSpeakers;
744         escapedValue(numSpeakers, 5, 8, 16,                     "numSpeakers");
745         numSpeakers++;
746         Layout.numSpeakers=numSpeakers;
747 
748         if (speakerLayoutType==1)
749         {
750             Layout.CICPspeakerIdxs.resize(numSpeakers);
751             for (size_t Pos=0; Pos<numSpeakers; Pos++)
752             {
753                 int8u CICPspeakerIdx;
754                 Get_S1(7, CICPspeakerIdx,                       "CICPspeakerIdx");
755                 Layout.CICPspeakerIdxs[Pos]=(Aac_OutputChannel)CICPspeakerIdx;
756             }
757         }
758         else if (speakerLayoutType==2)
759         {
760             mpegh3daFlexibleSpeakerConfig(Layout);
761         }
762     }
763     Element_End0();
764 
765     FILLING_BEGIN();
766         //Finish
767         if (Status[IsAccepted])
768             Finish("MPEG-H 3D Audio");
769     FILLING_END();
770 }
771 
772 //---------------------------------------------------------------------------
mpegh3daFlexibleSpeakerConfig(speaker_layout & Layout)773 void File_Mpegh3da::mpegh3daFlexibleSpeakerConfig(speaker_layout& Layout)
774 {
775     bool angularPrecision;
776     Element_Begin1("mpegh3daFlexibleSpeakerConfig");
777     Get_SB(angularPrecision,                                    "angularPrecision");
778     for (size_t Pos=0; Pos<Layout.numSpeakers; Pos++)
779     {
780         Layout.SpeakersInfo.push_back(speaker_info());
781         speaker_info& SpeakerInfo=Layout.SpeakersInfo[Layout.SpeakersInfo.size()-1];
782         mpegh3daSpeakerDescription(SpeakerInfo, angularPrecision);
783         if (SpeakerInfo.AzimuthAngle && SpeakerInfo.AzimuthAngle!=180)
784         {
785             bool alsoAddSymmetricPair;
786             Get_SB (alsoAddSymmetricPair,                       "alsoAddSymmetricPair");
787             if (alsoAddSymmetricPair)
788                 Pos++;
789         }
790     }
791     Element_End0();
792 }
793 
794 //---------------------------------------------------------------------------
mpegh3daSpeakerDescription(speaker_info & SpeakerInfo,bool angularPrecision)795 void File_Mpegh3da::mpegh3daSpeakerDescription(speaker_info& SpeakerInfo, bool angularPrecision)
796 {
797     Element_Begin1("mpegh3daSpeakerDescription");
798     TESTELSE_SB_SKIP(                                           "isCICPspeakerIdx");
799     {
800         int8u CICPspeakerIdx;
801         Get_S1 (7, CICPspeakerIdx,                              "CICPspeakerIdx");
802         if (CICPspeakerIdx<Mpegh3da_SpeakerInfo_Size)
803             SpeakerInfo=Mpegh3da_SpeakerInfo[CICPspeakerIdx];
804         else
805             SpeakerInfo.CICPspeakerIdx=(Aac_OutputChannel)CICPspeakerIdx;
806     }
807     TESTELSE_SB_ELSE(                                           "isCICPspeakerIdx");
808         int8u ElevationClass;
809         Get_S1(2, ElevationClass,                               "ElevationClass");
810 
811         switch (ElevationClass)
812         {
813         case 0:
814             SpeakerInfo.ElevationAngle=0;
815             break;
816         case 1:
817             SpeakerInfo.ElevationAngle=35;
818             SpeakerInfo.ElevationDirection=false;
819             break;
820         case 2:
821             SpeakerInfo.ElevationAngle=15;
822             SpeakerInfo.ElevationDirection=true;
823             break;
824         case 3:
825             int8u ElevationAngleIdx;
826             Get_S1(angularPrecision?7:5, ElevationAngleIdx, "ElevationAngleIdx");
827             SpeakerInfo.ElevationAngle=ElevationAngleIdx*(angularPrecision?1:5);
828 
829             if (SpeakerInfo.ElevationAngle)
830                 Get_SB(SpeakerInfo.ElevationDirection,         "ElevationDirection");
831             break;
832         }
833 
834         int8u AzimuthAngleIdx;
835         Get_S1(angularPrecision?8:6, AzimuthAngleIdx, "AzimuthAngleIdx");
836         SpeakerInfo.AzimuthAngle=AzimuthAngleIdx*(angularPrecision?1:5);
837 
838         if (SpeakerInfo.AzimuthAngle && SpeakerInfo.AzimuthAngle!=180)
839             Get_SB(SpeakerInfo.AzimuthDirection, "AzimuthDirection");
840 
841         Get_SB(SpeakerInfo.isLFE,                "isLFE");
842 
843         SpeakerInfo.CICPspeakerIdx=(Aac_OutputChannel)-1;
844     TESTELSE_SB_END();
845     Element_End0();
846 }
847 
848 //---------------------------------------------------------------------------
mpegh3daFrame()849 void File_Mpegh3da::mpegh3daFrame()
850 {
851     Skip_XX(Element_Size,                                       "mpegh3daFrame");
852 
853     FILLING_BEGIN();
854         //Filling
855         if (Status[IsAccepted])
856             Finish("MPEG-H 3D Audio");
857     FILLING_END();
858 }
859 
860 //---------------------------------------------------------------------------
Sync()861 void File_Mpegh3da::Sync()
862 {
863     //Parsing
864     Skip_B1(                                                    "syncword");
865 }
866 
867 //---------------------------------------------------------------------------
Marker()868 void File_Mpegh3da::Marker()
869 {
870     //Parsing
871     Info_B1(marker_byte,                                        "marker_byte"); Param_Info1C(marker_byte<Mpegh3da_marker_byte_Size, Mpegh3da_marker_byte[marker_byte]);
872 }
873 
874 //---------------------------------------------------------------------------
Crc16()875 void File_Mpegh3da::Crc16()
876 {
877     //Parsing
878     Skip_B2(                                                    "mhasParity16Data");
879 }
880 
881 //---------------------------------------------------------------------------
BufferInfo()882 void File_Mpegh3da::BufferInfo()
883 {
884     //Parsing
885     BS_Begin();
886     bool mhas_buffer_fullness_present;
887     Get_SB (mhas_buffer_fullness_present,                       "mhas_buffer_fullness_present");
888     if (mhas_buffer_fullness_present)
889     {
890         int32u mhas_buffer_fullness;
891         escapedValue(mhas_buffer_fullness, 15, 39, 71,          "mhas_buffer_fullness");
892     }
893     BS_End();
894 }
895 
896 //---------------------------------------------------------------------------
FrameworkConfig3d()897 void File_Mpegh3da::FrameworkConfig3d()
898 {
899     numAudioChannels=0;
900     numAudioObjects=0;
901     numSAOCTransportChannels=0;
902     numHOATransportChannels=0;
903 
904     Element_Begin1("FrameworkConfig3d");
905     Element_Begin1("Signals3d");
906     Get_S1(5, bsNumSignalGroups,                                "bsNumSignalGroups");
907     bsNumSignalGroups++; Param_Info2(bsNumSignalGroups, " signals");
908     SignalGroups.resize(bsNumSignalGroups);
909     for (int8u Pos=0; Pos<bsNumSignalGroups; Pos++)
910     {
911         signal_group& E=SignalGroups[Pos];
912         Element_Begin1("signalGroup");
913         Get_S1(3, E.Type,                                       "signalGroupType");
914         escapedValue(E.bsNumberOfSignals, 5, 8, 16,             "bsNumberOfSignals");
915         E.bsNumberOfSignals++;
916 
917         if (E.Type==SignalGroupTypeChannels)
918         {
919             numAudioChannels+=E.bsNumberOfSignals;
920             TESTELSE_SB_SKIP(                                   "differsFromReferenceLayout");
921                 SpeakerConfig3d(E.Layout);
922             TESTELSE_SB_ELSE(                                   "differsFromReferenceLayout");
923                 E.Layout=referenceLayout;
924             TESTELSE_SB_END();
925         }
926         else if (E.Type==SignalGroupTypeObject)
927         {
928             numAudioObjects+=E.bsNumberOfSignals;
929             E.Layout.numSpeakers=E.bsNumberOfSignals;
930         }
931         else if (E.Type==SignalGroupTypeSAOC)
932         {
933             numSAOCTransportChannels+=E.bsNumberOfSignals;
934             TEST_SB_SKIP(                                       "saocDmxLayoutPresent");
935                 SpeakerConfig3d(E.Layout);
936             TEST_SB_END();
937         }
938         else if (E.Type==SignalGroupTypeHOA)
939         {
940             numHOATransportChannels+=E.bsNumberOfSignals;
941             E.Layout.numSpeakers=E.bsNumberOfSignals;
942         }
943         Element_End0();
944     }
945     Element_End0();
946     Element_End0();
947 }
948 
949 //---------------------------------------------------------------------------
mpegh3daDecoderConfig()950 void File_Mpegh3da::mpegh3daDecoderConfig()
951 {
952     Elements.clear();
953 
954     Element_Begin1("mpegh3daDecoderConfig");
955     escapedValue(numElements, 4, 8, 16,                         "numElements");
956     numElements++;
957 
958     bool elementLengthPresent;
959     Get_SB (elementLengthPresent,                               "elementLengthPresent");
960 
961     for (size_t Pos=0; Pos<numElements; Pos++)
962     {
963         Element_Begin1("Element");
964         int8u usacElementType;
965         Get_S1(2, usacElementType,                              "usacElementType"); Element_Info1(Mpegh3da_usacElementType[usacElementType]);
966         switch (usacElementType)
967         {
968         case ID_USAC_SCE:
969             mpegh3daSingleChannelElementConfig(coreSbrFrameLengthIndex_Mapping[coreSbrFrameLengthIndex].sbrRatioIndex);
970             Elements.push_back(usac_element(ID_USAC_SCE));
971             break;
972         case ID_USAC_CPE:
973             mpegh3daChannelPairElementConfig(coreSbrFrameLengthIndex_Mapping[coreSbrFrameLengthIndex].sbrRatioIndex);
974             Elements.push_back(usac_element(ID_USAC_CPE));
975             break;
976         case ID_USAC_LFE:
977             Elements.push_back(usac_element(ID_USAC_LFE));
978             break;
979         case ID_USAC_EXT:
980             mpegh3daExtElementConfig();
981             Elements.push_back(usac_element(ID_USAC_EXT));
982             break;
983         }
984         Element_End0();
985     }
986     Element_End0();
987 }
988 
989 //---------------------------------------------------------------------------
mpegh3daSingleChannelElementConfig(int8u sbrRatioIndex)990 void File_Mpegh3da::mpegh3daSingleChannelElementConfig(int8u sbrRatioIndex)
991 {
992     Element_Begin1("mpegh3daSingleChannelElementConfig");
993     mpegh3daCoreConfig();
994     if (sbrRatioIndex)
995         SbrConfig();
996     Element_End0();
997 }
998 
999 //---------------------------------------------------------------------------
mpegh3daChannelPairElementConfig(int8u sbrRatioIndex)1000 void File_Mpegh3da::mpegh3daChannelPairElementConfig(int8u sbrRatioIndex)
1001 {
1002     int32u nBits=floor(log2(numAudioChannels+numAudioObjects+numHOATransportChannels+numSAOCTransportChannels-1))+1;
1003     int8u stereoConfigIndex=0;
1004     int8u qceIndex;
1005     Element_Begin1("mpegh3daChannelPairElementConfig");
1006     bool enhancedNoiseFilling=mpegh3daCoreConfig();
1007     if(enhancedNoiseFilling)
1008         Skip_SB(                                                "igfIndependentTiling");
1009 
1010     if (sbrRatioIndex)
1011     {
1012         SbrConfig();
1013         Get_S1(2, stereoConfigIndex,                            "stereoConfigIndex");
1014     }
1015 
1016     if (stereoConfigIndex) {
1017         Mps212Config(stereoConfigIndex);
1018     }
1019 
1020     Get_S1(2, qceIndex,                                         "qceIndex");
1021     if (qceIndex)
1022     {
1023         TEST_SB_SKIP(                                           "shiftIndex0");
1024             Skip_BS(nBits,                                      "shiftChannel0");
1025         TEST_SB_END();
1026     }
1027 
1028     TEST_SB_SKIP(                                               "shiftIndex1");
1029         Skip_BS(nBits,                                          "shiftChannel1");
1030     TEST_SB_END();
1031 
1032     if (sbrRatioIndex==0 && qceIndex==0)
1033         Skip_SB(                                                "lpdStereoIndex");
1034     Element_End0();
1035 }
1036 
1037 //---------------------------------------------------------------------------
mpegh3daExtElementConfig()1038 void File_Mpegh3da::mpegh3daExtElementConfig()
1039 {
1040     Element_Begin1("mpegh3daExtElementConfig");
1041     int32u usacExtElementType;
1042     escapedValue(usacExtElementType, 4, 8, 16,                  "usacExtElementType"); Element_Level--; Element_Info1C(usacExtElementType<Mpegh3da_usacExtElementType_Size, Mpegh3da_usacExtElementType[usacExtElementType]); Element_Level++;
1043 
1044     int32u usacExtElementConfigLength;
1045     escapedValue(usacExtElementConfigLength, 4, 8, 16,          "usacExtElementConfigLength");
1046 
1047     int32u usacExtElementDefaultLength=0;
1048     TEST_SB_SKIP(                                               "usacExtElementDefaultLengthPresent");
1049         escapedValue(usacExtElementDefaultLength, 8, 16, 0,     "usacExtElementDefaultLength"); //TODO: check if call is valid
1050         usacExtElementDefaultLength++;
1051     TEST_SB_END();
1052 
1053     Skip_SB(                                                    "usacExtElementPayloadFrag");
1054 
1055     size_t Remain_Before=BS->Remain();
1056     switch (usacExtElementType)
1057     {
1058     case ID_EXT_ELE_FILL:
1059         break; // No configuration element
1060     //case ID_EXT_ELE_MPEGS:
1061         //TODO: SpatialSpecificConfig();
1062         //break;
1063     //case ID_EXT_ELE_SAOC:
1064         //TODO: SAOCSpecificConfig();
1065         //break;
1066     case ID_EXT_ELE_AUDIOPREROLL:
1067         break; // No configuration element
1068     case ID_EXT_ELE_UNI_DRC:
1069         //if (referenceLayout.ChannelLayout!=19) //TEMP
1070             mpegh3daUniDrcConfig();
1071         break;
1072     case ID_EXT_ELE_OBJ_METADATA:
1073         ObjectMetadataConfig();
1074         break;
1075     //case ID_EXT_ELE_SAOC_3D:
1076     //    SAOC3DSpecificConfig();
1077     //    break;
1078     //case ID_EXT_ELE_HOA:
1079         //HOAConfig();
1080         //break;
1081     case ID_EXT_ELE_FMT_CNVRTR:
1082         break; // No configuration element
1083     //case ID_EXT_ELE_MCT:
1084         //MCTConfig();
1085         //break;
1086     case ID_EXT_ELE_TCC:
1087         TccConfig();
1088         break;
1089     //case ID_EXT_ELE_HOA_ENH_LAYER:
1090         //HOAEnhConfig();
1091         //break;
1092     //case ID_EXT_ELE_HREP:
1093         //HREPConfig(current_signal_group);
1094         //break;
1095     //case ID_EXT_ELE_ENHANCED_OBJ_METADATA:
1096         //EnhancedObjectMetadataConfig();
1097         //break;
1098         break;
1099     default:
1100         if (usacExtElementConfigLength)
1101             Skip_BS(usacExtElementConfigLength*8,               "reserved");
1102         break;
1103     }
1104     if (BS->Remain()+usacExtElementConfigLength*8>Remain_Before)
1105     {
1106         size_t Size=BS->Remain()+usacExtElementConfigLength*8-Remain_Before;
1107         int8u Padding=1;
1108         if (Size<8)
1109             Peek_S1((int8u)Size, Padding);
1110 
1111         if (Padding && Remain_Before!=BS->Remain() && usacExtElementType!=ID_EXT_ELE_OBJ_METADATA)
1112             Fill(Stream_Audio, 0, "NOK", "NOK", Unlimited, true, true);
1113         Skip_BS(Size, Padding?"(Unknown)":"Padding");
1114     }
1115 
1116     Element_End0();
1117 }
1118 
1119 //---------------------------------------------------------------------------
mpegh3daCoreConfig()1120 bool File_Mpegh3da::mpegh3daCoreConfig()
1121 {
1122     bool enhancedNoiseFilling;
1123     Element_Begin1("mpegh3daCoreConfig");
1124     Skip_SB(                                                    "tw_mdct");
1125     Skip_SB(                                                    "fullbandLpd");
1126     Skip_SB(                                                    "noiseFilling");
1127     TEST_SB_GET(enhancedNoiseFilling,                           "enhancedNoiseFilling");
1128         Skip_SB(                                                "igfUseEnf");
1129         Skip_SB(                                                "igfUseHighRes");
1130         Skip_SB(                                                "igfUseWhitening");
1131         Skip_SB(                                                "igfAfterTnsSynth");
1132         Skip_S1(5,                                              "igfStartIndex");
1133         Skip_S1(4,                                              "igfStopIndex");
1134     TEST_SB_END();
1135     Element_End0();
1136 
1137     return enhancedNoiseFilling;
1138 }
1139 
1140 //---------------------------------------------------------------------------
mpegh3daUniDrcConfig()1141 void File_Mpegh3da::mpegh3daUniDrcConfig()
1142 {
1143     Element_Begin1("mpegh3daUniDrcConfig");
1144     int8u drcCoefficientsUniDrcCount;
1145     Get_S1(3, drcCoefficientsUniDrcCount,                       "drcCoefficientsUniDrcCount");
1146 
1147     int8u drcInstructionsUniDrcCount;
1148     Get_S1(6, drcInstructionsUniDrcCount,                       "drcInstructionsUniDrcCount");
1149 
1150     Element_Begin1("mpegh3daUniDrcChannelLayout");
1151     Get_S1 (7, baseChannelCount,                                "baseChannelCount");
1152     Element_End0();
1153     if (!drcCoefficientsUniDrcCount)
1154         Fill(Stream_Audio, 0, "TEMP_drcCoefficientsUniDrcCount", drcCoefficientsUniDrcCount); //TEMP
1155 
1156     for (int8u Pos=0; Pos<drcCoefficientsUniDrcCount; Pos++)
1157         drcCoefficientsUniDrc(); // in File_USAC.cpp
1158 
1159     for (int8u Pos=0; Pos<drcInstructionsUniDrcCount; Pos++)
1160     {
1161         int8u drcInstructionsType;
1162         Get_S1(Peek_SB()?2:1, drcInstructionsType,              "drcInstructionsType");
1163 
1164         int8u ID;
1165         if (drcInstructionsType==2)
1166             Get_S1 (7, ID,                                      "mae_groupID");
1167         else if (drcInstructionsType==3)
1168             Get_S1 (5, ID,                                      "mae_groupPresetID");
1169         else
1170             ID=0;
1171 
1172         drcInstructionsUniDrc(false, true); // in File_USAC.cpp
1173         Mpegh3da_drcInstructionsUniDrc_Data[drcInstructionsType][ID][drcInstructionsUniDrc_Data.begin()->first]=drcInstructionsUniDrc_Data.begin()->second;
1174         drcInstructionsUniDrc_Data.clear();
1175     }
1176 
1177     TEST_SB_SKIP(                                               "uniDrcConfigExtPresent");
1178         uniDrcConfigExtension(); // in File_USAC.cpp
1179     TEST_SB_END();
1180 
1181     TEST_SB_SKIP(                                               "loudnessInfoSetPresent");
1182         mpegh3daLoudnessInfoSet();
1183     TEST_SB_END();
1184     Element_End0();
1185 }
1186 
1187 //---------------------------------------------------------------------------
downmixConfig()1188 void File_Mpegh3da::downmixConfig()
1189 {
1190     Element_Begin1("downmixConfig");
1191     int8u downmixConfigType;
1192     Get_S1 (2, downmixConfigType,                                "downmixConfigType");
1193     switch (downmixConfigType)
1194     {
1195         case 0:
1196         case 2:
1197         {
1198             bool passiveDownmixFlag;
1199             Get_SB (passiveDownmixFlag,                         "passiveDownmixFlag");
1200             if (!passiveDownmixFlag)
1201                 Skip_S1(3,                                      "phaseAlignStrength");
1202             Skip_SB(                                            "immersiveDownmixFlag");
1203         }
1204         break;
1205     }
1206     switch (downmixConfigType)
1207     {
1208         case 1:
1209         case 2:
1210         {
1211             Skip_S1(5,                                           "DownmixMatrixSet - TODO");
1212         }
1213         break;
1214     }
1215     Element_End0();
1216 }
1217 
1218 //---------------------------------------------------------------------------
mpegh3daLoudnessInfoSet()1219 void File_Mpegh3da::mpegh3daLoudnessInfoSet()
1220 {
1221     Element_Begin1("mpegh3daLoudnessInfoSet");
1222     int8u loudnessInfoCount;
1223     Get_S1(6, loudnessInfoCount,                                "loudnessInfoCount");
1224     for(int8u Pos=0; Pos<loudnessInfoCount; Pos++)
1225     {
1226         int8u loudnessInfoType;
1227         Get_S1(2, loudnessInfoType,                             "loudnessInfoType");
1228 
1229         int8u ID;
1230         if (loudnessInfoType==1 || loudnessInfoType==2)
1231             Get_S1 (7, ID,                                      "mae_groupID");
1232         else if (loudnessInfoType==3)
1233             Get_S1 (5, ID,                                      "mae_groupPresetID");
1234         else
1235             ID=0;
1236 
1237         bool IsNOK=loudnessInfo(false); // in File_USAC.cpp
1238         Mpegh3da_loudnessInfo_Data[loudnessInfoType][ID].Data[0][loudnessInfo_Data[0].begin()->first]=loudnessInfo_Data[0].begin()->second;
1239         loudnessInfo_Data[0].clear();
1240         if (IsNOK)
1241         {
1242             Element_End0();
1243             return;
1244         }
1245     }
1246 
1247     TEST_SB_SKIP(                                               "loudnessInfoAlbumPresent");
1248         int8u loudnessInfoAlbumCount;
1249         Get_S1(6, loudnessInfoAlbumCount,                       "loudnessInfoAlbumCount");
1250         for (int8u Pos=0; Pos<loudnessInfoAlbumCount; Pos++)
1251         {
1252             loudnessInfo(true); // in File_USAC.cpp
1253             Mpegh3da_loudnessInfo_Data[0][0].Data[1][loudnessInfo_Data[1].begin()->first]=loudnessInfo_Data[1].begin()->second;
1254             loudnessInfo_Data[1].clear();
1255         }
1256     TEST_SB_END();
1257 
1258     TEST_SB_SKIP(                                               "loudnessInfoSetExtensionPresent");
1259         loudnessInfoSetExtension(); // in File_USAC.cpp
1260     TEST_SB_END();
1261     Element_End0();
1262 }
1263 
1264 //---------------------------------------------------------------------------
ObjectMetadataConfig()1265 void File_Mpegh3da::ObjectMetadataConfig()
1266 {
1267     Element_Begin1("ObjectMetadataConfig");
1268     Skip_SB(                                                    "lowDelayMetadataCoding");
1269     TESTELSE_SB_SKIP(                                           "hasCoreLength");
1270     TESTELSE_SB_ELSE(                                           "hasCoreLength");
1271         Skip_S1(6,                                              "frameLength");
1272     TESTELSE_SB_END();
1273 
1274     TEST_SB_SKIP("hasScreenRelativeObjects");
1275         size_t num_objects=num_objects_Get();
1276         for (int16u Pos=0; Pos<num_objects; Pos++)
1277         {
1278             Skip_SB(                                            "isScreenRelativeObject");
1279         }
1280     TEST_SB_END();
1281     Skip_SB(                                                    "hasDynamicObjectPriority");
1282     Skip_SB(                                                    "hasUniformSpread");
1283     Element_End0();
1284 }
1285 
1286 //---------------------------------------------------------------------------
SAOC3DSpecificConfig()1287 void File_Mpegh3da::SAOC3DSpecificConfig()
1288 {
1289     int8u bsSamplingFrequencyIndex, bsNumSaocDmxChannels, bsNumSaocDmxObjects, bsNumSaocObjects;
1290     int32u NumSaocChannels=0, NumInputSignals=0;
1291     Element_Begin1("SAOC3DSpecificConfig");
1292     Get_S1(4, bsSamplingFrequencyIndex,                         "bsSamplingFrequencyIndex");
1293     if (bsSamplingFrequencyIndex==15)
1294         Skip_S3(24,                                             "bsSamplingFrequency");
1295 
1296     Skip_S1(3,                                                  "bsFreqRes");
1297     Skip_SB(                                                    "bsDoubleFrameLengthFlag");
1298     Get_S1(5, bsNumSaocDmxChannels,                             "bsNumSaocDmxChannels");
1299     Get_S1(5, bsNumSaocDmxObjects,                              "bsNumSaocDmxObjects");
1300     Skip_SB(                                                    "bsDecorrelationMethod");
1301 
1302     if (bsNumSaocDmxChannels)
1303     {
1304         speaker_layout saocChannelLayout;
1305         SpeakerConfig3d(saocChannelLayout);
1306         NumSaocChannels=SAOC3DgetNumChannels(saocChannelLayout);
1307         NumInputSignals+=NumSaocChannels;
1308     }
1309 
1310     Get_S1(8, bsNumSaocObjects ,                                "bsNumSaocObjects");
1311     NumInputSignals+=bsNumSaocObjects;
1312 
1313     for (int8u Pos=0; Pos<NumSaocChannels; Pos++)
1314     {
1315         for(int8u Pos2=Pos+1; Pos2<NumSaocChannels; Pos2++)
1316             Skip_SB(                                            "bsRelatedTo");
1317     }
1318 
1319     for (int8u Pos=NumSaocChannels; Pos<NumInputSignals; Pos++)
1320     {
1321         for(int8u Pos2=Pos+1; Pos2<NumInputSignals; Pos2++)
1322             Skip_SB(                                            "bsRelatedTo");
1323     }
1324 
1325     Skip_SB(                                                    "bsOneIOC");
1326     TEST_SB_SKIP(                                               "bsSaocDmxMethod");
1327         SAOC3DgetNumChannels(referenceLayout);
1328     TEST_SB_END();
1329 
1330     TEST_SB_SKIP(                                               "bsDualMode");
1331         Skip_S1(5,                                              "bsBandsLow");
1332     TEST_SB_END();
1333 
1334     TEST_SB_SKIP(                                               "bsDcuFlag");
1335         Skip_SB(                                                "bsDcuMandatory");
1336         TEST_SB_SKIP(                                           "bsDcuDynamic");
1337             Skip_SB(                                            "bsDcuMode");
1338             Skip_S1(4,                                          "bsDcuParam");
1339         TEST_SB_END();
1340     TEST_SB_END();
1341     Skip_S1(BS->Remain()%8,                                     "byte_align");
1342     //TODO: SAOC3DExtensionConfig();
1343     Element_End0();
1344 }
1345 
1346 //---------------------------------------------------------------------------
SAOC3DgetNumChannels(speaker_layout Layout)1347 int32u File_Mpegh3da::SAOC3DgetNumChannels(speaker_layout Layout)
1348 {
1349     int32u ToReturn=Layout.numSpeakers;
1350 
1351     for (int32u Pos=0; Pos<Layout.numSpeakers; Pos++)
1352     {
1353         if (Layout.SpeakersInfo.size()>Pos && Layout.SpeakersInfo[Pos].isLFE)
1354             ToReturn--;
1355     }
1356 
1357     return ToReturn;
1358 }
1359 
1360 //---------------------------------------------------------------------------
MCTConfig()1361 void File_Mpegh3da::MCTConfig()
1362 {
1363     Element_Begin1("MCTConfig");
1364     for(int32u chan=0; chan<numAudioChannels; ++chan) // bsNumberOfSignals[grp] but which grp?
1365     {
1366         Skip_SB(                                                "mctChanMask");
1367     }
1368     Element_End0();
1369 }
1370 
1371 //---------------------------------------------------------------------------
TccConfig()1372 void File_Mpegh3da::TccConfig()
1373 {
1374     Element_Begin1("TccConfig");
1375     for(int32u Pos=0; Pos<numElements; Pos++)
1376     {
1377         if(Elements.size()>Pos && (Elements[Pos].Type==ID_USAC_SCE || Elements[Pos].Type==ID_USAC_CPE))
1378             Skip_S1(2,                                       "tccMode");
1379     }
1380     Element_End0();
1381 }
1382 
1383 //---------------------------------------------------------------------------
EnhancedObjectMetadataConfig()1384 void File_Mpegh3da::EnhancedObjectMetadataConfig()
1385 {
1386     Element_Begin1("EnhancedObjectMetadataConfig");
1387     bool hasCommonGroupExcludedSectors=false;
1388     TEST_SB_SKIP(                                               "hasDiffuseness");
1389         Skip_SB(                                                "hasCommonGroupDiffuseness");
1390     TEST_SB_END();
1391 
1392     TEST_SB_SKIP(                                               "hasExcludedSectors");
1393         TEST_SB_GET(hasCommonGroupExcludedSectors,              "hasCommonGroupExcludedSectors");
1394             Skip_SB(                                            "useOnlyPredefinedSectors");
1395         TEST_SB_END();
1396     TEST_SB_END();
1397 
1398     TEST_SB_SKIP(                                               "hasClosestSpeakerCondition");
1399         Skip_S1(7,                                              "closestSpeakerThresholdAngle");
1400     TEST_SB_END();
1401 
1402     size_t num_objects=num_objects_Get();
1403     for (int8u Pos=0; Pos<num_objects; Pos++)
1404     {
1405         TEST_SB_SKIP(                                           "hasDivergence");
1406             Skip_S1(6,                                          "divergenceAzimuthRange");
1407         TEST_SB_END();
1408 
1409         if (!hasCommonGroupExcludedSectors)
1410             Skip_SB(                                            "useOnlyPredefinedSectors");
1411     }
1412     Element_End0();
1413 }
1414 
1415 //---------------------------------------------------------------------------
mpegh3daConfigExtension()1416 void File_Mpegh3da::mpegh3daConfigExtension()
1417 {
1418     Element_Begin1("mpegh3daConfigExtension");
1419     int32u numConfigExtensions;
1420     escapedValue(numConfigExtensions, 2, 4, 8,                  "numConfigExtensions");
1421     numConfigExtensions++;
1422 
1423     for (int32u Pos=0; Pos<numConfigExtensions; Pos++)
1424     {
1425         Element_Begin1("configExtension");
1426         int32u usacConfigExtType;
1427         escapedValue(usacConfigExtType, 4, 8, 16,               "usacConfigExtType"); Element_Info1C(usacConfigExtType<Mpegh3da_usacConfigExtType_Size, Mpegh3da_usacConfigExtType[usacConfigExtType]);
1428 
1429         int32u usacConfigExtLength;
1430         escapedValue(usacConfigExtLength, 4, 8, 16,             "usacConfigExtLength");
1431         if (!usacConfigExtLength)
1432         {
1433             Element_End0();
1434             continue;
1435         }
1436 
1437         size_t Remain_Before=BS->Remain();
1438         switch ((UsacConfigExtType)usacConfigExtType)
1439         {
1440         case ID_CONFIG_EXT_FILL:
1441             while (usacConfigExtLength)
1442             {
1443                 usacConfigExtLength--;
1444                 Skip_S1(8,                                      "fill_byte"); // should be '10100101'
1445             }
1446             break;
1447         case ID_CONFIG_EXT_DOWNMIX:
1448             downmixConfig();
1449             break;
1450         case ID_CONFIG_EXT_LOUDNESS_INFO:
1451             mpegh3daLoudnessInfoSet();
1452             break;
1453         case ID_CONFIG_EXT_AUDIOSCENE_INFO:
1454             mae_AudioSceneInfo();
1455             break;
1456         //case ID_CONFIG_EXT_HOA_MATRIX:
1457         //    HoaRenderingMatrixSet();
1458         //    break;
1459         case ID_CONFIG_EXT_ICG:
1460             ICGConfig();
1461             break;
1462         case ID_CONFIG_EXT_SIG_GROUP_INFO:
1463             SignalGroupInformation();
1464             break;
1465         case ID_CONFIG_EXT_COMPATIBLE_PROFILE_LEVEL_SET:
1466             CompatibleProfileLevelSet();
1467             break;
1468         default:
1469             Skip_BS(usacConfigExtLength*8,                      "reserved");
1470         }
1471         if (BS->Remain()+usacConfigExtLength*8>Remain_Before)
1472         {
1473             size_t Size=BS->Remain()+usacConfigExtLength*8-Remain_Before;
1474             int8u Padding=1;
1475             if (Size<8)
1476                 Peek_S1((int8u)Size, Padding);
1477 
1478             if (Padding && Remain_Before!=BS->Remain() && usacConfigExtType!=ID_CONFIG_EXT_DOWNMIX && usacConfigExtType!=ID_CONFIG_EXT_HOA_MATRIX)
1479                 Fill(Stream_Audio, 0, "NOK", "NOK", Unlimited, true, true);
1480             Skip_BS(Size, Padding?"(Unknown)":"Padding");
1481         }
1482         Element_End0();
1483     }
1484     Element_End0();
1485 }
1486 
1487 //---------------------------------------------------------------------------
SignalGroupInformation()1488 void File_Mpegh3da::SignalGroupInformation()
1489 {
1490     Element_Begin1("SignalGroupInformation");
1491     for (int8u Pos=0; Pos<bsNumSignalGroups+1; Pos++)
1492     {
1493         Skip_S1(3,                                              "groupPriority");
1494         Skip_SB(                                                "fixedPosition");
1495     }
1496     Element_End0();
1497 }
1498 
1499 //---------------------------------------------------------------------------
CompatibleProfileLevelSet()1500 void File_Mpegh3da::CompatibleProfileLevelSet()
1501 {
1502     Element_Begin1("CompatibleProfileLevelSet");
1503     int8u bsNumCompatibleSets;
1504     Get_S1 (4, bsNumCompatibleSets,                             "bsNumCompatibleSets");
1505     Skip_S1(4,                                                  "reserved");
1506     mpegh3daCompatibleProfileLevelSet.resize(bsNumCompatibleSets+1);
1507     for (int8u Pos=0; Pos<=bsNumCompatibleSets; Pos++)
1508     {
1509         Get_S1(8, mpegh3daCompatibleProfileLevelSet[Pos], "CompatibleSetIndication"); Param_Info1(Mpegh3da_Profile_Get(mpegh3daCompatibleProfileLevelSet[Pos]));
1510     }
1511     Element_End0();
1512 }
1513 
1514 //---------------------------------------------------------------------------
HoaRenderingMatrixSet()1515 void File_Mpegh3da::HoaRenderingMatrixSet()
1516 {
1517     Element_Begin1("HoaRenderingMatrixSet - TODO");
1518     Skip_S1(5,                                                  "numOfHoaRenderingMatrices");
1519     Element_End0();
1520 }
1521 
1522 //---------------------------------------------------------------------------
ICGConfig()1523 void File_Mpegh3da::ICGConfig()
1524 {
1525     Element_Begin1("ICGConfig");
1526     TEST_SB_SKIP(                                               "ICPresent");
1527         for (int32u Pos=0; Pos<numElements; Pos++)
1528         {
1529             if (Elements.size()>Pos && Elements[Pos].Type==ID_USAC_CPE)
1530                 Skip_SB(                                        "ICinCPE");
1531         }
1532 
1533         TEST_SB_SKIP(                                           "ICGPreAppliedPresent");
1534             for (int32u Pos=0; Pos<numElements; Pos++)
1535             {
1536                 if (Elements.size()>Pos && Elements[Pos].Type==ID_USAC_CPE)
1537                     Skip_SB(                                     "ICGPreAppliedCPE");
1538             }
1539         TEST_SB_END();
1540     TEST_SB_END();
1541     Element_End0();
1542 }
1543 
1544 //---------------------------------------------------------------------------
mae_AudioSceneInfo()1545 void File_Mpegh3da::mae_AudioSceneInfo()
1546 {
1547     Groups.clear();
1548     SwitchGroups.clear();
1549     GroupPresets.clear();
1550 
1551     Element_Begin1("mae_AudioSceneInfo");
1552     bool mae_isMainStream;
1553     TESTELSE_SB_GET (mae_isMainStream,                          "mae_isMainStream");
1554         TEST_SB_SKIP(                                           "mae_audioSceneInfoIDPresent");
1555             Get_S1 (8, audioSceneInfoID,                        "mae_audioSceneInfoID");
1556         TEST_SB_END();
1557         int8u mae_numGroups;
1558         Get_S1(7, mae_numGroups,                                "mae_numGroups");
1559         mae_GroupDefinition(mae_numGroups);
1560         int8u mae_numSwitchGroups;
1561         Get_S1(5, mae_numSwitchGroups,                          "mae_numSwitchGroups");
1562         mae_SwitchGroupDefinition(mae_numSwitchGroups);
1563         int8u mae_numGroupPresets;
1564         Get_S1(5, mae_numGroupPresets,                          "mae_numGroupPresets");
1565         mae_GroupPresetDefinition(mae_numGroupPresets);
1566         mae_Data(mae_numGroups, mae_numGroupPresets);
1567         Skip_S1(7,                                              "mae_metaDataElementIDmaxAvail");
1568     TESTELSE_SB_ELSE(                                           "mae_isMainStream");
1569         Skip_S1(7,                                              "mae_bsMetaDataElementIDoffset");
1570         Skip_S1(7,                                              "mae_metaDataElementIDmaxAvail");
1571     TESTELSE_SB_END();
1572     Element_End0();
1573 
1574     isMainStream=mae_isMainStream;
1575 }
1576 
1577 //---------------------------------------------------------------------------
mae_GroupDefinition(int8u numGroups)1578 void File_Mpegh3da::mae_GroupDefinition(int8u numGroups)
1579 {
1580     Element_Begin1("mae_GroupDefinition");
1581     Groups.resize(numGroups);
1582     for (int8u Pos=0; Pos<numGroups; Pos++)
1583     {
1584         Element_Begin1("mae_group");
1585         group& G=Groups[Pos];
1586         Get_S1 (7, G.ID,                                        "mae_groupID");
1587         Element_Info1(Ztring::ToZtring(G.ID));
1588         Get_SB (G.allowOnOff,                                   "mae_allowOnOff");
1589         Get_SB (G.defaultOnOff,                                 "mae_defaultOnOff");
1590 
1591         TEST_SB_SKIP(                                           "mae_allowPositionInteractivity");
1592             Skip_S1(7,                                          "mae_interactivityMinAzOffset");
1593             Skip_S1(7,                                          "mae_interactivityMaxAzOffset");
1594             Skip_S1(5,                                          "mae_interactivityMinElOffset");
1595             Skip_S1(5,                                          "mae_interactivityMaxElOffset");
1596             Skip_S1(4,                                          "mae_interactivityMinDistFactor");
1597             Skip_S1(4,                                          "mae_interactivityMaxDistFactor");
1598         TEST_SB_END();
1599 
1600         TEST_SB_SKIP(                                           "mae_allowGainInteractivity");
1601             Skip_S1(6,                                          "mae_interactivityMinGain");
1602             Skip_S1(5,                                          "mae_interactivityMaxGain");
1603         TEST_SB_END();
1604 
1605         int8u mae_bsGroupNumMembers;
1606         Get_S1(7, mae_bsGroupNumMembers,                        "mae_bsGroupNumMembers");
1607         mae_bsGroupNumMembers++;
1608         G.MemberID.resize(mae_bsGroupNumMembers);
1609         TESTELSE_SB_SKIP(                                       "mae_hasConjunctMembers");
1610             int8u mae_startID;
1611             Get_S1 (7, mae_startID,                             "mae_startID");
1612             for (int8u Pos2=0; Pos2<mae_bsGroupNumMembers; Pos2++)
1613                 G.MemberID[Pos2]=mae_startID++;
1614         TESTELSE_SB_ELSE(                                       "mae_hasConjunctMembers");
1615             for (int8u Pos2=0; Pos2<mae_bsGroupNumMembers; Pos2++)
1616                 Get_S1 (7, G.MemberID[Pos2],                    "mae_metaDataElementID");
1617         TESTELSE_SB_END();
1618         Element_End0();
1619     }
1620     Element_End0();
1621 }
1622 
1623 //---------------------------------------------------------------------------
mae_SwitchGroupDefinition(int8u numSwitchGroups)1624 void File_Mpegh3da::mae_SwitchGroupDefinition(int8u numSwitchGroups)
1625 {
1626     Element_Begin1("mae_SwitchGroupDefinition");
1627     SwitchGroups.resize(numSwitchGroups);
1628     for(int8u Pos=0; Pos<numSwitchGroups; Pos++)
1629     {
1630         Element_Begin1("mae_switchGroup");
1631         switch_group& S=SwitchGroups[Pos];
1632         Get_S1 (5, S.ID,                                        "mae_switchGroupID");
1633         Element_Info1(Ztring::ToZtring(S.ID));
1634 
1635         TESTELSE_SB_GET(S.allowOnOff,                           "mae_switchGroupAllowOnOff");
1636             Get_SB (S.defaultOnOff,                             "mae_switchGroupDefaultOnOff");
1637         TESTELSE_SB_ELSE(                                       "mae_switchGroupAllowOnOff");
1638             S.defaultOnOff=false;
1639         TESTELSE_SB_END();
1640 
1641         int8u mae_bsSwitchGroupNumMembers;
1642         Get_S1(5, mae_bsSwitchGroupNumMembers,                  "mae_bsSwitchGroupNumMembers");
1643         mae_bsSwitchGroupNumMembers++;
1644         S.MemberID.resize(mae_bsSwitchGroupNumMembers);
1645         for (int8u Pos2=0; Pos2<mae_bsSwitchGroupNumMembers; Pos2++)
1646             Get_S1 (7, S.MemberID[Pos2],                        "mae_switchGroupMemberID");
1647 
1648         Get_S1 (7, S.DefaultGroupID,                            "mae_switchGroupDefaultGroupID");
1649         Element_End0();
1650     }
1651     Element_End0();
1652 }
1653 
1654 //---------------------------------------------------------------------------
mae_GroupPresetDefinition(int8u numGroupPresets)1655 void File_Mpegh3da::mae_GroupPresetDefinition(int8u numGroupPresets)
1656 {
1657     Element_Begin1("mae_GroupPresetDefinition");
1658     GroupPresets.resize(numGroupPresets);
1659     for (int8u Pos=0; Pos<numGroupPresets; Pos++)
1660     {
1661         Element_Begin1("mae_groupPreset");
1662         group_preset& P=GroupPresets[Pos];
1663         Get_S1 (5, P.ID,                                        "mae_groupPresetID");
1664         Element_Info1(Ztring::ToZtring(P.ID));
1665         Get_S1 (5, P.Kind,                                      "mae_groupPresetKind");
1666 
1667         int8u mae_bsGroupPresetNumConditions;
1668         Get_S1 (4, mae_bsGroupPresetNumConditions,              "mae_bsGroupPresetNumConditions");
1669         mae_bsGroupPresetNumConditions++;
1670         P.Conditions.resize(mae_bsGroupPresetNumConditions);
1671         for (int8u Pos2=0; Pos2<mae_bsGroupPresetNumConditions; Pos2++)
1672         {
1673             Element_Begin1("mae_groupPreset");
1674             Get_S1 (7, P.Conditions[Pos2].ReferenceID,          "mae_groupPresetReferenceID");
1675             Element_Info1(P.Conditions[Pos2].ReferenceID);
1676             TEST_SB_GET (P.Conditions[Pos2].ConditionOnOff,     "mae_groupPresetConditionOnOff");
1677                 Skip_SB(                                        "mae_groupPresetDisableGainInteractivity");
1678                 TEST_SB_SKIP(                                   "mae_groupPresetGainFlag");
1679                     Skip_S1(8,                                  "mae_groupPresetGain");
1680                 TEST_SB_END();
1681                 Skip_SB(                                        "mae_groupPresetDisablePositionInteractivity");
1682                 TEST_SB_SKIP(                                   "mae_groupPresetPositionFlag");
1683                     Skip_S1(8,                                  "mae_groupPresetAzOffset");
1684                     Skip_S1(6,                                  "mae_groupPresetElOffset");
1685                     Skip_S1(4,                                  "mae_groupPresetDistFactor");
1686                 TEST_SB_END();
1687             TEST_SB_END();
1688             Element_End0();
1689         }
1690         Element_End0();
1691     }
1692     Element_End0();
1693 }
1694 
1695 //---------------------------------------------------------------------------
mae_Data(int8u numGroups,int8u numGroupPresets)1696 void File_Mpegh3da::mae_Data(int8u numGroups, int8u numGroupPresets)
1697 {
1698     Element_Begin1("mae_Data");
1699     int8u mae_numDataSets;
1700     Get_S1(4, mae_numDataSets,                                  "mae_numDataSets");
1701     for (int8u Pos=0; Pos<mae_numDataSets; Pos++)
1702     {
1703         Element_Begin1("mae_data");
1704         int8u mae_dataType;
1705         Get_S1(4, mae_dataType,                                 "mae_dataType");
1706         int16u mae_dataLength;
1707         Get_S2(16, mae_dataLength,                              "mae_dataLength");
1708 
1709         size_t Remain_Before=BS->Remain();
1710         switch ((MaeDataType)mae_dataType)
1711         {
1712         case ID_MAE_GROUP_DESCRIPTION:
1713         case ID_MAE_SWITCHGROUP_DESCRIPTION:
1714         case ID_MAE_GROUP_PRESET_DESCRIPTION:
1715             mae_Description((MaeDataType)mae_dataType);
1716             break;
1717         case ID_MAE_GROUP_CONTENT:
1718             mae_ContentData();
1719             break;
1720         case ID_MAE_GROUP_COMPOSITE:
1721             mae_CompositePair();
1722             break;
1723         case ID_MAE_SCREEN_SIZE:
1724             mae_ProductionScreenSizeData();
1725             break;
1726         case ID_MAE_DRC_UI_INFO:
1727             mae_DrcUserInterfaceInfo(mae_dataLength);
1728             break;
1729         case ID_MAE_SCREEN_SIZE_EXTENSION:
1730             mae_ProductionScreenSizeDataExtension();
1731             break;
1732         case ID_MAE_GROUP_PRESET_EXTENSION:
1733             mae_GroupPresetDefinitionExtension(numGroupPresets);
1734             break;
1735         case ID_MAE_LOUDNESS_COMPENSATION:
1736             mae_LoudnessCompensationData(numGroups, numGroupPresets);
1737             break;
1738         default:
1739             Skip_BS(mae_dataLength*8,                           "reserved");
1740         }
1741         if (BS->Remain()+mae_dataLength*8>Remain_Before)
1742         {
1743             size_t Size=BS->Remain()+mae_dataLength*8-Remain_Before;
1744             int8u Padding=1;
1745             if (Size<8)
1746                 Peek_S1((int8u)Size, Padding);
1747 
1748             if (Padding)
1749                 Fill(Stream_Audio, 0, "NOK", "NOK", Unlimited, true, true);
1750             Skip_BS(Size, Padding?"(Unknown)":"Padding");
1751         }
1752         Element_End0();
1753     }
1754     Element_End0();
1755 }
1756 
1757 //---------------------------------------------------------------------------
mae_Description(MaeDataType type)1758 void File_Mpegh3da::mae_Description(MaeDataType type)
1759 {
1760     Element_Info1("mae_Description");
1761     Element_Begin1("mae_Description");
1762     int8u mae_bsNumDescriptionBlocks;
1763     Get_S1(7, mae_bsNumDescriptionBlocks,                       "mae_bsNumDescriptionBlocks");
1764     mae_bsNumDescriptionBlocks++;
1765     for (int8u Pos=0; Pos<mae_bsNumDescriptionBlocks; Pos++)
1766     {
1767         Element_Begin1("mae_descriptionGroup");
1768         int8u ID;
1769         switch (type)
1770         {
1771             case ID_MAE_GROUP_DESCRIPTION:
1772                 Get_S1 (7, ID,                                  "mae_descriptionGroupID");
1773                 break;
1774             case ID_MAE_SWITCHGROUP_DESCRIPTION:
1775                 Get_S1 (5, ID,                                  "mae_descriptionSwitchGroupID");
1776                 break;
1777             case ID_MAE_GROUP_PRESET_DESCRIPTION:
1778                 Get_S1 (5, ID,                                  "mae_descriptionGroupPresetID");
1779                 break;
1780             default:;
1781         }
1782         Element_Info1(ID);
1783 
1784         int8u mae_bsNumDescLanguages;
1785         Get_S1(4, mae_bsNumDescLanguages,                       "mae_bsNumDescLanguages");
1786         mae_bsNumDescLanguages++;
1787         for (int8u Pos2=0; Pos2<mae_bsNumDescLanguages; Pos2++)
1788         {
1789             Element_Begin1("mae_bsDescription");
1790             int32u mae_bsDescriptionLanguage;
1791             Get_S3 (24, mae_bsDescriptionLanguage,              "mae_bsDescriptionLanguage");
1792             string Language;
1793             for (int i=16; i>=0; i-=8)
1794             {
1795                 char LanguageChar=char(mae_bsDescriptionLanguage>>i);
1796                 if (LanguageChar)
1797                     Language+=LanguageChar;
1798             }
1799             Param_Info1(Language);
1800             Element_Info1(Language);
1801 
1802             int8u mae_bsDescriptionDataLength;
1803             Get_S1(8, mae_bsDescriptionDataLength,              "mae_bsDescriptionDataLength");
1804             mae_bsDescriptionDataLength++;
1805             string Description;
1806             Description.reserve(mae_bsDescriptionDataLength);
1807             for (int8u Pos3=0; Pos3<mae_bsDescriptionDataLength; Pos3++)
1808             {
1809                 int8u mae_descriptionData;
1810                 Get_S1 (8, mae_descriptionData,                 "mae_descriptionData");
1811                 Description+=(char)mae_descriptionData;
1812             }
1813             Param_Info1(Ztring().From_UTF8(Description));
1814             Element_Info1(Ztring().From_UTF8(Description));
1815             switch (type)
1816             {
1817                 case ID_MAE_GROUP_DESCRIPTION:
1818                     for (size_t i=0; i<Groups.size(); i++)
1819                         if (Groups[i].ID==ID)
1820                             Groups[i].Description[Language]=Description;
1821                     break;
1822                 case ID_MAE_SWITCHGROUP_DESCRIPTION:
1823                     for (size_t i=0; i<SwitchGroups.size(); i++)
1824                         if (SwitchGroups[i].ID==ID)
1825                             SwitchGroups[i].Description[Language]=Description;
1826                     break;
1827                 case ID_MAE_GROUP_PRESET_DESCRIPTION:
1828                     for (size_t i=0; i<GroupPresets.size(); i++)
1829                         if (GroupPresets[i].ID==ID)
1830                             GroupPresets[i].Description[Language]=Description;
1831                     break;
1832                 default: ;
1833             }
1834             Element_End0();
1835         }
1836         Element_End0();
1837     }
1838     Element_End0();
1839 }
1840 
1841 //---------------------------------------------------------------------------
mae_ContentData()1842 void File_Mpegh3da::mae_ContentData()
1843 {
1844     Element_Info1("mae_ContentData");
1845     Element_Begin1("mae_ContentData");
1846     int8u mae_bsNumContentDataBlocks;
1847     Get_S1(7, mae_bsNumContentDataBlocks,                       "mae_bsNumContentDataBlocks");
1848     for (int8u Pos=0; Pos<mae_bsNumContentDataBlocks+1; Pos++)
1849     {
1850         Element_Begin1("mae_ContentDataGroup");
1851         int8u ID, Kind;
1852         Get_S1 (7, ID,                                          "mae_ContentDataGroupID");
1853         Element_Info1(ID);
1854         Get_S1 (4, Kind,                                        "mae_contentKind");
1855         Param_Info1C(Kind<Mpegh3da_contentKind_Size, Mpegh3da_contentKind[Kind]);
1856         Element_Info1C(Kind<Mpegh3da_contentKind_Size, Mpegh3da_contentKind[Kind]);
1857         string Language;
1858         TEST_SB_SKIP(                                           "mae_hasContentLanguage");
1859             int32u mae_contentLanguage;
1860             Get_S3 (24, mae_contentLanguage,                    "mae_contentLanguage");
1861             for (int i=16; i>=0; i-=8)
1862             {
1863                 char LanguageChar=char(mae_contentLanguage>>i);
1864                 if (LanguageChar)
1865                     Language+=LanguageChar;
1866             }
1867             Param_Info1(Language);
1868             Element_Info1(Language);
1869             TEST_SB_END();
1870 
1871         for (size_t i=0; i<Groups.size(); i++)
1872             if (Groups[i].ID==ID)
1873             {
1874                 Groups[i].Language=Language;
1875                 Groups[i].Kind=Kind;
1876             }
1877         Element_End0();
1878     }
1879     Element_End0();
1880 }
1881 
1882 //---------------------------------------------------------------------------
mae_CompositePair()1883 void File_Mpegh3da::mae_CompositePair()
1884 {
1885     Element_Begin1("mae_CompositePair");
1886     int8u mae_bsNumCompositePairs;
1887     Get_S1(7, mae_bsNumCompositePairs,                          "mae_bsNumCompositePairs");
1888     for (int8u Pos=0; Pos<mae_bsNumCompositePairs+1; Pos++)
1889     {
1890         Skip_S1(7,                                              "mae_CompositeElementID0");
1891         Skip_S1(7,                                              "mae_CompositeElementID1");
1892     }
1893     Element_End0();
1894 }
1895 
1896 //---------------------------------------------------------------------------
mae_ProductionScreenSizeData()1897 void File_Mpegh3da::mae_ProductionScreenSizeData()
1898 {
1899     Element_Begin1("mae_ProductionScreenSizeData");
1900     TEST_SB_SKIP(                                               "hasNonStandardScreenSize");
1901         Skip_S2(9,                                              "bsScreenSizeAz");
1902         Skip_S2(9,                                              "bsScreenSizeTopEl");
1903         Skip_S2(9,                                              "bsScreenSizeBottomEl");
1904     TEST_SB_END();
1905     Element_End0();
1906 }
1907 
1908 //---------------------------------------------------------------------------
mae_DrcUserInterfaceInfo(int16u dataLength)1909 void File_Mpegh3da::mae_DrcUserInterfaceInfo(int16u dataLength)
1910 {
1911     Element_Begin1("mae_DrcUserInterfaceInfo");
1912     int8u version;
1913     Get_S1(2, version,                                          "version");
1914     if (version==0)
1915     {
1916         int8u bsNumTargetLoudnessConditions;
1917         Get_S1(3, bsNumTargetLoudnessConditions,                "bsNumTargetLoudnessConditions");
1918         int16u bsNumTargetLoudnessConditions_Real;
1919         if (dataLength>2)
1920             bsNumTargetLoudnessConditions_Real=(dataLength*8-(2+3))/(6+16);
1921         else
1922             bsNumTargetLoudnessConditions_Real=0;
1923         if (bsNumTargetLoudnessConditions!=bsNumTargetLoudnessConditions_Real)
1924             Param_Info1("Error");
1925         for (int16u Pos=0; Pos<bsNumTargetLoudnessConditions_Real; Pos++)
1926         {
1927             Skip_S1(6,                                          "bsTargetLoudnessValueUpper");
1928             Skip_S2(16,                                         "drcSetEffectAvailable");
1929         }
1930     }
1931     else
1932     {
1933         Skip_BS((dataLength-2)*8,                               "reserved");
1934     }
1935     Element_End0();
1936 }
1937 
1938 //---------------------------------------------------------------------------
mae_ProductionScreenSizeDataExtension()1939 void File_Mpegh3da::mae_ProductionScreenSizeDataExtension()
1940 {
1941     Element_Begin1("mae_ProductionScreenSizeDataExtension");
1942     TEST_SB_SKIP(                                               "mae_overwriteProductionScreenSizeData");
1943         Skip_S2(10,                                             "bsScreenSizeLeftAz");
1944         Skip_S2(10,                                             "bsScreenSizeRightAz");
1945     TEST_SB_END();
1946     int8u mae_NumPresetProductionScreens;
1947     Get_S1(5, mae_NumPresetProductionScreens,                   "mae_NumPresetProductionScreens");
1948     for (int8u Pos=0; Pos< mae_NumPresetProductionScreens; Pos++)
1949     {
1950         Skip_S1(5,                                              "mae_productionScreenGroupPresetID");
1951         TEST_SB_SKIP(                                           "mae_hasNonStandardScreenSize");
1952             TESTELSE_SB_SKIP(                                   "isCenteredInAzimuth");
1953                 Skip_S2(9,                                      "bsScreenSizeAz");
1954             TESTELSE_SB_ELSE(                                   "isCenteredInAzimuth");
1955                 Skip_S2(10,                                     "bsScreenSizeLeftAz");
1956                 Skip_S2(10,                                     "bsScreenSizeRightAz");
1957             TESTELSE_SB_END();
1958             Skip_S2(9,                                          "bsScreenSizeTopEl");
1959             Skip_S2(9,                                          "bsScreenSizeBottomEl");
1960         TEST_SB_END();
1961     }
1962     Element_End0();
1963 }
1964 
1965 
1966 //---------------------------------------------------------------------------
mae_GroupPresetDefinitionExtension(int8u numGroupPresets)1967 void File_Mpegh3da::mae_GroupPresetDefinitionExtension(int8u numGroupPresets)
1968 {
1969     Element_Begin1("mae_GroupPresetDefinitionExtension");
1970     for (int8u Pos=0; Pos<numGroupPresets; Pos++)
1971     {
1972         TEST_SB_SKIP(                                           "mae_hasSwitchGroupConditions");
1973             int8u Temp=Pos<GroupPresets.size()?GroupPresets[Pos].Conditions.size():0;
1974             for(int8u Pos2=0; Pos2<Temp; Pos2++)
1975                 Skip_SB(                                        "mae_isSwitchGroupCondition");
1976         TEST_SB_END();
1977 
1978         TEST_SB_SKIP(                                           "mae_hasDownmixIdGroupPresetExtensions");
1979             int8u mae_numDownmixIdGroupPresetExtensions;
1980             Get_S1(5, mae_numDownmixIdGroupPresetExtensions,    "mae_numDownmixIdGroupPresetExtensions");
1981             for (int8u Pos2=1; Pos2<mae_numDownmixIdGroupPresetExtensions+1; Pos2++)
1982             {
1983                 Skip_S1(7,                                      "mae_groupPresetDownmixId");
1984 
1985                 int8u mae_bsGroupPresetNumConditions;
1986                 Get_S1(4, mae_bsGroupPresetNumConditions,       "mae_bsGroupPresetNumConditions");
1987                 for (int8u Pos3=0; Pos3<mae_bsGroupPresetNumConditions+1; Pos3++)
1988                 {
1989                     TESTELSE_SB_SKIP(                           "mae_isSwitchGroupCondition");
1990                         Skip_S1(5,                              "mae_groupPresetSwitchGroupID");
1991                     TESTELSE_SB_ELSE(                           "mae_isSwitchGroupCondition");
1992                         Skip_S1(7,                              "mae_groupPresetGroupID");
1993                     TESTELSE_SB_END();
1994                     TEST_SB_SKIP(                               "mae_groupPresetConditionOnOff");
1995                         Skip_SB(                                "mae_groupPresetDisableGainInteractivity");
1996                         TEST_SB_SKIP(                           "mae_groupPresetGainFlag");
1997                             Skip_S1(8,                          "mae_groupPresetGain");
1998                         TEST_SB_END();
1999                         Skip_SB(                                "mae_groupPresetDisablePositionInteractivity");
2000                         TEST_SB_SKIP(                           "mae_groupPresetPositionFlag");
2001                             Skip_S1(8,                          "mae_groupPresetAzOffset");
2002                             Skip_S1(6,                          "mae_groupPresetElOffset");
2003                             Skip_S1(4,                          "mae_groupPresetDistFactor");
2004                         TEST_SB_END();
2005                     TEST_SB_END();
2006                 }
2007             }
2008         TEST_SB_END();
2009     }
2010     Element_End0();
2011 }
2012 
2013 //---------------------------------------------------------------------------
mae_LoudnessCompensationData(int8u numGroups,int8u numGroupPresets)2014 void File_Mpegh3da::mae_LoudnessCompensationData(int8u numGroups, int8u numGroupPresets)
2015 {
2016     Element_Begin1("mae_LoudnessCompensationData");
2017     TEST_SB_SKIP(                                               "mae_loudnessCompGroupLoudnessPresent");
2018         for (int8u Pos=0; Pos<numGroups; Pos++)
2019             Skip_S1(8,                                          "mae_bsLoudnessCompGroupLoudness");
2020     TEST_SB_END();
2021 
2022     TEST_SB_SKIP(                                               "mae_loudnessCompDefaultParamsPresent");
2023         for (int8u Pos=0; Pos<numGroups; Pos++)
2024             Skip_SB(                                            "mae_loudnessCompDefaultIncludeGroup");
2025 
2026         TEST_SB_SKIP(                                           "mae_loudnessCompDefaultMinMaxGainPresent");
2027             Skip_S1(4,                                          "mae_bsLoudnessCompDefaultMinGain");
2028             Skip_S1(4,                                          "mae_bsLoudnessCompDefaultMaxGain");
2029         TEST_SB_END();
2030     TEST_SB_END();
2031 
2032     for (int8u Pos=0; Pos<numGroupPresets; Pos++)
2033     {
2034         TEST_SB_SKIP(                                           "mae_loudnessCompPresetParamsPresent");
2035             for (int8u Pos2=0; Pos2<numGroups; Pos2++)
2036                 Skip_SB(                                        "mae_loudnessCompPresetIncludeGroup");
2037 
2038             TEST_SB_SKIP(                                       "mae_loudnessCompPresetMinMaxGainPresent");
2039                 Skip_S1(4,                                      "mae_bsLoudnessCompPresetMinGain");
2040                 Skip_S1(4,                                      "mae_bsLoudnessCompPresetMaxGain");
2041             TEST_SB_END();
2042         TEST_SB_END();
2043     }
2044     Element_End0();
2045 }
2046 
2047 //---------------------------------------------------------------------------
audioTruncationInfo()2048 void File_Mpegh3da::audioTruncationInfo()
2049 {
2050     Element_Begin1("audioTruncationInfo");
2051     BS_Begin();
2052     Skip_SB(                                                    "isActive");
2053     Skip_SB(                                                    "ati_reserved");
2054     Skip_SB(                                                    "truncFromBegin");
2055     Skip_S2(13,                                                 "nTruncSamples");
2056     BS_End();
2057     Element_End0();
2058 }
2059 
2060 //---------------------------------------------------------------------------
mhaC()2061 void File_Mpegh3da::mhaC()
2062 {
2063     Element_Begin1("MHADecoderConfigurationRecord");
2064     Skip_B1(                                                    "configurationVersion");
2065     Skip_B1(                                                    "mpegh3daProfileLevelIndication");
2066     Skip_B1(                                                    "referenceChannelLayout");
2067     Skip_B2(                                                    "mpegh3daConfigLength");
2068     mpegh3daConfig();
2069     Element_End0();
2070 }
2071 
2072 //***************************************************************************
2073 // Helpers
2074 //***************************************************************************
2075 
2076 //---------------------------------------------------------------------------
num_objects_Get()2077 size_t File_Mpegh3da::num_objects_Get()
2078 {
2079     size_t num_signals_InElements=0;
2080     for (size_t i=0; i<Elements.size(); i++)
2081         if (Elements[i].Type==ID_USAC_SCE || Elements[i].Type==ID_USAC_CPE)
2082             num_signals_InElements++;
2083     size_t num_signals_InSignals=0;
2084     for (size_t i=0; i<SignalGroups.size(); i++)
2085     {
2086         if (num_signals_InElements==num_signals_InSignals)
2087         {
2088             return SignalGroups[i].bsNumberOfSignals;
2089             break;
2090         }
2091         num_signals_InSignals+=SignalGroups[i].bsNumberOfSignals;
2092     }
2093 
2094     return 0; //Problem
2095 }
2096 
2097 
2098 //---------------------------------------------------------------------------
Streams_Fill_ChannelLayout(const string & Prefix,const speaker_layout & Layout,int8u speakerLayoutType)2099 void File_Mpegh3da::Streams_Fill_ChannelLayout(const string& Prefix, const speaker_layout& Layout, int8u speakerLayoutType)
2100 {
2101     if (Aac_Channels_Get(Layout.ChannelLayout))
2102     {
2103         Fill(Stream_Audio, 0, (Prefix+"Channel(s)").c_str(), Aac_Channels_GetString(Layout.ChannelLayout));
2104         if (!Prefix.empty())
2105             Fill_SetOptions(Stream_Audio, 0, (Prefix + "Channel(s)").c_str(), "N NTY");
2106         if (!Prefix.empty())
2107         {
2108             string ChannelString=MediaInfoLib::Config.Language_Get(Ztring().From_UTF8(Aac_Channels_GetString(Layout.ChannelLayout)), __T(" channel")).To_UTF8();
2109             string ChannelMode=Aac_ChannelMode_GetString(Layout.ChannelLayout, true);
2110             if (ChannelMode.size()>3 || (ChannelMode.size()==3 && ChannelMode[2]!='0'))
2111                 ChannelString+=" ("+Aac_ChannelMode_GetString(Layout.ChannelLayout, true)+")";
2112             Fill(Stream_Audio, 0, (Prefix+"Channel(s)/String").c_str(), ChannelString);
2113             Fill_SetOptions(Stream_Audio, 0, (Prefix + "Channel(s)/String").c_str(), "Y NTN");
2114         }
2115         Fill(Stream_Audio, 0, (Prefix+"ChannelPositions").c_str(), Aac_ChannelConfiguration_GetString(Layout.ChannelLayout));
2116         if (!Prefix.empty())
2117             Fill_SetOptions(Stream_Audio, 0, (Prefix+"ChannelPositions").c_str(), "N YTY");
2118         Fill(Stream_Audio, 0, (Prefix+"ChannelPositions/String2").c_str(), Aac_ChannelConfiguration2_GetString(Layout.ChannelLayout));
2119         if (!Prefix.empty())
2120             Fill_SetOptions(Stream_Audio, 0, (Prefix+"ChannelPositions/String2").c_str(), "N YTY");
2121         Fill(Stream_Audio, 0, (Prefix+"ChannelMode").c_str(), Aac_ChannelMode_GetString(Layout.ChannelLayout, true));
2122         Fill_SetOptions(Stream_Audio, 0, (Prefix+"ChannelMode").c_str(), "N NTY");
2123         Fill(Stream_Audio, 0, (Prefix+"ChannelLayout").c_str(), Aac_ChannelLayout_GetString(Layout.ChannelLayout, true));
2124     }
2125     else if (Layout.numSpeakers)
2126     {
2127         if (speakerLayoutType==1) // Objects
2128         {
2129             Fill(Stream_Audio, 0, (Prefix+"NumberOfObjects").c_str(), Layout.numSpeakers);
2130             Fill_SetOptions(Stream_Audio, 0, (Prefix+"NumberOfObjects").c_str(), "N YTY");
2131             Fill(Stream_Audio, 0, (Prefix + "NumberOfObjects/String").c_str(), MediaInfoLib::Config.Language_Get(Ztring::ToZtring(Layout.numSpeakers), __T(" object")));
2132             Fill_SetOptions(Stream_Audio, 0, (Prefix+"NumberOfObjects/String").c_str(), "Y YTN");
2133         }
2134         else
2135         {
2136             Fill(Stream_Audio, 0, (Prefix+"Channel(s)").c_str(), Layout.numSpeakers);
2137             Fill_SetOptions(Stream_Audio, 0, (Prefix+"Channel(s)").c_str(), "N YTY");
2138             Fill(Stream_Audio, 0, (Prefix + "Channel(s)/String").c_str(), MediaInfoLib::Config.Language_Get(Ztring::ToZtring(Layout.numSpeakers), __T(" channel")));
2139             Fill_SetOptions(Stream_Audio, 0, (Prefix+"Channel(s)/String").c_str(), "Y YTN");
2140         }
2141         if (!Layout.CICPspeakerIdxs.empty())
2142         {
2143             Fill(Stream_Audio, 0, (Prefix+"ChannelMode").c_str(), Aac_ChannelMode_GetString(Layout.CICPspeakerIdxs));
2144             Fill(Stream_Audio, 0, (Prefix+"ChannelLayout").c_str(), Aac_ChannelLayout_GetString(Layout.CICPspeakerIdxs));
2145         }
2146         else
2147         {
2148             vector<Aac_OutputChannel> CICPspeakerIdxs;
2149             string ChannelLayout;
2150             for (size_t i=0; i<Layout.SpeakersInfo.size(); i++)
2151             {
2152                 if (i)
2153                     ChannelLayout+=' ';
2154                 if (Layout.SpeakersInfo[i].CICPspeakerIdx!=(Aac_OutputChannel)-1)
2155                 {
2156                     ChannelLayout+=Aac_ChannelLayout_GetString(&Layout.SpeakersInfo[i].CICPspeakerIdx, 1);
2157                     CICPspeakerIdxs.push_back(Layout.SpeakersInfo[i].CICPspeakerIdx);
2158                 }
2159                 else
2160                 {
2161                     if (Layout.SpeakersInfo[i].ElevationAngle==0)
2162                         ChannelLayout+='M';
2163                     else
2164                         ChannelLayout+=Layout.SpeakersInfo[i].ElevationDirection?'B':'U';
2165                     ChannelLayout+='_';
2166                     if (Layout.SpeakersInfo[i].AzimuthAngle!=0 && Layout.SpeakersInfo[i].AzimuthAngle!=180)
2167                         ChannelLayout+=Layout.SpeakersInfo[i].AzimuthDirection?'L':'R';
2168                     string AzimuthAngleString=Ztring::ToZtring(Layout.SpeakersInfo[i].AzimuthAngle).To_UTF8();
2169                     AzimuthAngleString.insert(0, 3-AzimuthAngleString.size(), '0');
2170                     ChannelLayout.append(AzimuthAngleString);
2171                 }
2172             }
2173             if (CICPspeakerIdxs.size()==Layout.SpeakersInfo.size())
2174             {
2175                 Fill(Stream_Audio, 0, (Prefix+"ChannelMode").c_str(), Aac_ChannelMode_GetString(CICPspeakerIdxs));
2176                 Fill(Stream_Audio, 0, (Prefix+"ChannelLayout").c_str(), Aac_ChannelLayout_GetString(CICPspeakerIdxs));
2177             }
2178             else
2179                 Fill(Stream_Audio, 0, (Prefix+"ChannelLayout").c_str(), ChannelLayout);
2180         }
2181     }
2182     else if (Layout.ChannelLayout)
2183     {
2184         Fill(Stream_Audio, 0, (Prefix+"ChannelLayout").c_str(), Layout.ChannelLayout);
2185     }
2186 }
2187 
2188 //***************************************************************************
2189 // C++
2190 //***************************************************************************
2191 
2192 } //NameSpace
2193 
2194 #endif //MEDIAINFO_MPEGH3DA_YES
2195 
2196