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