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