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 #include "MediaInfo/MediaInfo_Internal.h"
21 #include "MediaInfo/MediaInfo_Config.h"
22 #include "MediaInfo/File__Analyze.h"
23 #include "MediaInfo/File__MultipleParsing.h"
24 #if defined(MEDIAINFO_FILE_YES)
25 #include "ZenLib/File.h"
26 #endif //defined(MEDIAINFO_DIRECTORY_YES)
27 #if defined(MEDIAINFO_DIRECTORY_YES)
28 #include "ZenLib/Dir.h"
29 #endif //defined(MEDIAINFO_DIRECTORY_YES)
30 #include "ZenLib/FileName.h"
31 #if defined(MEDIAINFO_DIRECTORY_YES)
32     #include "MediaInfo/Reader/Reader_Directory.h"
33 #endif
34 #if defined(MEDIAINFO_FILE_YES)
35     #include "MediaInfo/Reader/Reader_File.h"
36 #endif
37 #if defined(MEDIAINFO_LIBCURL_YES)
38     #include "MediaInfo/Reader/Reader_libcurl.h"
39 #endif
40 #if defined(MEDIAINFO_LIBMMS_YES)
41     #include "MediaInfo/Reader/Reader_libmms.h"
42 #endif
43 #if defined(MEDIAINFO_IBI_YES)
44     #include "MediaInfo/Multiple/File_Ibi.h"
45 #endif
46 #include "MediaInfo/Multiple/File_Dxw.h"
47 #ifdef MEDIAINFO_COMPRESS
48     #include "ThirdParty/base64/base64.h"
49     #include "zlib.h"
50 #endif //MEDIAINFO_COMPRESS
51 #include <cmath>
52 #ifdef MEDIAINFO_DEBUG_WARNING_GET
53     #include <iostream>
54 #endif //MEDIAINFO_DEBUG_WARNING_GET
55 #ifdef MEDIAINFO_DEBUG_BUFFER
56     #include "ZenLib/FileName.h"
57     #include <cstring>
58 #endif //MEDIAINFO_DEBUG_BUFFER
59 #if MEDIAINFO_ADVANCED
60     #include <iostream>
61     #if defined(WINDOWS) && !defined(WINDOWS_UWP) && !defined(__BORLANDC__)
62         #include <fcntl.h>
63         #include <io.h>
64     #endif //defined(WINDOWS) && !defined(WINDOWS_UWP) && !defined(__BORLANDC__)
65 #endif //MEDIAINFO_ADVANCED
66 #if MEDIAINFO_ADVANCED && defined(MEDIAINFO_FILE_YES)
67     #include <limits>
68     #ifdef WINDOWS
69     namespace WindowsNamespace
70     {
71         #include <windows.h>
72         #undef Yield
73         #undef max
74     }
75     #elif defined(_POSIX_PRIORITY_SCHEDULING)
76         #include <sched.h>
77         #include <unistd.h>
78         #include <signal.h>
79     #endif //_POSIX_PRIORITY_SCHEDULING
80     #include <ctime>
81 #endif
82 using namespace ZenLib;
83 using namespace std;
84 //---------------------------------------------------------------------------
85 
86 namespace MediaInfoLib
87 {
88 
89 //---------------------------------------------------------------------------
90 //To clarify the code
91 namespace MediaInfo_Debug_MediaInfo_Internal
92 {
93 
94 #if defined (MEDIAINFO_DEBUG_CONFIG) || defined (MEDIAINFO_DEBUG_BUFFER) || defined (MEDIAINFO_DEBUG_OUTPUT)
95     #ifdef WINDOWS
96         const Char* MediaInfo_Debug_Name=__T("MediaInfo_Debug");
97     #else
98         const Char* MediaInfo_Debug_Name=__T("/tmp/MediaInfo_Debug");
99     #endif
100 #endif
101 
102 #ifdef MEDIAINFO_DEBUG_CONFIG
103     #define MEDIAINFO_DEBUG_CONFIG_TEXT(_TOAPPEND) \
104         { \
105             Ztring Debug; \
106             _TOAPPEND; \
107             Debug+=__T("\r\n"); \
108             if (!Debug_Config.Opened_Get()) \
109             { \
110                 if (Config.File_Names.empty()) \
111                     Debug_Config.Create(Ztring(MediaInfo_Debug_Name)+__T(".")+Ztring::ToZtring((size_t)this, 16)+__T(".Config.txt")); \
112                 else \
113                 { \
114                     Ztring File_Temp; \
115                     if (Config.File_Names[0].rfind(__T('\\'))!=string::npos) \
116                         File_Temp=Config.File_Names[0].substr(Config.File_Names[0].rfind(__T('\\'))+1, string::npos); \
117                     else if (Config.File_Names[0].rfind(__T('/'))!=string::npos) \
118                         File_Temp=Config.File_Names[0].substr(Config.File_Names[0].rfind(__T('/'))+1, string::npos); \
119                     else \
120                         File_Temp=Config.File_Names[0]; \
121                     Debug_Config.Create(Ztring(MediaInfo_Debug_Name)+__T(".")+Ztring::ToZtring((size_t)this, 16)+__T(".")+File_Temp+__T(".Config.txt")); \
122                 } \
123             } \
124             Debug_Config.Write(Debug); \
125         }
126 #else // MEDIAINFO_DEBUG_CONFIG
127     #define MEDIAINFO_DEBUG_CONFIG_TEXT(_TOAPPEND)
128 #endif // MEDIAINFO_DEBUG_CONFIG
129 
130 #ifdef MEDIAINFO_DEBUG_CONFIG
131     #define EXECUTE_SIZE_T(_METHOD,_DEBUGB) \
132         { \
133             size_t ToReturn=_METHOD; \
134             MEDIAINFO_DEBUG_CONFIG_TEXT(_DEBUGB) \
135             return ToReturn; \
136         }
137 #else //MEDIAINFO_DEBUG_CONFIG
138     #define EXECUTE_SIZE_T(_METHOD, _DEBUGB) \
139         return _METHOD;
140 #endif //MEDIAINFO_DEBUG_CONFIG
141 
142 #ifdef MEDIAINFO_DEBUG_CONFIG
143     #define EXECUTE_INT64U(_METHOD,_DEBUGB) \
144         { \
145             int64u ToReturn=_METHOD; \
146             MEDIAINFO_DEBUG_CONFIG_TEXT(_DEBUGB) \
147             return ToReturn; \
148         }
149 #else //MEDIAINFO_DEBUG_CONFIG
150     #define EXECUTE_INT64U(_METHOD, _DEBUGB) \
151         return _METHOD;
152 #endif //MEDIAINFO_DEBUG_CONFIG
153 
154 #ifdef MEDIAINFO_DEBUG_CONFIG
155     #define EXECUTE_STRING(_METHOD,_DEBUGB) \
156         { \
157             Ztring ToReturn=_METHOD; \
158             MEDIAINFO_DEBUG_CONFIG_TEXT(_DEBUGB) \
159             return ToReturn; \
160         }
161 #else //MEDIAINFO_DEBUG_CONFIG
162     #define EXECUTE_STRING(_METHOD,_DEBUGB) \
163         return _METHOD;
164 #endif //MEDIAINFO_DEBUG_CONFIG
165 
166 #ifdef MEDIAINFO_DEBUG_BUFFER
167     #define MEDIAINFO_DEBUG_BUFFER_SAVE(_BUFFER, _SIZE) \
168         { \
169             if (!Debug_Buffer_Stream.Opened_Get()) \
170             { \
171                 if (Config.File_Names.empty()) \
172                     Debug_Buffer_Stream.Create(Ztring(MediaInfo_Debug_Name)+__T(".")+Ztring::ToZtring((size_t)this, 16)+__T(".Buffer.Stream.0000000000000000")); \
173                 else \
174                 { \
175                     Ztring File_Temp; \
176                     if (Config.File_Names[0].rfind(__T('\\'))!=string::npos) \
177                         File_Temp=Config.File_Names[0].substr(Config.File_Names[0].rfind(__T('\\'))+1, string::npos); \
178                     else if (Config.File_Names[0].rfind(__T('/'))!=string::npos) \
179                         File_Temp=Config.File_Names[0].substr(Config.File_Names[0].rfind(__T('/'))+1, string::npos); \
180                     else \
181                         File_Temp=Config.File_Names[0]; \
182                     Debug_Buffer_Stream.Create(Ztring(MediaInfo_Debug_Name)+__T(".")+Ztring::ToZtring((size_t)this, 16)+__T(".")+File_Temp+__T(".Buffer.Stream.0000000000000000")); \
183                 } \
184                 Debug_Buffer_Stream_Order=0; \
185                 if (Config.File_Names.empty()) \
186                     Debug_Buffer_Sizes.Create(Ztring(MediaInfo_Debug_Name)+__T(".")+Ztring::ToZtring((size_t)this, 16)+__T(".Buffer.Sizes.0000000000000000")); \
187                 else \
188                 { \
189                     Ztring File_Temp; \
190                     if (Config.File_Names[0].rfind(__T('\\'))!=string::npos) \
191                         File_Temp=Config.File_Names[0].substr(Config.File_Names[0].rfind(__T('\\'))+1, string::npos); \
192                     else if (Config.File_Names[0].rfind(__T('/'))!=string::npos) \
193                         File_Temp=Config.File_Names[0].substr(Config.File_Names[0].rfind(__T('/'))+1, string::npos); \
194                     else \
195                         File_Temp=Config.File_Names[0]; \
196                     Debug_Buffer_Sizes.Create(Ztring(MediaInfo_Debug_Name)+__T(".")+Ztring::ToZtring((size_t)this, 16)+__T(".")+File_Temp+__T(".Buffer.Sizes.0000000000000000")); \
197                 } \
198                 Debug_Buffer_Sizes_Count=0; \
199             } \
200             Debug_Buffer_Stream.Write(_BUFFER, _SIZE); \
201             Debug_Buffer_Sizes.Write((int8u*)&_SIZE, sizeof(size_t)); \
202             Debug_Buffer_Sizes_Count+=_SIZE; \
203             if (Debug_Buffer_Sizes_Count>=MEDIAINFO_DEBUG_BUFFER_SAVE_FileSize) \
204             { \
205                 Debug_Buffer_Stream.Close(); \
206                 Debug_Buffer_Sizes.Close(); \
207                 Ztring Before=Ztring::ToZtring(Debug_Buffer_Stream_Order-1); \
208                 while (Before.size()<16) \
209                     Before.insert(0, 1, __T('0')); \
210                 Ztring Next=Ztring::ToZtring(Debug_Buffer_Stream_Order+1); \
211                 while (Next.size()<16) \
212                     Next.insert(0, 1, __T('0')); \
213                 Debug_Buffer_Stream.Create(Ztring(MediaInfo_Debug_Name)+__T(".")+Ztring::ToZtring((size_t)this, 16)+__T(".Buffer.Stream.")+Next); \
214                 Debug_Buffer_Sizes.Create(Ztring(MediaInfo_Debug_Name)+__T(".")+Ztring::ToZtring((size_t)this, 16)+__T(".Buffer.Sizes.")+Next); \
215                 File::Delete(Ztring(MediaInfo_Debug_Name)+__T(".")+Ztring::ToZtring((size_t)this, 16)+__T(".Buffer.Stream.")+Before); \
216                 File::Delete(Ztring(MediaInfo_Debug_Name)+__T(".")+Ztring::ToZtring((size_t)this, 16)+__T(".Buffer.Sizes.")+Before); \
217                 Debug_Buffer_Stream_Order++; \
218                 Debug_Buffer_Sizes_Count=0; \
219             } \
220         }
221 #else // MEDIAINFO_DEBUG_BUFFER
222     #define MEDIAINFO_DEBUG_BUFFER_SAVE(_BUFFER, _SIZE)
223 #endif // MEDIAINFO_DEBUG_BUFFER
224 
225 #ifdef MEDIAINFO_DEBUG_OUTPUT
226     #define MEDIAINFO_DEBUG_OUTPUT_INIT(_VALUE, _DEBUGB) \
227         { \
228             if (OptionLower==__T("file_duplicate")) \
229             { \
230                 size_t Pos=(size_t)ToReturn2.To_int64u(); \
231                 if (Pos>=Debug_Output_Pos_Stream.size()) \
232                 { \
233                     Debug_Output_Pos_Stream.resize(Pos+1); \
234                     Debug_Output_Pos_Stream[Pos]=new File(); \
235                     Debug_Output_Pos_Sizes.resize(Pos+1); \
236                     Debug_Output_Pos_Sizes[Pos]=new File(); \
237                     Debug_Output_Pos_Pointer.resize(Pos+1); \
238                     Debug_Output_Pos_Pointer[Pos]=(void*)Ztring(Value).SubString(__T("memory://"), __T(":")).To_int64u(); \
239                 } \
240             } \
241             EXECUTE_STRING(_VALUE, _DEBUGB) \
242         }
243 #else // MEDIAINFO_DEBUG_OUTPUT
244     #define MEDIAINFO_DEBUG_OUTPUT_INIT(_VALUE, _DEBUGB) \
245         EXECUTE_STRING(_VALUE, _DEBUGB)
246 #endif // MEDIAINFO_DEBUG_OUTPUT
247 
248 #ifdef MEDIAINFO_DEBUG_OUTPUT
249     #define MEDIAINFO_DEBUG_OUTPUT_VALUE(_VALUE, _METHOD) \
250         { \
251             size_t ByteCount=Info->Output_Buffer_Get(Value); \
252             void* ValueH=(void*)Ztring(Value).SubString(__T("memory://"), __T(":")).To_int64u(); \
253             map<void*, File>::iterator F_Stream=Debug_Output_Value_Stream.find(ValueH); \
254             if (F_Stream!=Debug_Output_Value_Stream.end()) \
255             { \
256                 map<void*, File>::iterator F_Sizes=Debug_Output_Value_Stream.find(ValueH); \
257                 if (!F_Stream->second.Opened_Get()) \
258                 { \
259                     F_Stream->second.Create(Ztring(MediaInfo_Debug_Name)+__T(".")+Ztring::ToZtring((size_t)this, 16)+__T(".Output.")+Ztring::ToZtring((size_t)ValueH, 16)+__T(".Stream")); \
260                     F_Sizes->second.Create(Ztring(MediaInfo_Debug_Name)+__T(".")+Ztring::ToZtring((size_t)this, 16)+__T(".Output.")+Ztring::ToZtring((size_t)ValueH, 16)+__T(".Sizes")); \
261                 } \
262                 F_Stream->second.Write((int8u*)ValueH, ByteCount); \
263                 F_Sizes->second.Write((int8u*)&ByteCount, sizeof(ByteCount)); \
264             } \
265             return ByteCount; \
266         }
267 #else // MEDIAINFO_DEBUG_OUTPUT
268     #define MEDIAINFO_DEBUG_OUTPUT_VALUE(_VALUE, _METHOD) \
269         return _METHOD
270 #endif // MEDIAINFO_DEBUG_OUTPUT
271 
272 #ifdef MEDIAINFO_DEBUG_OUTPUT
273     #define MEDIAINFO_DEBUG_OUTPUT_POS(_POS, _METHOD) \
274         { \
275             size_t ByteCount=Info->Output_Buffer_Get(_POS); \
276             if (_POS<Debug_Output_Pos_Stream.size()) \
277             { \
278                 if (!Debug_Output_Pos_Stream[_POS]->Opened_Get()) \
279                 { \
280                     Debug_Output_Pos_Stream[_POS]->Create(Ztring(MediaInfo_Debug_Name)+__T(".")+Ztring::ToZtring((size_t)this, 16)+__T(".Output.")+Ztring::ToZtring(Pos, 16)+__T(".Stream")); \
281                     Debug_Output_Pos_Sizes[_POS]->Create(Ztring(MediaInfo_Debug_Name)+__T(".")+Ztring::ToZtring((size_t)this, 16)+__T(".Output.")+Ztring::ToZtring(Pos, 16)+__T(".Sizes")); \
282                 } \
283                 Debug_Output_Pos_Stream[_POS]->Write((int8u*)Debug_Output_Pos_Pointer[_POS], ByteCount); \
284                 Debug_Output_Pos_Sizes[_POS]->Write((int8u*)&ByteCount, sizeof(ByteCount)); \
285             } \
286             return ByteCount; \
287         }
288 #else // MEDIAINFO_DEBUG_OUTPUT
289     #define MEDIAINFO_DEBUG_OUTPUT_POS(_VALUE, _METHOD) \
290         return _METHOD
291 #endif // MEDIAINFO_DEBUG_OUTPUT
292 
293 }
294 using namespace MediaInfo_Debug_MediaInfo_Internal;
295 
296 Ztring File__Analyze_Encoded_Library_String(const Ztring &CompanyName, const Ztring &Name, const Ztring &Version, const Ztring &Date, const Ztring &Encoded_Library);
297 
298 extern const Char* MediaInfo_Version;
299 
300 //***************************************************************************
301 // Modifiers - ChannelLayout_2018
302 //***************************************************************************
303 static const size_t ChannelLayout_2018_Size=63;
304 static const char* ChannelLayout_2018[ChannelLayout_2018_Size][2] =
305 {
306     { "BC", "Cb" },
307     { "BL", "Lb" },
308     { "BR", "Rb" },
309     { "CI", "Bfc" },
310     { "CL", "Ls" },
311     { "CR", "Rs" },
312     { "Ch", "Tfc" },
313     { "Chr", "Tbc" },
314     { "Cl", "Ls" },
315     { "Cr", "Rs" },
316     { "Cs", "Cb" },
317     { "Cv", "Tfc" },
318     { "Cvr", "Tbc" },
319     { "FC", "C" },
320     { "FL", "L" },
321     { "FLC", "Lscr" },
322     { "FR", "R" },
323     { "FRC", "Rscr" },
324     { "LI", "Bfl" },
325     { "Lc", "Lscr" },
326     { "Lfh", "Tfl" },
327     { "Lh", "Vhl" },
328     { "Lhr", "Tbl" },
329     { "Lhs", "Tfl" },
330     { "Lrh", "Tbl" },
331     { "Lrs", "Lb" },
332     { "Lsc", "Lscr" },
333     { "Lsr", "Lb" },
334     { "Ltm", "Tsl" },
335     { "Lts", "Tsl" },
336     { "Lv", "Tfl" },
337     { "Lvh", "Tfl" },
338     { "Lvr", "Tbl" },
339     { "Lvss", "Tll" },
340     { "Oh", "Tc" },
341     { "Rc", "Rscr" },
342     { "Rfh", "Tfrr" },
343     { "Rh", "Vhr" },
344     { "Rhr", "Tbr" },
345     { "Rhs", "Tfr" },
346     { "RI", "Bfr" },
347     { "Rrh", "Tbr" },
348     { "Rrs", "Rb" },
349     { "Rsc", "Rscr" },
350     { "Rsr", "Rb" },
351     { "Rtm", "Tsr" },
352     { "Rts", "Tsr" },
353     { "Rv", "Tfr" },
354     { "Rvh", "Tfr" },
355     { "Rvr", "Tbr" },
356     { "Rvss", "Tsr" },
357     { "S", "Cb" },
358     { "SL", "Ls" },
359     { "SR", "Rs" },
360     { "TBC", "Tbc" },
361     { "TBL", "Tbl" },
362     { "TBR", "Tbr" },
363     { "TC", "Tc" },
364     { "TFC", "Tfc" },
365     { "TFL", "Tfl" },
366     { "TFR", "Tfr" },
367     { "Ts", "Tc" },
368     { "Vhc", "Tfc" },
369 };
370 static const size_t ChannelLayout_2018_Aac_Size=3;
371 static const char* ChannelLayout_2018_Aac[ChannelLayout_2018_Aac_Size][2] =
372 {
373     { "Cb", "Bfc" },
374     { "Lb", "Bfl" },
375     { "Rb", "Bfr" },
376 };
ChannelLayout_2018_Rename(const Ztring & Channels,const Ztring & Format)377 Ztring ChannelLayout_2018_Rename(const Ztring& Channels, const Ztring& Format)
378 {
379     ZtringList List;
380     List.Separator_Set(0, __T(" "));
381     List.Write(Channels);
382     size_t LfePos[3];
383     memset(LfePos, -1, sizeof(LfePos));
384     bool IsAac=(Format==__T("USAC") || Format==__T("MPEG-H 3D Audio"));
385     for (size_t i=0; i<List.size(); i++)
386     {
387         Ztring& ChannelName=List[i];
388         string ChannelNameS=ChannelName.To_UTF8();
389         for (size_t j=0; j<ChannelLayout_2018_Size; j++)
390             if (!strcmp(ChannelNameS.c_str(), ChannelLayout_2018[j][0]))
391                 ChannelName.From_UTF8(ChannelLayout_2018[j][1]);
392         if (IsAac)
393         {
394             for (size_t j=0; j< ChannelLayout_2018_Aac_Size; j++)
395                 if (!strcmp(ChannelNameS.c_str(), ChannelLayout_2018_Aac[j][0]))
396                     ChannelName.From_UTF8(ChannelLayout_2018_Aac[j][1]);
397             if (ChannelNameS.size()>=3 && ChannelNameS[0]=='L' && ChannelNameS[1]=='F' && ChannelNameS[2]=='E')
398             {
399                 if (LfePos[0] && ChannelNameS.size()==3)
400                     LfePos[0]=i;
401                 if (LfePos[1] && ChannelNameS.size()==4 && ChannelNameS[3]==__T('2'))
402                     LfePos[1]=i;
403                 if (LfePos[2] && ChannelNameS.size()==4 && ChannelNameS[3]==__T('3'))
404                     LfePos[2]=i;
405             }
406         }
407     }
408     if (LfePos[0]==(size_t)-1 && LfePos[1]!=(size_t)-1 && LfePos[2]!=(size_t)-1)
409     {
410         List[LfePos[1]].resize(3); // LFE2 --> LFE
411         List[LfePos[2]][3]--; // LFE3 --> LFE2
412     }
413     Ztring ToReturn=List.Read();
414     return ToReturn;
415 }
ChannelLayout_2018_Rename(stream_t StreamKind,size_t Parameter,ZtringList & Info,const Ztring & StreamFormat,bool & ShouldReturn)416 Ztring ChannelLayout_2018_Rename(stream_t StreamKind, size_t Parameter, ZtringList& Info, const Ztring& StreamFormat, bool &ShouldReturn)
417 {
418     bool ShouldReturn_Save=ShouldReturn;
419     ShouldReturn=true;
420     switch (StreamKind)
421     {
422         case Stream_Audio:
423             switch (Parameter)
424             {
425                 case Audio_ChannelLayout: return ChannelLayout_2018_Rename(Info[Parameter], StreamFormat);
426                 default:;
427             }
428             break;
429         default:;
430     }
431     ShouldReturn=ShouldReturn_Save;
432     return Info[Parameter];
433 }
ChannelLayout_2018_Rename(stream_t StreamKind,const Ztring & Parameter,const Ztring & Value,const Ztring & StreamFormat,bool & ShouldReturn)434 Ztring ChannelLayout_2018_Rename(stream_t StreamKind, const Ztring& Parameter, const Ztring& Value, const Ztring& StreamFormat, bool &ShouldReturn)
435 {
436     bool ShouldReturn_Save=ShouldReturn;
437     ShouldReturn=true;
438     if (StreamKind==Stream_Audio && (Parameter==__T("BedChannelConfiguration") || (Parameter.size()>=14 && Parameter.find(__T(" ChannelLayout"), Parameter.size()-14)!=string::npos)))
439         return ChannelLayout_2018_Rename(Value, StreamFormat);
440     if (StreamKind==Stream_Audio)
441     {
442         size_t ObjectPos=Parameter.find(__T("Object"));
443         if (ObjectPos!=string::npos)
444         {
445             bool NoRename=false;
446             if (ObjectPos && !(Parameter[ObjectPos-1]==__T(' ')))
447                 NoRename=true;
448             if (ObjectPos+6>=Parameter.size() || !(Parameter[ObjectPos+6]>=__T('0') && Parameter[ObjectPos+6]<=__T('9')))
449                 NoRename=true;
450             if (!NoRename)
451             {
452                 size_t SpacePos=Parameter.find(__T(' '), ObjectPos);
453                 if (SpacePos==string::npos)
454                     return ChannelLayout_2018_Rename(Value, StreamFormat);
455             }
456         }
457         size_t AltPos=Parameter.find(__T("Alt"));
458         if (AltPos!=string::npos)
459         {
460             bool NoRename=false;
461             if (AltPos && !(Parameter[AltPos-1]==__T(' ')))
462                 NoRename=true;
463             if (AltPos+3>=Parameter.size() || !(Parameter[AltPos+3]>=__T('0') && Parameter[AltPos+3]<=__T('9')))
464                 NoRename=true;
465             if (!NoRename)
466             {
467                 size_t SpacePos=Parameter.find(__T(' '), AltPos);
468                 if (SpacePos==string::npos)
469                     return ChannelLayout_2018_Rename(Value, StreamFormat);
470             }
471         }
472         size_t BedPos=Parameter.find(__T("Bed"));
473         if (BedPos!=string::npos)
474         {
475             bool NoRename=false;
476             if (BedPos && !(Parameter[BedPos-1]==__T(' ')))
477                 NoRename=true;
478             if (BedPos+3>=Parameter.size() || !(Parameter[BedPos+3]>=__T('0') && Parameter[BedPos+3]<=__T('9')))
479                 NoRename=true;
480             if (!NoRename)
481             {
482                 size_t SpacePos=Parameter.find(__T(' '), BedPos);
483                 if (SpacePos==string::npos)
484                     return ChannelLayout_2018_Rename(Value, StreamFormat);
485             }
486         }
487     }
488     ShouldReturn=ShouldReturn_Save;
489     return Value;
490 }
491 
492 //***************************************************************************
493 // Modifiers - Highest format
494 //***************************************************************************
HighestFormat(stream_t StreamKind,size_t Parameter,const ZtringList & Info,bool & ShouldReturn)495 Ztring HighestFormat(stream_t StreamKind, size_t Parameter, const ZtringList& Info, bool &ShouldReturn)
496 {
497     if (Parameter>=Info.size())
498         return Ztring();
499 
500     size_t Parameter_Generic;
501     switch (StreamKind)
502     {
503         case Stream_Audio:
504             switch (Parameter)
505             {
506                 case Audio_Format: Parameter_Generic=Generic_Format; break;
507                 case Audio_Format_String: Parameter_Generic=Generic_Format_String; break;
508                 case Audio_Format_Profile: Parameter_Generic=Generic_Format_Profile; break;
509                 case Audio_Format_Level: Parameter_Generic=Generic_Format_Level; break;
510                 case Audio_Format_Info: Parameter_Generic=Generic_Format_Info; break;
511                 case Audio_Format_AdditionalFeatures: Parameter_Generic=Generic_Format_AdditionalFeatures; break;
512                 case Audio_Format_Commercial: Parameter_Generic=Generic_Format_Commercial; break;
513                 case Audio_Format_Commercial_IfAny: Parameter_Generic=Generic_Format_Commercial_IfAny; break;
514                 default: return Ztring();
515             }
516             break;
517         case Stream_General:
518             switch (Parameter)
519             {
520                 case General_Format: Parameter_Generic=Generic_Format; break;
521                 case General_Format_String: Parameter_Generic=Generic_Format_String; break;
522                 case General_Format_Profile: Parameter_Generic=Generic_Format_Profile; break;
523                 case General_Format_Info: Parameter_Generic=Generic_Format_Info; break;
524                 case General_Format_AdditionalFeatures: Parameter_Generic=Generic_Format_AdditionalFeatures; break;
525                 case General_Format_Commercial: Parameter_Generic=Generic_Format_Commercial; break;
526                 case General_Format_Commercial_IfAny: Parameter_Generic=Generic_Format_Commercial_IfAny; break;
527                 default: return Ztring();
528             }
529             break;
530         default: return Ztring();
531     }
532 
533     size_t Parameter_Format=File__Analyze::Fill_Parameter(StreamKind, Generic_Format);
534     size_t Parameter_Format_Profile=File__Analyze::Fill_Parameter(StreamKind, Generic_Format_Profile);
535     size_t Parameter_Format_AdditionalFeatures=File__Analyze::Fill_Parameter(StreamKind, Generic_Format_AdditionalFeatures);
536     if (Parameter_Format>=Info.size() || Parameter_Format_Profile>=Info.size() || Parameter_Format_AdditionalFeatures>=Info.size())
537         return Ztring();
538 
539     static const Char* _16ch =__T("16-ch");
540     static const Char* _9624=__T("96/24");
541     static const Char* Bluray=__T("Blu-ray Disc");
542     static const Char* AC3=__T("AC-3");
543     static const Char* EAC3=__T("E-AC-3");
544     static const Char* EAC3Dep=__T("E-AC-3+Dep");
545     static const Char* EAC3JOC=__T("E-AC-3 JOC");
546     static const Char* AAC=__T("AAC");
547     static const Char* AACLC=__T("AAC LC");
548     static const Char* AACLTP=__T("AAC LTP");
549     static const Char* AACMain=__T("AAC Main");
550     static const Char* AACSSR=__T("AAC SSR");
551     static const Char* AACLCSBR=__T("AAC LC SBR");
552     static const Char* AACLCSBRPS=__T("AAC LC SBR PS");
553     static const Char* Core=__T("Core");
554     static const Char* Discrete=__T("ES Discrete without ES Matrix");
555     static const Char* Dep=__T("Dep");
556     static const Char* DTS=__T("DTS");
557     static const Char* ERAAC=__T("ER AAC");
558     static const Char* ERAACLC=__T("ER AAC LC");
559     static const Char* ERAACLTP=__T("ER AAC LTP");
560     static const Char* ERAACScalable=__T("ER AAC scalable");
561     static const Char* ESMatrix=__T("ES Matrix");
562     static const Char* ESDiscrete=__T("ES Discrete");
563     static const Char* Express=__T("Express");
564     static const Char* HEAACv2 = __T("HE-AACv2");
565     static const Char* HEAAC = __T("HE-AAC");
566     static const Char* HRA=__T("HRA");
567     static const Char* JOC=__T("JOC");
568     static const Char* LC=__T("LC");
569     static const Char* LCSBR=__T("LC SBR");
570     static const Char* LCSBRPS=__T("LC SBR PS");
571     static const Char* LTP=__T("LTP");
572     static const Char* MA=__T("MA");
573     static const Char* Main=__T("Main");
574     static const Char* MLP=__T("MLP");
575     static const Char* MLPFBA=__T("MLP FBA");
576     static const Char* NonCore=__T("non-core");
577     static const Char* Scalable=__T("scalable");
578     static const Char* SSR=__T("SSR");
579 
580     ShouldReturn=true;
581     switch (Parameter_Generic)
582     {
583         case Generic_Format:
584             if (Info[Parameter_Format]==DTS)
585             {
586                 Ztring Format=Info[Parameter];
587                 ZtringList Profiles;
588                 Profiles.Separator_Set(0, __T(" / "));
589                 Profiles.Write(Info[Parameter_Format_Profile]);
590                 for (size_t i=Profiles.size()-1; i!=(size_t)-1; i--)
591                 {
592                     if (Profiles[i]==Express)
593                         Format+=__T(" LBR");
594                 }
595                 return Format;
596             }
597             break;
598         case Generic_Format_String:
599             if (Info[Parameter_Format]==AC3 || Info[Parameter_Format]==EAC3)
600             {
601                 Ztring ToReturn=Info[Parameter_Format];
602                 Ztring AdditionalFeatures=HighestFormat(StreamKind, Parameter_Format_AdditionalFeatures, Info, ShouldReturn);
603                 if (!AdditionalFeatures.find(EAC3))
604                     ToReturn.clear();
605 
606                 //Remove "Dep" from Format string
607                 size_t HasDep=AdditionalFeatures.find(Dep);
608                 if (HasDep!=string::npos)
609                 {
610                     if (ToReturn==AC3)
611                         ToReturn=EAC3;
612                     if (HasDep && AdditionalFeatures[HasDep-1]==__T(' '))
613                         AdditionalFeatures.erase(HasDep-1, 4);
614                     else if (HasDep+3<AdditionalFeatures.size() && AdditionalFeatures[HasDep+3]==__T(' '))
615                         AdditionalFeatures.erase(HasDep, 4);
616                     else if (AdditionalFeatures.size()==3)
617                         AdditionalFeatures.clear();
618                 }
619                 if (!AdditionalFeatures.empty())
620                 {
621                     if (!ToReturn.empty())
622                         ToReturn+=__T(' ');
623                     ToReturn+=AdditionalFeatures;
624                 }
625 
626                 return ToReturn;
627             }
628             else
629             {
630                 Ztring ToReturn=HighestFormat(StreamKind, Parameter_Format, Info, ShouldReturn);
631                 Ztring AdditionalFeatures=HighestFormat(StreamKind, Parameter_Format_AdditionalFeatures, Info, ShouldReturn);
632                 if (!AdditionalFeatures.empty())
633                     ToReturn+=__T(' ')+AdditionalFeatures;
634                 return ToReturn;
635             }
636             break;
637         case Generic_Format_AdditionalFeatures:
638             if (!Info[Parameter].empty())
639                 break;
640 
641             if (Info[Parameter_Format]==AAC)
642             {
643                 const Ztring& Profile=Info[Parameter_Format_Profile];
644                 if (Profile.find(HEAACv2)!=string::npos)
645                     return LCSBRPS;
646                 if (Profile.find(HEAAC)!=string::npos)
647                     return LCSBR;
648                 if (Profile.find(LC)!=string::npos)
649                     return LC;
650                 if (Profile.find(LTP)!=string::npos)
651                     return LTP;
652                 if (Profile.find(Main)!=string::npos)
653                     return Main;
654                 if (Profile.find(SSR)!=string::npos)
655                     return SSR;
656             }
657             if (Info[Parameter_Format]==DTS)
658             {
659                 Ztring AdditionalFeatures;
660                 ZtringList Profiles;
661                 Profiles.Separator_Set(0, __T(" / "));
662                 Profiles.Write(Info[Parameter_Format_Profile]);
663                 for (size_t i=Profiles.size()-1; i!=(size_t)-1; i--)
664                 {
665                     if (Profiles[i]!=Core && Profiles[i]!=Express)
666                     {
667                         if (!AdditionalFeatures.empty())
668                             AdditionalFeatures+=__T(' ');
669                              if (Profiles[i]==_9624)
670                             AdditionalFeatures+=_9624;
671                         else if (Profiles[i]==Discrete)
672                             AdditionalFeatures+=__T("XXCH");
673                         else if (Profiles[i]==ESDiscrete)
674                             AdditionalFeatures+=__T("ES XXCH");
675                         else if (Profiles[i]==ESMatrix)
676                             AdditionalFeatures+=__T("ES");
677                         else if (Profiles[i]==HRA)
678                             AdditionalFeatures+=__T("XBR");
679                         else if (Profiles[i]==MA)
680                             AdditionalFeatures+=__T("XLL");
681                         else
682                             AdditionalFeatures+=Profiles[i];
683                     }
684                 }
685                 return AdditionalFeatures;
686             }
687             if (Info[Parameter_Format]==ERAAC)
688             {
689                 const Ztring& Profile=Info[Parameter_Format_Profile];
690                 if (Profile.find(LC)!=string::npos)
691                     return LC;
692                 if (Profile.find(LTP)!=string::npos)
693                     return LTP;
694                 if (Profile.find(Scalable)!=string::npos)
695                     return Scalable;
696             }
697             if ((Info[Parameter_Format]==AC3 || Info[Parameter_Format]==EAC3) || Info[Parameter_Format].find(MLP)==0)
698             {
699                 Ztring AdditionalFeatures;
700                 ZtringList Profiles;
701                 Profiles.Separator_Set(0, __T(" / "));
702                 Profiles.Write(Info[Parameter_Format_Profile]);
703                 const Ztring& Format=Info[Parameter_Format];
704                 for (size_t i=Profiles.size()-1; i!=(size_t)-1; i--)
705                 {
706                     if (!AdditionalFeatures.empty())
707                         AdditionalFeatures+=__T(' ');
708 
709                             if (Profiles[i]==EAC3Dep)
710                         AdditionalFeatures+=Dep;
711                     else if (Profiles[i].find(JOC)!=string::npos)
712                         AdditionalFeatures+=JOC;
713                     else if (Profiles[i].find(_16ch)!=string::npos)
714                         AdditionalFeatures+=_16ch;
715                     else if (Profiles[i]==Format)
716                     {
717                         if (!AdditionalFeatures.empty())
718                             AdditionalFeatures.resize(AdditionalFeatures.size()-1);
719                     }
720                     else
721                         AdditionalFeatures+=Profiles[i];
722                 }
723                 return AdditionalFeatures;
724             }
725             break;
726         case Generic_Format_Profile:
727             if (Info[Parameter_Format]==AAC)
728                 return Info[Audio_Format_Level];
729             if (Info[Parameter_Format]==AC3 && Info[Parameter].find(EAC3)!=string::npos)
730                 return Bluray;
731             if (Info[Parameter_Format]==DTS)
732                 return Ztring();
733             if ((Info[Parameter_Format]==AC3 || Info[Parameter_Format]==EAC3) && (Info[Parameter].find(EAC3)!=string::npos || Info[Parameter].find(JOC)!=string::npos || Info[Parameter].find(MLP)!=string::npos))
734                 return Ztring();
735             if (Info[Parameter_Format].find(MLP)==0)
736                 return Ztring();
737             break;
738         case Generic_Format_Level:
739             if (Info[Parameter_Format]==AAC)
740                 return Ztring();
741             break;
742         case Generic_Format_Info:
743             if (Info[Parameter_Format]==AAC)
744             {
745                 const Ztring& Profile=Info[Audio_Format_Profile];
746                 if (Profile.find(HEAACv2)!=string::npos)
747                     return "Advanced Audio Codec Low Complexity with Spectral Band Replication and Parametric Stereo";
748                 if (Profile.find(HEAAC)!=string::npos)
749                     return "Advanced Audio Codec Low Complexity with Spectral Band Replication";
750                 if (Profile.find(LC)!=string::npos)
751                     return "Advanced Audio Codec Low Complexity";
752             }
753             if (Info[Parameter_Format].find(MLP)!=string::npos || Info[Parameter_Format_Profile].find(MLP)!=string::npos)
754             {
755                 Ztring ToReturn;
756                 if (Info[Parameter_Format]==AC3)
757                     ToReturn=__T("Audio Coding 3");
758                 else if (Info[Parameter_Format]==EAC3)
759                     ToReturn=__T("Enhanced AC-3");
760                 if (!ToReturn.empty())
761                 {
762                     if (Info[Parameter_Format_Profile].find(JOC)!=string::npos)
763                         ToReturn+=__T(" with Joint Object Coding");
764                     ToReturn+=__T(" + ");
765                 }
766                 ToReturn+=__T("Meridian Lossless Packing");
767                 if (Info[Parameter_Format]==MLPFBA || Info[Parameter_Format_Profile].find(MLPFBA)!=string::npos)
768                     ToReturn+=__T(" FBA");
769                 if (Info[Parameter_Format_Profile].find(_16ch)!=string::npos)
770                     ToReturn+=__T(" with 16-channel presentation");
771                 return ToReturn;
772             }
773             if (Info[Parameter_Format]==AC3 || Info[Parameter_Format]==EAC3)
774             {
775                 if (Info[Parameter_Format_Profile].find(JOC)!=string::npos
776                  || Info[Parameter_Format_AdditionalFeatures].find(JOC)!=string::npos)
777                     return __T("Enhanced AC-3 with Joint Object Coding");
778                 if (Info[Parameter_Format_Profile].find(EAC3)!=string::npos
779                  || Info[Parameter_Format_AdditionalFeatures].find(Dep)!=string::npos)
780                     return __T("Enhanced AC-3");
781             }
782             break;
783         case Generic_Format_Commercial:
784         case Generic_Format_Commercial_IfAny:
785             if (Info[Parameter_Format]==AAC)
786             {
787                 const Ztring& Profile=Info[Parameter_Format_Profile];
788                 if (Profile.find(HEAACv2)!=string::npos)
789                     return "HE-AACv2";
790                 if (Profile.find(HEAAC)!=string::npos)
791                     return "HE-AAC";
792             }
793             if (Info[Parameter_Format]==DTS)
794             {
795                 const Ztring& Profile=Info[Parameter_Format_Profile];
796                 if (Profile.find(MA)!=string::npos)
797                     return "DTS-HD Master Audio";
798                 if (Profile.find(HRA)!=string::npos)
799                     return "DTS-HD High Resolution Audio";
800                 if (Profile.find(_9624)!=string::npos)
801                     return "DTS 96/24";
802                 if (Profile.find(ESDiscrete)!=string::npos)
803                     return "DTS-ES Discrete";
804                 if (Profile.find(ESMatrix)!=string::npos)
805                     return "DTS-ES Matrix";
806                 if (Profile.find(Express)!=string::npos)
807                     return "DTS Express";
808             }
809             break;
810         default:;
811     }
812     return Info[Parameter];
813 }
814 
Text2StreamT(const Ztring & ParameterName,size_t ToRemove)815 static stream_t Text2StreamT(const Ztring& ParameterName, size_t ToRemove)
816 {
817     Ztring StreamKind_Text=ParameterName.substr(0, ParameterName.size()-ToRemove);
818     stream_t StreamKind2=Stream_Max;
819     if (StreamKind_Text==__T("General"))
820         StreamKind2=Stream_General;
821     if (StreamKind_Text==__T("Video"))
822         StreamKind2=Stream_Video;
823     if (StreamKind_Text==__T("Audio"))
824         StreamKind2=Stream_Audio;
825     if (StreamKind_Text==__T("Text"))
826         StreamKind2=Stream_Text;
827     if (StreamKind_Text==__T("Other"))
828         StreamKind2=Stream_Other;
829     if (StreamKind_Text==__T("Image"))
830         StreamKind2=Stream_Image;
831     if (StreamKind_Text==__T("Menu"))
832         StreamKind2=Stream_Menu;
833     return StreamKind2;
834 }
835 
836 //***************************************************************************
837 // std::cin threaded interface
838 //***************************************************************************
839 
840 #if MEDIAINFO_ADVANCED && defined(MEDIAINFO_FILE_YES) && !defined(WINDOWS_UWP) && !defined(__BORLANDC__)
841 class Reader_Cin_Thread;
842 set<Reader_Cin_Thread*> ToTerminate;
843 CriticalSection ToTerminate_CS;
844 
845 static void CtrlC_Register();
846 static void CtrlC_Unregister();
847 
Reader_Cin_Add(Reader_Cin_Thread * Thread)848 static void Reader_Cin_Add(Reader_Cin_Thread* Thread)
849 {
850     CriticalSectionLocker ToTerminate_CSL(ToTerminate_CS);
851     if (ToTerminate.empty())
852         CtrlC_Register();
853     ToTerminate.insert(Thread);
854 }
855 
Reader_Cin_Remove(Reader_Cin_Thread * Thread)856 static void Reader_Cin_Remove(Reader_Cin_Thread* Thread)
857 {
858     CriticalSectionLocker ToTerminate_CSL(ToTerminate_CS);
859     ToTerminate.erase(Thread);
860     if (ToTerminate.empty())
861         CtrlC_Unregister();
862 }
863 
864 class Reader_Cin_Thread : public Thread
865 {
866 public:
867     int8u* Buffer[2];
868     size_t Buffer_Size[2];
869     size_t Buffer_MaxSize;
870     bool   Buffer_Filling;
871     bool   Buffer_Used;
872 
Reader_Cin_Thread()873     Reader_Cin_Thread()
874     {
875         Buffer_MaxSize=64*1024;
876         Buffer[0]=new int8u[Buffer_MaxSize];
877         Buffer[1]=new int8u[Buffer_MaxSize];
878         Buffer_Size[0]=0;
879         Buffer_Size[1]=0;
880         Buffer_Filling=false;
881         Buffer_Used=false;
882         Reader_Cin_Add(this);
883     }
884 
~Reader_Cin_Thread()885     ~Reader_Cin_Thread()
886     {
887         Reader_Cin_Remove(this);
888     }
889 
Current(int8u * & Buffer_New,size_t & Buffer_Size_New)890     void Current(int8u*& Buffer_New, size_t& Buffer_Size_New)
891     {
892         //If the current buffer is full
893         Buffer_New=Buffer[Buffer_Used];
894         Buffer_Size_New=Buffer_Size[Buffer_Used];
895         if (Buffer_Size_New==Buffer_MaxSize)
896             return;
897 
898         //Not full, we accept it only if read is finished
899         if (IsRunning())
900             Buffer_Size_New=0;
901     }
902 
IsManaged()903     void IsManaged()
904     {
905         Buffer_Size[Buffer_Used]=0;
906         Buffer_Used=!Buffer_Used;
907     }
908 
Entry()909     void Entry()
910     {
911         while (!IsTerminating())
912         {
913             if (Buffer_Size[Buffer_Filling]==Buffer_MaxSize) //If end of buffer is reached
914             {
915                 Buffer_Filling=!Buffer_Filling;
916                 while (Buffer_Size[Buffer_Filling]) //Wait for first byte free
917                     Yield(); //TODO: use condition_variable
918                 continue; //Check again the condition before next step
919             }
920 
921             //Read from stdin
922             int NewChar=getchar();
923             if (NewChar==EOF)
924                 break;
925             Buffer[Buffer_Filling][Buffer_Size[Buffer_Filling]++]=(int8u)NewChar; //Fill the new char then increase offset
926         }
927 
928         RequestTerminate();
929         while (Buffer_Size[Buffer_Filling])
930             Yield(); //Wait for the all buffer are cleared by the read thread
931     }
932 };
933 
Reader_Cin_ForceTerminate()934 static void Reader_Cin_ForceTerminate()
935 {
936     CriticalSectionLocker ToTerminate_CSL(ToTerminate_CS);
937     for (set<Reader_Cin_Thread*>::iterator ToTerminate_Item=ToTerminate.begin(); ToTerminate_Item!=ToTerminate.end(); ++ToTerminate_Item)
938         (*ToTerminate_Item)->ForceTerminate();
939     ToTerminate.clear();
940 }
941 
Reader_Cin_ForceTerminate(Reader_Cin_Thread * Thread)942 static void Reader_Cin_ForceTerminate(Reader_Cin_Thread* Thread)
943 {
944     CriticalSectionLocker ToTerminate_CSL(ToTerminate_CS);
945     Thread->ForceTerminate();
946     ToTerminate.erase(Thread);
947 }
948 
CtrlC_Received()949 static void CtrlC_Received()
950 {
951     Reader_Cin_ForceTerminate();
952     CtrlC_Unregister();
953 }
954 
955 #ifdef WINDOWS
SignalHandler(WindowsNamespace::DWORD SignalType)956 static WindowsNamespace::BOOL WINAPI SignalHandler(WindowsNamespace::DWORD SignalType)
957 {
958     if (SignalType==CTRL_C_EVENT)
959     {
960         CtrlC_Received();
961         return true;
962     }
963 
964     return FALSE;
965 }
966 
CtrlC_Register()967 static void CtrlC_Register()
968 {
969     WindowsNamespace::SetConsoleCtrlHandler(SignalHandler, TRUE);
970 }
971 
CtrlC_Unregister()972 static void CtrlC_Unregister()
973 {
974     WindowsNamespace::SetConsoleCtrlHandler(SignalHandler, FALSE);
975 }
976 #else //WINDOWS
SignalHandler(int SignalType)977 static void SignalHandler(int SignalType)
978 {
979     if (SignalType==SIGINT)
980         CtrlC_Received();
981 }
982 
CtrlC_Register()983 static void CtrlC_Register()
984 {
985     signal(SIGINT, SignalHandler);
986 }
987 
CtrlC_Unregister()988 static void CtrlC_Unregister()
989 {
990     signal(SIGINT, SIG_DFL);
991 }
992 #endif //WINDOWS
993 
994 #endif
995 
996 //***************************************************************************
997 // Constructor/destructor
998 //***************************************************************************
999 
1000 //---------------------------------------------------------------------------
MediaInfo_Internal()1001 MediaInfo_Internal::MediaInfo_Internal()
1002 : Thread()
1003 {
1004     CriticalSectionLocker CSL(CS);
1005 
1006     MEDIAINFO_DEBUG_CONFIG_TEXT(Debug+=__T("Construction");)
1007 
1008     MediaInfoLib::Config.Init(); //Initialize Configuration
1009 
1010     BlockMethod=BlockMethod_Local;
1011     Info=NULL;
1012     #if !defined(MEDIAINFO_READER_NO)
1013         Reader=NULL;
1014     #endif //!defined(MEDIAINFO_READER_NO)
1015     Info_IsMultipleParsing=false;
1016 
1017     Stream.resize(Stream_Max);
1018     Stream_More.resize(Stream_Max);
1019 
1020     //Threading
1021     BlockMethod=0;
1022     IsInThread=false;
1023 }
1024 
1025 //---------------------------------------------------------------------------
~MediaInfo_Internal()1026 MediaInfo_Internal::~MediaInfo_Internal()
1027 {
1028     Close();
1029 
1030     CriticalSectionLocker CSL(CS);
1031 
1032     MEDIAINFO_DEBUG_CONFIG_TEXT(Debug+=__T("Destruction");)
1033 
1034     delete Info; //Info=NULL;
1035     #if !defined(MEDIAINFO_READER_NO)
1036         delete Reader; //Reader=NULL;
1037     #endif //!defined(MEDIAINFO_READER_NO)
1038     #ifdef MEDIAINFO_DEBUG_OUTPUT
1039         for (size_t Pos=0; Pos<Debug_Output_Pos_Stream.size(); Pos++)
1040         {
1041             delete Debug_Output_Pos_Stream[Pos]; //Debug_Output_Pos_Stream[Pos]=NULL;
1042             delete Debug_Output_Pos_Sizes[Pos]; //Debug_Output_Pos_Sizes[Pos]=NULL;
1043         }
1044     #endif //MEDIAINFO_DEBUG_OUTPUT
1045 }
1046 
1047 //***************************************************************************
1048 // Files
1049 //***************************************************************************
1050 
1051 //---------------------------------------------------------------------------
Open(const String & File_Name_)1052 size_t MediaInfo_Internal::Open(const String &File_Name_)
1053 {
1054     Close();
1055 
1056     //External IBI
1057     #if MEDIAINFO_IBIUSAGE
1058         if (Config.Ibi_UseIbiInfoIfAvailable_Get())
1059         {
1060             std::string IbiFile=Config.Ibi_Get();
1061             if (!IbiFile.empty())
1062             {
1063                 Info=new File_Ibi();
1064                 Open_Buffer_Init(IbiFile.size(), File_Name_);
1065                 Open_Buffer_Continue((const int8u*)IbiFile.c_str(), IbiFile.size());
1066                 Open_Buffer_Finalize();
1067 
1068                 if (!Get(Stream_General, 0, __T("Format")).empty() && Get(Stream_General, 0, __T("Format"))!=__T("Ibi"))
1069                     return 1;
1070 
1071                 //Nothing interesting
1072                 Close();
1073             }
1074         }
1075     #endif //MEDIAINFO_IBIUSAGE
1076     {
1077     CriticalSectionLocker CSL(CS);
1078 
1079     MEDIAINFO_DEBUG_CONFIG_TEXT(Debug+=__T("Open, File=");Debug+=Ztring(File_Name_).c_str();)
1080     Config.File_Names.clear();
1081     if (Config.File_FileNameFormat_Get()==__T("CSV"))
1082     {
1083         Config.File_Names.Separator_Set(0, __T(","));
1084         Config.File_Names.Write(File_Name_);
1085     }
1086     else if (!File_Name_.empty())
1087         Config.File_Names.push_back(File_Name_);
1088     if (Config.File_Names.empty())
1089     {
1090         return 0;
1091     }
1092     Config.File_Names_Pos=1;
1093     Config.IsFinishing=false;
1094     }
1095 
1096     //Parsing
1097     if (BlockMethod==1)
1098     {
1099         if (!IsInThread) //If already created, the routine will read the new files
1100         {
1101             Run();
1102             IsInThread=true;
1103         }
1104         return 0;
1105     }
1106     else
1107     {
1108         Entry(); //Normal parsing
1109         return Count_Get(Stream_General);
1110     }
1111 }
1112 
1113 //---------------------------------------------------------------------------
Entry()1114 void MediaInfo_Internal::Entry()
1115 {
1116     MEDIAINFO_DEBUG_CONFIG_TEXT(Debug+=__T("Entry");)
1117     Config.State_Set(0);
1118 
1119     if ((Config.File_Names[0].size()>=6
1120         && Config.File_Names[0][0]==__T('m')
1121         && Config.File_Names[0][1]==__T('m')
1122         && Config.File_Names[0][2]==__T('s')
1123         && Config.File_Names[0][3]==__T(':')
1124         && Config.File_Names[0][4]==__T('/')
1125         && Config.File_Names[0][5]==__T('/'))
1126         || (Config.File_Names[0].size()>=7
1127         && Config.File_Names[0][0]==__T('m')
1128         && Config.File_Names[0][1]==__T('m')
1129         && Config.File_Names[0][2]==__T('s')
1130         && Config.File_Names[0][3]==__T('h')
1131         && Config.File_Names[0][4]==__T(':')
1132         && Config.File_Names[0][5]==__T('/')
1133         && Config.File_Names[0][6]==__T('/')))
1134         #if defined(MEDIAINFO_LIBMMS_YES)
1135             Reader_libmms().Format_Test(this, Config.File_Names[0]);
1136         #else //MEDIAINFO_LIBMMS_YES
1137             {
1138             #if MEDIAINFO_EVENTS
1139                 struct MediaInfo_Event_Log_0 Event;
1140                 Event.EventCode=MediaInfo_EventCode_Create(MediaInfo_Parser_None, MediaInfo_Event_Log, 0);
1141                 Event.Type=0xC0;
1142                 Event.Severity=0xFF;
1143                 Event.MessageCode=0;
1144                 Event.MessageStringU=L"Libmms cupport is disabled due to compilation options";
1145                 Event.MessageStringA="Libmms cupport is disabled due to compilation options";
1146                 MediaInfoLib::Config.Event_Send((const int8u*)&Event, sizeof(MediaInfo_Event_Log_0));
1147             #endif //MEDIAINFO_EVENTS
1148             }
1149         #endif //MEDIAINFO_LIBMMS_YES
1150 
1151     else if (Config.File_Names[0].find(__T("://"))!=string::npos)
1152         #if defined(MEDIAINFO_LIBCURL_YES)
1153         {
1154             {
1155             CriticalSectionLocker CSL(CS);
1156             if (Reader)
1157             {
1158                 return; //There is a problem
1159             }
1160             Reader=new Reader_libcurl();
1161             }
1162 
1163             Reader->Format_Test(this, Config.File_Names[0]);
1164 
1165             #if MEDIAINFO_NEXTPACKET
1166                 if (Config.NextPacket_Get())
1167                     return;
1168             #endif //MEDIAINFO_NEXTPACKET
1169         }
1170         #else //MEDIAINFO_LIBCURL_YES
1171             {
1172             #if MEDIAINFO_EVENTS
1173                 struct MediaInfo_Event_Log_0 Event;
1174                 Event.EventCode=MediaInfo_EventCode_Create(MediaInfo_Parser_None, MediaInfo_Event_Log, 0);
1175                 Event.Type=0xC0;
1176                 Event.Severity=0xFF;
1177                 Event.MessageCode=0;
1178                 Event.MessageStringU=L"Libcurl support is disabled due to compilation options";
1179                 Event.MessageStringA="Libcurl support is disabled due to compilation options";
1180                 MediaInfoLib::Config.Event_Send((const int8u*)&Event, sizeof(MediaInfo_Event_Log_0));
1181             #endif //MEDIAINFO_EVENTS
1182             }
1183         #endif //MEDIAINFO_LIBCURL_YES
1184 
1185     #if defined(MEDIAINFO_DIRECTORY_YES)
1186         else if (Dir::Exists(Config.File_Names[0]))
1187             Reader_Directory().Format_Test(this, Config.File_Names[0]);
1188     #endif //MEDIAINFO_DIRECTORY_YES
1189 
1190     #if defined(MEDIAINFO_FILE_YES)
1191         else if (File::Exists(Config.File_Names[0]))
1192         {
1193             #if defined(MEDIAINFO_REFERENCES_YES)
1194                 string Dxw;
1195                 if (Config.File_CheckSideCarFiles_Get() && !Config.File_IsReferenced_Get())
1196                 {
1197                     FileName Test(Config.File_Names[0]);
1198                     Ztring FileExtension=Test.Extension_Get();
1199                     FileExtension.MakeLowerCase();
1200 
1201                     if (FileExtension!=__T("cap"))
1202                     {
1203                         Test.Extension_Set(__T("cap"));
1204                         if (File::Exists(Test))
1205                             Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".cap\" />\r\n";
1206                     }
1207                     if (FileExtension!=__T("dfxp"))
1208                     {
1209                         Test.Extension_Set(__T("dfxp"));
1210                         if (File::Exists(Test))
1211                             Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".dfxp\" />\r\n";
1212                     }
1213                     if (FileExtension!=__T("sami"))
1214                     {
1215                         Test.Extension_Set(__T("sami"));
1216                         if (File::Exists(Test))
1217                             Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".sami\" />\r\n";
1218                     }
1219                     if (FileExtension!=__T("sc2"))
1220                     {
1221                         Test.Extension_Set(__T("sc2"));
1222                         if (File::Exists(Test))
1223                             Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".sc2\" />\r\n";
1224                     }
1225                     if (FileExtension!=__T("scc"))
1226                     {
1227                         Test.Extension_Set(__T("scc"));
1228                         if (File::Exists(Test))
1229                             Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".scc\" />\r\n";
1230                     }
1231                     if (FileExtension!=__T("smi"))
1232                     {
1233                         Test.Extension_Set(__T("smi"));
1234                         if (File::Exists(Test))
1235                             Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".smi\" />\r\n";
1236                     }
1237                     if (FileExtension!=__T("srt"))
1238                     {
1239                         Test.Extension_Set(__T("srt"));
1240                         if (File::Exists(Test))
1241                             Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".srt\" />\r\n";
1242                     }
1243                     if (FileExtension!=__T("stl"))
1244                     {
1245                         Test.Extension_Set(__T("stl"));
1246                         if (File::Exists(Test))
1247                             Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".stl\" />\r\n";
1248                     }
1249                     if (FileExtension!=__T("ttml"))
1250                     {
1251                         Test.Extension_Set(__T("ttml"));
1252                         if (File::Exists(Test))
1253                             Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".ttml\" />\r\n";
1254                     }
1255                     if (FileExtension!=__T("ssa"))
1256                     {
1257                         Test.Extension_Set(__T("ssa"));
1258                         if (File::Exists(Test))
1259                             Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".ssa\" />\r\n";
1260                     }
1261                     if (FileExtension!=__T("ass"))
1262                     {
1263                         Test.Extension_Set(__T("ass"));
1264                         if (File::Exists(Test))
1265                             Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".ass\" />\r\n";
1266                     }
1267                     if (FileExtension!=__T("vtt"))
1268                     {
1269                         Test.Extension_Set(__T("vtt"));
1270                         if (File::Exists(Test))
1271                             Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".vtt\" />\r\n";
1272                     }
1273                     if (FileExtension!=__T("xml"))
1274                     {
1275                         Test.Extension_Set(__T("xml"));
1276                         if (File::Exists(Test))
1277                         {
1278                             MediaInfo_Internal MI;
1279                             Ztring ParseSpeed_Save=MI.Option(__T("ParseSpeed_Get"), __T(""));
1280                             Ztring Demux_Save=MI.Option(__T("Demux_Get"), __T(""));
1281                             MI.Option(__T("ParseSpeed"), __T("0"));
1282                             MI.Option(__T("Demux"), Ztring());
1283                             size_t MiOpenResult=MI.Open(Test);
1284                             MI.Option(__T("ParseSpeed"), ParseSpeed_Save); //This is a global value, need to reset it. TODO: local value
1285                             MI.Option(__T("Demux"), Demux_Save); //This is a global value, need to reset it. TODO: local value
1286                             if (MiOpenResult)
1287                             {
1288                                 Ztring Format=MI.Get(Stream_General, 0, General_Format);
1289                                 if (Format==__T("TTML"))
1290                                     Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".xml\" />\r\n";
1291                             }
1292                         }
1293                     }
1294 
1295                     #if defined(MEDIAINFO_DIRECTORY_YES)
1296                     Ztring Name=Test.Name_Get();
1297                     Ztring BaseName=Name.SubString(Ztring(), __T("_"));
1298                     if (!BaseName.empty())
1299                     {
1300                         ZtringList List;
1301                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_audio.mp4"), Dir::Include_Files);
1302                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_sub.dfxp"), Dir::Include_Files);
1303                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_sub.sami"), Dir::Include_Files);
1304                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_sub.sc2"), Dir::Include_Files);
1305                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_sub.scc"), Dir::Include_Files);
1306                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_sub.smi"), Dir::Include_Files);
1307                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_sub.srt"), Dir::Include_Files);
1308                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_sub.stl"), Dir::Include_Files);
1309                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_sub.vtt"), Dir::Include_Files);
1310                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_forcesub.dfxp"), Dir::Include_Files);
1311                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_forcesub.sami"), Dir::Include_Files);
1312                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_forcesub.sc2"), Dir::Include_Files);
1313                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_forcesub.scc"), Dir::Include_Files);
1314                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_forcesub.smi"), Dir::Include_Files);
1315                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_forcesub.srt"), Dir::Include_Files);
1316                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_forcesub.stl"), Dir::Include_Files);
1317                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_forcesub.vtt"), Dir::Include_Files);
1318                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_cc.dfxp"), Dir::Include_Files);
1319                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_cc.sami"), Dir::Include_Files);
1320                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_cc.sc2"), Dir::Include_Files);
1321                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_cc.scc"), Dir::Include_Files);
1322                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_cc.smi"), Dir::Include_Files);
1323                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_cc.srt"), Dir::Include_Files);
1324                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_cc.stl"), Dir::Include_Files);
1325                         List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_cc.vtt"), Dir::Include_Files);
1326                         for (size_t Pos=0; Pos<List.size(); Pos++)
1327                             Dxw+=" <clip file=\""+List[Pos].To_UTF8()+"\" />\r\n";
1328                     }
1329                     #endif //defined(MEDIAINFO_DIRECTORY_YES)
1330 
1331                     if (!Dxw.empty())
1332                     {
1333                         Dxw.insert(0, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n"
1334                                 "<indexFile xmlns=\"urn:digimetrics-xml-wrapper\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"urn:digimetrics-xml-wrapper DMSCLIP.XSD\">\r\n"
1335                                 " <clip source=\"main\" file=\""+FileName(Config.File_Names[0]).Name_Get().To_UTF8()+"."+FileName(Config.File_Names[0]).Extension_Get().To_UTF8()+"\" />\r\n");
1336                         Dxw.append("</indexFile>\r\n");
1337                         Config.File_FileNameFormat_Set(__T("Dxw"));
1338                     }
1339                 }
1340 
1341                 if (Dxw.empty())
1342                 {
1343                     {
1344                     CriticalSectionLocker CSL(CS);
1345                     if (Reader)
1346                     {
1347                         return; //There is a problem
1348                     }
1349                     Reader=new Reader_File();
1350                     }
1351 
1352                     Reader->Format_Test(this, Config.File_Names[0]);
1353                 }
1354                 else
1355                 {
1356                     Open_Buffer_Init(Dxw.size(), FileName(Config.File_Names[0]).Path_Get()+PathSeparator+FileName(Config.File_Names[0]).Name_Get());
1357                     Open_Buffer_Continue((const int8u*)Dxw.c_str(), Dxw.size());
1358                     #if MEDIAINFO_NEXTPACKET
1359                         if (Config.NextPacket_Get())
1360                             return;
1361                     #endif //MEDIAINFO_NEXTPACKET
1362                     Open_Buffer_Finalize();
1363                 }
1364             #else //defined(MEDIAINFO_REFERENCES_YES)
1365                 {
1366                 CriticalSectionLocker CSL(CS);
1367                 if (Reader)
1368                 {
1369                     return; //There is a problem
1370                 }
1371                 Reader=new Reader_File();
1372                 }
1373                 Reader->Format_Test(this, Config.File_Names[0]);
1374             #endif //defined(MEDIAINFO_REFERENCES_YES)
1375 
1376             #if MEDIAINFO_NEXTPACKET
1377                 if (Config.NextPacket_Get())
1378                     return;
1379             #endif //MEDIAINFO_NEXTPACKET
1380         }
1381     #endif //MEDIAINFO_FILE_YES
1382     #if MEDIAINFO_ADVANCED && defined(MEDIAINFO_FILE_YES) && !defined(WINDOWS_UWP) && !defined(__BORLANDC__)
1383         else if (Config.File_Names[0]==__T("-")
1384             #if defined(WINDOWS) && !defined(WINDOWS_UWP) && !defined(__BORLANDC__)
1385                 //&& WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0) == WAIT_OBJECT_0 //Check if there is something is stdin
1386                 && _setmode(_fileno(stdin), _O_BINARY) != -1 //Force binary mode
1387             #endif //defined(WINDOWS) && !defined(WINDOWS_UWP) && !defined(__BORLANDC__)
1388             )
1389         {
1390             Reader_Cin_Thread Cin;
1391             Cin.Run();
1392             Open_Buffer_Init();
1393             clock_t LastIn=-1;
1394             int64u TimeOut_Temp=MediaInfoLib::Config.TimeOut_Get();
1395             int64u TimeOut_Temp2=TimeOut_Temp*CLOCKS_PER_SEC;
1396             clock_t TimeOut=(!CLOCKS_PER_SEC || !TimeOut_Temp || TimeOut_Temp2/CLOCKS_PER_SEC==TimeOut_Temp)?((clock_t)TimeOut_Temp2):-1;
1397 
1398             for (;;)
1399             {
1400                 int8u* Buffer_New;
1401                 size_t Buffer_Size_New;
1402                 Cin.Current(Buffer_New, Buffer_Size_New);
1403                 if (Buffer_Size_New)
1404                 {
1405                     if (Open_Buffer_Continue(Buffer_New, Buffer_Size_New)[File__Analyze::IsFinished])
1406                         break;
1407                     Cin.IsManaged();
1408                     if (TimeOut!=-1)
1409                         LastIn=clock();
1410                 }
1411                 else if (Cin.IsExited())
1412                     break;
1413                 else
1414                 {
1415                     if (LastIn!=-1)
1416                     {
1417                         clock_t NewLastIn=clock();
1418                         if (NewLastIn-LastIn>=TimeOut)
1419                         {
1420                             Reader_Cin_ForceTerminate(&Cin);
1421                             LastIn=-1;
1422                         }
1423                     }
1424 
1425                     #ifdef WINDOWS
1426                         WindowsNamespace::Sleep(0);
1427                     #elif defined(_POSIX_PRIORITY_SCHEDULING)
1428                         sched_yield();
1429                     #endif //_POSIX_PRIORITY_SCHEDULING
1430                 }
1431             }
1432             Open_Buffer_Finalize();
1433         }
1434     #endif //MEDIAINFO_ADVANCED && defined(MEDIAINFO_FILE_YES) && !defined(WINDOWS_UWP) && !defined(__BORLANDC__)
1435 
1436     Config.State_Set(1);
1437 }
1438 
1439 //---------------------------------------------------------------------------
Open(const int8u * Begin,size_t Begin_Size,const int8u * End,size_t End_Size,int64u File_Size)1440 size_t MediaInfo_Internal::Open (const int8u* Begin, size_t Begin_Size, const int8u* End, size_t End_Size, int64u File_Size)
1441 {
1442     Open_Buffer_Init(File_Size);
1443     Open_Buffer_Continue(Begin, Begin_Size);
1444     if (End && Begin_Size+End_Size<=File_Size)
1445     {
1446         Open_Buffer_Init(File_Size, File_Size-End_Size);
1447         Open_Buffer_Continue(End, End_Size);
1448     }
1449     Open_Buffer_Finalize();
1450 
1451     return 1;
1452 }
1453 
1454 //---------------------------------------------------------------------------
Open_Buffer_Init(int64u File_Size_,const String & File_Name)1455 size_t MediaInfo_Internal::Open_Buffer_Init (int64u File_Size_, const String &File_Name)
1456 {
1457     CriticalSectionLocker CSL(CS);
1458 
1459     if (Config.File_Names.size()<=1) //If analyzing multiple files, theses members are adapted in File_Reader.cpp
1460     {
1461         if (File_Size_!=(int64u)-1)
1462         {
1463             Config.File_Size=Config.File_Current_Size=File_Size_;
1464             if (!Config.File_Sizes.empty())
1465                 Config.File_Sizes[Config.File_Sizes.size()-1]=File_Size_;
1466         }
1467     }
1468 
1469     if (Info==NULL)
1470     {
1471         Ztring ForceParser = Config.File_ForceParser_Get();
1472         if (!ForceParser.empty())
1473         {
1474             CS.Leave();
1475             SelectFromExtension(ForceParser);
1476             CS.Enter();
1477         }
1478         if (Info==NULL)
1479         {
1480             Info=new File__MultipleParsing;
1481             Info_IsMultipleParsing=true;
1482         }
1483     }
1484     #if MEDIAINFO_TRACE
1485         Info->Init(&Config, &Details, &Stream, &Stream_More);
1486     #else //MEDIAINFO_TRACE
1487         Info->Init(&Config, &Stream, &Stream_More);
1488     #endif //MEDIAINFO_TRACE
1489     if (!File_Name.empty())
1490         Info->File_Name=File_Name;
1491     Info->Open_Buffer_Init(File_Size_);
1492 
1493     if (File_Name.empty())
1494     {
1495         #if MEDIAINFO_EVENTS
1496             {
1497                 struct MediaInfo_Event_General_Start_0 Event;
1498                 memset(&Event, 0xFF, sizeof(struct MediaInfo_Event_Generic));
1499                 Event.EventCode=MediaInfo_EventCode_Create(MediaInfo_Parser_None, MediaInfo_Event_General_Start, 0);
1500                 Event.EventSize=sizeof(struct MediaInfo_Event_General_Start_0);
1501                 Event.StreamIDs_Size=0;
1502                 Event.Stream_Size=File_Size_;
1503                 Event.FileName=NULL;
1504                 Event.FileName_Unicode=NULL;
1505                 Config.Event_Send(NULL, (const int8u*)&Event, sizeof(MediaInfo_Event_General_Start_0));
1506             }
1507         #endif //MEDIAINFO_EVENTS
1508     }
1509 
1510     return 1;
1511 }
1512 
1513 //---------------------------------------------------------------------------
Open_Buffer_Init(int64u File_Size_,int64u File_Offset_)1514 size_t MediaInfo_Internal::Open_Buffer_Init (int64u File_Size_, int64u File_Offset_)
1515 {
1516     MEDIAINFO_DEBUG_CONFIG_TEXT(Debug+=__T("Open_Buffer_Init, File_Size=");Debug+=Ztring::ToZtring(File_Size_);Debug+=__T(", File_Offset=");Debug+=Ztring::ToZtring(File_Offset_);)
1517     #ifdef MEDIAINFO_DEBUG_BUFFER
1518         if (Info && File_Offset_>Info->File_Offset)
1519         {
1520             size_t Temp_Size=(size_t)(File_Offset_-Info->File_Offset);
1521             int8u* Temp=new int8u[Temp_Size];
1522             std::memset(Temp, 0xCC, Temp_Size);
1523             MEDIAINFO_DEBUG_BUFFER_SAVE(Temp, Temp_Size);
1524             delete[] Temp;
1525         }
1526     #endif //MEDIAINFO_DEBUG_BUFFER
1527 
1528     if (Config.File_Names.size()<=1) //If analyzing multiple files, theses members are adapted in File_Reader.cpp
1529     {
1530         if (File_Size_!=(int64u)-1)
1531         {
1532             Config.File_Size=Config.File_Current_Size=File_Size_;
1533             if (!Config.File_Sizes.empty())
1534                 Config.File_Sizes[Config.File_Sizes.size()-1]=File_Size_;
1535 
1536             if (Info && !Info->Retrieve(Stream_General, 0, General_FileSize).empty())
1537                 Info->Fill(Stream_General, 0, General_FileSize, File_Size_, 10, true); //TODO: avoid multiple tests of file size field, refactor it in order to have a single place for file size info
1538         }
1539     }
1540 
1541     if (Info==NULL || File_Size_!=(int64u)-1)
1542         Open_Buffer_Init(File_Size_);
1543 
1544     if (File_Offset_!=(int64u)-1 && Info)
1545     {
1546         CriticalSectionLocker CSL(CS);
1547         Info->Open_Buffer_Position_Set(File_Offset_);
1548     }
1549 
1550     #if MEDIAINFO_EVENTS
1551         if (Info && Info->Status[File__Analyze::IsAccepted])
1552         {
1553             struct MediaInfo_Event_General_Move_Done_0 Event;
1554             Info->Event_Prepare((struct MediaInfo_Event_Generic*)&Event, MediaInfo_EventCode_Create(MediaInfo_Parser_None, MediaInfo_Event_General_Move_Done, 0), sizeof(struct MediaInfo_Event_General_Move_Done_0));
1555             Event.StreamIDs_Size=0;
1556             Event.StreamOffset=File_Offset_;
1557             Config.Event_Send(NULL, (const int8u*)&Event, sizeof(MediaInfo_Event_General_Move_Done_0));
1558         }
1559         else
1560         {
1561             struct MediaInfo_Event_General_Start_0 Event;
1562             Info->Event_Prepare((struct MediaInfo_Event_Generic*)&Event, MediaInfo_EventCode_Create(MediaInfo_Parser_None, MediaInfo_Event_General_Start, 0), sizeof(struct MediaInfo_Event_General_Start_0));
1563             Event.StreamIDs_Size=0;
1564             Event.Stream_Size=File_Size_;
1565             Event.FileName=NULL;
1566             Event.FileName_Unicode=NULL;
1567             Config.Event_Send(NULL, (const int8u*)&Event, sizeof(MediaInfo_Event_General_Start_0));
1568         }
1569     #endif //MEDIAINFO_EVENTS
1570 
1571     EXECUTE_SIZE_T(1, Debug+=__T("Open_Buffer_Init, will return 1");)
1572 }
1573 
1574 //---------------------------------------------------------------------------
1575 #if MEDIAINFO_ADVANCED2
Open_Buffer_SegmentChange()1576 size_t MediaInfo_Internal::Open_Buffer_SegmentChange ()
1577 {
1578     MEDIAINFO_DEBUG_CONFIG_TEXT(Debug+=__T("Open_Buffer_SegmentChange"))
1579 
1580     if (Info == NULL)
1581         return 0;
1582     Info->Open_Buffer_SegmentChange();
1583 
1584     return 1;
1585 }
1586 #endif //MEDIAINFO_ADVANCED2
1587 
1588 //---------------------------------------------------------------------------
Open_Buffer_Unsynch()1589 void MediaInfo_Internal::Open_Buffer_Unsynch ()
1590 {
1591     MEDIAINFO_DEBUG_CONFIG_TEXT(Debug+=__T("Open_Buffer_Unsynch");)
1592 
1593     if (Info==NULL)
1594         return;
1595 
1596     CriticalSectionLocker CSL(CS);
1597     Info->Open_Buffer_Unsynch();
1598 }
1599 
1600 //---------------------------------------------------------------------------
Open_Buffer_Continue(const int8u * ToAdd,size_t ToAdd_Size)1601 std::bitset<32> MediaInfo_Internal::Open_Buffer_Continue (const int8u* ToAdd, size_t ToAdd_Size)
1602 {
1603     CriticalSectionLocker CSL(CS);
1604     MEDIAINFO_DEBUG_BUFFER_SAVE(ToAdd, ToAdd_Size);
1605     if (Info==NULL)
1606         return 0;
1607 
1608     //Encoded content
1609     #if MEDIAINFO_COMPRESS
1610         bool zlib=MediaInfoLib::Config.FlagsX_Get(Flags_Input_zlib);
1611         bool base64=MediaInfoLib::Config.FlagsX_Get(Flags_Input_base64);
1612         if (zlib || base64)
1613         {
1614             if (ToAdd_Size!=Config.File_Size)
1615             {
1616                 Info->ForceFinish(); // File must be complete when this option is used
1617                 return Info->Status;
1618             }
1619             string Input_Cache; // In case of encoded content, this string must live up to the end of the parsing
1620             if (base64)
1621             {
1622                 Input_Cache.assign((const char*)ToAdd, ToAdd_Size); ;
1623                 Input_Cache=Base64::decode(Input_Cache);
1624                 ToAdd=(const int8u*)Input_Cache.c_str();
1625                 ToAdd_Size= Input_Cache.size();
1626             }
1627             if (zlib)
1628             {
1629                 uLongf Output_Size_Max = ToAdd_Size;
1630                 while (Output_Size_Max)
1631                 {
1632                     Output_Size_Max *=16;
1633                     int8u* Output = new int8u[Output_Size_Max];
1634                     uLongf Output_Size = Output_Size_Max;
1635                     if (uncompress((Bytef*)Output, &Output_Size, (const Bytef*)ToAdd, (uLong)ToAdd_Size)>=0)
1636                     {
1637                         ToAdd=Output;
1638                         ToAdd_Size=Output_Size;
1639                         break;
1640                     }
1641                     delete[] Output;
1642                     if (Output_Size_Max>=4*1024*1024)
1643                     {
1644                         Info->ForceFinish();
1645                         return Info->Status;
1646                     }
1647                 }
1648             }
1649             Info->Open_Buffer_Continue(ToAdd, ToAdd_Size);
1650             if (zlib)
1651                 delete[] ToAdd;
1652         }
1653         else
1654     #endif //MEDIAINFO_COMPRESS
1655     Info->Open_Buffer_Continue(ToAdd, ToAdd_Size);
1656 
1657     if (Info_IsMultipleParsing && Info->Status[File__Analyze::IsAccepted])
1658     {
1659         //Found
1660         File__Analyze* Info_ToDelete=Info;
1661         Info=((File__MultipleParsing*)Info)->Parser_Get();
1662         delete Info_ToDelete; //Info_ToDelete=NULL;
1663         Info_IsMultipleParsing=false;
1664     }
1665 
1666     #if 0 //temp, for old users
1667     //The parser wanted seek but the buffer is not seekable
1668     if (Info->File_GoTo!=(int64u)-1 && Config.File_IsSeekable_Get()==0)
1669     {
1670         Info->Open_Buffer_Finalize(true);
1671         Info->File_GoTo=(int64u)-1;
1672         MEDIAINFO_DEBUG_CONFIG_TEXT(Debug+=__T("Open_Buffer_Continue, will return 0");)
1673         return 0;
1674     }
1675 
1676     return 1;
1677     #else
1678     //The parser wanted seek but the buffer is not seekable
1679     if (Info->File_GoTo!=(int64u)-1 && Config.File_IsSeekable_Get()==0)
1680     {
1681         Info->Fill();
1682         Info->File_GoTo=(int64u)-1;
1683     }
1684 
1685     return Info->Status;
1686     #endif
1687 }
1688 
1689 //---------------------------------------------------------------------------
Open_Buffer_Continue_GoTo_Get()1690 int64u MediaInfo_Internal::Open_Buffer_Continue_GoTo_Get ()
1691 {
1692     CriticalSectionLocker CSL(CS);
1693     if (Info==NULL)
1694         return (int64u)-1;
1695 
1696     if (Info->File_GoTo==(int64u)-1
1697      || (Info->File_GoTo>=Info->File_Offset && Info->File_GoTo<Info->File_Offset+0x10000)) //If jump is tiny, this is not worth the performance cost due to seek
1698         return (int64u)-1;
1699     else
1700         return Info->File_GoTo;
1701 }
1702 
1703 //---------------------------------------------------------------------------
Open_Buffer_CheckFileModifications()1704 void MediaInfo_Internal::Open_Buffer_CheckFileModifications()
1705 {
1706     CriticalSectionLocker CSL(CS);
1707     if (Info == NULL)
1708         return;
1709 
1710     Info->Open_Buffer_CheckFileModifications();
1711 }
1712 
1713 //---------------------------------------------------------------------------
Open_Buffer_Position_Set(int64u File_Offset)1714 bool MediaInfo_Internal::Open_Buffer_Position_Set(int64u File_Offset)
1715 {
1716     CriticalSectionLocker CSL(CS);
1717     if (Info==NULL)
1718         return false;
1719 
1720     Info->Open_Buffer_Position_Set(File_Offset);
1721 
1722     return true;
1723 }
1724 
1725 //---------------------------------------------------------------------------
1726 #if MEDIAINFO_SEEK
Open_Buffer_Seek(size_t Method,int64u Value,int64u ID)1727 size_t MediaInfo_Internal::Open_Buffer_Seek (size_t Method, int64u Value, int64u ID)
1728 {
1729     CriticalSectionLocker CSL(CS);
1730     if (Info==NULL)
1731         return 0;
1732 
1733     return Info->Open_Buffer_Seek(Method, Value, ID);
1734 }
1735 #endif //MEDIAINFO_SEEK
1736 
1737 //---------------------------------------------------------------------------
Open_Buffer_Finalize()1738 size_t MediaInfo_Internal::Open_Buffer_Finalize ()
1739 {
1740     CriticalSectionLocker CSL(CS);
1741     MEDIAINFO_DEBUG_CONFIG_TEXT(Debug+=__T("Open_Buffer_Finalize");)
1742     if (Info==NULL)
1743         return 0;
1744 
1745     Info->Open_Buffer_Finalize();
1746     #if MEDIAINFO_DEMUX
1747         if (Config.Demux_EventWasSent)
1748             return 0;
1749     #endif //MEDIAINFO_DEMUX
1750 
1751     //Cleanup
1752     if (!Config.File_IsSub_Get() && !Config.File_KeepInfo_Get()) //We need info for the calling parser
1753     {
1754         #if MEDIAINFO_TRACE
1755         ParserName=Ztring().From_UTF8(Info->ParserName); //Keep it in memory in case we need it after delete of Info
1756         #endif //MEDIAINFO_TRACE
1757         delete Info; Info=NULL;
1758     }
1759     if (Config.File_Names_Pos>=Config.File_Names.size())
1760     {
1761         delete[] Config.File_Buffer; Config.File_Buffer=NULL; Config.File_Buffer_Size=0; Config.File_Buffer_Size_Max=0;
1762     }
1763     #if MEDIAINFO_EVENTS
1764         if (!Config.File_IsReferenced_Get()) //TODO: get its own metadata in order to know if it was created by this instance
1765         {
1766             delete Config.Config_PerPackage; Config.Config_PerPackage=NULL;
1767         }
1768     #endif //MEDIAINFO_EVENTS
1769 
1770     EXECUTE_SIZE_T(1, Debug+=__T("Open_Buffer_Finalize, will return 1"))
1771 }
1772 
1773 //---------------------------------------------------------------------------
Open_NextPacket()1774 std::bitset<32> MediaInfo_Internal::Open_NextPacket ()
1775 {
1776     CriticalSectionLocker CSL(CS);
1777 
1778     bool Demux_EventWasSent=false;
1779     if (Info==NULL || !Info->Status[File__Analyze::IsFinished])
1780     {
1781         #if !defined(MEDIAINFO_READER_NO)
1782             if (Reader)
1783             {
1784                 CS.Leave();
1785                 Demux_EventWasSent=(Reader->Format_Test_PerParser_Continue(this)==2);
1786                 CS.Enter();
1787             }
1788             else
1789         #endif //defined(MEDIAINFO_READER_NO)
1790             {
1791                 #if MEDIAINFO_DEMUX && MEDIAINFO_NEXTPACKET
1792                     Config.Demux_EventWasSent=false;
1793                 #endif //MEDIAINFO_DEMUX && MEDIAINFO_NEXTPACKET
1794                 Open_Buffer_Continue(NULL, 0);
1795                 #if MEDIAINFO_DEMUX && MEDIAINFO_NEXTPACKET
1796                     if (!Config.Demux_EventWasSent)
1797                 #endif //MEDIAINFO_DEMUX && MEDIAINFO_NEXTPACKET
1798                         Open_Buffer_Finalize();
1799                 #if MEDIAINFO_DEMUX && MEDIAINFO_NEXTPACKET
1800                     Demux_EventWasSent=Config.Demux_EventWasSent;
1801                 #endif //MEDIAINFO_DEMUX && MEDIAINFO_NEXTPACKET
1802             }
1803     }
1804 
1805     std::bitset<32> ToReturn=Info==NULL?std::bitset<32>(0x0F):Info->Status;
1806     if (Demux_EventWasSent)
1807         ToReturn[8]=true; //bit 8 is for the reception of a frame
1808 
1809     return ToReturn;
1810 }
1811 
1812 //---------------------------------------------------------------------------
Close()1813 void MediaInfo_Internal::Close()
1814 {
1815     if (IsRunning() || IsTerminating())
1816     {
1817         RequestTerminate();
1818         while(!IsExited())
1819             Yield();
1820     }
1821 
1822     CriticalSectionLocker CSL(CS);
1823     MEDIAINFO_DEBUG_CONFIG_TEXT(Debug+=__T("Close");)
1824     Stream.clear();
1825     Stream.resize(Stream_Max);
1826     Stream_More.clear();
1827     Stream_More.resize(Stream_Max);
1828     delete Info; Info=NULL;
1829     #if !defined(MEDIAINFO_READER_NO)
1830         delete Reader; Reader=NULL;
1831     #endif //defined(MEDIAINFO_READER_NO)
1832 }
1833 
1834 //***************************************************************************
1835 // Get File info
1836 //***************************************************************************
1837 
1838 /*//---------------------------------------------------------------------------
1839 Ztring MediaInfo_Internal::Inform(size_t)
1840 {
1841     //Info case
1842     if (Info)
1843         return Info->Inform();
1844 
1845     if (!Info)
1846         return MediaInfoLib::Config.EmptyString_Get();
1847 
1848     return Info->Inform();
1849 } */
1850 
1851 //---------------------------------------------------------------------------
Get(stream_t StreamKind,size_t StreamPos,size_t Parameter,info_t KindOfInfo)1852 Ztring MediaInfo_Internal::Get(stream_t StreamKind, size_t StreamPos, size_t Parameter, info_t KindOfInfo)
1853 {
1854     #if MEDIAINFO_ADVANCED
1855     if (StreamKind==Stream_General && KindOfInfo==Info_Text)
1856     {
1857         switch (Parameter)
1858         {
1859             case General_Video_Codec_List:
1860             case General_Audio_Codec_List:
1861             case General_Text_Codec_List:
1862             case General_Image_Codec_List:
1863             case General_Other_Codec_List:
1864             case General_Menu_Codec_List:
1865                 if (!MediaInfoLib::Config.Legacy_Get())
1866                 {
1867                     // MediaInfo GUI is using them by default in one of its old templates, using the "Format" ones.
1868                     return Get(StreamKind, StreamPos, Parameter-2, Info_Text);
1869                 }
1870                 {
1871                 Ztring ParameterName=Get(Stream_General, 0, Parameter, Info_Name);
1872                 stream_t StreamKind2=Text2StreamT(ParameterName, 12);
1873                 size_t Parameter2=File__Analyze::Fill_Parameter(StreamKind2, Generic_Codec_String);
1874                 Ztring Temp;
1875                 size_t Count=Count_Get(StreamKind2);
1876                 for (size_t i=0; i<Count; i++)
1877                 {
1878                     if (i)
1879                         Temp+=__T(" / ");
1880                     size_t Temp_Size=Temp.size();
1881                     Temp+=Get(StreamKind2, i, Parameter2, Info_Text);
1882                 }
1883                 return (Temp.size()>(Count-1)*3)?Temp:Ztring();
1884                 }
1885                 break;
1886             case General_Video_Format_List:
1887             case General_Audio_Format_List:
1888             case General_Text_Format_List:
1889             case General_Image_Format_List:
1890             case General_Other_Format_List:
1891             case General_Menu_Format_List:
1892                 {
1893                 Ztring ParameterName=Get(Stream_General, 0, Parameter, Info_Name);
1894                 stream_t StreamKind2=Text2StreamT(ParameterName, 12);
1895                 size_t Parameter2=File__Analyze::Fill_Parameter(StreamKind2, Generic_Format_String);
1896                 Ztring Temp;
1897                 size_t Count=Count_Get(StreamKind2);
1898                 for (size_t i=0; i<Count; i++)
1899                 {
1900                     if (i)
1901                         Temp+=__T(" / ");
1902                     size_t Temp_Size=Temp.size();
1903                     Temp+=Get(StreamKind2, i, Parameter2, Info_Text);
1904                 }
1905                 return (Temp.size()>(Count-1)*3)?Temp:Ztring();
1906                 }
1907             case General_Video_Format_WithHint_List:
1908             case General_Audio_Format_WithHint_List:
1909             case General_Text_Format_WithHint_List:
1910             case General_Image_Format_WithHint_List:
1911             case General_Other_Format_WithHint_List:
1912             case General_Menu_Format_WithHint_List:
1913                 {
1914                 Ztring ParameterName=Get(Stream_General, 0, Parameter, Info_Name);
1915                 stream_t StreamKind2=Text2StreamT(ParameterName, 21);
1916                 size_t Parameter2=File__Analyze::Fill_Parameter(StreamKind2, Generic_Format_String);
1917                 Ztring Temp;
1918                 size_t Count=Count_Get(StreamKind2);
1919                 for (size_t i=0; i<Count; i++)
1920                 {
1921                     if (i)
1922                         Temp+=__T(" / ");
1923                     size_t Temp_Size=Temp.size();
1924                     Temp+=Get(StreamKind2, i, Parameter2, Info_Text);
1925                     Ztring Hint=Get(StreamKind2, i, File__Analyze::Fill_Parameter(StreamKind2, Generic_CodecID_Hint), Info_Text);
1926                     if (!Hint.empty())
1927                     {
1928                         Temp+=__T(" (");
1929                         Temp+=Hint;
1930                         Temp+=__T(')');
1931                     }
1932                 }
1933                 return (Temp.size()>(Count-1)*3)?Temp:Ztring();
1934                 }
1935             case General_Video_Language_List:
1936             case General_Audio_Language_List:
1937             case General_Text_Language_List:
1938             case General_Image_Language_List:
1939             case General_Other_Language_List:
1940             case General_Menu_Language_List:
1941                 {
1942                 Ztring ParameterName=Get(Stream_General, 0, Parameter, Info_Name);
1943                 stream_t StreamKind2=Text2StreamT(ParameterName, 14);
1944                 size_t Parameter2=File__Analyze::Fill_Parameter(StreamKind2, Generic_Language)+1;
1945                 Ztring Temp;
1946                 size_t Count=Count_Get(StreamKind2);
1947                 for (size_t i=0; i<Count; i++)
1948                 {
1949                     if (i)
1950                         Temp+=__T(" / ");
1951                     size_t Temp_Size=Temp.size();
1952                     Temp+=Get(StreamKind2, i, Parameter2, Info_Text);
1953                 }
1954                 return (Temp.size()>(Count-1)*3)?Temp:Ztring();
1955                 }
1956             case General_VideoCount:
1957             case General_AudioCount:
1958             case General_TextCount:
1959             case General_ImageCount:
1960             case General_OtherCount:
1961             case General_MenuCount:
1962                 {
1963                 stream_t StreamKind2=Text2StreamT(Get(Stream_General, 0, Parameter, Info_Name), 5);
1964                 size_t Count=Count_Get(StreamKind2);
1965                 if (Count)
1966                     return Ztring::ToZtring(Count);
1967                 else
1968                     return Ztring();
1969                 }
1970             default:;
1971         }
1972     }
1973     #endif //MEDIAINFO_ADVANCED
1974 
1975     CriticalSectionLocker CSL(CS);
1976     MEDIAINFO_DEBUG_CONFIG_TEXT(Debug+=__T("Get, StreamKind=");Debug+=Ztring::ToZtring((size_t)StreamKind);Debug+=__T(", StreamPos=");Debug+=Ztring::ToZtring(StreamPos);Debug+=__T(", Parameter=");Debug+=Ztring::ToZtring(Parameter);)
1977 
1978     if (Info && Info->Status[File__Analyze::IsUpdated])
1979     {
1980         Info->Open_Buffer_Update();
1981         Info->Status[File__Analyze::IsUpdated]=false;
1982         for (size_t Pos=File__Analyze::User_16; Pos<File__Analyze::User_16+16; Pos++)
1983             Info->Status[Pos]=false;
1984     }
1985 
1986     //Check integrity
1987     if (StreamKind>=Stream_Max || StreamPos>=Stream[StreamKind].size() || Parameter>=MediaInfoLib::Config.Info_Get(StreamKind).size()+Stream_More[StreamKind][StreamPos].size() || KindOfInfo>=Info_Max)
1988         return MediaInfoLib::Config.EmptyString_Get(); //Parameter is unknown
1989 
1990     else if (Parameter<MediaInfoLib::Config.Info_Get(StreamKind).size())
1991     {
1992         //Optimization : KindOfInfo>Info_Text is in static lists
1993         if (KindOfInfo!=Info_Text)
1994             EXECUTE_STRING(MediaInfoLib::Config.Info_Get(StreamKind, Parameter, KindOfInfo), Debug+=__T("Get, will return ");Debug+=ToReturn;) //look for static information only
1995         else if (Parameter<Stream[StreamKind][StreamPos].size())
1996         {
1997             bool ShouldReturn=false;
1998             #if MEDIAINFO_ADVANCED
1999             if (Config.File_HighestFormat_Get())
2000             #endif //MEDIAINFO_ADVANCED
2001             {
2002                 if (StreamKind==Stream_General && (Parameter==General_Audio_Format_List || Parameter==General_Audio_Format_WithHint_List))
2003                 {
2004                     ZtringList List;
2005                     List.Separator_Set(0, __T(" / "));
2006                     List.Write(Stream[Stream_General][StreamPos][Parameter]);
2007                     for (size_t i=0; i<List.size(); i++)
2008                         List[i]=HighestFormat(Stream_Audio, Audio_Format_String, Stream[Stream_Audio][i], ShouldReturn);
2009                     if (ShouldReturn)
2010                     {
2011                         Ztring ToReturn=List.Read();
2012                         EXECUTE_STRING(ToReturn, Debug+=__T("Get, will return "); Debug+=ToReturn;)
2013                     }
2014                 }
2015                 else
2016                 {
2017                     Ztring ToReturn=HighestFormat(StreamKind, Parameter, Stream[StreamKind][StreamPos], ShouldReturn);
2018                     if (ShouldReturn)
2019                         EXECUTE_STRING(ToReturn, Debug+=__T("Get, will return "); Debug+=ToReturn;)
2020                 }
2021             }
2022             size_t Format_Pos=File__Analyze::Fill_Parameter(StreamKind, Generic_Format);
2023             #if MEDIAINFO_ADVANCED
2024             if (Config.File_ChannelLayout_Get())
2025             #endif //MEDIAINFO_ADVANCED
2026             {
2027                 Ztring ToReturn;
2028                 if (Format_Pos<Stream[StreamKind][StreamPos].size())
2029                     ToReturn=ChannelLayout_2018_Rename(StreamKind, Parameter, Stream[StreamKind][StreamPos], Stream[StreamKind][StreamPos][Format_Pos], ShouldReturn);
2030                 if (ShouldReturn)
2031                     EXECUTE_STRING(ToReturn, Debug+=__T("Get, will return "); Debug += ToReturn;)
2032             }
2033             if (Format_Pos<Stream[StreamKind][StreamPos].size() && Stream[StreamKind][StreamPos][Parameter].empty() && Parameter==File__Analyze::Fill_Parameter(StreamKind, Generic_Format_String))
2034                 EXECUTE_STRING(Stream[StreamKind][StreamPos][Format_Pos], Debug += __T("Get, will return "); Debug+=ToReturn;)
2035             EXECUTE_STRING(Stream[StreamKind][StreamPos][Parameter], Debug += __T("Get, will return "); Debug+=ToReturn;)
2036         }
2037         else
2038             EXECUTE_STRING(MediaInfoLib::Config.EmptyString_Get(), Debug+=__T("Get, will return ");Debug+=ToReturn;) //This parameter is known, but not filled
2039     }
2040     else
2041     {
2042         #if MEDIAINFO_ADVANCED
2043         if (KindOfInfo==Info_Text && Config.File_ChannelLayout_Get())
2044         #endif //MEDIAINFO_ADVANCED
2045         {
2046             size_t Format_Pos=File__Analyze::Fill_Parameter(StreamKind, Generic_Format);
2047             Ztring ToReturn;
2048             bool ShouldReturn=false;
2049             if (Format_Pos<Stream[StreamKind][StreamPos].size())
2050                 ToReturn=ChannelLayout_2018_Rename(StreamKind, Stream_More[StreamKind][StreamPos][Parameter-MediaInfoLib::Config.Info_Get(StreamKind).size()][Info_Name], Stream_More[StreamKind][StreamPos][Parameter-MediaInfoLib::Config.Info_Get(StreamKind).size()](KindOfInfo), Stream[StreamKind][StreamPos][Format_Pos], ShouldReturn);
2051             if (ShouldReturn)
2052                 EXECUTE_STRING(ToReturn, Debug+=__T("Get, will return ");Debug+=ToReturn;)
2053         }
2054         EXECUTE_STRING(Stream_More[StreamKind][StreamPos][Parameter-MediaInfoLib::Config.Info_Get(StreamKind).size()](KindOfInfo), Debug+=__T("Get, will return ");Debug+=ToReturn;)
2055     }
2056 }
2057 
2058 //---------------------------------------------------------------------------
Get(stream_t StreamKind,size_t StreamPos,const String & Parameter,info_t KindOfInfo,info_t KindOfSearch)2059 Ztring MediaInfo_Internal::Get(stream_t StreamKind, size_t StreamPos, const String &Parameter, info_t KindOfInfo, info_t KindOfSearch)
2060 {
2061     //Legacy
2062     if (Parameter.find(__T("_String"))!=Error)
2063     {
2064         Ztring S1=Parameter;
2065         S1.FindAndReplace(__T("_String"), __T("/String"));
2066         return Get(StreamKind, StreamPos, S1, KindOfInfo, KindOfSearch);
2067     }
2068     if (Parameter==__T("Channels"))
2069         return Get(StreamKind, StreamPos, __T("Channel(s)"), KindOfInfo, KindOfSearch);
2070     if (Parameter==__T("Artist"))
2071         return Get(StreamKind, StreamPos, __T("Performer"), KindOfInfo, KindOfSearch);
2072     if (Parameter==__T("AspectRatio"))
2073         return Get(StreamKind, StreamPos, __T("DisplayAspectRatio"), KindOfInfo, KindOfSearch);
2074     if (Parameter==__T("AspectRatio/String"))
2075         return Get(StreamKind, StreamPos, __T("DisplayAspectRatio/String"), KindOfInfo, KindOfSearch);
2076     if (Parameter==__T("Choregrapher"))
2077         return Get(StreamKind, StreamPos, __T("Choreographer"), KindOfInfo, KindOfSearch);
2078     if (Parameter==__T("Chroma"))
2079         return Get(StreamKind, StreamPos, __T("Colorimetry"), KindOfInfo, KindOfSearch);
2080     if (Parameter==__T("PlayTime"))
2081         return Get(StreamKind, StreamPos, __T("Duration"), KindOfInfo, KindOfSearch);
2082     if (Parameter==__T("PlayTime/String"))
2083         return Get(StreamKind, StreamPos, __T("Duration/String"), KindOfInfo, KindOfSearch);
2084     if (Parameter==__T("PlayTime/String1"))
2085         return Get(StreamKind, StreamPos, __T("Duration/String1"), KindOfInfo, KindOfSearch);
2086     if (Parameter==__T("PlayTime/String2"))
2087         return Get(StreamKind, StreamPos, __T("Duration/String2"), KindOfInfo, KindOfSearch);
2088     if (Parameter==__T("PlayTime/String3"))
2089         return Get(StreamKind, StreamPos, __T("Duration/String3"), KindOfInfo, KindOfSearch);
2090     if (StreamKind==Stream_General && Parameter==__T("BitRate"))
2091         return Get(Stream_General, StreamPos, __T("OverallBitRate"), KindOfInfo, KindOfSearch);
2092     if (StreamKind==Stream_General && Parameter==__T("BitRate/String"))
2093         return Get(Stream_General, StreamPos, __T("OverallBitRate/String"), KindOfInfo, KindOfSearch);
2094     if (StreamKind==Stream_General && Parameter==__T("BitRate_Minimum"))
2095         return Get(Stream_General, StreamPos, __T("OverallBitRate_Minimum"), KindOfInfo, KindOfSearch);
2096     if (StreamKind==Stream_General && Parameter==__T("BitRate_Minimum/String"))
2097         return Get(Stream_General, StreamPos, __T("OverallBitRate_Minimum/String"), KindOfInfo, KindOfSearch);
2098     if (StreamKind==Stream_General && Parameter==__T("BitRate_Nominal"))
2099         return Get(Stream_General, StreamPos, __T("OverallBitRate_Nominal"), KindOfInfo, KindOfSearch);
2100     if (StreamKind==Stream_General && Parameter==__T("BitRate_Nominal/String"))
2101         return Get(Stream_General, StreamPos, __T("OverallBitRate_Nominal/String"), KindOfInfo, KindOfSearch);
2102     if (StreamKind==Stream_General && Parameter==__T("BitRate_Maximum"))
2103         return Get(Stream_General, StreamPos, __T("OverallBitRate_Maximum"), KindOfInfo, KindOfSearch);
2104     if (StreamKind==Stream_General && Parameter==__T("BitRate_Maximum/String"))
2105         return Get(Stream_General, StreamPos, __T("OverallBitRate_Maximum/String"), KindOfInfo, KindOfSearch);
2106     if (Parameter==__T("AFD"))
2107         return Get(StreamKind, StreamPos, __T("ActiveFormatDescription"), KindOfInfo, KindOfSearch);
2108     if (Parameter==__T("Encoded_Application") && Info && !Info->Retrieve(StreamKind, StreamPos, "Encoded_Application/String").empty())
2109         return Get(StreamKind, StreamPos, __T("Encoded_Application/String"), KindOfInfo, KindOfSearch);
2110     if (Parameter==__T("Encoded_Library") && Info && !Info->Retrieve(StreamKind, StreamPos, "Encoded_Library/String").empty())
2111         return Get(StreamKind, StreamPos, __T("Encoded_Library/String"), KindOfInfo, KindOfSearch);
2112     if (Parameter==__T("Encoded_Library/String") && !MediaInfoLib::Config.ReadByHuman_Get())
2113     {
2114         //TODO: slight duplicate of content in Streams_Finish_HumanReadable_PerStream, should be refactorized
2115         Ztring CompanyName=Get(StreamKind, StreamPos, __T("Encoded_Library_CompanyName"));
2116         Ztring Name=Get(StreamKind, StreamPos, __T("Encoded_Library_Name"));
2117         Ztring Version=Get(StreamKind, StreamPos, __T("Encoded_Library_Version"));
2118         Ztring Date=Get(StreamKind, StreamPos, __T("Encoded_Library_Date"));
2119         Ztring Encoded_Library=Get(StreamKind, StreamPos, __T("Encoded_Library"));
2120         return File__Analyze_Encoded_Library_String(CompanyName, Name, Version, Date, Encoded_Library);
2121     }
2122     if (!Parameter.compare(0, 11, __T("DolbyVision")))
2123     {
2124         Ztring Temp=Get(StreamKind, StreamPos, __T("HDR_Format")+Parameter.substr(11), KindOfInfo, KindOfSearch).substr(14);
2125         return Temp.substr(0, Temp.find(__T(" / ")));
2126     }
2127 
2128     CS.Enter();
2129     MEDIAINFO_DEBUG_CONFIG_TEXT(Debug+=__T("Get, StreamKind=");Debug+=Ztring::ToZtring((size_t)StreamKind);Debug+=__T(", StreamKind=");Debug+=Ztring::ToZtring(StreamPos);Debug+=__T(", Parameter=");Debug+=Ztring(Parameter);)
2130 
2131     if (Info && Info->Status[File__Analyze::IsUpdated])
2132     {
2133         Info->Open_Buffer_Update();
2134         Info->Status[File__Analyze::IsUpdated]=false;
2135         for (size_t Pos=File__Analyze::User_16; Pos<File__Analyze::User_16+16; Pos++)
2136             Info->Status[Pos]=false;
2137     }
2138 
2139     //Check integrity
2140     if (StreamKind>=Stream_Max || StreamPos>=Stream[StreamKind].size() || KindOfInfo>=Info_Max)
2141     {
2142         CS.Leave();
2143         EXECUTE_STRING(MediaInfoLib::Config.EmptyString_Get(), Debug+=__T("Get, stream and/or pos is invalid will return empty string");) //Parameter is unknown
2144     }
2145 
2146     //Special cases
2147     //-Inform for a stream
2148 #if defined(MEDIAINFO_TEXT_YES) || defined(MEDIAINFO_HTML_YES) || defined(MEDIAINFO_XML_YES) || defined(MEDIAINFO_CSV_YES) || defined(MEDIAINFO_CUSTOM_YES)
2149     if (Parameter==__T("Inform"))
2150     {
2151         CS.Leave();
2152         const Ztring InformZtring=Inform(StreamKind, StreamPos, true);
2153         CS.Enter();
2154         size_t Pos=MediaInfoLib::Config.Info_Get(StreamKind).Find(__T("Inform"));
2155         if (Pos!=Error)
2156             Stream[StreamKind][StreamPos](Pos)=InformZtring;
2157     }
2158 #endif
2159 
2160     //Case of specific info
2161     size_t ParameterI=MediaInfoLib::Config.Info_Get(StreamKind).Find(Parameter, KindOfSearch);
2162     if (ParameterI==Error)
2163     {
2164         ParameterI=Stream_More[StreamKind][StreamPos].Find(Parameter, KindOfSearch);
2165         if (ParameterI==Error)
2166         {
2167             #ifdef MEDIAINFO_DEBUG_WARNING_GET
2168                 if (Ztring(Parameter)!=__T("SCTE35_PID")) //TODO: define a special interface for parser-specific parameters
2169                     std::cerr<<"MediaInfo: Warning, Get(), parameter \""<<Ztring(Parameter).To_Local()<<"\""<<std::endl;
2170             #endif //MEDIAINFO_DEBUG_WARNING_GET
2171 
2172             CS.Leave();
2173             EXECUTE_STRING(MediaInfoLib::Config.EmptyString_Get(), Debug+=__T("Get, parameter is unknown, will return empty string");) //Parameter is unknown
2174         }
2175         CS.Leave();
2176         CriticalSectionLocker CSL(CS);
2177         #if MEDIAINFO_ADVANCED
2178         if (KindOfInfo==Info_Text && Config.File_ChannelLayout_Get())
2179         #endif //MEDIAINFO_ADVANCED
2180         {
2181             size_t Format_Pos=File__Analyze::Fill_Parameter(StreamKind, Generic_Format);
2182             Ztring ToReturn;
2183             bool ShouldReturn=false;
2184             if (Format_Pos<Stream[StreamKind][StreamPos].size())
2185                 ToReturn=ChannelLayout_2018_Rename(StreamKind, Stream_More[StreamKind][StreamPos][ParameterI][Info_Name], Stream_More[StreamKind][StreamPos][ParameterI](KindOfInfo), Stream[StreamKind][StreamPos][Format_Pos], ShouldReturn);
2186             if (ShouldReturn)
2187                 EXECUTE_STRING(ToReturn, Debug+=__T("Get, will return ");Debug+=ToReturn;)
2188         }
2189         EXECUTE_STRING(Stream_More[StreamKind][StreamPos][ParameterI](KindOfInfo), Debug+=__T("Get, will return ");Debug+=ToReturn;)
2190     }
2191 
2192     CS.Leave();
2193 
2194     EXECUTE_STRING(Get(StreamKind, StreamPos, ParameterI, KindOfInfo), Debug+=__T("Get, will return ");Debug+=ToReturn;)
2195 }
2196 
2197 //***************************************************************************
2198 // Set File info
2199 //***************************************************************************
2200 
2201 //---------------------------------------------------------------------------
Set(const String & ToSet,stream_t StreamKind,size_t StreamPos,size_t Parameter,const String & OldValue)2202 size_t MediaInfo_Internal::Set(const String &ToSet, stream_t StreamKind, size_t StreamPos, size_t Parameter, const String &OldValue)
2203 {
2204     CriticalSectionLocker CSL(CS);
2205     if (!Info)
2206         return 0;
2207 
2208     return Info->Set(StreamKind, StreamPos, Parameter, ToSet, OldValue);
2209 }
2210 
2211 //---------------------------------------------------------------------------
Set(const String & ToSet,stream_t StreamKind,size_t StreamPos,const String & Parameter,const String & OldValue)2212 size_t MediaInfo_Internal::Set(const String &ToSet, stream_t StreamKind, size_t StreamPos, const String &Parameter, const String &OldValue)
2213 {
2214     CriticalSectionLocker CSL(CS);
2215     if (!Info)
2216         return 0;
2217 
2218     return Info->Set(StreamKind, StreamPos, Parameter, ToSet, OldValue);
2219 }
2220 
2221 //***************************************************************************
2222 // Output buffer
2223 //***************************************************************************
2224 
2225 //---------------------------------------------------------------------------
Output_Buffer_Get(const String & Value)2226 size_t MediaInfo_Internal::Output_Buffer_Get (const String &Value)
2227 {
2228     CriticalSectionLocker CSL(CS);
2229     if (!Info)
2230         return 0;
2231 
2232     MEDIAINFO_DEBUG_OUTPUT_VALUE(Value, Info->Output_Buffer_Get(Value));
2233 }
2234 
2235 //---------------------------------------------------------------------------
Output_Buffer_Get(size_t Pos)2236 size_t MediaInfo_Internal::Output_Buffer_Get (size_t Pos)
2237 {
2238     CriticalSectionLocker CSL(CS);
2239     if (!Info)
2240         return 0;
2241 
2242     MEDIAINFO_DEBUG_OUTPUT_POS(Pos, Info->Output_Buffer_Get(Pos));
2243 }
2244 
2245 //***************************************************************************
2246 // Information
2247 //***************************************************************************
2248 
2249 //---------------------------------------------------------------------------
Option(const String & Option,const String & Value)2250 String MediaInfo_Internal::Option (const String &Option, const String &Value)
2251 {
2252     CriticalSectionLocker CSL(CS);
2253     MEDIAINFO_DEBUG_CONFIG_TEXT(Debug+=__T("Option, Option=");Debug+=Ztring(Option);Debug+=__T(", Value=");Debug+=Ztring(Value);)
2254     Ztring OptionLower=Option; OptionLower.MakeLowerCase();
2255     if (Option.empty())
2256         return String();
2257     else if (OptionLower==__T("language_update"))
2258     {
2259         if (!Info || Info->Get(Stream_General, 0, __T("CompleteName"))==__T(""))
2260             return __T("");
2261 
2262         ZtringListList Language=Value.c_str();
2263         MediaInfoLib::Config.Language_Set(Language);
2264 
2265         return __T("");
2266     }
2267     else if (OptionLower==__T("create_dummy"))
2268     {
2269         CreateDummy (Value);
2270         delete Info; Info=NULL;
2271         return __T("");
2272     }
2273     else if (OptionLower==__T("thread"))
2274     {
2275         BlockMethod=1;
2276         return __T("");
2277     }
2278     else if (Option==__T("info_capacities"))
2279     {
2280         return __T("Option removed");
2281     }
2282     #if MEDIAINFO_TRACE
2283     else if (OptionLower.find(__T("file_details_clear"))==0)
2284     {
2285         if (Info)
2286             Info->Details_Clear();
2287 
2288         return __T("");
2289     }
2290     #endif //MEDIAINFO_TRACE
2291     else if (OptionLower.find(__T("file_seek"))==0)
2292     {
2293         #if MEDIAINFO_SEEK
2294             #if !defined(MEDIAINFO_READER_NO)
2295                 if (Reader==NULL && Info==NULL)
2296                     return __T("Error: Reader pointer is empty");
2297             #endif //MEDIAINFO_READER_NO
2298 
2299             size_t Method=(size_t)-1;
2300             int64u SeekValue=(int64u)-1;
2301             int64u ID=(int64u)-1;
2302 
2303             ZtringList List; List.Separator_Set(0, __T(","));
2304             List.Write(Value);
2305             for (size_t Pos=0; Pos<List.size(); Pos++)
2306             {
2307                 if (!List[Pos].empty() && List[Pos].find(__T('%'))==List[Pos].size()-1)
2308                 {
2309                     Method=1;
2310                     SeekValue=(int64u)(Ztring(List[Pos]).To_float32()*100);
2311                 }
2312                 else if (!List[Pos].empty() && List[Pos].find_first_not_of(__T("0123456789"))==string::npos)
2313                 {
2314                     Method=0;
2315                     SeekValue=Ztring(List[Pos]).To_int64u();
2316                 }
2317                 else if (!List[Pos].empty() && List[Pos].find(__T("Frame="))!=string::npos)
2318                 {
2319                     Method=3;
2320                     Ztring FrameNumberZ=List[Pos].substr(List[Pos].find(__T("Frame="))+6, string::npos);
2321                     SeekValue=FrameNumberZ.To_int64u();
2322                 }
2323                 else if (!List[Pos].empty() && List[Pos].find(__T(':'))!=string::npos)
2324                 {
2325                     Method=2;
2326                     Ztring ValueZ=List[Pos];
2327                     SeekValue=0;
2328                     size_t Value_Pos=ValueZ.find(__T(':'));
2329                     if (Value_Pos==string::npos)
2330                         Value_Pos=ValueZ.size();
2331                     SeekValue+=Ztring(ValueZ.substr(0, Value_Pos)).To_int64u()*60*60*1000*1000*1000;
2332                     ValueZ.erase(0, Value_Pos+1);
2333                     Value_Pos=ValueZ.find(__T(':'));
2334                     if (Value_Pos==string::npos)
2335                         Value_Pos=ValueZ.size();
2336                     SeekValue+=Ztring(ValueZ.substr(0, Value_Pos)).To_int64u()*60*1000*1000*1000;
2337                     ValueZ.erase(0, Value_Pos+1);
2338                     Value_Pos=ValueZ.find(__T('.'));
2339                     if (Value_Pos==string::npos)
2340                         Value_Pos=ValueZ.size();
2341                     SeekValue+=Ztring(ValueZ.substr(0, Value_Pos)).To_int64u()*1000*1000*1000;
2342                     ValueZ.erase(0, Value_Pos+1);
2343                     if (!ValueZ.empty())
2344                         SeekValue+=Ztring(ValueZ).To_int64u()*1000*1000*1000/(int64u)pow(10.0, (int)ValueZ.size());
2345                 }
2346                 else if (!List[Pos].empty() && List[Pos].find(__T("ID="))!=string::npos)
2347                 {
2348                     Ztring IDZ=List[Pos].substr(List[Pos].find(__T("ID="))+3, string::npos);
2349                     ID=IDZ.To_int64u();
2350                 }
2351             }
2352 
2353             CS.Leave();
2354             size_t Result;
2355             #if !defined(MEDIAINFO_READER_NO)
2356                 if (Reader)
2357                     Result=Reader->Format_Test_PerParser_Seek(this, Method, SeekValue, ID);
2358                 else
2359             #endif //MEDIAINFO_READER_NO
2360                     Result=Open_Buffer_Seek(Method, SeekValue, ID);
2361             CS.Enter();
2362             switch (Result)
2363             {
2364                 case 1  : return __T("");
2365                 case 2  : return __T("Invalid value");
2366                 #if MEDIAINFO_IBIUSAGE
2367                 case 3  : return __T("Feature not supported / IBI file not provided");
2368                 case 4  : return __T("Problem during IBI file parsing");
2369                 #endif //MEDIAINFO_IBIUSAGE
2370                 case 5  : return __T("Invalid ID");
2371                 case 6  : return __T("Internal error");
2372                 #if !MEDIAINFO_IBIUSAGE
2373                 case (size_t)-2 : return __T("Feature not supported / IBI support disabled due to compilation options");
2374                 #endif //MEDIAINFO_IBIUSAGE
2375                 case (size_t)-1 : return __T("Feature not supported");
2376                 default : return __T("Unknown error");
2377             }
2378         #else //MEDIAINFO_SEEK
2379             return __T("Seek manager is disabled due to compilation options");
2380         #endif //MEDIAINFO_SEEK
2381     }
2382     #if MEDIAINFO_TRACE
2383         if (OptionLower.find(__T("file_details_stringpointer")) == 0 && MediaInfoLib::Config.Inform_Get()!=__T("MAXML") && (MediaInfoLib::Config.Trace_Level_Get() || MediaInfoLib::Config.Inform_Get()==__T("Details")) && !Details.empty())
2384         {
2385             return Ztring::ToZtring((int64u)Details.data())+__T(':')+Ztring::ToZtring((int64u)Details.size());
2386         }
2387     #endif //MEDIAINFO_TRACE
2388     #if MEDIAINFO_ADVANCED
2389         if (OptionLower.find(__T("file_inform_stringpointer")) == 0)
2390         {
2391             Inform_Cache = Inform(this).To_UTF8();
2392             #if MEDIAINFO_COMPRESS
2393                 if (Value.find(__T("zlib"))==0)
2394                 {
2395                     uLongf Compressed_Size=(uLongf)(Inform_Cache.size() + 16);
2396                     Bytef* Compressed=new Bytef[Inform_Cache.size()+16];
2397                     if (compress(Compressed, &Compressed_Size, (const Bytef*)Inform_Cache.c_str(), (uLong)Inform_Cache.size()) < 0)
2398                     {
2399                         delete[] Compressed;
2400                         return __T("Error during zlib compression");
2401                     }
2402                     Inform_Cache.assign((char*)Compressed, (size_t)Compressed_Size);
2403                     if (Value.find(__T("+base64"))+7==Value.size())
2404                     {
2405                         Inform_Cache=Base64::encode(Inform_Cache);
2406                     }
2407                 }
2408             #endif //MEDIAINFO_COMPRESS
2409             return Ztring::ToZtring((int64u)Inform_Cache.data()) + __T(':') + Ztring::ToZtring((int64u)Inform_Cache.size());
2410         }
2411     #endif //MEDIAINFO_ADVANCED
2412     else if (OptionLower.find(__T("reset"))==0)
2413     {
2414         MediaInfoLib::Config.Init(true);
2415         return Ztring();
2416     }
2417     else if (OptionLower.find(__T("file_"))==0)
2418     {
2419         Ztring ToReturn2=Config.Option(Option, Value);
2420         if (Info)
2421             Info->Option_Manage();
2422 
2423         MEDIAINFO_DEBUG_OUTPUT_INIT(ToReturn2, Debug+=__T("Option, will return ");Debug+=ToReturn;)
2424     }
2425     else
2426         EXECUTE_STRING(MediaInfoLib::Config.Option(Option, Value), Debug+=__T("Option, will return ");Debug+=ToReturn;)
2427 }
2428 
2429 //---------------------------------------------------------------------------
Count_Get(stream_t StreamKind,size_t StreamPos)2430 size_t MediaInfo_Internal::Count_Get (stream_t StreamKind, size_t StreamPos)
2431 {
2432     CriticalSectionLocker CSL(CS);
2433 
2434     if (Info && Info->Status[File__Analyze::IsUpdated])
2435     {
2436         Info->Open_Buffer_Update();
2437         Info->Status[File__Analyze::IsUpdated]=false;
2438         for (size_t Pos=File__Analyze::User_16; Pos<File__Analyze::User_16+16; Pos++)
2439             Info->Status[Pos]=false;
2440     }
2441 
2442     //Integrity
2443     if (StreamKind>=Stream_Max)
2444         return 0;
2445 
2446     //Count of streams
2447     if (StreamPos==Error)
2448         return Stream[StreamKind].size();
2449 
2450     //Integrity
2451     if (StreamPos>=Stream[StreamKind].size())
2452         return 0;
2453 
2454     //Count of piece of information in a stream
2455     return MediaInfoLib::Config.Info_Get(StreamKind).size()+Stream_More[StreamKind][StreamPos].size();
2456 }
2457 
2458 //---------------------------------------------------------------------------
State_Get()2459 size_t MediaInfo_Internal::State_Get ()
2460 {
2461     return (size_t)(Config.State_Get()*10000);
2462 }
2463 
2464 //---------------------------------------------------------------------------
2465 #if defined(MEDIAINFO_FILE_YES)
TestContinuousFileNames()2466 void MediaInfo_Internal::TestContinuousFileNames ()
2467 {
2468     CriticalSectionLocker CSL(CS);
2469     if (Info)
2470         Info->TestContinuousFileNames();
2471 }
2472 #endif //defined(MEDIAINFO_FILE_YES)
2473 
2474 //---------------------------------------------------------------------------
2475 #if MEDIAINFO_EVENTS
Event_Prepare(struct MediaInfo_Event_Generic * Event,int32u Event_Code,size_t Event_Size)2476 void MediaInfo_Internal::Event_Prepare (struct MediaInfo_Event_Generic* Event, int32u Event_Code, size_t Event_Size)
2477 {
2478     CriticalSectionLocker CSL(CS);
2479     if (Info)
2480         Info->Event_Prepare(Event, Event_Code, Event_Size);
2481 }
2482 #endif // MEDIAINFO_EVENTS
2483 
2484 //---------------------------------------------------------------------------
Inform(MediaInfo_Internal * Info)2485 Ztring MediaInfo_Internal::Inform(MediaInfo_Internal* Info)
2486 {
2487     std::vector<MediaInfoLib::MediaInfo_Internal*> Info2;
2488     Info2.push_back(Info);
2489     return MediaInfoLib::MediaInfo_Internal::Inform(Info2);
2490 }
2491 
2492 //---------------------------------------------------------------------------
Inform(std::vector<MediaInfo_Internal * > & Info)2493 Ztring MediaInfo_Internal::Inform(std::vector<MediaInfo_Internal*>& Info)
2494 {
2495     Ztring Result;
2496 
2497     #if defined(MEDIAINFO_XML_YES)
2498     if (MediaInfoLib::Config.Inform_Get()==__T("MAXML"))
2499     {
2500         Result+=__T("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")+MediaInfoLib::Config.LineSeparator_Get();
2501         Result+=__T('<');
2502         Result+=__T("MediaArea");
2503         Result+=MediaInfoLib::Config.LineSeparator_Get();
2504         Result+=__T("    xmlns=\"http")+(MediaInfoLib::Config.Https_Get()?Ztring(__T("s")):Ztring())+__T("://mediaarea.net/mediaarea\"");
2505         Result+=MediaInfoLib::Config.LineSeparator_Get();
2506         Result+=__T("    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
2507         Result+=MediaInfoLib::Config.LineSeparator_Get();
2508         Result+=__T("    xsi:schemaLocation=\"http")+(MediaInfoLib::Config.Https_Get()?Ztring(__T("s")):Ztring())+__T("://mediaarea.net/mediaarea http")+(MediaInfoLib::Config.Https_Get()?Ztring(__T("s")):Ztring())+__T("://mediaarea.net/mediaarea/mediaarea_0_1.xsd\"");
2509         Result+=MediaInfoLib::Config.LineSeparator_Get();
2510         Result+=__T("    version=\"0.1\"");
2511         Result+=__T(">")+MediaInfoLib::Config.LineSeparator_Get();
2512         Result+=__T("<creatingLibrary version=\"")+Ztring(MediaInfo_Version).SubString(__T(" - v"), Ztring())+__T("\" url=\"http")+(MediaInfoLib::Config.Https_Get()?Ztring(__T("s")):Ztring())+__T("://mediaarea.net/MediaInfo\">MediaInfoLib</creatingLibrary>");
2513         Result+=MediaInfoLib::Config.LineSeparator_Get();
2514 
2515         for (size_t FilePos=0; FilePos<Info.size(); FilePos++)
2516             Result+=Info[FilePos]->Inform();
2517 
2518         if (!Result.empty() && Result[Result.size()-1]!=__T('\r') && Result[Result.size()-1]!=__T('\n'))
2519             Result+=MediaInfoLib::Config.LineSeparator_Get();
2520         Result+=__T("</MediaArea");
2521         Result+=__T(">")+MediaInfoLib::Config.LineSeparator_Get();
2522     }
2523 
2524     else if (MediaInfoLib::Config.Trace_Level_Get() && MediaInfoLib::Config.Trace_Format_Get()==MediaInfoLib::Config.Trace_Format_XML)
2525     {
2526         Result+=__T("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")+MediaInfoLib::Config.LineSeparator_Get();
2527         Result+=__T('<');
2528         Result+=__T("MediaTrace");
2529         Result+=MediaInfoLib::Config.LineSeparator_Get();
2530         Result+=__T("    xmlns=\"http")+(MediaInfoLib::Config.Https_Get()?Ztring(__T("s")):Ztring())+__T("://mediaarea.net/mediatrace\"");
2531         Result+=MediaInfoLib::Config.LineSeparator_Get();
2532         Result+=__T("    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
2533         Result+=MediaInfoLib::Config.LineSeparator_Get();
2534         Result+=__T("    xsi:schemaLocation=\"http")+(MediaInfoLib::Config.Https_Get()?Ztring(__T("s")):Ztring())+__T("://mediaarea.net/mediatrace http")+(MediaInfoLib::Config.Https_Get()?Ztring(__T("s")):Ztring())+__T("://mediaarea.net/mediatrace/mediatrace_0_1.xsd\"");
2535         Result+=MediaInfoLib::Config.LineSeparator_Get();
2536         Result+=__T("    version=\"0.1\"");
2537         Result+=__T(">")+MediaInfoLib::Config.LineSeparator_Get();
2538         Result+=__T("<creatingLibrary version=\"")+Ztring(MediaInfo_Version).SubString(__T(" - v"), Ztring())+__T("\" url=\"http")+(MediaInfoLib::Config.Https_Get()?Ztring(__T("s")):Ztring())+__T("://mediaarea.net/MediaInfo\">MediaInfoLib</creatingLibrary>");
2539         Result+=MediaInfoLib::Config.LineSeparator_Get();
2540 
2541         for (size_t FilePos=0; FilePos<Info.size(); FilePos++)
2542         {
2543             size_t Modified;
2544             Result+=__T("<media");
2545             Ztring Options=Info[FilePos]->Get(Stream_General, 0, General_CompleteName, Info_Options);
2546             if (InfoOption_ShowInInform<Options.size() && Options[InfoOption_ShowInInform]==__T('Y'))
2547                 Result+=__T(" ref=\"")+MediaInfo_Internal::Xml_Content_Escape(Info[FilePos]->Get(Stream_General, 0, General_CompleteName), Modified)+__T("\"");
2548             if (Info[FilePos] && !Info[FilePos]->ParserName.empty())
2549                 Result+=__T(" parser=\"")+Info[FilePos]->ParserName+=__T("\"");
2550             Result+= __T('>');
2551             Result+=MediaInfoLib::Config.LineSeparator_Get();
2552             Result+=Info[FilePos]->Inform();
2553             if (!Result.empty() && Result[Result.size()-1]!=__T('\r') && Result[Result.size()-1]!=__T('\n'))
2554                 Result+=MediaInfoLib::Config.LineSeparator_Get();
2555             Result+=__T("</media>");
2556             Result+=MediaInfoLib::Config.LineSeparator_Get();
2557         }
2558 
2559         if (!Result.empty() && Result[Result.size()-1]!=__T('\r') && Result[Result.size()-1]!=__T('\n'))
2560             Result+=MediaInfoLib::Config.LineSeparator_Get();
2561         Result+=__T("</MediaTrace");
2562         Result+=__T(">")+MediaInfoLib::Config.LineSeparator_Get();
2563     }
2564 
2565     else if (MediaInfoLib::Config.Trace_Level_Get() && MediaInfoLib::Config.Trace_Format_Get()==MediaInfoLib::Config.Trace_Format_MICRO_XML)
2566     {
2567         Result+=__T("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")+MediaInfoLib::Config.LineSeparator_Get();
2568         Result+=__T('<');
2569         Result+=__T("MicroMediaTrace");
2570         Result+=__T(" xmlns=\"http")+(MediaInfoLib::Config.Https_Get()?Ztring(__T("s")):Ztring())+__T("://mediaarea.net/micromediatrace\"");
2571         Result+=__T(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
2572         Result+=__T(" mtsl=\"http")+(MediaInfoLib::Config.Https_Get()?Ztring(__T("s")):Ztring())+__T("://mediaarea.net/micromediatrace http")+(MediaInfoLib::Config.Https_Get()?Ztring(__T("s")):Ztring())+__T("://mediaarea.net/micromediatrace/micromediatrace.xsd\"");
2573         Result+=__T(" version=\"0.1\">");
2574         Result+=__T("<creatingLibrary version=\"")+Ztring(MediaInfo_Version).SubString(__T(" - v"), Ztring())+__T("\" url=\"http")+(MediaInfoLib::Config.Https_Get()?Ztring(__T("s")):Ztring())+__T("://mediaarea.net/MediaInfo\">MediaInfoLib</creatingLibrary>");
2575 
2576         for (size_t FilePos=0; FilePos<Info.size(); FilePos++)
2577         {
2578             size_t Modified;
2579             Result+=__T("<media");
2580             Ztring Options=Info[FilePos]->Get(Stream_General, 0, General_CompleteName, Info_Options);
2581             if (InfoOption_ShowInInform<Options.size() && Options[InfoOption_ShowInInform]==__T('Y'))
2582                 Result+=__T(" ref=\"")+MediaInfo_Internal::Xml_Content_Escape(Info[FilePos]->Get(Stream_General, 0, General_CompleteName), Modified)+__T("\"");
2583             if (Info[FilePos] && !Info[FilePos]->ParserName.empty())
2584                 Result+=__T(" parser=\"")+Info[FilePos]->ParserName+=__T("\"");
2585             Result+= __T('>');
2586             Result+=Info[FilePos]->Inform();
2587             Result+=__T("</media>");
2588         }
2589 
2590         Result+=__T("</MicroMediaTrace>");
2591     }
2592 
2593     else if (MediaInfoLib::Config.Inform_Get()==__T("XML") || MediaInfoLib::Config.Inform_Get()==__T("MIXML"))
2594     {
2595         Result+=__T("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")+MediaInfoLib::Config.LineSeparator_Get();
2596         Result+=__T('<');
2597         Result+=__T("MediaInfo");
2598         Result+=MediaInfoLib::Config.LineSeparator_Get();
2599         Result+=__T("    xmlns=\"http")+(MediaInfoLib::Config.Https_Get()?Ztring(__T("s")):Ztring())+__T("://mediaarea.net/mediainfo\"");
2600         Result+=MediaInfoLib::Config.LineSeparator_Get();
2601         Result+=__T("    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
2602         Result+=MediaInfoLib::Config.LineSeparator_Get();
2603         Result+=__T("    xsi:schemaLocation=\"http")+(MediaInfoLib::Config.Https_Get()?Ztring(__T("s")):Ztring())+__T("://mediaarea.net/mediainfo http")+(MediaInfoLib::Config.Https_Get()?Ztring(__T("s")):Ztring())+__T("://mediaarea.net/mediainfo/mediainfo_2_0.xsd\"");
2604         Result+=MediaInfoLib::Config.LineSeparator_Get();
2605         Result+=__T("    version=\"2.0\"");
2606         Result+=__T(">")+MediaInfoLib::Config.LineSeparator_Get();
2607         Result+=__T("<creatingLibrary version=\"")+Ztring(MediaInfo_Version).SubString(__T(" - v"), Ztring())+__T("\" url=\"http")+(MediaInfoLib::Config.Https_Get()?Ztring(__T("s")):Ztring())+__T("://mediaarea.net/MediaInfo\">MediaInfoLib</creatingLibrary>");
2608         Result+=MediaInfoLib::Config.LineSeparator_Get();
2609 
2610         for (size_t FilePos=0; FilePos<Info.size(); FilePos++)
2611             Result+=Info[FilePos]->Inform();
2612 
2613         if (!Result.empty() && Result[Result.size()-1]!=__T('\r') && Result[Result.size()-1]!=__T('\n'))
2614             Result+=MediaInfoLib::Config.LineSeparator_Get();
2615         Result+=__T("</MediaInfo");
2616         Result+=__T(">")+MediaInfoLib::Config.LineSeparator_Get();
2617     }
2618     else
2619     #endif //defined(MEDIAINFO_XML_YES)
2620     #if defined(MEDIAINFO_JSON_YES)
2621     if (MediaInfoLib::Config.Inform_Get()==__T("JSON"))
2622     {
2623         if (Info.size() > 1)
2624             Result+=__T("[")+MediaInfoLib::Config.LineSeparator_Get();
2625         for (size_t FilePos=0; FilePos<Info.size(); FilePos++)
2626         {
2627             Result+=Info[FilePos]->Inform();
2628 
2629             if (FilePos < Info.size() -1)
2630                 Result+=__T(",");
2631 
2632             Result+=MediaInfoLib::Config.LineSeparator_Get();
2633         }
2634         if (Info.size() > 1)
2635             Result+=__T("]")+MediaInfoLib::Config.LineSeparator_Get();
2636     }
2637     else
2638     #endif //defined(MEDIAINFO_JSON_YES)
2639     {
2640         size_t FilePos=0;
2641         ZtringListList MediaInfo_Custom_View; MediaInfo_Custom_View.Write(MediaInfoLib::Config.Option(__T("Inform_Get")));
2642         #if defined(MEDIAINFO_XML_YES)
2643         bool XML=false;
2644         if (MediaInfoLib::Config.Inform_Get()==__T("OLDXML"))
2645             XML=true;
2646         if (XML)
2647         {
2648             Result+=__T("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")+MediaInfoLib::Config.LineSeparator_Get();
2649             Result+=__T("<Mediainfo version=\"")+MediaInfoLib::Config.Info_Version_Get().SubString(__T(" v"), Ztring())+__T("\">");
2650             Result+=MediaInfoLib::Config.LineSeparator_Get();
2651         }
2652         else
2653         #endif //defined(MEDIAINFO_XML_YES)
2654         Result+=MediaInfo_Custom_View("Page_Begin");
2655         while (FilePos<Info.size())
2656         {
2657             Result+=Info[FilePos]->Inform();
2658             if (FilePos<Info.size()-1)
2659             {
2660                 Result+=MediaInfo_Custom_View("Page_Middle");
2661             }
2662             FilePos++;
2663         }
2664         #if defined(MEDIAINFO_XML_YES)
2665         if (XML)
2666         {
2667             if (!Result.empty() && Result[Result.size()-1]!=__T('\r') && Result[Result.size()-1]!=__T('\n'))
2668                 Result+=MediaInfoLib::Config.LineSeparator_Get();
2669             Result+=__T("</");
2670             if (MediaInfoLib::Config.Trace_Format_Get()==MediaInfoLib::Config.Trace_Format_XML)
2671                 Result+=__T("MediaTrace");
2672             else if (MediaInfoLib::Config.Trace_Format_Get()==MediaInfoLib::Config.Trace_Format_MICRO_XML)
2673                 Result+=__T("MicroMediaTrace");
2674             else
2675                 Result+=__T("Mediainfo");
2676             Result+=__T(">")+MediaInfoLib::Config.LineSeparator_Get();
2677         }
2678         else
2679         #endif //defined(MEDIAINFO_XML_YES)
2680             Result+=MediaInfo_Custom_View("Page_End");//
2681     }
2682 
2683     #if MEDIAINFO_COMPRESS
2684         bool zlib=MediaInfoLib::Config.FlagsX_Get(Flags_Inform_zlib);
2685         bool base64=MediaInfoLib::Config.FlagsX_Get(Flags_Inform_base64);
2686         if (zlib || base64)
2687         {
2688             string Inform_Cache = Result.To_UTF8();
2689             if (zlib)
2690             {
2691                 uLongf Compressed_Size=(uLongf)(Inform_Cache.size() + 16);
2692                 Bytef* Compressed=new Bytef[Inform_Cache.size()+16];
2693                 if (compress(Compressed, &Compressed_Size, (const Bytef*)Inform_Cache.c_str(), (uLong)Inform_Cache.size()) < 0)
2694                 {
2695                     delete[] Compressed;
2696                     return __T("Error during zlib compression");
2697                 }
2698                 Inform_Cache.assign((char*)Compressed, (size_t)Compressed_Size);
2699             }
2700             if (base64)
2701             {
2702                 Inform_Cache=Base64::encode(Inform_Cache);
2703             }
2704             Result.From_UTF8(Inform_Cache);
2705         }
2706     #endif //MEDIAINFO_COMPRESS
2707 
2708     return Result.c_str();
2709 }
2710 
2711 } //NameSpace
2712