1 /*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
2  *
3  *  Use of this source code is governed by a BSD-style license that can
4  *  be found in the License.html file in the root of the source tree.
5  */
6 
7 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8 //
9 // Information about DVD objects
10 // (.ifo files on DVD-Video)
11 //
12 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13 //
14 // Mainly from http://dvd.sourceforge.net/dvdinfo/ifo.html
15 //
16 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
17 
18 //---------------------------------------------------------------------------
19 // Pre-compilation
20 #include "MediaInfo/PreComp.h"
21 #ifdef __BORLANDC__
22     #pragma hdrstop
23 #endif
24 //---------------------------------------------------------------------------
25 
26 //---------------------------------------------------------------------------
27 #include "MediaInfo/Setup.h"
28 //---------------------------------------------------------------------------
29 
30 //---------------------------------------------------------------------------
31 #include <vector>
32 using namespace std;
33 //---------------------------------------------------------------------------
34 
35 //---------------------------------------------------------------------------
36 #if defined(MEDIAINFO_DVDV_YES)
37 //---------------------------------------------------------------------------
38 
39 //---------------------------------------------------------------------------
40 #include "MediaInfo/Multiple/File_Dvdv.h"
41 //---------------------------------------------------------------------------
42 
43 namespace MediaInfoLib
44 {
45 
46 //---------------------------------------------------------------------------
47 static const char*  IFO_VTS_Category[]=
48 {
49     "Normal",
50     "Karaoke",
51 };
52 
53 static const char*  IFO_Format_V[]=
54 {
55     "MPEG Video",
56     "MPEG Video",
57     "",
58     "",
59 };
60 
61 static const char*  IFO_Format_Version_V[]=
62 {
63     "Version 1",
64     "Version 2",
65     "",
66     "",
67 };
68 
69 static const char*  IFO_CodecV[]=
70 {
71     "MPEG-1V",
72     "MPEG-2V",
73     "",
74     "",
75 };
76 
77 static const char*  IFO_Standard[]=
78 {
79     "NTSC",
80     "PAL",
81     "",
82     "",
83 };
84 
85 static const float32  IFO_AspectRatio[]=
86 {
87     (float32)1.333,
88     (float32)0.000,
89     (float32)0.000,
90     (float32)1.778,
91 };
92 
93 static const char*  IFO_BitRate_Mode[]=
94 {
95     "VBR",
96     "CBR",
97 };
98 
99 static const size_t IFO_Width[]=
100 {720, 704, 352, 352,   0,   0,   0,   0};
101 
102 static const size_t IFO_Height[4][8]=
103 {{480, 480, 480, 240,   0,   0,   0,   0}, //NTSC
104  {576, 576, 576, 288,   0,   0,   0,   0}, //PAL
105  {  0,   0,   0,   0,   0,   0,   0,   0}, //Unknown
106  {  0,   0,   0,   0,   0,   0,   0,   0}, //Unknown
107  };
108 
109 static const float64 IFO_FrameRate[]=
110 {29.970, 25.000};
111 
112 static const char*  IFO_Format_A[]=
113 {
114     "AC-3",
115     "",
116     "MPEG Audio",
117     "MPEG Audio",
118     "PCM",
119     "",
120     "DTS",
121     "SDDS",
122 };
123 
124 static const char*  IFO_Format_Profile_A[]=
125 {
126     "",
127     "",
128     "Version 1",
129     "Version 2",
130     "",
131     "",
132     "",
133     "",
134 };
135 
136 static const char*  IFO_CodecA[]=
137 {
138     "AC3",
139     "",
140     "MPEG-1A",
141     "MPEG-2A",
142     "LPCM (Big Endian)",
143     "",
144     "DTS",
145     "SDDS",
146 };
147 
148 static const char*  IFO_ModeA[]=
149 {
150     "",
151     "Karaoke",
152     "Surround",
153     "",
154 };
155 
156 static const char*  IFO_ResolutionA[]=
157 {
158     "16",
159     "20",
160     "24",
161     "DRC",
162 };
163 
164 static const int16u IFO_SamplingRate[]=
165 {48000, 0, 0, 0, 0, 0, 0, 0};
166 
167 static const char*  IFO_Language_MoreA[]=
168 {
169     "",
170     "",
171     "For visually impaired",
172     "Director's comments",
173     "Director's comments",
174     "",
175     "",
176     "",
177 };
178 
179 static const char*  IFO_Format_T[]=
180 {
181     "RLE",
182     "",
183     "",
184     "",
185     "",
186     "",
187     "",
188     "",
189 };
190 
191 static const char*  IFO_Resolution_T[]=
192 {
193     "2",
194     "",
195     "",
196     "",
197     "",
198     "",
199     "",
200     "",
201 };
202 
203 static const char*  IFO_CodecT[]=
204 {
205     "2-bit RLE",
206     "",
207     "",
208     "",
209     "",
210     "",
211     "",
212     "",
213 };
214 
215 static const char*  IFO_Language_MoreT[]=
216 {
217     "",
218     "Normal",
219     "Large",
220     "Children",
221     "",
222     "",
223     "Large",
224     "Children",
225     "",
226     "Forced",
227     "",
228     "",
229     "",
230     "Director comments",
231     "Director comments large",
232     "Director comments children",
233 };
234 
235 static const size_t IFO_PlaybackTime_FrameRate[]=
236 {1, 25, 1, 30};
237 
238 static const char*  IFO_MenuType[]=
239 {
240     "",
241     "",
242     "",
243     "root",
244     "sub-picture",
245     "audio",
246     "angle",
247     "PTT (chapter)",
248     "",
249     "",
250     "",
251     "",
252     "",
253     "",
254     "",
255     "",
256 };
257 
258 //---------------------------------------------------------------------------
259 extern const char*  AC3_ChannelPositions[];
260 extern const char*  AC3_ChannelPositions2[];
261 
262 //***************************************************************************
263 // Constructor/Destructor
264 //***************************************************************************
265 
266 //---------------------------------------------------------------------------
File_Dvdv()267 File_Dvdv::File_Dvdv()
268 :File__Analyze()
269 {
270     //Temp
271     VTS_Attributes_AreHere=false;
272     Program_Pos=0;
273     Time_Pos=0;
274 }
275 
276 //***************************************************************************
277 // Streams management
278 //***************************************************************************
279 
280 //---------------------------------------------------------------------------
Streams_Finish()281 void File_Dvdv::Streams_Finish()
282 {
283     //Purge what is not needed anymore
284     if (!File_Name.empty()) //Only if this is not a buffer, with buffer we can have more data
285         Sectors.clear();
286 }
287 
288 //***************************************************************************
289 // Buffer
290 //***************************************************************************
291 
292 //---------------------------------------------------------------------------
FileHeader_Parse()293 void File_Dvdv::FileHeader_Parse()
294 {
295     //Parsing
296     int64u Identifier;
297     int32u Type;
298     Get_C8 (Identifier,                                         "Identifier");
299     Get_C4 (Type,                                               "Type");
300 
301     FILLING_BEGIN();
302         //Identifier
303         if (Identifier!=CC8("DVDVIDEO"))
304         {
305             Reject("DVD Video");
306             return;
307         }
308 
309         Accept("DVD Video");
310 
311         Fill(Stream_General, 0, General_Format, "DVD Video");
312 
313         //Versions
314         switch (Type)
315         {
316             case Dvdv::VMG : VMG(); break;
317             case Dvdv::VTS : VTS(); break;
318             default        :
319                         Reject("DVD Video");
320                         return;
321         }
322     FILLING_END();
323 }
324 
325 //---------------------------------------------------------------------------
326 
327 
328 //***************************************************************************
329 // Elements
330 //***************************************************************************
331 
332 #define SUBELEMENT(_ELEMENT) \
333     { \
334         Element_Begin1(#_ELEMENT); \
335         _ELEMENT(); \
336         Element_End0(); \
337     } \
338 
339 //---------------------------------------------------------------------------
VMG()340 void File_Dvdv::VMG()
341 {
342     int32u Sector_Pointer_LastSector, Sector_Pointer_TT_SRPT, Sector_Pointer_VMGM_PGCI_UT, Sector_Pointer_VMG_PTL_MAIT, Sector_Pointer_VMG_VTS_ATRT, Sector_Pointer_VMG_TXTDT_MG, Sector_Pointer_VMGM_C_ADT, Sector_Pointer_VMGM_VOBU_ADMAP;
343     int16u Version, Audio_Count, Text_Count;
344     Element_Info1("DVD Video - VMG");
345     Element_Begin1("Header");
346         Info_B4(LastSector,                                     "Last sector of VMG set (last sector of BUP)"); Param_Info2((LastSector+1)*2048, " bytes");
347         Skip_XX(12,                                             "Unknown");
348         Get_B4 (Sector_Pointer_LastSector,                      "last sector of IFO");
349         Get_B2 (Version,                                        "version number"); Param_Info1(Ztring::ToZtring((Version&0x00F0)>>4)+__T(".")+Ztring::ToZtring(Version&0x000F));
350         Info_B4(Category,                                       "VMG category");
351         Skip_B2(                                                "number of volumes");
352         Skip_B2(                                                "volume number");
353         Skip_B1(                                                "side ID");
354         Skip_XX(19,                                             "Unknown");
355         Skip_B2(                                                "number of title sets");
356         Skip_Local(32,                                          "Provider ID");
357         Skip_B8(                                                "VMG POS");
358         Skip_XX(24,                                             "Unknown");
359         Skip_B4(                                                "end byte address of VMGI_MAT");
360         Skip_B4(                                                "start address of FP_PGC (First Play program chain)");
361         Skip_XX(56,                                             "Unknown");
362         Info_B4(Sector_Pointer_Menu,                            "start sector of Menu VOB");
363         Get_B4 (Sector_Pointer_TT_SRPT,                         "sector pointer to TT_SRPT (table of titles)");
364         Get_B4 (Sector_Pointer_VMGM_PGCI_UT,                    "sector pointer to VMGM_PGCI_UT (Menu Program Chain table)");
365         Get_B4 (Sector_Pointer_VMG_PTL_MAIT,                    "sector pointer to VMG_PTL_MAIT (Parental Management masks)");
366         Get_B4 (Sector_Pointer_VMG_VTS_ATRT,                    "sector pointer to VMG_VTS_ATRT (copies of VTS audio/sub-picture attributes)");
367         Get_B4 (Sector_Pointer_VMG_TXTDT_MG,                    "sector pointer to VMG_TXTDT_MG (text data)");
368         Get_B4 (Sector_Pointer_VMGM_C_ADT,                      "sector pointer to VMGM_C_ADT (menu cell address table)");
369         Get_B4 (Sector_Pointer_VMGM_VOBU_ADMAP,                 "sector pointer to VMGM_VOBU_ADMAP (menu VOBU address map)");
370         Skip_XX(32,                                             "Unknown");
371     Element_End0();
372 
373     //-VTSM
374     VTS_Attributes_AreHere=true;
375     Element_Begin1("VMGM (VMG for Menu)");
376         Element_Begin1("Video streams");
377             Element_Info2(1, " streams");
378             SUBELEMENT(Video)
379         Element_End0();
380         Element_Begin1("Audio streams");
381             Get_B2 (Audio_Count,                                "number of audio streams in VMGM_VOBS");
382             Element_Info2(Audio_Count, " streams");
383             for (int16u Pos=0; Pos<8; Pos++)
384             {
385                 if (Pos<Audio_Count)
386                     SUBELEMENT(Audio)
387                 else
388                     Skip_XX(8,                                  "Reserved for Audio");
389             }
390             Skip_XX(16,                                         "Unknown");
391         Element_End0();
392         Element_Begin1("Text streams");
393             Get_B2 (Text_Count,                                 "number of subpicture streams in VMGM_VOBS");
394             Element_Info2(Text_Count, " streams");
395             for (int16u Pos=0; Pos<1; Pos++)
396             {
397                 if (Pos<Text_Count)
398                     SUBELEMENT(Text)
399                 else
400                     Skip_XX(6,                                  "Reserved for Text");
401             }
402             Skip_XX(164,                                        "Unknown");
403         Element_End0();
404     Element_End0();
405     Skip_XX(2048-Element_Offset,                                "Junk");
406 
407     //Filling
408     FILLING_BEGIN();
409         Fill(Stream_General, 0, General_Format_Profile, "Menu");
410 
411         if (Version>0x001F)
412             return;
413         Sectors.resize(Sector_Pointer_LastSector+1);
414         if (Sector_Pointer_TT_SRPT<=Sector_Pointer_LastSector)
415             Sectors[Sector_Pointer_TT_SRPT]=Sector_TT_SRPT;
416         if (Sector_Pointer_VMGM_PGCI_UT<=Sector_Pointer_LastSector)
417             Sectors[Sector_Pointer_VMGM_PGCI_UT]=Sector_VMGM_PGCI_UT;
418         if (Sector_Pointer_VMG_PTL_MAIT<=Sector_Pointer_LastSector)
419             Sectors[Sector_Pointer_VMG_PTL_MAIT]=Sector_VMG_PTL_MAIT;
420         if (Sector_Pointer_VMG_VTS_ATRT<=Sector_Pointer_LastSector)
421             Sectors[Sector_Pointer_VMG_VTS_ATRT]=Sector_VMG_VTS_ATRT;
422         if (Sector_Pointer_VMG_TXTDT_MG<=Sector_Pointer_LastSector)
423             Sectors[Sector_Pointer_VMG_TXTDT_MG]=Sector_VMG_TXTDT_MG;
424         if (Sector_Pointer_VMGM_C_ADT<=Sector_Pointer_LastSector)
425             Sectors[Sector_Pointer_VMGM_C_ADT]=Sector_VMGM_C_ADT;
426         if (Sector_Pointer_VMGM_VOBU_ADMAP<=Sector_Pointer_LastSector)
427             Sectors[Sector_Pointer_VMGM_VOBU_ADMAP]=Sector_VMGM_VOBU_ADMAP;
428     FILLING_END();
429 }
430 
431 //---------------------------------------------------------------------------
VTS()432 void File_Dvdv::VTS()
433 {
434     //Parsing
435     int32u Sector_Pointer_LastSector, Sector_Pointer_VTS_PTT_SRPT, Sector_Pointer_VTS_PGCI, Sector_Pointer_VTSM_PGCI_UT, Sector_Pointer_VTS_TMAPTI, Sector_Pointer_VTSM_C_ADT, Sector_Pointer_VTSM_VOBU_ADMAP, Sector_Pointer_VTS_C_ADT, Sector_Pointer_VTS_VOBU_ADMAP;
436     int16u Version, Audio_Count, Text_Count;
437     Element_Info1("DVD Video - VTS (Video Title Set)");
438     Element_Begin1("Header");
439         Info_B4(LastSector,                                     "Last sector of Title set (last sector of BUP)"); Param_Info2((LastSector+1)*2048, " bytes");
440         Skip_XX(12,                                             "Unknown");
441         Get_B4 (Sector_Pointer_LastSector,                      "last sector of IFO");
442         Get_B2 (Version,                                        "version number"); Param_Info1(Ztring::ToZtring((Version&0x00F0)>>4)+__T(".")+Ztring::ToZtring(Version&0x000F));
443         Info_B4(Category,                                       "VTS category");
444         #if MEDIAINFO_TRACE
445             if (Category<2) Param_Info1(IFO_VTS_Category[Category]);
446         #endif //MEDIAINFO_TRACE
447         Skip_XX(90,                                             "Unknown");
448         Skip_B4(                                                "end byte address of VTS_MAT");
449         Skip_XX(60,                                             "Unknown");
450         Info_B4(StartSector_Menu,                               "start sector of Menu VOB"); Param_Info2((StartSector_Menu+1)*2048, " bytes");
451         Info_B4(StartSector_Title,                              "start sector of Title Vob"); Param_Info2((StartSector_Title+1)*2048, " bytes");
452         Get_B4 (Sector_Pointer_VTS_PTT_SRPT,                    "sector pointer to VTS_PTT_SRPT (Table of Titles and Chapters)");
453         Get_B4 (Sector_Pointer_VTS_PGCI,                        "sector pointer to VTS_PGCI (Title Program Chain table)");
454         Get_B4 (Sector_Pointer_VTSM_PGCI_UT,                    "sector pointer to VTSM_PGCI_UT (Menu Program Chain table)");
455         Get_B4 (Sector_Pointer_VTS_TMAPTI,                      "sector pointer to VTS_TMAPTI (Time map)");
456         Get_B4 (Sector_Pointer_VTSM_C_ADT,                      "sector pointer to VTSM_C_ADT (Menu cell address table)");
457         Get_B4 (Sector_Pointer_VTSM_VOBU_ADMAP,                 "sector pointer to VTSM_VOBU_ADMAP(menu VOBU address map)");
458         Get_B4 (Sector_Pointer_VTS_C_ADT,                       "sector pointer to VTS_C_ADT (Title set cell address table)");
459         Get_B4 (Sector_Pointer_VTS_VOBU_ADMAP,                  "sector pointer to VTS_VOBU_ADMAP (Title set VOBU address map)");
460         Skip_XX(24,                                             "Unknown");
461     Element_End0();
462 
463     //-VTSM
464     Element_Begin1("VTSM (VTS for Menu, Vob 0)");
465         Element_Begin1("Video streams");
466             Element_Info2(1, " streams");
467             SUBELEMENT(Video)
468         Element_End0();
469         Element_Begin1("Audio streams");
470             Get_B2 (Audio_Count,                                "number of audio streams in VTSM_VOBS");
471             Element_Info2(Audio_Count, " streams");
472             for (int16u Pos=0; Pos<8; Pos++)
473             {
474                 if (Pos<Audio_Count)
475                     SUBELEMENT(Audio)
476                 else
477                     Skip_XX(8,                                  "Reserved for Audio");
478             }
479             Skip_XX(16,                                         "Unknown");
480         Element_End0();
481         Element_Begin1("Text streams");
482             Get_B2 (Text_Count,                                 "number of subpicture streams in VTSM_VOBS");
483             Element_Info2(Text_Count, " streams");
484             for (int16u Pos=0; Pos<1; Pos++)
485             {
486                 if (Pos<Text_Count)
487                     SUBELEMENT(Text)
488                 else
489                     Skip_XX(6,                                  "Reserved for Text");
490             }
491             Skip_XX(164,                                        "Unknown");
492         Element_End0();
493     Element_End0();
494 
495     //-VTS
496     VTS_Attributes_AreHere=true;
497     Element_Begin1("VTS (VTS for movie, Vob 1-9)");
498         Element_Begin1("Video streams");
499             Element_Info2(1, " streams");
500             SUBELEMENT(Video)
501         Element_End0();
502         Element_Begin1("Audio streams");
503             Get_B2 (Audio_Count,                                "number of audio streams in VMGM_VOBS");
504             Element_Info2(Audio_Count, " streams");
505             for (int16u Pos=0; Pos<8; Pos++)
506             {
507                 if (Pos<Audio_Count)
508                     SUBELEMENT(Audio)
509                 else
510                     Skip_XX(8,                                  "Reserved for Audio");
511             }
512             Skip_XX(16,                                         "Unknown");
513         Element_End0();
514         Element_Begin1("Text streams");
515             Get_B2 (Text_Count,                                 "number of subpicture streams in VMGM_VOBS");
516             Element_Info2(Text_Count, " streams");
517             for (int16u Pos=0; Pos<32; Pos++)
518             {
519                 if (Pos<Text_Count)
520                     SUBELEMENT(Text)
521                 else
522                     Skip_XX(6,                                  "Reserved for Text");
523             }
524             Skip_XX(2,                                          "Unknown");
525         Element_End0();
526         Element_Begin1("MultiChannel Info");
527             Element_Info2(Audio_Count, " streams");
528             for (int16u Pos=0; Pos<8; Pos++)
529             {
530                 if (Pos<Audio_Count)
531                     SUBELEMENT(MultiChannel)
532                 else
533                     Skip_XX(24,                                 "Reserved for multichannel extension");
534             }
535         Element_End0();
536     Element_End0();
537     Skip_XX(2048-Element_Offset,                                "Junk");
538 
539     //Filling
540     FILLING_BEGIN();
541         Fill(Stream_General, 0, General_Format_Profile, "Program");
542 
543         if (Version>0x001F)
544             return;
545         if (Sector_Pointer_LastSector==(int32u)-1 || Sector_Pointer_LastSector+1>File_Size/2048)
546             Sector_Pointer_LastSector=(int32u)(File_Size/2048);
547         Sectors.resize(Sector_Pointer_LastSector+1);
548         if (Sector_Pointer_VTS_PTT_SRPT<=Sector_Pointer_LastSector)
549             Sectors[Sector_Pointer_VTS_PTT_SRPT]=Sector_VTS_PTT_SRPT;
550         if (Sector_Pointer_VTS_PGCI<=Sector_Pointer_LastSector)
551             Sectors[Sector_Pointer_VTS_PGCI]=Sector_VTS_PGCI;
552         if (Sector_Pointer_VTSM_PGCI_UT<=Sector_Pointer_LastSector)
553             Sectors[Sector_Pointer_VTSM_PGCI_UT]=Sector_VTSM_PGCI_UT;
554         if (Sector_Pointer_VTS_TMAPTI<=Sector_Pointer_LastSector)
555             Sectors[Sector_Pointer_VTS_TMAPTI]=Sector_VTS_TMAPTI;
556         if (Sector_Pointer_VTSM_C_ADT<=Sector_Pointer_LastSector)
557             Sectors[Sector_Pointer_VTSM_C_ADT]=Sector_VTSM_C_ADT;
558         if (Sector_Pointer_VTSM_VOBU_ADMAP<=Sector_Pointer_LastSector)
559             Sectors[Sector_Pointer_VTSM_VOBU_ADMAP]=Sector_VTSM_VOBU_ADMAP;
560         if (Sector_Pointer_VTS_C_ADT<=Sector_Pointer_LastSector)
561             Sectors[Sector_Pointer_VTS_C_ADT]=Sector_VTS_C_ADT;
562         if (Sector_Pointer_VTS_VOBU_ADMAP<=Sector_Pointer_LastSector)
563             Sectors[Sector_Pointer_VTS_VOBU_ADMAP]=Sector_VTS_VOBU_ADMAP;
564     FILLING_END();
565 }
566 
567 //---------------------------------------------------------------------------
Video()568 void File_Dvdv::Video()
569 {
570     //Parsing
571     int32u Codec, Standard, AspectRatio, Resolution, BitRate_Mode;
572     BS_Begin();
573     Get_BS (2, Codec,                                           "Coding mode"); Param_Info1(IFO_CodecV[Codec]);
574     Get_BS (2, Standard,                                        "Standard"); Param_Info1(IFO_Standard[Standard]);
575     Get_BS (2, AspectRatio,                                     "Aspect ratio"); Param_Info1(IFO_AspectRatio[AspectRatio]);
576     Info_BS(1, Pan,                                             "Automatic Pan/Scan"); Param_Info1(Pan?"No":"Yes");
577     Info_BS(1, Letter,                                          "Automatic Letterbox"); Param_Info1(Letter?"No":"Yes");
578     Skip_BS(1,                                                  "CC for line 21 field 1 in GOP (NTSC only)");
579     Skip_BS(1,                                                  "CC for line 21 field 2 in GOP (NTSC only)");
580     Get_BS (3, Resolution,                                      "Resolution"); Param_Info1(Ztring::ToZtring(IFO_Width[Resolution])+__T("x")+Ztring::ToZtring(IFO_Height[Standard][Resolution]));
581     Info_BS(1, Letterboxed,                                     "Letterboxed"); Param_Info1(Letter?"Yes":"No");
582     Get_BS (1, BitRate_Mode,                                    "Bitrate mode"); Param_Info1(IFO_BitRate_Mode[BitRate_Mode]);
583     Info_BS(1, Camera,                                          "Camera/Film"); Param_Info1(Letter?"Film":"Camera");
584     BS_End();
585 
586     //Filling
587     FILLING_BEGIN();
588         if (VTS_Attributes_AreHere)
589         {
590             Stream_Prepare(Stream_Video);
591             Fill(Stream_Video, StreamPos_Last, Video_Format, IFO_Format_V[Codec]);
592             Fill(Stream_Video, StreamPos_Last, Video_Format_Version, IFO_Format_Version_V[Codec]);
593             Fill(Stream_Video, StreamPos_Last, Video_Codec, IFO_CodecV[Codec]);
594             Fill(Stream_Video, StreamPos_Last, Video_Width, IFO_Width[Resolution]);
595             Fill(Stream_Video, StreamPos_Last, Video_Height, IFO_Height[Standard][Resolution]);
596             Fill(Stream_Video, StreamPos_Last, Video_DisplayAspectRatio, IFO_AspectRatio[AspectRatio], 3, true);
597             Fill(Stream_Video, StreamPos_Last, Video_FrameRate, IFO_FrameRate[Standard]);
598             Fill(Stream_Video, StreamPos_Last, Video_BitRate_Mode, IFO_BitRate_Mode[BitRate_Mode]);
599             Fill(Stream_Video, StreamPos_Last, General_ID, __T("224"));
600             Fill(Stream_Video, StreamPos_Last, General_ID_String, __T("224 (0xE0)"), Unlimited, true);
601         }
602     FILLING_END();
603 }
604 
605 //---------------------------------------------------------------------------
Audio()606 void File_Dvdv::Audio()
607 {
608     //Parsing
609     Ztring Language;
610     int32u Codec, LanguageType, Mode, Resolution, SamplingRate, Channels;
611     int8u Language_Extension, ChannelsK=(int8u)-1;
612     BS_Begin();
613     Get_BS (3, Codec,                                           "Coding mode"); Param_Info1(IFO_CodecA[Codec]);
614     Info_BS(1, MultiChannel,                                    "Multichannel extension present"); Param_Info1(MultiChannel?"Yes":"No");
615     Get_BS (2, LanguageType,                                    "Language type"); Param_Info1(LanguageType==1?"2CC":"Unknown");
616     Get_BS (2, Mode,                                            "Application mode"); Param_Info1(IFO_ModeA[Mode]);
617     Get_BS (2, Resolution,                                      "Resolution"); Param_Info1C((Codec==2 || Codec==3), IFO_ResolutionA[Resolution]); Param_Info1C((Codec==4), Mode?"DRC":"No DRC");
618     Get_BS (2, SamplingRate,                                    "Sampling rate"); Param_Info1(Ztring::ToZtring(IFO_SamplingRate[SamplingRate]));
619     Get_BS (4, Channels,                                        "Channels"); Param_Info2(Channels+1, " channels");
620     BS_End();
621     Get_UTF8(3, Language,                                       "Language code");
622     if (!Language.empty() && Language[0]>=0x80)
623         Language.clear(); //this is 0xFF...
624     if (Language==__T("iw"))
625         Language=__T("he"); //Hebrew patch, is "iw" in DVDs
626     Get_B1 (Language_Extension,                                 "Language extension"); Param_Info1C((Language_Extension<8), IFO_Language_MoreA[Language_Extension]);
627     Skip_B1(                                                    "Unknown");
628     switch (Mode)
629     {
630         case 1 : //Karaoke
631             {
632             BS_Begin();
633             Skip_BS(1,                                          "Zero");
634             Get_S1 (3, ChannelsK,                               "Channels");
635                 #ifdef MEDIAINFO_AC3_YES
636                     Param_Info1(AC3_ChannelPositions[ChannelsK]);
637                 #endif //MEDIAINFO_AC3_YES
638             Skip_BS(2,                                          "Version");
639             Info_BS(1, MC,                                      "MC intro present"); Param_Info1(MC?"Yes":"No");
640             Info_BS(1, Duet,                                    "Duet"); Param_Info1(Duet?"Duet":"Solo");
641             BS_End();
642             }
643             break;
644         case 2 : //Surround
645             {
646             BS_Begin();
647             Skip_BS(4,                                          "Reserved");
648             Info_BS(1, DolbyDecode,                             "Suitable for Dolby surround decoding"); Param_Info1(DolbyDecode?"Yes":"No");
649             Skip_BS(3,                                          "Reserved");
650             BS_End();
651             }
652             break;
653     default:
654             {
655             Skip_B1(                                            "Reserved");
656             }
657     }
658 
659     //Filling
660     FILLING_BEGIN();
661         if (VTS_Attributes_AreHere)
662         {
663             Stream_Prepare(Stream_Audio);
664             Fill(Stream_Audio, StreamPos_Last, Audio_Format, IFO_Format_A[Codec]);
665             Fill(Stream_Audio, StreamPos_Last, Audio_Format_Profile, IFO_Format_Profile_A[Codec]);
666             Fill(Stream_Audio, StreamPos_Last, Audio_Codec, IFO_CodecA[Codec]);
667             Fill(Stream_Audio, StreamPos_Last, Audio_SamplingRate, IFO_SamplingRate[SamplingRate]);
668             Fill(Stream_Audio, StreamPos_Last, Audio_Channel_s_, Channels+1);
669             if (Codec==3)
670                 Fill(Stream_Audio, StreamPos_Last, Audio_BitDepth, IFO_ResolutionA[Resolution]);
671             else if (Codec==4 && Mode)
672                 Fill(Stream_Audio, StreamPos_Last, Audio_BitDepth, "DRC");
673             Fill(Stream_Audio, StreamPos_Last, Audio_Language, Language);
674             if (Language_Extension<8)
675                 Fill(Stream_Audio, StreamPos_Last, Audio_Language_More, IFO_Language_MoreA[Language_Extension]);
676             #ifdef MEDIAINFO_AC3_YES
677                 if (Codec==0 && ChannelsK!=(int8u)-1) //AC-3
678                 {
679                     Fill(Stream_Audio, 0, Audio_ChannelPositions, AC3_ChannelPositions[ChannelsK]);
680                     Fill(Stream_Audio, 0, Audio_ChannelPositions_String2, AC3_ChannelPositions2[ChannelsK]);
681                 }
682             #endif //MEDIAINFO_AC3_YES
683         }
684     FILLING_END();
685 }
686 
687 //---------------------------------------------------------------------------
Text()688 void File_Dvdv::Text()
689 {
690     //Parsing
691     Ztring Language;
692     int32u Codec, LanguageType;
693     int8u Language_Extension;
694     BS_Begin();
695     Get_BS (3, Codec,                                           "Coding mode"); Param_Info1(IFO_CodecT[Codec]);
696     Skip_BS(3,                                                  "Reserved");
697     Get_BS (2, LanguageType,                                    "Language type"); Param_Info1(LanguageType==1?"2CC":"Unknown");
698     BS_End();
699     Skip_B1(                                                    "Reserved");
700     Get_UTF8(3, Language,                                       "Language code");
701     if (!Language.empty() && Language[0]>=0x80)
702         Language.clear(); //this is 0xFF...
703     if (Language==__T("iw"))
704         Language=__T("he"); //Hebrew patch, is "iw" in DVDs
705     Get_B1 (Language_Extension,                                 "Language extension"); Param_Info1C((Language_Extension<16), IFO_Language_MoreT[Language_Extension]);
706 
707     //Filling
708     FILLING_BEGIN();
709         if (VTS_Attributes_AreHere)
710         {
711             Stream_Prepare(Stream_Text);
712             Fill(Stream_Text, StreamPos_Last, Text_Format, IFO_Format_T[Codec]);
713             Fill(Stream_Text, StreamPos_Last, Text_BitDepth, IFO_Resolution_T[Codec]);
714             Fill(Stream_Text, StreamPos_Last, Text_Codec, IFO_CodecT[Codec]);
715             Fill(Stream_Text, StreamPos_Last, Text_Language, Language);
716 
717             if (Language_Extension<16)
718                  Fill(Stream_Text, StreamPos_Last, Text_Language_More, IFO_Language_MoreT[Language_Extension]);
719         }
720     FILLING_END();
721 }
722 
723 //---------------------------------------------------------------------------
MultiChannel()724 void File_Dvdv::MultiChannel()
725 {
726     //Parsing
727     BS_Begin();
728     Element_Begin1("ACH0");
729         Skip_BS(7,                                              "Reserved");
730         Skip_BS(1,                                              "ACH0 Guide Melody exists");
731     Element_End0();
732     Element_Begin1("ACH1");
733         Skip_BS(7,                                              "Reserved");
734         Skip_BS(1,                                              "ACH1 Guide Melody exists");
735     Element_End0();
736     Element_Begin1("ACH2");
737         Skip_BS(4,                                              "Reserved");
738         Skip_BS(1,                                              "ACH2 Guide Vocal 1 exists");
739         Skip_BS(1,                                              "ACH2 Guide Vocal 2 exists");
740         Skip_BS(1,                                              "ACH2 Guide Melody 1 exists");
741         Skip_BS(1,                                              "ACH2 Guide Melody 2 exists");
742     Element_End0();
743     Element_Begin1("ACH3");
744         Skip_BS(4,                                              "Reserved");
745         Skip_BS(1,                                              "ACH3 Guide Vocal 1 exists");
746         Skip_BS(1,                                              "ACH3 Guide Vocal 2 exists");
747         Skip_BS(1,                                              "ACH3 Guide Melody A exists");
748         Skip_BS(1,                                              "ACH3 Sound Effect A exists");
749     Element_End0();
750     Element_Begin1("ACH4");
751         Skip_BS(4,                                              "Reserved");
752         Skip_BS(1,                                              "ACH4 Guide Vocal 1 exists");
753         Skip_BS(1,                                              "ACH4 Guide Vocal 2 exists");
754         Skip_BS(1,                                              "ACH4 Guide Melody B exists");
755         Skip_BS(1,                                              "ACH4 Sound Effect B exists");
756     Element_End0();
757     BS_End();
758     Skip_XX(19,                                                 "Unknown");
759 }
760 
761 //***************************************************************************
762 // Buffer
763 //***************************************************************************
764 
765 //---------------------------------------------------------------------------
Header_Parse()766 void File_Dvdv::Header_Parse()
767 {
768     //Calculating
769     size_t Sector_Pos=(size_t)((File_Offset+Buffer_Offset)/2048);
770     size_t Sector_Count=1;
771     while (Sector_Pos+Sector_Count<Sectors.size() && Sectors[Sector_Pos+Sector_Count]==Sector_Nothing)
772         Sector_Count++;
773 
774     //Filling
775     Header_Fill_Size(Sector_Count*2048);
776 }
777 
778 //---------------------------------------------------------------------------
Data_Parse()779 void File_Dvdv::Data_Parse()
780 {
781     //Parsing
782     size_t Sector_Pos=(size_t)((File_Offset+Buffer_Offset)/2048);
783     if (Sector_Pos>=Sectors.size())
784     {
785         Accept("DVD Video");
786         Finish("DVD Video");
787         return;
788     }
789 
790     //Parsing
791     switch(Sectors[Sector_Pos])
792     {
793         case Sector_VTS_PTT_SRPT    : VTS_PTT_SRPT(); break;
794         case Sector_VTS_PGCI        : VTS_PGCI(); break;
795         case Sector_VTSM_PGCI_UT    : VTSM_PGCI_UT(); break;
796         case Sector_VTS_TMAPTI      : VTS_TMAPTI(); break;
797         case Sector_VTSM_C_ADT      : VTSM_C_ADT(); break;
798         case Sector_VTSM_VOBU_ADMAP : VTSM_VOBU_ADMAP(); break;
799         case Sector_VTS_C_ADT       : VTS_C_ADT(); break;
800         case Sector_VTS_VOBU_ADMAP  : VTS_VOBU_ADMAP(); break;
801         case Sector_TT_SRPT         : TT_SRPT(); break;
802         case Sector_VMGM_PGCI_UT    : VMGM_PGCI_UT(); break;
803         case Sector_VMG_PTL_MAIT    : VMG_PTL_MAIT(); break;
804         case Sector_VMG_VTS_ATRT    : VMG_VTS_ATRT(); break;
805         case Sector_VMG_TXTDT_MG    : VMG_TXTDT_MG(); break;
806         case Sector_VMGM_C_ADT      : VMGM_C_ADT(); break;
807         case Sector_VMGM_VOBU_ADMAP : VMGM_VOBU_ADMAP(); break;
808         default                     : ;
809     }
810 }
811 
812 //***************************************************************************
813 // Elements
814 //***************************************************************************
815 
816 //---------------------------------------------------------------------------
VTS_PTT_SRPT()817 void File_Dvdv::VTS_PTT_SRPT ()
818 {
819     Element_Name("Table of Titles and Chapters");
820 
821     //Parsing
822     int32u Element_RealSize;
823     Element_Begin1("Header");
824         Skip_B2(                                                "Count of elements");
825         Skip_B2(                                                "Unknown");
826         Get_B4 (Element_RealSize,                               "End address");
827         Element_RealSize++; //Last byte
828     Element_End0();
829     Element_Begin1("Extra data");
830         int32u Offset;
831         Get_B4 (Offset,                                         "Offset of first element");
832         int64u Extra_Size=Offset-Element_Offset;
833         if (Extra_Size>0)
834             Skip_XX(Extra_Size,                                 "Extra data (Unknown)");
835     Element_End0();
836 
837     //For each chapter
838     while (Element_Offset<Element_RealSize)
839     {
840         //VTS_PTT
841         int16u PGCN, PGN;
842         Element_Begin0();
843         Get_B2 (PGCN,                                           "Program Chain (PGCN)");
844         Get_B2 (PGN,                                            "Program (PGN)");
845         Element_Name("Chapter"); Element_Info1(Ztring::ToZtring(PGCN)); Element_Info1(Ztring::ToZtring(PGN));
846         Element_End0();
847     }
848 }
849 
850 //---------------------------------------------------------------------------
VTS_PGCI()851 void File_Dvdv::VTS_PGCI ()
852 {
853     Element_Name("Title Program Chain table");
854 
855     //Parsing
856     int32u EndAddress;
857     Element_Begin1("Header");
858         int32u Offset;
859         Skip_B2(                                                "Number of Program Chains");
860         Skip_B2(                                                "Reserved");
861         Get_B4 (EndAddress,                                     "End address");
862         if (EndAddress>=Element_Size)
863             EndAddress=(int32u)Element_Size-1;
864         Element_Begin1("PGC category");
865             BS_Begin();
866             Skip_BS(1,                                          "entry PGC");
867             Skip_BS(7,                                          "title number");
868             BS_End();
869             Skip_B1(                                            "Unknown");
870             Skip_B2(                                            "parental management mask");
871         Element_End0();
872         Get_B4 (Offset,                                         "offset to VTS_PGC - relative to VTS_PGCI");
873         if (Offset-16>0)
874             Skip_XX(Offset-16,                                  "Unknown");
875     Element_End0();
876 
877     //For each Program
878     //DETAILLEVEL_SET(1.0);
879     while (Element_Offset<=EndAddress)
880     {
881         PGC(Offset, true);
882     }
883 }
884 
885 //---------------------------------------------------------------------------
VTSM_PGCI_UT()886 void File_Dvdv::VTSM_PGCI_UT ()
887 {
888     Element_Name("Menu Program Chain table");
889 
890     //Parsing
891     int16u LU_Count;
892     Element_Begin1("Header");
893         int32u EndAddress, Offset;
894         int8u Flags;
895         Get_B2 (LU_Count,                                       "Number of Language Units");
896         Skip_B2(                                                "Reserved");
897         Get_B4 (EndAddress,                                     "End address");
898         if (EndAddress>=Element_Size)
899             EndAddress=(int32u)Element_Size-1;
900         Skip_C3(                                                "Language");
901         Get_B1 (Flags,                                          "Menu existence flags");
902             Skip_Flags(Flags, 3,                                "PTT");
903             Skip_Flags(Flags, 4,                                "angle");
904             Skip_Flags(Flags, 5,                                "audio");
905             Skip_Flags(Flags, 6,                                "sub-picture");
906             Skip_Flags(Flags, 7,                                "root");
907         Get_B4 (Offset,                                         "Offset to VTSM_LU relative to VTSM_PGCI_UT");
908         if (Offset-16>0)
909             Skip_XX(Offset-16,                                  "Unknown");
910     Element_End0();
911 
912     for (int16u LU_Pos=0; LU_Pos<LU_Count; LU_Pos++)
913     {
914         Element_Begin1("Language Unit");
915         int32u LU_Size;
916         int16u PGC_Count;
917         Element_Begin1("Header");
918             Get_B2 (PGC_Count,                                  "Number of Program Chains");
919             Skip_B2(                                            "Reserved");
920             Get_B4 (LU_Size,                                    "end address (last byte of last PGC in this LU) relative to VTSM_LU");
921             LU_Size++; //Last byte
922             Element_Begin1("PGC category");
923                 int32u EntryPGC;
924                 BS_Begin();
925                 Get_BS (1, EntryPGC,                            "Entry PGC");
926                 Skip_BS(3,                                      "Unknown");
927                 if (EntryPGC)
928                 {
929                     Info_BS(4, MenuType,                        "menu type"); Param_Info1(IFO_MenuType[MenuType]);
930                 }
931                 else
932                 {
933                     Skip_BS(4,                                  "Reserved");
934                 }
935                 BS_End();
936                 Skip_B1(                                        "Unknown");
937                 Skip_B2(                                        "parental management mask");
938             Element_End0();
939             Get_B4 (Offset,                                     "offset to VTSM_PGC relative to VTSM_LU");
940             if (Offset-16>0)
941                 Skip_XX(Offset-16,                              "Unknown");
942         Element_End0();
943         for (int16u PGC_Pos=0; PGC_Pos<PGC_Count; PGC_Pos++)
944             PGC(Element_Offset);
945 
946         Element_End0();
947     }
948 }
949 
950 //---------------------------------------------------------------------------
VTS_TMAPTI()951 void File_Dvdv::VTS_TMAPTI ()
952 {
953     Element_Name("Time map");
954 
955     //Parsing
956     Element_Begin1("Header");
957         int32u EndAddress, Offset;
958         Skip_B2(                                                "Number of program chains");
959         Skip_B2(                                                "Reserved");
960         Get_B4 (EndAddress,                                     "End address");
961         if (EndAddress>=Element_Size)
962             EndAddress=(int32u)Element_Size-1;
963         Get_B4 (Offset,                                         "Offset to VTS_TMAP 1");
964         if (Offset-12>0)
965             Skip_XX(Offset-12,                                  "Unknown");
966     Element_End0();
967 
968     //DETAILLEVEL_SET(1.0);
969     while (Element_Offset<=EndAddress)
970     {
971         //VTS_TMAP
972         Element_Begin1("Time Map");
973         //std::vector<size_t> Sector_Times;
974         int8u Sector_Times_SecondsPerTime;
975         int16u Count;
976         Get_B1 (Sector_Times_SecondsPerTime,                    "Time unit (seconds)");
977         Skip_B1(                                                "Unknown");
978         Get_B2 (Count,                                          "Number of entries in map");
979         //Sector_Times.resize(Count);
980         BS_Begin();
981         for (int16u Pos=0; Pos<Count; Pos++)
982         {
983             Element_Begin1("Sector Offset");
984             int32u SectorOffset;
985             Skip_BS( 1,                                         "discontinuous with previous");
986             Get_BS (31, SectorOffset,                           "Sector offset within VOBS of nearest VOBU");
987             //Get_B4 (Sector_Times[Pos],                          Sector offset within VOBS of nearest VOBU);// Param_Info1(Ztring().Duration_From_Milliseconds((Pos+1)*Sectors_Times_SecondsPerTime[Program_Pos]));
988             //Sector_Times[Pos]&=0x7FFFFFFF; //bit 31 is set if VOBU time codes are discontinuous with previous
989             Element_Info1(SectorOffset);
990             Element_End0();
991         }
992         BS_End();
993         Element_End0();
994 
995         //Filling
996         //Sectors_Times.push_back(Sector_Times);
997         //Sectors_Times_SecondsPerTime.push_back(Sector_Times_SecondsPerTime);
998     }
999 }
1000 
1001 //---------------------------------------------------------------------------
VTSM_C_ADT()1002 void File_Dvdv::VTSM_C_ADT ()
1003 {
1004     Element_Name("Menu cell address table");
1005 
1006     //Parsing
1007     int32u EndAddress;
1008     Element_Begin1("Header");
1009         Skip_B2(                                                "Number of cells");
1010         Skip_B2(                                                "Reserved");
1011         Get_B4 (EndAddress,                                     "End address");
1012         if (EndAddress>=Element_Size)
1013             EndAddress=(int32u)Element_Size-1;
1014     Element_End0();
1015 
1016     //DETAILLEVEL_SET(1.0);
1017     while (Element_Offset<=EndAddress)
1018     {
1019         //ADT
1020         Element_Begin1("Entry");
1021         Skip_B2(                                                "VOBidn");
1022         Skip_B1(                                                "CELLidn");
1023         Skip_B1(                                                "Unknown");
1024         Skip_B4(                                                "Starting sector within VOB");
1025         Skip_B4(                                                "Ending sector within VOB");
1026         Element_End0();
1027     }
1028 }
1029 
1030 //---------------------------------------------------------------------------
VTSM_VOBU_ADMAP()1031 void File_Dvdv::VTSM_VOBU_ADMAP ()
1032 {
1033     Element_Name("Menu VOBU address map");
1034 
1035     //Parsing
1036     int32u EndAddress;
1037     Element_Begin1("Header");
1038         Get_B4 (EndAddress,                                     "End address");
1039         if (EndAddress>=Element_Size)
1040             EndAddress=(int32u)Element_Size-1;
1041     Element_End0();
1042 
1043     //DETAILLEVEL_SET(1.0);
1044     while (Element_Offset<=EndAddress)
1045     {
1046         //ADMAP
1047         Skip_B4(                                                "Starting sector within VOB of first VOBU");
1048     }
1049 }
1050 
1051 //---------------------------------------------------------------------------
VTS_C_ADT()1052 void File_Dvdv::VTS_C_ADT ()
1053 {
1054     Element_Name("Title set cell address table");
1055 
1056     //Parsing
1057     int32u EndAddress;
1058     Element_Begin1("Header");
1059         Skip_B2(                                                "Number of cells");
1060         Skip_B2(                                                "Reserved");
1061         Get_B4 (EndAddress,                                     "End address");
1062         if (EndAddress>=Element_Size)
1063             EndAddress=(int32u)Element_Size-1;
1064     Element_End0();
1065 
1066     //DETAILLEVEL_SET(1.0);
1067     while (Element_Offset<=EndAddress)
1068     {
1069         //ADT
1070         Element_Begin1("Entry");
1071         int32u Start, End;
1072         int16u VOBidn;
1073         int8u CELLidn;
1074         Get_B2 (VOBidn,                                         "VOBidn");
1075         Get_B1 (CELLidn,                                        "CELLidn");
1076         Skip_B1(                                                "Unknown");
1077         Get_B4 (Start,                                          "Starting sector within VOB"); Param_Info1(Time_ADT(Start));
1078         Get_B4 (End,                                            "Ending sector within VOB"); Param_Info1(Time_ADT(End));
1079         Element_End0();
1080 
1081         //Filling
1082         FILLING_BEGIN();
1083         FILLING_END();
1084         //Fill(Ztring::ToZtring(CELLidn).To_Local().c_str(), Time_ADT(Start));
1085     }
1086 }
1087 
1088 //---------------------------------------------------------------------------
VTS_VOBU_ADMAP()1089 void File_Dvdv::VTS_VOBU_ADMAP ()
1090 {
1091     Element_Name("Title set VOBU address map");
1092 
1093     //Parsing
1094     int32u EndAddress;
1095     Element_Begin1("Header");
1096         Get_B4 (EndAddress,                                     "End address");
1097         if (EndAddress>=Element_Size)
1098             EndAddress=(int32u)Element_Size-1;
1099     Element_End0();
1100 
1101     //DETAILLEVEL_SET(1.0);
1102     while (Element_Offset<Element_Size)
1103     {
1104         //ADMAP
1105         Skip_B4(                                                "Starting sector within VOB of first VOBU");
1106     }
1107 }
1108 
1109 //***************************************************************************
1110 // Helpers
1111 //***************************************************************************
1112 
1113 //---------------------------------------------------------------------------
Time_ADT(int32u)1114 Ztring File_Dvdv::Time_ADT(int32u)
1115 {
1116     return Ztring();
1117     /*
1118     if (Sectors_Times.empty())
1119         return Ztring(); //TODO: it can be empty?
1120 
1121     while (Time_Pos<Sectors_Times[Program_Pos].size() && Sectors_Times[Program_Pos][Time_Pos]<Value)
1122         Time_Pos++;
1123     if (Time_Pos<Sectors_Times[Program_Pos].size())
1124     {
1125         int32u Time=(Time_Pos+1)*Sectors_Times_SecondsPerTime[Program_Pos]*1000;
1126         float32 Part;
1127         //True time is between Time and Time+Sectors_Times_SecondsPerTime, finding where...
1128         int32u Sectors_Count;
1129         if (Time_Pos==0)
1130             Sectors_Count=Sectors_Times[Program_Pos][Time_Pos];
1131         else
1132             Sectors_Count=Sectors_Times[Program_Pos][Time_Pos]-Sectors_Times[Program_Pos][Time_Pos-1];
1133         Part=(Sectors_Times[Program_Pos][Time_Pos]-Value); //Count of more sectors after
1134         Part/=Sectors_Count; //Percentage
1135         Time=(int32u)((Time_Pos+1-Part)*Sectors_Times_SecondsPerTime[Program_Pos]*1000);
1136 
1137         return Ztring().Duration_From_Milliseconds(Time*1000);
1138     }
1139     else
1140     {
1141         int32u Time=(Time_Pos+1)*Sectors_Times_SecondsPerTime[Program_Pos]*1000;
1142         float32 Part;
1143         //True time is between Time and Time+Sectors_Times_SecondsPerTime, finding where... but with the last offset diffrence
1144         int32u Sectors_Count=Sectors_Times[Program_Pos][Time_Pos-1]-Sectors_Times[Program_Pos][Time_Pos-2];
1145         Part=((int32s)Sectors_Times[Program_Pos][Time_Pos-1])-((int32s)Value); //Count of more sectors after
1146         Part/=Sectors_Count; //Percentage
1147         Part+=1; //We were one offset less
1148         Time=(int32u)((Time_Pos+1-Part)*Sectors_Times_SecondsPerTime[Program_Pos]*1000);
1149 
1150         return Ztring().Duration_From_Milliseconds(Time*1000);
1151     }
1152     */
1153 }
1154 
Get_Duration(int64u & Duration,const Ztring & Name)1155 void File_Dvdv::Get_Duration(int64u  &Duration, const Ztring &Name)
1156 {
1157     int32u FrameRate, FF;
1158     int8u HH, MM, Sec;
1159     Element_Begin1(Name);
1160         Get_B1 (HH,                                     "Hours (BCD)");
1161         Get_B1 (MM,                                     "Minutes (BCD)");
1162         Get_B1 (Sec,                                     "Seconds (BCD)");
1163         BS_Begin();
1164         Get_BS (2, FrameRate,                           "Frame rate"); Param_Info2(IFO_PlaybackTime_FrameRate[FrameRate], " fps");
1165         Get_BS (6, FF,                                  "Frames (BCD)");
1166         BS_End();
1167 
1168         Duration= Ztring::ToZtring(HH, 16).To_int64u() * 60 * 60 * 1000 //BCD
1169                 + Ztring::ToZtring(MM, 16).To_int64u()      * 60 * 1000 //BCD
1170                 + Ztring::ToZtring(Sec, 16).To_int64u()          * 1000 //BCD
1171                 + Ztring::ToZtring(FF, 16).To_int64u()           * 1000/IFO_PlaybackTime_FrameRate[FrameRate]; //BCD
1172 
1173         Element_Info1(Ztring::ToZtring(Duration));
1174     Element_End0();
1175 }
1176 
1177 
PGC(int64u Offset,bool Title)1178 void File_Dvdv::PGC(int64u Offset, bool Title)
1179 {
1180         vector<int8u> Stream_Control_Audio;
1181         vector<int8u> Stream_Control_SubPicture_43;
1182         vector<int8u> Stream_Control_SubPicture_Wide;
1183         vector<int8u> Stream_Control_SubPicture_Letterbox;
1184         vector<int8u> Stream_Control_SubPicture_PanScan;
1185         vector<int64u> CellDurations;
1186         vector<int8u> ProgramMap;
1187 
1188         //VTS_PGC
1189         Element_Begin1("PGC");
1190         int16u commands, program_map, cell_playback, cell_position;
1191         int8u Program_Count;
1192         Element_Begin1("Header");
1193             int32u Flags;
1194             int8u Cells;
1195             int64u TotalDuration;
1196             Skip_B2(                                            "Unknown");
1197             Get_B1 (Program_Count,                              "number of programs");
1198             Get_B1 (Cells,                                      "number of cells");
1199             Get_Duration(TotalDuration,                         "Duration");
1200             Get_B4 (Flags,                                      "prohibited user ops");
1201                 /*Skip_Flags(Flags,  0,                           "Time play or search");
1202                 Skip_Flags(Flags,  1, PTT play or search);
1203                 Skip_Flags(Flags,  2, Title play);
1204                 Skip_Flags(Flags,  3, Stop);
1205                 Skip_Flags(Flags,  4, GoUp);
1206                 Skip_Flags(Flags,  5, Time or PTT search);
1207                 Skip_Flags(Flags,  6, TopPG or PrevPG search);
1208                 Skip_Flags(Flags,  7, NextPG search);
1209                 Skip_Flags(Flags,  8, Forward scan);
1210                 Skip_Flags(Flags,  9, Backward scan);
1211                 Skip_Flags(Flags, 10, Menu call - Title);
1212                 Skip_Flags(Flags, 11, Menu call - Root);
1213                 Skip_Flags(Flags, 12, Menu call - Subpicture);
1214                 Skip_Flags(Flags, 13, Menu call - Audio);
1215                 Skip_Flags(Flags, 14, Menu call - Angle);
1216                 Skip_Flags(Flags, 15, Menu call - PTT);
1217                 Skip_Flags(Flags, 16, Resume);
1218                 Skip_Flags(Flags, 17, Button select or activate);
1219                 Skip_Flags(Flags, 18, Still off);
1220                 Skip_Flags(Flags, 19, Pause on);
1221                 Skip_Flags(Flags, 20, Audio stream change);
1222                 Skip_Flags(Flags, 21, Subpicture stream change);
1223                 Skip_Flags(Flags, 22, Angle change);
1224                 Skip_Flags(Flags, 23, Karaoke audio mix change);
1225                 Skip_Flags(Flags, 24, Video presentation mode change);
1226                 */
1227                 /*
1228                 Skip_Flags(Flags,  0, Video presentation mode change);
1229                 Skip_Flags(Flags,  1, Karaoke audio mix change);
1230                 Skip_Flags(Flags,  2, Angle change);
1231                 Skip_Flags(Flags,  3, Subpicture stream change);
1232                 Skip_Flags(Flags,  4, Audio stream change);
1233                 Skip_Flags(Flags,  5, Pause on);
1234                 Skip_Flags(Flags,  6, Still off);
1235                 Skip_Flags(Flags,  7, Button select or activate);
1236                 Skip_Flags(Flags,  8, Resume);
1237                 Skip_Flags(Flags,  9, Menu call - PTT);
1238                 Skip_Flags(Flags, 10, Menu call - Angle);
1239                 Skip_Flags(Flags, 11, Menu call - Audio);
1240                 Skip_Flags(Flags, 12, Menu call - Subpicture);
1241                 Skip_Flags(Flags, 13, Menu call - Root);
1242                 Skip_Flags(Flags, 14, Menu call - Title);
1243                 Skip_Flags(Flags, 15, Backward scan);
1244                 Skip_Flags(Flags, 16, Forward scan);
1245                 Skip_Flags(Flags, 17, NextPG search);
1246                 Skip_Flags(Flags, 18, TopPG or PrevPG search);
1247                 Skip_Flags(Flags, 19, Time or PTT search);
1248                 Skip_Flags(Flags, 20, GoUp);
1249                 Skip_Flags(Flags, 21, Stop);
1250                 Skip_Flags(Flags, 22, Title play);
1251                 Skip_Flags(Flags, 23, PTT play or search);
1252                 Skip_Flags(Flags, 24,                               Time play or search);
1253                 */
1254             Element_Begin1("Audio Stream Controls");
1255             for (size_t Pos=0; Pos<8; Pos++)
1256             {
1257                 Element_Begin1("Audio Stream Control");
1258                 Element_Info1(Ztring::ToZtring(Pos));
1259                 int8u Number;
1260                 bool  Available;
1261                 BS_Begin();
1262                 Get_SB (   Available,                           "Stream available");
1263                 Get_S1 (7, Number,                              "Stream number");
1264                 BS_End();
1265                 Skip_B1(                                        "Reserved");
1266                 Element_End0();
1267                 if (Available)
1268                     Stream_Control_Audio.push_back(Number);
1269 
1270                 if (Available && Retrieve(Stream_Audio, Pos, Text_ID).empty() && Sectors[(size_t)((File_Offset+Buffer_Offset)/2048)]==Sector_VTS_PGCI)
1271                 {
1272                     while (Pos>Count_Get(Stream_Audio))
1273                         Stream_Prepare(Stream_Audio);
1274 
1275                     int8u ToAdd=0;
1276                     if (Retrieve(Stream_Audio, Pos, Audio_Format)==__T("AC-3"))
1277                         ToAdd=0x80;
1278                     if (Retrieve(Stream_Audio, Pos, Audio_Format)==__T("DTS"))
1279                         ToAdd=0x88;
1280                     if (Retrieve(Stream_Audio, Pos, Audio_Format)==__T("LPCM"))
1281                         ToAdd=0xA0;
1282                     Ztring ID_String = Get_Hex_ID(ToAdd + Number);
1283                     Fill(Stream_Audio, Pos, Audio_ID, ID_String);
1284                     Fill(Stream_Audio, Pos, Audio_ID_String, ID_String, true);
1285                 }
1286             }
1287             Element_End0();
1288             Element_Begin1("Subpicture Stream Controls");
1289             for (size_t Pos=0; Pos<32; Pos++)
1290             {
1291                 Element_Begin1("Subpicture Stream Control");
1292                 Element_Info1(Ztring::ToZtring(Pos));
1293                 int8u Number_43, Number_Wide, Number_Letterbox, Number_PanScan;
1294                 bool  Available;
1295                 BS_Begin();
1296                 Get_SB (   Available,                           "Stream available");
1297                 Get_S1 (7, Number_43,                           "Stream number for 4/3");
1298                 BS_End();
1299                 Get_B1 (Number_Wide,                            "Stream number for Wide");
1300                 Get_B1 (Number_Letterbox,                       "Stream number for Letterbox");
1301                 Get_B1 (Number_PanScan,                         "Stream number for Pan&Scan");
1302                 Element_End0();
1303                 if (Available)
1304                 {
1305                     Stream_Control_SubPicture_43.push_back(Number_43);
1306                     Stream_Control_SubPicture_Wide.push_back(Number_Wide);
1307                     Stream_Control_SubPicture_Letterbox.push_back(Number_Letterbox);
1308                     Stream_Control_SubPicture_PanScan.push_back(Number_PanScan);
1309                 }
1310 
1311                 if (Available && Retrieve(Stream_Text, Pos, Text_ID).empty() && Sectors[(size_t)((File_Offset+Buffer_Offset)/2048)]==Sector_VTS_PGCI)
1312                 {
1313                     while (Pos>Count_Get(Stream_Text))
1314                         Stream_Prepare(Stream_Text);
1315 
1316                     Ztring ID_String = Get_Hex_ID(0x20 + Number_Wide);
1317                     Fill(Stream_Text, Pos, Text_ID, ID_String);
1318                     Fill(Stream_Text, Pos, Text_ID_String, ID_String, true);
1319                 }
1320             }
1321             Element_End0();
1322             Skip_B2(                                            "next PGCN");
1323             Skip_B2(                                            "previous PGCN");
1324             Skip_B2(                                            "goup PGCN");
1325             Skip_B1(                                            "PGC still time - 255=infinite");
1326             Skip_B1(                                            "PG playback mode");
1327             Element_Begin1("palette");
1328             for (int Pos=0; Pos<16; Pos++)
1329             {
1330                 Skip_B4(                                        "palette (0 - Y - Cr - Cb)");
1331             }
1332             Element_End0();
1333             Get_B2 (commands,                                   "offset within PGC to commands");
1334             Get_B2 (program_map,                                "offset within PGC to program map");
1335             Get_B2 (cell_playback,                              "offset within PGC to cell playback information table");
1336             Get_B2 (cell_position,                              "offset within PGC to cell position information table");
1337         Element_End0();
1338 
1339         //commands
1340         if (commands>0)
1341         {
1342             if (Element_Offset<Offset+commands)
1343             {
1344                 if (Offset+commands>Element_Size)
1345                 {
1346                     Skip_XX(Element_Size-Element_Offset,            "Unknown");
1347                     return;
1348                 }
1349                 Skip_XX(Offset+commands-Element_Offset,             "Unknown");
1350             }
1351             Element_Begin1("commands");
1352             int16u PreCommands_Count, PostCommands_Count, CellCommands_Count, EndAdress;
1353             Get_B2 (PreCommands_Count,                          "Number of pre commands");
1354             Get_B2 (PostCommands_Count,                         "Number of post commands");
1355             Get_B2 (CellCommands_Count,                         "Number of cell commands");
1356             Get_B2 (EndAdress,                                  "End address relative to command table");
1357             if (PreCommands_Count>0)
1358             {
1359                 Element_Begin1("Pre commands");
1360                     for (int16u Pos=0; Pos<PreCommands_Count; Pos++)
1361                     {
1362                         Element_Begin1("Pre command");
1363                         Skip_XX(8,                              "Pre command");
1364                         Element_End0();
1365                     }
1366                 Element_End0();
1367             }
1368             if (PostCommands_Count>0)
1369             {
1370                 Element_Begin1("Post commands");
1371                     for (int16u Pos=0; Pos<PostCommands_Count; Pos++)
1372                     {
1373                         Element_Begin1("Post command");
1374                         Skip_XX(8,                              "Post command");
1375                         Element_End0();
1376                     }
1377                 Element_End0();
1378             }
1379             if (CellCommands_Count>0)
1380             {
1381                 Element_Begin1("Cell commands");
1382                     for (int16u Pos=0; Pos<CellCommands_Count; Pos++)
1383                     {
1384                         Element_Begin1("Cell command");
1385                         Skip_XX(8,                              "Cell command");
1386                         Element_End0();
1387                     }
1388                 Element_End0();
1389             }
1390             Element_End0();
1391         }
1392 
1393         //program map
1394         if (program_map>0)
1395         {
1396             if (Element_Offset<Offset+program_map)
1397                 Skip_XX(Offset+program_map-Element_Offset,          "Unknown");
1398             Element_Begin1("program map");
1399             for (int8u Pos=0; Pos<Program_Count; Pos++)
1400             {
1401                 Element_Begin1("Entry");
1402                 int8u entry;
1403                 Get_B1( entry,  "Entry cell number");
1404                 ProgramMap.push_back(entry);
1405                 //Skip_B1(                                        "Entry cell number");
1406                 Element_End0();
1407             }
1408             Element_End0();
1409         }
1410 
1411         //cell playback
1412         if (cell_playback>0)
1413         {
1414             if (Element_Offset<Offset+cell_playback)
1415                 Skip_XX(Offset+cell_playback-Element_Offset,        "Unknown");
1416             Element_Begin1("cell playback");
1417             for (int8u Pos=0; Pos<Cells; Pos++)
1418             {
1419                 int64u CellDuration;
1420                 Element_Begin1("cell");
1421                 Skip_XX(4,                                      "ToDo");
1422                 Get_Duration(CellDuration,                      "Time");
1423                 Skip_B4(                                        "first VOBU start sector");
1424                 Skip_B4(                                        "first ILVU end sector");
1425                 Skip_B4(                                        "last VOBU start sector");
1426                 Skip_B4(                                        "last VOBU end sector");
1427                 Element_Info1(Ztring::ToZtring(Pos)); Element_Info1(Ztring::ToZtring(CellDuration));
1428                 Element_End0();
1429 
1430                 CellDurations.push_back(CellDuration);
1431             }
1432             Element_End0();
1433         }
1434 
1435         //cell position
1436         if (cell_position>0)
1437         {
1438             if (Element_Offset<Offset+cell_position)
1439                 Skip_XX(Offset+cell_position-Element_Offset,        "Unknown");
1440             Element_Begin1("cell position");
1441             for (int8u Pos=0; Pos<Cells; Pos++)
1442             {
1443                 Element_Begin1("cell");
1444                 Skip_B2(                                        "VOBid");
1445                 Skip_B1(                                        "reserved");
1446                 Skip_B1(                                        "Cell id");
1447                 Element_End0();
1448             }
1449             Element_End0();
1450         }
1451 
1452         Element_End0();
1453 
1454         FILLING_BEGIN();
1455             if (Title)
1456             {
1457                 Stream_Prepare(Stream_Menu);
1458 
1459                 int64u ProgramTotalDuration=0;
1460                 Fill(Stream_Menu, StreamPos_Last, Menu_Chapters_Pos_Begin, Count_Get(Stream_Menu, StreamPos_Last), 10, true);
1461                 for (int8u Pos=0; Pos<ProgramMap.size(); Pos++)
1462                 {
1463                     Fill(StreamKind_Last, StreamPos_Last, Ztring().Duration_From_Milliseconds(ProgramTotalDuration).To_Local().c_str(), Ztring(__T("Chapter "))+Ztring::ToZtring(Pos+1));
1464 
1465                     int8u End;
1466                     if (Pos+1>=Program_Count)
1467                         End=Cells+1;
1468                     else
1469                         End=ProgramMap[Pos+1];
1470 
1471                     int64u ProgramDuration=0;
1472                     if (Pos<ProgramMap.size())
1473                         for (int8u CellPos=ProgramMap[Pos]; CellPos<End; CellPos++)
1474                             if (CellPos && CellPos<=CellDurations.size())
1475                                 ProgramDuration+=CellDurations[CellPos-1];
1476                     ProgramTotalDuration+=ProgramDuration;
1477                 }
1478                 Fill(Stream_Menu, StreamPos_Last, Menu_Chapters_Pos_End, Count_Get(Stream_Menu, StreamPos_Last), 10, true);
1479                 Fill(Stream_Menu, StreamPos_Last, Menu_Duration, TotalDuration);
1480 
1481                 for (size_t Pos=0; Pos<Stream_Control_Audio.size(); Pos++)
1482                 {
1483                     Fill(StreamKind_Last, StreamPos_Last, "List (Audio)", Stream_Control_Audio[Pos]);
1484                 }
1485                 for (size_t Pos=0; Pos<Stream_Control_SubPicture_43.size(); Pos++)
1486                 {
1487                     Fill(StreamKind_Last, StreamPos_Last, "List (Subtitles 4/3)", Stream_Control_SubPicture_43[Pos]);
1488                 }
1489                 for (size_t Pos=0; Pos<Stream_Control_SubPicture_Wide.size(); Pos++)
1490                 {
1491                     Fill(StreamKind_Last, StreamPos_Last, "List (Subtitles Wide)", Stream_Control_SubPicture_Wide[Pos]);
1492                 }
1493                 for (size_t Pos=0; Pos<Stream_Control_SubPicture_Letterbox.size(); Pos++)
1494                 {
1495                     Fill(StreamKind_Last, StreamPos_Last, "List (Subtitles Letterbox)", Stream_Control_SubPicture_Letterbox[Pos]);
1496                 }
1497                 for (size_t Pos=0; Pos<Stream_Control_SubPicture_PanScan.size(); Pos++)
1498                 {
1499                     Fill(StreamKind_Last, StreamPos_Last, "List (Subtitles Pan&Scan)", Stream_Control_SubPicture_PanScan[Pos]);
1500                 }
1501             }
1502         FILLING_END();
1503 }
1504 
1505 //---------------------------------------------------------------------------
TT_SRPT()1506 void File_Dvdv::TT_SRPT()
1507 {
1508     Element_Name("table of titles");
1509 }
1510 
1511 //---------------------------------------------------------------------------
VMGM_PGCI_UT()1512 void File_Dvdv::VMGM_PGCI_UT()
1513 {
1514     Element_Name("Menu Program Chain table");
1515 }
1516 
1517 //---------------------------------------------------------------------------
VMG_PTL_MAIT()1518 void File_Dvdv::VMG_PTL_MAIT()
1519 {
1520     Element_Name("Parental Management masks");
1521 }
1522 
1523 //---------------------------------------------------------------------------
VMG_VTS_ATRT()1524 void File_Dvdv::VMG_VTS_ATRT()
1525 {
1526     Element_Name("copies of VTS audio/sub-picture attributes");
1527 
1528     //Parsing
1529     int32u EndAddress;
1530     Element_Begin1("Header");
1531         int32u Offset;
1532         Skip_B4(                                                "Number of title sets");
1533         Get_B4 (EndAddress,                                     "End address");
1534         if (EndAddress>=Element_Size)
1535             EndAddress=(int32u)Element_Size-1;
1536         Get_B4 (Offset,                                         "Offset to VTSM_LU relative to VTSM_PGCI_UT");
1537         if (Offset-12>0)
1538             Skip_XX(Offset-12,                                  "Unknown");
1539     Element_End0();
1540 
1541     while (Element_Offset<=EndAddress)
1542     {
1543         Element_Begin1("VTS_ATRT");
1544             Element_Begin1("Header");
1545                 int32u Size;
1546                 Get_B4 (Size,                                   "End address");
1547                 Size++; //Last byte
1548             Element_End0();
1549             Element_Begin1("Copy of VTS Category");
1550                 Skip_B4(                                        "VTS Category");
1551             Element_End0();
1552             Element_Begin1("Copy of VTS attributes");
1553                 Skip_XX(Size-8,                                 "VTS attributes");
1554             Element_End0();
1555         Element_End0();
1556     }
1557 }
1558 
1559 //---------------------------------------------------------------------------
VMG_TXTDT_MG()1560 void File_Dvdv::VMG_TXTDT_MG()
1561 {
1562     Element_Name("text data");
1563 }
1564 
1565 //---------------------------------------------------------------------------
VMGM_C_ADT()1566 void File_Dvdv::VMGM_C_ADT()
1567 {
1568     Element_Name("menu cell address table");
1569 }
1570 
1571 //---------------------------------------------------------------------------
VMGM_VOBU_ADMAP()1572 void File_Dvdv::VMGM_VOBU_ADMAP()
1573 {
1574     Element_Name("menu VOBU address map");
1575 }
1576 
1577 } //NameSpace
1578 
1579 #endif //MEDIAINFO_DVDV_YES
1580