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