1 /*****************************************************************************
2 * dvd_ifo.c: Functions for ifo parsing
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: dvd_ifo.c,v 1.1 2001/02/08 04:43:27 sam 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 *****************************************************************************/
37 #include "input_dvd.h"
43 /*****************************************************************************
44 * IfoFindVMG : When reading directly on a device, finds the offset to the
45 * beginning of video_ts.ifo.
46 *****************************************************************************/
47 static int IfoFindVMG( ifo_t* p_ifo )
49 char psz_ifo_start[12] = "DVDVIDEO-VMG";
52 read( p_ifo->i_fd, psz_test, 12 );
54 while( strncmp( psz_test, psz_ifo_start, 12 ) != 0 )
56 /* The start of ifo file is on a sector boundary */
57 p_ifo->i_pos = lseek64( p_ifo->i_fd,
58 p_ifo->i_pos + DVD_LB_SIZE,
60 read( p_ifo->i_fd, psz_test, 12 );
62 p_ifo->i_off = p_ifo->i_pos;
64 //fprintf( stderr, "VMG Off : %lld\n", (long long)(p_ifo->i_off) );
69 /*****************************************************************************
70 * IfoFindVTS : beginning of vts_*.ifo.
71 *****************************************************************************/
72 static int IfoFindVTS( ifo_t* p_ifo )
74 char psz_ifo_start[12] = "DVDVIDEO-VTS";
77 read( p_ifo->i_fd, psz_test, 12 );
79 while( strncmp( psz_test, psz_ifo_start, 12 ) != 0 )
81 /* The start of ifo file is on a sector boundary */
82 p_ifo->i_pos = lseek64( p_ifo->i_fd,
83 p_ifo->i_pos + DVD_LB_SIZE,
85 read( p_ifo->i_fd, psz_test, 12 );
87 p_ifo->i_off = p_ifo->i_pos;
89 //fprintf( stderr, "VTS Off : %lld\n", (long long)(p_ifo->i_off) );
94 /*****************************************************************************
95 * IfoInit : Creates an ifo structure and prepares for parsing directly
97 *****************************************************************************/
98 ifo_t IfoInit( int i_fd )
102 /* If we are here the dvd device has already been opened */
104 /* No data at the beginning of the disk
105 * 512000 bytes is just another value :) */
106 ifo.i_pos = lseek64( ifo.i_fd, 250 *DVD_LB_SIZE, SEEK_SET );
107 /* FIXME : use udf filesystem to find the beginning of the file */
113 /*****************************************************************************
114 * IfoEnd : Frees all the memory allocated to ifo structures
115 *****************************************************************************/
116 void IfoEnd( ifo_t* p_ifo )
120 /* Free structures from video title sets */
121 for( j=0 ; j<p_ifo->vmg.mat.i_tts_nb ; j++ )
123 free( p_ifo->p_vts[j].vobu_admap.pi_vobu_ssector );
124 free( p_ifo->p_vts[j].c_adt.p_cell_inf );
125 free( p_ifo->p_vts[j].m_vobu_admap.pi_vobu_ssector );
126 free( p_ifo->p_vts[j].m_c_adt.p_cell_inf );
127 for( i=0 ; i<p_ifo->p_vts[j].tmap_ti.i_nb ; i++ )
129 free( p_ifo->p_vts[j].tmap_ti.p_tmap[i].pi_sector );
131 free( p_ifo->p_vts[j].tmap_ti.pi_sbyte );
132 free( p_ifo->p_vts[j].tmap_ti.p_tmap );
133 free( p_ifo->p_vts[j].pgci_ti.p_srp );
134 for( i=0 ; i<p_ifo->p_vts[j].pgci_ut.i_lu_nb ; i++ )
136 free( p_ifo->p_vts[j].pgci_ut.p_pgci_inf[i].p_srp );
138 free( p_ifo->p_vts[j].pgci_ut.p_pgci_inf );
139 free( p_ifo->p_vts[j].pgci_ut.p_lu );
142 free( p_ifo->p_vts );
144 /* Free structures from video manager */
145 free( p_ifo->vmg.vobu_admap.pi_vobu_ssector );
146 free( p_ifo->vmg.c_adt.p_cell_inf );
147 for( i=0 ; i<p_ifo->vmg.pgci_ut.i_lu_nb ; i++ )
149 free( p_ifo->vmg.pgci_ut.p_pgci_inf[i].p_srp );
151 free( p_ifo->vmg.pgci_ut.p_pgci_inf );
152 free( p_ifo->vmg.pgci_ut.p_lu );
153 for( i=1 ; i<=8 ; i++ )
155 free( p_ifo->vmg.ptl_mait.p_ptl_mask->ppi_ptl_mask[i] );
157 free( p_ifo->vmg.ptl_mait.p_ptl_desc );
158 free( p_ifo->vmg.ptl_mait.p_ptl_mask );
159 free( p_ifo->vmg.vts_atrt.pi_vts_atrt_sbyte );
160 free( p_ifo->vmg.vts_atrt.p_vts_atrt );
161 free( p_ifo->vmg.pgc.p_cell_pos_inf );
162 free( p_ifo->vmg.pgc.p_cell_play_inf );
163 free( p_ifo->vmg.pgc.prg_map.pi_entry_cell );
164 free( p_ifo->vmg.pgc.com_tab.p_cell_com );
165 free( p_ifo->vmg.pgc.com_tab.p_post_com );
166 free( p_ifo->vmg.pgc.com_tab.p_pre_com );
172 * Macros to process ifo files
175 #define GET( p_field , i_len ) \
177 read( p_ifo->i_fd , (p_field) , (i_len) ); \
178 /*fprintf(stderr, "Pos : %lld Val : %llx\n", \
179 (long long)(p_ifo->i_pos - i_start), \
180 (long long)*(p_field) ); */ \
181 p_ifo->i_pos += i_len; \
184 #define GETC( p_field ) \
186 read( p_ifo->i_fd , (p_field) , 1 ); \
187 /*fprintf(stderr, "Pos : %lld Value : %d\n", \
188 (long long)(p_ifo->i_pos - i_start), \
193 #define GETS( p_field ) \
195 read( p_ifo->i_fd , (p_field) , 2 ); \
196 *(p_field) = ntohs( *(p_field) ); \
197 /*fprintf(stderr, "Pos : %lld Value : %d\n", \
198 (long long)(p_ifo->i_pos - i_start), \
203 #define GETL( p_field ) \
205 read( p_ifo->i_fd , (p_field) , 4 ); \
206 *(p_field) = ntohl( *(p_field) ); \
207 /*fprintf(stderr, "Pos : %lld Value : %d\n", \
208 (long long)(p_ifo->i_pos - i_start), \
213 #define GETLL( p_field ) \
215 read( p_ifo->i_fd , (p_field) , 8 ); \
216 *(p_field) = ntoh64( *(p_field) ); \
217 /*fprintf(stderr, "Pos : %lld Value : %lld\n", \
218 (long long)(p_ifo->i_pos - i_start), \
223 #define FLUSH( i_len ) \
225 /*fprintf(stderr, "Pos : %lld\n", (long long)(p_ifo->i_pos - i_start));*/ \
226 p_ifo->i_pos = lseek64( p_ifo->i_fd , \
227 p_ifo->i_pos + (i_len), SEEK_SET ); \
231 * Function common to Video Manager and Video Title set Processing
234 /*****************************************************************************
235 * ReadPGC : Fills the Program Chain structure.
236 *****************************************************************************/
237 #define GETCOMMAND( p_com ) \
239 read( p_ifo->i_fd , (p_com) , 8 ); \
240 /*fprintf(stderr, "Pos : %lld Type : %d direct : %d cmd : %d dircmp : %d cmp : %d subcmd : %d v0 : %d v2 : %d v4 : %d\n", \
241 (long long)(p_ifo->i_pos - i_start), \
242 (int)((p_com)->i_type), \
243 (int)((p_com)->i_direct), \
244 (int)((p_com)->i_cmd), \
245 (int)((p_com)->i_dir_cmp), \
246 (int)((p_com)->i_cmp), \
247 (int)((p_com)->i_sub_cmd), \
248 (int)((p_com)->i_v0), \
249 (int)((p_com)->i_v2), \
250 (int)((p_com)->i_v4) ); */ \
254 static pgc_t ReadPGC( ifo_t* p_ifo )
258 off64_t i_start = p_ifo->i_pos;
260 //fprintf( stderr, "PGC\n" );
263 GETC( &pgc.i_prg_nb );
264 GETC( &pgc.i_cell_nb );
265 GETL( &pgc.i_play_time );
266 GETL( &pgc.i_prohibited_user_op );
267 for( i=0 ; i<8 ; i++ )
269 GETS( &pgc.pi_audio_status[i] );
271 for( i=0 ; i<32 ; i++ )
273 GETL( &pgc.pi_subpic_status[i] );
275 GETS( &pgc.i_next_pgc_nb );
276 GETS( &pgc.i_prev_pgc_nb );
277 GETS( &pgc.i_goup_pgc_nb );
278 GETC( &pgc.i_still_time );
279 GETC( &pgc.i_play_mode );
280 for( i=0 ; i<16 ; i++ )
282 GETL( &pgc.pi_yuv_color[i] );
283 /* FIXME : We have to erase the extra bit */
285 GETS( &pgc.i_com_tab_sbyte );
286 GETS( &pgc.i_prg_map_sbyte );
287 GETS( &pgc.i_cell_play_inf_sbyte );
288 GETS( &pgc.i_cell_pos_inf_sbyte );
290 /* Parsing of pgc_com_tab_t */
291 if( pgc.i_com_tab_sbyte )
293 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_start
294 + pgc.i_com_tab_sbyte, SEEK_SET );
295 GETS( &pgc.com_tab.i_pre_com_nb );
296 GETS( &pgc.com_tab.i_post_com_nb );
297 GETS( &pgc.com_tab.i_cell_com_nb );
299 if( pgc.com_tab.i_pre_com_nb )
301 pgc.com_tab.p_pre_com =
302 malloc(pgc.com_tab.i_pre_com_nb *sizeof(ifo_command_t));
303 if( pgc.com_tab.p_pre_com == NULL )
305 intf_ErrMsg( "Out of memory" );
309 for( i=0 ; i<pgc.com_tab.i_pre_com_nb ; i++ )
311 GETCOMMAND( &pgc.com_tab.p_pre_com[i] );
314 if( pgc.com_tab.i_post_com_nb )
316 pgc.com_tab.p_post_com =
317 malloc(pgc.com_tab.i_post_com_nb *sizeof(ifo_command_t));
318 if( pgc.com_tab.p_post_com == NULL )
320 intf_ErrMsg( "Out of memory" );
324 for( i=0 ; i<pgc.com_tab.i_post_com_nb ; i++ )
326 GETCOMMAND( &pgc.com_tab.p_post_com[i] );
329 if( pgc.com_tab.i_cell_com_nb )
331 pgc.com_tab.p_cell_com =
332 malloc(pgc.com_tab.i_cell_com_nb *sizeof(ifo_command_t));
333 if( pgc.com_tab.p_cell_com == NULL )
335 intf_ErrMsg( "Out of memory" );
339 for( i=0 ; i<pgc.com_tab.i_cell_com_nb ; i++ )
341 GETCOMMAND( &pgc.com_tab.p_cell_com[i] );
345 /* Parsing of pgc_prg_map_t */
346 if( pgc.i_prg_map_sbyte )
348 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_start
349 + pgc.i_prg_map_sbyte, SEEK_SET );
350 pgc.prg_map.pi_entry_cell = malloc( pgc.i_prg_nb *sizeof(u8) );
351 if( pgc.prg_map.pi_entry_cell == NULL )
353 intf_ErrMsg( "Out of memory" );
357 GET( pgc.prg_map.pi_entry_cell, pgc.i_prg_nb );
358 /* FIXME : check endianness here */
360 /* Parsing of cell_play_inf_t */
361 if( pgc.i_cell_play_inf_sbyte )
363 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_start
364 + pgc.i_cell_play_inf_sbyte, SEEK_SET );
365 pgc.p_cell_play_inf = malloc( pgc.i_cell_nb *sizeof(cell_play_inf_t) );
366 if( pgc.p_cell_play_inf == NULL )
368 intf_ErrMsg( "Out of memory" );
372 for( i=0 ; i<pgc.i_cell_nb ; i++ )
374 GETS( &pgc.p_cell_play_inf[i].i_cat );
375 GETC( &pgc.p_cell_play_inf[i].i_still_time );
376 GETC( &pgc.p_cell_play_inf[i].i_com_nb );
377 GETL( &pgc.p_cell_play_inf[i].i_play_time );
378 GETL( &pgc.p_cell_play_inf[i].i_entry_sector );
379 GETL( &pgc.p_cell_play_inf[i].i_first_ilvu_vobu_esector );
380 GETL( &pgc.p_cell_play_inf[i].i_lvobu_ssector );
381 GETL( &pgc.p_cell_play_inf[i].i_lsector );
384 /* Parsing of cell_pos_inf_map */
385 if( pgc.i_cell_pos_inf_sbyte )
387 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_start
388 + pgc.i_cell_pos_inf_sbyte, SEEK_SET );
389 pgc.p_cell_pos_inf = malloc( pgc.i_cell_nb *sizeof(cell_pos_inf_t) );
390 if( pgc.p_cell_play_inf == NULL )
392 intf_ErrMsg( "Out of memory" );
396 for( i=0 ; i<pgc.i_cell_nb ; i++ )
398 GETS( &pgc.p_cell_pos_inf[i].i_vob_id );
400 GETC( &pgc.p_cell_pos_inf[i].i_cell_id );
407 /*****************************************************************************
408 * ReadUnit : Fills Menu Language Unit Table/ PGC Info Table
409 *****************************************************************************/
410 static pgci_inf_t ReadUnit( ifo_t* p_ifo )
414 off64_t i_start = p_ifo->i_pos;
416 //fprintf( stderr, "Unit\n" );
418 GETS( &inf.i_srp_nb );
420 GETL( &inf.i_lu_ebyte );
421 inf.p_srp = malloc( inf.i_srp_nb *sizeof(pgci_srp_t) );
422 if( inf.p_srp == NULL )
424 intf_ErrMsg( "Out of memory" );
428 for( i=0 ; i<inf.i_srp_nb ; i++ )
430 GETC( &inf.p_srp[i].i_pgc_cat_mask );
431 GETC( &inf.p_srp[i].i_pgc_cat );
432 GETS( &inf.p_srp[i].i_par_mask );
433 GETL( &inf.p_srp[i].i_pgci_sbyte );
435 for( i=0 ; i<inf.i_srp_nb ; i++ )
437 p_ifo->i_pos = lseek64( p_ifo->i_fd,
438 i_start + inf.p_srp[i].i_pgci_sbyte,
440 inf.p_srp[i].pgc = ReadPGC( p_ifo );
446 /*****************************************************************************
447 * ReadUnitTable : Fills the PGCI Unit structure.
448 *****************************************************************************/
449 static pgci_ut_t ReadUnitTable( ifo_t* p_ifo )
453 off64_t i_start = p_ifo->i_pos;
455 //fprintf( stderr, "Unit Table\n" );
457 GETS( &pgci.i_lu_nb );
459 GETL( &pgci.i_ebyte );
460 pgci.p_lu = malloc( pgci.i_lu_nb *sizeof(pgci_lu_t) );
461 if( pgci.p_lu == NULL )
463 intf_ErrMsg( "Out of memory" );
467 for( i=0 ; i<pgci.i_lu_nb ; i++ )
469 GET( pgci.p_lu[i].ps_lang_code, 2 );
471 GETC( &pgci.p_lu[i].i_existence_mask );
472 GETL( &pgci.p_lu[i].i_lu_sbyte );
474 pgci.p_pgci_inf = malloc( pgci.i_lu_nb *sizeof(pgci_inf_t) );
475 if( pgci.p_pgci_inf == NULL )
477 intf_ErrMsg( "Out of memory" );
481 for( i=0 ; i<pgci.i_lu_nb ; i++ )
483 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_start +
484 pgci.p_lu[i].i_lu_sbyte,
486 pgci.p_pgci_inf[i] = ReadUnit( p_ifo );
492 /*****************************************************************************
493 * ReadCellInf : Fills the Cell Information structure.
494 *****************************************************************************/
495 static c_adt_t ReadCellInf( ifo_t* p_ifo )
499 off64_t i_start = p_ifo->i_pos;
501 //fprintf( stderr, "CELL ADD\n" );
503 GETS( &c_adt.i_vob_nb );
505 GETL( &c_adt.i_ebyte );
506 i_max = ( i_start + c_adt.i_ebyte + 1 - p_ifo->i_pos ) / sizeof(cell_inf_t);
507 c_adt.p_cell_inf = malloc( i_max *sizeof(cell_inf_t) );
508 if( c_adt.p_cell_inf == NULL )
510 intf_ErrMsg( "Out of memory" );
514 for( i=0 ; i<i_max ; i++ )
516 GETS( &c_adt.p_cell_inf[i].i_vob_id );
517 GETC( &c_adt.p_cell_inf[i].i_cell_id );
519 GETL( &c_adt.p_cell_inf[i].i_ssector );
520 GETL( &c_adt.p_cell_inf[i].i_esector );
526 /*****************************************************************************
527 * ReadMap : Fills the VOBU Map structure.
528 *****************************************************************************/
529 static vobu_admap_t ReadMap( ifo_t* p_ifo )
533 off64_t i_start = p_ifo->i_pos;
535 //fprintf( stderr, "VOBU ADMAP\n" );
537 GETL( &map.i_ebyte );
538 i_max = ( i_start + map.i_ebyte + 1 - p_ifo->i_pos ) / sizeof(u32);
539 map.pi_vobu_ssector = malloc( i_max *sizeof(u32) );
540 for( i=0 ; i<i_max ; i++ )
542 GETL( &map.pi_vobu_ssector[i] );
549 * Video Manager Information Processing.
550 * This is what is contained in video_ts.ifo.
553 /*****************************************************************************
554 * ReadVMGInfMat : Fills the Management Information structure.
555 *****************************************************************************/
556 static vmgi_mat_t ReadVMGInfMat( ifo_t* p_ifo )
560 // off64_t i_start = p_ifo->i_pos;
562 //fprintf( stderr, "VMGI\n" );
564 GET( mat.psz_id , 12 );
565 mat.psz_id[12] = '\0';
566 GETL( &mat.i_lsector );
568 GETL( &mat.i_i_lsector );
570 GETC( &mat.i_spec_ver );
572 GETS( &mat.i_vol_nb );
574 GETC( &mat.i_disc_side );
576 GETS( &mat.i_tts_nb );
577 GET( mat.ps_provider_id, 32 );
578 GETLL( &mat.i_pos_code );
580 GETL( &mat.i_i_mat_ebyte );
581 GETL( &mat.i_fp_pgc_sbyte );
583 GETL( &mat.i_vobs_ssector );
584 GETL( &mat.i_ptt_srpt_ssector );
585 GETL( &mat.i_pgci_ut_ssector );
586 GETL( &mat.i_ptl_mait_ssector );
587 GETL( &mat.i_vts_atrt_ssector );
588 GETL( &mat.i_txtdt_mg_ssector );
589 GETL( &mat.i_c_adt_ssector );
590 GETL( &mat.i_vobu_admap_ssector );
592 GETS( &mat.i_video_atrt );
594 GETC( &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 for( i=0 ; i < mat.i_subpic_nb ; i++ )
603 GET( &mat.pi_subpic_atrt[i], 6 );
604 /* FIXME : take care of endianness */
610 /*****************************************************************************
611 * ReadVMGTitlePointer : Fills the Part Of Title Search Pointer structure.
612 *****************************************************************************/
613 static vmg_ptt_srpt_t ReadVMGTitlePointer( ifo_t* p_ifo )
617 // off64_t i_start = p_ifo->i_pos;
619 //fprintf( stderr, "PTR\n" );
621 GETS( &ptr.i_ttu_nb );
623 GETL( &ptr.i_ebyte );
625 ptr.p_tts = malloc( ptr.i_ttu_nb *sizeof(tts_t) );
626 if( ptr.p_tts == NULL )
628 intf_ErrMsg( "Out of memory" );
632 for( i=0 ; i<ptr.i_ttu_nb ; i++ )
634 GETC( &ptr.p_tts[i].i_play_type );
635 GETC( &ptr.p_tts[i].i_angle_nb );
636 GETS( &ptr.p_tts[i].i_ptt_nb );
637 GETS( &ptr.p_tts[i].i_parental_id );
638 GETC( &ptr.p_tts[i].i_tts_nb );
639 GETC( &ptr.p_tts[i].i_vts_ttn );
640 GETL( &ptr.p_tts[i].i_ssector );
646 /*****************************************************************************
647 * ReadParentalInf : Fills the Parental Management structure.
648 *****************************************************************************/
649 static vmg_ptl_mait_t ReadParentalInf( ifo_t* p_ifo )
653 off64_t i_start = p_ifo->i_pos;
655 //fprintf( stderr, "PTL\n" );
657 GETS( &par.i_country_nb );
658 GETS( &par.i_vts_nb );
659 GETL( &par.i_ebyte );
660 par.p_ptl_desc = malloc( par.i_country_nb *sizeof(vmg_ptl_mai_desc_t) );
661 if( par.p_ptl_desc == NULL )
663 intf_ErrMsg( "Out of memory" );
667 for( i=0 ; i<par.i_country_nb ; i++ )
669 GET( par.p_ptl_desc[i].ps_country_code, 2 );
671 GETS( &par.p_ptl_desc[i].i_ptl_mai_sbyte );
674 par.p_ptl_mask = malloc( par.i_country_nb *sizeof(vmg_ptl_mask_t) );
675 if( par.p_ptl_mask == NULL )
677 intf_ErrMsg( "Out of memory" );
681 for( i=0 ; i<par.i_country_nb ; i++ )
683 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_start +
684 par.p_ptl_desc[i].i_ptl_mai_sbyte, SEEK_SET );
685 for( j=1 ; j<=8 ; j++ )
687 par.p_ptl_mask[i].ppi_ptl_mask[j] =
688 malloc( par.i_vts_nb *sizeof(u16) );
689 if( par.p_ptl_mask[i].ppi_ptl_mask[j] == NULL )
691 intf_ErrMsg( "Out of memory" );
695 for( k=0 ; k<par.i_vts_nb ; k++ )
697 GETS( &par.p_ptl_mask[i].ppi_ptl_mask[j][k] );
705 /*****************************************************************************
706 * ReadVTSAttr : Fills the structure about VTS attributes.
707 *****************************************************************************/
708 static vmg_vts_atrt_t ReadVTSAttr( ifo_t* p_ifo )
712 off64_t i_start = p_ifo->i_pos;
714 //fprintf( stderr, "VTS ATTR\n" );
716 GETS( &atrt.i_vts_nb );
718 GETL( &atrt.i_ebyte );
719 atrt.pi_vts_atrt_sbyte = malloc( atrt.i_vts_nb *sizeof(u32) );
720 if( atrt.pi_vts_atrt_sbyte == NULL )
722 intf_ErrMsg( "Out of memory" );
726 for( i=0 ; i<atrt.i_vts_nb ; i++ )
728 GETL( &atrt.pi_vts_atrt_sbyte[i] );
730 atrt.p_vts_atrt = malloc( atrt.i_vts_nb *sizeof(vts_atrt_t) );
731 if( atrt.p_vts_atrt == NULL )
733 intf_ErrMsg( "Out of memory" );
737 for( i=0 ; i<atrt.i_vts_nb ; i++ )
739 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_start +
740 atrt.pi_vts_atrt_sbyte[i],
742 GETL( &atrt.p_vts_atrt[i].i_ebyte );
743 GETL( &atrt.p_vts_atrt[i].i_cat_app_type );
744 GETS( &atrt.p_vts_atrt[i].i_vtsm_video_atrt );
746 GETC( &atrt.p_vts_atrt[i].i_vtsm_audio_nb );
747 for( j=0 ; j<8 ; j++ )
749 GETLL( &atrt.p_vts_atrt[i].pi_vtsm_audio_atrt[j] );
752 GETC( &atrt.p_vts_atrt[i].i_vtsm_subpic_nb );
753 for( j=0 ; j<28 ; j++ )
755 GET( &atrt.p_vts_atrt[i].pi_vtsm_subpic_atrt[j], 6 );
756 /* FIXME : Fix endianness issue here */
759 GETS( &atrt.p_vts_atrt[i].i_vtstt_video_atrt );
761 GETL( &atrt.p_vts_atrt[i].i_vtstt_audio_nb );
762 for( j=0 ; j<8 ; j++ )
764 GETLL( &atrt.p_vts_atrt[i].pi_vtstt_audio_atrt[j] );
767 GETC( &atrt.p_vts_atrt[i].i_vtstt_subpic_nb );
768 for( j=0 ; j<atrt.p_vts_atrt[i].i_vtstt_subpic_nb ; j++ )
770 GET( &atrt.p_vts_atrt[i].pi_vtstt_subpic_atrt[j], 6 );
771 /* FIXME : Fix endianness issue here */
778 /*****************************************************************************
779 * ReadVMG : Parse video_ts.ifo file to fill the Video Manager structure.
780 *****************************************************************************/
781 static vmg_t ReadVMG( ifo_t* p_ifo )
785 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off, SEEK_SET);
786 vmg.mat = ReadVMGInfMat( p_ifo );
787 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
788 vmg.mat.i_fp_pgc_sbyte, SEEK_SET );
789 vmg.pgc = ReadPGC( p_ifo );
790 if( vmg.mat.i_ptt_srpt_ssector )
792 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
793 vmg.mat.i_ptt_srpt_ssector *DVD_LB_SIZE,
795 vmg.ptt_srpt = ReadVMGTitlePointer( p_ifo );
797 if( vmg.mat.i_pgci_ut_ssector )
799 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
800 vmg.mat.i_pgci_ut_ssector *DVD_LB_SIZE,
802 vmg.pgci_ut = ReadUnitTable( p_ifo );
804 if( vmg.mat.i_ptl_mait_ssector )
806 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
807 vmg.mat.i_ptl_mait_ssector *DVD_LB_SIZE,
809 vmg.ptl_mait = ReadParentalInf( p_ifo );
811 if( vmg.mat.i_vts_atrt_ssector )
813 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
814 vmg.mat.i_vts_atrt_ssector *DVD_LB_SIZE,
816 vmg.vts_atrt = ReadVTSAttr( p_ifo );
818 if( vmg.mat.i_c_adt_ssector )
820 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
821 vmg.mat.i_c_adt_ssector *DVD_LB_SIZE,
823 vmg.c_adt = ReadCellInf( p_ifo );
825 if( vmg.mat.i_vobu_admap_ssector )
827 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
828 vmg.mat.i_vobu_admap_ssector *DVD_LB_SIZE,
830 vmg.vobu_admap = ReadMap( p_ifo );
836 * Video Title Set Information Processing.
837 * This is what is contained in vts_*.ifo.
840 /*****************************************************************************
841 * ReadVTSInfMat : Fills the Title Set Information structure.
842 *****************************************************************************/
843 static vtsi_mat_t ReadVTSInfMat( ifo_t* p_ifo )
847 // off64_t i_start = p_ifo->i_pos;
849 //fprintf( stderr, "VTSI\n" );
851 GET( mat.psz_id , 12 );
852 mat.psz_id[12] = '\0';
853 GETL( &mat.i_lsector );
855 GETL( &mat.i_i_lsector );
857 GETC( &mat.i_spec_ver );
860 GETL( &mat.i_mat_ebyte );
862 GETL( &mat.i_m_vobs_ssector );
863 GETL( &mat.i_tt_vobs_ssector );
864 GETL( &mat.i_ptt_srpt_ssector );
865 GETL( &mat.i_pgcit_ssector );
866 GETL( &mat.i_m_pgci_ut_ssector );
867 GETL( &mat.i_tmap_ti_ssector );
868 GETL( &mat.i_m_c_adt_ssector );
869 GETL( &mat.i_m_vobu_admap_ssector );
870 GETL( &mat.i_c_adt_ssector );
871 GETL( &mat.i_vobu_admap_ssector );
873 GETS( &mat.i_m_video_atrt );
875 GETC( &mat.i_m_audio_nb );
876 for( i=0 ; i<8 ; i++ )
878 GETLL( &mat.pi_m_audio_atrt[i] );
881 GETC( &mat.i_m_subpic_nb );
882 for( i=0 ; i<28 ; i++ )
884 GET( &mat.pi_m_subpic_atrt[i], 6 );
885 /* FIXME : take care of endianness */
888 GETS( &mat.i_video_atrt );
890 GETC( &mat.i_audio_nb );
891 for( i=0 ; i<8 ; i++ )
893 GETLL( &mat.pi_audio_atrt[i] );
896 GETC( &mat.i_subpic_nb );
897 for( i=0 ; i<mat.i_subpic_nb ; i++ )
899 GET( &mat.pi_subpic_atrt[i], 6 );
900 /* FIXME : take care of endianness */
906 /*****************************************************************************
907 * ReadVTSTitlePointer : Fills the Part Of Title Search Pointer structure.
908 *****************************************************************************/
909 static vts_ptt_srpt_t ReadVTSTitlePointer( ifo_t* p_ifo )
913 off64_t i_start = p_ifo->i_pos;
915 //fprintf( stderr, "PTR\n" );
917 GETS( &ptr.i_ttu_nb );
919 GETL( &ptr.i_ebyte );
920 ptr.pi_ttu_sbyte = malloc( ptr.i_ttu_nb *sizeof(u32) );
921 if( ptr.pi_ttu_sbyte == NULL )
923 intf_ErrMsg( "Out of memory" );
927 for( i=0 ; i<ptr.i_ttu_nb ; i++ )
929 GETL( &ptr.pi_ttu_sbyte[i] );
932 ptr.p_ttu = malloc( ptr.i_ttu_nb *sizeof(ttu_t) );
933 if( ptr.p_ttu == NULL )
935 intf_ErrMsg( "Out of memory" );
939 for( i=0 ; i<ptr.i_ttu_nb ; i++ )
941 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_start +
942 ptr.pi_ttu_sbyte[i], SEEK_SET );
943 GETS( &ptr.p_ttu[i].i_pgc_nb );
944 GETS( &ptr.p_ttu[i].i_prg_nb );
950 /*****************************************************************************
951 * ReadVTSTimeMap : Fills the time map table
952 *****************************************************************************/
953 static vts_tmap_ti_t ReadVTSTimeMap( ifo_t* p_ifo )
957 // off64_t i_start = p_ifo->i_pos;
959 //fprintf( stderr, "TMAP\n" );
963 GETL( &tmap.i_ebyte );
964 tmap.pi_sbyte = malloc( tmap.i_nb *sizeof(u32) );
965 if( tmap.pi_sbyte == NULL )
967 intf_ErrMsg( "Out of memory" );
971 for( i=0 ; i<tmap.i_nb ; i++ )
973 GETL( &tmap.pi_sbyte[i] );
975 tmap.p_tmap = malloc( tmap.i_nb *sizeof(tmap_t) );
976 if( tmap.p_tmap == NULL )
978 intf_ErrMsg( "Out of memory" );
982 for( i=0 ; i<tmap.i_nb ; i++ )
984 GETC( &tmap.p_tmap[i].i_time_unit );
986 GETS( &tmap.p_tmap[i].i_entry_nb );
987 tmap.p_tmap[i].pi_sector =
988 malloc( tmap.p_tmap[i].i_entry_nb *sizeof(u32) );
989 if( tmap.p_tmap[i].pi_sector == NULL )
991 intf_ErrMsg( "Out of memory" );
995 for( j=0 ; j<tmap.p_tmap[i].i_entry_nb ; j++ )
997 GETL( &tmap.p_tmap[i].pi_sector[j] );
1005 /*****************************************************************************
1006 * ReadVTS : Parse vts*.ifo files to fill the Video Title Set structure.
1007 *****************************************************************************/
1008 static vts_t ReadVTS( ifo_t* p_ifo )
1012 vts.i_pos = p_ifo->i_pos;
1014 vts.mat = ReadVTSInfMat( p_ifo );
1015 if( vts.mat.i_ptt_srpt_ssector )
1017 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1018 vts.mat.i_ptt_srpt_ssector *DVD_LB_SIZE,
1020 vts.ptt_srpt = ReadVTSTitlePointer( p_ifo );
1022 if( vts.mat.i_m_pgci_ut_ssector )
1024 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1025 vts.mat.i_m_pgci_ut_ssector *DVD_LB_SIZE,
1027 vts.pgci_ut = ReadUnitTable( p_ifo );
1029 if( vts.mat.i_pgcit_ssector )
1031 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1032 vts.mat.i_pgcit_ssector *DVD_LB_SIZE,
1034 vts.pgci_ti = ReadUnit( p_ifo );
1036 if( vts.mat.i_tmap_ti_ssector )
1038 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1039 vts.mat.i_tmap_ti_ssector *DVD_LB_SIZE,
1041 vts.tmap_ti = ReadVTSTimeMap( p_ifo );
1043 if( vts.mat.i_m_c_adt_ssector )
1045 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1046 vts.mat.i_m_c_adt_ssector *DVD_LB_SIZE,
1048 vts.m_c_adt = ReadCellInf( p_ifo );
1050 if( vts.mat.i_m_vobu_admap_ssector )
1052 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1053 vts.mat.i_m_vobu_admap_ssector *DVD_LB_SIZE,
1055 vts.m_vobu_admap = ReadMap( p_ifo );
1057 if( vts.mat.i_c_adt_ssector )
1059 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1060 vts.mat.i_c_adt_ssector *DVD_LB_SIZE,
1062 vts.c_adt = ReadCellInf( p_ifo );
1064 if( vts.mat.i_vobu_admap_ssector )
1066 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1067 vts.mat.i_vobu_admap_ssector *DVD_LB_SIZE,
1069 vts.vobu_admap = ReadMap( p_ifo );
1076 * DVD Information Management
1079 /*****************************************************************************
1080 * IfoRead : Function that fills structure and calls specified functions
1082 *****************************************************************************/
1083 void IfoRead( ifo_t* p_ifo )
1088 p_ifo->vmg = ReadVMG( p_ifo );
1089 p_ifo->p_vts = malloc( p_ifo->vmg.mat.i_tts_nb *sizeof(vts_t) );
1090 if( p_ifo->p_vts == NULL )
1092 intf_ErrMsg( "Out of memory" );
1096 for( i=0 ; i<1/*p_ifo->vmg.mat.i_tts_nb*/ ; i++ )
1099 intf_WarnMsg( 3, "######### VTS %d #############\n", i+1 );
1101 i_off = p_ifo->vmg.ptt_srpt.p_tts[i].i_ssector *DVD_LB_SIZE;
1102 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_off, SEEK_SET );
1103 /* FIXME : use udf filesystem to avoid this */
1104 IfoFindVTS( p_ifo );
1105 p_ifo->p_vts[i] = ReadVTS( p_ifo );
1111 * IFO virtual machine : a set of commands that give the behaviour of the dvd
1114 /*****************************************************************************
1115 * CommandRead : translates the command strings in ifo into command
1117 *****************************************************************************/
1118 void CommandRead( ifo_command_t com )
1120 u8* pi_code = (u8*)(&com);
1122 switch( com.i_type )
1127 fprintf( stderr, "NOP\n" );
1129 else if( cmd.i_cmp )
1136 case 2: /* SetSystem */
1147 fprintf( stderr, "Unknown Command\n" );
1154 /*****************************************************************************
1156 *****************************************************************************/
1157 static void IfoGoto( ifo_command_t cmd )
1164 /*****************************************************************************
1166 *****************************************************************************/
1167 static void IfoLnk( ifo_t* p_ifo )
1172 /*****************************************************************************
1174 *****************************************************************************/
1175 static void IfoJmp( ifo_t* p_ifo )