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 // For user: you can disable or enable it
9 //#define MEDIAINFO_DEBUG
10 //---------------------------------------------------------------------------
11
12 //---------------------------------------------------------------------------
13 // Pre-compilation
14 #include "MediaInfo/PreComp.h"
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18 //---------------------------------------------------------------------------
19
20 //---------------------------------------------------------------------------
21 #include "MediaInfo/Setup.h"
22 //---------------------------------------------------------------------------
23
24 //---------------------------------------------------------------------------
25 #if defined(MEDIAINFO_FILE_YES)
26 #include "MediaInfo/Reader/Reader_File.h"
27 #include "MediaInfo/File__Analyze.h"
28 #include "ZenLib/FileName.h"
29 #ifdef WINDOWS
30 #undef __TEXT
31 #if __cplusplus >= 201703L || _MSVC_LANG >= 201703L
32 namespace WindowsNamespace
33 {
34 #endif
35 #include "windows.h"
36 #if __cplusplus >= 201703L || _MSVC_LANG >= 201703L
37 }
38 using namespace WindowsNamespace;
39 #endif
40 #endif //WINDOWS
41 using namespace ZenLib;
42 using namespace std;
43 //---------------------------------------------------------------------------
44 // Debug stuff
45 #ifdef MEDIAINFO_DEBUG
46 int64u Reader_File_Offset=0;
47 int64u Reader_File_BytesRead_Total=0;
48 int64u Reader_File_BytesRead=0;
49 int64u Reader_File_Count=1;
50 #include <iostream>
51 #endif // MEDIAINFO_DEBUG
52 //---------------------------------------------------------------------------
53
54 namespace MediaInfoLib
55 {
56
57 #if MEDIAINFO_READTHREAD
Entry()58 void Reader_File_Thread::Entry()
59 {
60 ReadSize_Max=Base->Buffer_Max>>3;
61
62 for (;;)
63 {
64 size_t ToRead;
65 size_t Buffer_ToReadOffset;
66 {
67 CriticalSectionLocker CSL(Base->CS);
68 if (Base->Buffer_Begin==Base->Buffer_Max)
69 {
70 Base->IsLooping=false;
71 Base->Buffer_End=Base->Buffer_End2;
72 Base->Buffer_End2=0;
73 Base->Buffer_Begin=0;
74 }
75
76 if (Base->IsLooping)
77 {
78 ToRead=Base->Buffer_Begin-Base->Buffer_End2;
79 Buffer_ToReadOffset=Base->Buffer_End2;
80 }
81 else
82 {
83 ToRead=Base->Buffer_Max-Base->Buffer_End;
84 Buffer_ToReadOffset=Base->Buffer_End;
85 }
86 }
87 if (ToRead)
88 {
89 if (ToRead>ReadSize_Max)
90 ToRead=ReadSize_Max;
91 size_t BytesRead=Base->F.Read(Base->Buffer+Buffer_ToReadOffset, ToRead);
92 if (!BytesRead)
93 break;
94
95 {
96 CriticalSectionLocker CSL(Base->CS);
97 if (Base->IsLooping)
98 {
99 Base->Buffer_End2+=BytesRead;
100 }
101 else
102 {
103 Base->Buffer_End+=BytesRead;
104 if (Base->Buffer_End==Base->Buffer_Max)
105 {
106 Base->IsLooping=true;
107 }
108 }
109 }
110 #ifdef WINDOWS
111 SetEvent(Base->Condition_WaitingForMoreData);
112 #endif //WINDOWS
113 }
114 #ifdef WINDOWS
115 else
116 WaitForSingleObject(Base->Condition_WaitingForMorePlace, INFINITE);
117 #endif //WINDOWS
118
119 if (IsTerminating())
120 break;
121 Yield();
122 }
123
124 #ifdef WINDOWS
125 SetEvent(Base->Condition_WaitingForMoreData); //Sending the last event in case the main threading is waiting for more data
126 #endif //WINDOWS
127 }
128 #endif //MEDIAINFO_READTHREAD
129
130 const size_t Buffer_NoJump=128*1024;
131
132 //---------------------------------------------------------------------------
~Reader_File()133 Reader_File::~Reader_File()
134 {
135 #if MEDIAINFO_READTHREAD
136 Destroy_Thread(MI_Internal);
137 #endif //MEDIAINFO_READTHREAD
138 }
139
140 //---------------------------------------------------------------------------
141 #if MEDIAINFO_READTHREAD
Destroy_Thread(MediaInfo_Internal * MI)142 void Reader_File::Destroy_Thread(MediaInfo_Internal* MI)
143 {
144 if (ThreadInstance)
145 {
146 ThreadInstance->RequestTerminate();
147 SetEvent(Condition_WaitingForMorePlace);
148 while (!ThreadInstance->IsExited())
149 Sleep(0);
150 #ifdef WINDOWS
151 CloseHandle(Condition_WaitingForMorePlace);
152 CloseHandle(Condition_WaitingForMoreData);
153 #endif //WINDOWS
154 delete ThreadInstance; ThreadInstance = NULL;
155
156 MI->Config.File_Buffer = NULL;
157 MI->Config.File_Buffer_Size = 0;
158 MI->Config.File_Buffer_Size_Max = 0;
159 Buffer_Max = 0;
160 delete[] Buffer; Buffer = NULL;
161 Buffer_Begin = 0;
162 Buffer_End = 0;
163 Buffer_End2 = 0;
164 IsLooping = false;
165 }
166 }
167 #endif //MEDIAINFO_READTHREAD
168
169 //---------------------------------------------------------------------------
Format_Test(MediaInfo_Internal * MI,String File_Name)170 size_t Reader_File::Format_Test(MediaInfo_Internal* MI, String File_Name)
171 {
172 //std::cout<<Ztring(File_Name).To_Local().c_str()<<std::endl;
173 #if MEDIAINFO_EVENTS
174 {
175 string File_Name_Local=Ztring(File_Name).To_Local();
176 wstring File_Name_Unicode=Ztring(File_Name).To_Unicode();
177 struct MediaInfo_Event_General_Start_0 Event;
178 memset(&Event, 0xFF, sizeof(struct MediaInfo_Event_Generic));
179 Event.EventCode=MediaInfo_EventCode_Create(MediaInfo_Parser_None, MediaInfo_Event_General_Start, 0);
180 Event.EventSize=sizeof(struct MediaInfo_Event_General_Start_0);
181 Event.StreamIDs_Size=0;
182 Event.Stream_Size=File::Size_Get(File_Name);
183 Event.FileName=File_Name_Local.c_str();
184 Event.FileName_Unicode=File_Name_Unicode.c_str();
185 MI->Config.Event_Send(NULL, (const int8u*)&Event, sizeof(MediaInfo_Event_General_Start_0));
186 }
187 #endif //MEDIAINFO_EVENTS
188
189 //With Parser MultipleParsing
190 /*
191 MI->Open_Buffer_Init((int64u)-1, File_Name);
192 if (Format_Test_PerParser(MI, File_Name))
193 return 1;
194 return 0; //There is a problem
195 */
196
197 //Get the Extension
198 Ztring Extension=FileName::Extension_Get(File_Name);
199 Extension.MakeLowerCase();
200
201 //Search the theorical format from extension
202 InfoMap &FormatList=MediaInfoLib::Config.Format_Get();
203 InfoMap::iterator Format=FormatList.end();
204 if (!MI->Config.File_ForceParser_Get().empty())
205 Format=FormatList.find(MI->Config.File_ForceParser_Get());
206 if (Format==FormatList.end())
207 {
208 Format=FormatList.begin();
209 while (Format!=FormatList.end())
210 {
211 ZtringList Extensions;
212 Extensions.Separator_Set(0, __T(" "));
213 Extensions.Write(FormatList.Get(Format->first, InfoFormat_Extensions));
214 if (Extensions.Find(Extension)!=Error)
215 break;
216 ++Format;
217 }
218 }
219 if (Format!=FormatList.end())
220 {
221 const Ztring &Parser=Format->second(InfoFormat_Parser);
222 if (MI->SelectFromExtension(Parser))
223 {
224 //Test the theorical format
225 if (Format_Test_PerParser(MI, File_Name)>0)
226 return 1;
227 }
228 }
229
230 size_t ToReturn=MI->ListFormats(File_Name);
231 return ToReturn;
232 }
233
234 //---------------------------------------------------------------------------
Format_Test_PerParser(MediaInfo_Internal * MI,const String & File_Name)235 size_t Reader_File::Format_Test_PerParser(MediaInfo_Internal* MI, const String &File_Name)
236 {
237 //Init
238 MI_Internal=MI;
239 #if MEDIAINFO_READTHREAD
240 ThreadInstance=NULL;
241 Buffer_End2=0; //Is also used for counting bytes before activating the thread
242 #endif //MEDIAINFO_READTHREAD
243
244 //Opening the file
245 F.Open(File_Name);
246 if (!F.Opened_Get())
247 return 0;
248
249 //Info
250 Status=0;
251 MI->Config.File_Size=F.Size_Get();
252 MI->Config.File_Current_Offset=0;
253 MI->Config.File_Current_Size=MI->Config.File_Size;
254 MI->Config.File_Sizes.clear();
255 MI->Config.File_Sizes.push_back(MI->Config.File_Size);
256 MI->Config.File_Names_Pos=1;
257 if (MI->Config.File_Names.size()>1)
258 {
259 #if MEDIAINFO_ADVANCED
260 if (MI->Config.File_IgnoreSequenceFileSize_Get())
261 {
262 MI->Config.File_Size=(int64u)-1;
263 }
264 else
265 #endif //MEDIAINFO_ADVANCED
266 {
267 for (size_t Pos=1; Pos<MI->Config.File_Names.size(); Pos++)
268 {
269 int64u Size=File::Size_Get(MI->Config.File_Names[Pos]);
270 MI->Config.File_Sizes.push_back(Size);
271 MI->Config.File_Size+=Size;
272 }
273 }
274 }
275
276 //Partial file handling
277 Ztring Config_Partial_Begin=MI->Config.File_Partial_Begin_Get();
278 if (!Config_Partial_Begin.empty() && Config_Partial_Begin[0]>=__T('0') && Config_Partial_Begin[0]<=__T('9'))
279 {
280 if (Config_Partial_Begin.find(__T('%'))==Config_Partial_Begin.size()-1)
281 Partial_Begin=float64_int64s(MI->Config.File_Size*Config_Partial_Begin.To_float64()/100);
282 else
283 Partial_Begin=Config_Partial_Begin.To_int64u();
284 if (Partial_Begin)
285 F.GoTo(Partial_Begin);
286 }
287 else
288 Partial_Begin=0;
289 Ztring Config_Partial_End=MI->Config.File_Partial_End_Get();
290 if (!Config_Partial_End.empty() && Config_Partial_End[0]>=__T('0') && Config_Partial_End[0]<=__T('9'))
291 {
292 if (Config_Partial_End.find(__T('%'))==Config_Partial_End.size()-1)
293 Partial_End=float64_int64s(MI->Config.File_Size*Config_Partial_End.To_float64()/100);
294 else
295 Partial_End=Config_Partial_End.To_int64u();
296 }
297 else
298 Partial_End=(int64u)-1;
299 if (Partial_Begin>MI->Config.File_Size)
300 Partial_Begin=0; //Wrong value
301 if (Partial_Begin>Partial_End)
302 Partial_Begin=0; //Wrong value
303 CountOfSeconds=0;
304
305 //Parser
306 MI->Open_Buffer_Init((Partial_End<=MI->Config.File_Size?Partial_End:MI->Config.File_Size)-Partial_Begin, File_Name);
307
308 //Buffer
309 MI->Option(__T("File_Buffer_Size_Hint_Pointer"), Ztring::ToZtring((size_t)(&MI->Config.File_Buffer_Size_ToRead)));
310 MI->Config.File_Buffer_Repeat_IsSupported=true;
311
312 //Test the format with buffer
313 return Format_Test_PerParser_Continue(MI);
314 }
315
316 //---------------------------------------------------------------------------
Format_Test_PerParser_Continue(MediaInfo_Internal * MI)317 size_t Reader_File::Format_Test_PerParser_Continue (MediaInfo_Internal* MI)
318 {
319 if (MI == NULL)
320 return 0;
321
322 bool StopAfterFilled=MI->Config.File_StopAfterFilled_Get();
323 bool ShouldContinue=true;
324 if (MI->Info)
325 Status=MI->Info->Status;
326
327 //Previous data
328 if (MI->Config.File_Buffer_Repeat)
329 {
330 MI->Config.File_Buffer_Repeat=false;
331 #if MEDIAINFO_DEMUX
332 MI->Config.Demux_EventWasSent=false;
333 #endif //MEDIAINFO_DEMUX
334
335 Status=MI->Open_Buffer_Continue(MI->Config.File_Buffer, MI->Config.File_Buffer_Size);
336
337 #if MEDIAINFO_READTHREAD
338 if (ThreadInstance && !MI->Config.File_Buffer_Repeat)
339 {
340 CS.Enter();
341 Buffer_Begin+=MI->Config.File_Buffer_Size;
342 #ifdef WINDOWS
343 if (Buffer_Begin==Buffer_Max)
344 {
345 CS.Leave();
346 SetEvent(Condition_WaitingForMorePlace);
347 }
348 else
349 #endif //WINDOWS
350 CS.Leave();
351 }
352 #endif //MEDIAINFO_READTHREAD
353
354 #if MEDIAINFO_DEMUX
355 //Demux
356 if (MI->Config.Demux_EventWasSent)
357 return 2; //Must return immediately
358 #endif //MEDIAINFO_DEMUX
359
360 //Threading
361 if (MI->IsTerminating() || MI->Config.RequestTerminate)
362 return 1; //Termination is requested
363
364 if (Status[File__Analyze::IsFinished] || (StopAfterFilled && Status[File__Analyze::IsFilled]))
365 ShouldContinue=false;
366 }
367
368 #if MEDIAINFO_DEMUX
369 //PerPacket
370 if (ShouldContinue && MI->Config.Demux_EventWasSent)
371 {
372 MI->Config.Demux_EventWasSent=false;
373
374 Status=MI->Open_Buffer_Continue(NULL, 0);
375
376 //Demux
377 if (MI->Config.Demux_EventWasSent)
378 return 2; //Must return immediately
379
380 //Threading
381 if (MI->IsTerminating() || MI->Config.RequestTerminate)
382 return 1; //Termination is requested
383
384 if (Status[File__Analyze::IsFinished] || MI->Config.IsFinishing || (StopAfterFilled && Status[File__Analyze::IsFilled]))
385 ShouldContinue=false;
386 }
387 #endif //MEDIAINFO_DEMUX
388
389 if (ShouldContinue)
390 {
391 //Test the format with buffer
392 while (!(Status[File__Analyze::IsFinished] || (StopAfterFilled && Status[File__Analyze::IsFilled])))
393 {
394 //Seek (if needed)
395 if (MI->Open_Buffer_Continue_GoTo_Get()!=(int64u)-1)
396 {
397 #ifdef MEDIAINFO_DEBUG
398 std::cout<<std::hex<<Reader_File_Offset<<" - "<<Reader_File_Offset+Reader_File_BytesRead<<" : "<<std::dec<<Reader_File_BytesRead<<" bytes"<<std::endl;
399 Reader_File_Offset=MI->Open_Buffer_Continue_GoTo_Get();
400 Reader_File_BytesRead=0;
401 Reader_File_Count++;
402 #endif //MEDIAINFO_DEBUG
403
404 #if MEDIAINFO_READTHREAD
405 Destroy_Thread(MI);
406 if (Buffer_End2!=(size_t)-1)
407 Buffer_End2=0;
408 #endif //MEDIAINFO_READTHREAD
409
410 int64u GoTo=Partial_Begin+MI->Open_Buffer_Continue_GoTo_Get();
411 MI->Config.File_Current_Offset=0;
412 int64u Buffer_NoJump_Temp=Buffer_NoJump;
413 if (MI->Config.File_Names.size()>1)
414 {
415 size_t Pos;
416 #if MEDIAINFO_SEEK
417 if (MI->Config.File_GoTo_IsFrameOffset)
418 {
419 Pos=(size_t)MI->Open_Buffer_Continue_GoTo_Get(); //File_GoTo is the frame offset in that case
420 MI->Info->File_GoTo=(int64u)-1;
421 MI->Config.File_GoTo_IsFrameOffset=false;
422 GoTo=0;
423 }
424 else
425 #endif //MEDIAINFO_SEEK
426 {
427 for (Pos=0; Pos<MI->Config.File_Names.size(); Pos++)
428 {
429 if (Pos==MI->Config.File_Sizes.size())
430 MI->Config.File_Sizes.push_back(F.Size_Get());
431 else if (MI->Config.File_Sizes[Pos]==(int64u)-1)
432 MI->Config.File_Sizes[Pos]=F.Size_Get();
433
434 if (Pos>=MI->Config.File_Sizes.size() || MI->Config.File_Sizes[Pos]==(int64u)-1)
435 break;
436
437 if (GoTo<MI->Config.File_Sizes[Pos])
438 break;
439
440 GoTo-=MI->Config.File_Sizes[Pos];
441 MI->Config.File_Current_Offset+=MI->Config.File_Sizes[Pos];
442 }
443 if (Pos>=MI->Config.File_Sizes.size())
444 break;
445 }
446 if (Pos!=MI->Config.File_Names_Pos-1)
447 {
448 F.Close();
449 F.Open(MI->Config.File_Names[Pos]);
450 if (Pos>=MI->Config.File_Sizes.size())
451 {
452 MI->Config.File_Sizes.resize(Pos, (int64u)-1);
453 MI->Config.File_Sizes.push_back(F.Size_Get());
454 }
455 MI->Config.File_Names_Pos=Pos+1;
456 MI->Config.File_Current_Size=MI->Config.File_Current_Offset+F.Size_Get();
457 Buffer_NoJump_Temp=0;
458 }
459 }
460
461 if (GoTo>=F.Size_Get())
462 break; //Seek requested, but on a file bigger in theory than what is in the real file, we can't do this
463 if (!(GoTo>F.Position_Get() && GoTo<F.Position_Get()+Buffer_NoJump_Temp)) //No smal jumps
464 {
465 if (!F.GoTo(GoTo))
466 break; //File is not seekable
467
468 MI->Open_Buffer_Init((int64u)-1, MI->Config.File_Current_Offset+F.Position_Get()-Partial_Begin);
469 }
470 }
471
472 #if MEDIAINFO_READTHREAD
473 if (ThreadInstance==NULL && Buffer_End2!=(size_t)-1 && Buffer_End2>=16*1024*1024)
474 {
475 if (!MI->Config.File_IsGrowing && MI->Config.File_Names.size()==1)
476 {
477 delete[] MI->Config.File_Buffer; MI->Config.File_Buffer=NULL;
478 MI->Config.File_Buffer_Size_Max=0;
479 Buffer_Max=MI->Config.File_Buffer_Read_Size_Get();
480 Buffer=new int8u[Buffer_Max];
481 Buffer_Begin=0;
482 Buffer_End=0;
483 Buffer_End2=0;
484 IsLooping=false;
485 #ifdef WINDOWS
486 Condition_WaitingForMorePlace=CreateEvent(NULL, FALSE, FALSE, NULL);
487 Condition_WaitingForMoreData=CreateEvent(NULL, FALSE, FALSE, NULL);
488 #endif //WINDOWS
489 ThreadInstance=new Reader_File_Thread();
490 ThreadInstance->Base=this;
491 ThreadInstance->Run();
492 }
493 else
494 Buffer_End2=(size_t)-1;
495 }
496 #endif //MEDIAINFO_READTHREAD
497
498 //Handling of hints
499 if (MI->Config.File_Buffer_Size_ToRead==0)
500 break; //Problem while config
501 if (
502 #if MEDIAINFO_READTHREAD
503 ThreadInstance==NULL &&
504 #endif //MEDIAINFO_READTHREAD
505 MI->Config.File_Buffer_Size_ToRead>MI->Config.File_Buffer_Size_Max)
506 {
507 delete[] MI->Config.File_Buffer;
508 if (MI->Config.File_Buffer_Size_Max==0)
509 MI->Config.File_Buffer_Size_Max=1;
510 while (MI->Config.File_Buffer_Size_ToRead>MI->Config.File_Buffer_Size_Max)
511 MI->Config.File_Buffer_Size_Max*=2;
512 if (MI->Config.File_Buffer_Size_Max>=64*1024*1024)
513 {
514 MI->Config.File_Buffer_Size_Max=64*1024*1024; //limitation of the buffer in order to avoid to big memory usage
515 MI->Config.File_Buffer_Size_ToRead=MI->Config.File_Buffer_Size_Max;
516 }
517 MI->Config.File_Buffer=new int8u[MI->Config.File_Buffer_Size_Max];
518 }
519
520 //Testing multiple file per stream
521 if (
522 #if MEDIAINFO_READTHREAD
523 ThreadInstance==NULL &&
524 #endif //MEDIAINFO_READTHREAD
525 F.Position_Get()>=F.Size_Get())
526 {
527 #if MEDIAINFO_ADVANCED2
528 MI->Open_Buffer_SegmentChange();
529 #endif //MEDIAINFO_ADVANCED2
530 if (MI->Config.File_Names_Pos && MI->Config.File_Names_Pos<MI->Config.File_Names.size())
531 {
532 MI->Config.File_Current_Offset+=MI->Config.File_Names_Pos<=MI->Config.File_Sizes.size()?MI->Config.File_Sizes[MI->Config.File_Names_Pos-1]:F.Size_Get();
533 F.Close();
534 #if MEDIAINFO_EVENTS
535 MI->Config.Event_SubFile_Start(MI->Config.File_Names[MI->Config.File_Names_Pos]);
536 #endif //MEDIAINFO_EVENTS
537 F.Open(MI->Config.File_Names[MI->Config.File_Names_Pos]);
538 while (!F.Opened_Get())
539 {
540 #if MEDIAINFO_EVENTS
541 MI->Config.Event_SubFile_Missing_Absolute(MI->Config.File_Names[MI->Config.File_Names_Pos]);
542 #endif //MEDIAINFO_EVENTS
543 if (MI->Config.File_Names_Pos+1<MI->Config.File_Names.size())
544 {
545 MI->Config.File_Names_Pos++;
546 F.Open(MI->Config.File_Names[MI->Config.File_Names_Pos]);
547 }
548 else //break the otherwise infinite loop
549 {
550 break;
551 }
552 }
553 if (MI->Config.File_Names_Pos>=MI->Config.File_Sizes.size())
554 {
555 MI->Config.File_Sizes.resize(MI->Config.File_Names_Pos, 0);
556 MI->Config.File_Sizes.push_back(F.Size_Get());
557 }
558 MI->Config.File_Names_Pos++;
559 MI->Config.File_Current_Size+=F.Size_Get();
560 }
561 }
562
563 #if MEDIAINFO_READTHREAD
564 if (ThreadInstance)
565 {
566 CS.Enter();
567 #ifdef WINDOWS
568 if (Buffer_End2+Buffer_End-Buffer_Begin<Buffer_Max/8*7)
569 {
570 CS.Leave();
571 SetEvent(Condition_WaitingForMorePlace);
572 CS.Enter();
573 }
574 #endif //WINDOWS
575
576 for (;;)
577 {
578 MI->Config.File_Buffer_Size=Buffer_End-Buffer_Begin;
579
580 if (MI->Config.File_Buffer_Size)
581 break;
582
583 if (!ThreadInstance->IsExited())
584 {
585 CS.Leave();
586 #ifdef WINDOWS
587 WaitForSingleObject(Condition_WaitingForMoreData, INFINITE);
588 #else //WINDOWS
589 Sleep(0);
590 #endif //WINDOWS
591 CS.Enter();
592 }
593 else
594 {
595 if (IsLooping)
596 {
597 IsLooping=false;
598 Buffer_End=Buffer_End2;
599 Buffer_End2=0;
600 Buffer_Begin=0;
601 }
602
603 MI->Config.File_Buffer_Size=Buffer_End-Buffer_Begin;
604 break;
605 }
606 }
607 MI->Config.File_Buffer=Buffer+Buffer_Begin;
608 CS.Leave();
609 if (MI->Config.File_Buffer_Size>MI->Config.File_Buffer_Size_ToRead)
610 MI->Config.File_Buffer_Size=MI->Config.File_Buffer_Size_ToRead;
611 }
612 else
613 #endif //MEDIAINFO_READTHREAD
614 {
615 size_t SizeToRead=(F.Position_Get()+MI->Config.File_Buffer_Size_ToRead<(Partial_End<=MI->Config.File_Size?Partial_End:MI->Config.File_Size))?MI->Config.File_Buffer_Size_ToRead:((size_t)((Partial_End<=MI->Config.File_Size?Partial_End:MI->Config.File_Size)-F.Position_Get()));
616 if (MI->Config.File_Buffer_Size_Max>MI->Info->Buffer_Size)
617 {
618 size_t SizeToRead_Max=MI->Config.File_Buffer_Size_Max-MI->Info->Buffer_Size;
619 if (SizeToRead>SizeToRead_Max)
620 SizeToRead=SizeToRead_Max;
621 }
622 MI->Config.File_Buffer_Size=F.Read(MI->Config.File_Buffer, SizeToRead);
623 #if MEDIAINFO_READTHREAD
624 if (ThreadInstance==NULL && Buffer_End2!=(size_t)-1)
625 Buffer_End2+=MI->Config.File_Buffer_Size;
626 #endif //MEDIAINFO_READTHREAD
627 }
628
629 /* High CPU usage
630 #if MEDIAINFO_EVENTS
631 if (MI->Config.File_Buffer_Size)
632 {
633 struct MediaInfo_Event_Global_BytesRead_0 Event;
634 memset(&Event, 0xFF, sizeof(struct MediaInfo_Event_Generic));
635 Event.EventCode=MediaInfo_EventCode_Create(MediaInfo_Parser_None, MediaInfo_Event_Global_BytesRead, 0);
636 Event.EventSize=sizeof(struct MediaInfo_Event_Global_BytesRead_0);
637 Event.StreamIDs_Size=0;
638 Event.StreamOffset=F.Position_Get()-MI->Config.File_Buffer_Size;
639 Event.Content_Size=MI->Config.File_Buffer_Size;
640 Event.Content=MI->Config.File_Buffer;
641 MI->Config.Event_Send(NULL, (const int8u*)&Event, sizeof(MediaInfo_Event_Global_BytesRead_0));
642 }
643 #endif //MEDIAINFO_EVENTS
644 */
645
646 //Testing growing files
647 if (MI->Config.ParseSpeed>=1.0 && !MI->Config.File_IsGrowing && MI->Config.File_Current_Offset+F.Position_Get()>=MI->Config.File_Size)
648 {
649 if (MI->Config.File_TestContinuousFileNames_Get())
650 {
651 //int64u Growing_Temp=MI->Config.File_Names.size();
652 if (MI->Config.File_Names.size()>=24) // only if already a sequence of files
653 MI->TestContinuousFileNames();
654 /* TODO: fix about sequences of files
655 if (MI->Config.File_Names.size()!=Growing_Temp)
656 MI->Config.File_IsGrowing=true;
657 */
658 }
659 if (MI->Config.File_Names.size()==1)
660 {
661 int64u Growing_Temp=F.Size_Get();
662 if (MI->Config.File_Size!=Growing_Temp)
663 MI->Config.File_IsGrowing=true;
664 }
665 }
666 if (MI->Config.File_IsNotGrowingAnymore)
667 {
668 MI->Config.File_Current_Size=MI->Config.File_Size=F.Size_Get();
669 MI->Open_Buffer_Init(MI->Config.File_Size, F.Position_Get()-MI->Config.File_Buffer_Size);
670 MI->Config.File_IsGrowing=false;
671 }
672 if ((MI->Config.File_IsGrowing //Was previously detected as growing
673 || (!MI->Config.File_IsNotGrowingAnymore && MI->Config.File_GrowingFile_Force_Get())) //Forced test and container did not indicate it is not growing anymore
674 #if MEDIAINFO_READTHREAD
675 && (!ThreadInstance || (!IsLooping && Buffer_Begin+MI->Config.File_Buffer_Size>=Buffer_End)) //File buffer hit the end of buffer
676 #endif //MEDIAINFO_READTHREAD
677 && F.Opened_Get() //File must be still open
678 && MI->Config.File_Current_Offset+F.Position_Get()>=MI->Config.File_Size //File read hit the end of file
679 && MI->Config.File_Names.size()==1) //TODO: fix about sequences of files
680 {
681 #if MEDIAINFO_EVENTS
682 {
683 struct MediaInfo_Event_General_WaitForMoreData_Start_0 Event;
684 memset(&Event, 0xFF, sizeof(struct MediaInfo_Event_Generic));
685 Event.EventCode=MediaInfo_EventCode_Create(MediaInfo_Parser_None, MediaInfo_Event_General_WaitForMoreData_Start, 0);
686 Event.EventSize=sizeof(struct MediaInfo_Event_General_WaitForMoreData_Start_0);
687 Event.StreamIDs_Size=0;
688 Event.Duration_Max=(double)MI->Config.File_GrowingFile_Delay_Get();
689 MI->Config.Event_Send(NULL, (const int8u*)&Event, sizeof(MediaInfo_Event_General_WaitForMoreData_Start_0));
690 }
691 #endif //MEDIAINFO_EVENTS
692
693 for (; CountOfSeconds<(size_t)MI->Config.File_GrowingFile_Delay_Get(); CountOfSeconds++)
694 {
695 int64u LastFile_Size_Old=MI->Config.File_Sizes[MI->Config.File_Sizes.size()-1];
696 size_t Files_Count_Old=MI->Config.File_Names.size();
697 //MI->TestContinuousFileNames(); //TODO: fix about sequences of files, "MI->Config.File_Names.size()==1 && " was added "else if (MI->Config.File_TestContinuousFileNames_Get())" commented
698 int64u LastFile_Size_New=F.Size_Get();
699 size_t Files_Count_New=MI->Config.File_Names.size();
700 MI->Open_Buffer_CheckFileModifications();
701
702 if (LastFile_Size_New != LastFile_Size_Old || Files_Count_New != Files_Count_Old || MI->Config.File_IsNotGrowingAnymore)
703 {
704 #if MEDIAINFO_EVENTS
705 {
706 struct MediaInfo_Event_General_WaitForMoreData_End_0 Event;
707 memset(&Event, 0xFF, sizeof(struct MediaInfo_Event_Generic));
708 Event.EventCode=MediaInfo_EventCode_Create(MediaInfo_Parser_None, MediaInfo_Event_General_WaitForMoreData_End, 0);
709 Event.EventSize=sizeof(struct MediaInfo_Event_General_WaitForMoreData_End_0);
710 Event.StreamIDs_Size=0;
711 Event.Duration_Max=(double)MI->Config.File_GrowingFile_Delay_Get();
712 Event.Duration_Actual=(double)CountOfSeconds;
713 Event.Flags=0; //Countinuing
714 MI->Config.Event_Send(NULL, (const int8u*)&Event, sizeof(MediaInfo_Event_General_WaitForMoreData_End_0));
715 }
716 #endif //MEDIAINFO_EVENTS
717 CountOfSeconds=0;
718 MI->Config.File_Current_Size=MI->Config.File_Size=LastFile_Size_New; //TODO: check if it is not doable in Open_Buffer_Init() also when MI->Config.File_Names.size() > 1
719 if (!MI->Config.File_Sizes.empty())
720 MI->Config.File_Sizes[MI->Config.File_Sizes.size()-1]=LastFile_Size_New;
721 if (MI->Config.File_Names.size()==1) //if more than 1 file, file size config is already done in TestContinuousFileNames()
722 MI->Open_Buffer_Init(MI->Config.File_Size, MI->Config.File_Current_Offset+F.Position_Get()-MI->Config.File_Buffer_Size);
723 #if MEDIAINFO_READTHREAD
724 if (ThreadInstance)
725 ThreadInstance->RunAgain();
726 #endif //MEDIAINFO_READTHREAD
727 break;
728 }
729
730 #ifdef WINDOWS
731 Sleep(1000);
732 #endif //WINDOWS
733 }
734
735 if (CountOfSeconds>=(size_t)MI->Config.File_GrowingFile_Delay_Get())
736 {
737 #if MEDIAINFO_EVENTS
738 {
739 struct MediaInfo_Event_General_WaitForMoreData_End_0 Event;
740 memset(&Event, 0xFF, sizeof(struct MediaInfo_Event_Generic));
741 Event.EventCode=MediaInfo_EventCode_Create(MediaInfo_Parser_None, MediaInfo_Event_General_WaitForMoreData_End, 0);
742 Event.EventSize=sizeof(struct MediaInfo_Event_General_WaitForMoreData_End_0);
743 Event.StreamIDs_Size=0;
744 Event.Duration_Max=(double)MI->Config.File_GrowingFile_Delay_Get();
745 Event.Duration_Actual=(double)CountOfSeconds;
746 Event.Flags=1; //Giving up
747 MI->Config.Event_Send(NULL, (const int8u*)&Event, sizeof(MediaInfo_Event_General_WaitForMoreData_End_0));
748 }
749 #endif //MEDIAINFO_EVENTS
750
751 MI->Config.File_IsGrowing=false;
752 }
753 }
754
755 if (!MI->Config.File_Buffer_Size
756 && (MI->Config.File_Current_Offset + F.Position_Get()>=MI->Config.File_Size
757 || (MI->Config.File_Size==(int64u)-1 && MI->Config.File_Names_Pos>=MI->Config.File_Names.size() && F.Position_Get()>=F.Size_Get())))
758 break; //Finished, and no other data
759
760 #ifdef MEDIAINFO_DEBUG
761 Reader_File_BytesRead_Total+=MI->Config.File_Buffer_Size;
762 Reader_File_BytesRead+=MI->Config.File_Buffer_Size;
763 #endif //MEDIAINFO_DEBUG
764
765 //Parser
766 Status=MI->Open_Buffer_Continue(MI->Config.File_Buffer, MI->Config.File_Buffer_Size);
767
768 #if MEDIAINFO_READTHREAD
769 if (ThreadInstance && !MI->Config.File_Buffer_Repeat)
770 {
771 CS.Enter();
772 Buffer_Begin+=MI->Config.File_Buffer_Size;
773 #ifdef WINDOWS
774 if (Buffer_Begin==Buffer_Max)
775 {
776 CS.Leave();
777 SetEvent(Condition_WaitingForMorePlace);
778 }
779 else
780 #endif //WINDOWS
781 CS.Leave();
782 }
783 #endif //MEDIAINFO_READTHREAD
784
785 if (!MI->Config.File_IsGrowing && MI->Config.File_Buffer_Size==0)
786 {
787 #if MEDIAINFO_EVENTS
788 MediaInfoLib::Config.Log_Send(0xC0, 0xFF, 0xF0F00101, "File read error");
789 #endif //MEDIAINFO_EVENTS
790 break;
791 }
792
793 #if MEDIAINFO_DEMUX
794 if (MI->Config.Demux_EventWasSent)
795 return 2; //Must return immediately
796 #endif //MEDIAINFO_DEMUX
797
798 //Threading
799 if (MI->IsTerminating() || MI->Config.RequestTerminate)
800 break; //Termination is requested
801 }
802 }
803
804 //Deleting buffer
805 #if MEDIAINFO_READTHREAD
806 if (ThreadInstance)
807 {
808 Destroy_Thread(MI);
809 }
810 else
811 #endif //MEDIAINFO_READTHREAD
812 {
813 delete[] MI->Config.File_Buffer; MI->Config.File_Buffer=NULL;
814 MI->Config.File_Buffer_Size_Max=0;
815 }
816
817 #ifdef MEDIAINFO_DEBUG
818 std::cout<<std::hex<<Reader_File_Offset<<" - "<<Reader_File_Offset+Reader_File_BytesRead<<" : "<<std::dec<<Reader_File_BytesRead<<" bytes"<<std::endl;
819 std::cout<<"Total: "<<std::dec<<Reader_File_BytesRead_Total<<" bytes in "<<Reader_File_Count<<" blocks"<<std::endl;
820 #endif //MEDIAINFO_DEBUG
821
822 if (!MI->Config.File_KeepInfo_Get())
823 {
824 //File
825 F.Close();
826 }
827
828 //Is this file detected?
829 if (!Status[File__Analyze::IsAccepted])
830 return 0;
831
832 MI->Open_Buffer_Finalize();
833
834 #if MEDIAINFO_DEMUX
835 if (MI->Config.Demux_EventWasSent)
836 return 2; //Must return immediately
837 #endif //MEDIAINFO_DEMUX
838
839 return 1;
840 }
841
842 //---------------------------------------------------------------------------
843 #if MEDIAINFO_SEEK
Format_Test_PerParser_Seek(MediaInfo_Internal * MI,size_t Method,int64u Value,int64u ID)844 size_t Reader_File::Format_Test_PerParser_Seek (MediaInfo_Internal* MI, size_t Method, int64u Value, int64u ID)
845 {
846 size_t ToReturn=MI->Open_Buffer_Seek(Method, Value, ID);
847
848 if (ToReturn==0 || ToReturn==1)
849 {
850 //Reset
851 Status=0;
852 }
853
854 return ToReturn;
855 }
856 #endif //MEDIAINFO_SEEK
857
858 } //NameSpace
859
860 #endif //MEDIAINFO_FILE_YES
861