1 /*****************************************************************************
2 * dvd_ifo.c: Functions for ifo parsing
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
6 * Author: Stéphane Borel <stef@via.ecp.fr>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
41 /*****************************************************************************
42 * IfoFindStart : When reading directly on a device, finds the offset to the
43 * beginning of video_ts.ifo.
44 *****************************************************************************/
45 static int IfoFindStart( ifo_t* p_ifo )
47 char psz_ifo_start[12] = "DVDVIDEO-VMG";
50 read( p_ifo->i_fd, psz_test, 12 );
52 while( strncmp( psz_test, psz_ifo_start, 12 ) != 0 )
54 /* The start of ifo file is on a sector boundary */
55 p_ifo->i_pos = lseek64( p_ifo->i_fd,
56 p_ifo->i_pos + DVD_LB_SIZE,
58 read( p_ifo->i_fd, psz_test, 12 );
60 p_ifo->i_off = p_ifo->i_pos;
62 fprintf( stderr, "VMG Off : %lld\n", (long long)(p_ifo->i_off) );
67 /*****************************************************************************
68 * IfoFindVTS : beginning of vts_*.ifo.
69 *****************************************************************************/
70 static int IfoFindVTS( ifo_t* p_ifo )
72 char psz_ifo_start[12] = "DVDVIDEO-VTS";
75 read( p_ifo->i_fd, psz_test, 12 );
77 while( strncmp( psz_test, psz_ifo_start, 12 ) != 0 )
79 /* The start of ifo file is on a sector boundary */
80 p_ifo->i_pos = lseek64( p_ifo->i_fd,
81 p_ifo->i_pos + DVD_LB_SIZE,
83 read( p_ifo->i_fd, psz_test, 12 );
85 p_ifo->i_off = p_ifo->i_pos;
87 fprintf( stderr, "VTS Off : %lld\n", (long long)(p_ifo->i_off) );
92 /*****************************************************************************
93 * IfoInit : Creates an ifo structure and prepares for parsing directly
95 *****************************************************************************/
96 ifo_t IfoInit( int i_fd )
100 /* If we are here the dvd device has already been opened */
102 /* No data at the beginning of the disk
103 * 512000 bytes is just another value :) */
104 ifo.i_pos = lseek64( ifo.i_fd, 250 *DVD_LB_SIZE, SEEK_SET );
105 /* FIXME : use udf filesystem to find the beginning of the file */
106 IfoFindStart( &ifo );
111 /*****************************************************************************
112 * IfoEnd : Frees all the memory allocated to ifo structures
113 *****************************************************************************/
114 void IfoEnd( ifo_t* p_ifo )
118 /* Free structures from video title sets */
119 for( j=0 ; j<p_ifo->vmg.mat.i_tts_nb ; j++ )
121 free( p_ifo->p_vts[j].vobu_admap.pi_vobu_ssector );
122 free( p_ifo->p_vts[j].c_adt.p_cell_inf );
123 free( p_ifo->p_vts[j].m_vobu_admap.pi_vobu_ssector );
124 free( p_ifo->p_vts[j].m_c_adt.p_cell_inf );
125 for( i=0 ; i<p_ifo->p_vts[j].tmap_ti.i_nb ; i++ )
127 free( p_ifo->p_vts[j].tmap_ti.p_tmap[i].pi_sector );
129 free( p_ifo->p_vts[j].tmap_ti.pi_sbyte );
130 free( p_ifo->p_vts[j].tmap_ti.p_tmap );
131 free( p_ifo->p_vts[j].pgci_ti.p_srp );
132 for( i=0 ; i<p_ifo->p_vts[j].pgci_ut.i_lu_nb ; i++ )
134 free( p_ifo->p_vts[j].pgci_ut.p_pgci_inf[i].p_srp );
136 free( p_ifo->p_vts[j].pgci_ut.p_pgci_inf );
137 free( p_ifo->p_vts[j].pgci_ut.p_lu );
140 free( p_ifo->p_vts );
142 /* Free structures from video manager */
143 free( p_ifo->vmg.vobu_admap.pi_vobu_ssector );
144 free( p_ifo->vmg.c_adt.p_cell_inf );
145 for( i=0 ; i<p_ifo->vmg.pgci_ut.i_lu_nb ; i++ )
147 free( p_ifo->vmg.pgci_ut.p_pgci_inf[i].p_srp );
149 free( p_ifo->vmg.pgci_ut.p_pgci_inf );
150 free( p_ifo->vmg.pgci_ut.p_lu );
151 for( i=1 ; i<=8 ; i++ )
153 free( p_ifo->vmg.ptl_mait.p_ptl_mask->ppi_ptl_mask[i] );
155 free( p_ifo->vmg.ptl_mait.p_ptl_desc );
156 free( p_ifo->vmg.ptl_mait.p_ptl_mask );
157 free( p_ifo->vmg.vts_atrt.pi_vts_atrt_sbyte );
158 free( p_ifo->vmg.vts_atrt.p_vts_atrt );
159 free( p_ifo->vmg.pgc.p_cell_pos_inf );
160 free( p_ifo->vmg.pgc.p_cell_play_inf );
161 free( p_ifo->vmg.pgc.prg_map.pi_entry_cell );
162 free( p_ifo->vmg.pgc.com_tab.ps_cell_com );
163 free( p_ifo->vmg.pgc.com_tab.ps_post_com );
164 free( p_ifo->vmg.pgc.com_tab.ps_pre_com );
170 * Macros to process ifo files
173 #define GET( p_field , i_len ) \
175 read( p_ifo->i_fd , (p_field) , (i_len) ); \
176 fprintf(stderr, "Pos : %lld Val : %llx\n", \
177 (long long)(p_ifo->i_pos - i_start), \
178 (long long)*(p_field) ); \
180 lseek64( p_ifo->i_fd, p_ifo->i_pos + (i_len), SEEK_SET ); \
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), \
189 p_ifo->i_pos = lseek64( p_ifo->i_fd , p_ifo->i_pos + 1 , SEEK_SET ); \
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), \
199 p_ifo->i_pos = lseek64( p_ifo->i_fd , p_ifo->i_pos + 2 , SEEK_SET ); \
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), \
209 p_ifo->i_pos = lseek64( p_ifo->i_fd , p_ifo->i_pos + 4 , SEEK_SET ); \
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), \
219 p_ifo->i_pos = lseek64( p_ifo->i_fd , p_ifo->i_pos + 8 , SEEK_SET ); \
222 #define FLUSH( i_len ) \
224 fprintf(stderr, "Pos : %lld\n", (long long)(p_ifo->i_pos - i_start)); \
225 p_ifo->i_pos = lseek64( 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 static pgc_t ReadPGC( ifo_t* p_ifo )
240 off64_t i_start = p_ifo->i_pos;
242 fprintf( stderr, "PGC\n" );
245 GETC( &pgc.i_prg_nb );
246 GETC( &pgc.i_cell_nb );
247 GETL( &pgc.i_play_time );
248 GETL( &pgc.i_prohibited_user_op );
249 for( i=0 ; i<8 ; i++ )
251 GETS( &pgc.pi_audio_status[i] );
253 for( i=0 ; i<32 ; i++ )
255 GETL( &pgc.pi_subpic_status[i] );
257 GETS( &pgc.i_next_pgc_nb );
258 GETS( &pgc.i_prev_pgc_nb );
259 GETS( &pgc.i_goup_pgc_nb );
260 GETC( &pgc.i_still_time );
261 GETC( &pgc.i_play_mode );
262 for( i=0 ; i<16 ; i++ )
264 GETL( &pgc.pi_yuv_color[i] );
265 /* FIXME : We have to erase the extra bit */
267 GETS( &pgc.i_com_tab_sbyte );
268 GETS( &pgc.i_prg_map_sbyte );
269 GETS( &pgc.i_cell_play_inf_sbyte );
270 GETS( &pgc.i_cell_pos_inf_sbyte );
272 /* Parsing of pgc_com_tab_t */
273 if( pgc.i_com_tab_sbyte )
275 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_start
276 + pgc.i_com_tab_sbyte, SEEK_SET );
277 GETS( &pgc.com_tab.i_pre_com_nb );
278 GETS( &pgc.com_tab.i_post_com_nb );
279 GETS( &pgc.com_tab.i_cell_com_nb );
281 if( pgc.com_tab.i_pre_com_nb )
283 pgc.com_tab.ps_pre_com =
284 malloc(pgc.com_tab.i_pre_com_nb *COMMAND_SIZE);
285 if( pgc.com_tab.ps_pre_com == NULL )
287 intf_ErrMsg( "Out of memory" );
291 GET( pgc.com_tab.ps_pre_com,
292 pgc.com_tab.i_pre_com_nb *COMMAND_SIZE );
294 if( pgc.com_tab.i_post_com_nb )
296 pgc.com_tab.ps_post_com =
297 malloc(pgc.com_tab.i_post_com_nb *COMMAND_SIZE);
298 if( pgc.com_tab.ps_post_com == NULL )
300 intf_ErrMsg( "Out of memory" );
304 GET( pgc.com_tab.ps_post_com,
305 pgc.com_tab.i_post_com_nb *COMMAND_SIZE );
307 if( pgc.com_tab.i_cell_com_nb )
309 pgc.com_tab.ps_cell_com =
310 malloc(pgc.com_tab.i_cell_com_nb *COMMAND_SIZE);
311 if( pgc.com_tab.ps_cell_com == NULL )
313 intf_ErrMsg( "Out of memory" );
317 GET( pgc.com_tab.ps_cell_com,
318 pgc.com_tab.i_cell_com_nb *COMMAND_SIZE );
321 /* Parsing of pgc_prg_map_t */
322 if( pgc.i_prg_map_sbyte )
324 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_start
325 + pgc.i_prg_map_sbyte, SEEK_SET );
326 pgc.prg_map.pi_entry_cell = malloc( pgc.i_prg_nb *sizeof(u8) );
327 if( pgc.prg_map.pi_entry_cell == NULL )
329 intf_ErrMsg( "Out of memory" );
333 GET( pgc.prg_map.pi_entry_cell, pgc.i_prg_nb );
334 /* FIXME : check endianness here */
336 /* Parsing of cell_play_inf_t */
337 if( pgc.i_cell_play_inf_sbyte )
339 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_start
340 + pgc.i_cell_play_inf_sbyte, SEEK_SET );
341 pgc.p_cell_play_inf = malloc( pgc.i_cell_nb *sizeof(cell_play_inf_t) );
342 if( pgc.p_cell_play_inf == NULL )
344 intf_ErrMsg( "Out of memory" );
348 for( i=0 ; i<pgc.i_cell_nb ; i++ )
350 GETS( &pgc.p_cell_play_inf[i].i_cat );
351 GETC( &pgc.p_cell_play_inf[i].i_still_time );
352 GETC( &pgc.p_cell_play_inf[i].i_com_nb );
353 GETL( &pgc.p_cell_play_inf[i].i_play_time );
354 GETL( &pgc.p_cell_play_inf[i].i_entry_sector );
355 GETL( &pgc.p_cell_play_inf[i].i_first_ilvu_vobu_esector );
356 GETL( &pgc.p_cell_play_inf[i].i_lvobu_ssector );
357 GETL( &pgc.p_cell_play_inf[i].i_lsector );
360 /* Parsing of cell_pos_inf_map */
361 if( pgc.i_cell_pos_inf_sbyte )
363 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_start
364 + pgc.i_cell_pos_inf_sbyte, SEEK_SET );
365 pgc.p_cell_pos_inf = malloc( pgc.i_cell_nb *sizeof(cell_pos_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_pos_inf[i].i_vob_id );
376 GETC( &pgc.p_cell_pos_inf[i].i_cell_id );
383 /*****************************************************************************
384 * ReadUnit : Fills Menu Language Unit Table/ PGC Info Table
385 *****************************************************************************/
386 static pgci_inf_t ReadUnit( ifo_t* p_ifo )
390 off64_t i_start = p_ifo->i_pos;
392 fprintf( stderr, "Unit\n" );
394 GETS( &inf.i_srp_nb );
396 GETL( &inf.i_lu_ebyte );
397 inf.p_srp = malloc( inf.i_srp_nb *sizeof(pgci_srp_t) );
398 if( inf.p_srp == NULL )
400 intf_ErrMsg( "Out of memory" );
404 for( i=0 ; i<inf.i_srp_nb ; i++ )
406 GETC( &inf.p_srp[i].i_pgc_cat_mask );
407 GETC( &inf.p_srp[i].i_pgc_cat );
408 GETS( &inf.p_srp[i].i_par_mask );
409 GETL( &inf.p_srp[i].i_pgci_sbyte );
411 for( i=0 ; i<inf.i_srp_nb ; i++ )
413 p_ifo->i_pos = lseek64( p_ifo->i_fd,
414 i_start + inf.p_srp[i].i_pgci_sbyte,
416 inf.p_srp[i].pgc = ReadPGC( p_ifo );
422 /*****************************************************************************
423 * ReadUnitTable : Fills the PGCI Unit structure.
424 *****************************************************************************/
425 static pgci_ut_t ReadUnitTable( ifo_t* p_ifo )
429 off64_t i_start = p_ifo->i_pos;
431 fprintf( stderr, "Unit Table\n" );
433 GETS( &pgci.i_lu_nb );
435 GETL( &pgci.i_ebyte );
436 pgci.p_lu = malloc( pgci.i_lu_nb *sizeof(pgci_lu_t) );
437 if( pgci.p_lu == NULL )
439 intf_ErrMsg( "Out of memory" );
443 for( i=0 ; i<pgci.i_lu_nb ; i++ )
445 GET( pgci.p_lu[i].ps_lang_code, 2 );
447 GETC( &pgci.p_lu[i].i_existence_mask );
448 GETL( &pgci.p_lu[i].i_lu_sbyte );
450 pgci.p_pgci_inf = malloc( pgci.i_lu_nb *sizeof(pgci_inf_t) );
451 if( pgci.p_pgci_inf == NULL )
453 intf_ErrMsg( "Out of memory" );
457 for( i=0 ; i<pgci.i_lu_nb ; i++ )
459 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_start +
460 pgci.p_lu[i].i_lu_sbyte,
462 pgci.p_pgci_inf[i] = ReadUnit( p_ifo );
468 /*****************************************************************************
469 * ReadCellInf : Fills the Cell Information structure.
470 *****************************************************************************/
471 static c_adt_t ReadCellInf( ifo_t* p_ifo )
475 off64_t i_start = p_ifo->i_pos;
477 fprintf( stderr, "CELL ADD\n" );
479 GETS( &c_adt.i_vob_nb );
481 GETL( &c_adt.i_ebyte );
482 i_max = ( i_start + c_adt.i_ebyte + 1 - p_ifo->i_pos ) / sizeof(cell_inf_t);
483 c_adt.p_cell_inf = malloc( i_max *sizeof(cell_inf_t) );
484 if( c_adt.p_cell_inf == NULL )
486 intf_ErrMsg( "Out of memory" );
490 for( i=0 ; i<i_max ; i++ )
492 GETS( &c_adt.p_cell_inf[i].i_vob_id );
493 GETC( &c_adt.p_cell_inf[i].i_cell_id );
495 GETL( &c_adt.p_cell_inf[i].i_ssector );
496 GETL( &c_adt.p_cell_inf[i].i_esector );
502 /*****************************************************************************
503 * ReadMap : Fills the VOBU Map structure.
504 *****************************************************************************/
505 static vobu_admap_t ReadMap( ifo_t* p_ifo )
509 off64_t i_start = p_ifo->i_pos;
511 fprintf( stderr, "VOBU ADMAP\n" );
513 GETL( &map.i_ebyte );
514 i_max = ( i_start + map.i_ebyte + 1 - p_ifo->i_pos ) / sizeof(u32);
515 map.pi_vobu_ssector = malloc( i_max *sizeof(u32) );
516 for( i=0 ; i<i_max ; i++ )
518 GETL( &map.pi_vobu_ssector[i] );
525 * Video Manager Information Processing.
526 * This is what is contained in video_ts.ifo.
529 /*****************************************************************************
530 * ReadVMGInfMat : Fills the Management Information structure.
531 *****************************************************************************/
532 static vmgi_mat_t ReadVMGInfMat( ifo_t* p_ifo )
536 off64_t i_start = p_ifo->i_pos;
538 fprintf( stderr, "VMGI\n" );
540 GET( mat.psz_id , 12 );
541 mat.psz_id[12] = '\0';
542 GETL( &mat.i_lsector );
544 GETL( &mat.i_i_lsector );
546 GETC( &mat.i_spec_ver );
548 GETS( &mat.i_vol_nb );
550 GETC( &mat.i_disc_side );
552 GETS( &mat.i_tts_nb );
553 GET( mat.ps_provider_id, 32 );
554 GETLL( &mat.i_pos_code );
556 GETL( &mat.i_i_mat_ebyte );
557 GETL( &mat.i_fp_pgc_sbyte );
559 GETL( &mat.i_vobs_ssector );
560 GETL( &mat.i_ptt_srpt_ssector );
561 GETL( &mat.i_pgci_ut_ssector );
562 GETL( &mat.i_ptl_mait_ssector );
563 GETL( &mat.i_vts_atrt_ssector );
564 GETL( &mat.i_txtdt_mg_ssector );
565 GETL( &mat.i_c_adt_ssector );
566 GETL( &mat.i_vobu_admap_ssector );
568 GETS( &mat.i_video_atrt );
570 GETC( &mat.i_audio_nb );
571 for( i=0 ; i < 8 ; i++ )
573 GETLL( &mat.pi_audio_atrt[i] );
576 GETC( &mat.i_subpic_nb );
577 for( i=0 ; i < mat.i_subpic_nb ; i++ )
579 GET( &mat.pi_subpic_atrt[i], 6 );
580 /* FIXME : take care of endianness */
586 /*****************************************************************************
587 * ReadVMGTitlePointer : Fills the Part Of Title Search Pointer structure.
588 *****************************************************************************/
589 static vmg_ptt_srpt_t ReadVMGTitlePointer( ifo_t* p_ifo )
593 off64_t i_start = p_ifo->i_pos;
595 fprintf( stderr, "PTR\n" );
597 GETS( &ptr.i_ttu_nb );
599 GETL( &ptr.i_ebyte );
601 ptr.p_tts = malloc( ptr.i_ttu_nb *sizeof(tts_t) );
602 if( ptr.p_tts == NULL )
604 intf_ErrMsg( "Out of memory" );
608 for( i=0 ; i<ptr.i_ttu_nb ; i++ )
610 GETC( &ptr.p_tts[i].i_play_type );
611 GETC( &ptr.p_tts[i].i_angle_nb );
612 GETS( &ptr.p_tts[i].i_ptt_nb );
613 GETS( &ptr.p_tts[i].i_parental_id );
614 GETC( &ptr.p_tts[i].i_tts_nb );
615 GETC( &ptr.p_tts[i].i_vts_ttn );
616 GETL( &ptr.p_tts[i].i_ssector );
622 /*****************************************************************************
623 * ReadParentalInf : Fills the Parental Management structure.
624 *****************************************************************************/
625 static vmg_ptl_mait_t ReadParentalInf( ifo_t* p_ifo )
629 off64_t i_start = p_ifo->i_pos;
631 fprintf( stderr, "PTL\n" );
633 GETS( &par.i_country_nb );
634 GETS( &par.i_vts_nb );
635 GETL( &par.i_ebyte );
636 par.p_ptl_desc = malloc( par.i_country_nb *sizeof(vmg_ptl_mai_desc_t) );
637 if( par.p_ptl_desc == NULL )
639 intf_ErrMsg( "Out of memory" );
643 for( i=0 ; i<par.i_country_nb ; i++ )
645 GET( par.p_ptl_desc[i].ps_country_code, 2 );
647 GETS( &par.p_ptl_desc[i].i_ptl_mai_sbyte );
650 par.p_ptl_mask = malloc( par.i_country_nb *sizeof(vmg_ptl_mask_t) );
651 if( par.p_ptl_mask == NULL )
653 intf_ErrMsg( "Out of memory" );
657 for( i=0 ; i<par.i_country_nb ; i++ )
659 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_start +
660 par.p_ptl_desc[i].i_ptl_mai_sbyte, SEEK_SET );
661 for( j=1 ; j<=8 ; j++ )
663 par.p_ptl_mask[i].ppi_ptl_mask[j] =
664 malloc( par.i_vts_nb *sizeof(u16) );
665 if( par.p_ptl_mask[i].ppi_ptl_mask[j] == NULL )
667 intf_ErrMsg( "Out of memory" );
671 for( k=0 ; k<par.i_vts_nb ; k++ )
673 GETS( &par.p_ptl_mask[i].ppi_ptl_mask[j][k] );
681 /*****************************************************************************
682 * ReadVTSAttr : Fills the structure about VTS attributes.
683 *****************************************************************************/
684 static vmg_vts_atrt_t ReadVTSAttr( ifo_t* p_ifo )
688 off64_t i_start = p_ifo->i_pos;
690 fprintf( stderr, "VTS ATTR\n" );
692 GETS( &atrt.i_vts_nb );
694 GETL( &atrt.i_ebyte );
695 atrt.pi_vts_atrt_sbyte = malloc( atrt.i_vts_nb *sizeof(u32) );
696 if( atrt.pi_vts_atrt_sbyte == NULL )
698 intf_ErrMsg( "Out of memory" );
702 for( i=0 ; i<atrt.i_vts_nb ; i++ )
704 GETL( &atrt.pi_vts_atrt_sbyte[i] );
706 atrt.p_vts_atrt = malloc( atrt.i_vts_nb *sizeof(vts_atrt_t) );
707 if( atrt.p_vts_atrt == NULL )
709 intf_ErrMsg( "Out of memory" );
713 for( i=0 ; i<atrt.i_vts_nb ; i++ )
715 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_start +
716 atrt.pi_vts_atrt_sbyte[i],
718 GETL( &atrt.p_vts_atrt[i].i_ebyte );
719 GETL( &atrt.p_vts_atrt[i].i_cat_app_type );
720 GETS( &atrt.p_vts_atrt[i].i_vtsm_video_atrt );
722 GETC( &atrt.p_vts_atrt[i].i_vtsm_audio_nb );
723 for( j=0 ; j<8 ; j++ )
725 GETLL( &atrt.p_vts_atrt[i].pi_vtsm_audio_atrt[j] );
728 GETC( &atrt.p_vts_atrt[i].i_vtsm_subpic_nb );
729 for( j=0 ; j<28 ; j++ )
731 GET( &atrt.p_vts_atrt[i].pi_vtsm_subpic_atrt[j], 6 );
732 /* FIXME : Fix endianness issue here */
735 GETS( &atrt.p_vts_atrt[i].i_vtstt_video_atrt );
737 GETL( &atrt.p_vts_atrt[i].i_vtstt_audio_nb );
738 for( j=0 ; j<8 ; j++ )
740 GETLL( &atrt.p_vts_atrt[i].pi_vtstt_audio_atrt[j] );
743 GETC( &atrt.p_vts_atrt[i].i_vtstt_subpic_nb );
744 for( j=0 ; j<atrt.p_vts_atrt[i].i_vtstt_subpic_nb ; j++ )
746 GET( &atrt.p_vts_atrt[i].pi_vtstt_subpic_atrt[j], 6 );
747 /* FIXME : Fix endianness issue here */
754 /*****************************************************************************
755 * ReadVMG : Parse video_ts.ifo file to fill the Video Manager structure.
756 *****************************************************************************/
757 static vmg_t ReadVMG( ifo_t* p_ifo )
761 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off, SEEK_SET);
762 vmg.mat = ReadVMGInfMat( p_ifo );
763 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
764 vmg.mat.i_fp_pgc_sbyte, SEEK_SET );
765 vmg.pgc = ReadPGC( p_ifo );
766 if( vmg.mat.i_ptt_srpt_ssector )
768 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
769 vmg.mat.i_ptt_srpt_ssector *DVD_LB_SIZE,
771 vmg.ptt_srpt = ReadVMGTitlePointer( p_ifo );
773 if( vmg.mat.i_pgci_ut_ssector )
775 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
776 vmg.mat.i_pgci_ut_ssector *DVD_LB_SIZE,
778 vmg.pgci_ut = ReadUnitTable( p_ifo );
780 if( vmg.mat.i_ptl_mait_ssector )
782 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
783 vmg.mat.i_ptl_mait_ssector *DVD_LB_SIZE,
785 vmg.ptl_mait = ReadParentalInf( p_ifo );
787 if( vmg.mat.i_vts_atrt_ssector )
789 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
790 vmg.mat.i_vts_atrt_ssector *DVD_LB_SIZE,
792 vmg.vts_atrt = ReadVTSAttr( p_ifo );
794 if( vmg.mat.i_c_adt_ssector )
796 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
797 vmg.mat.i_c_adt_ssector *DVD_LB_SIZE,
799 vmg.c_adt = ReadCellInf( p_ifo );
801 if( vmg.mat.i_vobu_admap_ssector )
803 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
804 vmg.mat.i_vobu_admap_ssector *DVD_LB_SIZE,
806 vmg.vobu_admap = ReadMap( p_ifo );
812 * Video Title Set Information Processing.
813 * This is what is contained in vts_*.ifo.
816 /*****************************************************************************
817 * ReadVTSInfMat : Fills the Title Set Information structure.
818 *****************************************************************************/
819 static vtsi_mat_t ReadVTSInfMat( ifo_t* p_ifo )
823 off64_t i_start = p_ifo->i_pos;
825 fprintf( stderr, "VTSI\n" );
827 GET( mat.psz_id , 12 );
828 mat.psz_id[12] = '\0';
829 GETL( &mat.i_lsector );
831 GETL( &mat.i_i_lsector );
833 GETC( &mat.i_spec_ver );
836 GETL( &mat.i_mat_ebyte );
838 GETL( &mat.i_m_vobs_ssector );
839 GETL( &mat.i_tt_vobs_ssector );
840 GETL( &mat.i_ptt_srpt_ssector );
841 GETL( &mat.i_pgcit_ssector );
842 GETL( &mat.i_m_pgci_ut_ssector );
843 GETL( &mat.i_tmap_ti_ssector );
844 GETL( &mat.i_m_c_adt_ssector );
845 GETL( &mat.i_m_vobu_admap_ssector );
846 GETL( &mat.i_c_adt_ssector );
847 GETL( &mat.i_vobu_admap_ssector );
849 GETS( &mat.i_m_video_atrt );
851 GETC( &mat.i_m_audio_nb );
852 for( i=0 ; i<8 ; i++ )
854 GETLL( &mat.pi_m_audio_atrt[i] );
857 GETC( &mat.i_m_subpic_nb );
858 for( i=0 ; i<28 ; i++ )
860 GET( &mat.pi_m_subpic_atrt[i], 6 );
861 /* FIXME : take care of endianness */
864 GETS( &mat.i_video_atrt );
866 GETC( &mat.i_audio_nb );
867 for( i=0 ; i<8 ; i++ )
869 GETLL( &mat.pi_audio_atrt[i] );
872 GETC( &mat.i_subpic_nb );
873 for( i=0 ; i<mat.i_subpic_nb ; i++ )
875 GET( &mat.pi_subpic_atrt[i], 6 );
876 /* FIXME : take care of endianness */
882 /*****************************************************************************
883 * ReadVTSTitlePointer : Fills the Part Of Title Search Pointer structure.
884 *****************************************************************************/
885 static vts_ptt_srpt_t ReadVTSTitlePointer( ifo_t* p_ifo )
889 off64_t i_start = p_ifo->i_pos;
891 fprintf( stderr, "PTR\n" );
893 GETS( &ptr.i_ttu_nb );
895 GETL( &ptr.i_ebyte );
896 ptr.pi_ttu_sbyte = malloc( ptr.i_ttu_nb *sizeof(u32) );
897 if( ptr.pi_ttu_sbyte == NULL )
899 intf_ErrMsg( "Out of memory" );
903 for( i=0 ; i<ptr.i_ttu_nb ; i++ )
905 GETL( &ptr.pi_ttu_sbyte[i] );
908 ptr.p_ttu = malloc( ptr.i_ttu_nb *sizeof(ttu_t) );
909 if( ptr.p_ttu == NULL )
911 intf_ErrMsg( "Out of memory" );
915 for( i=0 ; i<ptr.i_ttu_nb ; i++ )
917 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_start +
918 ptr.pi_ttu_sbyte[i], SEEK_SET );
919 GETS( &ptr.p_ttu[i].i_pgc_nb );
920 GETS( &ptr.p_ttu[i].i_prg_nb );
926 /*****************************************************************************
927 * ReadVTSTimeMap : Fills the time map table
928 *****************************************************************************/
929 static vts_tmap_ti_t ReadVTSTimeMap( ifo_t* p_ifo )
933 off64_t i_start = p_ifo->i_pos;
935 fprintf( stderr, "TMAP\n" );
939 GETL( &tmap.i_ebyte );
940 tmap.pi_sbyte = malloc( tmap.i_nb *sizeof(u32) );
941 if( tmap.pi_sbyte == NULL )
943 intf_ErrMsg( "Out of memory" );
947 for( i=0 ; i<tmap.i_nb ; i++ )
949 GETL( &tmap.pi_sbyte[i] );
951 tmap.p_tmap = malloc( tmap.i_nb *sizeof(tmap_t) );
952 if( tmap.p_tmap == NULL )
954 intf_ErrMsg( "Out of memory" );
958 for( i=0 ; i<tmap.i_nb ; i++ )
960 GETC( &tmap.p_tmap[i].i_time_unit );
962 GETS( &tmap.p_tmap[i].i_entry_nb );
963 tmap.p_tmap[i].pi_sector =
964 malloc( tmap.p_tmap[i].i_entry_nb *sizeof(u32) );
965 if( tmap.p_tmap[i].pi_sector == NULL )
967 intf_ErrMsg( "Out of memory" );
971 for( j=0 ; j<tmap.p_tmap[i].i_entry_nb ; j++ )
973 GETL( &tmap.p_tmap[i].pi_sector[j] );
981 /*****************************************************************************
982 * ReadVTS : Parse vts*.ifo files to fill the Video Title Set structure.
983 *****************************************************************************/
984 static vts_t ReadVTS( ifo_t* p_ifo )
988 vts.i_pos = p_ifo->i_pos;
990 vts.mat = ReadVTSInfMat( p_ifo );
991 if( vts.mat.i_ptt_srpt_ssector )
993 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
994 vts.mat.i_ptt_srpt_ssector *DVD_LB_SIZE,
996 vts.ptt_srpt = ReadVTSTitlePointer( p_ifo );
998 if( vts.mat.i_m_pgci_ut_ssector )
1000 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1001 vts.mat.i_m_pgci_ut_ssector *DVD_LB_SIZE,
1003 vts.pgci_ut = ReadUnitTable( p_ifo );
1005 if( vts.mat.i_pgcit_ssector )
1007 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1008 vts.mat.i_pgcit_ssector *DVD_LB_SIZE,
1010 vts.pgci_ti = ReadUnit( p_ifo );
1012 if( vts.mat.i_tmap_ti_ssector )
1014 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1015 vts.mat.i_tmap_ti_ssector *DVD_LB_SIZE,
1017 vts.tmap_ti = ReadVTSTimeMap( p_ifo );
1019 if( vts.mat.i_m_c_adt_ssector )
1021 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1022 vts.mat.i_m_c_adt_ssector *DVD_LB_SIZE,
1024 vts.m_c_adt = ReadCellInf( p_ifo );
1026 if( vts.mat.i_m_vobu_admap_ssector )
1028 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1029 vts.mat.i_m_vobu_admap_ssector *DVD_LB_SIZE,
1031 vts.m_vobu_admap = ReadMap( p_ifo );
1033 if( vts.mat.i_c_adt_ssector )
1035 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1036 vts.mat.i_c_adt_ssector *DVD_LB_SIZE,
1038 vts.c_adt = ReadCellInf( p_ifo );
1040 if( vts.mat.i_vobu_admap_ssector )
1042 p_ifo->i_pos = lseek64( p_ifo->i_fd, p_ifo->i_off +
1043 vts.mat.i_vobu_admap_ssector *DVD_LB_SIZE,
1045 vts.vobu_admap = ReadMap( p_ifo );
1052 * DVD Information Management
1055 /*****************************************************************************
1056 * IfoRead : Function that fills structure and calls specified functions
1058 *****************************************************************************/
1059 void IfoRead( ifo_t* p_ifo )
1064 p_ifo->vmg = ReadVMG( p_ifo );
1065 p_ifo->p_vts = malloc( p_ifo->vmg.mat.i_tts_nb *sizeof(vts_t) );
1066 if( p_ifo->p_vts == NULL )
1068 intf_ErrMsg( "Out of memory" );
1072 for( i=0 ; i<p_ifo->vmg.mat.i_tts_nb ; i++ )
1075 fprintf( stderr, "######### VTS %d #############\n", i );
1077 i_off = p_ifo->vmg.ptt_srpt.p_tts[i].i_ssector *DVD_LB_SIZE;
1078 p_ifo->i_pos = lseek64( p_ifo->i_fd, i_off, SEEK_SET );
1079 /* FIXME : use udf filesystem to avoid this */
1080 IfoFindVTS( p_ifo );
1081 p_ifo->p_vts[i] = ReadVTS( p_ifo );