1 /*****************************************************************************
2 * dvd_ifo.c: Functions for ifo parsing
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: dvd_ifo.c,v 1.2 2001/02/08 08:08:03 stef 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 //fprintf( stderr, "vmgi audio nb : %d\n", mat.i_audio_nb );
596 for( i=0 ; i < 8 ; i++ )
598 GETLL( &mat.pi_audio_atrt[i] );
601 GETC( &mat.i_subpic_nb );
602 //fprintf( stderr, "vmgi subpic nb : %d\n", mat.i_subpic_nb );
603 for( i=0 ; i < mat.i_subpic_nb ; i++ )
605 GET( &mat.pi_subpic_atrt[i], 6 );
606 /* FIXME : take care of endianness */
612 /*****************************************************************************
613 * ReadVMGTitlePointer : Fills the Part Of Title Search Pointer structure.
614 *****************************************************************************/
615 static vmg_ptt_srpt_t ReadVMGTitlePointer( ifo_t* p_ifo )
619 // off64_t i_start = p_ifo->i_pos;
621 //fprintf( stderr, "PTR\n" );
623 GETS( &ptr.i_ttu_nb );
625 GETL( &ptr.i_ebyte );
627 ptr.p_tts = malloc( ptr.i_ttu_nb *sizeof(tts_t) );
628 if( ptr.p_tts == NULL )
630 intf_ErrMsg( "Out of memory" );
634 for( i=0 ; i<ptr.i_ttu_nb ; i++ )
636 GETC( &ptr.p_tts[i].i_play_type );
637 GETC( &ptr.p_tts[i].i_angle_nb );
638 GETS( &ptr.p_tts[i].i_ptt_nb );
639 GETS( &ptr.p_tts[i].i_parental_id );
640 GETC( &ptr.p_tts[i].i_tts_nb );
641 GETC( &ptr.p_tts[i].i_vts_ttn );
642 GETL( &ptr.p_tts[i].i_ssector );
648 /*****************************************************************************
649 * ReadParentalInf : Fills the Parental Management structure.
650 *****************************************************************************/
651 static vmg_ptl_mait_t ReadParentalInf( ifo_t* p_ifo )
655 off64_t i_start = p_ifo->i_pos;
657 //fprintf( stderr, "PTL\n" );
659 GETS( &par.i_country_nb );
660 GETS( &par.i_vts_nb );
661 GETL( &par.i_ebyte );
662 par.p_ptl_desc = malloc( par.i_country_nb *sizeof(vmg_ptl_mai_desc_t) );
663 if( par.p_ptl_desc == NULL )
665 intf_ErrMsg( "Out of memory" );
669 for( i=0 ; i<par.i_country_nb ; i++ )
671 GET( par.p_ptl_desc[i].ps_country_code, 2 );
673 GETS( &par.p_ptl_desc[i].i_ptl_mai_sbyte );
676 par.p_ptl_mask = malloc( par.i_country_nb *sizeof(vmg_ptl_mask_t) );
677 if( par.p_ptl_mask == NULL )
679 intf_ErrMsg( "Out of memory" );
683 for( i=0 ; i<par.i_country_nb ; i++ )
685 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_start +
686 par.p_ptl_desc[i].i_ptl_mai_sbyte, SEEK_SET );
687 for( j=1 ; j<=8 ; j++ )
689 par.p_ptl_mask[i].ppi_ptl_mask[j] =
690 malloc( par.i_vts_nb *sizeof(u16) );
691 if( par.p_ptl_mask[i].ppi_ptl_mask[j] == NULL )
693 intf_ErrMsg( "Out of memory" );
697 for( k=0 ; k<par.i_vts_nb ; k++ )
699 GETS( &par.p_ptl_mask[i].ppi_ptl_mask[j][k] );
707 /*****************************************************************************
708 * ReadVTSAttr : Fills the structure about VTS attributes.
709 *****************************************************************************/
710 static vmg_vts_atrt_t ReadVTSAttr( ifo_t* p_ifo )
714 off64_t i_start = p_ifo->i_pos;
716 //fprintf( stderr, "VTS ATTR\n" );
718 GETS( &atrt.i_vts_nb );
720 GETL( &atrt.i_ebyte );
721 atrt.pi_vts_atrt_sbyte = malloc( atrt.i_vts_nb *sizeof(u32) );
722 if( atrt.pi_vts_atrt_sbyte == NULL )
724 intf_ErrMsg( "Out of memory" );
728 for( i=0 ; i<atrt.i_vts_nb ; i++ )
730 GETL( &atrt.pi_vts_atrt_sbyte[i] );
732 atrt.p_vts_atrt = malloc( atrt.i_vts_nb *sizeof(vts_atrt_t) );
733 if( atrt.p_vts_atrt == NULL )
735 intf_ErrMsg( "Out of memory" );
739 for( i=0 ; i<atrt.i_vts_nb ; i++ )
741 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_start +
742 atrt.pi_vts_atrt_sbyte[i],
744 GETL( &atrt.p_vts_atrt[i].i_ebyte );
745 GETL( &atrt.p_vts_atrt[i].i_cat_app_type );
746 GETS( &atrt.p_vts_atrt[i].i_vtsm_video_atrt );
748 GETC( &atrt.p_vts_atrt[i].i_vtsm_audio_nb );
749 //fprintf( stderr, "m audio nb : %d\n", atrt.p_vts_atrt[i].i_vtsm_audio_nb );
750 for( j=0 ; j<8 ; j++ )
752 GETLL( &atrt.p_vts_atrt[i].pi_vtsm_audio_atrt[j] );
755 GETC( &atrt.p_vts_atrt[i].i_vtsm_subpic_nb );
756 //fprintf( stderr, "m subp nb : %d\n", atrt.p_vts_atrt[i].i_vtsm_subpic_nb );
757 for( j=0 ; j<28 ; j++ )
759 GET( &atrt.p_vts_atrt[i].pi_vtsm_subpic_atrt[j], 6 );
760 /* FIXME : Fix endianness issue here */
763 GETS( &atrt.p_vts_atrt[i].i_vtstt_video_atrt );
765 GETL( &atrt.p_vts_atrt[i].i_vtstt_audio_nb );
766 //fprintf( stderr, "tt audio nb : %d\n", atrt.p_vts_atrt[i].i_vtstt_audio_nb );
767 for( j=0 ; j<8 ; j++ )
769 GETLL( &atrt.p_vts_atrt[i].pi_vtstt_audio_atrt[j] );
772 GETC( &atrt.p_vts_atrt[i].i_vtstt_subpic_nb );
773 //fprintf( stderr, "tt subp nb : %d\n", atrt.p_vts_atrt[i].i_vtstt_subpic_nb );
774 for( j=0 ; j<28/*atrt.p_vts_atrt[i].i_vtstt_subpic_nb*/ ; j++ )
776 GET( &atrt.p_vts_atrt[i].pi_vtstt_subpic_atrt[j], 6 );
777 /* FIXME : Fix endianness issue here */
784 /*****************************************************************************
785 * ReadVMG : Parse video_ts.ifo file to fill the Video Manager structure.
786 *****************************************************************************/
787 static vmg_t ReadVMG( ifo_t* p_ifo )
791 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off, SEEK_SET);
792 vmg.mat = ReadVMGInfMat( p_ifo );
793 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
794 vmg.mat.i_fp_pgc_sbyte, SEEK_SET );
795 vmg.pgc = ReadPGC( p_ifo );
796 if( vmg.mat.i_ptt_srpt_ssector )
798 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
799 vmg.mat.i_ptt_srpt_ssector *DVD_LB_SIZE,
801 vmg.ptt_srpt = ReadVMGTitlePointer( p_ifo );
803 if( vmg.mat.i_pgci_ut_ssector )
805 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
806 vmg.mat.i_pgci_ut_ssector *DVD_LB_SIZE,
808 vmg.pgci_ut = ReadUnitTable( p_ifo );
810 if( vmg.mat.i_ptl_mait_ssector )
812 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
813 vmg.mat.i_ptl_mait_ssector *DVD_LB_SIZE,
815 vmg.ptl_mait = ReadParentalInf( p_ifo );
817 if( vmg.mat.i_vts_atrt_ssector )
819 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
820 vmg.mat.i_vts_atrt_ssector *DVD_LB_SIZE,
822 vmg.vts_atrt = ReadVTSAttr( p_ifo );
824 if( vmg.mat.i_c_adt_ssector )
826 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
827 vmg.mat.i_c_adt_ssector *DVD_LB_SIZE,
829 vmg.c_adt = ReadCellInf( p_ifo );
831 if( vmg.mat.i_vobu_admap_ssector )
833 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
834 vmg.mat.i_vobu_admap_ssector *DVD_LB_SIZE,
836 vmg.vobu_admap = ReadMap( p_ifo );
842 * Video Title Set Information Processing.
843 * This is what is contained in vts_*.ifo.
846 /*****************************************************************************
847 * ReadVTSInfMat : Fills the Title Set Information structure.
848 *****************************************************************************/
849 static vtsi_mat_t ReadVTSInfMat( ifo_t* p_ifo )
853 // off64_t i_start = p_ifo->i_pos;
855 //fprintf( stderr, "VTSI\n" );
857 GET( mat.psz_id , 12 );
858 mat.psz_id[12] = '\0';
859 GETL( &mat.i_lsector );
861 GETL( &mat.i_i_lsector );
863 GETC( &mat.i_spec_ver );
866 GETL( &mat.i_mat_ebyte );
868 GETL( &mat.i_m_vobs_ssector );
869 GETL( &mat.i_tt_vobs_ssector );
870 GETL( &mat.i_ptt_srpt_ssector );
871 GETL( &mat.i_pgcit_ssector );
872 GETL( &mat.i_m_pgci_ut_ssector );
873 GETL( &mat.i_tmap_ti_ssector );
874 GETL( &mat.i_m_c_adt_ssector );
875 GETL( &mat.i_m_vobu_admap_ssector );
876 GETL( &mat.i_c_adt_ssector );
877 GETL( &mat.i_vobu_admap_ssector );
879 GETS( &mat.i_m_video_atrt );
881 GETC( &mat.i_m_audio_nb );
882 for( i=0 ; i<8 ; i++ )
884 GETLL( &mat.pi_m_audio_atrt[i] );
887 GETC( &mat.i_m_subpic_nb );
888 for( i=0 ; i<28 ; i++ )
890 GET( &mat.pi_m_subpic_atrt[i], 6 );
891 /* FIXME : take care of endianness */
894 GETS( &mat.i_video_atrt );
896 GETC( &mat.i_audio_nb );
897 //fprintf( stderr, "vtsi audio nb : %d\n", mat.i_audio_nb );
898 for( i=0 ; i<8 ; i++ )
900 GETLL( &mat.pi_audio_atrt[i] );
903 GETC( &mat.i_subpic_nb );
904 //fprintf( stderr, "vtsi subpic nb : %d\n", mat.i_subpic_nb );
905 for( i=0 ; i<mat.i_subpic_nb ; i++ )
907 GET( &mat.pi_subpic_atrt[i], 6 );
908 /* FIXME : take care of endianness */
914 /*****************************************************************************
915 * ReadVTSTitlePointer : Fills the Part Of Title Search Pointer structure.
916 *****************************************************************************/
917 static vts_ptt_srpt_t ReadVTSTitlePointer( ifo_t* p_ifo )
921 off64_t i_start = p_ifo->i_pos;
923 //fprintf( stderr, "PTR\n" );
925 GETS( &ptr.i_ttu_nb );
927 GETL( &ptr.i_ebyte );
928 ptr.pi_ttu_sbyte = malloc( ptr.i_ttu_nb *sizeof(u32) );
929 if( ptr.pi_ttu_sbyte == NULL )
931 intf_ErrMsg( "Out of memory" );
935 for( i=0 ; i<ptr.i_ttu_nb ; i++ )
937 GETL( &ptr.pi_ttu_sbyte[i] );
940 ptr.p_ttu = malloc( ptr.i_ttu_nb *sizeof(ttu_t) );
941 if( ptr.p_ttu == NULL )
943 intf_ErrMsg( "Out of memory" );
947 for( i=0 ; i<ptr.i_ttu_nb ; i++ )
949 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_start +
950 ptr.pi_ttu_sbyte[i], SEEK_SET );
951 GETS( &ptr.p_ttu[i].i_pgc_nb );
952 GETS( &ptr.p_ttu[i].i_prg_nb );
958 /*****************************************************************************
959 * ReadVTSTimeMap : Fills the time map table
960 *****************************************************************************/
961 static vts_tmap_ti_t ReadVTSTimeMap( ifo_t* p_ifo )
965 // off64_t i_start = p_ifo->i_pos;
967 //fprintf( stderr, "TMAP\n" );
971 GETL( &tmap.i_ebyte );
972 tmap.pi_sbyte = malloc( tmap.i_nb *sizeof(u32) );
973 if( tmap.pi_sbyte == NULL )
975 intf_ErrMsg( "Out of memory" );
979 for( i=0 ; i<tmap.i_nb ; i++ )
981 GETL( &tmap.pi_sbyte[i] );
983 tmap.p_tmap = malloc( tmap.i_nb *sizeof(tmap_t) );
984 if( tmap.p_tmap == NULL )
986 intf_ErrMsg( "Out of memory" );
990 for( i=0 ; i<tmap.i_nb ; i++ )
992 GETC( &tmap.p_tmap[i].i_time_unit );
994 GETS( &tmap.p_tmap[i].i_entry_nb );
995 tmap.p_tmap[i].pi_sector =
996 malloc( tmap.p_tmap[i].i_entry_nb *sizeof(u32) );
997 if( tmap.p_tmap[i].pi_sector == NULL )
999 intf_ErrMsg( "Out of memory" );
1003 for( j=0 ; j<tmap.p_tmap[i].i_entry_nb ; j++ )
1005 GETL( &tmap.p_tmap[i].pi_sector[j] );
1013 /*****************************************************************************
1014 * ReadVTS : Parse vts*.ifo files to fill the Video Title Set structure.
1015 *****************************************************************************/
1016 static vts_t ReadVTS( ifo_t* p_ifo )
1020 vts.i_pos = p_ifo->i_pos;
1022 vts.mat = ReadVTSInfMat( p_ifo );
1023 if( vts.mat.i_ptt_srpt_ssector )
1025 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1026 vts.mat.i_ptt_srpt_ssector *DVD_LB_SIZE,
1028 vts.ptt_srpt = ReadVTSTitlePointer( p_ifo );
1030 if( vts.mat.i_m_pgci_ut_ssector )
1032 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1033 vts.mat.i_m_pgci_ut_ssector *DVD_LB_SIZE,
1035 vts.pgci_ut = ReadUnitTable( p_ifo );
1037 if( vts.mat.i_pgcit_ssector )
1039 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1040 vts.mat.i_pgcit_ssector *DVD_LB_SIZE,
1042 vts.pgci_ti = ReadUnit( p_ifo );
1044 if( vts.mat.i_tmap_ti_ssector )
1046 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1047 vts.mat.i_tmap_ti_ssector *DVD_LB_SIZE,
1049 vts.tmap_ti = ReadVTSTimeMap( p_ifo );
1051 if( vts.mat.i_m_c_adt_ssector )
1053 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1054 vts.mat.i_m_c_adt_ssector *DVD_LB_SIZE,
1056 vts.m_c_adt = ReadCellInf( p_ifo );
1058 if( vts.mat.i_m_vobu_admap_ssector )
1060 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1061 vts.mat.i_m_vobu_admap_ssector *DVD_LB_SIZE,
1063 vts.m_vobu_admap = ReadMap( p_ifo );
1065 if( vts.mat.i_c_adt_ssector )
1067 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1068 vts.mat.i_c_adt_ssector *DVD_LB_SIZE,
1070 vts.c_adt = ReadCellInf( p_ifo );
1072 if( vts.mat.i_vobu_admap_ssector )
1074 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1075 vts.mat.i_vobu_admap_ssector *DVD_LB_SIZE,
1077 vts.vobu_admap = ReadMap( p_ifo );
1084 * DVD Information Management
1087 /*****************************************************************************
1088 * IfoRead : Function that fills structure and calls specified functions
1090 *****************************************************************************/
1091 void IfoRead( ifo_t* p_ifo )
1096 p_ifo->vmg = ReadVMG( p_ifo );
1097 p_ifo->p_vts = malloc( p_ifo->vmg.mat.i_tts_nb *sizeof(vts_t) );
1098 if( p_ifo->p_vts == NULL )
1100 intf_ErrMsg( "Out of memory" );
1104 for( i=0 ; i<1/*p_ifo->vmg.mat.i_tts_nb*/ ; i++ )
1107 intf_WarnMsg( 3, "######### VTS %d #############\n", i+1 );
1109 i_off = p_ifo->vmg.ptt_srpt.p_tts[i].i_ssector *DVD_LB_SIZE;
1110 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_off, SEEK_SET );
1111 /* FIXME : use udf filesystem to avoid this */
1112 IfoFindVTS( p_ifo );
1113 p_ifo->p_vts[i] = ReadVTS( p_ifo );
1119 * IFO virtual machine : a set of commands that give the behaviour of the dvd
1122 /*****************************************************************************
1123 * CommandRead : translates the command strings in ifo into command
1125 *****************************************************************************/
1126 void CommandRead( ifo_command_t com )
1128 u8* pi_code = (u8*)(&com);
1130 switch( com.i_type )
1135 fprintf( stderr, "NOP\n" );
1137 else if( cmd.i_cmp )
1144 case 2: /* SetSystem */
1155 fprintf( stderr, "Unknown Command\n" );
1162 /*****************************************************************************
1164 *****************************************************************************/
1165 static void IfoGoto( ifo_command_t cmd )
1172 /*****************************************************************************
1174 *****************************************************************************/
1175 static void IfoLnk( ifo_t* p_ifo )
1180 /*****************************************************************************
1182 *****************************************************************************/
1183 static void IfoJmp( ifo_t* p_ifo )