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 //
9 // Init and Finalize part
10 //
11 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12 
13 //---------------------------------------------------------------------------
14 // Pre-compilation
15 #include "MediaInfo/PreComp.h"
16 #ifdef __BORLANDC__
17     #pragma hdrstop
18 #endif
19 //---------------------------------------------------------------------------
20 
21 //---------------------------------------------------------------------------
22 #include "MediaInfo/Setup.h"
23 //---------------------------------------------------------------------------
24 
25 //---------------------------------------------------------------------------
26 #include "ZenLib/Utils.h"
27 #if defined(MEDIAINFO_FILE_YES)
28 #include "ZenLib/File.h"
29 #endif //defined(MEDIAINFO_FILE_YES)
30 #include "ZenLib/FileName.h"
31 #include "MediaInfo/File__Analyze.h"
32 #include "MediaInfo/MediaInfo_Config_MediaInfo.h"
33 #include "MediaInfo/MediaInfo_Internal.h"
34 #if MEDIAINFO_IBI
35     #include "MediaInfo/Multiple/File_Ibi.h"
36 #endif //MEDIAINFO_IBI
37 #if MEDIAINFO_FIXITY
38     #ifndef WINDOWS
39     //ZenLib has File::Copy only for Windows for the moment. //TODO: support correctly (including meta)
40     #include <fstream>
41     #endif //WINDOWS
42 #endif //MEDIAINFO_FIXITY
43 using namespace ZenLib;
44 //---------------------------------------------------------------------------
45 
46 namespace MediaInfoLib
47 {
48 
49 //---------------------------------------------------------------------------
50 extern MediaInfo_Config Config;
51 //---------------------------------------------------------------------------
52 
53 //---------------------------------------------------------------------------
File__Analyze_Encoded_Library_String(const Ztring & CompanyName,const Ztring & Name,const Ztring & Version,const Ztring & Date,const Ztring & Encoded_Library)54 Ztring File__Analyze_Encoded_Library_String (const Ztring &CompanyName, const Ztring &Name, const Ztring &Version, const Ztring &Date, const Ztring &Encoded_Library)
55 {
56     if (!Name.empty())
57     {
58         Ztring String;
59         if (!CompanyName.empty())
60         {
61             String+=CompanyName;
62             String+=__T(" ");
63         }
64         String+=Name;
65         if (!Version.empty())
66         {
67             String+=__T(" ");
68             String+=Version;
69         }
70         if (!Date.empty())
71         {
72             String+=__T(" (");
73             String+=Date;
74             String+=__T(")");
75         }
76         return String;
77     }
78     else
79         return Encoded_Library;
80 }
81 
82 //---------------------------------------------------------------------------
Streams_Finish_Global()83 void File__Analyze::Streams_Finish_Global()
84 {
85     if (IsSub)
86         return;
87 
88     TestDirectory();
89 
90     #if MEDIAINFO_ADVANCED
91         if (MediaInfoLib::Config.ExternalMetaDataConfig_Get().empty()) // ExternalMetadata is used directly only if there is no ExternalMetadata config (=another format)
92         {
93             Ztring ExternalMetadata=MediaInfoLib::Config.ExternalMetadata_Get();
94             if (!ExternalMetadata.empty())
95             {
96                 ZtringListList List;
97                 List.Separator_Set(0, MediaInfoLib::Config.LineSeparator_Get());
98                 List.Separator_Set(1, __T(";"));
99                 List.Write(ExternalMetadata);
100 
101                 for (size_t i=0; i<List.size(); i++)
102                 {
103                     // col 1&2 can be removed, conidered as "General;0"
104                     // 1: stream kind (General, Video, Audio, Text...)
105                     // 2: 0-based stream number
106                     // 3: field name
107                     // 4: field value
108                     // 5 (optional): replace instead of ignoring if field is already present (metadata from the file)
109                     if (List[i].size()<2 || List[i].size()>5)
110                     {
111                         MediaInfoLib::Config.Log_Send(0xC0, 0xFF, 0, "Invalid column size for external metadata");
112                         continue;
113                     }
114 
115                     Ztring StreamKindZ=Ztring(List[i][0]).MakeLowerCase();
116                     stream_t StreamKind;
117                     size_t   Offset;
118                     if (List[i].size()<4)
119                     {
120                         StreamKind=Stream_General;
121                         Offset=2;
122                     }
123                     else
124                     {
125                         Offset=0;
126                              if (StreamKindZ==__T("general"))   StreamKind=Stream_General;
127                         else if (StreamKindZ==__T("video"))     StreamKind=Stream_Video;
128                         else if (StreamKindZ==__T("audio"))     StreamKind=Stream_Audio;
129                         else if (StreamKindZ==__T("text"))      StreamKind=Stream_Text;
130                         else if (StreamKindZ==__T("other"))     StreamKind=Stream_Other;
131                         else if (StreamKindZ==__T("image"))     StreamKind=Stream_Image;
132                         else if (StreamKindZ==__T("menu"))      StreamKind=Stream_Menu;
133                         else
134                         {
135                             MediaInfoLib::Config.Log_Send(0xC0, 0xFF, 0, "Invalid column 0 for external metadata");
136                             continue;
137                         }
138                     }
139                     size_t StreamPos=(size_t)List[i][1].To_int64u();
140                     bool ShouldReplace=List[i].size()>4-Offset && List[i][4-Offset].To_int64u();
141                     if (ShouldReplace || Retrieve_Const(StreamKind, StreamPos, List[i][2-Offset].To_UTF8().c_str()).empty())
142                         Fill(StreamKind, StreamPos, List[i][2-Offset].To_UTF8().c_str(), List[i][3-Offset], ShouldReplace);
143                 }
144             }
145         }
146     #endif //MEDIAINFO_ADVANCED
147 
148     #if MEDIAINFO_ADVANCED
149         //Default frame rate
150         if (Count_Get(Stream_Video)==1 && Retrieve(Stream_Video, 0, Video_FrameRate).empty() && Config->File_DefaultFrameRate_Get())
151             Fill(Stream_Video, 0, Video_FrameRate, Config->File_DefaultFrameRate_Get());
152     #endif //MEDIAINFO_ADVANCED
153 
154     //Video Frame count
155     if (Count_Get(Stream_Video)==1 && Count_Get(Stream_Audio)==0 && Retrieve(Stream_Video, 0, Video_FrameCount).empty())
156     {
157         if (Frame_Count_NotParsedIncluded!=(int64u)-1 && File_Offset+Buffer_Size==File_Size)
158             Fill(Stream_Video, 0, Video_FrameCount, Frame_Count_NotParsedIncluded);
159         else if (Config->File_Names.size()>1 && StreamSource==IsStream)
160             Fill(Stream_Video, 0, Video_FrameCount, Config->File_Names.size());
161         #if MEDIAINFO_IBIUSAGE
162         else
163         {
164             //External IBI
165             std::string IbiFile=Config->Ibi_Get();
166             if (!IbiFile.empty())
167             {
168                 if (IbiStream)
169                     IbiStream->Infos.clear(); //TODO: support IBI data from different inputs
170                 else
171                     IbiStream=new ibi::stream;
172 
173                 File_Ibi MI;
174                 Open_Buffer_Init(&MI, IbiFile.size());
175                 MI.Ibi=new ibi;
176                 MI.Open_Buffer_Continue((const int8u*)IbiFile.c_str(), IbiFile.size());
177                 if (!MI.Ibi->Streams.empty())
178                     (*IbiStream)=(*MI.Ibi->Streams.begin()->second);
179             }
180 
181             if (IbiStream && !IbiStream->Infos.empty() && IbiStream->Infos[IbiStream->Infos.size()-1].IsContinuous && IbiStream->Infos[IbiStream->Infos.size()-1].FrameNumber!=(int64u)-1)
182                 Fill(Stream_Video, 0, Video_FrameCount, IbiStream->Infos[IbiStream->Infos.size()-1].FrameNumber);
183         }
184         #endif //MEDIAINFO_IBIUSAGE
185     }
186 
187     //Exception
188     if (Retrieve(Stream_General, 0, General_Format)==__T("AC-3") && (Retrieve(Stream_General, 0, General_Format_Profile).find(__T("E-AC-3"))==0 || Retrieve(Stream_General, 0, General_Format_AdditionalFeatures).find(__T("Dep"))!=string::npos))
189     {
190         //Using AC-3 extensions + E-AC-3 extensions + "eb3" specific extension
191         Ztring Extensions=Retrieve(Stream_General, 0, General_Format_Extensions);
192         if (Extensions.find(__T(" eb3"))==string::npos)
193         {
194             Extensions+=__T(' ');
195             Extensions+=MediaInfoLib::Config.Format_Get(__T("E-AC-3"), InfoFormat_Extensions);
196             Extensions+=__T(" eb3");
197             Fill(Stream_General, 0, General_Format_Extensions, Extensions, true);
198             if (MediaInfoLib::Config.Legacy_Get())
199                 Fill(Stream_General, 0, General_Codec_Extensions, Extensions, true);
200         }
201     }
202 
203     Streams_Finish_StreamOnly();
204     Streams_Finish_StreamOnly();
205     Streams_Finish_InterStreams();
206     Streams_Finish_StreamOnly();
207     Streams_Finish_InterStreams();
208     Streams_Finish_StreamOnly();
209     Streams_Finish_InterStreams();
210     Streams_Finish_StreamOnly();
211 
212     Config->File_ExpandSubs_Update((void**)(&Stream_More));
213 
214     if (!IsSub && !Config->File_IsReferenced_Get() && MediaInfoLib::Config.ReadByHuman_Get())
215         Streams_Finish_HumanReadable();
216 }
217 
218 //---------------------------------------------------------------------------
219 #if defined(MEDIAINFO_FILE_YES)
TestContinuousFileNames(size_t CountOfFiles,Ztring FileExtension,bool SkipComputeDelay)220 void File__Analyze::TestContinuousFileNames(size_t CountOfFiles, Ztring FileExtension, bool SkipComputeDelay)
221 {
222     if (IsSub || !Config->File_TestContinuousFileNames_Get())
223         return;
224 
225     size_t Pos=Config->File_Names.size();
226     if (!Pos)
227         return;
228 
229     //Trying to detect continuous file names (e.g. video stream as an image or HLS)
230     size_t Pos_Base = (size_t)-1;
231     bool AlreadyPresent=Config->File_Names.size()==1?true:false;
232     FileName FileToTest(Config->File_Names.Read(Config->File_Names.size()-1));
233     #ifdef WIN32
234         FileToTest.FindAndReplace(__T("/"), __T("\\"), 0, Ztring_Recursive); // "/" is sometimes used on Windows and it is considered as valid
235     #endif //WIN32
236     Ztring FileToTest_Name=FileToTest.Name_Get();
237     Ztring FileToTest_Name_After=FileToTest_Name;
238     size_t FileNameToTest_End=FileToTest_Name.size();
239     while (FileNameToTest_End && !(FileToTest_Name[FileNameToTest_End-1]>=__T('0') && FileToTest_Name[FileNameToTest_End-1]<=__T('9')))
240         FileNameToTest_End--;
241     size_t FileNameToTest_Pos=FileNameToTest_End;
242     while (FileNameToTest_Pos && FileToTest_Name[FileNameToTest_Pos-1]>=__T('0') && FileToTest_Name[FileNameToTest_Pos-1]<=__T('9'))
243         FileNameToTest_Pos--;
244     if (FileNameToTest_Pos!=FileToTest_Name.size() && FileNameToTest_Pos!=FileNameToTest_End)
245     {
246         size_t Numbers_Size=FileNameToTest_End-FileNameToTest_Pos;
247         int64u Pos=Ztring(FileToTest_Name.substr(FileNameToTest_Pos)).To_int64u();
248         FileToTest_Name.resize(FileNameToTest_Pos);
249         FileToTest_Name_After.erase(0, FileToTest_Name.size()+Numbers_Size);
250 
251         /*
252         for (;;)
253         {
254             Pos++;
255             Ztring Pos_Ztring; Pos_Ztring.From_Number(Pos);
256             if (Numbers_Size>Pos_Ztring.size())
257                 Pos_Ztring.insert(0, Numbers_Size-Pos_Ztring.size(), __T('0'));
258             Ztring Next=FileToTest.Path_Get()+PathSeparator+FileToTest_Name+Pos_Ztring+__T('.')+(FileExtension.empty()?FileToTest.Extension_Get():FileExtension);
259             if (!File::Exists(Next))
260                 break;
261             Config->File_Names.push_back(Next);
262         }
263         */
264 
265         //Detecting with a smarter algo (but missing frames are not detected)
266         Ztring FileToTest_Name_Begin=FileToTest.Path_Get()+PathSeparator+FileToTest_Name;
267         Ztring FileToTest_Name_End=FileToTest_Name_After+__T('.')+(FileExtension.empty()?FileToTest.Extension_Get():FileExtension);
268         Pos_Base = (size_t)Pos;
269         size_t Pos_Add_Max = 1;
270         #if MEDIAINFO_ADVANCED
271             bool File_IgnoreSequenceFileSize=Config->File_IgnoreSequenceFilesCount_Get(); //TODO: double check if it is expected
272 
273             size_t SequenceFileSkipFrames=Config->File_SequenceFilesSkipFrames_Get();
274             if (SequenceFileSkipFrames)
275             {
276                 for (;;)
277                 {
278                     size_t Pos_Add_Max_Old=Pos_Add_Max;
279                     for (size_t TempPos=Pos_Add_Max; TempPos<=Pos_Add_Max+SequenceFileSkipFrames; TempPos++)
280                     {
281                         Ztring Pos_Ztring; Pos_Ztring.From_Number(Pos_Base+TempPos);
282                         if (Numbers_Size>Pos_Ztring.size())
283                             Pos_Ztring.insert(0, Numbers_Size-Pos_Ztring.size(), __T('0'));
284                         Ztring Next=FileToTest_Name_Begin+Pos_Ztring+FileToTest_Name_End;
285                         if (File::Exists(Next))
286                         {
287                             Pos_Add_Max=TempPos+1;
288                             break;
289                         }
290                     }
291                     if (Pos_Add_Max==Pos_Add_Max_Old)
292                         break;
293                 }
294             }
295             else
296             {
297         #endif //MEDIAINFO_ADVANCED
298         for (;;)
299         {
300             Ztring Pos_Ztring; Pos_Ztring.From_Number(Pos_Base+Pos_Add_Max);
301             if (Numbers_Size>Pos_Ztring.size())
302                 Pos_Ztring.insert(0, Numbers_Size-Pos_Ztring.size(), __T('0'));
303             Ztring Next=FileToTest_Name_Begin+Pos_Ztring+FileToTest_Name_End;
304             if (!File::Exists(Next))
305                 break;
306             Pos_Add_Max<<=1;
307             #if MEDIAINFO_ADVANCED
308                 if (File_IgnoreSequenceFileSize && Pos_Add_Max>=CountOfFiles)
309                     break;
310             #endif //MEDIAINFO_ADVANCED
311         }
312         size_t Pos_Add_Min = Pos_Add_Max >> 1;
313         while (Pos_Add_Min+1<Pos_Add_Max)
314         {
315             size_t Pos_Add_Middle = Pos_Add_Min + ((Pos_Add_Max - Pos_Add_Min) >> 1);
316             Ztring Pos_Ztring; Pos_Ztring.From_Number(Pos_Base+Pos_Add_Middle);
317             if (Numbers_Size>Pos_Ztring.size())
318                 Pos_Ztring.insert(0, Numbers_Size-Pos_Ztring.size(), __T('0'));
319             Ztring Next=FileToTest_Name_Begin+Pos_Ztring+FileToTest_Name_End;
320             if (File::Exists(Next))
321                 Pos_Add_Min=Pos_Add_Middle;
322             else
323                 Pos_Add_Max=Pos_Add_Middle;
324         }
325 
326         #if MEDIAINFO_ADVANCED
327             } //SequenceFileSkipFrames
328         #endif //MEDIAINFO_ADVANCED
329 
330         size_t Pos_Max = Pos_Base + Pos_Add_Max;
331         Config->File_Names.reserve(Pos_Add_Max);
332         for (Pos=Pos_Base+1; Pos<Pos_Max; ++Pos)
333         {
334             Ztring Pos_Ztring; Pos_Ztring.From_Number(Pos);
335             if (Numbers_Size>Pos_Ztring.size())
336                 Pos_Ztring.insert(0, Numbers_Size-Pos_Ztring.size(), __T('0'));
337             Config->File_Names.push_back(FileToTest_Name_Begin+Pos_Ztring+FileToTest_Name_End);
338         }
339 
340         if (!Config->File_IsReferenced_Get() && Config->File_Names.size()<CountOfFiles && AlreadyPresent)
341             Config->File_Names.resize(1); //Removing files, wrong detection
342     }
343 
344     if (Config->File_Names.size()==Pos)
345         return;
346 
347     Config->File_IsImageSequence=true;
348     if (StreamSource==IsStream)
349         Frame_Count_NotParsedIncluded=Pos_Base;
350     #if MEDIAINFO_DEMUX
351         float64 Demux_Rate=Config->Demux_Rate_Get();
352         if (!Demux_Rate)
353             Demux_Rate=24;
354         if (!SkipComputeDelay && Frame_Count_NotParsedIncluded!=(int64u)-1)
355             Fill(Stream_Video, 0, Video_Delay, float64_int64s(Frame_Count_NotParsedIncluded*1000/Demux_Rate));
356     #endif //MEDIAINFO_DEMUX
357 
358     #if MEDIAINFO_ADVANCED
359         if (!Config->File_IgnoreSequenceFileSize_Get() || Config->File_Names.size()<=1)
360     #endif //MEDIAINFO_ADVANCED
361     {
362         for (; Pos<Config->File_Names.size(); Pos++)
363         {
364             int64u Size=File::Size_Get(Config->File_Names[Pos]);
365             Config->File_Sizes.push_back(Size);
366             Config->File_Size+=Size;
367         }
368     }
369     #if MEDIAINFO_ADVANCED
370         else
371         {
372             Config->File_Size=(int64u)-1;
373             File_Size=(int64u)-1;
374             Clear(Stream_General, 0, General_FileSize);
375         }
376     #endif //MEDIAINFO_ADVANCED
377 
378     File_Size=Config->File_Size;
379     Element[0].Next=File_Size;
380     #if MEDIAINFO_ADVANCED
381         if (!Config->File_IgnoreSequenceFileSize_Get() || Config->File_Names.size()<=1)
382     #endif //MEDIAINFO_ADVANCED
383         Fill (Stream_General, 0, General_FileSize, File_Size, 10, true);
384     #if MEDIAINFO_ADVANCED
385         if (!Config->File_IgnoreSequenceFilesCount_Get())
386     #endif //MEDIAINFO_ADVANCED
387     {
388         Fill (Stream_General, 0, General_CompleteName_Last, Config->File_Names[Config->File_Names.size()-1], true);
389         Fill (Stream_General, 0, General_FolderName_Last, FileName::Path_Get(Config->File_Names[Config->File_Names.size()-1]), true);
390         Fill (Stream_General, 0, General_FileName_Last, FileName::Name_Get(Config->File_Names[Config->File_Names.size()-1]), true);
391         Fill (Stream_General, 0, General_FileExtension_Last, FileName::Extension_Get(Config->File_Names[Config->File_Names.size()-1]), true);
392         if (Retrieve(Stream_General, 0, General_FileExtension_Last).empty())
393             Fill(Stream_General, 0, General_FileNameExtension_Last, Retrieve(Stream_General, 0, General_FileName_Last));
394         else
395             Fill(Stream_General, 0, General_FileNameExtension_Last, Retrieve(Stream_General, 0, General_FileName_Last)+__T('.')+Retrieve(Stream_General, 0, General_FileExtension_Last));
396     }
397 
398     #if MEDIAINFO_ADVANCED
399         if (Config->File_Source_List_Get())
400         {
401             Ztring SourcePath=FileName::Path_Get(Retrieve(Stream_General, 0, General_CompleteName));
402             size_t SourcePath_Size=SourcePath.size()+1; //Path size + path separator size
403             for (size_t Pos=0; Pos<Config->File_Names.size(); Pos++)
404             {
405                 Ztring Temp=Config->File_Names[Pos];
406                 Temp.erase(0, SourcePath_Size);
407                 Fill(Stream_General, 0, "Source_List", Temp);
408             }
409             Fill_SetOptions(Stream_General, 0, "Source_List", "N NT");
410         }
411     #endif //MEDIAINFO_ADVANCED
412 }
413 #endif //defined(MEDIAINFO_FILE_YES)
414 
415 //---------------------------------------------------------------------------
416 #if defined(MEDIAINFO_FILE_YES)
417 // title-of-work/
418 //     title-of-work.wav
419 //     dpx/
420 //         title-of-work_0086880.dpx
421 //         title-of-work_0086881.dpx
422 //         ... etc ...
PotentialAudioNames_Scenario1(const Ztring & DpxName,Ztring & ContainerDirName,ZtringList & List)423 static void PotentialAudioNames_Scenario1(const Ztring& DpxName, Ztring& ContainerDirName, ZtringList& List)
424 {
425     if (DpxName.size()<4)
426         return;
427 
428     if (DpxName.substr(DpxName.size()-4)!=__T(".dpx"))
429         return;
430 
431     size_t PathSeparator_Pos1=DpxName.find_last_of(__T("\\/"));
432     if (PathSeparator_Pos1==string::npos)
433         return;
434 
435     size_t PathSeparator_Pos2=DpxName.find_last_of(__T("\\/"), PathSeparator_Pos1-1);
436     if (PathSeparator_Pos2==string::npos)
437         return;
438 
439     size_t PathSeparator_Pos3=DpxName.find_last_of(__T("\\/"), PathSeparator_Pos2-1); //string::npos is accepted (relative path)
440 
441     size_t TitleSeparator_Pos=DpxName.find_last_of(__T('_'));
442     if (TitleSeparator_Pos==string::npos || TitleSeparator_Pos<=PathSeparator_Pos1)
443         return;
444 
445     Ztring DirDpx=DpxName.substr(PathSeparator_Pos2+1, PathSeparator_Pos1-(PathSeparator_Pos2+1));
446     if (DirDpx!=__T("dpx"))
447         return;
448 
449     Ztring TitleDpx=DpxName.substr(PathSeparator_Pos1+1, TitleSeparator_Pos-(PathSeparator_Pos1+1));
450     Ztring TitleDir=DpxName.substr(PathSeparator_Pos3+1, PathSeparator_Pos2-(PathSeparator_Pos3+1));
451     if (TitleDpx!=TitleDir)
452         return;
453 
454     ContainerDirName=DpxName.substr(0, PathSeparator_Pos2+1);
455     List.push_back(ContainerDirName+TitleDpx+__T(".wav"));
456 }
TestDirectory()457 void File__Analyze::TestDirectory()
458 {
459     if (IsSub || !Config->File_TestDirectory_Get())
460         return;
461 
462     if (Config->File_Names.size()<=1)
463         return;
464 
465     Ztring ContainerDirName;
466     ZtringList List;
467     PotentialAudioNames_Scenario1(Config->File_Names[0], ContainerDirName, List);
468     bool IsModified=false;
469     for (size_t i=0; i<List.size(); i++)
470     {
471         MediaInfo_Internal MI;
472         if (MI.Open(List[i]))
473         {
474             IsModified=true;
475             Ztring AudioFileName=MI.Get(Stream_General, 0, General_CompleteName);
476             for (size_t StreamKind=Stream_General+1; StreamKind<Stream_Max; StreamKind++)
477                 for (size_t StreamPos=0; StreamPos<MI.Count_Get((stream_t)StreamKind); StreamPos++)
478                 {
479                     Stream_Prepare((stream_t)StreamKind);
480                     Merge(MI, (stream_t)StreamKind, StreamPos_Last, StreamPos);
481                     if (AudioFileName.size()>ContainerDirName.size())
482                         Fill((stream_t)StreamKind, StreamPos_Last, "Source", AudioFileName.substr(ContainerDirName.size()));
483                     Fill((stream_t)StreamKind, StreamPos_Last, "MuxingMode", MI.Get(Stream_General, 0, General_Format));
484                     if (Retrieve_Const((stream_t)StreamKind, StreamPos_Last, "Encoded_Application").empty())
485                         Fill((stream_t)StreamKind, StreamPos_Last, "Encoded_Application", MI.Get(Stream_General, 0, General_Encoded_Application));
486                     if (Retrieve_Const((stream_t)StreamKind, StreamPos_Last, "Encoded_Library").empty())
487                         Fill((stream_t)StreamKind, StreamPos_Last, "Encoded_Library", MI.Get(Stream_General, 0, General_Encoded_Library));
488                 }
489             #if MEDIAINFO_ADVANCED
490                 if (!Config->File_IgnoreSequenceFileSize_Get())
491             #endif //MEDIAINFO_ADVANCED
492             {
493                 File_Size+=MI.Get(Stream_General, 0, General_FileSize).To_int64u();
494             }
495         }
496     }
497     if (IsModified)
498     {
499         Ztring VideoFileName=Retrieve(Stream_General, 0, General_CompleteName);
500         Ztring VideoFileName_Last=Retrieve(Stream_General, 0, General_CompleteName_Last);
501         Ztring VideoMuxingMode=Retrieve_Const(Stream_General, 0, General_Format);
502         if (VideoFileName.size()>ContainerDirName.size())
503             Fill(Stream_Video, 0, "Source", VideoFileName.substr(ContainerDirName.size()));
504         if (VideoFileName_Last.size()>ContainerDirName.size())
505             Fill(Stream_Video, 0, "Source_Last", VideoFileName_Last.substr(ContainerDirName.size()));
506         Fill(Stream_Video, 0, Video_MuxingMode, VideoMuxingMode);
507 
508         Fill(Stream_General, 0, General_CompleteName, ContainerDirName, true);
509         Fill(Stream_General, 0, General_FileSize, File_Size, 10, true);
510         Fill(Stream_General, 0, General_Format, "Directory", Unlimited, true, true);
511 
512         Clear(Stream_General, 0, General_CompleteName_Last);
513         Clear(Stream_General, 0, General_FolderName_Last);
514         Clear(Stream_General, 0, General_FileName_Last);
515         Clear(Stream_General, 0, General_FileNameExtension_Last);
516         Clear(Stream_General, 0, General_FileExtension_Last);
517         Clear(Stream_General, 0, General_Format_String);
518         Clear(Stream_General, 0, General_Format_Info);
519         Clear(Stream_General, 0, General_Format_Url);
520         Clear(Stream_General, 0, General_Format_Commercial);
521         Clear(Stream_General, 0, General_Format_Commercial_IfAny);
522         Clear(Stream_General, 0, General_Format_Version);
523         Clear(Stream_General, 0, General_Format_Profile);
524         Clear(Stream_General, 0, General_Format_Level);
525         Clear(Stream_General, 0, General_Format_Compression);
526         Clear(Stream_General, 0, General_Format_Settings);
527         Clear(Stream_General, 0, General_Format_AdditionalFeatures);
528         Clear(Stream_General, 0, General_InternetMediaType);
529         Clear(Stream_General, 0, General_Duration);
530         Clear(Stream_General, 0, General_Encoded_Application);
531         Clear(Stream_General, 0, General_Encoded_Application_String);
532         Clear(Stream_General, 0, General_Encoded_Application_CompanyName);
533         Clear(Stream_General, 0, General_Encoded_Application_Name);
534         Clear(Stream_General, 0, General_Encoded_Application_Version);
535         Clear(Stream_General, 0, General_Encoded_Application_Url);
536         Clear(Stream_General, 0, General_Encoded_Library);
537         Clear(Stream_General, 0, General_Encoded_Library_String);
538         Clear(Stream_General, 0, General_Encoded_Library_CompanyName);
539         Clear(Stream_General, 0, General_Encoded_Library_Name);
540         Clear(Stream_General, 0, General_Encoded_Library_Version);
541         Clear(Stream_General, 0, General_Encoded_Library_Date);
542         Clear(Stream_General, 0, General_Encoded_Library_Settings);
543         Clear(Stream_General, 0, General_Encoded_OperatingSystem);
544         Clear(Stream_General, 0, General_FrameCount);
545         Clear(Stream_General, 0, General_FrameRate);
546     }
547 }
548 #endif //defined(MEDIAINFO_FILE_YES)
549 
550 //---------------------------------------------------------------------------
551 #if MEDIAINFO_FIXITY
FixFile(int64u FileOffsetForWriting,const int8u * ToWrite,const size_t ToWrite_Size)552 bool File__Analyze::FixFile(int64u FileOffsetForWriting, const int8u* ToWrite, const size_t ToWrite_Size)
553 {
554     if (Config->File_Names.empty())
555         return false; //Streams without file names are not supported
556 
557     #ifdef WINDOWS
558     File::Copy(Config->File_Names[0], Config->File_Names[0]+__T(".Fixed"));
559     #else //WINDOWS
560     //ZenLib has File::Copy only for Windows for the moment. //TODO: support correctly (including meta)
561     if (!File::Exists(Config->File_Names[0]+__T(".Fixed")))
562     {
563         std::ofstream  Dest(Ztring(Config->File_Names[0]+__T(".Fixed")).To_Local().c_str(), std::ios::binary);
564         if (Dest.fail())
565             return false;
566         std::ifstream  Source(Config->File_Names[0].To_Local().c_str(), std::ios::binary);
567         if (Source.fail())
568             return false;
569         Dest << Source.rdbuf();
570         if (Dest.fail())
571             return false;
572     }
573     #endif //WINDOWS
574 
575     File F;
576     if (!F.Open(Config->File_Names[0]+__T(".Fixed"), File::Access_Write))
577         return false;
578 
579     if (!F.GoTo(FileOffsetForWriting))
580         return false;
581 
582     F.Write(ToWrite, ToWrite_Size);
583 
584     return true;
585 }
586 #endif //MEDIAINFO_FIXITY
587 
588 //---------------------------------------------------------------------------
Streams_Finish_StreamOnly()589 void File__Analyze::Streams_Finish_StreamOnly()
590 {
591     //Generic
592     for (size_t StreamKind=Stream_General; StreamKind<Stream_Max; StreamKind++)
593         for (size_t StreamPos=0; StreamPos<Count_Get((stream_t)StreamKind); StreamPos++)
594             Streams_Finish_StreamOnly((stream_t)StreamKind, StreamPos);
595 
596     //For each kind of (*Stream)
597     for (size_t Pos=0; Pos<Count_Get(Stream_General);  Pos++) Streams_Finish_StreamOnly_General(Pos);
598     for (size_t Pos=0; Pos<Count_Get(Stream_Video);    Pos++) Streams_Finish_StreamOnly_Video(Pos);
599     for (size_t Pos=0; Pos<Count_Get(Stream_Audio);    Pos++) Streams_Finish_StreamOnly_Audio(Pos);
600     for (size_t Pos=0; Pos<Count_Get(Stream_Text);     Pos++) Streams_Finish_StreamOnly_Text(Pos);
601     for (size_t Pos=0; Pos<Count_Get(Stream_Other);    Pos++) Streams_Finish_StreamOnly_Other(Pos);
602     for (size_t Pos=0; Pos<Count_Get(Stream_Image);    Pos++) Streams_Finish_StreamOnly_Image(Pos);
603     for (size_t Pos=0; Pos<Count_Get(Stream_Menu);     Pos++) Streams_Finish_StreamOnly_Menu(Pos);
604 }
605 
606 //---------------------------------------------------------------------------
Streams_Finish_StreamOnly(stream_t StreamKind,size_t Pos)607 void File__Analyze::Streams_Finish_StreamOnly(stream_t StreamKind, size_t Pos)
608 {
609     //Format
610     if (Retrieve_Const(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_Format)).empty())
611         Fill(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_Format), Retrieve_Const(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_CodecID)));
612 
613     //BitRate from Duration and StreamSize
614     if (StreamKind!=Stream_General && StreamKind!=Stream_Other && StreamKind!=Stream_Menu && Retrieve(StreamKind, Pos, "BitRate").empty() && !Retrieve(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_StreamSize)).empty() && !Retrieve(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_Duration)).empty())
615     {
616         float64 Duration=0;
617         if (StreamKind==Stream_Video && !Retrieve(Stream_Video, Pos, Video_FrameCount).empty() && !Retrieve(Stream_Video, Pos, Video_FrameRate).empty())
618         {
619             int64u FrameCount=Retrieve(Stream_Video, Pos, Video_FrameCount).To_int64u();
620             float64 FrameRate=Retrieve(Stream_Video, Pos, Video_FrameRate).To_float64();
621             if (FrameCount && FrameRate)
622                 Duration=FrameCount*1000/FrameRate; //More precise (example: 1 frame at 29.97 fps)
623         }
624         if (Duration==0)
625             Duration=Retrieve(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_Duration)).To_float64();
626         int64u StreamSize=Retrieve(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_StreamSize)).To_int64u();
627         if (Duration>0 && StreamSize>0)
628             Fill(StreamKind, Pos, "BitRate", StreamSize*8*1000/Duration, 0);
629     }
630 
631     //BitRate_Encoded from Duration and StreamSize_Encoded
632     if (StreamKind!=Stream_General && StreamKind!=Stream_Other && StreamKind!=Stream_Menu && Retrieve(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_BitRate_Encoded)).empty() && !Retrieve(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_StreamSize_Encoded)).empty() && !Retrieve(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_Duration)).empty())
633     {
634         float64 Duration=0;
635         if (StreamKind==Stream_Video && !Retrieve(Stream_Video, Pos, Video_FrameCount).empty() && !Retrieve(Stream_Video, Pos, Video_FrameRate).empty())
636         {
637             int64u FrameCount=Retrieve(Stream_Video, Pos, Video_FrameCount).To_int64u();
638             float64 FrameRate=Retrieve(Stream_Video, Pos, Video_FrameRate).To_float64();
639             if (FrameCount && FrameRate)
640                 Duration=FrameCount*1000/FrameRate; //More precise (example: 1 frame at 29.97 fps)
641         }
642         if (Duration==0)
643             Duration=Retrieve(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_Duration)).To_float64();
644         int64u StreamSize_Encoded=Retrieve(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_StreamSize_Encoded)).To_int64u();
645         if (Duration>0)
646             Fill(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_BitRate_Encoded), StreamSize_Encoded*8*1000/Duration, 0);
647     }
648 
649     //Duration from Bitrate and StreamSize
650     if (StreamKind!=Stream_Other && Retrieve(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_Duration)).empty() && !Retrieve(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_StreamSize)).empty() && !Retrieve(StreamKind, Pos, "BitRate").empty() && Count_Get(Stream_Video)+Count_Get(Stream_Audio)>1) //If only one stream, duration will be copied later, useful for exact bitrate calculation //TODO: enable it aslo for 1 stream, after handling of incoherencies found during tests
651     {
652         int64u BitRate=Retrieve(StreamKind, Pos, "BitRate").To_int64u();
653         int64u StreamSize=Retrieve(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_StreamSize)).To_int64u();
654         if (BitRate>0 && StreamSize>0)
655             Fill(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_Duration), ((float64)StreamSize)*8*1000/BitRate, 0);
656     }
657 
658     //StreamSize from BitRate and Duration
659     if (StreamKind!=Stream_Other && Retrieve(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_StreamSize)).empty() && !Retrieve(StreamKind, Pos, "BitRate").empty() && !Retrieve(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_Duration)).empty() && Retrieve(StreamKind, Pos, "BitRate").find(__T(" / "))==std::string::npos) //If not done the first time or by other routine
660     {
661         float64 BitRate=Retrieve(StreamKind, Pos, "BitRate").To_float64();
662         float64 Duration=Retrieve(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_Duration)).To_float64();
663         if (BitRate>0 && Duration>0)
664         {
665             float64 StreamSize=BitRate*Duration/8/1000;
666             Fill(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_StreamSize), StreamSize, 0);
667         }
668     }
669 
670     //Bit rate and maximum bit rate
671     if (!Retrieve(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_BitRate)).empty() && Retrieve(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_BitRate))==Retrieve(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_BitRate_Maximum)))
672     {
673         Clear(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_BitRate_Maximum));
674         if (Retrieve(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_BitRate_Mode)).empty())
675             Fill(StreamKind, Pos, Fill_Parameter(StreamKind, Generic_BitRate_Mode), "CBR");
676     }
677 }
678 
679 //---------------------------------------------------------------------------
Streams_Finish_StreamOnly_General(size_t StreamPos)680 void File__Analyze::Streams_Finish_StreamOnly_General(size_t StreamPos)
681 {
682     //File extension test
683     if (Retrieve(Stream_General, StreamPos, "FileExtension_Invalid").empty())
684     {
685         const Ztring& Name=Retrieve(Stream_General, StreamPos, General_FileName);
686         const Ztring& Extension=Retrieve(Stream_General, StreamPos, General_FileExtension);
687         if (!Name.empty() || !Extension.empty())
688         {
689             InfoMap &FormatList=MediaInfoLib::Config.Format_Get();
690             InfoMap::iterator Format=FormatList.find(Retrieve(Stream_General, StreamPos, General_Format));
691             if (Format!=FormatList.end())
692             {
693                 ZtringList ValidExtensions;
694                 ValidExtensions.Separator_Set(0, __T(" "));
695                 ValidExtensions.Write(Retrieve(Stream_General, StreamPos, General_Format_Extensions));
696                 if (!ValidExtensions.empty() && ValidExtensions.Find(Extension)==string::npos)
697                     Fill(Stream_General, StreamPos, "FileExtension_Invalid", ValidExtensions.Read());
698             }
699         }
700     }
701 }
702 
703 //---------------------------------------------------------------------------
Streams_Finish_StreamOnly_Video(size_t Pos)704 void File__Analyze::Streams_Finish_StreamOnly_Video(size_t Pos)
705 {
706     //Frame count
707     if (Retrieve(Stream_Video, Pos, Video_FrameCount).empty() && Frame_Count_NotParsedIncluded!=(int64u)-1 && File_Offset+Buffer_Size==File_Size)
708     {
709         if (Count_Get(Stream_Video)==1 && Count_Get(Stream_Audio)==0)
710             Fill(Stream_Video, 0, Video_FrameCount, Frame_Count_NotParsedIncluded);
711     }
712 
713     //FrameCount from Duration and FrameRate
714     if (Retrieve(Stream_Video, Pos, Video_FrameCount).empty())
715     {
716         int64s Duration=Retrieve(Stream_Video, Pos, Video_Duration).To_int64s();
717         bool DurationFromGeneral;
718         if (Duration==0)
719         {
720             Duration=Retrieve(Stream_General, 0, General_Duration).To_int64s();
721             DurationFromGeneral=Retrieve(Stream_General, 0, General_Format)!=Retrieve(Stream_Video, Pos, Audio_Format);
722         }
723         else
724             DurationFromGeneral=false;
725         float64 FrameRate=Retrieve(Stream_Video, Pos, Video_FrameRate).To_float64();
726         if (Duration && FrameRate)
727         {
728             Fill(Stream_Video, Pos, Video_FrameCount, Duration*FrameRate/1000, 0);
729             if (DurationFromGeneral && Retrieve_Const(Stream_Audio, Pos, Audio_Format)!=Retrieve_Const(Stream_General, 0, General_Format))
730             {
731                 Fill(Stream_Video, Pos, "FrameCount_Source", "General_Duration");
732                 Fill_SetOptions(Stream_Video, Pos, "FrameCount_Source", "N NTN");
733             }
734         }
735     }
736 
737     //Duration from FrameCount and FrameRate
738     if (Retrieve(Stream_Video, Pos, Video_Duration).empty())
739     {
740         int64u FrameCount=Retrieve(Stream_Video, Pos, Video_FrameCount).To_int64u();
741         float64 FrameRate=Retrieve(Stream_Video, Pos, Video_FrameRate).To_float64();
742         if (FrameCount && FrameRate)
743         {
744             Fill(Stream_Video, Pos, Video_Duration, FrameCount/FrameRate*1000, 0);
745             Ztring Source=Retrieve(Stream_Video, Pos, "FrameCount_Source");
746             if (!Source.empty())
747             {
748                 Fill(Stream_Video, Pos, "Duration_Source", Source);
749                 Fill_SetOptions(Stream_Video, Pos, "Duration_Source", "N NTN");
750             }
751         }
752     }
753 
754     //FrameRate from FrameCount and Duration
755     if (Retrieve(Stream_Video, Pos, Video_FrameRate).empty())
756     {
757         int64u FrameCount=Retrieve(Stream_Video, Pos, Video_FrameCount).To_int64u();
758         float64 Duration=Retrieve(Stream_Video, Pos, Video_Duration).To_float64()/1000;
759         if (FrameCount && Duration)
760            Fill(Stream_Video, Pos, Video_FrameRate, FrameCount/Duration, 3);
761     }
762 
763     //Pixel Aspect Ratio forced to 1.000 if none
764     if (Retrieve(Stream_Video, Pos, Video_PixelAspectRatio).empty())
765         Fill(Stream_Video, Pos, Video_PixelAspectRatio, 1.000);
766 
767     //Standard
768     if (Retrieve(Stream_Video, Pos, Video_Standard).empty() && (Retrieve(Stream_Video, Pos, Video_Width)==__T("720") || Retrieve(Stream_Video, Pos, Video_Width)==__T("704")))
769     {
770              if (Retrieve(Stream_Video, Pos, Video_Height)==__T("576") && Retrieve(Stream_Video, Pos, Video_FrameRate)==__T("25.000"))
771             Fill(Stream_Video, Pos, Video_Standard, "PAL");
772         else if ((Retrieve(Stream_Video, Pos, Video_Height)==__T("486") || Retrieve(Stream_Video, Pos, Video_Height)==__T("480")) && Retrieve(Stream_Video, Pos, Video_FrameRate)==__T("29.970"))
773             Fill(Stream_Video, Pos, Video_Standard, "NTSC");
774     }
775     if (Retrieve(Stream_Video, Pos, Video_Standard).empty() && Retrieve(Stream_Video, Pos, Video_Width)==__T("352"))
776     {
777              if ((Retrieve(Stream_Video, Pos, Video_Height)==__T("576") || Retrieve(Stream_Video, Pos, Video_Height)==__T("288")) && Retrieve(Stream_Video, Pos, Video_FrameRate)==__T("25.000"))
778             Fill(Stream_Video, Pos, Video_Standard, "PAL");
779         else if ((Retrieve(Stream_Video, Pos, Video_Height)==__T("486") || Retrieve(Stream_Video, Pos, Video_Height)==__T("480") || Retrieve(Stream_Video, Pos, Video_Height)==__T("243") || Retrieve(Stream_Video, Pos, Video_Height)==__T("240")) && Retrieve(Stream_Video, Pos, Video_FrameRate)==__T("29.970"))
780             Fill(Stream_Video, Pos, Video_Standard, "NTSC");
781     }
782 
783     //Known ScanTypes
784     if (Retrieve(Stream_Video, Pos, Video_ScanType).empty()
785      && (Retrieve(Stream_Video, Pos, Video_Format)==__T("RED")
786       || Retrieve(Stream_Video, Pos, Video_Format)==__T("CineForm")
787       || Retrieve(Stream_Video, Pos, Video_Format)==__T("DPX")
788       || Retrieve(Stream_Video, Pos, Video_Format)==__T("EXR")))
789             Fill(Stream_Video, Pos, Video_ScanType, "Progressive");
790 
791     //Useless chroma subsampling
792     if (Retrieve(Stream_Video, Pos, Video_ColorSpace)==__T("RGB")
793      && Retrieve(Stream_Video, Pos, Video_ChromaSubsampling)==__T("4:4:4"))
794         Clear(Stream_Video, Pos, Video_ChromaSubsampling);
795 
796     //Chroma subsampling position
797     if (Retrieve(Stream_Video, Pos, Video_ChromaSubsampling_String).empty() && !Retrieve(Stream_Video, Pos, Video_ChromaSubsampling).empty())
798     {
799         if (Retrieve(Stream_Video, Pos, Video_ChromaSubsampling_Position).empty())
800             Fill(Stream_Video, Pos, Video_ChromaSubsampling_String, Retrieve(Stream_Video, Pos, Video_ChromaSubsampling));
801         else
802             Fill(Stream_Video, Pos, Video_ChromaSubsampling_String, Retrieve(Stream_Video, Pos, Video_ChromaSubsampling)+__T(" (")+ Retrieve(Stream_Video, Pos, Video_ChromaSubsampling_Position)+__T(')'));
803     }
804 
805     //Commercial name
806     if ((Retrieve(Stream_Video, Pos, Video_BitDepth).empty() || Retrieve(Stream_Video, Pos, Video_BitDepth)==__T("10")) //e.g. ProRes has not bitdepth info
807      && Retrieve(Stream_Video, Pos, Video_ChromaSubsampling)==__T("4:2:0")
808      && (Retrieve(Stream_Video, Pos, Video_colour_description_present).empty() || //From  CFF: "colour_description_present_flag SHALL be set to 1 if the color parameters from [R709] are not used."
809        ( Retrieve(Stream_Video, Pos, Video_colour_primaries)==__T("BT.2020")
810       && Retrieve(Stream_Video, Pos, Video_transfer_characteristics)==__T("PQ")
811       && Retrieve(Stream_Video, Pos, Video_matrix_coefficients).find(__T("BT.2020"))==0))
812      && !Retrieve(Stream_Video, Pos, "MasteringDisplay_ColorPrimaries").empty()
813      // && !Retrieve(Stream_Video, Pos, "MaxCLL").empty()
814      // && !Retrieve(Stream_Video, Pos, "MaxFALL").empty() // MaxCLL & MaxFALL are required except if not available so not required in practice https://www.cta.tech/News/Press-Releases/2015/August/CEA-Defines-%E2%80%98HDR-Compatible%E2%80%99-Displays.aspx https://www.ultrahdforum.org/wp-content/uploads/2016/04/Ultra-HD-Forum-Deployment-Guidelines-V1.1-Summer-2016.pdf
815         )
816     {
817         //We actually fill HDR10/HDR10+ by default, so it will be removed below if not fitting in the color related rules
818     }
819     else if (!Retrieve_Const(Stream_Video, Pos, Video_HDR_Format_Compatibility).empty())
820     {
821     }
822     if (Retrieve(Stream_Video, Pos, Video_HDR_Format_String).empty())
823     {
824         ZtringList Summary;
825         Summary.Separator_Set(0, __T(" / "));
826         Summary.Write(Retrieve(Stream_Video, Pos, Video_HDR_Format));
827         ZtringList Commercial=Summary;
828         if (!Summary.empty())
829         {
830             ZtringList HDR_Format_Compatibility;
831             HDR_Format_Compatibility.Separator_Set(0, __T(" / "));
832             HDR_Format_Compatibility.Write(Retrieve(Stream_Video, Pos, Video_HDR_Format_Compatibility));
833             HDR_Format_Compatibility.resize(Summary.size());
834             ZtringList ToAdd;
835             ToAdd.Separator_Set(0, __T(" / "));
836             for (size_t i=Video_HDR_Format_String+1; i<=Video_HDR_Format_Settings; i++)
837             {
838                 ToAdd.Write(Retrieve(Stream_Video, Pos, i));
839                 ToAdd.resize(Summary.size());
840                 for (size_t j=0; j<Summary.size(); j++)
841                 {
842                     if (!ToAdd[j].empty())
843                     {
844                         switch (i)
845                         {
846                             case Video_HDR_Format_Version: Summary[j]+=__T(", Version "); break;
847                             case Video_HDR_Format_Level: Summary[j]+=__T('.'); break;
848                             default: Summary[j] += __T(", ");
849                         }
850                         Summary[j]+=ToAdd[j];
851                     }
852                 }
853             }
854             for (size_t j=0; j<Summary.size(); j++)
855                 if (!HDR_Format_Compatibility[j].empty())
856                 {
857                     Summary[j]+=__T(", ")+HDR_Format_Compatibility[j]+__T(" compatible");
858                     Commercial[j]=HDR_Format_Compatibility[j].substr(0, HDR_Format_Compatibility[j].find(__T(' ')));
859                 }
860             Fill(Stream_Video, Pos, Video_HDR_Format_String, Summary.Read());
861             Fill(Stream_Video, Pos, Video_HDR_Format_Commercial, Commercial.Read());
862         }
863     }
864     #if defined(MEDIAINFO_VC3_YES)
865         if (Retrieve(Stream_Video, Pos, Video_Format_Commercial_IfAny).empty() && Retrieve(Stream_Video, Pos, Video_Format)==__T("VC-3") && Retrieve(Stream_Video, Pos, Video_Format_Profile).find(__T("HD"))==0)
866         {
867             //http://www.avid.com/static/resources/US/documents/dnxhd.pdf
868             int64u Height=Retrieve(Stream_Video, Pos, Video_Height).To_int64u();
869             int64u BitRate=float64_int64s(Retrieve(Stream_Video, Pos, Video_BitRate).To_float64()/1000000);
870             int64u FrameRate=float64_int64s(Retrieve(Stream_Video, Pos, Video_FrameRate).To_float64());
871             int64u BitRate_Final=0;
872             if (Height>=900 && Height<=1300)
873             {
874                 if (FrameRate==60)
875                 {
876                     if (BitRate>=420 && BitRate<440) //440
877                         BitRate_Final=440;
878                     if (BitRate>=271 && BitRate<311) //291
879                         BitRate_Final=290;
880                     if (BitRate>=80 && BitRate<100) //90
881                         BitRate_Final=90;
882                 }
883                 if (FrameRate==50)
884                 {
885                     if (BitRate>=347 && BitRate<387) //367
886                         BitRate_Final=365;
887                     if (BitRate>=222 && BitRate<262) //242
888                         BitRate_Final=240;
889                     if (BitRate>=65 && BitRate<85) //75
890                         BitRate_Final=75;
891                 }
892                 if (FrameRate==30)
893                 {
894                     if (BitRate>=420 && BitRate<440) //440
895                         BitRate_Final=440;
896                     if (BitRate>=200 && BitRate<240) //220
897                         BitRate_Final=220;
898                     if (BitRate>=130 && BitRate<160) //145
899                         BitRate_Final=145;
900                     if (BitRate>=90 && BitRate<110) //100
901                         BitRate_Final=100;
902                     if (BitRate>=40 && BitRate<50) //45
903                         BitRate_Final=45;
904                 }
905                 if (FrameRate==25)
906                 {
907                     if (BitRate>=347 && BitRate<387) //367
908                         BitRate_Final=365;
909                     if (BitRate>=164 && BitRate<204) //184
910                         BitRate_Final=185;
911                     if (BitRate>=111 && BitRate<131) //121
912                         BitRate_Final=120;
913                     if (BitRate>=74 && BitRate<94) //84
914                         BitRate_Final=85;
915                     if (BitRate>=31 && BitRate<41) //36
916                         BitRate_Final=36;
917                 }
918                 if (FrameRate==24)
919                 {
920                     if (BitRate>=332 && BitRate<372) //352
921                         BitRate_Final=350;
922                     if (BitRate>=156 && BitRate<196) //176
923                         BitRate_Final=175;
924                     if (BitRate>=105 && BitRate<125) //116
925                         BitRate_Final=116;
926                     if (BitRate>=70 && BitRate<90) //80
927                         BitRate_Final=80;
928                     if (BitRate>=31 && BitRate<41) //36
929                         BitRate_Final=36;
930                 }
931             }
932             if (Height>=600 && Height<=800)
933             {
934                 if (FrameRate==60)
935                 {
936                     if (BitRate>=200 && BitRate<240) //220
937                         BitRate_Final=220;
938                     if (BitRate>=130 && BitRate<160) //145
939                         BitRate_Final=145;
940                     if (BitRate>=90 && BitRate<110) //110
941                         BitRate_Final=100;
942                 }
943                 if (FrameRate==50)
944                 {
945                     if (BitRate>=155 && BitRate<195) //175
946                         BitRate_Final=175;
947                     if (BitRate>=105 && BitRate<125) //115
948                         BitRate_Final=115;
949                     if (BitRate>=75 && BitRate<95) //85
950                         BitRate_Final=85;
951                 }
952                 if (FrameRate==30)
953                 {
954                     if (BitRate>=100 && BitRate<120) //110
955                         BitRate_Final=110;
956                     if (BitRate>=62 && BitRate<82) //72
957                         BitRate_Final=75;
958                     if (BitRate>=44 && BitRate<56) //51
959                         BitRate_Final=50;
960                 }
961                 if (FrameRate==25)
962                 {
963                     if (BitRate>=82 && BitRate<102) //92
964                         BitRate_Final=90;
965                     if (BitRate>=55 && BitRate<65) //60
966                         BitRate_Final=60;
967                     if (BitRate>=38 && BitRate<48) //43
968                         BitRate_Final=45;
969                 }
970                 if (FrameRate==24)
971                 {
972                     if (BitRate>=78 && BitRate<98) //88
973                         BitRate_Final=90;
974                     if (BitRate>=53 && BitRate<63) //58
975                         BitRate_Final=60;
976                     if (BitRate>=36 && BitRate<46) //41
977                         BitRate_Final=41;
978                 }
979             }
980 
981             if (BitRate_Final)
982             {
983                 int64u BitDepth=Retrieve(Stream_Video, Pos, Video_BitDepth).To_int64u();
984                 if (BitDepth==8 || BitDepth==10)
985                     Fill(Stream_Video, Pos, Video_Format_Commercial_IfAny, __T("DNxHD ")+Ztring::ToZtring(BitRate_Final)+(BitDepth==10?__T("x"):__T(""))); //"x"=10-bit
986             }
987         }
988         if (Retrieve(Stream_Video, Pos, Video_Format_Commercial_IfAny).empty() && Retrieve(Stream_Video, Pos, Video_Format)==__T("VC-3") && Retrieve(Stream_Video, Pos, Video_Format_Profile).find(__T("RI@"))==0)
989         {
990             Fill(Stream_Video, Pos, Video_Format_Commercial_IfAny, __T("DNxHR ")+Retrieve(Stream_Video, Pos, Video_Format_Profile).substr(3));
991         }
992     #endif //defined(MEDIAINFO_VC3_YES)
993 }
994 
995 //---------------------------------------------------------------------------
Streams_Finish_StreamOnly_Audio(size_t Pos)996 void File__Analyze::Streams_Finish_StreamOnly_Audio(size_t Pos)
997 {
998     //
999     if (Retrieve(Stream_Audio, Pos, Audio_StreamSize_Encoded)==Retrieve(Stream_Audio, Pos, Audio_StreamSize))
1000         Clear(Stream_Audio, Pos, Audio_StreamSize_Encoded);
1001     if (Retrieve(Stream_Audio, Pos, Audio_BitRate_Encoded)==Retrieve(Stream_Audio, Pos, Audio_BitRate))
1002         Clear(Stream_Audio, Pos, Audio_BitRate_Encoded);
1003 
1004     //Dolby ED2 merge
1005     if (Retrieve(Stream_Audio, Pos, Audio_Format)==__T("Dolby ED2"))
1006     {
1007         int64u BitRate=Retrieve(Stream_Audio, Pos, Audio_BitRate).To_int64u();
1008         int64u BitRate_Encoded=Retrieve(Stream_Audio, Pos, Audio_BitRate_Encoded).To_int64u();
1009         int64u StreamSize=Retrieve(Stream_Audio, Pos, Audio_StreamSize).To_int64u();
1010         int64u StreamSize_Encoded=Retrieve(Stream_Audio, Pos, Audio_StreamSize_Encoded).To_int64u();
1011         for (size_t i=Pos+1; i<Count_Get(Stream_Audio);)
1012         {
1013             size_t OtherID_Count;
1014             Ztring OtherID;
1015             Ztring OtherID_String;
1016             if (Retrieve_Const(Stream_Audio, i, Audio_Format)==__T("Dolby ED2"))
1017             {
1018                 //if (Retrieve_Const(Stream_Audio, i, Audio_Channel_s_).To_int64u())
1019                 if (!Retrieve_Const(Stream_Audio, i, "Presentation0").empty())
1020                     break; // It is the next ED2
1021                 OtherID_Count=0;
1022                 OtherID=Retrieve(Stream_Audio, i, Audio_ID);
1023                 OtherID_String =Retrieve(Stream_Audio, i, Audio_ID_String);
1024             }
1025             if (i+7<Count_Get(Stream_Audio) // 8 tracks Dolby E
1026              && Retrieve_Const(Stream_Audio, i  , Audio_Format)==__T("Dolby E")
1027              && Retrieve_Const(Stream_Audio, i+7, Audio_Format)==__T("Dolby E"))
1028             {
1029                 Ztring NextID=Retrieve_Const(Stream_Audio, i, Audio_ID);
1030                 size_t NextID_DashPos=NextID.rfind(__T('-'));
1031                 if (NextID_DashPos!=(size_t)-1)
1032                     NextID.erase(NextID_DashPos);
1033                 if (Retrieve_Const(Stream_Audio, i+7, Audio_ID)==NextID+__T("-8"))
1034                 {
1035                     OtherID_Count=7;
1036                     OtherID=NextID;
1037                 }
1038                 NextID=Retrieve_Const(Stream_Audio, i, Audio_ID_String);
1039                 NextID_DashPos=NextID.rfind(__T('-'));
1040                 if (NextID_DashPos!=(size_t)-1)
1041                     NextID.erase(NextID_DashPos);
1042                 if (Retrieve_Const(Stream_Audio, i+7, Audio_ID_String)==NextID+__T("-8"))
1043                 {
1044                     OtherID_String=NextID;
1045                 }
1046             }
1047             if (OtherID.empty())
1048                 break;
1049 
1050             size_t OtherID_DashPos=OtherID.rfind(__T('-'));
1051             if (OtherID_DashPos!=(size_t)-1)
1052                 OtherID.erase(0, OtherID_DashPos+1);
1053             if (!OtherID.empty() && OtherID[0]==__T('(') && OtherID[OtherID.size()-1]==__T(')'))
1054             {
1055                 OtherID.resize(OtherID.size()-1);
1056                 OtherID.erase(0, 1);
1057             }
1058             Ztring ID=Retrieve(Stream_Audio, Pos, Audio_ID);
1059             if (!ID.empty() && ID[ID.size()-1]==__T(')'))
1060             {
1061                 ID.resize(ID.size()-1);
1062                 ID+=__T(" / ");
1063                 ID+=OtherID;
1064                 ID+=__T(')');
1065                 Fill(Stream_Audio, Pos, Audio_ID, ID, true);
1066             }
1067             else
1068             {
1069                 Ztring CurrentID_String=Retrieve(Stream_Audio, Pos, Audio_ID_String);
1070                 Fill(Stream_Audio, Pos, Audio_ID, OtherID);
1071                 Fill(Stream_Audio, Pos, Audio_ID_String, CurrentID_String+__T(" / ")+OtherID_String, true);
1072             }
1073             for (size_t j=i+OtherID_Count; j>=i; j--)
1074             {
1075                 BitRate+=Retrieve(Stream_Audio, j, Audio_BitRate).To_int64u();
1076                 BitRate_Encoded+=Retrieve(Stream_Audio, j, Audio_BitRate_Encoded).To_int64u();
1077                 StreamSize+=Retrieve(Stream_Audio, j, Audio_StreamSize).To_int64u();
1078                 StreamSize_Encoded+=Retrieve(Stream_Audio, j, Audio_StreamSize_Encoded).To_int64u();
1079                 Stream_Erase(Stream_Audio, j);
1080             }
1081 
1082             ZtringList List[6];
1083             for (size_t j=0; j<6; j++)
1084                 List[j].Separator_Set(0, __T(" / "));
1085             List[0].Write(Get(Stream_Menu, 0, __T("Format")));
1086             List[1].Write(Get(Stream_Menu, 0, __T("Format/String")));
1087             List[2].Write(Get(Stream_Menu, 0, __T("List_StreamKind")));
1088             List[3].Write(Get(Stream_Menu, 0, __T("List_StreamPos")));
1089             List[4].Write(Get(Stream_Menu, 0, __T("List")));
1090             List[5].Write(Get(Stream_Menu, 0, __T("List/String")));
1091             bool IsNok=false;
1092             for (size_t j=0; j<6; j++)
1093                 if (!List[j].empty() && List[j].size()!=List[3].size())
1094                     IsNok=true;
1095             if (!IsNok && !List[2].empty() && List[2].size()==List[3].size())
1096             {
1097                 size_t Audio_Begin;
1098                 for (Audio_Begin=0; Audio_Begin <List[2].size(); Audio_Begin++)
1099                     if (List[2][Audio_Begin]==__T("2"))
1100                         break;
1101                 if (Audio_Begin!=List[2].size())
1102                 {
1103                     for (size_t j=0; j<6; j++)
1104                         if (!List[j].empty())
1105                             List[j].erase(List[j].begin()+Audio_Begin+i);
1106                     size_t Audio_End;
1107                     for (Audio_End=Audio_Begin+1; Audio_End<List[2].size(); Audio_End++)
1108                         if (List[2][Audio_End]!=__T("2"))
1109                             break;
1110                     for (size_t j=Audio_Begin+i; j<Audio_End; j++)
1111                         List[3][j].From_Number(List[3][j].To_int32u()-1-OtherID_Count);
1112                     Fill(Stream_Menu, 0, "Format", List[0].Read(), true);
1113                     Fill(Stream_Menu, 0, "Format/String", List[1].Read(), true);
1114                     Fill(Stream_Menu, 0, "List_StreamKind", List[2].Read(), true);
1115                     Fill(Stream_Menu, 0, "List_StreamPos", List[3].Read(), true);
1116                     Fill(Stream_Menu, 0, "List", List[4].Read(), true);
1117                     Fill(Stream_Menu, 0, "List/String", List[5].Read(), true);
1118                 }
1119             }
1120         }
1121         if (BitRate)
1122             Fill(Stream_Audio, Pos, Audio_BitRate, BitRate, 10, true);
1123         if (BitRate_Encoded)
1124             Fill(Stream_Audio, Pos, Audio_BitRate_Encoded, BitRate_Encoded, 10, true);
1125         if (StreamSize)
1126             Fill(Stream_Audio, Pos, Audio_StreamSize, StreamSize, 10, true);
1127         if (StreamSize_Encoded)
1128             Fill(Stream_Audio, Pos, Audio_StreamSize_Encoded, StreamSize_Encoded, 10, true);
1129     }
1130 
1131     //Channels
1132     if (Retrieve(Stream_Audio, Pos, Audio_Channel_s_).empty())
1133     {
1134         const Ztring& CodecID=Retrieve(Stream_Audio, Pos, Audio_CodecID);
1135         if (CodecID==__T("samr")
1136          || CodecID==__T("sawb")
1137          || CodecID==__T("7A21")
1138          || CodecID==__T("7A22"))
1139         Fill(Stream_Audio, Pos, Audio_Channel_s_, 1); //AMR is always with 1 channel
1140     }
1141 
1142     //SamplingCount
1143     if (Retrieve(Stream_Audio, Pos, Audio_SamplingCount).empty())
1144     {
1145         float64 Duration=Retrieve(Stream_Audio, Pos, Audio_Duration).To_float64();
1146         bool DurationFromGeneral;
1147         if (Duration==0)
1148         {
1149             Duration=Retrieve(Stream_General, 0, General_Duration).To_float64();
1150             DurationFromGeneral=Retrieve(Stream_General, 0, General_Format)!=Retrieve(Stream_Audio, Pos, Audio_Format);
1151         }
1152         else
1153             DurationFromGeneral=false;
1154         float64 SamplingRate=Retrieve(Stream_Audio, Pos, Audio_SamplingRate).To_float64();
1155         if (Duration && SamplingRate)
1156         {
1157             Fill(Stream_Audio, Pos, Audio_SamplingCount, Duration/1000*SamplingRate, 0);
1158             if (DurationFromGeneral && Retrieve_Const(Stream_Audio, Pos, Audio_Format)!=Retrieve_Const(Stream_General, 0, General_Format))
1159             {
1160                 Fill(Stream_Audio, Pos, "SamplingCount_Source", "General_Duration");
1161                 Fill_SetOptions(Stream_Audio, Pos, "SamplingCount_Source", "N NTN");
1162             }
1163         }
1164     }
1165 
1166     //Frame count
1167     if (Retrieve(Stream_Audio, Pos, Audio_FrameCount).empty() && Frame_Count_NotParsedIncluded!=(int64u)-1 && File_Offset+Buffer_Size==File_Size)
1168     {
1169         if (Count_Get(Stream_Video)==0 && Count_Get(Stream_Audio)==1)
1170             Fill(Stream_Audio, 0, Audio_FrameCount, Frame_Count_NotParsedIncluded);
1171     }
1172 
1173     //FrameRate same as SampleRate
1174     if (Retrieve(Stream_Audio, Pos, Audio_SamplingRate).To_float64() == Retrieve(Stream_Audio, Pos, Audio_FrameRate).To_float64())
1175         Clear(Stream_Audio, Pos, Audio_FrameRate);
1176 
1177     //SamplingRate
1178     if (Retrieve(Stream_Audio, Pos, Audio_SamplingRate).empty())
1179     {
1180         float64 BitDepth=Retrieve(Stream_Audio, Pos, Audio_BitDepth).To_float64();
1181         float64 Channels=Retrieve(Stream_Audio, Pos, Audio_Channel_s_).To_float64();
1182         float64 BitRate=Retrieve(Stream_Audio, Pos, Audio_BitRate).To_float64();
1183         if (BitDepth && Channels && BitRate)
1184             Fill(Stream_Audio, Pos, Audio_SamplingRate, BitRate/Channels/BitDepth, 0);
1185     }
1186 
1187     //SamplesPerFrames
1188     if (Retrieve(Stream_Audio, Pos, Audio_SamplesPerFrame).empty())
1189     {
1190         float64 FrameRate=Retrieve(Stream_Audio, Pos, Audio_FrameRate).To_float64();
1191         float64 SamplingRate=0;
1192         ZtringList SamplingRates;
1193         SamplingRates.Separator_Set(0, " / ");
1194         SamplingRates.Write(Retrieve(Stream_Audio, Pos, Audio_SamplingRate));
1195         for (size_t i=0; i<SamplingRates.size(); ++i)
1196         {
1197             SamplingRate = SamplingRates[i].To_float64();
1198             if (SamplingRate)
1199                 break; // Using the first valid one
1200         }
1201         if (FrameRate && SamplingRate && FrameRate!=SamplingRate)
1202         {
1203             float64 SamplesPerFrameF=SamplingRate/FrameRate;
1204             Ztring SamplesPerFrame;
1205             if (SamplesPerFrameF>1601 && SamplesPerFrameF<1602)
1206                 SamplesPerFrame = __T("1601.6"); // Usually this is 29.970 fps PCM. TODO: check if it is OK in all cases
1207             else if (SamplesPerFrameF>800 && SamplesPerFrameF<801)
1208                 SamplesPerFrame = __T("800.8"); // Usually this is 59.940 fps PCM. TODO: check if it is OK in all cases
1209             else
1210                 SamplesPerFrame.From_Number(SamplesPerFrameF, 0);
1211             Fill(Stream_Audio, Pos, Audio_SamplesPerFrame, SamplesPerFrame);
1212         }
1213     }
1214 
1215     //Duration
1216     if (Retrieve(Stream_Audio, Pos, Audio_Duration).empty())
1217     {
1218         float64 SamplingRate=Retrieve(Stream_Audio, Pos, Audio_SamplingRate).To_float64();
1219         if (SamplingRate)
1220         {
1221             float64 Duration=Retrieve(Stream_Audio, Pos, Audio_SamplingCount).To_float64()*1000/SamplingRate;
1222             if (Duration)
1223             {
1224                 Fill(Stream_Audio, Pos, Audio_Duration, Duration, 0);
1225                 Ztring Source=Retrieve(Stream_Audio, Pos, "SamplingCount_Source");
1226                 if (!Source.empty())
1227                 {
1228                     Fill(Stream_Audio, Pos, "Duration_Source", Source);
1229                     Fill_SetOptions(Stream_Audio, Pos, "Duration_Source", "N NTN");
1230                 }
1231             }
1232         }
1233     }
1234 
1235     //Stream size
1236     if (Retrieve(Stream_Audio, Pos, Audio_StreamSize).empty() && Retrieve(Stream_Audio, Pos, Audio_BitRate_Mode)==__T("CBR"))
1237     {
1238         float64 Duration=Retrieve(Stream_Audio, Pos, Audio_Duration).To_float64();
1239         float64 BitRate=Retrieve(Stream_Audio, Pos, Audio_BitRate).To_float64();
1240         if (Duration && BitRate)
1241             Fill(Stream_Audio, Pos, Audio_StreamSize, Duration*BitRate/8/1000, 0, true);
1242     }
1243     if (Retrieve(Stream_Audio, Pos, Audio_StreamSize_Encoded).empty() && !Retrieve(Stream_Audio, Pos, Audio_BitRate_Encoded).empty() && Retrieve(Stream_Audio, Pos, Audio_BitRate_Mode)==__T("CBR"))
1244     {
1245         float64 Duration=Retrieve(Stream_Audio, Pos, Audio_Duration).To_float64();
1246         float64 BitRate_Encoded=Retrieve(Stream_Audio, Pos, Audio_BitRate_Encoded).To_float64();
1247         if (Duration)
1248             Fill(Stream_Audio, Pos, Audio_StreamSize_Encoded, Duration*BitRate_Encoded/8/1000, 0, true);
1249     }
1250 
1251     //CBR/VBR
1252     if (Retrieve(Stream_Audio, Pos, Audio_BitRate_Mode).empty() && !Retrieve(Stream_Audio, Pos, Audio_Codec).empty())
1253     {
1254         Ztring Z1=MediaInfoLib::Config.Codec_Get(Retrieve(Stream_Audio, Pos, Audio_Codec), InfoCodec_BitRate_Mode, Stream_Audio);
1255         if (!Z1.empty())
1256             Fill(Stream_Audio, Pos, Audio_BitRate_Mode, Z1);
1257     }
1258 }
1259 
1260 //---------------------------------------------------------------------------
Streams_Finish_StreamOnly_Text(size_t Pos)1261 void File__Analyze::Streams_Finish_StreamOnly_Text(size_t Pos)
1262 {
1263     //FrameRate from FrameCount and Duration
1264     if (Retrieve(Stream_Text, Pos, Text_FrameRate).empty())
1265     {
1266         int64u FrameCount=Retrieve(Stream_Text, Pos, Text_FrameCount).To_int64u();
1267         float64 Duration=Retrieve(Stream_Text, Pos, Text_Duration).To_float64()/1000;
1268         if (FrameCount && Duration)
1269            Fill(Stream_Text, Pos, Text_FrameRate, FrameCount/Duration, 3);
1270     }
1271 }
1272 
1273 //---------------------------------------------------------------------------
Streams_Finish_StreamOnly_Other(size_t UNUSED (StreamPos))1274 void File__Analyze::Streams_Finish_StreamOnly_Other(size_t UNUSED(StreamPos))
1275 {
1276 }
1277 
1278 //---------------------------------------------------------------------------
Streams_Finish_StreamOnly_Image(size_t UNUSED (StreamPos))1279 void File__Analyze::Streams_Finish_StreamOnly_Image(size_t UNUSED(StreamPos))
1280 {
1281 }
1282 
1283 //---------------------------------------------------------------------------
Streams_Finish_StreamOnly_Menu(size_t UNUSED (StreamPos))1284 void File__Analyze::Streams_Finish_StreamOnly_Menu(size_t UNUSED(StreamPos))
1285 {
1286 }
1287 
1288 //---------------------------------------------------------------------------
Streams_Finish_InterStreams()1289 void File__Analyze::Streams_Finish_InterStreams()
1290 {
1291     //Duration if General not filled
1292     if (Retrieve(Stream_General, 0, General_Duration).empty())
1293     {
1294         int64u Duration=0;
1295         //For all streams (Generic)
1296         for (size_t StreamKind=Stream_Video; StreamKind<Stream_Max; StreamKind++)
1297             for (size_t Pos=0; Pos<Count_Get((stream_t)StreamKind); Pos++)
1298             {
1299                 if (!Retrieve((stream_t)StreamKind, Pos, Fill_Parameter((stream_t)StreamKind, Generic_Duration)).empty())
1300                 {
1301                     int64u Duration_Stream=Retrieve((stream_t)StreamKind, Pos, Fill_Parameter((stream_t)StreamKind, Generic_Duration)).To_int64u();
1302                     if (Duration_Stream>Duration)
1303                         Duration=Duration_Stream;
1304                 }
1305             }
1306 
1307         //Filling
1308         if (Duration>0)
1309             Fill(Stream_General, 0, General_Duration, Duration);
1310     }
1311 
1312     //(*Stream) size if all stream sizes are OK
1313     if (Retrieve(Stream_General, 0, General_StreamSize).empty())
1314     {
1315         int64u StreamSize_Total=0;
1316         bool IsOK=true;
1317         //For all streams (Generic)
1318         for (size_t StreamKind=Stream_Video; StreamKind<Stream_Max; StreamKind++)
1319         {
1320             if (StreamKind!=Stream_Other && StreamKind!=Stream_Menu) //They have no big size, we never calculate them
1321                 for (size_t Pos=0; Pos<Count_Get((stream_t)StreamKind); Pos++)
1322                 {
1323                     if (!Retrieve((stream_t)StreamKind, Pos, Fill_Parameter((stream_t)StreamKind, Generic_StreamSize_Encoded)).empty())
1324                         StreamSize_Total+=Retrieve((stream_t)StreamKind, Pos, Fill_Parameter((stream_t)StreamKind, Generic_StreamSize_Encoded)).To_int64u();
1325                     else if (!Retrieve((stream_t)StreamKind, Pos, Fill_Parameter((stream_t)StreamKind, Generic_StreamSize)).empty())
1326                         StreamSize_Total+=Retrieve((stream_t)StreamKind, Pos, Fill_Parameter((stream_t)StreamKind, Generic_StreamSize)).To_int64u();
1327                     else
1328                         IsOK=false; //StreamSize not available for 1 stream, we can't calculate
1329                 }
1330         }
1331 
1332         //Filling
1333         if (IsOK && StreamSize_Total>0 && StreamSize_Total<File_Size)
1334             Fill(Stream_General, 0, General_StreamSize, File_Size-StreamSize_Total);
1335     }
1336 
1337     //OverallBitRate if we have one Audio stream with bitrate
1338     if (Retrieve(Stream_General, 0, General_Duration).empty() && Retrieve(Stream_General, 0, General_OverallBitRate).empty() && Count_Get(Stream_Video) == 0 && Count_Get(Stream_Audio) == 1 && Retrieve(Stream_Audio, 0, Audio_BitRate).To_int64u() != 0 && (Retrieve(Stream_General, 0, General_Format) == Retrieve(Stream_Audio, 0, Audio_Format) || !Retrieve(Stream_General, 0, General_HeaderSize).empty()))
1339     {
1340         const Ztring& EncodedBitRate=Retrieve_Const(Stream_Audio, 0, Audio_BitRate_Encoded);
1341         Fill(Stream_General, 0, General_OverallBitRate, EncodedBitRate.empty()?Retrieve_Const(Stream_Audio, 0, Audio_BitRate):EncodedBitRate);
1342     }
1343 
1344     //OverallBitRate if Duration
1345     if (Retrieve(Stream_General, 0, General_OverallBitRate).empty() && Retrieve(Stream_General, 0, General_Duration).To_int64u()!=0 && !Retrieve(Stream_General, 0, General_FileSize).empty())
1346     {
1347         float64 Duration=0;
1348         if (Count_Get(Stream_Video)==1 && Retrieve(Stream_General, 0, General_Duration)==Retrieve(Stream_Video, 0, General_Duration) && !Retrieve(Stream_Video, 0, Video_FrameCount).empty() && !Retrieve(Stream_Video, 0, Video_FrameRate).empty())
1349         {
1350             int64u FrameCount=Retrieve(Stream_Video, 0, Video_FrameCount).To_int64u();
1351             float64 FrameRate=Retrieve(Stream_Video, 0, Video_FrameRate).To_float64();
1352             if (FrameCount && FrameRate)
1353                 Duration=FrameCount*1000/FrameRate; //More precise (example: 1 frame at 29.97 fps)
1354         }
1355         if (Duration==0)
1356             Duration=Retrieve(Stream_General, 0, General_Duration).To_float64();
1357         Fill(Stream_General, 0, General_OverallBitRate, Retrieve(Stream_General, 0, General_FileSize).To_int64u()*8*1000/Duration, 0);
1358     }
1359 
1360     //Duration if OverallBitRate
1361     if (Retrieve(Stream_General, 0, General_Duration).empty() && Retrieve(Stream_General, 0, General_OverallBitRate).To_int64u()!=0)
1362         Fill(Stream_General, 0, General_Duration, Retrieve(Stream_General, 0, General_FileSize).To_float64()*8*1000/Retrieve(Stream_General, 0, General_OverallBitRate).To_float64(), 0);
1363 
1364     //Video bitrate can be the nominal one if <4s (bitrate estimation is not enough precise
1365     if (Count_Get(Stream_Video)==1 && Retrieve(Stream_Video, 0, Video_BitRate).empty() && Retrieve(Stream_General, 0, General_Duration).To_int64u()<4000)
1366     {
1367         Fill(Stream_Video, 0, Video_BitRate, Retrieve(Stream_Video, 0, Video_BitRate_Nominal));
1368         Clear(Stream_Video, 0, Video_BitRate_Nominal);
1369     }
1370 
1371     //Video bitrate if we have all audio bitrates and overal bitrate
1372     if (Count_Get(Stream_Video)==1 && Retrieve(Stream_General, 0, General_OverallBitRate).size()>4 && Retrieve(Stream_Video, 0, Video_BitRate).empty() && Retrieve(Stream_Video, 0, Video_BitRate_Encoded).empty() && Retrieve(Stream_General, 0, General_Duration).To_int64u()>=1000) //BitRate is > 10 000 and Duration>10s, to avoid strange behavior
1373     {
1374         double GeneralBitRate_Ratio=0.98;  //Default container overhead=2%
1375         int32u GeneralBitRate_Minus=5000;  //5000 bps because of a "classic" stream overhead
1376         double VideoBitRate_Ratio  =0.98;  //Default container overhead=2%
1377         int32u VideoBitRate_Minus  =2000;  //2000 bps because of a "classic" stream overhead
1378         double AudioBitRate_Ratio  =0.98;  //Default container overhead=2%
1379         int32u AudioBitRate_Minus  =2000;  //2000 bps because of a "classic" stream overhead
1380         double TextBitRate_Ratio   =0.98;  //Default container overhead=2%
1381         int32u TextBitRate_Minus   =2000;  //2000 bps because of a "classic" stream overhead
1382         //Specific value depends of Container
1383         if (StreamSource==IsStream)
1384         {
1385             GeneralBitRate_Ratio=1;
1386             GeneralBitRate_Minus=0;
1387             VideoBitRate_Ratio  =1;
1388             VideoBitRate_Minus  =0;
1389             AudioBitRate_Ratio  =1;
1390             AudioBitRate_Minus  =0;
1391             TextBitRate_Ratio   =1;
1392             TextBitRate_Minus   =0;
1393         }
1394         if (Get(Stream_General, 0, __T("Format"))==__T("MPEG-TS"))
1395         {
1396             GeneralBitRate_Ratio=0.98;
1397             GeneralBitRate_Minus=0;
1398             VideoBitRate_Ratio  =0.97;
1399             VideoBitRate_Minus  =0;
1400             AudioBitRate_Ratio  =0.96;
1401             AudioBitRate_Minus  =0;
1402             TextBitRate_Ratio   =0.96;
1403             TextBitRate_Minus   =0;
1404         }
1405         if (Get(Stream_General, 0, __T("Format"))==__T("MPEG-PS"))
1406         {
1407             GeneralBitRate_Ratio=0.99;
1408             GeneralBitRate_Minus=0;
1409             VideoBitRate_Ratio  =0.99;
1410             VideoBitRate_Minus  =0;
1411             AudioBitRate_Ratio  =0.99;
1412             AudioBitRate_Minus  =0;
1413             TextBitRate_Ratio   =0.99;
1414             TextBitRate_Minus   =0;
1415         }
1416         if (MediaInfoLib::Config.Format_Get(Retrieve(Stream_General, 0, General_Format), InfoFormat_KindofFormat)==__T("MPEG-4"))
1417         {
1418             GeneralBitRate_Ratio=1;
1419             GeneralBitRate_Minus=0;
1420             VideoBitRate_Ratio  =1;
1421             VideoBitRate_Minus  =0;
1422             AudioBitRate_Ratio  =1;
1423             AudioBitRate_Minus  =0;
1424             TextBitRate_Ratio   =1;
1425             TextBitRate_Minus   =0;
1426         }
1427         if (Get(Stream_General, 0, __T("Format"))==__T("Matroska"))
1428         {
1429             GeneralBitRate_Ratio=0.99;
1430             GeneralBitRate_Minus=0;
1431             VideoBitRate_Ratio  =0.99;
1432             VideoBitRate_Minus  =0;
1433             AudioBitRate_Ratio  =0.99;
1434             AudioBitRate_Minus  =0;
1435             TextBitRate_Ratio   =0.99;
1436             TextBitRate_Minus   =0;
1437         }
1438         if (Get(Stream_General, 0, __T("Format"))==__T("MXF"))
1439         {
1440             GeneralBitRate_Ratio=1;
1441             GeneralBitRate_Minus=1000;
1442             VideoBitRate_Ratio  =1.00;
1443             VideoBitRate_Minus  =1000;
1444             AudioBitRate_Ratio  =1.00;
1445             AudioBitRate_Minus  =1000;
1446             TextBitRate_Ratio   =1.00;
1447             TextBitRate_Minus   =1000;
1448         }
1449 
1450         //Testing
1451         float64 VideoBitRate=Retrieve(Stream_General, 0, General_OverallBitRate).To_float64()*GeneralBitRate_Ratio-GeneralBitRate_Minus;
1452         bool VideobitRateIsValid=true;
1453         for (size_t Pos=0; Pos<Count_Get(Stream_Audio); Pos++)
1454         {
1455             float64 AudioBitRate=0;
1456             if (!Retrieve(Stream_Audio, Pos, Audio_BitRate_Encoded).empty() && Retrieve(Stream_Audio, Pos, Audio_BitRate_Encoded)[0]<=__T('9')) //Note: quick test if it is a number
1457                 AudioBitRate=Retrieve(Stream_Audio, Pos, Audio_BitRate_Encoded).To_float64();
1458             else if (!Retrieve(Stream_Audio, Pos, Audio_BitRate).empty() && Retrieve(Stream_Audio, Pos, Audio_BitRate)[0]<=__T('9')) //Note: quick test if it is a number
1459                 AudioBitRate=Retrieve(Stream_Audio, Pos, Audio_BitRate).To_float64();
1460             else
1461                 VideobitRateIsValid=false;
1462             if (VideobitRateIsValid && AudioBitRate_Ratio)
1463                 VideoBitRate-=AudioBitRate/AudioBitRate_Ratio+AudioBitRate_Minus;
1464         }
1465         for (size_t Pos=0; Pos<Count_Get(Stream_Text); Pos++)
1466         {
1467             float64 TextBitRate;
1468             if (Retrieve(Stream_Text, Pos, Text_BitRate_Encoded).empty())
1469                 TextBitRate=Retrieve(Stream_Text, Pos, Text_BitRate).To_float64();
1470             else
1471                 TextBitRate=Retrieve(Stream_Text, Pos, Text_BitRate_Encoded).To_float64();
1472             if (TextBitRate_Ratio)
1473                 VideoBitRate-=TextBitRate/TextBitRate_Ratio+TextBitRate_Minus;
1474             else
1475                 VideoBitRate-=1000; //Estimation: Text stream are not often big
1476         }
1477         if (VideobitRateIsValid && VideoBitRate>=10000) //to avoid strange behavior
1478         {
1479             VideoBitRate=VideoBitRate*VideoBitRate_Ratio-VideoBitRate_Minus;
1480             Fill(Stream_Video, 0, Video_BitRate, VideoBitRate, 0); //Default container overhead=2%
1481             if (Retrieve(Stream_Video, 0, Video_StreamSize).empty() && !Retrieve(Stream_Video, 0, Video_Duration).empty())
1482             {
1483                 float64 Duration=0;
1484                 if (!Retrieve(Stream_Video, 0, Video_FrameCount).empty() && !Retrieve(Stream_Video, 0, Video_FrameRate).empty())
1485                 {
1486                     int64u FrameCount=Retrieve(Stream_Video, 0, Video_FrameCount).To_int64u();
1487                     float64 FrameRate=Retrieve(Stream_Video, 0, Video_FrameRate).To_float64();
1488                     if (FrameCount && FrameRate)
1489                         Duration=FrameCount*1000/FrameRate; //More precise (example: 1 frame at 29.97 fps)
1490                 }
1491                 if (Duration==0)
1492                     Duration=Retrieve(Stream_Video, 0, Video_Duration).To_float64();
1493                 if (Duration)
1494                 {
1495                     int64u StreamSize=float64_int64s(VideoBitRate/8*Duration/1000);
1496                     if (StreamSource==IsStream && File_Size!=(int64u)-1 && StreamSize>=File_Size*0.99)
1497                         StreamSize=File_Size;
1498                     Fill(Stream_Video, 0, Video_StreamSize, StreamSize);
1499                 }
1500             }
1501         }
1502     }
1503 
1504     //General stream size if we have all streamsize
1505     if (File_Size!=(int64u)-1 && Retrieve(Stream_General, 0, General_StreamSize).empty())
1506     {
1507         //Testing
1508         int64s StreamSize=File_Size;
1509         bool StreamSizeIsValid=true;
1510         for (size_t StreamKind_Pos=Stream_General+1; StreamKind_Pos<Stream_Menu; StreamKind_Pos++)
1511             for (size_t Pos=0; Pos<Count_Get((stream_t)StreamKind_Pos); Pos++)
1512             {
1513                 int64u StreamXX_StreamSize=0;
1514                 if (!Retrieve((stream_t)StreamKind_Pos, Pos, Fill_Parameter((stream_t)StreamKind_Pos, Generic_StreamSize_Encoded)).empty())
1515                     StreamXX_StreamSize+=Retrieve((stream_t)StreamKind_Pos, Pos, Fill_Parameter((stream_t)StreamKind_Pos, Generic_StreamSize_Encoded)).To_int64u();
1516                 else if (!Retrieve((stream_t)StreamKind_Pos, Pos, Fill_Parameter((stream_t)StreamKind_Pos, Generic_StreamSize)).empty())
1517                     StreamXX_StreamSize+=Retrieve((stream_t)StreamKind_Pos, Pos, Fill_Parameter((stream_t)StreamKind_Pos, Generic_StreamSize)).To_int64u();
1518                 if (StreamXX_StreamSize>0 || StreamKind_Pos==Stream_Text)
1519                     StreamSize-=StreamXX_StreamSize;
1520                 else
1521                     StreamSizeIsValid=false;
1522             }
1523         if (StreamSizeIsValid && StreamSize>=0) //to avoid strange behavior
1524             Fill(Stream_General, 0, General_StreamSize, StreamSize);
1525     }
1526 
1527     //General_OverallBitRate_Mode
1528     if (Retrieve(Stream_General, 0, General_OverallBitRate_Mode).empty())
1529     {
1530         bool IsValid=false;
1531         bool IsCBR=true;
1532         bool IsVBR=false;
1533         for (size_t StreamKind=Stream_General+1; StreamKind<Stream_Menu; StreamKind++)
1534             for (size_t StreamPos=0; StreamPos<Count_Get((stream_t)StreamKind); StreamPos++)
1535             {
1536                 if (!IsValid)
1537                     IsValid=true;
1538                 if (Retrieve((stream_t)StreamKind, StreamPos, Fill_Parameter((stream_t)StreamKind, Generic_BitRate_Mode))!=__T("CBR"))
1539                     IsCBR=false;
1540                 if (Retrieve((stream_t)StreamKind, StreamPos, Fill_Parameter((stream_t)StreamKind, Generic_BitRate_Mode))==__T("VBR"))
1541                     IsVBR=true;
1542             }
1543         if (IsValid)
1544         {
1545             if (IsCBR)
1546                 Fill(Stream_General, 0, General_OverallBitRate_Mode, "CBR");
1547             if (IsVBR)
1548                 Fill(Stream_General, 0, General_OverallBitRate_Mode, "VBR");
1549         }
1550     }
1551 
1552     //FrameRate if General not filled
1553     if (Retrieve(Stream_General, 0, General_FrameRate).empty() && Count_Get(Stream_Video))
1554     {
1555         Ztring FrameRate=Retrieve(Stream_Video, 0, Video_FrameRate);
1556         bool IsOk=true;
1557         if (FrameRate.empty())
1558         {
1559             for (size_t StreamKind=Stream_General+1; StreamKind<Stream_Max; StreamKind++)
1560                 for (size_t StreamPos=0; StreamPos<Count_Get((stream_t)StreamKind); StreamPos++)
1561                 {
1562                     Ztring FrameRate2=Retrieve((stream_t)StreamKind, StreamPos, Fill_Parameter((stream_t)StreamKind, Generic_FrameRate));
1563                     if (!FrameRate2.empty() && FrameRate2!=FrameRate)
1564                         IsOk=false;
1565                 }
1566         }
1567         if (IsOk)
1568             Fill(Stream_General, 0, General_FrameRate, FrameRate);
1569     }
1570 
1571     //FrameCount if General not filled
1572     if (Retrieve(Stream_General, 0, General_FrameCount).empty() && Count_Get(Stream_Video) && Retrieve(Stream_General, 0, "IsTruncated").empty())
1573     {
1574         Ztring FrameCount=Retrieve(Stream_Video, 0, Video_FrameCount);
1575         bool IsOk=true;
1576         if (FrameCount.empty())
1577         {
1578             for (size_t StreamKind=Stream_General+1; StreamKind<Stream_Max; StreamKind++)
1579                 for (size_t StreamPos=0; StreamPos<Count_Get((stream_t)StreamKind); StreamPos++)
1580                 {
1581                     Ztring FrameCount2=Retrieve((stream_t)StreamKind, StreamPos, Fill_Parameter((stream_t)StreamKind, Generic_FrameCount));
1582                     if (!FrameCount2.empty() && FrameCount2!=FrameCount)
1583                         IsOk=false;
1584                 }
1585         }
1586         if (IsOk)
1587             Fill(Stream_General, 0, General_FrameCount, FrameCount);
1588     }
1589 
1590     //Tags
1591     Tags();
1592 }
1593 
1594 //---------------------------------------------------------------------------
Streams_Finish_HumanReadable()1595 void File__Analyze::Streams_Finish_HumanReadable()
1596 {
1597     //Generic
1598     for (size_t StreamKind=Stream_General; StreamKind<Stream_Max; StreamKind++)
1599         for (size_t StreamPos=0; StreamPos<Count_Get((stream_t)StreamKind); StreamPos++)
1600             for (size_t Parameter=0; Parameter<Count_Get((stream_t)StreamKind, StreamPos); Parameter++)
1601                 Streams_Finish_HumanReadable_PerStream((stream_t)StreamKind, StreamPos, Parameter);
1602 }
1603 
1604 //---------------------------------------------------------------------------
Streams_Finish_HumanReadable_PerStream(stream_t StreamKind,size_t StreamPos,size_t Parameter)1605 void File__Analyze::Streams_Finish_HumanReadable_PerStream(stream_t StreamKind, size_t StreamPos, size_t Parameter)
1606 {
1607     const Ztring ParameterName=Retrieve(StreamKind, StreamPos, Parameter, Info_Name);
1608     const Ztring Value=Retrieve(StreamKind, StreamPos, Parameter, Info_Text);
1609 
1610     //Strings
1611     const Ztring &List_Measure_Value=MediaInfoLib::Config.Info_Get(StreamKind).Read(Parameter, Info_Measure);
1612             if (List_Measure_Value==__T(" byte"))
1613         FileSize_FileSize123(StreamKind, StreamPos, Parameter);
1614     else if (List_Measure_Value==__T(" bps") || List_Measure_Value==__T(" Hz"))
1615         Kilo_Kilo123(StreamKind, StreamPos, Parameter);
1616     else if (List_Measure_Value==__T(" ms"))
1617         Duration_Duration123(StreamKind, StreamPos, Parameter);
1618     else if (List_Measure_Value==__T("Yes"))
1619         YesNo_YesNo(StreamKind, StreamPos, Parameter);
1620     else
1621     {
1622         Value_Value123(StreamKind, StreamPos, Parameter);
1623 
1624         //Special cases - 120 fps 24/30 mode
1625         if (StreamKind==Stream_Video
1626          && List_Measure_Value==__T(" fps")
1627          && Retrieve(StreamKind, StreamPos, Video_FrameRate).To_int32u()==120
1628          && Retrieve(StreamKind, StreamPos, Video_FrameRate_Minimum).To_int32u()==24
1629          && Retrieve(StreamKind, StreamPos, Video_FrameRate_Maximum).To_int32u()==30)
1630             Fill(Stream_Video, StreamPos_Last, Video_FrameRate_String, MediaInfoLib::Config.Language_Get(Retrieve(StreamKind, StreamPos, Video_FrameRate)+__T(" (24/30)"), __T(" fps")), true);
1631 
1632         //Special cases - Frame rate
1633         if (StreamKind==Stream_Video
1634          && Parameter==Video_FrameRate
1635          && !Retrieve(StreamKind, StreamPos, Video_FrameRate).empty()
1636          && !Retrieve(StreamKind, StreamPos, Video_FrameRate_Num).empty()
1637          && !Retrieve(StreamKind, StreamPos, Video_FrameRate_Den).empty())
1638             Fill(Stream_Video, StreamPos, Video_FrameRate_String, MediaInfoLib::Config.Language_Get(Retrieve(StreamKind, StreamPos, Video_FrameRate)+__T(" (")+Retrieve(StreamKind, StreamPos, Video_FrameRate_Num)+__T("/")+Retrieve(StreamKind, StreamPos, Video_FrameRate_Den)+__T(")"), __T(" fps")), true);
1639         if (StreamKind==Stream_Video
1640          && Parameter==Video_FrameRate_Original
1641          && !Retrieve(StreamKind, StreamPos, Video_FrameRate_Original).empty()
1642          && !Retrieve(StreamKind, StreamPos, Video_FrameRate_Original_Num).empty()
1643          && !Retrieve(StreamKind, StreamPos, Video_FrameRate_Original_Den).empty())
1644             Fill(Stream_Video, StreamPos, Video_FrameRate_Original_String, MediaInfoLib::Config.Language_Get(Retrieve(StreamKind, StreamPos, Video_FrameRate_Original)+__T(" (")+Retrieve(StreamKind, StreamPos, Video_FrameRate_Original_Num)+__T("/")+Retrieve(StreamKind, StreamPos, Video_FrameRate_Original_Den)+__T(")"), __T(" fps")), true);
1645         if (StreamKind==Stream_Other
1646          && Parameter==Other_FrameRate
1647          && !Retrieve(StreamKind, StreamPos, Other_FrameRate).empty()
1648          && !Retrieve(StreamKind, StreamPos, Other_FrameRate_Num).empty()
1649          && !Retrieve(StreamKind, StreamPos, Other_FrameRate_Den).empty())
1650             Fill(Stream_Other, StreamPos, Other_FrameRate_String, MediaInfoLib::Config.Language_Get(Retrieve(StreamKind, StreamPos, Other_FrameRate)+__T(" (")+Retrieve(StreamKind, StreamPos, Other_FrameRate_Num)+__T("/")+Retrieve(StreamKind, StreamPos, Other_FrameRate_Den)+__T(")"), __T(" fps")), true);
1651     }
1652 
1653     //BitRate_Mode / OverallBitRate_Mode
1654     if (ParameterName==(StreamKind==Stream_General?__T("OverallBitRate_Mode"):__T("BitRate_Mode")) && MediaInfoLib::Config.ReadByHuman_Get())
1655     {
1656         Clear(StreamKind, StreamPos, StreamKind==Stream_General?"OverallBitRate_Mode/String":"BitRate_Mode/String");
1657 
1658         ZtringList List;
1659         List.Separator_Set(0, __T(" / "));
1660         List.Write(Retrieve(StreamKind, StreamPos, Parameter));
1661 
1662         //Per value
1663         for (size_t Pos=0; Pos<List.size(); Pos++)
1664             List[Pos]=MediaInfoLib::Config.Language_Get(Ztring(__T("BitRate_Mode_"))+List[Pos]);
1665 
1666         const Ztring Translated=List.Read();
1667         Fill(StreamKind, StreamPos, StreamKind==Stream_General?"OverallBitRate_Mode/String":"BitRate_Mode/String", Translated.find(__T("BitRate_Mode_"))?Translated:Value);
1668     }
1669 
1670     //Encoded_Application
1671     if ((   ParameterName==__T("Encoded_Application")
1672          || ParameterName==__T("Encoded_Application_CompanyName")
1673          || ParameterName==__T("Encoded_Application_Name")
1674          || ParameterName==__T("Encoded_Application_Version")
1675          || ParameterName==__T("Encoded_Application_Date"))
1676         && Retrieve(StreamKind, StreamPos, "Encoded_Application/String").empty())
1677     {
1678         Ztring CompanyName=Retrieve(StreamKind, StreamPos, "Encoded_Application_CompanyName");
1679         Ztring Name=Retrieve(StreamKind, StreamPos, "Encoded_Application_Name");
1680         Ztring Version=Retrieve(StreamKind, StreamPos, "Encoded_Application_Version");
1681         Ztring Date=Retrieve(StreamKind, StreamPos, "Encoded_Application_Date");
1682         if (!Name.empty())
1683         {
1684             Ztring String;
1685             if (!CompanyName.empty())
1686             {
1687                 String+=CompanyName;
1688                 String+=__T(" ");
1689             }
1690             String+=Name;
1691             if (!Version.empty())
1692             {
1693                 String+=__T(" ");
1694                 String+=Version;
1695             }
1696             if (!Date.empty())
1697             {
1698                 String+=__T(" (");
1699                 String+=Date;
1700                 String+=__T(")");
1701             }
1702             Fill(StreamKind, StreamPos, "Encoded_Application/String", String, true);
1703         }
1704         else
1705             Fill(StreamKind, StreamPos, "Encoded_Application/String", Retrieve(StreamKind, StreamPos, "Encoded_Application"), true);
1706     }
1707 
1708     //Encoded_Library
1709     if ((   ParameterName==__T("Encoded_Library")
1710          || ParameterName==__T("Encoded_Library_CompanyName")
1711          || ParameterName==__T("Encoded_Library_Name")
1712          || ParameterName==__T("Encoded_Library_Version")
1713          || ParameterName==__T("Encoded_Library_Date"))
1714         && Retrieve(StreamKind, StreamPos, "Encoded_Library/String").empty())
1715     {
1716         Ztring CompanyName=Retrieve(StreamKind, StreamPos, "Encoded_Library_CompanyName");
1717         Ztring Name=Retrieve(StreamKind, StreamPos, "Encoded_Library_Name");
1718         Ztring Version=Retrieve(StreamKind, StreamPos, "Encoded_Library_Version");
1719         Ztring Date=Retrieve(StreamKind, StreamPos, "Encoded_Library_Date");
1720         Ztring Encoded_Library=Retrieve(StreamKind, StreamPos, "Encoded_Library");
1721         Fill(StreamKind, StreamPos, "Encoded_Library/String", File__Analyze_Encoded_Library_String(CompanyName, Name, Version, Date, Encoded_Library), true);
1722     }
1723 
1724     //Format_Settings_Matrix
1725     if (StreamKind==Stream_Video && Parameter==Video_Format_Settings_Matrix)
1726     {
1727         Fill(Stream_Video, StreamPos, Video_Format_Settings_Matrix_String, MediaInfoLib::Config.Language_Get_Translate(__T("Format_Settings_Matrix_"), Value));
1728     }
1729 
1730     //Scan type
1731     if (StreamKind==Stream_Video && Parameter==Video_ScanType)
1732     {
1733         Fill(Stream_Video, StreamPos, Video_ScanType_String, MediaInfoLib::Config.Language_Get_Translate(__T("Interlaced_"), Value));
1734     }
1735     if (StreamKind==Stream_Video && Parameter==Video_ScanType_Original)
1736     {
1737         Fill(Stream_Video, StreamPos, Video_ScanType_Original_String, MediaInfoLib::Config.Language_Get_Translate(__T("Interlaced_"), Value));
1738     }
1739     if (StreamKind==Stream_Video && Parameter==Video_ScanType_StoreMethod)
1740     {
1741         Ztring ToTranslate=Ztring(__T("StoreMethod_"))+Value;
1742         if (!Retrieve(Stream_Video, StreamPos, Video_ScanType_StoreMethod_FieldsPerBlock).empty())
1743             ToTranslate+=__T('_')+Retrieve(Stream_Video, StreamPos, Video_ScanType_StoreMethod_FieldsPerBlock);
1744         Ztring Translated=MediaInfoLib::Config.Language_Get(ToTranslate);
1745         Fill(Stream_Video, StreamPos, Video_ScanType_StoreMethod_String, Translated.find(__T("StoreMethod_"))?Translated:Value);
1746     }
1747 
1748     //Scan order
1749     if (StreamKind==Stream_Video && Parameter==Video_ScanOrder)
1750     {
1751         Fill(Stream_Video, StreamPos, Video_ScanOrder_String, MediaInfoLib::Config.Language_Get_Translate(__T("Interlaced_"), Value));
1752     }
1753     if (StreamKind==Stream_Video && Parameter==Video_ScanOrder_Stored)
1754     {
1755         Fill(Stream_Video, StreamPos, Video_ScanOrder_Stored_String, MediaInfoLib::Config.Language_Get_Translate(__T("Interlaced_"), Value));
1756     }
1757     if (StreamKind==Stream_Video && Parameter==Video_ScanOrder_Original)
1758     {
1759         Fill(Stream_Video, StreamPos, Video_ScanOrder_Original_String, MediaInfoLib::Config.Language_Get_Translate(__T("Interlaced_"), Value));
1760     }
1761 
1762     //Interlacement
1763     if (StreamKind==Stream_Video && Parameter==Video_Interlacement)
1764     {
1765         const Ztring &Z1=Retrieve(Stream_Video, StreamPos, Video_Interlacement);
1766         if (Z1.size()==3)
1767             Fill(Stream_Video, StreamPos, Video_Interlacement_String, MediaInfoLib::Config.Language_Get(Ztring(__T("Interlaced_"))+Z1));
1768         else
1769             Fill(Stream_Video, StreamPos, Video_Interlacement_String, MediaInfoLib::Config.Language_Get(Z1));
1770         if (Retrieve(Stream_Video, StreamPos, Video_Interlacement_String).empty())
1771             Fill(Stream_Video, StreamPos, Video_Interlacement_String, Z1, true);
1772     }
1773 
1774     //FrameRate_Mode
1775     if (StreamKind==Stream_Video && Parameter==Video_FrameRate_Mode)
1776     {
1777         Fill(Stream_Video, StreamPos, Video_FrameRate_Mode_String, MediaInfoLib::Config.Language_Get_Translate(__T("FrameRate_Mode_"), Value));
1778     }
1779 
1780     //Compression_Mode
1781     if (Parameter==Fill_Parameter(StreamKind, Generic_Compression_Mode))
1782     {
1783         Fill(StreamKind, StreamPos, Fill_Parameter(StreamKind, Generic_Compression_Mode_String), MediaInfoLib::Config.Language_Get_Translate(__T("Compression_Mode_"), Value));
1784     }
1785 
1786     //Delay_Source
1787     if (Parameter==Fill_Parameter(StreamKind, Generic_Delay_Source))
1788     {
1789         Fill(StreamKind, StreamPos, Fill_Parameter(StreamKind, Generic_Delay_Source_String), MediaInfoLib::Config.Language_Get_Translate(__T("Delay_Source_"), Value));
1790     }
1791 
1792     //Gop_OpenClosed
1793     if (StreamKind==Stream_Video && (Parameter==Video_Gop_OpenClosed || Parameter==Video_Gop_OpenClosed_FirstFrame))
1794     {
1795         Fill(Stream_Video, StreamPos, Parameter+1, MediaInfoLib::Config.Language_Get_Translate(__T("Gop_OpenClosed_"), Value), true);
1796     }
1797 }
1798 
1799 } //NameSpace
1800