1 /* Copyright (c) MediaArea.net SARL. All Rights Reserved.
2 *
3 * Use of this source code is governed by a BSD-style license that can
4 * be found in the License.html file in the root of the source tree.
5 */
6
7 //---------------------------------------------------------------------------
8 // Pre-compilation
9 #include "MediaInfo/PreComp.h"
10 #ifdef __BORLANDC__
11 #pragma hdrstop
12 #endif
13 //---------------------------------------------------------------------------
14
15 //---------------------------------------------------------------------------
16 #include "MediaInfo/Setup.h"
17 //---------------------------------------------------------------------------
18
19 //---------------------------------------------------------------------------
20 #if defined(MEDIAINFO_MPEGTS_YES)
21 //---------------------------------------------------------------------------
22
23 //---------------------------------------------------------------------------
24 #include "MediaInfo/Multiple/File_MpegTs.h"
25 #include "MediaInfo/Multiple/File_MpegPs.h"
26 #include "MediaInfo/Multiple/File_Mpeg_Descriptors.h"
27 #include "MediaInfo/MediaInfo_Config_MediaInfo.h"
28 #include "MediaInfo/MediaInfo.h"
29 #include "MediaInfo/MediaInfo_Internal.h"
30 #if defined(MEDIAINFO_REFERENCES_YES)
31 #include "ZenLib/File.h"
32 #endif //defined(MEDIAINFO_REFERENCES_YES)
33 #include <memory>
34 #include <algorithm>
35 #if MEDIAINFO_EVENTS
36 #include "MediaInfo/MediaInfo_Config_MediaInfo.h"
37 #include "MediaInfo/MediaInfo_Events_Internal.h"
38 #include "MediaInfo/MediaInfo_Config_PerPackage.h"
39 #endif //MEDIAINFO_EVENTS
40 #if MEDIAINFO_IBIUSAGE && MEDIAINFO_SEEK
41 #include "MediaInfo/Multiple/File_Ibi.h"
42 #endif //MEDIAINFO_IBIUSAGE && MEDIAINFO_SEEK
43 using namespace std;
44 //---------------------------------------------------------------------------
45
46 namespace MediaInfoLib
47 {
48
49 //***************************************************************************
50 // Constants
51 //***************************************************************************
52
53 namespace Elements
54 {
55 const int32u HDMV=0x48444D56; //BluRay
56 }
57
58
59 #if !MEDIAINFO_ADVANCED
60 const float64 Config_VbrDetection_Delta=0;
61 const int64u Config_VbrDetection_Occurences=4;
62 #endif // MEDIAINFO_ADVANCED
63
Scte128_tag(int8u tag)64 static const char* Scte128_tag (int8u tag)
65 {
66 switch (tag)
67 {
68 case 0x00: return "Forbidden";
69 case 0x01: return "Used by DVB";
70 case 0x02: return "AU_Information";
71 case 0xDF: return "Registered";
72 case 0xFF: return "Reserved";
73 default : return tag<0xE0?"Reserved":"User private";
74 }
75 }
76 //***************************************************************************
77 // Depends of configuration
78 //***************************************************************************
79
80 #if !defined(MEDIAINFO_BDAV_YES)
81 const size_t BDAV_Size=0;
82 #endif
83 #if !defined(MEDIAINFO_TSP_YES)
84 const size_t TSP_Size=0;
85 #endif
86 #if !defined(MEDIAINFO_BDAV_YES) && !defined(MEDIAINFO_TSP_YES)
87 const size_t TS_Size=188;
88 #endif
89
90 //***************************************************************************
91 // Info
92 //***************************************************************************
93
94 //---------------------------------------------------------------------------
95 //From Mpeg_Psi
96 extern const char* Mpeg_Descriptors_registration_format_identifier_Format(int32u format_identifier);
97 extern stream_t Mpeg_Descriptors_registration_format_identifier_StreamKind(int32u format_identifier);
98
99 extern const char* Mpeg_Psi_stream_type_Format(int8u stream_type, int32u format_identifier);
100 extern const char* Mpeg_Psi_stream_type_Codec(int8u stream_type, int32u format_identifier);
101 extern stream_t Mpeg_Psi_stream_type_StreamKind(int32u stream_type, int32u format_identifier);
102 extern const char* Mpeg_Psi_stream_type_Info(int8u stream_type, int32u format_identifier);
103
104 extern const char* Mpeg_Psi_table_id(int8u table_id);
105 extern const char* Mpeg_Descriptors_stream_Format(int8u descriptor_tag, int32u format_identifier);
106 extern const char* Mpeg_Descriptors_stream_Codec(int8u descriptor_tag, int32u format_identifier);
107 extern stream_t Mpeg_Descriptors_stream_Kind(int8u descriptor_tag, int32u format_identifier);
108
109 extern const char* Mpeg_Descriptors_CA_system_ID(int16u CA_system_ID);
110
111 //---------------------------------------------------------------------------
112 //DTS Neural (ETSI EN 300 468 v1.14+)
113 const size_t MpegTs_DtsNeural_2_Count=9;
114 const size_t MpegTs_DtsNeural_6_Count=4;
115
116 static const int8u MpegTs_DtsNeural_Channels_2[MpegTs_DtsNeural_2_Count]=
117 {
118 0,
119 3,
120 4,
121 5,
122 6,
123 7,
124 8,
125 6,
126 7,
127 };
128
129 static const int8u MpegTs_DtsNeural_Channels_6[MpegTs_DtsNeural_6_Count]=
130 {
131 0,
132 6,
133 7,
134 8,
135 };
136
MpegTs_DtsNeural_Channels(int8u Channels,int8u config_id)137 static const int8u MpegTs_DtsNeural_Channels(int8u Channels, int8u config_id)
138 {
139 if (config_id==0)
140 return 0;
141
142 switch (Channels)
143 {
144 case 2 :
145 if (config_id>=MpegTs_DtsNeural_2_Count)
146 return 0;
147 return MpegTs_DtsNeural_Channels_2[config_id];
148 case 6 :
149 if (config_id>=MpegTs_DtsNeural_6_Count)
150 return 0;
151 return MpegTs_DtsNeural_Channels_6[config_id];
152 default: return 0;
153 }
154 }
155
156 static const char* MpegTs_DtsNeural_ChannelPositions_2[MpegTs_DtsNeural_2_Count]=
157 {
158 "",
159 "Front: L R, LFE",
160 "Front: L C R, LFE",
161 "Front: L R, Side: L R, LFE",
162 "Front: L C R, Side: L R, LFE",
163 "Front: L C R, Side: L R, Back: C, LFE",
164 "Front: L C R, Side: L R, Back: L R, LFE",
165 "Front: L R, Side: L R, Back: C, LFE",
166 "Front: L R, Side: L R, Back: L R, LFE",
167 };
168
169 static const char* MpegTs_DtsNeural_ChannelPositions_6[MpegTs_DtsNeural_6_Count]=
170 {
171 "",
172 "Front: L C R, Side: L R",
173 "Front: L C R, Side: L R, Back: C",
174 "Front: L C R, Side: L R, Back: L R",
175 };
176
MpegTs_DtsNeural_ChannelPositions(int8u Channels,int8u config_id)177 static const char* MpegTs_DtsNeural_ChannelPositions(int8u Channels, int8u config_id)
178 {
179 if (config_id==0)
180 return "";
181
182 switch (Channels)
183 {
184 case 2 :
185 if (config_id>=MpegTs_DtsNeural_2_Count)
186 return "";
187 return MpegTs_DtsNeural_ChannelPositions_2[config_id];
188 case 6 :
189 if (config_id>=MpegTs_DtsNeural_6_Count)
190 return "";
191 return MpegTs_DtsNeural_ChannelPositions_6[config_id];
192 default: return "";
193 }
194 }
195
196 static const char* MpegTs_DtsNeural_ChannelPositions2_2[MpegTs_DtsNeural_2_Count]=
197 {
198 "",
199 "2/0/0.1",
200 "3/0/0.1",
201 "2/2/0.1",
202 "3/2/0.1",
203 "3/2/1.1",
204 "3/2/2.1",
205 "2/2/1.1",
206 "2/2/2.1",
207 };
208
209 static const char* MpegTs_DtsNeural_ChannelPositions2_6[MpegTs_DtsNeural_6_Count]=
210 {
211 "",
212 "3/2/0.1",
213 "3/2/1.1",
214 "3/2/2.1",
215 };
216
MpegTs_DtsNeural_ChannelPositions2(int8u Channels,int8u config_id)217 static const char* MpegTs_DtsNeural_ChannelPositions2(int8u Channels, int8u config_id)
218 {
219 if (config_id==0)
220 return "";
221
222 switch (Channels)
223 {
224 case 2 :
225 if (config_id>=MpegTs_DtsNeural_2_Count)
226 return "";
227 return MpegTs_DtsNeural_ChannelPositions2_2[config_id];
228 case 6 :
229 if (config_id>=MpegTs_DtsNeural_6_Count)
230 return "";
231 return MpegTs_DtsNeural_ChannelPositions2_6[config_id];
232 default: return "";
233 }
234 }
235
236 //---------------------------------------------------------------------------
Decimal_Hexa(int64u Number)237 static Ztring Decimal_Hexa(int64u Number)
238 {
239 return Get_Hex_ID(Number);
240 }
241
242 //***************************************************************************
243 // Constructor/Destructor
244 //***************************************************************************
245
246 //---------------------------------------------------------------------------
File_MpegTs()247 File_MpegTs::File_MpegTs()
248 #if MEDIAINFO_DUPLICATE
249 :File__Duplicate()
250 #endif //MEDIAINFO_DUPLICATE
251 {
252 //Configuration
253 ParserName="MpegTs";
254 #if MEDIAINFO_EVENTS
255 ParserIDs[0]=MediaInfo_Parser_MpegTs;
256 StreamIDs_Width[0]=4;
257 #endif //MEDIAINFO_EVENTS
258 #if MEDIAINFO_DEMUX
259 Demux_Level=4; //Intermediate
260 #endif //MEDIAINFO_DEMUX
261 MustSynchronize=true;
262 Buffer_TotalBytes_FirstSynched_Max=64*1024;
263 Buffer_TotalBytes_Fill_Max=(int64u)-1; //Disabling this feature for this format, this is done in the parser
264 Trusted_Multiplier=2;
265 #if MEDIAINFO_DEMUX
266 Demux_EventWasSent_Accept_Specific=true;
267 #endif //MEDIAINFO_DEMUX
268
269 //Internal config
270 #if defined(MEDIAINFO_BDAV_YES)
271 BDAV_Size=0; //No BDAV header
272 #endif
273 #if defined(MEDIAINFO_TSP_YES)
274 TSP_Size=0; //No TSP footer
275 #endif
276 #ifdef MEDIAINFO_ARIBSTDB24B37_YES
277 FromAribStdB24B37=false;
278 #endif
279 NoPatPmt=false;
280
281 //Data
282 MpegTs_JumpTo_Begin=MediaInfoLib::Config.MpegTs_MaximumOffset_Get();
283 MpegTs_JumpTo_End=MediaInfoLib::Config.MpegTs_MaximumOffset_Get()/4;
284 MpegTs_ScanUpTo=(int64u)-1;
285 Searching_TimeStamp_Start=true;
286 Complete_Stream=NULL;
287 ForceStreamDisplay=MediaInfoLib::Config.MpegTs_ForceStreamDisplay_Get();
288 ForceTextStreamDisplay=MediaInfoLib::Config.MpegTs_ForceTextStreamDisplay_Get();
289
290 #if MEDIAINFO_SEEK
291 Seek_Value=(int64u)-1;
292 Seek_ID=(int64u)-1;
293 InfiniteLoop_Detect=0;
294 Duration_Detected=false;
295 #endif //MEDIAINFO_SEEK
296 }
297
~File_MpegTs()298 File_MpegTs::~File_MpegTs ()
299 {
300 delete Complete_Stream; Complete_Stream=NULL;
301 }
302
303 //***************************************************************************
304 // Streams management
305 //***************************************************************************
306
307 //---------------------------------------------------------------------------
Streams_Accept()308 void File_MpegTs::Streams_Accept()
309 {
310 Fill(Stream_General, 0, General_Format, BDAV_Size?"BDAV":(TSP_Size?"MPEG-TS 188+16":"MPEG-TS"), Unlimited, true, true);
311 if (NoPatPmt)
312 Fill(Stream_General, 0, General_Format_Profile, "No PAT/PMT");
313
314 #if MEDIAINFO_DEMUX && MEDIAINFO_NEXTPACKET
315 if (Config->NextPacket_Get() && Config->Event_CallBackFunction_IsSet())
316 Config->Demux_EventWasSent=true;
317 #endif //MEDIAINFO_DEMUX && MEDIAINFO_NEXTPACKET
318
319 if (!IsSub && !Config->File_IsReferenced_Get())
320 {
321 #if MEDIAINFO_ADVANCED
322 // TODO: temporary disabling theses options for MPEG-TS, because it does not work as expected
323 if (Config->File_IgnoreSequenceFileSize_Get())
324 Config->File_IgnoreSequenceFileSize_Set(false);
325 if (Config->File_IgnoreSequenceFilesCount_Get())
326 Config->File_IgnoreSequenceFilesCount_Set(false);
327 #endif //MEDIAINFO_ADVANCED
328
329 TestContinuousFileNames(24, Ztring(), true);
330 }
331
332 //Temp
333 MpegTs_JumpTo_Begin=(File_Offset_FirstSynched==(int64u)-1?0:Buffer_TotalBytes_LastSynched)+MediaInfoLib::Config.MpegTs_MaximumOffset_Get();
334 MpegTs_JumpTo_End=MediaInfoLib::Config.MpegTs_MaximumOffset_Get()/4;
335 if (MpegTs_JumpTo_Begin==(int64u)-1 || MpegTs_JumpTo_Begin+MpegTs_JumpTo_End>=File_Size)
336 {
337 if (MpegTs_JumpTo_Begin+MpegTs_JumpTo_End>File_Size)
338 {
339 MpegTs_JumpTo_Begin=File_Size;
340 MpegTs_JumpTo_End=0;
341 }
342 else
343 MpegTs_JumpTo_Begin=File_Size-MpegTs_JumpTo_End;
344 }
345 }
346
347 //---------------------------------------------------------------------------
Streams_Fill()348 void File_MpegTs::Streams_Fill ()
349 {
350 Status[User_20]=true;
351 }
352
353 //---------------------------------------------------------------------------
Streams_Update()354 void File_MpegTs::Streams_Update()
355 {
356 if (Status[User_19])
357 Streams_Update_Programs();
358
359 if (Status[User_18])
360 Streams_Update_EPG();
361
362 #ifdef MEDIAINFO_MPEGTS_PCR_YES
363 if (Status[User_16])
364 Streams_Update_Duration_Update();
365 #endif //MEDIAINFO_MPEGTS_PCR_YES
366
367 if (Status[User_17])
368 Streams_Update_Duration_End();
369
370 if (File_Name.empty() && Config->ParseSpeed>=1.0)
371 Fill(Stream_General, 0, General_FileSize, (File_Offset+Buffer_Offset!=File_Size)?Buffer_TotalBytes:File_Size, 10, true);
372 }
373
374 //---------------------------------------------------------------------------
Streams_Update_Programs()375 void File_MpegTs::Streams_Update_Programs()
376 {
377 //Per stream
378 bool PerStream_AlwaysParse=ForceStreamDisplay;
379 if (!PerStream_AlwaysParse)
380 {
381 size_t Programs_Size=Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs.size();
382 PerStream_AlwaysParse=true;
383 if (Programs_Size<=2)
384 {
385 //Testing if it is a Blu-ray
386 for (complete_stream::transport_stream::programs::iterator Program=Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs.begin(); Program!=Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs.end(); ++Program)
387 if (Program->first!=0x0000 && Program->second.registration_format_identifier!=Elements::HDMV)
388 {
389 PerStream_AlwaysParse=false;
390 break;
391 }
392 }
393 }
394 for (std::set<int16u>::iterator StreamID=Complete_Stream->PES_PIDs.begin(); StreamID!=Complete_Stream->PES_PIDs.end(); ++StreamID)
395 if (PerStream_AlwaysParse || Complete_Stream->Streams[*StreamID]->IsUpdated_IsRegistered || Complete_Stream->Streams[*StreamID]->IsUpdated_Info)
396 {
397 Streams_Update_Programs_PerStream(*StreamID);
398 Complete_Stream->Streams[*StreamID]->IsUpdated_IsRegistered=false;
399 Complete_Stream->Streams[*StreamID]->IsUpdated_Info=false;
400 }
401
402 //Fill General
403 if (Complete_Stream->transport_stream_id_IsValid)
404 {
405 Fill(Stream_General, 0, General_ID, Complete_Stream->transport_stream_id, 10, true);
406 Fill(Stream_General, 0, General_ID_String, Decimal_Hexa(Complete_Stream->transport_stream_id), true);
407 }
408 if (!Complete_Stream->network_name.empty())
409 {
410 Fill(Stream_General, 0, General_NetworkName, Complete_Stream->network_name, true);
411 Complete_Stream->network_name.clear();
412 }
413 if (!Complete_Stream->original_network_name.empty())
414 {
415 Fill(Stream_General, 0, General_OriginalNetworkName, Complete_Stream->original_network_name, true);
416 Complete_Stream->original_network_name.clear();
417 }
418 Ztring Countries;
419 Ztring TimeZones;
420 for (std::map<Ztring, Ztring>::iterator TimeZone=Complete_Stream->TimeZones.begin(); TimeZone!=Complete_Stream->TimeZones.end(); ++TimeZone)
421 {
422 Countries+=TimeZone->first+__T(" / ");
423 TimeZones+=TimeZone->second+__T(" / ");
424 }
425 if (!Countries.empty())
426 {
427 Countries.resize(Countries.size()-3);
428 Fill(Stream_General, 0, General_Country, Countries, true);
429 Complete_Stream->TimeZones.clear();
430 }
431 if (!TimeZones.empty())
432 {
433 TimeZones.resize(TimeZones.size()-3);
434 Fill(Stream_General, 0, General_TimeZone, TimeZones, true);
435 Complete_Stream->TimeZones.clear();
436 }
437 if (!Complete_Stream->Duration_Start.empty())
438 {
439 Fill(Stream_General, 0, General_Duration_Start, Complete_Stream->Duration_Start, true);
440 Complete_Stream->Duration_Start.clear();
441 }
442 complete_stream::transport_streams::iterator Transport_Stream=Complete_Stream->transport_stream_id_IsValid?Complete_Stream->Transport_Streams.find(Complete_Stream->transport_stream_id):Complete_Stream->Transport_Streams.end();
443 if (Transport_Stream!=Complete_Stream->Transport_Streams.end())
444 {
445 //TS info
446 for (std::map<std::string, ZenLib::Ztring>::iterator Info=Transport_Stream->second.Infos.begin(); Info!=Transport_Stream->second.Infos.end(); ++Info)
447 Fill(Stream_General, 0, Info->first.c_str(), Info->second, true);
448 Transport_Stream->second.Infos.clear();
449
450 //Per source (ATSC)
451 if (Transport_Stream->second.source_id_IsValid)
452 {
453 complete_stream::sources::iterator Source=Complete_Stream->Sources.find(Transport_Stream->second.source_id);
454 if (Source!=Complete_Stream->Sources.end())
455 {
456 if (!Source->second.texts.empty())
457 {
458 Ztring Texts;
459 for (std::map<int16u, Ztring>::iterator text=Source->second.texts.begin(); text!=Source->second.texts.end(); ++text)
460 Texts+=text->second+__T(" - ");
461 if (!Texts.empty())
462 Texts.resize(Texts.size()-3);
463 Fill(Stream_General, 0, General_ServiceProvider, Texts);
464 }
465 }
466 }
467
468 //Per program
469 for (complete_stream::transport_stream::programs::iterator Program=Transport_Stream->second.Programs.begin(); Program!=Transport_Stream->second.Programs.end(); ++Program)
470 {
471 if (Program->second.IsParsed)
472 {
473 // Special case: force text stream display if requested and if video stream is present
474 if (ForceTextStreamDisplay)
475 {
476 for (size_t Pos = 0; Pos < Program->second.elementary_PIDs.size(); Pos++)
477 {
478 int16u elementary_PID = Program->second.elementary_PIDs[Pos];
479 if (Complete_Stream->Streams[elementary_PID]->StreamKind == Stream_Video && Complete_Stream->Streams[elementary_PID]->IsRegistered)
480 {
481 // Video stream is present, finding and filling text streams
482 for (size_t Pos = 0; Pos < Program->second.elementary_PIDs.size(); Pos++)
483 {
484 int16u elementary_PID = Program->second.elementary_PIDs[Pos];
485 if (Complete_Stream->Streams[elementary_PID]->StreamKind_FromDescriptor == Stream_Text && !Complete_Stream->Streams[elementary_PID]->IsRegistered)
486 Streams_Update_Programs_PerStream(elementary_PID);
487 }
488 break;
489 }
490 }
491 }
492
493 //Per pid
494 Ztring Languages, Codecs, Formats, StreamKinds, StreamPoss, elementary_PIDs, elementary_PIDs_String, Delay, LawRating, Title;
495 for (size_t Pos=0; Pos<Program->second.elementary_PIDs.size(); Pos++)
496 {
497 int16u elementary_PID=Program->second.elementary_PIDs[Pos];
498 if (PerStream_AlwaysParse || Complete_Stream->Streams[elementary_PID]->IsRegistered)
499 {
500 #if defined(MEDIAINFO_TELETEXT_YES)
501 if (!Complete_Stream->Streams[elementary_PID]->Teletexts.empty())
502 {
503 for (std::map<int16u, teletext>::iterator Teletext=Complete_Stream->Streams[elementary_PID]->Teletexts.begin(); Teletext!=Complete_Stream->Streams[elementary_PID]->Teletexts.end(); ++Teletext)
504 {
505 Ztring Format;
506 Ztring Language;
507 if (Teletext->second.StreamKind!=Stream_Max)
508 {
509 StreamKinds+=Ztring::ToZtring(Teletext->second.StreamKind);
510 StreamPoss+=Ztring::ToZtring(Teletext->second.StreamPos);
511 Format=Retrieve(Teletext->second.StreamKind, Teletext->second.StreamPos, "Format");
512 Language=Retrieve(Teletext->second.StreamKind, Teletext->second.StreamPos, "Language");
513 }
514 Formats+=Format+__T(" / ");
515 Codecs+=Format+__T(" / ");
516 StreamKinds+=__T(" / ");
517 StreamPoss+=__T(" / ");
518 elementary_PIDs+=Ztring::ToZtring(elementary_PID)+__T('-')+Ztring::ToZtring(Teletext->first)+__T(" / ");
519 Languages+=Language+__T(" / ");
520 Ztring List_String=Decimal_Hexa(elementary_PID)+__T('-')+Ztring::ToZtring(Teletext->first);
521 List_String+=__T(" (");
522 List_String+=Format;
523 if (!Language.empty())
524 {
525 List_String+=__T(", ");
526 List_String+=Language;
527 }
528 List_String+=__T(")");
529 elementary_PIDs_String+=List_String+__T(" / ");
530 }
531 }
532 else
533 #endif //MEDIAINFO_TELETEXT_YES
534 {
535 Ztring Format=Retrieve(Complete_Stream->Streams[elementary_PID]->StreamKind, Complete_Stream->Streams[elementary_PID]->StreamPos, Fill_Parameter(Complete_Stream->Streams[elementary_PID]->StreamKind, Generic_Format));
536 if (Format.empty())
537 Format=Mpeg_Psi_stream_type_Format(Complete_Stream->Streams[elementary_PID]->stream_type, Program->second.registration_format_identifier);
538 if (Format.empty())
539 {
540 std::map<std::string, Ztring>::iterator Format_FromInfo=Complete_Stream->Streams[elementary_PID]->Infos.find("Format");
541 if (Format_FromInfo!=Complete_Stream->Streams[elementary_PID]->Infos.end())
542 Format=Format_FromInfo->second;
543 }
544 if (Format.empty())
545 Program->second.HasNotDisplayableStreams=true;
546 Formats+=Format+__T(" / ");
547 Codecs+=Retrieve(Complete_Stream->Streams[elementary_PID]->StreamKind, Complete_Stream->Streams[elementary_PID]->StreamPos, Fill_Parameter(Complete_Stream->Streams[elementary_PID]->StreamKind, Generic_Codec))+__T(" / ");
548 if (Complete_Stream->Streams[elementary_PID]->StreamKind!=Stream_Max)
549 {
550 StreamKinds+=Ztring::ToZtring(Complete_Stream->Streams[elementary_PID]->StreamKind);
551 StreamPoss+=Ztring::ToZtring(Complete_Stream->Streams[elementary_PID]->StreamPos);
552 }
553 StreamKinds+=__T(" / ");
554 StreamPoss+=__T(" / ");
555 elementary_PIDs+=Ztring::ToZtring(elementary_PID)+__T(" / ");
556 Ztring Language=Retrieve(Complete_Stream->Streams[elementary_PID]->StreamKind, Complete_Stream->Streams[elementary_PID]->StreamPos, "Language/String");
557 Languages+=Language+__T(" / ");
558 Ztring List_String=Decimal_Hexa(elementary_PID);
559 List_String+=__T(" (");
560 List_String+=Format;
561 if (!Language.empty())
562 {
563 List_String+=__T(", ");
564 List_String+=Language;
565 }
566 List_String+=__T(")");
567 elementary_PIDs_String+=List_String+__T(" / ");
568 }
569
570 if (Complete_Stream->Streams[elementary_PID]->IsPCR)
571 {
572 Delay=Ztring::ToZtring(((float64)Complete_Stream->Streams[elementary_PID]->TimeStamp_Start)/27000, 6);
573 }
574
575 //Law rating
576 if (Complete_Stream->Streams[elementary_PID] && Complete_Stream->Streams[elementary_PID]->Parser)
577 {
578 Ztring LawRating_Temp=Complete_Stream->Streams[elementary_PID]->Parser->Retrieve(Stream_General, 0, General_LawRating);
579 if (!LawRating_Temp.empty())
580 LawRating+=LawRating_Temp+__T(" / ");
581 Ztring Title_Temp=Complete_Stream->Streams[elementary_PID]->Parser->Retrieve(Stream_General, 0, General_Title);
582 if (!Title_Temp.empty())
583 Title+=Title_Temp+__T(" / ");
584 }
585 }
586 }
587
588 if (Program->second.Update_Needed_Info || Program->second.Update_Needed_IsRegistered || Program->second.Update_Needed_StreamCount || Program->second.Update_Needed_StreamPos)
589 {
590 if (!Transport_Stream->second.Programs.empty()
591 && (Transport_Stream->second.Programs.size()>1
592 || Transport_Stream->second.Programs.begin()->second.HasNotDisplayableStreams
593 || !Transport_Stream->second.Programs.begin()->second.Infos.empty()
594 || !Transport_Stream->second.Programs.begin()->second.DVB_EPG_Blocks.empty()
595 || (Transport_Stream->second.Programs.begin()->second.source_id_IsValid && Complete_Stream->Sources.find(Transport_Stream->second.Programs.begin()->second.source_id)!=Complete_Stream->Sources.end())
596 || Config->File_MpegTs_ForceMenu_Get()))
597 {
598 if (Program->second.StreamPos==(size_t)-1)
599 {
600 size_t StreamPos=(size_t)-1;
601 for (size_t program_number=0; program_number<Complete_Stream->program_number_Order.size(); program_number++)
602 if (Program->first<Complete_Stream->program_number_Order[program_number])
603 {
604 StreamPos=program_number;
605 for (size_t program_number2=program_number; program_number2<Complete_Stream->program_number_Order.size(); program_number2++)
606 Transport_Stream->second.Programs[Complete_Stream->program_number_Order[program_number2]].StreamPos++;
607 Complete_Stream->program_number_Order.insert(Complete_Stream->program_number_Order.begin()+program_number, Program->first);
608 break;
609 }
610 if (StreamPos==(size_t)-1)
611 {
612 Complete_Stream->program_number_Order.push_back(Program->first);
613 }
614
615 Stream_Prepare(Stream_Menu, StreamPos);
616 Program->second.StreamPos=StreamPos_Last;
617 }
618 else
619 StreamPos_Last=Program->second.StreamPos;
620 Fill(Stream_Menu, StreamPos_Last, Menu_ID, Program->second.pid, 10, true);
621 Fill(Stream_Menu, StreamPos_Last, Menu_ID_String, Decimal_Hexa(Program->second.pid), true);
622 Fill(Stream_Menu, StreamPos_Last, Menu_MenuID, Program->first, 10, true);
623 Fill(Stream_Menu, StreamPos_Last, Menu_MenuID_String, Decimal_Hexa(Program->first), true);
624 Clear(Stream_Menu, StreamPos_Last, General_StreamOrder);
625 for (size_t programs_List_Pos=0; programs_List_Pos<Transport_Stream->second.programs_List.size(); ++programs_List_Pos)
626 if (Transport_Stream->second.programs_List[programs_List_Pos]==Program->first)
627 Fill(Stream_Menu, StreamPos_Last, General_StreamOrder, programs_List_Pos);
628 for (std::map<std::string, ZenLib::Ztring>::iterator Info=Program->second.Infos.begin(); Info!=Program->second.Infos.end(); ++Info)
629 Fill(Stream_Menu, StreamPos_Last, Info->first.c_str(), Info->second, true);
630 Program->second.Infos.clear();
631 for (std::map<std::string, ZenLib::Ztring>::iterator Info=Program->second.ExtraInfos_Content.begin(); Info!=Program->second.ExtraInfos_Content.end(); ++Info)
632 Fill(Stream_Menu, StreamPos_Last, Info->first.c_str(), Info->second, true);
633 Program->second.ExtraInfos_Content.clear();
634 for (std::map<std::string, ZenLib::Ztring>::iterator Info=Program->second.ExtraInfos_Option.begin(); Info!=Program->second.ExtraInfos_Option.end(); ++Info)
635 Fill_SetOptions(Stream_Menu, StreamPos_Last, Info->first.c_str(), Info->second.To_UTF8().c_str());
636 Program->second.ExtraInfos_Option.clear();
637
638 if (!Formats.empty())
639 Formats.resize(Formats.size()-3);
640 Fill(Stream_Menu, StreamPos_Last, Menu_Format, Formats, true);
641 if (!Codecs.empty())
642 Codecs.resize(Codecs.size()-3);
643 Fill(Stream_Menu, StreamPos_Last, Menu_Codec, Codecs, true);
644 if (!StreamKinds.empty())
645 StreamKinds.resize(StreamKinds.size()-3);
646 Fill(Stream_Menu, StreamPos_Last, Menu_List_StreamKind, StreamKinds, true);
647 if (!elementary_PIDs_String.empty())
648 elementary_PIDs_String.resize(elementary_PIDs_String.size()-3);
649 Fill(Stream_Menu, StreamPos_Last, Menu_List_String, elementary_PIDs_String, true);
650 if (!elementary_PIDs.empty())
651 elementary_PIDs.resize(elementary_PIDs.size()-3);
652 Fill(Stream_Menu, StreamPos_Last, Menu_List, elementary_PIDs, true);
653 if (!StreamPoss.empty())
654 StreamPoss.resize(StreamPoss.size()-3);
655 Fill(Stream_Menu, StreamPos_Last, Menu_List_StreamPos, StreamPoss, true);
656 if (!Languages.empty())
657 Languages.resize(Languages.size()-3);
658 Fill(Stream_Menu, StreamPos_Last, Menu_Language, Languages, true);
659 if (!LawRating.empty())
660 LawRating.resize(LawRating.size()-3);
661 Fill(Stream_Menu, StreamPos_Last, "LawRating", LawRating, true);
662 if (StreamPos_Last)
663 Clear(Stream_General, 0, General_LawRating); //More than 1 menu, can not be in General part
664 if (!Title.empty())
665 Title.resize(Title.size()-3);
666 Fill(Stream_Menu, StreamPos_Last, "Title", Title, true);
667 if (StreamPos_Last)
668 Clear(Stream_General, 0, General_Title); //More than 1 menu, can not be in General part
669 }
670 }
671
672 //Delay
673 if (Program->second.Update_Needed_IsRegistered)
674 {
675 switch (Count_Get(Stream_Menu))
676 {
677 case 0 : Fill(Stream_General, 0, General_Delay, Delay, true); break;
678 default: Fill(Stream_Menu, StreamPos_Last, Menu_Delay, Delay, true); break;
679 }
680 Program->second.Update_Needed_IsRegistered=false;
681 }
682 if (Count_Get(Stream_Menu)==2)
683 Clear(Stream_General, 0, General_Delay); //Not valid, multiple menus
684 }
685 }
686 }
687
688 //Commercial name
689 if (Count_Get(Stream_Video)==1
690 && Count_Get(Stream_Audio)==1
691 && Retrieve(Stream_Video, 0, Video_Format)==__T("MPEG Video")
692 && Retrieve(Stream_Video, 0, Video_Format_Commercial_IfAny).find(__T("HDV"))==0
693 && Retrieve(Stream_Audio, 0, Audio_Format)==__T("MPEG Audio")
694 && Retrieve(Stream_Audio, 0, Audio_Format_Version)==__T("Version 1")
695 && Retrieve(Stream_Audio, 0, Audio_Format_Profile)==__T("Layer 2")
696 && Retrieve(Stream_Audio, 0, Audio_BitRate)==__T("384000"))
697 Fill(Stream_General, 0, General_Format_Commercial_IfAny, Retrieve(Stream_Video, 0, Video_Format_Commercial_IfAny));
698 }
699
700 //---------------------------------------------------------------------------
Streams_Update_Programs_PerStream(size_t StreamID)701 void File_MpegTs::Streams_Update_Programs_PerStream(size_t StreamID)
702 {
703 complete_stream::stream* Temp=Complete_Stream->Streams[StreamID];
704
705 //No direct handling of Sub streams;
706 if (Temp->stream_type==0x20 && Temp->SubStream_pid) //Stereoscopic is not alone
707 return;
708
709 if (Temp->Parser)
710 Temp->Parser->Open_Buffer_Update();
711
712 //Merging from a previous merge
713 size_t Counts[Stream_Max];
714 for (size_t StreamKind=Stream_General+1; StreamKind<Stream_Max; StreamKind++)
715 Counts[StreamKind]=Count_Get((stream_t)StreamKind);
716 if (Temp->StreamKind != Stream_Max && Temp->StreamPos != (size_t)-1 && Temp->Parser)
717 {
718 Merge(*Temp->Parser, Temp->StreamKind, 0, Temp->StreamPos);
719 StreamKind_Last=Temp->StreamKind;
720 StreamPos_Last=Temp->StreamPos;
721 }
722 else
723 {
724 //By the parser
725 StreamKind_Last=Stream_Max;
726 if (Temp->Parser && Temp->Parser->Status[IsAccepted])
727 {
728 if (Temp->SubStream_pid!=0x0000) //With a substream
729 Fill(Complete_Stream->Streams[Temp->SubStream_pid]->Parser);
730 if (Temp->Parser->Count_Get(Stream_Video) && Temp->Parser->Count_Get(Stream_Text))
731 {
732 //Special case: Video and Text are together
733 Stream_Prepare(Stream_Video);
734 Merge(*Temp->Parser, Stream_Video, 0, StreamPos_Last);
735 }
736 else
737 Merge(*Temp->Parser);
738
739 //More from the FMC parser
740 if (Temp->FMC_ES_ID_IsValid)
741 {
742 complete_stream::transport_stream::iod_ess::iterator IOD_ES=Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].IOD_ESs.find(Temp->FMC_ES_ID);
743 if (IOD_ES!=Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].IOD_ESs.end() && IOD_ES->second.Parser)
744 {
745 Finish(IOD_ES->second.Parser);
746 Merge(*IOD_ES->second.Parser, StreamKind_Last, StreamPos_Last, 0);
747 }
748 }
749
750 //LATM
751 complete_stream::transport_stream::iod_ess::iterator IOD_ES=Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].IOD_ESs.find(Complete_Stream->Streams[StreamID]->FMC_ES_ID);
752 #ifdef MEDIAINFO_MPEG4_YES
753 if (IOD_ES!=Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].IOD_ESs.end() && IOD_ES->second.SLConfig && Retrieve(Stream_Audio, StreamPos_Last, Audio_MuxingMode).empty())
754 Fill(Stream_Audio, StreamPos_Last, Audio_MuxingMode, "SL");
755 #endif
756 if (Complete_Stream->Streams[StreamID]->stream_type==0x11 && Retrieve(Stream_Audio, StreamPos_Last, Audio_MuxingMode).empty())
757 Fill(Stream_Audio, StreamPos_Last, Audio_MuxingMode, "LATM");
758 }
759
760 //By the descriptors
761 if (StreamKind_Last==Stream_Max && Complete_Stream->transport_stream_id_IsValid && !Temp->program_numbers.empty() && !Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs.empty())
762 {
763 int32u format_identifier=Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs[Temp->program_numbers[0]].registration_format_identifier;
764 if (Temp->IsRegistered
765 && Mpeg_Descriptors_registration_format_identifier_StreamKind(format_identifier)!=Stream_Max)
766 {
767 StreamKind_Last=Mpeg_Descriptors_registration_format_identifier_StreamKind(format_identifier);
768 Stream_Prepare(StreamKind_Last);
769 Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_Format), Mpeg_Descriptors_registration_format_identifier_Format(format_identifier));
770 Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_Codec), Mpeg_Descriptors_registration_format_identifier_Format(format_identifier));
771 }
772 }
773
774 //By registration_format_identifier
775 if (StreamKind_Last==Stream_Max && Temp->registration_format_identifier && Temp->IsRegistered && Mpeg_Descriptors_registration_format_identifier_StreamKind(Temp->registration_format_identifier)!=Stream_Max)
776 {
777 StreamKind_Last=Mpeg_Descriptors_registration_format_identifier_StreamKind(Temp->registration_format_identifier);
778 Stream_Prepare(StreamKind_Last);
779 Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_Format), Mpeg_Descriptors_registration_format_identifier_Format(Temp->registration_format_identifier));
780 Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_Codec), Mpeg_Descriptors_registration_format_identifier_Format(Temp->registration_format_identifier));
781 }
782
783 //By the stream_type
784 if (StreamKind_Last==Stream_Max && Complete_Stream->transport_stream_id_IsValid && !Temp->program_numbers.empty() && !Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs.empty())
785 {
786 int32u format_identifier=Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs[Temp->program_numbers[0]].registration_format_identifier;
787 if (Mpeg_Psi_stream_type_StreamKind(Temp->stream_type, format_identifier)!=Stream_Max && (Temp->IsRegistered || ForceStreamDisplay || format_identifier==Elements::HDMV))
788 {
789 StreamKind_Last=Mpeg_Psi_stream_type_StreamKind(Temp->stream_type, format_identifier);
790 if (StreamKind_Last==Stream_General && Temp->Parser) //Only information, no streams
791 {
792 Merge (*Temp->Parser, Stream_General, 0, 0);
793 StreamKind_Last=Stream_Max;
794 }
795 Stream_Prepare(StreamKind_Last);
796 Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_Format), Mpeg_Psi_stream_type_Format(Temp->stream_type, format_identifier));
797 Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_Codec), Mpeg_Psi_stream_type_Codec(Temp->stream_type, format_identifier));
798 }
799 }
800
801 //By the StreamKind
802 if (StreamKind_Last==Stream_Max && Temp->StreamKind_FromDescriptor!=Stream_Max && (Temp->IsRegistered || ForceStreamDisplay || (ForceTextStreamDisplay && Temp->StreamKind_FromDescriptor==Stream_Text) || (!Temp->program_numbers.empty() && Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs[Temp->program_numbers[0]].registration_format_identifier==Elements::HDMV)))
803 {
804 Stream_Prepare(Temp->StreamKind_FromDescriptor);
805 }
806 }
807
808 //More info
809 if (StreamKind_Last!=Stream_Max)
810 {
811 for (size_t StreamKind=Stream_General+1; StreamKind<Stream_Max; StreamKind++)
812 {
813 size_t Counts_Now=Count_Get((stream_t)StreamKind);
814 for (size_t StreamPos=Counts[StreamKind]; StreamPos<Counts_Now; StreamPos++)
815 {
816 Temp->StreamKind=StreamKind_Last;
817 Temp->StreamPos=StreamPos;
818
819 //Encryption
820 if (Temp->CA_system_ID)
821 Fill((stream_t)StreamKind, StreamPos, "Encryption", Mpeg_Descriptors_CA_system_ID(Temp->CA_system_ID));
822 else if (Temp->Scrambled_Count>16)
823 Fill((stream_t)StreamKind, StreamPos, "Encryption", "Encrypted");
824
825 //TS info
826 for (std::map<std::string, ZenLib::Ztring>::iterator Info=Temp->Infos.begin(); Info!=Temp->Infos.end(); ++Info)
827 {
828 //Special case: Preselections
829 string First=Info->first;
830 if ((stream_t)StreamKind==Stream_Audio && First.rfind("Preselection", 12)==0 && Retrieve_Const((stream_t)Stream_Audio, StreamPos, Audio_Format)==__T("AC-4"))
831 {
832 const ZtringListList& More=(*Stream_More)[Stream_Audio][StreamPos];
833 size_t Count=More.size();
834 map<int32u, int32u> ID_Mappings;
835 int32u First_ID=Ztring().From_UTF8(First.substr(12)).To_int32u();
836 First="Presentation"+Info->first.substr(12);
837 size_t First_Space=First.find(' ');
838 if (First_Space!=string::npos)
839 {
840 string First_AfterSpace=First.substr(First_Space+1);
841 if (First_AfterSpace=="ID")
842 First=First.substr(0, First_Space+1)+"PresentationID";
843 }
844 else
845 {
846 //Look for ID in descriptor
847 std::map<std::string, ZenLib::Ztring>::iterator Info_ID=Temp->Infos.find(Info->first+" ID");
848 if (Info_ID!=Temp->Infos.end())
849 ID_Mappings[First_ID]=Info_ID->second.To_int32u();
850 }
851
852 //
853 map<int32u, int32u>::iterator ID_Mapping=ID_Mappings.find(First_ID);
854 if (ID_Mapping!=ID_Mappings.end())
855 First_ID=ID_Mapping->second;
856
857 //Look for PresentationID in descriptor
858 size_t Pos=0;
859 bool Pos_FoundInID=false;
860 for (;;)
861 {
862 Ztring LookingFor=__T("Presentation")+Ztring::ToZtring(Pos);
863 bool PreselectionIsFound=false;
864 for (size_t Parameter=0; Parameter<Count; Parameter++)
865 if (Info_Name<More[Parameter].size() && More[Parameter][Info_Name]==LookingFor)
866 {
867 PreselectionIsFound=true;
868 if (Parameter+3<Count && Info_Text<More[Parameter+3].size() && More[Parameter+3][Info_Name]==LookingFor+__T(" PresentationID") && More[Parameter+3][Info_Text]==Ztring::ToZtring(First_ID))
869 {
870 if (First_Space!=string::npos)
871 First=First.substr(First_Space);
872 else
873 First.clear();
874 First.insert(0, LookingFor.To_UTF8());
875 PreselectionIsFound=false;
876 break;
877 }
878 }
879 if (!PreselectionIsFound)
880 break;
881 Pos++;
882 }
883 }
884
885 if (Retrieve((stream_t)StreamKind, StreamPos, First.c_str()).empty())
886 {
887 //Special case : DTS Neural
888 if ((stream_t)StreamKind==Stream_Audio && First=="Matrix_ChannelPositions" && Info->second.find(__T("DTS Neural Audio "))==0)
889 {
890 int8u Channels=Retrieve(Stream_Audio, StreamPos, Audio_Channel_s_).To_int8u();
891 if (Channels)
892 {
893 int8u config_id=Ztring(Info->second.substr(17, string::npos)).To_int8u();
894 int8u Matrix_Channels=MpegTs_DtsNeural_Channels(Channels, config_id);
895 if (Matrix_Channels)
896 {
897 Fill(Stream_Audio, StreamPos, Audio_Matrix_Channel_s_, Matrix_Channels);
898 Fill(Stream_Audio, StreamPos, Audio_Matrix_ChannelPositions, MpegTs_DtsNeural_ChannelPositions(Channels, config_id));
899 Fill(Stream_Audio, StreamPos, Audio_ChannelPositions_String2, MpegTs_DtsNeural_ChannelPositions2(Channels, config_id));
900 }
901 }
902
903 }
904 else
905 {
906 Fill((stream_t)StreamKind, StreamPos, First.c_str(), Info->second, true);
907 std::map<std::string, ZenLib::Ztring>::iterator Option=Temp->Infos_Option.find(First.c_str());
908 if (Option!=Temp->Infos_Option.end())
909 Fill_SetOptions((stream_t)StreamKind, StreamPos, First.c_str(), Option->second.To_UTF8().c_str());
910 }
911 }
912 else if (Info->first=="CodecID")
913 {
914 Fill((stream_t)StreamKind, StreamPos, Info->first.c_str(), Info->second+__T('-')+Retrieve((stream_t)StreamKind, StreamPos, Info->first.c_str()), true);
915 }
916 else if (Info->first.find("HDR_Format")==0)
917 {
918 Fill((stream_t)StreamKind, StreamPos, Info->first.c_str(), Info->second+__T(" / ")+Retrieve((stream_t)StreamKind, StreamPos, Info->first.c_str()), true);
919 }
920 }
921
922 //Common
923 if (Temp->SubStream_pid!=0x0000) //Wit a substream
924 {
925 Ztring Format_Profile=Retrieve(Stream_Video, StreamPos, Video_Format_Profile);
926 Fill(Stream_Video, StreamPos, Video_ID, Ztring::ToZtring(Temp->SubStream_pid)+__T(" / ")+Ztring::ToZtring(StreamID), true);
927 Fill(Stream_Video, StreamPos, Video_ID_String, Decimal_Hexa(Temp->SubStream_pid)+__T(" / ")+Decimal_Hexa(StreamID), true);
928 if (!Format_Profile.empty() && Complete_Stream->Streams[Temp->SubStream_pid] && Complete_Stream->Streams[Temp->SubStream_pid]->Parser)
929 Fill(Stream_Video, StreamPos, Video_Format_Profile, Complete_Stream->Streams[Temp->SubStream_pid]->Parser->Retrieve(Stream_Video, 0, Video_Format_Profile)+__T(" / ")+Format_Profile, true);
930 }
931 else if (Retrieve((stream_t)StreamKind, StreamPos, General_ID).find(__T('-'))!=string::npos)
932 {
933 Ztring ID=Retrieve((stream_t)StreamKind, StreamPos, General_ID);
934 size_t ID_Pos=ID.find(__T('-'));
935 if (ID_Pos!=string::npos)
936 ID.erase(ID.begin(), ID.begin()+ID_Pos+1); //Removing the PS part
937 Ztring ID_String=Retrieve((stream_t)StreamKind, StreamPos, General_ID_String);
938 size_t ID_String_Pos=ID_String.find(__T('-'));
939 if (ID_String_Pos!=string::npos)
940 ID_String.erase(ID_String.begin(), ID_String.begin()+ID_String_Pos+1); //Removing the PS part
941 #ifdef MEDIAINFO_ARIBSTDB24B37_YES
942 if (FromAribStdB24B37)
943 {
944 Fill((stream_t)StreamKind, StreamPos, General_ID, ID, true);
945 Fill((stream_t)StreamKind, StreamPos, General_ID_String, ID_String, true);
946 }
947 else
948 #endif //MEDIAINFO_ARIBSTDB24B37_YES
949 {
950 Fill((stream_t)StreamKind, StreamPos, General_ID, Ztring::ToZtring(StreamID)+__T('-')+ID, true);
951 Fill((stream_t)StreamKind, StreamPos, General_ID_String, Decimal_Hexa(StreamID)+__T('-')+ID_String, true);
952 }
953 }
954 else
955 {
956 Fill((stream_t)StreamKind, StreamPos, General_ID, StreamID, 10, true);
957 Fill((stream_t)StreamKind, StreamPos, General_ID_String, Decimal_Hexa(StreamID), true);
958 }
959 for (size_t Pos=0; Pos<Temp->program_numbers.size(); Pos++)
960 {
961 Fill((stream_t)StreamKind, StreamPos, General_MenuID, Temp->program_numbers[Pos], 10, Pos==0);
962 Fill((stream_t)StreamKind, StreamPos, General_MenuID_String, Decimal_Hexa(Temp->program_numbers[Pos]), Pos==0);
963 }
964
965 //StreamOrder
966 Clear((stream_t)StreamKind, StreamPos, General_StreamOrder);
967 for (size_t program_FromStream=0; program_FromStream<Temp->program_numbers.size(); ++program_FromStream)
968 {
969 int16u program_number=Temp->program_numbers[program_FromStream];
970 std::vector<int16u> &programs_List=Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].programs_List;
971 size_t programs_List_Pos=0;
972 for (; programs_List_Pos<programs_List.size(); ++programs_List_Pos)
973 if (programs_List[programs_List_Pos]==program_number)
974 break;
975 if (programs_List_Pos<programs_List.size())
976 {
977 complete_stream::transport_stream::program &Program=Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs[program_number];
978 for (size_t elementary_PID_Pos=0; elementary_PID_Pos<Program.elementary_PIDs.size(); ++elementary_PID_Pos)
979 if (Program.elementary_PIDs[elementary_PID_Pos]==StreamID)
980 Fill((stream_t)StreamKind, StreamPos, General_StreamOrder, Ztring::ToZtring(programs_List_Pos)+__T('-')+Ztring::ToZtring(elementary_PID_Pos));
981 }
982 }
983
984 //Special cases
985 if ((stream_t)StreamKind==Stream_Video && Temp->Parser && Temp->Parser->Count_Get(Stream_Text))
986 {
987 }
988 }
989 }
990 Temp->Infos.clear();
991 Temp->Infos_Option.clear();
992
993 //Special cases
994 if (Temp->Parser && Temp->Parser->Count_Get(Stream_Video))
995 {
996 //Video and Text may be together
997 size_t Text_Count=Temp->Parser->Count_Get(Stream_Text);
998 for (size_t Text_Pos=0; Text_Pos<Text_Count; Text_Pos++)
999 {
1000 Ztring Parser_ID=Temp->Parser->Retrieve(Stream_Text, Text_Pos, Text_ID);
1001 if (Parser_ID.find(__T('-'))!=string::npos)
1002 Parser_ID.erase(Parser_ID.begin(), Parser_ID.begin()+Parser_ID.find(__T('-'))+1);
1003 Ztring ID=Retrieve(Stream_Video, Temp->StreamPos, Video_ID)+__T('-')+Parser_ID;
1004 Ztring ID_String=Retrieve(Stream_Video, Temp->StreamPos, Video_ID_String)+__T('-')+Parser_ID;
1005 StreamPos_Last=(size_t)-1;
1006 for (size_t Pos=0; Pos<Count_Get(Stream_Text); Pos++)
1007 if (Retrieve(Stream_Text, Pos, Text_ID)==ID && Retrieve(Stream_Text, Pos, "MuxingMode")==Temp->Parser->Retrieve(Stream_Text, Text_Pos, "MuxingMode"))
1008 {
1009 StreamPos_Last=Pos;
1010 break;
1011 }
1012 if (StreamPos_Last==(size_t)-1)
1013 Stream_Prepare(Stream_Text, StreamPos_Last);
1014 if (!IsSub)
1015 Fill(Stream_Text, StreamPos_Last, "MuxingMode_MoreInfo", __T("Muxed in Video #")+Ztring().From_Number(Temp->StreamPos+1), true);
1016 Merge(*Temp->Parser, Stream_Text, Text_Pos, StreamPos_Last);
1017
1018 Fill(Stream_Text, StreamPos_Last, Text_ID, ID, true);
1019 Fill(Stream_Text, StreamPos_Last, Text_ID_String, ID_String, true);
1020 Fill(Stream_Text, StreamPos_Last, Text_StreamOrder, Retrieve(Stream_Video, Temp->StreamPos, Video_StreamOrder), true);
1021 Fill(Stream_Text, StreamPos_Last, Text_MenuID, Retrieve(Stream_Video, Temp->StreamPos, Video_MenuID), true);
1022 Fill(Stream_Text, StreamPos_Last, Text_MenuID_String, Retrieve(Stream_Video, Temp->StreamPos, Video_MenuID_String), true);
1023 Fill(Stream_Text, StreamPos_Last, Text_Duration, Retrieve(Stream_Video, Temp->StreamPos, Video_Duration), true);
1024 Fill(Stream_Text, StreamPos_Last, Text_Delay, Retrieve(Stream_Video, Temp->StreamPos, Video_Delay), true);
1025 Fill(Stream_Text, StreamPos_Last, Text_Delay_Source, Retrieve(Stream_Video, Temp->StreamPos, Video_Delay_Source), true);
1026 }
1027
1028 StreamKind_Last=Temp->StreamKind;
1029 StreamPos_Last=Temp->StreamPos;
1030 }
1031 }
1032
1033 //Teletext
1034 #if defined(MEDIAINFO_TELETEXT_YES)
1035 bool RelyOnTsInfo=(StreamKind_Last==Stream_Max);
1036 for (std::map<int16u, teletext>::iterator Teletext=Temp->Teletexts.begin(); Teletext!=Temp->Teletexts.end(); ++Teletext)
1037 {
1038 if (RelyOnTsInfo)
1039 {
1040 std::map<std::string, Ztring>::iterator Info_Format=Teletext->second.Infos.find("Format");
1041 Stream_Prepare((Info_Format!=Teletext->second.Infos.end() && Info_Format->second==__T("Teletext"))?Stream_Other:Stream_Text);
1042 Fill(StreamKind_Last, StreamPos_Last, General_ID, Ztring::ToZtring(StreamID)+__T('-')+Ztring::ToZtring(Teletext->first), true);
1043 Fill(StreamKind_Last, StreamPos_Last, General_ID_String, Decimal_Hexa(StreamID)+__T('-')+Ztring::ToZtring(Teletext->first), true);
1044
1045 for (size_t Pos=0; Pos<Temp->program_numbers.size(); Pos++)
1046 {
1047 Fill(StreamKind_Last, StreamPos_Last, General_MenuID, Temp->program_numbers[Pos], 10, Pos==0);
1048 Fill(StreamKind_Last, StreamPos_Last, General_MenuID_String, Decimal_Hexa(Temp->program_numbers[Pos]), Pos==0);
1049 }
1050 }
1051 else
1052 {
1053 StreamKind_Last=Stream_Max;
1054 StreamPos_Last=(size_t)-1;
1055 Ztring ID=Ztring::ToZtring(StreamID)+__T('-')+Ztring::ToZtring(Teletext->first);
1056 for (size_t StreamKind=Stream_General+1; StreamKind<Stream_Max; StreamKind++)
1057 for (size_t StreamPos=0; StreamPos<Count_Get((stream_t)StreamKind); StreamPos++)
1058 if (Retrieve((stream_t)StreamKind, StreamPos, General_ID) == ID)
1059 {
1060 StreamKind_Last=(stream_t)StreamKind;
1061 StreamPos_Last=StreamPos;
1062 }
1063 }
1064
1065 //TS info
1066 if (StreamKind_Last!=Stream_Max)
1067 {
1068 for (std::map<std::string, ZenLib::Ztring>::iterator Info=Teletext->second.Infos.begin(); Info!=Teletext->second.Infos.end(); ++Info)
1069 {
1070 if (Retrieve(StreamKind_Last, StreamPos_Last, Info->first.c_str()).empty())
1071 Fill(StreamKind_Last, StreamPos_Last, Info->first.c_str(), Info->second);
1072 }
1073 Teletext->second.Infos.clear();
1074 }
1075 Teletext->second.StreamKind=StreamKind_Last;
1076 Teletext->second.StreamPos=StreamPos_Last;
1077 }
1078 #endif //MEDIAINFO_TELETEXT_YES
1079
1080 //From parser General part
1081 MergeGeneral(Temp, General_LawRating);
1082 MergeGeneral(Temp, General_Title);
1083 MergeGeneral(Temp, General_Recorded_Date);
1084 MergeGeneral(Temp, General_Encoded_Application);
1085 MergeGeneral(Temp, General_Encoded_Application_CompanyName);
1086 MergeGeneral(Temp, General_Encoded_Application_Name);
1087 }
1088
1089 //---------------------------------------------------------------------------
Streams_Update_EPG()1090 void File_MpegTs::Streams_Update_EPG()
1091 {
1092 //EPG
1093 complete_stream::transport_streams::iterator Transport_Stream=Complete_Stream->transport_stream_id_IsValid?Complete_Stream->Transport_Streams.find(Complete_Stream->transport_stream_id):Complete_Stream->Transport_Streams.end();
1094 if (Transport_Stream==Complete_Stream->Transport_Streams.end())
1095 return;
1096
1097 //Per source (ATSC)
1098 if (Transport_Stream->second.source_id_IsValid)
1099 {
1100 complete_stream::sources::iterator Source=Complete_Stream->Sources.find(Transport_Stream->second.source_id);
1101 if (Source!=Complete_Stream->Sources.end())
1102 {
1103 //EPG
1104 std::map<Ztring, Ztring> EPGs;
1105 for (complete_stream::source::atsc_epg_blocks::iterator ATSC_EPG_Block=Source->second.ATSC_EPG_Blocks.begin(); ATSC_EPG_Block!=Source->second.ATSC_EPG_Blocks.end(); ++ATSC_EPG_Block)
1106 for (complete_stream::source::atsc_epg_block::events::iterator Event=ATSC_EPG_Block->second.Events.begin(); Event!=ATSC_EPG_Block->second.Events.end(); ++Event)
1107 {
1108 Ztring Texts;
1109 for (std::map<int16u, Ztring>::iterator text=Event->second.texts.begin(); text!=Event->second.texts.end(); ++text)
1110 Texts+=text->second+__T(" - ");
1111 if (!Texts.empty())
1112 Texts.resize(Texts.size()-3);
1113 EPGs[Ztring().Date_From_Seconds_1970(Event->second.start_time+315964800-Complete_Stream->GPS_UTC_offset)]=Event->second.title+__T(" / ")+Texts+__T(" / / / ")+Event->second.duration+__T(" / ");
1114 }
1115 if (!EPGs.empty())
1116 {
1117 //Trashing old EPG
1118 size_t Begin=Retrieve(Stream_General, 0, General_EPG_Positions_Begin).To_int32u();
1119 size_t End=Retrieve(Stream_General, 0, General_EPG_Positions_End).To_int32u();
1120 if (Begin && End && Begin<End)
1121 for (size_t Pos=End-1; Pos>=Begin; Pos--)
1122 Clear(Stream_General, 0, Pos);
1123
1124 //Filling
1125 Fill(Stream_General, 0, General_EPG_Positions_Begin, Count_Get(Stream_General, 0), 10, true);
1126 for (std::map<Ztring, Ztring>::iterator EPG=EPGs.begin(); EPG!=EPGs.end(); ++EPG)
1127 Fill(Stream_General, 0, EPG->first.To_UTF8().c_str(), EPG->second, true);
1128 Fill(Stream_General, 0, General_EPG_Positions_End, Count_Get(Stream_General, 0), 10, true);
1129 }
1130 }
1131 }
1132
1133 //Per program
1134 if (!Transport_Stream->second.Programs.empty()
1135 && (Transport_Stream->second.Programs.size()>1
1136 || !Transport_Stream->second.Programs.begin()->second.Infos.empty()
1137 || !Transport_Stream->second.Programs.begin()->second.DVB_EPG_Blocks.empty()
1138 || Complete_Stream->Sources.find(Transport_Stream->second.Programs.begin()->second.source_id)!=Complete_Stream->Sources.end()
1139 || Config->File_MpegTs_ForceMenu_Get()))
1140 for (complete_stream::transport_stream::programs::iterator Program=Transport_Stream->second.Programs.begin(); Program!=Transport_Stream->second.Programs.end(); ++Program)
1141 {
1142 if (Program->second.IsParsed)
1143 {
1144 bool EPGs_IsUpdated=false;
1145 std::map<Ztring, Ztring> EPGs;
1146
1147 //EPG - DVB
1148 if (Program->second.DVB_EPG_Blocks_IsUpdated)
1149 {
1150 for (complete_stream::transport_stream::program::dvb_epg_blocks::iterator DVB_EPG_Block=Program->second.DVB_EPG_Blocks.begin(); DVB_EPG_Block!=Program->second.DVB_EPG_Blocks.end(); ++DVB_EPG_Block)
1151 for (complete_stream::transport_stream::program::dvb_epg_block::events::iterator Event=DVB_EPG_Block->second.Events.begin(); Event!=DVB_EPG_Block->second.Events.end(); ++Event)
1152 if (EPGs.find(Event->second.start_time)==EPGs.end() || DVB_EPG_Block->first==0x4E) //Does not exist or "DVB - event_information_section - actual_transport_stream : return present/following"
1153 EPGs[Event->second.start_time]=Event->second.short_event.event_name+__T(" / ")+Event->second.short_event.text+__T(" / ")+Event->second.content+__T(" / / ")+Event->second.duration+__T(" / ")+Event->second.running_status;
1154 Program->second.DVB_EPG_Blocks_IsUpdated=false;
1155 EPGs_IsUpdated=true;
1156 }
1157
1158 //EPG - ATSC
1159 if (Program->second.source_id_IsValid)
1160 {
1161 complete_stream::sources::iterator Source=Complete_Stream->Sources.find(Program->second.source_id);
1162 if (Source!=Complete_Stream->Sources.end())
1163 {
1164 if (!Source->second.texts.empty())
1165 {
1166 Ztring Texts;
1167 for (std::map<int16u, Ztring>::iterator text=Source->second.texts.begin(); text!=Source->second.texts.end(); ++text)
1168 Texts+=text->second+__T(" - ");
1169 if (!Texts.empty())
1170 Texts.resize(Texts.size()-3);
1171 if (Program->second.StreamPos==(size_t)-1)
1172 {
1173 Complete_Stream->program_number_Order.push_back(Program->first);
1174 Stream_Prepare(Stream_Menu);
1175 Program->second.StreamPos=StreamPos_Last;
1176 }
1177 Fill(Stream_Menu, Program->second.StreamPos, Menu_ServiceProvider, Texts, true);
1178 }
1179 if (Source->second.ATSC_EPG_Blocks_IsUpdated)
1180 {
1181 for (complete_stream::source::atsc_epg_blocks::iterator ATSC_EPG_Block=Source->second.ATSC_EPG_Blocks.begin(); ATSC_EPG_Block!=Source->second.ATSC_EPG_Blocks.end(); ++ATSC_EPG_Block)
1182 for (complete_stream::source::atsc_epg_block::events::iterator Event=ATSC_EPG_Block->second.Events.begin(); Event!=ATSC_EPG_Block->second.Events.end(); ++Event)
1183 if (Event->second.start_time!=(int32u)-1) //TODO: find the reason when start_time is not set
1184 {
1185 Ztring Texts;
1186 for (std::map<int16u, Ztring>::iterator text=Event->second.texts.begin(); text!=Event->second.texts.end(); ++text)
1187 Texts+=text->second+__T(" - ");
1188 if (!Texts.empty())
1189 Texts.resize(Texts.size()-3);
1190 EPGs[Ztring().Date_From_Seconds_1970(Event->second.start_time+315964800-Complete_Stream->GPS_UTC_offset)]=Event->second.title+__T(" / ")+Texts+__T(" / / / ")+Event->second.duration+__T(" / ");
1191 }
1192 Source->second.ATSC_EPG_Blocks_IsUpdated=false;
1193 EPGs_IsUpdated=true;
1194 }
1195 }
1196 }
1197
1198 //EPG - Filling
1199 if (EPGs_IsUpdated)
1200 {
1201 if (Program->second.StreamPos==(size_t)-1)
1202 {
1203 Complete_Stream->program_number_Order.push_back(Program->first);
1204 Stream_Prepare(Stream_Menu);
1205 Program->second.StreamPos=StreamPos_Last;
1206 }
1207
1208 Program->second.EPGs=EPGs;
1209 Streams_Update_EPG_PerProgram(Program);
1210 }
1211 }
1212 }
1213
1214 Complete_Stream->Sources_IsUpdated=false;
1215 Complete_Stream->Programs_IsUpdated=false;
1216 }
1217
1218 //---------------------------------------------------------------------------
Streams_Update_EPG_PerProgram(complete_stream::transport_stream::programs::iterator Program)1219 void File_MpegTs::Streams_Update_EPG_PerProgram(complete_stream::transport_stream::programs::iterator Program)
1220 {
1221 size_t Chapters_Pos_Begin=Retrieve(Stream_Menu, Program->second.StreamPos, Menu_Chapters_Pos_Begin).To_int32u();
1222 size_t Chapters_Pos_End=Retrieve(Stream_Menu, Program->second.StreamPos, Menu_Chapters_Pos_End).To_int32u();
1223 if (Chapters_Pos_Begin && Chapters_Pos_End)
1224 {
1225 for (size_t Pos=Chapters_Pos_End-1; Pos>=Chapters_Pos_Begin; Pos--)
1226 Clear(Stream_Menu, Program->second.StreamPos, Pos);
1227 Clear(Stream_Menu, Program->second.StreamPos, Menu_Chapters_Pos_Begin);
1228 Clear(Stream_Menu, Program->second.StreamPos, Menu_Chapters_Pos_End);
1229 }
1230 if (!Program->second.EPGs.empty())
1231 {
1232 Fill(Stream_Menu, Program->second.StreamPos, Menu_Chapters_Pos_Begin, Count_Get(Stream_Menu, Program->second.StreamPos), 10, true);
1233 for (std::map<Ztring, Ztring>::iterator EPG=Program->second.EPGs.begin(); EPG!=Program->second.EPGs.end(); ++EPG)
1234 Fill(Stream_Menu, Program->second.StreamPos, EPG->first.To_UTF8().c_str(), EPG->second, true);
1235 Fill(Stream_Menu, Program->second.StreamPos, Menu_Chapters_Pos_End, Count_Get(Stream_Menu, Program->second.StreamPos), 10, true);
1236 }
1237 }
1238
1239 //---------------------------------------------------------------------------
1240 #ifdef MEDIAINFO_MPEGTS_PCR_YES
Streams_Update_Duration_Update()1241 void File_MpegTs::Streams_Update_Duration_Update()
1242 {
1243 bool IsVbr=false;
1244 bool IsCbr=false;
1245 #if MEDIAINFO_ADVANCED
1246 float64 TimeStamp_InstantaneousBitRate_Min_Raw=DBL_MAX;
1247 float64 TimeStamp_InstantaneousBitRate_Max_Raw=0;
1248 int64u TimeStamp_Distance_Min=(int64u)-1;
1249 int64u TimeStamp_Distance_Max=0;
1250 int64u TimeStamp_Distance_Total=0;
1251 int64u TimeStamp_Distance_Count=0;
1252 int64u TimeStamp_HasProblems=0;
1253 #endif // MEDIAINFO_ADVANCED
1254
1255 int64u Duration_Count=0;
1256 int64u Duration_Max=0;
1257 int64u Duration_Sum=0;
1258 int64u Bytes_Sum=0;
1259 for (std::map<int16u, int16u>::iterator PCR_PID=Complete_Stream->PCR_PIDs.begin(); PCR_PID!=Complete_Stream->PCR_PIDs.end(); ++PCR_PID)
1260 {
1261 complete_stream::streams::iterator Stream=Complete_Stream->Streams.begin()+PCR_PID->first;
1262 if (*Stream && (*Stream)->TimeStamp_End_IsUpdated)
1263 {
1264 if ((*Stream)->TimeStamp_End<0x100000000LL*300 && (*Stream)->TimeStamp_Start>0x100000000LL*300)
1265 (*Stream)->TimeStamp_End+=0x200000000LL*300; //33 bits, cyclic
1266 if ((*Stream)->TimeStamp_Start<(*Stream)->TimeStamp_End)
1267 {
1268 int64u Duration=0;
1269 int64u Bytes=0;
1270 #if MEDIAINFO_ADVANCED
1271 if (Config->ParseSpeed>=1 && !(*Stream)->TimeStamp_Intermediate.empty())
1272 {
1273 Duration=(*Stream)->TimeStamp_Intermediate[0]-(*Stream)->TimeStamp_Start;
1274 size_t Last=(*Stream)->TimeStamp_Intermediate.size()-1;
1275 for (size_t Pos=1; Pos+1<Last; Pos+=2)
1276 Duration+=(*Stream)->TimeStamp_Intermediate[Pos+1]-(*Stream)->TimeStamp_Intermediate[Pos];
1277 Duration+=(*Stream)->TimeStamp_End-(*Stream)->TimeStamp_Intermediate[Last];
1278 }
1279 else
1280 #endif // MEDIAINFO_ADVANCED
1281 {
1282 Duration=(*Stream)->TimeStamp_End-(*Stream)->TimeStamp_Start;
1283 }
1284 Bytes=(*Stream)->TimeStamp_End_Offset-(*Stream)->TimeStamp_Start_Offset;
1285
1286 if (Duration>Duration_Max)
1287 Duration_Max=Duration;
1288 Duration_Count++;
1289 Duration_Sum+=Duration;
1290 Bytes_Sum+=Bytes;
1291
1292 (*Stream)->TimeStamp_End_IsUpdated=false;
1293 (*Stream)->IsPCR_Duration=(float64)Duration;
1294
1295 //Filling menu duration
1296 if (Count_Get(Stream_Menu))
1297 {
1298 complete_stream::transport_streams::iterator Transport_Stream=Complete_Stream->transport_stream_id_IsValid?Complete_Stream->Transport_Streams.find(Complete_Stream->transport_stream_id):Complete_Stream->Transport_Streams.end();
1299 if (Transport_Stream!=Complete_Stream->Transport_Streams.end())
1300 {
1301 //Per program
1302 for (size_t Pos=0; Pos<(*Stream)->program_numbers.size(); Pos++)
1303 {
1304 int16u program_number=(*Stream)->program_numbers[Pos];
1305 if (Transport_Stream->second.Programs[program_number].IsRegistered) //Only if the menu is already displayed
1306 Fill(Stream_Menu, Transport_Stream->second.Programs[program_number].StreamPos, Menu_Duration, ((float64)Duration)/27000, 6, true);
1307 }
1308 }
1309 }
1310 }
1311
1312 if ((*Stream)->TimeStamp_InstantaneousBitRate_BitRateMode_IsVbr>=Config_VbrDetection_Occurences)
1313 IsVbr=true;
1314 if ((*Stream)->TimeStamp_InstantaneousBitRate_BitRateMode_IsCbr)
1315 IsCbr=true;
1316 #if MEDIAINFO_ADVANCED
1317 if (Config->ParseSpeed>=1)
1318 {
1319 if (TimeStamp_InstantaneousBitRate_Min_Raw>(*Stream)->TimeStamp_InstantaneousBitRate_Min_Raw)
1320 TimeStamp_InstantaneousBitRate_Min_Raw=(*Stream)->TimeStamp_InstantaneousBitRate_Min_Raw;
1321 if (TimeStamp_InstantaneousBitRate_Max_Raw<(*Stream)->TimeStamp_InstantaneousBitRate_Max_Raw)
1322 TimeStamp_InstantaneousBitRate_Max_Raw=(*Stream)->TimeStamp_InstantaneousBitRate_Max_Raw;
1323 TimeStamp_Distance_Total+=(*Stream)->TimeStamp_Distance_Total;
1324 TimeStamp_Distance_Count+=(*Stream)->TimeStamp_Distance_Count;
1325 if (TimeStamp_Distance_Min>(*Stream)->TimeStamp_Distance_Min)
1326 TimeStamp_Distance_Min=(*Stream)->TimeStamp_Distance_Min;
1327 if (TimeStamp_Distance_Max<(*Stream)->TimeStamp_Distance_Max)
1328 TimeStamp_Distance_Max=(*Stream)->TimeStamp_Distance_Max;
1329 TimeStamp_HasProblems+=(*Stream)->TimeStamp_HasProblems;
1330 }
1331 #endif // MEDIAINFO_ADVANCED
1332 }
1333 }
1334
1335 if (Duration_Max)
1336 Fill(Stream_General, 0, General_Duration, ((float64)Duration_Max) / 27000, 6, true);
1337 if (Duration_Count && Duration_Sum && Bytes_Sum)
1338 {
1339 //Filling Duration and bitrate with an average of content from all streams with PCR
1340 //Min and Max are based on a a 1 byte precision in the computed byte count + +/- 500 ns tolerance for hte PCR vale
1341 Fill(Stream_General, 0, General_OverallBitRate, Bytes_Sum * 8 / (((float64)Duration_Sum) / 27000000), 0, true);
1342 Fill(Stream_General, 0, "OverallBitRate_Precision_Min", (Bytes_Sum - Duration_Count) * 8 / (((float64)(Duration_Sum + 13500 * Duration_Count)) / 27000000), 0, true);
1343 Fill_SetOptions(Stream_General, 0, "OverallBitRate_Precision_Min", "N NT");
1344 Fill(Stream_General, 0, "OverallBitRate_Precision_Max", (Bytes_Sum + Duration_Count) * 8 / (((float64)(Duration_Sum - 13500 * Duration_Count)) / 27000000), 0, true);
1345 Fill_SetOptions(Stream_General, 0, "OverallBitRate_Precision_Max", "N NT");
1346 }
1347
1348 if (IsVbr)
1349 Fill(Stream_General, 0, General_OverallBitRate_Mode, "VBR", Unlimited, true, true);
1350 else if (IsCbr)
1351 Fill(Stream_General, 0, General_OverallBitRate_Mode, "CBR", Unlimited, true, true);
1352 else
1353 Clear(Stream_General, 0, General_OverallBitRate_Mode);
1354 #if MEDIAINFO_ADVANCED
1355 if (Config->ParseSpeed>=1)
1356 {
1357 if ((IsVbr || !IsCbr) && TimeStamp_InstantaneousBitRate_Min_Raw<DBL_MAX)
1358 Fill(Stream_General, 0, General_OverallBitRate_Minimum, TimeStamp_InstantaneousBitRate_Min_Raw, 0, true);
1359 else
1360 Clear(Stream_General, 0, General_OverallBitRate_Minimum);
1361 if ((IsVbr || !IsCbr) && TimeStamp_InstantaneousBitRate_Max_Raw)
1362 Fill(Stream_General, 0, General_OverallBitRate_Maximum, TimeStamp_InstantaneousBitRate_Max_Raw, 0, true);
1363 else
1364 Clear(Stream_General, 0, General_OverallBitRate_Maximum);
1365 if (TimeStamp_Distance_Count)
1366 {
1367 Fill(Stream_General, 0, "PCR_Distance_Average", ((float64)TimeStamp_Distance_Total)/27000000/TimeStamp_Distance_Count, 9, true);
1368 Fill_SetOptions(Stream_General, 0, "PCR_Distance_Average", "N NT");
1369 }
1370 if (TimeStamp_Distance_Min!=(int64u)-1)
1371 {
1372 Fill(Stream_General, 0, "PCR_Distance_Min", ((float64)TimeStamp_Distance_Min)/27000000, 9, true);
1373 Fill_SetOptions(Stream_General, 0, "PCR_Distance_Min", "N NT");
1374 }
1375 if (TimeStamp_Distance_Max)
1376 {
1377 Fill(Stream_General, 0, "PCR_Distance_Max", ((float64)TimeStamp_Distance_Max)/27000000, 9, true);
1378 Fill_SetOptions(Stream_General, 0, "PCR_Distance_Max", "N NT");
1379 }
1380 {
1381 Fill(Stream_General, 0, "PCR_Invalid_Count", TimeStamp_HasProblems, 10, true);
1382 Fill_SetOptions(Stream_General, 0, "PCR_Invalid_Count", "N NT");
1383 }
1384
1385 }
1386 #endif // MEDIAINFO_ADVANCED
1387 }
1388 #endif //MEDIAINFO_MPEGTS_PCR_YES
1389
1390 //---------------------------------------------------------------------------
Streams_Update_Duration_End()1391 void File_MpegTs::Streams_Update_Duration_End()
1392 {
1393 //General
1394 Fill(Stream_General, 0, General_Duration_End, Complete_Stream->Duration_End, true);
1395
1396 Complete_Stream->Duration_End_IsUpdated=false;
1397 }
1398
1399 //---------------------------------------------------------------------------
Streams_Finish()1400 void File_MpegTs::Streams_Finish()
1401 {
1402 //Per stream
1403 for (size_t StreamID=0; StreamID<0x2000; StreamID++)
1404 if (Complete_Stream->Streams[StreamID]->Parser)
1405 {
1406 if (!Complete_Stream->Streams[StreamID]->Parser->Status[IsFinished])
1407 {
1408 int64u File_Size_Temp=File_Size;
1409 File_Size=File_Offset+Buffer_Offset+Element_Offset;
1410 Open_Buffer_Continue(Complete_Stream->Streams[StreamID]->Parser, Buffer, 0, false);
1411 File_Size=File_Size_Temp;
1412 Finish(Complete_Stream->Streams[StreamID]->Parser);
1413 #if MEDIAINFO_DEMUX
1414 if (Config->Demux_EventWasSent)
1415 return;
1416 #endif //MEDIAINFO_DEMUX
1417 }
1418 }
1419
1420 #if MEDIAINFO_DUPLICATE
1421 File__Duplicate_Streams_Finish();
1422 #endif //MEDIAINFO_DUPLICATE
1423
1424 #if MEDIAINFO_IBIUSAGE
1425 if (!IsSub && Config_Ibi_Create)
1426 {
1427 for (ibi::streams::iterator IbiStream_Temp=Ibi.Streams.begin(); IbiStream_Temp!=Ibi.Streams.end(); ++IbiStream_Temp)
1428 {
1429 if (IbiStream_Temp->second && IbiStream_Temp->second->DtsFrequencyNumerator==1000000000 && IbiStream_Temp->second->DtsFrequencyDenominator==1)
1430 {
1431 bool IsOk=true;
1432 for (size_t Pos=0; Pos<IbiStream_Temp->second->Infos.size(); Pos++)
1433 if (!IbiStream_Temp->second->Infos[Pos].IsContinuous && Pos+1!=IbiStream_Temp->second->Infos.size())
1434 IsOk=false;
1435 if (IsOk) //Only is all items are continuous (partial IBI not yet supported)
1436 {
1437 IbiStream_Temp->second->DtsFrequencyNumerator=90000;
1438 for (size_t Pos=0; Pos<IbiStream_Temp->second->Infos.size(); Pos++)
1439 {
1440 int64u Temp=IbiStream_Temp->second->Infos[Pos].Dts*90/1000000;
1441 IbiStream_Temp->second->Infos[Pos].Dts=Temp;
1442 }
1443 }
1444 }
1445 }
1446 }
1447 #endif //MEDIAINFO_IBIUSAGE
1448 }
1449
1450 //***************************************************************************
1451 // Buffer - Synchro
1452 //***************************************************************************
1453
1454 //---------------------------------------------------------------------------
Synchronize()1455 bool File_MpegTs::Synchronize()
1456 {
1457 //Synchronizing
1458 while ( Buffer_Offset+188*16+BDAV_Size*16+TSP_Size*16<=Buffer_Size
1459 && !(Buffer[Buffer_Offset+188* 0+BDAV_Size* 1+TSP_Size* 0]==0x47
1460 && Buffer[Buffer_Offset+188* 1+BDAV_Size* 2+TSP_Size* 1]==0x47
1461 && Buffer[Buffer_Offset+188* 2+BDAV_Size* 3+TSP_Size* 2]==0x47
1462 && Buffer[Buffer_Offset+188* 3+BDAV_Size* 4+TSP_Size* 3]==0x47
1463 && Buffer[Buffer_Offset+188* 4+BDAV_Size* 5+TSP_Size* 4]==0x47
1464 && Buffer[Buffer_Offset+188* 5+BDAV_Size* 6+TSP_Size* 5]==0x47
1465 && Buffer[Buffer_Offset+188* 6+BDAV_Size* 7+TSP_Size* 6]==0x47
1466 && Buffer[Buffer_Offset+188* 7+BDAV_Size* 8+TSP_Size* 7]==0x47
1467 && Buffer[Buffer_Offset+188* 8+BDAV_Size* 9+TSP_Size* 8]==0x47
1468 && Buffer[Buffer_Offset+188* 9+BDAV_Size*10+TSP_Size* 9]==0x47
1469 && Buffer[Buffer_Offset+188*10+BDAV_Size*11+TSP_Size*10]==0x47
1470 && Buffer[Buffer_Offset+188*11+BDAV_Size*12+TSP_Size*11]==0x47
1471 && Buffer[Buffer_Offset+188*12+BDAV_Size*13+TSP_Size*12]==0x47
1472 && Buffer[Buffer_Offset+188*13+BDAV_Size*14+TSP_Size*13]==0x47
1473 && Buffer[Buffer_Offset+188*14+BDAV_Size*15+TSP_Size*14]==0x47
1474 && Buffer[Buffer_Offset+188*15+BDAV_Size*16+TSP_Size*15]==0x47))
1475 {
1476 Buffer_Offset++;
1477 while ( Buffer_Offset+BDAV_Size+1<=Buffer_Size
1478 && Buffer[Buffer_Offset+BDAV_Size]!=0x47)
1479 Buffer_Offset++;
1480 }
1481
1482 if (Buffer_Offset+188*16+BDAV_Size*16+TSP_Size*16>=Buffer_Size
1483 #ifdef MEDIAINFO_ARIBSTDB24B37_YES
1484 && !FromAribStdB24B37
1485 #endif
1486 )
1487 return false;
1488
1489 //Synched is OK
1490 return true;
1491 }
1492
1493 //---------------------------------------------------------------------------
Synched_Test()1494 bool File_MpegTs::Synched_Test()
1495 {
1496 while (Buffer_Offset+TS_Size<=Buffer_Size)
1497 {
1498 //Synchro testing
1499 if (Buffer[Buffer_Offset+BDAV_Size]!=0x47)
1500 {
1501 Synched=false;
1502 #if MEDIAINFO_DUPLICATE
1503 if (File__Duplicate_Get())
1504 Trusted++; //We don't want to stop parsing if duplication is requested, TS is not a lot stable, normal...
1505 #endif //MEDIAINFO_DUPLICATE
1506 return true;
1507 }
1508
1509 //Getting pid
1510 pid=(Buffer[Buffer_Offset+BDAV_Size+1]&0x1F)<<8
1511 | Buffer[Buffer_Offset+BDAV_Size+2];
1512
1513 complete_stream::stream* Stream=Complete_Stream->Streams[pid];
1514 if (Stream->Searching)
1515 {
1516 //Trace config
1517 #if MEDIAINFO_TRACE
1518 if (Config_Trace_Level)
1519 {
1520 if (Stream->Kind==complete_stream::stream::pes)
1521 {
1522 if (!Trace_Layers[8])
1523 Trace_Layers_Update(8); //Stream
1524 }
1525 else
1526 Trace_Layers_Update(IsSub?1:0);
1527 }
1528 #endif //MEDIAINFO_TRACE
1529
1530 payload_unit_start_indicator=(Buffer[Buffer_Offset+BDAV_Size+1]&0x40)!=0;
1531 if (payload_unit_start_indicator)
1532 {
1533 //Searching start
1534 if (Stream->Searching_Payload_Start) //payload_unit_start_indicator
1535 {
1536 if (Stream->Kind==complete_stream::stream::psi)
1537 {
1538 //Searching table_id
1539 size_t Version_Pos=BDAV_Size
1540 +4 //standart header
1541 +((Buffer[Buffer_Offset+BDAV_Size+3]&0x20)?(1+Buffer[Buffer_Offset+BDAV_Size+4]):0); //adaptation_field_control (adaptation) --> adaptation_field_length
1542 if (Version_Pos>=BDAV_Size+188)
1543 return true; //There is a problem with this block, accelerated parsing disabled
1544 Version_Pos+=1+Buffer[Buffer_Offset+Version_Pos]; //pointer_field
1545 if (Version_Pos>=BDAV_Size+188)
1546 return true; //There is a problem with this block, accelerated parsing disabled
1547 int8u table_id=Buffer[Buffer_Offset+Version_Pos]; //table_id
1548 #if MEDIAINFO_TRACE
1549 if (Trace_Activated)
1550 Stream->Element_Info1=Mpeg_Psi_table_id(table_id);
1551 #endif //MEDIAINFO_TRACE
1552 if (table_id==0xCD) //specifc case for ATSC STT
1553 {
1554 if (Config_Trace_TimeSection_OnlyFirstOccurrence)
1555 {
1556 if (!TimeSection_FirstOccurrenceParsed)
1557 TimeSection_FirstOccurrenceParsed=true;
1558 #if MEDIAINFO_TRACE
1559 else
1560 {
1561 Trace_Layers.reset(); //We do not want to display data about other occurences
1562 Trace_Layers_Update();
1563 }
1564 #endif //MEDIAINFO_TRACE
1565 }
1566 return true; //Version has no meaning
1567 }
1568 #if MEDIAINFO_IBIUSAGE
1569 if (table_id==0x00)
1570 Complete_Stream->Streams[pid]->Ibi_SynchronizationOffset_BeginOfFrame=File_Offset+Buffer_Offset;
1571 if (table_id==0x02)
1572 Complete_Stream->Streams[pid]->Ibi_SynchronizationOffset_BeginOfFrame=Complete_Stream->Streams[0x0000]->Ibi_SynchronizationOffset_BeginOfFrame;
1573 #endif //MEDIAINFO_IBIUSAGE
1574 complete_stream::stream::table_ids::iterator Table_ID=Stream->Table_IDs.begin()+table_id;
1575 if (*Table_ID)
1576 {
1577 //Searching table_id_extension, version_number, section_number
1578 if (!(Buffer[Buffer_Offset+Version_Pos+1]&0x80)) //section_syntax_indicator
1579 {
1580 if (table_id==0x70 && Config_Trace_TimeSection_OnlyFirstOccurrence)
1581 {
1582 if (!TimeSection_FirstOccurrenceParsed)
1583 TimeSection_FirstOccurrenceParsed=true;
1584 #if MEDIAINFO_TRACE
1585 else
1586 {
1587 Trace_Layers.reset(); //We do not want to display data about other occurences
1588 Trace_Layers_Update();
1589 }
1590 #endif //MEDIAINFO_TRACE
1591 }
1592 return true; //No version
1593 }
1594 Version_Pos+=3; //Header size
1595 if (Version_Pos+5>=BDAV_Size+188)
1596 return true; //Not able to detect version (too far)
1597 int16u table_id_extension=(Buffer[Buffer_Offset+Version_Pos]<<8)|Buffer[Buffer_Offset+Version_Pos+1];
1598 int8u version_number=(Buffer[Buffer_Offset+Version_Pos+2]&0x3F)>>1;
1599 int8u section_number=Buffer[Buffer_Offset+Version_Pos+3];
1600 complete_stream::stream::table_id::table_id_extensions::iterator Table_ID_Extension=(*Table_ID)->Table_ID_Extensions.find(table_id_extension);
1601 if (Table_ID_Extension==(*Table_ID)->Table_ID_Extensions.end())
1602 {
1603 if ((*Table_ID)->Table_ID_Extensions_CanAdd)
1604 {
1605 (*Table_ID)->Table_ID_Extensions[table_id_extension].version_number=version_number;
1606 (*Table_ID)->Table_ID_Extensions[table_id_extension].Section_Numbers.resize(0x100);
1607 (*Table_ID)->Table_ID_Extensions[table_id_extension].Section_Numbers[section_number]=true;
1608 return true; //table_id_extension is not yet parsed
1609 }
1610 }
1611 else if (Table_ID_Extension->second.version_number!=version_number)
1612 {
1613 if (Table_ID_Extension->second.version_number!=(int8u)-1 && Config_Trace_TimeSection_OnlyFirstOccurrence)
1614 break;
1615 Table_ID_Extension->second.version_number=version_number;
1616 Table_ID_Extension->second.Section_Numbers.clear();
1617 Table_ID_Extension->second.Section_Numbers.resize(0x100);
1618 Table_ID_Extension->second.Section_Numbers[section_number]=true;
1619 return true; //version is different
1620 }
1621 else if (!Table_ID_Extension->second.Section_Numbers[section_number])
1622 {
1623 Table_ID_Extension->second.Section_Numbers[section_number]=true;
1624 return true; //section is not yet parsed
1625 }
1626 else if (table_id==0x02 && Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs_NotParsedCount)
1627 {
1628 //PMT is looping, so this is nearly sure that all PMT available in the stream are assigned
1629 #ifdef MEDIAINFO_MPEGTS_ALLSTREAMS_YES
1630 for (size_t pid=0x10; pid<0x1FFF; pid++) //Wanting 0x10-->0x2F (DVB), 0x1ABC (cea_osd), 0x1FF7-->0x1FFF (ATSC)
1631 for (size_t Table_ID=0x00; Table_ID<0xFF; Table_ID++)
1632 {
1633 Complete_Stream->Streams[pid]->init(Table_ID); //event_information_section - actual_transport_stream, schedule
1634
1635 if (Pos==0x001F)
1636 Pos=0x1ABB; //Skipping normal data
1637 if (Pos==0x01ABC)
1638 Pos=0x1FF6; //Skipping normal data
1639 }
1640 #else //MEDIAINFO_MPEGTS_ALLSTREAMS_YES
1641 if (Complete_Stream->Streams[0x0010]->Kind==complete_stream::stream::unknown)
1642 {
1643 Complete_Stream->Streams[0x0010]->init(0x40); //network_information_section - actual_network
1644 }
1645 if (Complete_Stream->Streams[0x0011]->Kind==complete_stream::stream::unknown)
1646 {
1647 Complete_Stream->Streams[0x0011]->init(0x42); //service_description_section - actual_transport_stream
1648 }
1649 if (Complete_Stream->Streams[0x0012]->Kind==complete_stream::stream::unknown)
1650 {
1651 Complete_Stream->Streams[0x0012]->init(0x4E); //event_information_section - actual_transport_stream, present/following
1652 for (size_t Table_ID=0x50; Table_ID<0x60; Table_ID++)
1653 Complete_Stream->Streams[0x0012]->Table_IDs[Table_ID]=new complete_stream::stream::table_id; //event_information_section - actual_transport_stream, schedule
1654 }
1655 if (Complete_Stream->Streams[0x0014]->Kind==complete_stream::stream::unknown)
1656 {
1657 Complete_Stream->Streams[0x0014]->init(0x70); //time_date_section
1658 Complete_Stream->Streams[0x0014]->Table_IDs[0x73]=new complete_stream::stream::table_id; //time_offset_section
1659 }
1660 if (Complete_Stream->Streams[0x1FFB]->Kind==complete_stream::stream::unknown)
1661 {
1662 Complete_Stream->Streams[0x1FFB]->init(0xC7); //Master Guide Table
1663 Complete_Stream->Streams[0x1FFB]->Table_IDs[0xCD]=new complete_stream::stream::table_id; //System Time Table
1664 }
1665 #endif //MEDIAINFO_MPEGTS_ALLSTREAMS_YES
1666 }
1667 }
1668 }
1669 else
1670 return true; //No version in this pid
1671 }
1672 }
1673
1674 //Searching continue and parser timestamp
1675 if (Stream->Searching_Payload_Continue
1676 #ifdef MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
1677 || Stream->Searching_ParserTimeStamp_Start
1678 || Stream->Searching_ParserTimeStamp_End
1679 #endif //MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
1680 )
1681 return true;
1682
1683 //Adaptation layer
1684 #ifdef MEDIAINFO_MPEGTS_PCR_YES
1685 if (( Stream->Searching_TimeStamp_Start
1686 || Stream->Searching_TimeStamp_End)
1687 #ifdef MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
1688 && !Stream->Searching_ParserTimeStamp_End
1689 #endif //MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
1690 )
1691 {
1692 if ((Buffer[Buffer_Offset+BDAV_Size+3]&0x20)==0x20) //adaptation_field_control (adaptation)
1693 {
1694 int8u adaptation_field_length=Buffer[Buffer_Offset+BDAV_Size+4];
1695 if (adaptation_field_length>=5) //adaptation_field_length
1696 {
1697 bool discontinuity_indicator=(Buffer[Buffer_Offset+BDAV_Size+5]&0x80)!=0;
1698 bool PCR_flag=(Buffer[Buffer_Offset+BDAV_Size+5]&0x10)!=0;
1699 if (PCR_flag)
1700 {
1701 int64u program_clock_reference=( (((int64u)Buffer[Buffer_Offset+BDAV_Size+6])<<25)
1702 | (((int64u)Buffer[Buffer_Offset+BDAV_Size+7])<<17)
1703 | (((int64u)Buffer[Buffer_Offset+BDAV_Size+8])<< 9)
1704 | (((int64u)Buffer[Buffer_Offset+BDAV_Size+9])<< 1)
1705 | (((int64u)Buffer[Buffer_Offset+BDAV_Size+10])>>7));
1706 program_clock_reference*=300;
1707 program_clock_reference+=( (((int64u)Buffer[Buffer_Offset+BDAV_Size+10]&0x01)<<8)
1708 | (((int64u)Buffer[Buffer_Offset+BDAV_Size+11]) ));
1709 if (Complete_Stream->Streams[pid]->Searching_TimeStamp_End
1710 #ifdef MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
1711 && (!Complete_Stream->Streams[pid]->Searching_ParserTimeStamp_End
1712 || Complete_Stream->Streams[pid]->IsPCR) //If PCR, we always want it.
1713 #endif //MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
1714 )
1715 {
1716 Header_Parse_Events_Duration_Helper(program_clock_reference,discontinuity_indicator);
1717 }
1718 if (Complete_Stream->Streams[pid]->Searching_TimeStamp_Start)
1719 {
1720 //This is the first PCR
1721 Complete_Stream->Streams[pid]->TimeStamp_Start=program_clock_reference;
1722 Complete_Stream->Streams[pid]->TimeStamp_Start_Offset=File_Offset+Buffer_Offset;
1723 Complete_Stream->Streams[pid]->TimeStamp_End=program_clock_reference;
1724 Complete_Stream->Streams[pid]->TimeStamp_End_IsUpdated=true;
1725 Complete_Stream->Streams[pid]->TimeStamp_End_Offset=File_Offset+Buffer_Offset;
1726 Complete_Stream->Streams[pid]->Searching_TimeStamp_Start_Set(false);
1727 Complete_Stream->Streams[pid]->Searching_TimeStamp_End_Set(true);
1728 Complete_Stream->Streams_With_StartTimeStampCount++;
1729 {
1730 Status[IsUpdated]=true;
1731 Status[User_16]=true;
1732 }
1733 }
1734
1735 //Test if we can find the TS bitrate
1736 if (!Complete_Stream->Streams[pid]->EndTimeStampMoreThanxSeconds && Complete_Stream->Streams[pid]->TimeStamp_Start!=(int64u)-1
1737 && (File_Offset+Buffer_Offset-Buffer_TotalBytes_FirstSynched)*2<File_Size)
1738 {
1739 if (program_clock_reference<Complete_Stream->Streams[pid]->TimeStamp_Start)
1740 {
1741 if (Complete_Stream->Streams[pid]->TimeStamp_Start-program_clock_reference<10LL*90000*300) //Testing if difference is less that 10 seconds (value arbitrary choosen)
1742 Complete_Stream->Streams[pid]->TimeStamp_Start=program_clock_reference; //Looks like we have a small jump in the past in a buggy file, accepting it.
1743 else
1744 program_clock_reference+=0x200000000LL*300; //33 bits, cyclic
1745 }
1746 if ((program_clock_reference-Complete_Stream->Streams[pid]->TimeStamp_Start)>Begin_MaxDuration)
1747 {
1748 Complete_Stream->Streams[pid]->EndTimeStampMoreThanxSeconds=true;
1749 Complete_Stream->Streams_With_EndTimeStampMoreThanxSecondsCount++;
1750 if (Complete_Stream->Streams_NotParsedCount
1751 && Complete_Stream->Streams_With_StartTimeStampCount>0
1752 && Complete_Stream->Streams_With_StartTimeStampCount==Complete_Stream->Streams_With_EndTimeStampMoreThanxSecondsCount)
1753 {
1754 //We are already parsing 16 seconds (for all PCRs), we don't hope to have more info
1755 MpegTs_JumpTo_Begin=File_Offset+Buffer_Offset-Buffer_TotalBytes_FirstSynched;
1756 MpegTs_JumpTo_End=MpegTs_JumpTo_Begin;
1757 if (MpegTs_JumpTo_Begin+MpegTs_JumpTo_End>=File_Size)
1758 {
1759 if (MpegTs_JumpTo_Begin+MpegTs_JumpTo_End>File_Size)
1760 {
1761 MpegTs_JumpTo_Begin=File_Size;
1762 MpegTs_JumpTo_End=0;
1763 }
1764 else
1765 MpegTs_JumpTo_Begin=File_Size-MpegTs_JumpTo_End;
1766 }
1767 }
1768 }
1769 }
1770 }
1771 }
1772 }
1773 }
1774 #endif //MEDIAINFO_MPEGTS_PCR_YES
1775 }
1776
1777 #if MEDIAINFO_DUPLICATE
1778 if (Stream->ShouldDuplicate)
1779 {
1780 Element_Size=TS_Size;
1781 File__Duplicate_Write();
1782 }
1783 #endif //MEDIAINFO_DUPLICATE
1784
1785 Header_Parse_Events();
1786
1787 Buffer_Offset+=TS_Size;
1788 }
1789
1790 if (File_Offset+Buffer_Size>=File_Size)
1791 Detect_EOF(); //for TRP files
1792
1793 return false; //Not enough data
1794 }
1795
1796 //---------------------------------------------------------------------------
Header_Parse_Events_Duration_Helper(int64u & program_clock_reference,const bool discontinuity_indicator)1797 void File_MpegTs::Header_Parse_Events_Duration_Helper(int64u& program_clock_reference, const bool discontinuity_indicator)
1798 {
1799 Header_Parse_Events_Duration(program_clock_reference);
1800 if (program_clock_reference!=Complete_Stream->Streams[pid]->TimeStamp_End) //Some PCRs are buggy (low precision), using the first stream offset in the case of duplicate PCR value
1801 {
1802 if (Complete_Stream->Streams[pid]->TimeStamp_End_Offset!=(int64u)-1)
1803 {
1804 if (program_clock_reference+0x12c00000000LL<Complete_Stream->Streams[pid]->TimeStamp_End)
1805 program_clock_reference+=0x25800000000LL; //33 bits and *300
1806 if (!discontinuity_indicator && program_clock_reference>Complete_Stream->Streams[pid]->TimeStamp_End && program_clock_reference<Complete_Stream->Streams[pid]->TimeStamp_End+10*27000000) //Not before, not after 10 seconds, else there is a problem
1807 {
1808 float64 Duration_InstantaneousBitRate_Min=(float64)(program_clock_reference-Complete_Stream->Streams[pid]->TimeStamp_End-(Config_VbrDetection_Delta?0:810));
1809 float64 Duration_InstantaneousBitRate_Max=(float64)(program_clock_reference-Complete_Stream->Streams[pid]->TimeStamp_End+(Config_VbrDetection_Delta?0:810));
1810 float64 Bytes_InstantaneousBitRate=(float64)(File_Offset+Buffer_Offset-Complete_Stream->Streams[pid]->TimeStamp_End_Offset);
1811 float64 TimeStamp_InstantaneousBitRate_Current_Min=Bytes_InstantaneousBitRate*8/Duration_InstantaneousBitRate_Max*27000000*(1-Config_VbrDetection_Delta);
1812 float64 TimeStamp_InstantaneousBitRate_Current_Raw=Bytes_InstantaneousBitRate*8/Duration_InstantaneousBitRate_Min*27000000;
1813 float64 TimeStamp_InstantaneousBitRate_Current_Max=Bytes_InstantaneousBitRate*8/Duration_InstantaneousBitRate_Min*27000000*(1+Config_VbrDetection_Delta);
1814 if (Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Current_Min)
1815 {
1816 if (TimeStamp_InstantaneousBitRate_Current_Max<Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Current_Min || TimeStamp_InstantaneousBitRate_Current_Min>Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Current_Max)
1817 {
1818 Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_BitRateMode_IsVbr++;
1819 #if MEDIAINFO_ADVANCED
1820 if (Config_VbrDetection_GiveUp && Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_BitRateMode_IsVbr>=Config_VbrDetection_Occurences)
1821 Config->ParseSpeed=0;
1822 #endif // MEDIAINFO_ADVANCED
1823 }
1824 else
1825 Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_BitRateMode_IsCbr++;
1826 }
1827 float64 Duration_Min=(float64)(program_clock_reference-Complete_Stream->Streams[pid]->TimeStamp_End-1);
1828 float64 Duration_Raw=(float64)(program_clock_reference-Complete_Stream->Streams[pid]->TimeStamp_End);
1829 float64 Duration_Max=(float64)(program_clock_reference-Complete_Stream->Streams[pid]->TimeStamp_End+1);
1830 float64 Bytes=(float64)(File_Offset+Buffer_Offset-Complete_Stream->Streams[pid]->TimeStamp_End_Offset);
1831 float64 TimeStamp_Min=Bytes*8/Duration_Max*27000000*(1-Config_VbrDetection_Delta);
1832 float64 TimeStamp_Raw=Bytes*8/Duration_Raw*27000000;
1833 float64 TimeStamp_Max=Bytes*8/Duration_Min*27000000*(1+Config_VbrDetection_Delta);
1834 Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Current_Min=TimeStamp_Min;
1835 Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Current_Raw=TimeStamp_Raw;
1836 Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Current_Max=TimeStamp_Max;
1837 #if MEDIAINFO_ADVANCED
1838 if (Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Min_Raw>TimeStamp_InstantaneousBitRate_Current_Raw)
1839 Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Min_Raw=TimeStamp_InstantaneousBitRate_Current_Raw;
1840 if (Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Max_Raw<TimeStamp_InstantaneousBitRate_Current_Raw)
1841 Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Max_Raw=TimeStamp_InstantaneousBitRate_Current_Raw;
1842 int64u Distance=program_clock_reference-Complete_Stream->Streams[pid]->TimeStamp_End;
1843 if (Complete_Stream->Streams[pid]->TimeStamp_Distance_Min>Distance)
1844 Complete_Stream->Streams[pid]->TimeStamp_Distance_Min=Distance;
1845 if (Complete_Stream->Streams[pid]->TimeStamp_Distance_Max<Distance)
1846 Complete_Stream->Streams[pid]->TimeStamp_Distance_Max=Distance;
1847 Complete_Stream->Streams[pid]->TimeStamp_Distance_Total+=Distance;
1848 Complete_Stream->Streams[pid]->TimeStamp_Distance_Count++;
1849 #endif // MEDIAINFO_ADVANCED
1850 }
1851 #if MEDIAINFO_ADVANCED
1852 else
1853 {
1854 if (!discontinuity_indicator)
1855 Complete_Stream->Streams[pid]->TimeStamp_HasProblems++;
1856 float64 Bytes=(float64)(File_Offset+Buffer_Offset-Complete_Stream->Streams[pid]->TimeStamp_End_Offset);
1857 int64u TimeToAdd;
1858 if (Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Current_Raw)
1859 TimeToAdd=float64_int64s(Bytes*8/Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Current_Raw*27000000);
1860 else
1861 TimeToAdd=0;
1862 Complete_Stream->Streams[pid]->TimeStamp_Intermediate.push_back(Complete_Stream->Streams[pid]->TimeStamp_End+TimeToAdd);
1863 Complete_Stream->Streams[pid]->TimeStamp_Intermediate.push_back(program_clock_reference);
1864 }
1865 #endif // MEDIAINFO_ADVANCED
1866 }
1867 Complete_Stream->Streams[pid]->TimeStamp_End=program_clock_reference;
1868 Complete_Stream->Streams[pid]->TimeStamp_End_IsUpdated=true;
1869 Complete_Stream->Streams[pid]->TimeStamp_End_Offset=File_Offset+Buffer_Offset;
1870 {
1871 Status[IsUpdated]=true;
1872 Status[User_16]=true;
1873 }
1874 }
1875 }
1876 //---------------------------------------------------------------------------
Synched_Init()1877 void File_MpegTs::Synched_Init()
1878 {
1879 Begin_MaxDuration=Config->ParseSpeed>=0.8?(int64u)-1:MediaInfoLib::Config.MpegTs_MaximumScanDuration_Get()*27/1000;
1880
1881 //Config->File_Filter_Set(462);
1882 //Default values
1883 Complete_Stream=new complete_stream;
1884 Complete_Stream->Streams.resize(0x2000);
1885 for (size_t StreamID=0; StreamID<0x2000; StreamID++)
1886 Complete_Stream->Streams[StreamID]=new complete_stream::stream;
1887 Complete_Stream->Streams[0x0000]->init(0x00); // program_association_section
1888 Complete_Stream->Streams[0x0001]->init(0x01); // CA_section
1889 Complete_Stream->Streams[0x0002]->Searching_Payload_Start_Set(true);
1890 Complete_Stream->Streams[0x0002]->Kind=complete_stream::stream::psi; // Transport Stream Description Table
1891 Complete_Stream->Streams[0x0002]->Table_IDs.resize(0x100);
1892 Complete_Stream->Streams[0x0003]->Searching_Payload_Start_Set(true);
1893 Complete_Stream->Streams[0x0003]->Kind=complete_stream::stream::psi; // IPMP Control Information Table
1894 Complete_Stream->Streams[0x0003]->Table_IDs.resize(0x100);
1895
1896 //Config
1897 Config_Trace_TimeSection_OnlyFirstOccurrence=MediaInfoLib::Config.Trace_TimeSection_OnlyFirstOccurrence_Get();
1898 TimeSection_FirstOccurrenceParsed=false;
1899 #if MEDIAINFO_ADVANCED
1900 Config_VbrDetection_Delta=MediaInfoLib::Config.MpegTs_VbrDetection_Delta_Get();
1901 Config_VbrDetection_Occurences=MediaInfoLib::Config.MpegTs_VbrDetection_Occurences_Get();
1902 Config_VbrDetection_GiveUp=MediaInfoLib::Config.MpegTs_VbrDetection_GiveUp_Get();
1903 #endif // MEDIAINFO_ADVANCED
1904
1905 #ifdef MEDIAINFO_ARIBSTDB24B37_YES
1906 if (FromAribStdB24B37)
1907 {
1908 #if MEDIAINFO_EVENTS
1909 StreamIDs_Width[0]=0;
1910 #endif //MEDIAINFO_EVENTS
1911 SetAllToPES();
1912 }
1913 #endif //MEDIAINFO_ARIBSTDB24B37_YES
1914
1915 if (NoPatPmt)
1916 SetAllToPES(); //TODO: do not set up PAT ID when NoPatPmt is set
1917
1918 //Continue, again, for Duplicate and Filter
1919 Option_Manage();
1920 }
1921
1922 //***************************************************************************
1923 // Buffer - Global
1924 //***************************************************************************
1925
1926 //---------------------------------------------------------------------------
Read_Buffer_Unsynched()1927 void File_MpegTs::Read_Buffer_Unsynched()
1928 {
1929 if (Complete_Stream==NULL || Complete_Stream->Streams.empty())
1930 return;
1931
1932 for (size_t StreamID=0; StreamID<0x2000; StreamID++)//std::map<int64u, stream>::iterator Stream=Streams.begin(); Stream!=Streams.end(); Stream++)
1933 {
1934 //End timestamp is out of date
1935 #if defined(MEDIAINFO_MPEGTS_PCR_YES) || defined(MEDIAINFO_MPEGTS_PESTIMESTAMP_YES)
1936 Complete_Stream->Streams[StreamID]->Searching_TimeStamp_Start_Set(false); //No more searching start
1937 Complete_Stream->Streams[StreamID]->TimeStamp_End=(int64u)-1;
1938 Complete_Stream->Streams[StreamID]->TimeStamp_End_IsUpdated=false;
1939 Complete_Stream->Streams[StreamID]->TimeStamp_End_Offset=(int64u)-1;
1940 if (Complete_Stream->Streams[StreamID]->TimeStamp_Start!=(int64u)-1)
1941 Complete_Stream->Streams[StreamID]->Searching_TimeStamp_End_Set(true); //Searching only for a start found
1942 #endif //defined(MEDIAINFO_MPEGTS_PCR_YES) || defined(MEDIAINFO_MPEGTS_PESTIMESTAMP_YES)
1943 if (Complete_Stream->Streams[StreamID]->Parser)
1944 {
1945 #ifdef MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
1946 Complete_Stream->Streams[StreamID]->Searching_ParserTimeStamp_Start_Set(false); //No more searching start
1947 if (Complete_Stream->Streams[StreamID]->Kind==complete_stream::stream::pes
1948 && ((File_MpegPs*)Complete_Stream->Streams[StreamID]->Parser)->HasTimeStamps)
1949 Complete_Stream->Streams[StreamID]->Searching_ParserTimeStamp_End_Set(true); //Searching only for a start found
1950 #endif //MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
1951 if (File_GoTo==0)
1952 Complete_Stream->Streams[StreamID]->Parser->Unsynch_Frame_Count=0;
1953 Complete_Stream->Streams[StreamID]->Parser->Open_Buffer_Unsynch();
1954 }
1955 #if MEDIAINFO_IBIUSAGE
1956 Complete_Stream->Streams[StreamID]->Ibi_SynchronizationOffset_BeginOfFrame=(int64u)-1;
1957 for (complete_stream::stream::table_ids::iterator TableID=Complete_Stream->Streams[StreamID]->Table_IDs.begin(); TableID!=Complete_Stream->Streams[StreamID]->Table_IDs.end(); ++TableID)
1958 if (*TableID)
1959 for (complete_stream::stream::table_id::table_id_extensions::iterator TableIdExtension=(*TableID)->Table_ID_Extensions.begin(); TableIdExtension!=(*TableID)->Table_ID_Extensions.end(); ++TableIdExtension)
1960 TableIdExtension->second.version_number=(int8u)-1;
1961 #endif //MEDIAINFO_IBIUSAGE
1962 }
1963 Complete_Stream->Duration_End.clear();
1964
1965 //Clearing durations
1966 Clear(Stream_General, 0, General_Duration);
1967 Clear(Stream_General, 0, General_Duration_End);
1968 for (size_t StreamPos=0; StreamPos<Count_Get(Stream_Menu); StreamPos++)
1969 Clear(Stream_Menu, StreamPos, Menu_Duration);
1970 #if MEDIAINFO_EVENTS
1971 if (Config->Config_PerPackage)
1972 Config->Config_PerPackage->Unsynch();
1973 #endif //MEDIAINFO_EVENTS
1974 }
1975
1976 //---------------------------------------------------------------------------
Read_Buffer_Continue()1977 void File_MpegTs::Read_Buffer_Continue()
1978 {
1979 if (!IsSub)
1980 {
1981 if (Config->ParseSpeed>=1.0)
1982 Config->State_Set(((float)Buffer_TotalBytes)/File_Size);
1983 else if (Buffer_TotalBytes>MpegTs_JumpTo_Begin+MpegTs_JumpTo_End)
1984 Config->State_Set((float)0.99); //Nearly the end
1985 else
1986 Config->State_Set(((float)Buffer_TotalBytes)/(MpegTs_JumpTo_Begin+MpegTs_JumpTo_End));
1987 }
1988
1989 #if MEDIAINFO_DEMUX
1990 if (Complete_Stream && pid<0x2000 && Complete_Stream->Streams[pid]->Kind==complete_stream::stream::pes && Complete_Stream->Streams[pid]->Parser && ((File_MpegPs*)Complete_Stream->Streams[pid]->Parser)->Demux_StreamIsBeingParsed_type!=(int8u)-1)
1991 {
1992 Open_Buffer_Continue(Complete_Stream->Streams[pid]->Parser, Buffer, 0, false);
1993 PES_Parse_Finish();
1994 }
1995 #endif //MEDIAINFO_DEMUX
1996 }
1997
1998 //---------------------------------------------------------------------------
Read_Buffer_AfterParsing()1999 void File_MpegTs::Read_Buffer_AfterParsing()
2000 {
2001 if (Complete_Stream==NULL)
2002 return; //No synchronization yet
2003
2004 //Stop parsing if sream is not coherent
2005 if (!Status[IsAccepted] && Buffer_TotalBytes-Buffer_TotalBytes_FirstSynched>=MpegTs_JumpTo_Begin/4)
2006 {
2007 Reject();
2008 return;
2009 }
2010
2011 if (!Status[IsFilled])
2012 {
2013 //Test if parsing of headers is OK
2014 if ((Complete_Stream->Streams_NotParsedCount==0 && (NoPatPmt || (Complete_Stream->transport_stream_id_IsValid && Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs_NotParsedCount==0)))
2015 || (Buffer_TotalBytes-Buffer_TotalBytes_FirstSynched>=MpegTs_JumpTo_Begin && Config->ParseSpeed<0.8)
2016 || File_Offset+Buffer_Size==File_Size)
2017 {
2018 //Filling
2019 for (std::set<int16u>::iterator StreamID=Complete_Stream->PES_PIDs.begin(); StreamID!=Complete_Stream->PES_PIDs.end(); ++StreamID)
2020 {
2021 if (Complete_Stream->Streams[*StreamID]->Parser)
2022 {
2023 Fill(Complete_Stream->Streams[*StreamID]->Parser);
2024
2025 Complete_Stream->Streams[*StreamID]->Parser->Status[IsUpdated]=false;
2026 Complete_Stream->Streams[*StreamID]->IsUpdated_Info=true;
2027 }
2028
2029 for (size_t Pos=0; Pos<Complete_Stream->Streams[*StreamID]->program_numbers.size(); Pos++)
2030 Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs[Complete_Stream->Streams[*StreamID]->program_numbers[Pos]].Update_Needed_IsRegistered=true;
2031 }
2032 Complete_Stream->Streams_NotParsedCount=0;
2033 Fill();
2034
2035 //Deactivating
2036 if (Config->File_StopSubStreamAfterFilled_Get())
2037 for (std::set<int16u>::iterator StreamID=Complete_Stream->PES_PIDs.begin(); StreamID!=Complete_Stream->PES_PIDs.end(); ++StreamID)
2038 {
2039 Complete_Stream->Streams[*StreamID]->Searching_Payload_Start_Set(false);
2040 Complete_Stream->Streams[*StreamID]->Searching_Payload_Continue_Set(false);
2041 }
2042
2043 //Status
2044 Status[IsUpdated]=true;
2045 Status[User_19]=true;
2046
2047 //
2048 if (!(Buffer_TotalBytes-Buffer_TotalBytes_FirstSynched>=MpegTs_JumpTo_Begin && Config->ParseSpeed<0.8))
2049 {
2050 MpegTs_JumpTo_Begin=File_Offset+Buffer_Offset-Buffer_TotalBytes_FirstSynched;
2051 MpegTs_JumpTo_End=MpegTs_JumpTo_Begin;
2052
2053 //Avoid too short duration of the end. e.g. with quick pass, MpegTs_JumpTo_End may have content only for 2 frames which is not enough for catching an I-frame at the end of the file. Forcing to 2 seconds
2054 if (Config->ParseSpeed < 0.5)
2055 {
2056 complete_stream::streams::iterator It_End=Complete_Stream->Streams.end();
2057 for (complete_stream::streams::iterator It=Complete_Stream->Streams.begin(); It!=It_End; ++It)
2058 {
2059 complete_stream::stream* &Stream=*It;
2060
2061 if (Stream && Stream->Kind==complete_stream::stream::pes && Stream->TimeStamp_Start!=(int64u)-1 && Stream->TimeStamp_End!=(int64u)-1 && Stream->TimeStamp_Start!=Stream->TimeStamp_End)
2062 {
2063 int64u Duration=Stream->TimeStamp_End-Stream->TimeStamp_Start;
2064 if (Duration<27000000*2) // 2 seconds
2065 {
2066 int64u Ratio = 0;
2067 if (Duration)
2068 Ratio = (27000000 * 2) / Duration;
2069 MpegTs_JumpTo_End*=Ratio;
2070 if (MpegTs_JumpTo_End>MediaInfoLib::Config.MpegTs_MaximumOffset_Get()/4)
2071 MpegTs_JumpTo_End=MediaInfoLib::Config.MpegTs_MaximumOffset_Get()/4;
2072 break; //Using the first PES found
2073 }
2074 }
2075 }
2076 }
2077
2078 if (MpegTs_JumpTo_Begin+MpegTs_JumpTo_End>=File_Size)
2079 {
2080 if (MpegTs_JumpTo_Begin+MpegTs_JumpTo_End>File_Size)
2081 {
2082 MpegTs_JumpTo_Begin=File_Size;
2083 MpegTs_JumpTo_End=0;
2084 }
2085 else
2086 MpegTs_JumpTo_Begin=File_Size-MpegTs_JumpTo_End;
2087 }
2088 }
2089
2090 //Jumping
2091 if (Config->ParseSpeed<1.0 && Config->File_IsSeekable_Get()
2092 #if MEDIAINFO_ADVANCED
2093 && (!Config->File_IgnoreSequenceFileSize_Get() || Config->File_Names_Pos!=Config->File_Names.size()) // TODO: temporary disabling theses options for MPEG-TS (see above), because it does not work as expected
2094 #endif //MEDIAINFO_ADVANCED
2095 && MpegTs_ScanUpTo == (int64u)-1
2096 && File_Offset+Buffer_Size<File_Size-MpegTs_JumpTo_End && MpegTs_JumpTo_End)
2097 {
2098 #if !defined(MEDIAINFO_MPEGTS_PCR_YES) && !defined(MEDIAINFO_MPEGTS_PESTIMESTAMP_YES)
2099 GoToFromEnd(47); //TODO: Should be changed later (when Finalize stuff will be split)
2100 #else //!defined(MEDIAINFO_MPEGTS_PCR_YES) && !defined(MEDIAINFO_MPEGTS_PESTIMESTAMP_YES)
2101 #if defined(MEDIAINFO_EIA608_YES) || defined(MEDIAINFO_EIA708_YES)
2102 if (File_Offset+Buffer_Size<File_Size/2-MpegTs_JumpTo_Begin && File_Size/2+MpegTs_JumpTo_Begin<File_Size-MpegTs_JumpTo_End && ((Config->File_DtvccTransport_Stream_IsPresent && !Config->File_DtvccTransport_Descriptor_IsPresent)
2103 #if defined(MEDIAINFO_EIA608_YES)
2104 || Config->File_Scte20_IsPresent
2105 #endif //defined(MEDIAINFO_EIA608_YES)
2106 ))
2107 {
2108 MpegTs_ScanUpTo=File_Size/2+MpegTs_JumpTo_Begin;
2109 GoTo(File_Size/2-MpegTs_JumpTo_Begin);
2110 }
2111 else
2112 #endif //defined(MEDIAINFO_EIA608_YES) || defined(MEDIAINFO_EIA708_YES)
2113 GoToFromEnd(MpegTs_JumpTo_End);
2114 Searching_TimeStamp_Start=false;
2115 #endif //!defined(MEDIAINFO_MPEGTS_PCR_YES) && !defined(MEDIAINFO_MPEGTS_PESTIMESTAMP_YES)
2116 Open_Buffer_Unsynch();
2117 }
2118 }
2119 }
2120
2121 if (MpegTs_ScanUpTo != (int64u)-1 && File_Offset+Buffer_Size>=MpegTs_ScanUpTo)
2122 {
2123 MpegTs_ScanUpTo = (int64u)-1;
2124 GoToFromEnd(MpegTs_JumpTo_End);
2125 Open_Buffer_Unsynch();
2126 }
2127 }
2128
2129 //---------------------------------------------------------------------------
2130 #if MEDIAINFO_SEEK
Read_Buffer_Seek(size_t Method,int64u Value,int64u ID)2131 size_t File_MpegTs::Read_Buffer_Seek (size_t Method, int64u Value, int64u ID)
2132 {
2133 //Reset
2134 Seek_Value=(int64u)-1;
2135 Seek_ID=(int64u)-1;
2136 InfiniteLoop_Detect=0;
2137 #if MEDIAINFO_DEMUX
2138 Config->Demux_IsSeeking=false;
2139 #endif //MEDIAINFO_DEMUX
2140
2141 //Init
2142 if (!Duration_Detected)
2143 {
2144 //External IBI
2145 #if MEDIAINFO_IBIUSAGE
2146 std::string IbiFile=Config->Ibi_Get();
2147 if (!IbiFile.empty())
2148 {
2149 Ibi.Streams.clear(); //TODO: support IBI data from different inputs
2150
2151 File_Ibi MI;
2152 Open_Buffer_Init(&MI, IbiFile.size());
2153 MI.Ibi=&Ibi;
2154 MI.Open_Buffer_Continue((const int8u*)IbiFile.c_str(), IbiFile.size());
2155 }
2156 //Creating base IBI from a quick analysis of the file
2157 else
2158 {
2159 MediaInfo_Internal MI;
2160 MI.Option(__T("File_KeepInfo"), __T("1"));
2161 Ztring ParseSpeed_Save=MI.Option(__T("ParseSpeed_Get"), __T(""));
2162 Ztring Demux_Save=MI.Option(__T("Demux_Get"), __T(""));
2163 MI.Option(__T("ParseSpeed"), __T("0"));
2164 MI.Option(__T("Demux"), Ztring());
2165 Config->File_Names.Separator_Set(0, ",");
2166 Ztring File_Names=Config->File_Names.Read();
2167 MI.Option(__T("File_FileNameFormat"), __T("CSV"));
2168 size_t MiOpenResult=MI.Open(File_Names);
2169 MI.Option(__T("ParseSpeed"), ParseSpeed_Save); //This is a global value, need to reset it. TODO: local value
2170 MI.Option(__T("Demux"), Demux_Save); //This is a global value, need to reset it. TODO: local value
2171 if (!MiOpenResult)
2172 return (size_t)-1;
2173 for (ibi::streams::iterator IbiStream_Temp=((File_MpegTs*)MI.Info)->Ibi.Streams.begin(); IbiStream_Temp!=((File_MpegTs*)MI.Info)->Ibi.Streams.end(); ++IbiStream_Temp)
2174 {
2175 if (Ibi.Streams[IbiStream_Temp->first]==NULL)
2176 Ibi.Streams[IbiStream_Temp->first]=new ibi::stream(*IbiStream_Temp->second);
2177 Ibi.Streams[IbiStream_Temp->first]->Unsynch();
2178 for (size_t Pos=0; Pos<IbiStream_Temp->second->Infos.size(); Pos++)
2179 {
2180 Ibi.Streams[IbiStream_Temp->first]->Add(IbiStream_Temp->second->Infos[Pos]);
2181 if (!IbiStream_Temp->second->Infos[Pos].IsContinuous)
2182 Ibi.Streams[IbiStream_Temp->first]->Unsynch();
2183 }
2184 Ibi.Streams[IbiStream_Temp->first]->Unsynch();
2185 }
2186 if (Ibi.Streams.empty())
2187 return 4; //Problem during IBI file parsing
2188 }
2189 #endif //#if MEDIAINFO_IBIUSAGE
2190
2191 Duration_Detected=true;
2192 }
2193
2194 //Parsing
2195 switch (Method)
2196 {
2197 case 0 :
2198 GoTo(Value);
2199 Open_Buffer_Unsynch();
2200 return 1;
2201 case 1 :
2202 GoTo(File_Size*Value/10000);
2203 Open_Buffer_Unsynch();
2204 return 1;
2205 case 2 : //Timestamp
2206 #if MEDIAINFO_IBIUSAGE
2207 {
2208 ibi::streams::iterator IbiStream_Temp;
2209 if (ID==(int64u)-1)
2210 IbiStream_Temp=Ibi.Streams.begin();
2211 else
2212 IbiStream_Temp=Ibi.Streams.find(ID);
2213 if (IbiStream_Temp==Ibi.Streams.end() || IbiStream_Temp->second->Infos.empty())
2214 {
2215 for (IbiStream_Temp=Ibi.Streams.begin(); IbiStream_Temp!=Ibi.Streams.end(); ++IbiStream_Temp)
2216 if (!IbiStream_Temp->second->Infos.empty())
2217 break;
2218
2219 if (IbiStream_Temp==Ibi.Streams.end())
2220 return 5; //Invalid ID
2221 }
2222
2223 if (!(IbiStream_Temp->second->DtsFrequencyNumerator==1000000000 && IbiStream_Temp->second->DtsFrequencyDenominator==1))
2224 {
2225 float64 ValueF=(float64)Value;
2226 ValueF/=1000000000; //Value is in ns
2227 ValueF/=IbiStream_Temp->second->DtsFrequencyDenominator;
2228 ValueF*=IbiStream_Temp->second->DtsFrequencyNumerator;
2229 Value=float64_int64s(ValueF);
2230 }
2231
2232 for (size_t Pos=0; Pos<IbiStream_Temp->second->Infos.size(); Pos++)
2233 {
2234 if (Value<=IbiStream_Temp->second->Infos[Pos].Dts || Pos+1==IbiStream_Temp->second->Infos.size())
2235 {
2236 if (Value<IbiStream_Temp->second->Infos[Pos].Dts && Pos)
2237 Pos--;
2238
2239 //Checking continuity of Ibi
2240 if (!IbiStream_Temp->second->Infos[Pos].IsContinuous && Pos+1<IbiStream_Temp->second->Infos.size() && InfiniteLoop_Detect<8) //With infinite loop detect
2241 {
2242 InfiniteLoop_Detect++;
2243 Config->Demux_IsSeeking=true;
2244 Seek_Value=Value;
2245 Seek_Value_Maximal=IbiStream_Temp->second->Infos[Pos+1].StreamOffset;
2246 Seek_ID=IbiStream_Temp->first;
2247 GoTo((IbiStream_Temp->second->Infos[Pos].StreamOffset+IbiStream_Temp->second->Infos[Pos+1].StreamOffset)/2);
2248 Open_Buffer_Unsynch();
2249
2250 return 1;
2251 }
2252
2253 InfiniteLoop_Detect=0;
2254 Config->Demux_IsSeeking=false;
2255 if (Complete_Stream && Complete_Stream->Streams[(size_t)IbiStream_Temp->first] && Complete_Stream->Streams[(size_t)IbiStream_Temp->first]->Parser)
2256 Complete_Stream->Streams[(size_t)IbiStream_Temp->first]->Parser->Unsynch_Frame_Count=IbiStream_Temp->second->Infos[Pos].FrameNumber;
2257 else
2258 Unsynch_Frame_Counts[(int16u)IbiStream_Temp->first]=IbiStream_Temp->second->Infos[Pos].FrameNumber;
2259
2260 GoTo(IbiStream_Temp->second->Infos[Pos].StreamOffset);
2261 Open_Buffer_Unsynch();
2262
2263 return 1;
2264 }
2265 }
2266
2267 return 2; //Invalid value
2268 }
2269 #else //MEDIAINFO_IBIUSAGE
2270 return (size_t)-2; //Not supported / IBI disabled
2271 #endif //MEDIAINFO_IBIUSAGE
2272 case 3 : //FrameNumber
2273 #if MEDIAINFO_IBIUSAGE
2274 {
2275 ibi::streams::iterator IbiStream_Temp;
2276 if (ID==(int64u)-1)
2277 IbiStream_Temp=Ibi.Streams.begin();
2278 else
2279 IbiStream_Temp=Ibi.Streams.find(ID);
2280 if (IbiStream_Temp==Ibi.Streams.end() || IbiStream_Temp->second->Infos.empty())
2281 {
2282 for (IbiStream_Temp=Ibi.Streams.begin(); IbiStream_Temp!=Ibi.Streams.end(); ++IbiStream_Temp)
2283 if (!IbiStream_Temp->second->Infos.empty())
2284 break;
2285
2286 if (IbiStream_Temp==Ibi.Streams.end())
2287 return 5; //Invalid ID
2288 }
2289
2290 for (size_t Pos=0; Pos<IbiStream_Temp->second->Infos.size(); Pos++)
2291 {
2292 if (Value<=IbiStream_Temp->second->Infos[Pos].FrameNumber || Pos+1==IbiStream_Temp->second->Infos.size())
2293 {
2294 if (Value<IbiStream_Temp->second->Infos[Pos].FrameNumber && Pos)
2295 Pos--;
2296
2297 Config->Demux_IsSeeking=false;
2298 if (Complete_Stream && Complete_Stream->Streams[(size_t)IbiStream_Temp->first] && Complete_Stream->Streams[(size_t)IbiStream_Temp->first]->Parser)
2299 Complete_Stream->Streams[(size_t)IbiStream_Temp->first]->Parser->Unsynch_Frame_Count=IbiStream_Temp->second->Infos[Pos].FrameNumber;
2300 else
2301 Unsynch_Frame_Counts[(int16u)IbiStream_Temp->first]=IbiStream_Temp->second->Infos[Pos].FrameNumber;
2302
2303 GoTo(IbiStream_Temp->second->Infos[Pos].StreamOffset);
2304 Open_Buffer_Unsynch();
2305
2306 return 1;
2307 }
2308 }
2309
2310 return 2; //Invalid value
2311 }
2312 #else //MEDIAINFO_IBIUSAGE
2313 return (size_t)-2; //Not supported / IBI disabled
2314 #endif //MEDIAINFO_IBIUSAGE
2315 default : return (size_t)-1; //Not supported
2316 }
2317 }
2318 #endif //MEDIAINFO_SEEK
2319
2320 //***************************************************************************
2321 // Buffer - File header
2322 //***************************************************************************
2323
2324 //---------------------------------------------------------------------------
FileHeader_Begin()2325 bool File_MpegTs::FileHeader_Begin()
2326 {
2327 if (Buffer_Size<8)
2328 return false; //Wait for more data
2329
2330 //False positives detection: detect some headers from other files, DV parser is not smart enough
2331 if (CC8(Buffer+Buffer_Offset)==0x444C472056312E30LL //DLG
2332 || CC4(Buffer)==0x52494646 //RIFF
2333 || CC4(Buffer+4)==0x66747970 //ftyp
2334 || CC4(Buffer+4)==0x66726565 //free
2335 || CC4(Buffer+4)==0x6D646174 //mdat
2336 || CC4(Buffer+4)==0x6D6F6F76 //moov
2337 || CC4(Buffer+4)==0x736B6970 //skip
2338 || CC4(Buffer+4)==0x77696465 //wide
2339 || CC4(Buffer)==0x060E2B34) //MXF begin
2340 {
2341 Reject("MPEG-TS");
2342 return true;
2343 }
2344
2345 //Configuring
2346 #if defined(MEDIAINFO_BDAV_YES) || defined(MEDIAINFO_TSP_YES)
2347 TS_Size=188
2348 #if defined(MEDIAINFO_BDAV_YES)
2349 +BDAV_Size
2350 #endif
2351 #if defined(MEDIAINFO_TSP_YES)
2352 +TSP_Size
2353 #endif
2354 ;
2355 #endif
2356
2357 //Configuration
2358 Option_Manage();
2359
2360 return true;
2361 }
2362
2363 //***************************************************************************
2364 // Buffer - Per element
2365 //***************************************************************************
2366
2367 //---------------------------------------------------------------------------
Header_Parse()2368 void File_MpegTs::Header_Parse()
2369 {
2370 #if MEDIAINFO_TRACE
2371 if (Trace_Activated)
2372 {
2373 //Parsing
2374 bool adaptation, payload;
2375 if (BDAV_Size)
2376 Skip_B4( "BDAV"); //BDAV supplement
2377 Skip_B1( "sync_byte");
2378 BS_Begin();
2379 Skip_SB( "transport_error_indicator");
2380 Get_SB ( payload_unit_start_indicator, "payload_unit_start_indicator");
2381 Skip_SB( "transport_priority");
2382 Get_S2 (13, pid, "pid");
2383 Get_S1 ( 2, transport_scrambling_control, "transport_scrambling_control");
2384 Get_SB ( adaptation, "adaptation_field_control (adaptation)");
2385 Get_SB ( payload, "adaptation_field_control (payload)");
2386 Skip_S1( 4, "continuity_counter");
2387 BS_End();
2388
2389 //Info
2390 /* Trace: used to display program number(s)
2391 if (!Complete_Stream->Streams[pid]->program_numbers.empty())
2392 {
2393 Ztring Program_Numbers;
2394 for (size_t Pos=0; Pos<Complete_Stream->Streams[pid]->program_numbers.size(); Pos++)
2395 Program_Numbers+=Ztring::ToZtring_From_CC2(Complete_Stream->Streams[pid]->program_numbers[Pos])+__T('/');
2396 if (!Program_Numbers.empty())
2397 Program_Numbers.resize(Program_Numbers.size()-1);
2398 Data_Info(Program_Numbers);
2399 }
2400 else
2401 Data_Info(" ");
2402 */
2403 Data_Info(Complete_Stream->Streams[pid]->Element_Info1);
2404
2405 //Adaptation
2406 if (adaptation)
2407 Header_Parse_AdaptationField();
2408 else
2409 {
2410 }
2411
2412 //Data
2413 if (payload)
2414 {
2415 //Encryption
2416 if (transport_scrambling_control>0)
2417 Complete_Stream->Streams[pid]->Scrambled_Count++;
2418 }
2419 else if (Element_Offset+TSP_Size<TS_Size)
2420 Skip_XX(TS_Size-Element_Offset-TSP_Size, "Junk");
2421
2422 //Filling
2423 Header_Fill_Code(pid, __T("0x")+Ztring().From_CC2(pid));
2424 Header_Fill_Size(TS_Size);
2425
2426 Header_Parse_Events();
2427 }
2428 else
2429 {
2430 #endif //MEDIAINFO_TRACE
2431 //Parsing
2432 payload_unit_start_indicator=(Buffer[Buffer_Offset+BDAV_Size+1]&0x40)!=0;
2433 transport_scrambling_control= Buffer[Buffer_Offset+BDAV_Size+3]&0xC0;
2434 bool adaptation= (Buffer[Buffer_Offset+BDAV_Size+3]&0x20)!=0;
2435 bool payload= (Buffer[Buffer_Offset+BDAV_Size+3]&0x10)!=0;
2436 Element_Offset+=BDAV_Size+4;
2437
2438 //Adaptation
2439 if (adaptation)
2440 Header_Parse_AdaptationField();
2441 else
2442 {
2443 }
2444
2445 //Data
2446 if (payload)
2447 {
2448 //Encryption
2449 if (transport_scrambling_control>0)
2450 Complete_Stream->Streams[pid]->Scrambled_Count++;
2451 }
2452
2453 //Filling
2454 /*Element[1].Next=File_Offset+Buffer_Offset+TS_Size; //*/Header_Fill_Size(TS_Size);
2455 //Element[1].IsComplete=true; //Header_Fill_Size(TS_Size);
2456
2457 Header_Parse_Events();
2458 #if MEDIAINFO_TRACE
2459 }
2460 #endif //MEDIAINFO_TRACE
2461 }
2462
2463 //---------------------------------------------------------------------------
Header_Parse_AdaptationField()2464 void File_MpegTs::Header_Parse_AdaptationField()
2465 {
2466 #if MEDIAINFO_TRACE
2467 if (Trace_Activated)
2468 {
2469 int64u Element_Pos_Save=Element_Offset;
2470 Element_Begin1("adaptation_field");
2471 int8u adaptation_field_length;
2472 Get_B1 (adaptation_field_length, "adaptation_field_length");
2473 if (adaptation_field_length>188-4-1) //TS size - header - adaptation_field_length
2474 {
2475 adaptation_field_length=188-4-1;
2476 Skip_XX(188-4-1, "stuffing_bytes");
2477 }
2478 else if (adaptation_field_length>0)
2479 {
2480 bool discontinuity_indicator, PCR_flag, OPCR_flag, splicing_point_flag, transport_private_data_flag, adaptation_field_extension_flag;
2481 BS_Begin();
2482 Get_SB ( discontinuity_indicator, "discontinuity_indicator");
2483 Skip_SB( "random_access_indicator");
2484 Skip_SB( "elementary_stream_priority_indicator");
2485 Get_SB ( PCR_flag, "PCR_flag");
2486 Get_SB ( OPCR_flag, "OPCR_flag");
2487 Get_SB ( splicing_point_flag, "splicing_point_flag");
2488 Get_SB ( transport_private_data_flag, "transport_private_data_flag");
2489 Get_SB ( adaptation_field_extension_flag, "adaptation_field_extension_flag");
2490 BS_End();
2491 if (PCR_flag)
2492 {
2493 #ifdef MEDIAINFO_MPEGTS_PCR_YES
2494 BS_Begin();
2495 int64u program_clock_reference_base;
2496 int16u program_clock_reference_extension;
2497 Get_S8 (33, program_clock_reference_base, "program_clock_reference_base"); Param_Info_From_Milliseconds(program_clock_reference_base/90);
2498 Data_Info_From_Milliseconds(program_clock_reference_base/90);
2499 Skip_S1( 6, "reserved");
2500 Get_S2 ( 9, program_clock_reference_extension, "program_clock_reference_extension");
2501 int64u program_clock_reference=program_clock_reference_base*300+program_clock_reference_extension;
2502 Param_Info1(program_clock_reference);
2503 BS_End();
2504 if (Complete_Stream->Streams[pid]->Searching_TimeStamp_End
2505 #ifdef MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
2506 && (!Complete_Stream->Streams[pid]->Searching_ParserTimeStamp_End
2507 || Complete_Stream->Streams[pid]->IsPCR) //If PCR, we always want it.
2508 #endif //MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
2509 )
2510 {
2511 Header_Parse_Events_Duration_Helper(program_clock_reference,discontinuity_indicator);
2512 }
2513 if (Complete_Stream->Streams[pid]->Searching_TimeStamp_Start)
2514 {
2515 //This is the first PCR
2516 Complete_Stream->Streams[pid]->TimeStamp_Start=program_clock_reference;
2517 Complete_Stream->Streams[pid]->TimeStamp_Start_Offset=File_Offset+Buffer_Offset;
2518 Complete_Stream->Streams[pid]->TimeStamp_End=program_clock_reference;
2519 Complete_Stream->Streams[pid]->TimeStamp_End_IsUpdated=true;
2520 Complete_Stream->Streams[pid]->TimeStamp_End_Offset=File_Offset+Buffer_Offset;
2521 Complete_Stream->Streams[pid]->Searching_TimeStamp_Start_Set(false);
2522 Complete_Stream->Streams[pid]->Searching_TimeStamp_End_Set(true);
2523 Complete_Stream->Streams_With_StartTimeStampCount++;
2524 {
2525 Status[IsUpdated]=true;
2526 Status[User_16]=true;
2527 }
2528 }
2529
2530 //Test if we can find the TS bitrate
2531 if (!Complete_Stream->Streams[pid]->EndTimeStampMoreThanxSeconds && Complete_Stream->Streams[pid]->TimeStamp_Start!=(int64u)-1
2532 && (File_Offset+Buffer_Offset-Buffer_TotalBytes_FirstSynched)*2<File_Size)
2533 {
2534 if (program_clock_reference<Complete_Stream->Streams[pid]->TimeStamp_Start)
2535 {
2536 if (Complete_Stream->Streams[pid]->TimeStamp_Start-program_clock_reference<10LL*90000*300) //Testing if difference is less that 10 seconds (value arbitrary choosen)
2537 Complete_Stream->Streams[pid]->TimeStamp_Start=program_clock_reference; //Looks like we have a small jump in the past in a buggy file, accepting it.
2538 else
2539 program_clock_reference+=0x200000000LL*300; //33 bits, cyclic
2540 }
2541 if ((program_clock_reference-Complete_Stream->Streams[pid]->TimeStamp_Start)>Begin_MaxDuration)
2542 {
2543 Complete_Stream->Streams[pid]->EndTimeStampMoreThanxSeconds=true;
2544 Complete_Stream->Streams_With_EndTimeStampMoreThanxSecondsCount++;
2545 if (Complete_Stream->Streams_NotParsedCount
2546 && Complete_Stream->Streams_With_StartTimeStampCount>0
2547 && Complete_Stream->Streams_With_StartTimeStampCount==Complete_Stream->Streams_With_EndTimeStampMoreThanxSecondsCount)
2548 {
2549 //We are already parsing 16 seconds (for all PCRs), we don't hope to have more info
2550 MpegTs_JumpTo_Begin=File_Offset+Buffer_Offset-Buffer_TotalBytes_FirstSynched;
2551 MpegTs_JumpTo_End=MpegTs_JumpTo_Begin;
2552 if (MpegTs_JumpTo_Begin+MpegTs_JumpTo_End>=File_Size)
2553 {
2554 if (MpegTs_JumpTo_Begin+MpegTs_JumpTo_End>File_Size)
2555 {
2556 MpegTs_JumpTo_Begin=File_Size;
2557 MpegTs_JumpTo_End=0;
2558 }
2559 else
2560 MpegTs_JumpTo_Begin=File_Size-MpegTs_JumpTo_End;
2561 }
2562 }
2563 }
2564 }
2565 #else //MEDIAINFO_MPEGTS_PCR_YES
2566 Skip_B6( "program_clock_reference");
2567 #endif //MEDIAINFO_MPEGTS_PCR_YES
2568 }
2569 if (OPCR_flag)
2570 {
2571 BS_Begin();
2572 Skip_S8(33, "original_program_clock_reference_base");
2573 Skip_S1( 6, "reserved");
2574 Skip_S2( 9, "original_program_clock_reference_extension");
2575 BS_End();
2576 }
2577 if (splicing_point_flag)
2578 {
2579 Skip_B1( "splice_countdown");
2580 }
2581 if (transport_private_data_flag)
2582 {
2583 int8u transport_private_data_length;
2584 Get_B1 (transport_private_data_length, "transport_private_data_length");
2585 if (Element_Offset+transport_private_data_length<=Element_Pos_Save+1+adaptation_field_length)
2586 transport_private_data(transport_private_data_length);
2587 else
2588 Skip_XX(Element_Pos_Save+1+adaptation_field_length-Element_Offset, "problem");
2589 }
2590 if (adaptation_field_extension_flag)
2591 {
2592 int8u adaptation_field_extension_length;
2593 Get_B1 (adaptation_field_extension_length, "adaptation_field_extension_length");
2594 if (Element_Offset+adaptation_field_extension_length<=Element_Pos_Save+1+adaptation_field_length)
2595 {
2596 Element_Begin1("adaptation_field_extension");
2597 int64u End=Element_Offset+adaptation_field_extension_length;
2598 bool ltw_flag, piecewise_rate_flag, seamless_splice_flag;
2599 BS_Begin();
2600 Get_SB ( ltw_flag, "ltw_flag");
2601 Get_SB ( piecewise_rate_flag, "piecewise_rate_flag");
2602 Get_SB ( seamless_splice_flag, "seamless_splice_flag");
2603 Skip_S1( 5, "reserved");
2604 if (ltw_flag)
2605 {
2606 Skip_SB( "ltw_valid_flag");
2607 Skip_S2(15, "ltw_offset");
2608 }
2609 if (piecewise_rate_flag)
2610 {
2611 Skip_S1( 2, "reserved");
2612 Skip_S3(22, "piecewise_rate");
2613 }
2614 if (seamless_splice_flag)
2615 {
2616 Skip_S1( 4, "splice_type");
2617 int16u DTS_29, DTS_14;
2618 int8u DTS_32;
2619 Element_Begin1("DTS");
2620 Get_S1 ( 3, DTS_32, "DTS_32");
2621 Mark_1();
2622 Get_S2 (15, DTS_29, "DTS_29");
2623 Mark_1();
2624 Get_S2 (15, DTS_14, "DTS_14");
2625 Mark_1();
2626
2627 //Filling
2628 int64u DTS;
2629 DTS=(((int64u)DTS_32)<<30)
2630 | (((int64u)DTS_29)<<15)
2631 | (((int64u)DTS_14));
2632 Element_Info_From_Milliseconds(DTS/90);
2633 Element_End0();
2634 }
2635 BS_End();
2636 if (Element_Offset<End)
2637 Skip_XX(End-Element_Offset, "reserved");
2638 Element_End0();
2639 }
2640 else
2641 Skip_XX(Element_Pos_Save+1+adaptation_field_length-Element_Offset, "problem");
2642 }
2643 }
2644
2645 if (Element_Offset<Element_Pos_Save+1+adaptation_field_length)
2646 Skip_XX(Element_Pos_Save+1+adaptation_field_length-Element_Offset, "stuffing_bytes");
2647 Element_End0();
2648 }
2649 else
2650 {
2651 #endif //MEDIAINFO_TRACE
2652 int8u adaptation_field_length=Buffer[Buffer_Offset+BDAV_Size+4];
2653 #ifdef MEDIAINFO_MPEGTS_PCR_YES
2654 if (adaptation_field_length>188-4-1) //TS size - header - adaptation_field_length
2655 adaptation_field_length=188-4-1;
2656 else if (adaptation_field_length)
2657 {
2658 bool discontinuity_indicator=(Buffer[Buffer_Offset+BDAV_Size+5]&0x80)!=0;
2659 bool PCR_flag=(Buffer[Buffer_Offset+BDAV_Size+5]&0x10)!=0;
2660 bool OPCR_flag=(Buffer[Buffer_Offset+BDAV_Size+5]&0x08)!=0;
2661 bool splicing_point_flag=(Buffer[Buffer_Offset+BDAV_Size+5]&0x04)!=0;
2662 bool transport_private_data_flag=(Buffer[Buffer_Offset+BDAV_Size+5]&0x02)!=0;
2663 if (PCR_flag)
2664 {
2665 int64u program_clock_reference=( (((int64u)Buffer[Buffer_Offset+BDAV_Size+6])<<25)
2666 | (((int64u)Buffer[Buffer_Offset+BDAV_Size+7])<<17)
2667 | (((int64u)Buffer[Buffer_Offset+BDAV_Size+8])<< 9)
2668 | (((int64u)Buffer[Buffer_Offset+BDAV_Size+9])<< 1)
2669 | (((int64u)Buffer[Buffer_Offset+BDAV_Size+10])>>7));
2670 program_clock_reference*=300;
2671 program_clock_reference+=( (((int64u)Buffer[Buffer_Offset+BDAV_Size+10]&0x01)<<8)
2672 | (((int64u)Buffer[Buffer_Offset+BDAV_Size+11]) ));
2673 if (Complete_Stream->Streams[pid]->Searching_TimeStamp_End
2674 #ifdef MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
2675 && (!Complete_Stream->Streams[pid]->Searching_ParserTimeStamp_End
2676 || Complete_Stream->Streams[pid]->IsPCR) //If PCR, we always want it.
2677 #endif //MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
2678 )
2679 {
2680 Header_Parse_Events_Duration(program_clock_reference);
2681 if (program_clock_reference!=Complete_Stream->Streams[pid]->TimeStamp_End) //Some PCRs are buggy (low precision), using the first stream offset in the case of duplicate PCR value
2682 {
2683 if (Complete_Stream->Streams[pid]->TimeStamp_End_Offset!=(int64u)-1)
2684 {
2685 if (program_clock_reference+0x12c00000000LL<Complete_Stream->Streams[pid]->TimeStamp_End)
2686 program_clock_reference+=0x25800000000LL; //33 bits and *300
2687 if (!discontinuity_indicator && program_clock_reference>Complete_Stream->Streams[pid]->TimeStamp_End && program_clock_reference<Complete_Stream->Streams[pid]->TimeStamp_End+10*27000000) //Not before, not after 10 seconds, else there is a problem
2688 {
2689 float64 Duration_InstantaneousBitRate_Min=(float64)(program_clock_reference-Complete_Stream->Streams[pid]->TimeStamp_End-(Config_VbrDetection_Delta?0:810));
2690 float64 Duration_InstantaneousBitRate_Max=(float64)(program_clock_reference-Complete_Stream->Streams[pid]->TimeStamp_End+(Config_VbrDetection_Delta?0:810));
2691 float64 Bytes_InstantaneousBitRate=(float64)(File_Offset+Buffer_Offset-Complete_Stream->Streams[pid]->TimeStamp_End_Offset);
2692 float64 TimeStamp_InstantaneousBitRate_Current_Min=Bytes_InstantaneousBitRate*8/Duration_InstantaneousBitRate_Max*27000000*(1-Config_VbrDetection_Delta);
2693 float64 TimeStamp_InstantaneousBitRate_Current_Max=Bytes_InstantaneousBitRate*8/Duration_InstantaneousBitRate_Min*27000000*(1+Config_VbrDetection_Delta);
2694 if (Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Current_Min)
2695 {
2696 if (TimeStamp_InstantaneousBitRate_Current_Max<Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Current_Min || TimeStamp_InstantaneousBitRate_Current_Min>Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Current_Max)
2697 {
2698 Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_BitRateMode_IsVbr++;
2699 #if MEDIAINFO_ADVANCED
2700 if (Config_VbrDetection_GiveUp && Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_BitRateMode_IsVbr>=Config_VbrDetection_Occurences)
2701 Config->ParseSpeed=0;
2702 #endif // MEDIAINFO_ADVANCED
2703 }
2704 else
2705 Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_BitRateMode_IsCbr++;
2706 }
2707 float64 Duration_Min=(float64)(program_clock_reference-Complete_Stream->Streams[pid]->TimeStamp_End-1);
2708 float64 Duration_Raw=(float64)(program_clock_reference-Complete_Stream->Streams[pid]->TimeStamp_End);
2709 float64 Duration_Max=(float64)(program_clock_reference-Complete_Stream->Streams[pid]->TimeStamp_End+1);
2710 float64 Bytes=(float64)(File_Offset+Buffer_Offset-Complete_Stream->Streams[pid]->TimeStamp_End_Offset);
2711 float64 InstantaneousBitRate_Min=Bytes*8/Duration_Max*27000000*(1-Config_VbrDetection_Delta);
2712 float64 InstantaneousBitRate_Raw=Bytes*8/Duration_Raw*27000000;
2713 float64 InstantaneousBitRate_Max=Bytes*8/Duration_Min*27000000*(1+Config_VbrDetection_Delta);
2714 Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Current_Min=InstantaneousBitRate_Min;
2715 Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Current_Raw=InstantaneousBitRate_Raw;
2716 Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Current_Max=InstantaneousBitRate_Max;
2717 #if MEDIAINFO_ADVANCED
2718 if (Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Min_Raw>InstantaneousBitRate_Raw)
2719 Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Min_Raw=InstantaneousBitRate_Raw;
2720 if (Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Max_Raw<InstantaneousBitRate_Raw)
2721 Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Max_Raw=InstantaneousBitRate_Raw;
2722 int64u Distance=program_clock_reference-Complete_Stream->Streams[pid]->TimeStamp_End;
2723 if (Complete_Stream->Streams[pid]->TimeStamp_Distance_Min>Distance)
2724 Complete_Stream->Streams[pid]->TimeStamp_Distance_Min=Distance;
2725 if (Complete_Stream->Streams[pid]->TimeStamp_Distance_Max<Distance)
2726 Complete_Stream->Streams[pid]->TimeStamp_Distance_Max=Distance;
2727 Complete_Stream->Streams[pid]->TimeStamp_Distance_Total+=Distance;
2728 Complete_Stream->Streams[pid]->TimeStamp_Distance_Count++;
2729 #endif // MEDIAINFO_ADVANCED
2730 }
2731 #if MEDIAINFO_ADVANCED
2732 else
2733 {
2734 if (!discontinuity_indicator)
2735 Complete_Stream->Streams[pid]->TimeStamp_HasProblems++;
2736 float64 Bytes=(float64)(File_Offset+Buffer_Offset-Complete_Stream->Streams[pid]->TimeStamp_End_Offset);
2737 int64u TimeToAdd;
2738 if (Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Current_Raw)
2739 TimeToAdd=float64_int64s(Bytes*8/Complete_Stream->Streams[pid]->TimeStamp_InstantaneousBitRate_Current_Raw*27000000);
2740 else
2741 TimeToAdd=0;
2742 Complete_Stream->Streams[pid]->TimeStamp_Intermediate.push_back(Complete_Stream->Streams[pid]->TimeStamp_End+TimeToAdd);
2743 Complete_Stream->Streams[pid]->TimeStamp_Intermediate.push_back(program_clock_reference);
2744 }
2745 #endif // MEDIAINFO_ADVANCED
2746 }
2747 Complete_Stream->Streams[pid]->TimeStamp_End=program_clock_reference;
2748 Complete_Stream->Streams[pid]->TimeStamp_End_IsUpdated=true;
2749 Complete_Stream->Streams[pid]->TimeStamp_End_Offset=File_Offset+Buffer_Offset;
2750 {
2751 Status[IsUpdated]=true;
2752 Status[User_16]=true;
2753 }
2754 }
2755 }
2756 if (Complete_Stream->Streams[pid]->Searching_TimeStamp_Start)
2757 {
2758 //This is the first PCR
2759 Complete_Stream->Streams[pid]->TimeStamp_Start=program_clock_reference;
2760 Complete_Stream->Streams[pid]->TimeStamp_Start_Offset=File_Offset+Buffer_Offset;
2761 Complete_Stream->Streams[pid]->TimeStamp_End=program_clock_reference;
2762 Complete_Stream->Streams[pid]->TimeStamp_End_IsUpdated=true;
2763 Complete_Stream->Streams[pid]->TimeStamp_End_Offset=File_Offset+Buffer_Offset;
2764 Complete_Stream->Streams[pid]->Searching_TimeStamp_Start_Set(false);
2765 Complete_Stream->Streams[pid]->Searching_TimeStamp_End_Set(true);
2766 Complete_Stream->Streams_With_StartTimeStampCount++;
2767 {
2768 Status[IsUpdated]=true;
2769 Status[User_16]=true;
2770 }
2771 }
2772
2773 //Test if we can find the TS bitrate
2774 if (!Complete_Stream->Streams[pid]->EndTimeStampMoreThanxSeconds && Complete_Stream->Streams[pid]->TimeStamp_Start!=(int64u)-1
2775 && (File_Offset+Buffer_Offset-Buffer_TotalBytes_FirstSynched)*2<File_Size)
2776 {
2777 if (program_clock_reference<Complete_Stream->Streams[pid]->TimeStamp_Start)
2778 {
2779 if (Complete_Stream->Streams[pid]->TimeStamp_Start-program_clock_reference<10LL*90000*300) //Testing if difference is less that 10 seconds (value arbitrary choosen)
2780 Complete_Stream->Streams[pid]->TimeStamp_Start=program_clock_reference; //Looks like we have a small jump in the past in a buggy file, accepting it.
2781 else
2782 program_clock_reference+=0x200000000LL*300; //33 bits, cyclic
2783 }
2784 if ((program_clock_reference-Complete_Stream->Streams[pid]->TimeStamp_Start)>Begin_MaxDuration)
2785 {
2786 Complete_Stream->Streams[pid]->EndTimeStampMoreThanxSeconds=true;
2787 Complete_Stream->Streams_With_EndTimeStampMoreThanxSecondsCount++;
2788 if (Complete_Stream->Streams_NotParsedCount
2789 && Complete_Stream->Streams_With_StartTimeStampCount>0
2790 && Complete_Stream->Streams_With_StartTimeStampCount==Complete_Stream->Streams_With_EndTimeStampMoreThanxSecondsCount)
2791 {
2792 //We are already parsing 16 seconds (for all PCRs), we don't hope to have more info
2793 MpegTs_JumpTo_Begin=File_Offset+Buffer_Offset-Buffer_TotalBytes_FirstSynched;
2794 MpegTs_JumpTo_End=MpegTs_JumpTo_Begin;
2795 if (MpegTs_JumpTo_Begin+MpegTs_JumpTo_End>=File_Size)
2796 {
2797 if (MpegTs_JumpTo_Begin+MpegTs_JumpTo_End>File_Size)
2798 {
2799 MpegTs_JumpTo_Begin=File_Size;
2800 MpegTs_JumpTo_End=0;
2801 }
2802 else
2803 MpegTs_JumpTo_Begin=File_Size-MpegTs_JumpTo_End;
2804 }
2805 }
2806 }
2807 }
2808 }
2809 if (transport_private_data_flag && adaptation_field_length>1+(PCR_flag?6:0)+(OPCR_flag?6:0)+(splicing_point_flag?1:0)+1)
2810 {
2811 int8u transport_private_data_length=Buffer[Buffer_Offset+BDAV_Size+5+1+(PCR_flag?6:0)+(OPCR_flag?6:0)+(splicing_point_flag?1:0)];
2812 if (1+(PCR_flag?6:0)+(OPCR_flag?6:0)+(splicing_point_flag?1:0)+1+transport_private_data_length<=adaptation_field_length)
2813 {
2814 int64u Element_Offset_Save=Element_Offset;
2815 Element_Offset=5+1+(PCR_flag?6:0)+(OPCR_flag?6:0)+(splicing_point_flag?1:0)+1;
2816 transport_private_data(transport_private_data_length);
2817 Element_Offset=Element_Offset_Save;
2818 }
2819 }
2820 }
2821 #endif //MEDIAINFO_MPEGTS_PCR_YES
2822 Element_Offset+=1+adaptation_field_length;
2823 #if MEDIAINFO_TRACE
2824 }
2825 #endif //MEDIAINFO_TRACE
2826 }
2827
2828 //---------------------------------------------------------------------------
2829 #if MEDIAINFO_EVENTS
Header_Parse_Events()2830 void File_MpegTs::Header_Parse_Events()
2831 {
2832 }
2833 #endif //MEDIAINFO_EVENTS
2834
2835 //---------------------------------------------------------------------------
2836 #if MEDIAINFO_EVENTS
Header_Parse_Events_Duration(int64u program_clock_reference)2837 void File_MpegTs::Header_Parse_Events_Duration(int64u program_clock_reference)
2838 {
2839 }
2840 #endif //MEDIAINFO_EVENTS
2841
2842 //---------------------------------------------------------------------------
2843 #if MEDIAINFO_ADVANCED2
Read_Buffer_SegmentChange()2844 void File_MpegTs::Read_Buffer_SegmentChange()
2845 {
2846 if (Complete_Stream==NULL || Complete_Stream->Streams.empty())
2847 return;
2848
2849 for (size_t StreamID=0; StreamID<0x2000; StreamID++)//std::map<int64u, stream>::iterator Stream=Streams.begin(); Stream!=Streams.end(); Stream++)
2850 if (Complete_Stream->Streams[StreamID]->Parser)
2851 Complete_Stream->Streams[StreamID]->Parser->Open_Buffer_SegmentChange();
2852 }
2853 #endif //MEDIAINFO_ADVANCED2
2854
2855 //---------------------------------------------------------------------------
Data_Parse()2856 void File_MpegTs::Data_Parse()
2857 {
2858 //Counting
2859 Frame_Count++;
2860
2861 //TSP specific
2862 if (TSP_Size)
2863 Element_Size-=TSP_Size;
2864
2865 #if MEDIAINFO_DUPLICATE
2866 if (Complete_Stream->Streams[pid]->ShouldDuplicate)
2867 File__Duplicate_Write();
2868 #endif //MEDIAINFO_DUPLICATE
2869
2870 //Parsing
2871 if (!Complete_Stream->Streams[pid]->Searching_Payload_Start
2872 && !Complete_Stream->Streams[pid]->Searching_Payload_Continue
2873 #ifdef MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
2874 && !Complete_Stream->Streams[pid]->Searching_ParserTimeStamp_Start
2875 && !Complete_Stream->Streams[pid]->Searching_ParserTimeStamp_End
2876 #endif //MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
2877 )
2878 Skip_XX(Element_Size, "data");
2879 else
2880 switch (Complete_Stream->Streams[pid]->Kind)
2881 {
2882 case complete_stream::stream::pes : PES(); break;
2883 case complete_stream::stream::psi : PSI(); break;
2884 default: ;
2885 }
2886
2887 //TSP specific
2888 if (TSP_Size)
2889 {
2890 Element_Size+=TSP_Size;
2891 switch(TSP_Size)
2892 {
2893 case 16: Skip_B16( "TSP"); break; //TSP supplement
2894 default: Skip_XX(TSP_Size, "TSP");
2895 }
2896 }
2897 }
2898
2899 //***************************************************************************
2900 // Elements
2901 //***************************************************************************
2902
2903 //---------------------------------------------------------------------------
PES()2904 void File_MpegTs::PES()
2905 {
2906 //Info
2907 DETAILS_INFO(if (Complete_Stream->transport_stream_id_IsValid) Element_Info1(Mpeg_Psi_stream_type_Info(Complete_Stream->Streams[pid]->stream_type, Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs[Complete_Stream->Streams[pid]->program_numbers[0]].registration_format_identifier));)
2908
2909 //Demux
2910 #if MEDIAINFO_DEMUX
2911 Element_Code=pid;
2912 Demux(Buffer+Buffer_Offset, (size_t)Element_Size, ContentType_MainStream);
2913 #endif //MEDIAINFO_DEMUX
2914
2915 //Exists
2916 if (!Complete_Stream->Streams[pid]->IsRegistered)
2917 {
2918 Complete_Stream->Streams[pid]->IsRegistered=true;
2919 for (size_t Pos=0; Pos<Complete_Stream->Streams[pid]->program_numbers.size(); Pos++)
2920 if (!Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs[Complete_Stream->Streams[pid]->program_numbers[Pos]].IsRegistered)
2921 {
2922 Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs[Complete_Stream->Streams[pid]->program_numbers[Pos]].Update_Needed_IsRegistered=true;
2923
2924 Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs[Complete_Stream->Streams[pid]->program_numbers[Pos]].IsRegistered=true;
2925 }
2926
2927 Complete_Stream->Streams[pid]->IsUpdated_IsRegistered=true;
2928 Complete_Stream->PES_PIDs.insert(pid);
2929
2930 Status[IsUpdated]=true;
2931 Status[User_19]=true;
2932 }
2933
2934 //Case of encrypted streams
2935 if (transport_scrambling_control)
2936 {
2937 if (!Complete_Stream->Streams[pid]->Searching_Payload_Continue)
2938 Complete_Stream->Streams[pid]->Searching_Payload_Continue_Set(true); //In order to count the packets
2939
2940 if (Complete_Stream->Streams[pid]->Scrambled_Count>16)
2941 {
2942 //Don't need anymore
2943 Complete_Stream->Streams[pid]->Searching_Payload_Start_Set(false);
2944 Complete_Stream->Streams[pid]->Searching_Payload_Continue_Set(false);
2945 #ifdef MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
2946 Complete_Stream->Streams[pid]->Searching_ParserTimeStamp_Start_Set(false);
2947 #endif //MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
2948 if (!Complete_Stream->Streams[pid]->IsParsed && Complete_Stream->Streams_NotParsedCount)
2949 {
2950 Complete_Stream->Streams[pid]->IsParsed=true;
2951 Complete_Stream->Streams_NotParsedCount--;
2952 }
2953 }
2954 Skip_XX(Element_Size-Element_Offset, "Scrambled data");
2955
2956 return;
2957 }
2958 else if (Complete_Stream->Streams[pid]->Scrambled_Count)
2959 Complete_Stream->Streams[pid]->Scrambled_Count--;
2960
2961 //Parser creation
2962 if (Complete_Stream->Streams[pid]->Parser==NULL)
2963 {
2964 //Waiting for first payload_unit_start_indicator
2965 if (!payload_unit_start_indicator)
2966 {
2967 Element_DoNotShow(); //We don't want to show this item because there is no interessant info
2968 return; //This is not the start of the PES
2969 }
2970
2971 //If unknown stream_type
2972 if (Complete_Stream->transport_stream_id_IsValid
2973 && Mpeg_Psi_stream_type_StreamKind(Complete_Stream->Streams[pid]->stream_type, Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs[Complete_Stream->Streams[pid]->program_numbers[0]].registration_format_identifier)==Stream_Max
2974 && Complete_Stream->Streams[pid]->stream_type!=0x06 //Exception for private data
2975 && Complete_Stream->Streams[pid]->stream_type<=0x7F //Exception for private data
2976 && Mpeg_Descriptors_registration_format_identifier_StreamKind(Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs[Complete_Stream->Streams[pid]->program_numbers[0]].registration_format_identifier)==Stream_Max //From Descriptor
2977 && Config->File_MpegTs_stream_type_Trust_Get())
2978 {
2979 Complete_Stream->Streams[pid]->Searching_Payload_Start_Set(false);
2980 Complete_Stream->Streams[pid]->Searching_Payload_Continue_Set(false);
2981 #ifdef MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
2982 Complete_Stream->Streams[pid]->Searching_ParserTimeStamp_Start_Set(false);
2983 Complete_Stream->Streams[pid]->Searching_ParserTimeStamp_End_Set(false);
2984 #endif //MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
2985 if (!Complete_Stream->Streams[pid]->IsParsed && Complete_Stream->Streams_NotParsedCount)
2986 {
2987 Complete_Stream->Streams[pid]->IsParsed=true;
2988 Complete_Stream->Streams_NotParsedCount--;
2989 }
2990 return;
2991 }
2992
2993 //Allocating an handle if needed
2994 #if defined(MEDIAINFO_MPEGPS_YES)
2995 Complete_Stream->Streams[pid]->Parser=new File_MpegPs;
2996 #if MEDIAINFO_SEEK
2997 if (Unsynch_Frame_Counts.find(pid)!=Unsynch_Frame_Counts.end())
2998 {
2999 ((File_MpegPs*)Complete_Stream->Streams[pid]->Parser)->Unsynch_Frame_Count_Temp=Unsynch_Frame_Counts[pid];
3000 Unsynch_Frame_Counts.erase(pid);
3001 }
3002 #endif //MEDIAINFO_SEEK
3003 #if MEDIAINFO_DEMUX
3004 if (Config_Demux)
3005 {
3006 if (Complete_Stream->Streams[pid]->stream_type==0x20 && Complete_Stream->Streams[pid]->SubStream_pid)
3007 {
3008 //Creating the demux buffer
3009 ((File_MpegPs*)Complete_Stream->Streams[pid]->Parser)->SubStream_Demux=new File_MpegPs::demux;
3010 //If main parser is already created, associating the new demux buffer
3011 if (Complete_Stream->Streams[Complete_Stream->Streams[pid]->SubStream_pid]->Parser)
3012 ((File_MpegPs*)Complete_Stream->Streams[Complete_Stream->Streams[pid]->SubStream_pid]->Parser)->SubStream_Demux=((File_MpegPs*)Complete_Stream->Streams[pid]->Parser)->SubStream_Demux;
3013 }
3014 if (Complete_Stream->Streams[pid]->stream_type!=0x20 && Complete_Stream->Streams[pid]->SubStream_pid && (File_MpegPs*)Complete_Stream->Streams[Complete_Stream->Streams[pid]->SubStream_pid]->Parser)
3015 {
3016 //If SubStream parser is already created, associating the SubStream demux buffer
3017 ((File_MpegPs*)Complete_Stream->Streams[pid]->Parser)->SubStream_Demux=((File_MpegPs*)Complete_Stream->Streams[Complete_Stream->Streams[pid]->SubStream_pid]->Parser)->SubStream_Demux;
3018 }
3019 }
3020 #endif //MEDIAINFO_DEMUX
3021 #if defined(MEDIAINFO_ARIBSTDB24B37_YES)
3022 if (FromAribStdB24B37)
3023 ((File_MpegPs*)Complete_Stream->Streams[pid]->Parser)->FromAribStdB24B37=true;
3024 #endif //defined(MEDIAINFO_ARIBSTDB24B37_YES)
3025 #ifdef MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
3026 if (Searching_TimeStamp_Start)
3027 Complete_Stream->Streams[pid]->Searching_ParserTimeStamp_Start_Set(true);
3028 ((File_MpegPs*)Complete_Stream->Streams[pid]->Parser)->Searching_TimeStamp_Start=Complete_Stream->Streams[pid]->Searching_ParserTimeStamp_Start;
3029 #endif //MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
3030 ((File_MpegPs*)Complete_Stream->Streams[pid]->Parser)->FromTS=true;
3031 if (Config->File_MpegTs_stream_type_Trust_Get())
3032 ((File_MpegPs*)Complete_Stream->Streams[pid]->Parser)->FromTS_stream_type=Complete_Stream->Streams[pid]->stream_type;
3033 ((File_MpegPs*)Complete_Stream->Streams[pid]->Parser)->FromTS_descriptor_tag=Complete_Stream->Streams[pid]->descriptor_tag;
3034 if (!Complete_Stream->Streams[pid]->program_numbers.empty())
3035 ((File_MpegPs*)Complete_Stream->Streams[pid]->Parser)->FromTS_program_format_identifier=Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs[Complete_Stream->Streams[pid]->program_numbers[0]].registration_format_identifier;
3036 ((File_MpegPs*)Complete_Stream->Streams[pid]->Parser)->FromTS_format_identifier=Complete_Stream->Streams[pid]->registration_format_identifier;
3037 ((File_MpegPs*)Complete_Stream->Streams[pid]->Parser)->MPEG_Version=2;
3038 complete_stream::transport_stream::iod_ess::iterator IOD_ES=Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].IOD_ESs.find(Complete_Stream->Streams[pid]->FMC_ES_ID);
3039 if (IOD_ES!=Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].IOD_ESs.end())
3040 {
3041 #ifdef MEDIAINFO_MPEG4_YES
3042 ((File_MpegPs*)Complete_Stream->Streams[pid]->Parser)->ParserFromTs=IOD_ES->second.Parser; IOD_ES->second.Parser=NULL;
3043 ((File_MpegPs*)Complete_Stream->Streams[pid]->Parser)->SLConfig=IOD_ES->second.SLConfig; IOD_ES->second.SLConfig=NULL;
3044 #endif
3045 }
3046 #ifdef MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
3047 Complete_Stream->Streams[pid]->Parser->ShouldContinueParsing=true;
3048 #endif //MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
3049 Complete_Stream->Streams[pid]->Searching_Payload_Continue_Set(true);
3050 #else
3051 //Filling
3052 Streams[pid]->Parser=new File_Unknown();
3053 #endif
3054 Complete_Stream->Streams[pid]->Parser->CA_system_ID_MustSkipSlices=Complete_Stream->Streams[pid]->CA_system_ID_MustSkipSlices;
3055 #if MEDIAINFO_IBIUSAGE
3056 if (Ibi.Streams[pid]==NULL)
3057 Ibi.Streams[pid]=new ibi::stream;
3058 Complete_Stream->Streams[pid]->Parser->IbiStream=Ibi.Streams[pid];
3059 #endif //MEDIAINFO_IBIUSAGE
3060 Open_Buffer_Init(Complete_Stream->Streams[pid]->Parser);
3061 }
3062
3063 //If unsynched, waiting for first payload_unit_start_indicator
3064 if (!Complete_Stream->Streams[pid]->Parser->Synched && !payload_unit_start_indicator)
3065 {
3066 Element_DoNotShow(); //We don't want to show this item because there is no interessant info
3067 return; //This is not the start of the PES
3068 }
3069
3070 //Parsing
3071 if (Complete_Stream->Streams[pid]->Kind==complete_stream::stream::pes && Complete_Stream->Streams[pid]->IsPCR)
3072 ((File_MpegPs*)Complete_Stream->Streams[pid]->Parser)->FrameInfo.PCR=Complete_Stream->Streams[pid]->TimeStamp_End==(int64u)-1?(int64u)-1:Complete_Stream->Streams[pid]->TimeStamp_End*1000/27; //27 MHz
3073 #if MEDIAINFO_IBIUSAGE
3074 if (Complete_Stream->transport_stream_id!=(int16u)-1 && !Complete_Stream->Streams[pid]->program_numbers.empty())
3075 {
3076 int16u Program_PID=Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs[Complete_Stream->Streams[pid]->program_numbers[0]].pid;
3077 Complete_Stream->Streams[pid]->Parser->Ibi_SynchronizationOffset_Current=Complete_Stream->Streams[Program_PID]->Ibi_SynchronizationOffset_BeginOfFrame;
3078 if (Complete_Stream->Streams[pid]->Parser->Ibi_SynchronizationOffset_Current==(int64u)-1)
3079 return; //Not yet synchronized
3080 }
3081 else
3082 Complete_Stream->Streams[pid]->Parser->Ibi_SynchronizationOffset_Current=File_Offset+Buffer_Offset-Header_Size;
3083 #endif //MEDIAINFO_IBIUSAGE
3084
3085 #if defined(MEDIAINFO_ARIBSTDB24B37_YES)
3086 if (FromAribStdB24B37)
3087 Complete_Stream->Streams[pid]->Parser->FrameInfo=FrameInfo;
3088 #endif //defined(MEDIAINFO_ARIBSTDB24B37_YES)
3089
3090 //EIA-608/EIA-708 descriptors
3091 #if defined(MEDIAINFO_EIA608_YES) || defined(MEDIAINFO_EIA708_YES)
3092 Complete_Stream->Streams[pid]->Parser->ServiceDescriptors=NULL;
3093 if (Complete_Stream->Streams[pid]->ServiceDescriptors_IsPresent)
3094 Complete_Stream->Streams[pid]->Parser->ServiceDescriptors=&Complete_Stream->Streams[pid]->ServiceDescriptors;
3095 if (Complete_Stream->Streams[pid]->Parser->ServiceDescriptors==NULL)
3096 {
3097 for (size_t ProgramPos=0; ProgramPos<Complete_Stream->Streams[pid]->program_numbers.size(); ++ProgramPos)
3098 {
3099 Complete_Stream->Streams[pid]->Parser->ServiceDescriptors=Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs[Complete_Stream->Streams[pid]->program_numbers[ProgramPos]].ServiceDescriptors;
3100 if (Complete_Stream->Streams[pid]->Parser->ServiceDescriptors)
3101 break;
3102 }
3103 }
3104 if (Complete_Stream->Streams[pid]->Parser->ServiceDescriptors==NULL)
3105 {
3106 for (size_t ProgramPos=0; ProgramPos<Complete_Stream->Streams[pid]->program_numbers.size(); ++ProgramPos)
3107 if (Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs[Complete_Stream->Streams[pid]->program_numbers[ProgramPos]].source_id_IsValid)
3108 {
3109 int16u source_id=Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs[Complete_Stream->Streams[pid]->program_numbers[ProgramPos]].source_id;
3110 complete_stream::sources::iterator Source=Complete_Stream->Sources.find(source_id);
3111 if (Source!=Complete_Stream->Sources.end())
3112 for (complete_stream::source::atsc_epg_blocks::iterator ATSC_EPG_Block=Source->second.ATSC_EPG_Blocks.begin(); ATSC_EPG_Block!=Source->second.ATSC_EPG_Blocks.end(); ++ATSC_EPG_Block)
3113 for (complete_stream::source::atsc_epg_block::events::iterator Event=ATSC_EPG_Block->second.Events.begin(); Event!=ATSC_EPG_Block->second.Events.end(); ++Event)
3114 if (Event->second.ServiceDescriptors)
3115 {
3116 Complete_Stream->Streams[pid]->Parser->ServiceDescriptors=Event->second.ServiceDescriptors;
3117 break;
3118 }
3119 }
3120 }
3121 if (Complete_Stream->Streams[pid]->Parser->ServiceDescriptors==NULL)
3122 Complete_Stream->Streams[pid]->Parser->ServiceDescriptors=&Complete_Stream->Streams[pid]->ServiceDescriptors; //Default to empty descriptor present in order to say descriptor info is supported
3123 #endif
3124
3125 //Teletext descriptors
3126 #if defined(MEDIAINFO_TELETEXT_YES)
3127 Complete_Stream->Streams[pid]->Parser->Teletexts=&Complete_Stream->Streams[pid]->Teletexts;
3128 #endif
3129
3130 Open_Buffer_Continue(Complete_Stream->Streams[pid]->Parser);
3131 PES_Parse_Finish();
3132 }
3133
3134 //---------------------------------------------------------------------------
PES_Parse_Finish()3135 void File_MpegTs::PES_Parse_Finish()
3136 {
3137 //Test if parsing of headers is OK
3138 if (NoPatPmt && !Status[IsAccepted])
3139 Accept("MPEG-TS");
3140
3141 if (Complete_Stream->Streams[pid]->Parser->Status[IsUpdated])
3142 {
3143 Complete_Stream->Streams[pid]->Parser->Status[IsUpdated]=false;
3144 Complete_Stream->Streams[pid]->IsUpdated_Info=true;
3145 for (size_t Pos=0; Pos<Complete_Stream->Streams[pid]->program_numbers.size(); Pos++)
3146 Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs[Complete_Stream->Streams[pid]->program_numbers[Pos]].Update_Needed_IsRegistered=true;
3147
3148 Status[IsUpdated]=true;
3149 Status[User_19]=true;
3150 }
3151
3152 #if defined(MEDIAINFO_MPEGPS_YES) && defined(MEDIAINFO_MPEGTS_PESTIMESTAMP_YES)
3153 if (Complete_Stream->Streams[pid]->Kind==complete_stream::stream::pes
3154 && MpegTs_JumpTo_Begin+MpegTs_JumpTo_End>File_Size
3155 && !Complete_Stream->Streams[pid]->Searching_ParserTimeStamp_End
3156 && ((File_MpegPs*)Complete_Stream->Streams[pid]->Parser)->HasTimeStamps)
3157 {
3158 Complete_Stream->Streams[pid]->Searching_ParserTimeStamp_Start_Set(false);
3159 Complete_Stream->Streams[pid]->Searching_ParserTimeStamp_End_Set(true);
3160 }
3161 #endif //MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
3162
3163 //Need anymore?
3164 if (Complete_Stream->Streams[pid]->Parser->Status[IsFilled]
3165 || Complete_Stream->Streams[pid]->Parser->Status[IsFinished])
3166 {
3167 if ((Complete_Stream->Streams[pid]->Searching_Payload_Start || Complete_Stream->Streams[pid]->Searching_Payload_Continue) && Config->ParseSpeed<1 && MpegTs_JumpTo_End)
3168 {
3169 if (Config->File_StopSubStreamAfterFilled_Get())
3170 {
3171 Complete_Stream->Streams[pid]->Searching_Payload_Start_Set(false);
3172 Complete_Stream->Streams[pid]->Searching_Payload_Continue_Set(false);
3173 }
3174 if (!Complete_Stream->Streams[pid]->IsParsed && Complete_Stream->Streams_NotParsedCount)
3175 {
3176 Complete_Stream->Streams[pid]->IsParsed=true;
3177 Complete_Stream->Streams_NotParsedCount--;
3178 }
3179 }
3180 #ifdef MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
3181 if (Complete_Stream->Streams[pid]->Searching_ParserTimeStamp_Start)
3182 Complete_Stream->Streams[pid]->Searching_ParserTimeStamp_Start_Set(false);
3183 #else //MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
3184 if (Config->ParseSpeed<1.0)
3185 Finish(Complete_Stream->Streams[pid]->Parser);
3186 #endif //MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
3187 }
3188
3189 #if MEDIAINFO_SEEK && MEDIAINFO_IBIUSAGE
3190 if (Seek_ID!=(int64u)-1)
3191 {
3192 if (Ibi.Streams[Seek_ID]->IsModified)
3193 {
3194 Read_Buffer_Seek(2, Seek_Value, Seek_ID);
3195 }
3196 else if (Ibi.Streams[Seek_ID]->Infos_Pos>=2 && Ibi.Streams[Seek_ID]->IsSynchronized && Ibi.Streams[Seek_ID]->Infos[Ibi.Streams[Seek_ID]->Infos_Pos-1].StreamOffset>=Seek_Value_Maximal)
3197 {
3198 InfiniteLoop_Detect++;
3199 if (InfiniteLoop_Detect>16)
3200 {
3201 //Infinite loop
3202 Seek_ID=(int64u)-1;
3203 Seek_Value=(int64u)-1;
3204 InfiniteLoop_Detect=0;
3205 Config->Demux_IsSeeking=false;
3206 }
3207 else
3208 {
3209 //No intermediate seek point found, going to previous seek point
3210 GoTo(Ibi.Streams[Seek_ID]->Infos[Ibi.Streams[Seek_ID]->Infos_Pos-2].StreamOffset);
3211 Open_Buffer_Unsynch();
3212 }
3213 }
3214 }
3215 #endif //MEDIAINFO_SEEK && MEDIAINFO_IBIUSAGE
3216 }
3217
3218 //---------------------------------------------------------------------------
PSI()3219 void File_MpegTs::PSI()
3220 {
3221 //Initializing
3222 if (payload_unit_start_indicator)
3223 {
3224 #if MEDIAINFO_EVENTS
3225 StreamIDs[StreamIDs_Size-1]=pid;
3226 #endif //MEDIAINFO_EVENTS
3227 delete ((File_Mpeg_Psi*)Complete_Stream->Streams[pid]->Parser); Complete_Stream->Streams[pid]->Parser=new File_Mpeg_Psi;
3228 Open_Buffer_Init(Complete_Stream->Streams[pid]->Parser);
3229 ((File_Mpeg_Psi*)Complete_Stream->Streams[pid]->Parser)->Complete_Stream=Complete_Stream;
3230 ((File_Mpeg_Psi*)Complete_Stream->Streams[pid]->Parser)->pid=pid;
3231 }
3232 else if (Complete_Stream->Streams[pid]->Parser==NULL)
3233 {
3234 Skip_XX(Element_Size, "data");
3235 return; //This is not the start of the PSI
3236 }
3237
3238 //Parsing
3239 #if MEDIAINFO_IBIUSAGE
3240 Complete_Stream->Streams[pid]->Parser->Ibi_SynchronizationOffset_Current=File_Offset+Buffer_Offset-Header_Size;
3241 #endif //MEDIAINFO_IBIUSAGE
3242 Open_Buffer_Continue(Complete_Stream->Streams[pid]->Parser);
3243
3244 //Filling
3245 if (Complete_Stream->Streams[pid]->Parser->Status[IsFilled])
3246 {
3247 //Accept
3248 if (!Status[IsAccepted] && pid==0x0000 && Complete_Stream->Streams[pid]->Parser->Status[IsAccepted])
3249 Accept("MPEG-TS");
3250
3251 //Disabling this pid
3252 delete Complete_Stream->Streams[pid]->Parser; Complete_Stream->Streams[pid]->Parser=NULL;
3253 Complete_Stream->Streams[pid]->Searching_Payload_Start_Set(true);
3254 Complete_Stream->Streams[pid]->Searching_Payload_Continue_Set(false);
3255
3256 //EPG
3257 if (Complete_Stream->Sources_IsUpdated || Complete_Stream->Programs_IsUpdated)
3258 {
3259 Status[IsUpdated]=true;
3260 Status[User_18]=true;
3261 }
3262
3263 //Duration
3264 if (Complete_Stream->Duration_End_IsUpdated)
3265 {
3266 Status[IsUpdated]=true;
3267 Status[User_17]=true;
3268 }
3269
3270 //Program change
3271 if (pid==0x0000)
3272 {
3273 Status[IsFilled]=false;
3274
3275 Status[IsUpdated]=true;
3276 Status[User_19]=true;
3277 }
3278 if (!Complete_Stream->Streams[pid]->Table_IDs.empty() && Complete_Stream->Streams[pid]->Table_IDs[0x02])
3279 {
3280 Status[IsFilled]=false;
3281
3282 //Status[IsUpdated]=true;
3283 //Status[User_19]=true;
3284 }
3285
3286 //Item removal
3287 if (pid==0x0000 || (!Complete_Stream->Streams[pid]->Table_IDs.empty() && Complete_Stream->Streams[pid]->Table_IDs[0x02]))
3288 {
3289 for (size_t StreamKind=Stream_General+1; StreamKind<Stream_Max; StreamKind++)
3290 if (!Complete_Stream->StreamPos_ToRemove[StreamKind].empty())
3291 {
3292 sort(Complete_Stream->StreamPos_ToRemove[StreamKind].begin(), Complete_Stream->StreamPos_ToRemove[StreamKind].end());
3293 size_t Pos=Complete_Stream->StreamPos_ToRemove[StreamKind].size();
3294 do
3295 {
3296 Pos--;
3297
3298 //Erasing text substreams
3299 Ztring ID_ToFind=Retrieve((stream_t)StreamKind, Complete_Stream->StreamPos_ToRemove[StreamKind][Pos], General_ID)+__T('-');
3300 for (size_t TextPos=0; TextPos<Count_Get(Stream_Text); TextPos++)
3301 if (Retrieve(Stream_Text, TextPos, General_ID).find(ID_ToFind)==0)
3302 Stream_Erase(Stream_Text, TextPos);
3303
3304 //Erasing the stream
3305 Stream_Erase((stream_t)StreamKind, Complete_Stream->StreamPos_ToRemove[StreamKind][Pos]);
3306
3307 //Moving other StreamPos
3308 for (size_t Pos2=Pos+1; Pos2<Complete_Stream->StreamPos_ToRemove[StreamKind].size(); Pos2++)
3309 Complete_Stream->StreamPos_ToRemove[StreamKind][Pos2]--;
3310
3311 //Informing that the menu must be recalculated - TODO: only the related programs
3312 if (StreamKind!=Stream_Menu)
3313 {
3314 for (complete_stream::transport_stream::programs::iterator Program=Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs.begin(); Program!=Complete_Stream->Transport_Streams[Complete_Stream->transport_stream_id].Programs.end(); ++Program)
3315 Program->second.Update_Needed_StreamPos=true;
3316 }
3317 else if (Complete_Stream->StreamPos_ToRemove[StreamKind][Pos]<Complete_Stream->program_number_Order.size())
3318 {
3319 Complete_Stream->program_number_Order.erase(Complete_Stream->program_number_Order.begin()+Complete_Stream->StreamPos_ToRemove[StreamKind][Pos]);
3320 }
3321 }
3322 while (Pos);
3323 Complete_Stream->StreamPos_ToRemove[StreamKind].clear();
3324 }
3325
3326 Status[IsUpdated]=true;
3327 Status[User_19]=true;
3328 }
3329 }
3330 else
3331 //Waiting for more data
3332 Complete_Stream->Streams[pid]->Searching_Payload_Continue_Set(true);
3333 }
3334
3335 //---------------------------------------------------------------------------
SetAllToPES()3336 void File_MpegTs::SetAllToPES()
3337 {
3338 Complete_Stream->Streams_NotParsedCount=(size_t)-1;
3339 for (size_t StreamID=0; StreamID<0x2000; StreamID++)
3340 {
3341 delete Complete_Stream->Streams[StreamID]; Complete_Stream->Streams[StreamID]=new complete_stream::stream;
3342 }
3343 #ifdef MEDIAINFO_ARIBSTDB24B37_YES
3344 size_t StreamID=FromAribStdB24B37?0x00:0x20;
3345 #else //MEDIAINFO_ARIBSTDB24B37_YES
3346 size_t StreamID=0x20;
3347 #endif //MEDIAINFO_ARIBSTDB24B37_YES
3348 for (; StreamID<0x1FFF; StreamID++)
3349 {
3350 Complete_Stream->Streams[StreamID]->Kind=complete_stream::stream::pes;
3351 Complete_Stream->Streams[StreamID]->Searching_Payload_Start_Set(true);
3352 Complete_Stream->Streams[StreamID]->Searching_Payload_Continue_Set(false);
3353 #if MEDIAINFO_TRACE
3354 if (Trace_Activated)
3355 Complete_Stream->Streams[StreamID]->Element_Info1="PES";
3356 #endif //MEDIAINFO_TRACE
3357 #ifdef MEDIAINFO_MPEGTS_PCR_YES
3358 Complete_Stream->Streams[StreamID]->Searching_TimeStamp_Start_Set(true);
3359 Complete_Stream->Streams[StreamID]->Searching_TimeStamp_End_Set(false);
3360 #endif //MEDIAINFO_MPEGTS_PCR_YES
3361 #ifdef MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
3362 Complete_Stream->Streams[StreamID]->Searching_ParserTimeStamp_Start_Set(true);
3363 Complete_Stream->Streams[StreamID]->Searching_ParserTimeStamp_End_Set(false);
3364 #endif //MEDIAINFO_MPEGTS_PESTIMESTAMP_YES
3365 }
3366 }
3367
3368 //---------------------------------------------------------------------------
transport_private_data(int8u transport_private_data_length)3369 void File_MpegTs::transport_private_data(int8u transport_private_data_length)
3370 {
3371 //Trying SCTE 128
3372 int64u End=Element_Offset+transport_private_data_length;
3373 #if MEDIAINFO_TRACE
3374 bool Trace_Activated_Save=Trace_Activated;
3375 Trace_Activated=false;
3376 #endif //MEDIAINFO_TRACE
3377 Element_Begin1("SCTE 128 coherency test");
3378 bool IsOk=true;
3379 while (Element_Offset+2<=End)
3380 {
3381 int8u tag, length;
3382 Get_B1 (tag, "tag");
3383 Get_B1 (length, "length");
3384 if (Element_Offset+length>End || (tag==0xDF && length<4))
3385 {
3386 Skip_XX(End-Element_Offset, "problem");
3387 IsOk=false;
3388 }
3389 else
3390 Skip_XX(length, "data");
3391 }
3392 if (Element_Offset<End)
3393 {
3394 Skip_XX(End-Element_Offset, "problem");
3395 IsOk=false;
3396 }
3397 Element_End0();
3398 #if MEDIAINFO_TRACE
3399 Trace_Activated=Trace_Activated_Save;
3400 #endif //MEDIAINFO_TRACE
3401 if (IsOk)
3402 {
3403 Element_Offset=End-transport_private_data_length;
3404 while (Element_Offset+2<=End)
3405 {
3406 Element_Begin0();
3407 int8u tag, length;
3408 Get_B1 (tag, "tag"); Param_Info1(Scte128_tag(tag)); Element_Name(Scte128_tag(tag));
3409 Get_B1 (length, "length");
3410 if (tag==0xDF && length>=4)
3411 {
3412 int32u format_identifier;
3413 Get_C4 (format_identifier, "format identifier");
3414 switch (format_identifier)
3415 {
3416 case 0x45425030 : //EBP0
3417 {
3418 int64u End2=Element_Offset+length-4;
3419 Element_Info1("CableLabs - Encoder Boundary Point");
3420 BS_Begin();
3421 bool EBP_fragment_flag, EBP_segment_flag, EBP_SAP_flag, EBP_grouping_flag, EBP_time_flag, EBP_concealment_flag, EBP_extension_flag;
3422 Get_SB (EBP_fragment_flag, "EBP_fragment_flag");
3423 Get_SB (EBP_segment_flag, "EBP_segment_flag");
3424 Get_SB (EBP_SAP_flag, "EBP_SAP_flag");
3425 Get_SB (EBP_grouping_flag, "EBP_grouping_flag");
3426 Get_SB (EBP_time_flag, "EBP_time_flag");
3427 Get_SB (EBP_concealment_flag, "EBP_concealment_flag");
3428 Skip_SB( "Reserved");
3429 Get_SB (EBP_extension_flag, "EBP_extension_flag");
3430 if (EBP_extension_flag)
3431 {
3432 Skip_SB( "EBP_ext_partition_flag");
3433 Skip_S1(7, "reserved");
3434 }
3435 if (EBP_SAP_flag)
3436 {
3437 Skip_S1(3, "EBP_SAP_type");
3438 Skip_S1(5, "reserved");
3439 }
3440 if (EBP_grouping_flag)
3441 {
3442 bool EBP_grouping_ext_flag=true;
3443 while (EBP_grouping_ext_flag && Element_Offset<End2)
3444 {
3445 Get_SB (EBP_grouping_ext_flag, "EBP_grouping_ext_flag");
3446 Skip_S1(7, "EBP_grouping_id");
3447 }
3448 }
3449 BS_End();
3450 if (EBP_time_flag)
3451 {
3452 Element_Begin1("EBP_acquisition_time");
3453 if (Complete_Stream->Streams[pid] && !Complete_Stream->Streams[pid]->EBP_Marker_Detected)
3454 {
3455 int32u Seconds, Fraction;
3456 Get_B4 (Seconds, "Seconds"); Param_Info1(Ztring().Date_From_Seconds_1970((int32u)(Seconds-2208988800))); //Param_Info1(Ztring().Date_From_Seconds_1900(Seconds)); //Temp for old ZenLib
3457 Get_B4 (Fraction, "Fraction"); Param_Info1(Ztring::ToZtring(((float64)Fraction)/0x100000000LL, 9));
3458 Complete_Stream->Streams[pid]->Infos["EBP_AcquisitionTime"]=Ztring().Date_From_Seconds_1970((int32u)(Seconds-2208988800))+__T('.')+Ztring::ToZtring(((float64)Fraction)/0x100000000LL, 9).substr(2); //.Date_From_Seconds_1900(Seconds)); //Temp for old ZenLib
3459 Complete_Stream->Streams[pid]->EBP_Marker_Detected=true;
3460 }
3461 else
3462 {
3463 Info_B4(Seconds, "Seconds"); Param_Info1(Ztring().Date_From_Seconds_1970((int32u)(Seconds-2208988800))); //Param_Info1(Ztring().Date_From_Seconds_1900(Seconds)); //Temp for old ZenLib
3464 Info_B4(Fraction, "Fraction"); Param_Info1(Ztring::ToZtring(((float64)Fraction)/0x100000000LL, 9));
3465 }
3466 Element_End0();
3467 }
3468 if (EBP_concealment_flag)
3469 {
3470 Skip_B8( "EBP_ext_partitions");
3471 }
3472 if (Element_Offset<End)
3473 Skip_XX(End-Element_Offset, "EBP_reserved_bytes");
3474 }
3475 break;
3476 default : Skip_XX(length-4, "data");
3477 }
3478 }
3479 else
3480 Skip_XX(length, "data");
3481 Element_End0();
3482 }
3483 }
3484 else
3485 Skip_XX(transport_private_data_length, "transport_private_data");
3486 }
3487
3488 //---------------------------------------------------------------------------
MergeGeneral(complete_stream::stream * Stream,general Parameter)3489 void File_MpegTs::MergeGeneral(complete_stream::stream* Stream, general Parameter)
3490 {
3491 if (!Stream->Parser)
3492 return;
3493
3494 const Ztring& Value = Stream->Parser->Retrieve_Const(Stream_General, 0, Parameter);
3495 if (Value.empty())
3496 return;
3497
3498 if (Count_Get(Stream_Menu))
3499 {
3500 Ztring MenuID = Retrieve(Stream->StreamKind, Stream->StreamPos, General_MenuID);
3501 for (size_t Pos = 0; Pos<Count_Get(Stream_Menu); Pos++)
3502 if (Retrieve(Stream_Menu, Pos, General_MenuID) == MenuID)
3503 Fill(Stream_Menu, Pos, Stream->Parser->Retrieve(Stream_General, 0, Parameter, Info_Name).To_UTF8().c_str(), Value, true);
3504 }
3505 else
3506 Fill(Stream_General, 0, Parameter, Value, true);
3507 }
3508
3509
3510 } //NameSpace
3511
3512 #endif //MEDIAINFO_MPEGTS_YES
3513