1 /*****************************************************************************
2 * dvd_ifo.c: Functions for ifo parsing
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: dvd_ifo.c,v 1.3 2001/02/08 17:44:12 massiot Exp $
7 * Author: Stéphane Borel <stef@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
36 #include "input_dvd.h"
42 /*****************************************************************************
43 * IfoFindVMG : When reading directly on a device, finds the offset to the
44 * beginning of video_ts.ifo.
45 *****************************************************************************/
46 static int IfoFindVMG( ifo_t* p_ifo )
48 char psz_ifo_start[12] = "DVDVIDEO-VMG";
51 read( p_ifo->i_fd, psz_test, 12 );
53 while( strncmp( psz_test, psz_ifo_start, 12 ) != 0 )
55 /* The start of ifo file is on a sector boundary */
56 p_ifo->i_pos = lseek( p_ifo->i_fd,
57 p_ifo->i_pos + DVD_LB_SIZE,
59 read( p_ifo->i_fd, psz_test, 12 );
61 p_ifo->i_off = p_ifo->i_pos;
63 //fprintf( stderr, "VMG Off : %lld\n", (long long)(p_ifo->i_off) );
68 /*****************************************************************************
69 * IfoFindVTS : beginning of vts_*.ifo.
70 *****************************************************************************/
71 static int IfoFindVTS( ifo_t* p_ifo )
73 char psz_ifo_start[12] = "DVDVIDEO-VTS";
76 read( p_ifo->i_fd, psz_test, 12 );
78 while( strncmp( psz_test, psz_ifo_start, 12 ) != 0 )
80 /* The start of ifo file is on a sector boundary */
81 p_ifo->i_pos = lseek( p_ifo->i_fd,
82 p_ifo->i_pos + DVD_LB_SIZE,
84 read( p_ifo->i_fd, psz_test, 12 );
86 p_ifo->i_off = p_ifo->i_pos;
88 //fprintf( stderr, "VTS Off : %lld\n", (long long)(p_ifo->i_off) );
93 /*****************************************************************************
94 * IfoInit : Creates an ifo structure and prepares for parsing directly
96 *****************************************************************************/
97 ifo_t IfoInit( int i_fd )
101 /* If we are here the dvd device has already been opened */
103 /* No data at the beginning of the disk
104 * 512000 bytes is just another value :) */
105 ifo.i_pos = lseek( ifo.i_fd, 250 *DVD_LB_SIZE, SEEK_SET );
106 /* FIXME : use udf filesystem to find the beginning of the file */
112 /*****************************************************************************
113 * IfoEnd : Frees all the memory allocated to ifo structures
114 *****************************************************************************/
115 void IfoEnd( ifo_t* p_ifo )
119 /* Free structures from video title sets */
120 for( j=0 ; j<p_ifo->vmg.mat.i_tts_nb ; j++ )
122 free( p_ifo->p_vts[j].vobu_admap.pi_vobu_ssector );
123 free( p_ifo->p_vts[j].c_adt.p_cell_inf );
124 free( p_ifo->p_vts[j].m_vobu_admap.pi_vobu_ssector );
125 free( p_ifo->p_vts[j].m_c_adt.p_cell_inf );
126 for( i=0 ; i<p_ifo->p_vts[j].tmap_ti.i_nb ; i++ )
128 free( p_ifo->p_vts[j].tmap_ti.p_tmap[i].pi_sector );
130 free( p_ifo->p_vts[j].tmap_ti.pi_sbyte );
131 free( p_ifo->p_vts[j].tmap_ti.p_tmap );
132 free( p_ifo->p_vts[j].pgci_ti.p_srp );
133 for( i=0 ; i<p_ifo->p_vts[j].pgci_ut.i_lu_nb ; i++ )
135 free( p_ifo->p_vts[j].pgci_ut.p_pgci_inf[i].p_srp );
137 free( p_ifo->p_vts[j].pgci_ut.p_pgci_inf );
138 free( p_ifo->p_vts[j].pgci_ut.p_lu );
141 free( p_ifo->p_vts );
143 /* Free structures from video manager */
144 free( p_ifo->vmg.vobu_admap.pi_vobu_ssector );
145 free( p_ifo->vmg.c_adt.p_cell_inf );
146 for( i=0 ; i<p_ifo->vmg.pgci_ut.i_lu_nb ; i++ )
148 free( p_ifo->vmg.pgci_ut.p_pgci_inf[i].p_srp );
150 free( p_ifo->vmg.pgci_ut.p_pgci_inf );
151 free( p_ifo->vmg.pgci_ut.p_lu );
152 for( i=1 ; i<=8 ; i++ )
154 free( p_ifo->vmg.ptl_mait.p_ptl_mask->ppi_ptl_mask[i] );
156 free( p_ifo->vmg.ptl_mait.p_ptl_desc );
157 free( p_ifo->vmg.ptl_mait.p_ptl_mask );
158 free( p_ifo->vmg.vts_atrt.pi_vts_atrt_sbyte );
159 free( p_ifo->vmg.vts_atrt.p_vts_atrt );
160 free( p_ifo->vmg.pgc.p_cell_pos_inf );
161 free( p_ifo->vmg.pgc.p_cell_play_inf );
162 free( p_ifo->vmg.pgc.prg_map.pi_entry_cell );
163 free( p_ifo->vmg.pgc.com_tab.p_cell_com );
164 free( p_ifo->vmg.pgc.com_tab.p_post_com );
165 free( p_ifo->vmg.pgc.com_tab.p_pre_com );
171 * Macros to process ifo files
174 #define GET( p_field , i_len ) \
176 read( p_ifo->i_fd , (p_field) , (i_len) ); \
177 /*fprintf(stderr, "Pos : %lld Val : %llx\n", \
178 (long long)(p_ifo->i_pos - i_start), \
179 (long long)*(p_field) ); */ \
180 p_ifo->i_pos += i_len; \
183 #define GETC( p_field ) \
185 read( p_ifo->i_fd , (p_field) , 1 ); \
186 /*fprintf(stderr, "Pos : %lld Value : %d\n", \
187 (long long)(p_ifo->i_pos - i_start), \
192 #define GETS( p_field ) \
194 read( p_ifo->i_fd , (p_field) , 2 ); \
195 *(p_field) = ntohs( *(p_field) ); \
196 /*fprintf(stderr, "Pos : %lld Value : %d\n", \
197 (long long)(p_ifo->i_pos - i_start), \
202 #define GETL( p_field ) \
204 read( p_ifo->i_fd , (p_field) , 4 ); \
205 *(p_field) = ntohl( *(p_field) ); \
206 /*fprintf(stderr, "Pos : %lld Value : %d\n", \
207 (long long)(p_ifo->i_pos - i_start), \
212 #define GETLL( p_field ) \
214 read( p_ifo->i_fd , (p_field) , 8 ); \
215 *(p_field) = ntoh64( *(p_field) ); \
216 /*fprintf(stderr, "Pos : %lld Value : %lld\n", \
217 (long long)(p_ifo->i_pos - i_start), \
222 #define FLUSH( i_len ) \
224 /*fprintf(stderr, "Pos : %lld\n", (long long)(p_ifo->i_pos - i_start));*/ \
225 p_ifo->i_pos = lseek( p_ifo->i_fd , \
226 p_ifo->i_pos + (i_len), SEEK_SET ); \
230 * Function common to Video Manager and Video Title set Processing
233 /*****************************************************************************
234 * ReadPGC : Fills the Program Chain structure.
235 *****************************************************************************/
236 #define GETCOMMAND( p_com ) \
238 read( p_ifo->i_fd , (p_com) , 8 ); \
239 /*fprintf(stderr, "Pos : %lld Type : %d direct : %d cmd : %d dircmp : %d cmp : %d subcmd : %d v0 : %d v2 : %d v4 : %d\n", \
240 (long long)(p_ifo->i_pos - i_start), \
241 (int)((p_com)->i_type), \
242 (int)((p_com)->i_direct), \
243 (int)((p_com)->i_cmd), \
244 (int)((p_com)->i_dir_cmp), \
245 (int)((p_com)->i_cmp), \
246 (int)((p_com)->i_sub_cmd), \
247 (int)((p_com)->i_v0), \
248 (int)((p_com)->i_v2), \
249 (int)((p_com)->i_v4) ); */ \
253 static pgc_t ReadPGC( ifo_t* p_ifo )
257 off_t i_start = p_ifo->i_pos;
259 //fprintf( stderr, "PGC\n" );
262 GETC( &pgc.i_prg_nb );
263 GETC( &pgc.i_cell_nb );
264 GETL( &pgc.i_play_time );
265 GETL( &pgc.i_prohibited_user_op );
266 for( i=0 ; i<8 ; i++ )
268 GETS( &pgc.pi_audio_status[i] );
270 for( i=0 ; i<32 ; i++ )
272 GETL( &pgc.pi_subpic_status[i] );
274 GETS( &pgc.i_next_pgc_nb );
275 GETS( &pgc.i_prev_pgc_nb );
276 GETS( &pgc.i_goup_pgc_nb );
277 GETC( &pgc.i_still_time );
278 GETC( &pgc.i_play_mode );
279 for( i=0 ; i<16 ; i++ )
281 GETL( &pgc.pi_yuv_color[i] );
282 /* FIXME : We have to erase the extra bit */
284 GETS( &pgc.i_com_tab_sbyte );
285 GETS( &pgc.i_prg_map_sbyte );
286 GETS( &pgc.i_cell_play_inf_sbyte );
287 GETS( &pgc.i_cell_pos_inf_sbyte );
289 /* Parsing of pgc_com_tab_t */
290 if( pgc.i_com_tab_sbyte )
292 p_ifo->i_pos = lseek( p_ifo->i_fd, i_start
293 + pgc.i_com_tab_sbyte, SEEK_SET );
294 GETS( &pgc.com_tab.i_pre_com_nb );
295 GETS( &pgc.com_tab.i_post_com_nb );
296 GETS( &pgc.com_tab.i_cell_com_nb );
298 if( pgc.com_tab.i_pre_com_nb )
300 pgc.com_tab.p_pre_com =
301 malloc(pgc.com_tab.i_pre_com_nb *sizeof(ifo_command_t));
302 if( pgc.com_tab.p_pre_com == NULL )
304 intf_ErrMsg( "Out of memory" );
308 for( i=0 ; i<pgc.com_tab.i_pre_com_nb ; i++ )
310 GETCOMMAND( &pgc.com_tab.p_pre_com[i] );
313 if( pgc.com_tab.i_post_com_nb )
315 pgc.com_tab.p_post_com =
316 malloc(pgc.com_tab.i_post_com_nb *sizeof(ifo_command_t));
317 if( pgc.com_tab.p_post_com == NULL )
319 intf_ErrMsg( "Out of memory" );
323 for( i=0 ; i<pgc.com_tab.i_post_com_nb ; i++ )
325 GETCOMMAND( &pgc.com_tab.p_post_com[i] );
328 if( pgc.com_tab.i_cell_com_nb )
330 pgc.com_tab.p_cell_com =
331 malloc(pgc.com_tab.i_cell_com_nb *sizeof(ifo_command_t));
332 if( pgc.com_tab.p_cell_com == NULL )
334 intf_ErrMsg( "Out of memory" );
338 for( i=0 ; i<pgc.com_tab.i_cell_com_nb ; i++ )
340 GETCOMMAND( &pgc.com_tab.p_cell_com[i] );
344 /* Parsing of pgc_prg_map_t */
345 if( pgc.i_prg_map_sbyte )
347 p_ifo->i_pos = lseek( p_ifo->i_fd, i_start
348 + pgc.i_prg_map_sbyte, SEEK_SET );
349 pgc.prg_map.pi_entry_cell = malloc( pgc.i_prg_nb *sizeof(u8) );
350 if( pgc.prg_map.pi_entry_cell == NULL )
352 intf_ErrMsg( "Out of memory" );
356 GET( pgc.prg_map.pi_entry_cell, pgc.i_prg_nb );
357 /* FIXME : check endianness here */
359 /* Parsing of cell_play_inf_t */
360 if( pgc.i_cell_play_inf_sbyte )
362 p_ifo->i_pos = lseek( p_ifo->i_fd, i_start
363 + pgc.i_cell_play_inf_sbyte, SEEK_SET );
364 pgc.p_cell_play_inf = malloc( pgc.i_cell_nb *sizeof(cell_play_inf_t) );
365 if( pgc.p_cell_play_inf == NULL )
367 intf_ErrMsg( "Out of memory" );
371 for( i=0 ; i<pgc.i_cell_nb ; i++ )
373 GETS( &pgc.p_cell_play_inf[i].i_cat );
374 GETC( &pgc.p_cell_play_inf[i].i_still_time );
375 GETC( &pgc.p_cell_play_inf[i].i_com_nb );
376 GETL( &pgc.p_cell_play_inf[i].i_play_time );
377 GETL( &pgc.p_cell_play_inf[i].i_entry_sector );
378 GETL( &pgc.p_cell_play_inf[i].i_first_ilvu_vobu_esector );
379 GETL( &pgc.p_cell_play_inf[i].i_lvobu_ssector );
380 GETL( &pgc.p_cell_play_inf[i].i_lsector );
383 /* Parsing of cell_pos_inf_map */
384 if( pgc.i_cell_pos_inf_sbyte )
386 p_ifo->i_pos = lseek( p_ifo->i_fd, i_start
387 + pgc.i_cell_pos_inf_sbyte, SEEK_SET );
388 pgc.p_cell_pos_inf = malloc( pgc.i_cell_nb *sizeof(cell_pos_inf_t) );
389 if( pgc.p_cell_play_inf == NULL )
391 intf_ErrMsg( "Out of memory" );
395 for( i=0 ; i<pgc.i_cell_nb ; i++ )
397 GETS( &pgc.p_cell_pos_inf[i].i_vob_id );
399 GETC( &pgc.p_cell_pos_inf[i].i_cell_id );
406 /*****************************************************************************
407 * ReadUnit : Fills Menu Language Unit Table/ PGC Info Table
408 *****************************************************************************/
409 static pgci_inf_t ReadUnit( ifo_t* p_ifo )
413 off_t i_start = p_ifo->i_pos;
415 //fprintf( stderr, "Unit\n" );
417 GETS( &inf.i_srp_nb );
419 GETL( &inf.i_lu_ebyte );
420 inf.p_srp = malloc( inf.i_srp_nb *sizeof(pgci_srp_t) );
421 if( inf.p_srp == NULL )
423 intf_ErrMsg( "Out of memory" );
427 for( i=0 ; i<inf.i_srp_nb ; i++ )
429 GETC( &inf.p_srp[i].i_pgc_cat_mask );
430 GETC( &inf.p_srp[i].i_pgc_cat );
431 GETS( &inf.p_srp[i].i_par_mask );
432 GETL( &inf.p_srp[i].i_pgci_sbyte );
434 for( i=0 ; i<inf.i_srp_nb ; i++ )
436 p_ifo->i_pos = lseek( p_ifo->i_fd,
437 i_start + inf.p_srp[i].i_pgci_sbyte,
439 inf.p_srp[i].pgc = ReadPGC( p_ifo );
445 /*****************************************************************************
446 * ReadUnitTable : Fills the PGCI Unit structure.
447 *****************************************************************************/
448 static pgci_ut_t ReadUnitTable( ifo_t* p_ifo )
452 off_t i_start = p_ifo->i_pos;
454 //fprintf( stderr, "Unit Table\n" );
456 GETS( &pgci.i_lu_nb );
458 GETL( &pgci.i_ebyte );
459 pgci.p_lu = malloc( pgci.i_lu_nb *sizeof(pgci_lu_t) );
460 if( pgci.p_lu == NULL )
462 intf_ErrMsg( "Out of memory" );
466 for( i=0 ; i<pgci.i_lu_nb ; i++ )
468 GET( pgci.p_lu[i].ps_lang_code, 2 );
470 GETC( &pgci.p_lu[i].i_existence_mask );
471 GETL( &pgci.p_lu[i].i_lu_sbyte );
473 pgci.p_pgci_inf = malloc( pgci.i_lu_nb *sizeof(pgci_inf_t) );
474 if( pgci.p_pgci_inf == NULL )
476 intf_ErrMsg( "Out of memory" );
480 for( i=0 ; i<pgci.i_lu_nb ; i++ )
482 p_ifo->i_pos = lseek( p_ifo->i_fd, i_start +
483 pgci.p_lu[i].i_lu_sbyte,
485 pgci.p_pgci_inf[i] = ReadUnit( p_ifo );
491 /*****************************************************************************
492 * ReadCellInf : Fills the Cell Information structure.
493 *****************************************************************************/
494 static c_adt_t ReadCellInf( ifo_t* p_ifo )
498 off_t i_start = p_ifo->i_pos;
500 //fprintf( stderr, "CELL ADD\n" );
502 GETS( &c_adt.i_vob_nb );
504 GETL( &c_adt.i_ebyte );
505 i_max = ( i_start + c_adt.i_ebyte + 1 - p_ifo->i_pos ) / sizeof(cell_inf_t);
506 c_adt.p_cell_inf = malloc( i_max *sizeof(cell_inf_t) );
507 if( c_adt.p_cell_inf == NULL )
509 intf_ErrMsg( "Out of memory" );
513 for( i=0 ; i<i_max ; i++ )
515 GETS( &c_adt.p_cell_inf[i].i_vob_id );
516 GETC( &c_adt.p_cell_inf[i].i_cell_id );
518 GETL( &c_adt.p_cell_inf[i].i_ssector );
519 GETL( &c_adt.p_cell_inf[i].i_esector );
525 /*****************************************************************************
526 * ReadMap : Fills the VOBU Map structure.
527 *****************************************************************************/
528 static vobu_admap_t ReadMap( ifo_t* p_ifo )
532 off_t i_start = p_ifo->i_pos;
534 //fprintf( stderr, "VOBU ADMAP\n" );
536 GETL( &map.i_ebyte );
537 i_max = ( i_start + map.i_ebyte + 1 - p_ifo->i_pos ) / sizeof(u32);
538 map.pi_vobu_ssector = malloc( i_max *sizeof(u32) );
539 for( i=0 ; i<i_max ; i++ )
541 GETL( &map.pi_vobu_ssector[i] );
548 * Video Manager Information Processing.
549 * This is what is contained in video_ts.ifo.
552 /*****************************************************************************
553 * ReadVMGInfMat : Fills the Management Information structure.
554 *****************************************************************************/
555 static vmgi_mat_t ReadVMGInfMat( ifo_t* p_ifo )
559 // off_t i_start = p_ifo->i_pos;
561 //fprintf( stderr, "VMGI\n" );
563 GET( mat.psz_id , 12 );
564 mat.psz_id[12] = '\0';
565 GETL( &mat.i_lsector );
567 GETL( &mat.i_i_lsector );
569 GETC( &mat.i_spec_ver );
571 GETS( &mat.i_vol_nb );
573 GETC( &mat.i_disc_side );
575 GETS( &mat.i_tts_nb );
576 GET( mat.ps_provider_id, 32 );
577 GETLL( &mat.i_pos_code );
579 GETL( &mat.i_i_mat_ebyte );
580 GETL( &mat.i_fp_pgc_sbyte );
582 GETL( &mat.i_vobs_ssector );
583 GETL( &mat.i_ptt_srpt_ssector );
584 GETL( &mat.i_pgci_ut_ssector );
585 GETL( &mat.i_ptl_mait_ssector );
586 GETL( &mat.i_vts_atrt_ssector );
587 GETL( &mat.i_txtdt_mg_ssector );
588 GETL( &mat.i_c_adt_ssector );
589 GETL( &mat.i_vobu_admap_ssector );
591 GETS( &mat.i_video_atrt );
593 GETC( &mat.i_audio_nb );
594 //fprintf( stderr, "vmgi audio nb : %d\n", mat.i_audio_nb );
595 for( i=0 ; i < 8 ; i++ )
597 GETLL( &mat.pi_audio_atrt[i] );
600 GETC( &mat.i_subpic_nb );
601 //fprintf( stderr, "vmgi subpic nb : %d\n", mat.i_subpic_nb );
602 for( i=0 ; i < mat.i_subpic_nb ; i++ )
604 GET( &mat.pi_subpic_atrt[i], 6 );
605 /* FIXME : take care of endianness */
611 /*****************************************************************************
612 * ReadVMGTitlePointer : Fills the Part Of Title Search Pointer structure.
613 *****************************************************************************/
614 static vmg_ptt_srpt_t ReadVMGTitlePointer( ifo_t* p_ifo )
618 // off_t i_start = p_ifo->i_pos;
620 //fprintf( stderr, "PTR\n" );
622 GETS( &ptr.i_ttu_nb );
624 GETL( &ptr.i_ebyte );
626 ptr.p_tts = malloc( ptr.i_ttu_nb *sizeof(tts_t) );
627 if( ptr.p_tts == NULL )
629 intf_ErrMsg( "Out of memory" );
633 for( i=0 ; i<ptr.i_ttu_nb ; i++ )
635 GETC( &ptr.p_tts[i].i_play_type );
636 GETC( &ptr.p_tts[i].i_angle_nb );
637 GETS( &ptr.p_tts[i].i_ptt_nb );
638 GETS( &ptr.p_tts[i].i_parental_id );
639 GETC( &ptr.p_tts[i].i_tts_nb );
640 GETC( &ptr.p_tts[i].i_vts_ttn );
641 GETL( &ptr.p_tts[i].i_ssector );
647 /*****************************************************************************
648 * ReadParentalInf : Fills the Parental Management structure.
649 *****************************************************************************/
650 static vmg_ptl_mait_t ReadParentalInf( ifo_t* p_ifo )
654 off_t i_start = p_ifo->i_pos;
656 //fprintf( stderr, "PTL\n" );
658 GETS( &par.i_country_nb );
659 GETS( &par.i_vts_nb );
660 GETL( &par.i_ebyte );
661 par.p_ptl_desc = malloc( par.i_country_nb *sizeof(vmg_ptl_mai_desc_t) );
662 if( par.p_ptl_desc == NULL )
664 intf_ErrMsg( "Out of memory" );
668 for( i=0 ; i<par.i_country_nb ; i++ )
670 GET( par.p_ptl_desc[i].ps_country_code, 2 );
672 GETS( &par.p_ptl_desc[i].i_ptl_mai_sbyte );
675 par.p_ptl_mask = malloc( par.i_country_nb *sizeof(vmg_ptl_mask_t) );
676 if( par.p_ptl_mask == NULL )
678 intf_ErrMsg( "Out of memory" );
682 for( i=0 ; i<par.i_country_nb ; i++ )
684 p_ifo->i_pos = lseek( p_ifo->i_fd, i_start +
685 par.p_ptl_desc[i].i_ptl_mai_sbyte, SEEK_SET );
686 for( j=1 ; j<=8 ; j++ )
688 par.p_ptl_mask[i].ppi_ptl_mask[j] =
689 malloc( par.i_vts_nb *sizeof(u16) );
690 if( par.p_ptl_mask[i].ppi_ptl_mask[j] == NULL )
692 intf_ErrMsg( "Out of memory" );
696 for( k=0 ; k<par.i_vts_nb ; k++ )
698 GETS( &par.p_ptl_mask[i].ppi_ptl_mask[j][k] );
706 /*****************************************************************************
707 * ReadVTSAttr : Fills the structure about VTS attributes.
708 *****************************************************************************/
709 static vmg_vts_atrt_t ReadVTSAttr( ifo_t* p_ifo )
713 off_t i_start = p_ifo->i_pos;
715 //fprintf( stderr, "VTS ATTR\n" );
717 GETS( &atrt.i_vts_nb );
719 GETL( &atrt.i_ebyte );
720 atrt.pi_vts_atrt_sbyte = malloc( atrt.i_vts_nb *sizeof(u32) );
721 if( atrt.pi_vts_atrt_sbyte == NULL )
723 intf_ErrMsg( "Out of memory" );
727 for( i=0 ; i<atrt.i_vts_nb ; i++ )
729 GETL( &atrt.pi_vts_atrt_sbyte[i] );
731 atrt.p_vts_atrt = malloc( atrt.i_vts_nb *sizeof(vts_atrt_t) );
732 if( atrt.p_vts_atrt == NULL )
734 intf_ErrMsg( "Out of memory" );
738 for( i=0 ; i<atrt.i_vts_nb ; i++ )
740 p_ifo->i_pos = lseek( p_ifo->i_fd, i_start +
741 atrt.pi_vts_atrt_sbyte[i],
743 GETL( &atrt.p_vts_atrt[i].i_ebyte );
744 GETL( &atrt.p_vts_atrt[i].i_cat_app_type );
745 GETS( &atrt.p_vts_atrt[i].i_vtsm_video_atrt );
747 GETC( &atrt.p_vts_atrt[i].i_vtsm_audio_nb );
748 //fprintf( stderr, "m audio nb : %d\n", atrt.p_vts_atrt[i].i_vtsm_audio_nb );
749 for( j=0 ; j<8 ; j++ )
751 GETLL( &atrt.p_vts_atrt[i].pi_vtsm_audio_atrt[j] );
754 GETC( &atrt.p_vts_atrt[i].i_vtsm_subpic_nb );
755 //fprintf( stderr, "m subp nb : %d\n", atrt.p_vts_atrt[i].i_vtsm_subpic_nb );
756 for( j=0 ; j<28 ; j++ )
758 GET( &atrt.p_vts_atrt[i].pi_vtsm_subpic_atrt[j], 6 );
759 /* FIXME : Fix endianness issue here */
762 GETS( &atrt.p_vts_atrt[i].i_vtstt_video_atrt );
764 GETL( &atrt.p_vts_atrt[i].i_vtstt_audio_nb );
765 //fprintf( stderr, "tt audio nb : %d\n", atrt.p_vts_atrt[i].i_vtstt_audio_nb );
766 for( j=0 ; j<8 ; j++ )
768 GETLL( &atrt.p_vts_atrt[i].pi_vtstt_audio_atrt[j] );
771 GETC( &atrt.p_vts_atrt[i].i_vtstt_subpic_nb );
772 //fprintf( stderr, "tt subp nb : %d\n", atrt.p_vts_atrt[i].i_vtstt_subpic_nb );
773 for( j=0 ; j<28/*atrt.p_vts_atrt[i].i_vtstt_subpic_nb*/ ; j++ )
775 GET( &atrt.p_vts_atrt[i].pi_vtstt_subpic_atrt[j], 6 );
776 /* FIXME : Fix endianness issue here */
783 /*****************************************************************************
784 * ReadVMG : Parse video_ts.ifo file to fill the Video Manager structure.
785 *****************************************************************************/
786 static vmg_t ReadVMG( ifo_t* p_ifo )
790 p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off, SEEK_SET);
791 vmg.mat = ReadVMGInfMat( p_ifo );
792 p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
793 vmg.mat.i_fp_pgc_sbyte, SEEK_SET );
794 vmg.pgc = ReadPGC( p_ifo );
795 if( vmg.mat.i_ptt_srpt_ssector )
797 p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
798 vmg.mat.i_ptt_srpt_ssector *DVD_LB_SIZE,
800 vmg.ptt_srpt = ReadVMGTitlePointer( p_ifo );
802 if( vmg.mat.i_pgci_ut_ssector )
804 p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
805 vmg.mat.i_pgci_ut_ssector *DVD_LB_SIZE,
807 vmg.pgci_ut = ReadUnitTable( p_ifo );
809 if( vmg.mat.i_ptl_mait_ssector )
811 p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
812 vmg.mat.i_ptl_mait_ssector *DVD_LB_SIZE,
814 vmg.ptl_mait = ReadParentalInf( p_ifo );
816 if( vmg.mat.i_vts_atrt_ssector )
818 p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
819 vmg.mat.i_vts_atrt_ssector *DVD_LB_SIZE,
821 vmg.vts_atrt = ReadVTSAttr( p_ifo );
823 if( vmg.mat.i_c_adt_ssector )
825 p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
826 vmg.mat.i_c_adt_ssector *DVD_LB_SIZE,
828 vmg.c_adt = ReadCellInf( p_ifo );
830 if( vmg.mat.i_vobu_admap_ssector )
832 p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
833 vmg.mat.i_vobu_admap_ssector *DVD_LB_SIZE,
835 vmg.vobu_admap = ReadMap( p_ifo );
841 * Video Title Set Information Processing.
842 * This is what is contained in vts_*.ifo.
845 /*****************************************************************************
846 * ReadVTSInfMat : Fills the Title Set Information structure.
847 *****************************************************************************/
848 static vtsi_mat_t ReadVTSInfMat( ifo_t* p_ifo )
852 // off_t i_start = p_ifo->i_pos;
854 //fprintf( stderr, "VTSI\n" );
856 GET( mat.psz_id , 12 );
857 mat.psz_id[12] = '\0';
858 GETL( &mat.i_lsector );
860 GETL( &mat.i_i_lsector );
862 GETC( &mat.i_spec_ver );
865 GETL( &mat.i_mat_ebyte );
867 GETL( &mat.i_m_vobs_ssector );
868 GETL( &mat.i_tt_vobs_ssector );
869 GETL( &mat.i_ptt_srpt_ssector );
870 GETL( &mat.i_pgcit_ssector );
871 GETL( &mat.i_m_pgci_ut_ssector );
872 GETL( &mat.i_tmap_ti_ssector );
873 GETL( &mat.i_m_c_adt_ssector );
874 GETL( &mat.i_m_vobu_admap_ssector );
875 GETL( &mat.i_c_adt_ssector );
876 GETL( &mat.i_vobu_admap_ssector );
878 GETS( &mat.i_m_video_atrt );
880 GETC( &mat.i_m_audio_nb );
881 for( i=0 ; i<8 ; i++ )
883 GETLL( &mat.pi_m_audio_atrt[i] );
886 GETC( &mat.i_m_subpic_nb );
887 for( i=0 ; i<28 ; i++ )
889 GET( &mat.pi_m_subpic_atrt[i], 6 );
890 /* FIXME : take care of endianness */
893 GETS( &mat.i_video_atrt );
895 GETC( &mat.i_audio_nb );
896 //fprintf( stderr, "vtsi audio nb : %d\n", mat.i_audio_nb );
897 for( i=0 ; i<8 ; i++ )
899 GETLL( &mat.pi_audio_atrt[i] );
902 GETC( &mat.i_subpic_nb );
903 //fprintf( stderr, "vtsi subpic nb : %d\n", mat.i_subpic_nb );
904 for( i=0 ; i<mat.i_subpic_nb ; i++ )
906 GET( &mat.pi_subpic_atrt[i], 6 );
907 /* FIXME : take care of endianness */
913 /*****************************************************************************
914 * ReadVTSTitlePointer : Fills the Part Of Title Search Pointer structure.
915 *****************************************************************************/
916 static vts_ptt_srpt_t ReadVTSTitlePointer( ifo_t* p_ifo )
920 off_t i_start = p_ifo->i_pos;
922 //fprintf( stderr, "PTR\n" );
924 GETS( &ptr.i_ttu_nb );
926 GETL( &ptr.i_ebyte );
927 ptr.pi_ttu_sbyte = malloc( ptr.i_ttu_nb *sizeof(u32) );
928 if( ptr.pi_ttu_sbyte == NULL )
930 intf_ErrMsg( "Out of memory" );
934 for( i=0 ; i<ptr.i_ttu_nb ; i++ )
936 GETL( &ptr.pi_ttu_sbyte[i] );
939 ptr.p_ttu = malloc( ptr.i_ttu_nb *sizeof(ttu_t) );
940 if( ptr.p_ttu == NULL )
942 intf_ErrMsg( "Out of memory" );
946 for( i=0 ; i<ptr.i_ttu_nb ; i++ )
948 p_ifo->i_pos = lseek( p_ifo->i_fd, i_start +
949 ptr.pi_ttu_sbyte[i], SEEK_SET );
950 GETS( &ptr.p_ttu[i].i_pgc_nb );
951 GETS( &ptr.p_ttu[i].i_prg_nb );
957 /*****************************************************************************
958 * ReadVTSTimeMap : Fills the time map table
959 *****************************************************************************/
960 static vts_tmap_ti_t ReadVTSTimeMap( ifo_t* p_ifo )
964 // off_t i_start = p_ifo->i_pos;
966 //fprintf( stderr, "TMAP\n" );
970 GETL( &tmap.i_ebyte );
971 tmap.pi_sbyte = malloc( tmap.i_nb *sizeof(u32) );
972 if( tmap.pi_sbyte == NULL )
974 intf_ErrMsg( "Out of memory" );
978 for( i=0 ; i<tmap.i_nb ; i++ )
980 GETL( &tmap.pi_sbyte[i] );
982 tmap.p_tmap = malloc( tmap.i_nb *sizeof(tmap_t) );
983 if( tmap.p_tmap == NULL )
985 intf_ErrMsg( "Out of memory" );
989 for( i=0 ; i<tmap.i_nb ; i++ )
991 GETC( &tmap.p_tmap[i].i_time_unit );
993 GETS( &tmap.p_tmap[i].i_entry_nb );
994 tmap.p_tmap[i].pi_sector =
995 malloc( tmap.p_tmap[i].i_entry_nb *sizeof(u32) );
996 if( tmap.p_tmap[i].pi_sector == NULL )
998 intf_ErrMsg( "Out of memory" );
1002 for( j=0 ; j<tmap.p_tmap[i].i_entry_nb ; j++ )
1004 GETL( &tmap.p_tmap[i].pi_sector[j] );
1012 /*****************************************************************************
1013 * ReadVTS : Parse vts*.ifo files to fill the Video Title Set structure.
1014 *****************************************************************************/
1015 static vts_t ReadVTS( ifo_t* p_ifo )
1019 vts.i_pos = p_ifo->i_pos;
1021 vts.mat = ReadVTSInfMat( p_ifo );
1022 if( vts.mat.i_ptt_srpt_ssector )
1024 p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
1025 vts.mat.i_ptt_srpt_ssector *DVD_LB_SIZE,
1027 vts.ptt_srpt = ReadVTSTitlePointer( p_ifo );
1029 if( vts.mat.i_m_pgci_ut_ssector )
1031 p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
1032 vts.mat.i_m_pgci_ut_ssector *DVD_LB_SIZE,
1034 vts.pgci_ut = ReadUnitTable( p_ifo );
1036 if( vts.mat.i_pgcit_ssector )
1038 p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
1039 vts.mat.i_pgcit_ssector *DVD_LB_SIZE,
1041 vts.pgci_ti = ReadUnit( p_ifo );
1043 if( vts.mat.i_tmap_ti_ssector )
1045 p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
1046 vts.mat.i_tmap_ti_ssector *DVD_LB_SIZE,
1048 vts.tmap_ti = ReadVTSTimeMap( p_ifo );
1050 if( vts.mat.i_m_c_adt_ssector )
1052 p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
1053 vts.mat.i_m_c_adt_ssector *DVD_LB_SIZE,
1055 vts.m_c_adt = ReadCellInf( p_ifo );
1057 if( vts.mat.i_m_vobu_admap_ssector )
1059 p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
1060 vts.mat.i_m_vobu_admap_ssector *DVD_LB_SIZE,
1062 vts.m_vobu_admap = ReadMap( p_ifo );
1064 if( vts.mat.i_c_adt_ssector )
1066 p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
1067 vts.mat.i_c_adt_ssector *DVD_LB_SIZE,
1069 vts.c_adt = ReadCellInf( p_ifo );
1071 if( vts.mat.i_vobu_admap_ssector )
1073 p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
1074 vts.mat.i_vobu_admap_ssector *DVD_LB_SIZE,
1076 vts.vobu_admap = ReadMap( p_ifo );
1083 * DVD Information Management
1086 /*****************************************************************************
1087 * IfoRead : Function that fills structure and calls specified functions
1089 *****************************************************************************/
1090 void IfoRead( ifo_t* p_ifo )
1095 p_ifo->vmg = ReadVMG( p_ifo );
1096 p_ifo->p_vts = malloc( p_ifo->vmg.mat.i_tts_nb *sizeof(vts_t) );
1097 if( p_ifo->p_vts == NULL )
1099 intf_ErrMsg( "Out of memory" );
1103 for( i=0 ; i<1/*p_ifo->vmg.mat.i_tts_nb*/ ; i++ )
1106 intf_WarnMsg( 3, "######### VTS %d #############\n", i+1 );
1108 i_off = p_ifo->vmg.ptt_srpt.p_tts[i].i_ssector *DVD_LB_SIZE;
1109 p_ifo->i_pos = lseek( p_ifo->i_fd, i_off, SEEK_SET );
1110 /* FIXME : use udf filesystem to avoid this */
1111 IfoFindVTS( p_ifo );
1112 p_ifo->p_vts[i] = ReadVTS( p_ifo );
1118 * IFO virtual machine : a set of commands that give the behaviour of the dvd
1121 /*****************************************************************************
1122 * CommandRead : translates the command strings in ifo into command
1124 *****************************************************************************/
1125 void CommandRead( ifo_command_t com )
1127 u8* pi_code = (u8*)(&com);
1129 switch( com.i_type )
1134 fprintf( stderr, "NOP\n" );
1136 else if( cmd.i_cmp )
1143 case 2: /* SetSystem */
1154 fprintf( stderr, "Unknown Command\n" );
1161 /*****************************************************************************
1163 *****************************************************************************/
1164 static void IfoGoto( ifo_command_t cmd )
1171 /*****************************************************************************
1173 *****************************************************************************/
1174 static void IfoLnk( ifo_t* p_ifo )
1179 /*****************************************************************************
1181 *****************************************************************************/
1182 static void IfoJmp( ifo_t* p_ifo )