1 /*****************************************************************************
2 * dvd_ifo.c: Functions for ifo parsing
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: dvd_ifo.c,v 1.21 2001/04/15 15:32:48 stef Exp $
7 * Author: Stéphane Borel <stef@via.ecp.fr>
10 * - libifo by Thomas Mirlacher <dent@cosy.sbg.ac.at>
11 * - IFO structure documentation by Thomas Mirlacher, Björn Englund,
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
27 *****************************************************************************/
29 /*****************************************************************************
31 *****************************************************************************/
47 #include "input_dvd.h"
52 void CommandRead ( command_desc_t );
53 static int ReadTitle ( ifo_t * , title_t *, off_t );
54 static int FreeTitle ( title_t * );
55 static int ReadUnitInf ( ifo_t * , unit_inf_t *, off_t );
56 static int FreeUnitInf ( unit_inf_t * );
57 static int ReadTitleUnit ( ifo_t * , title_unit_t *, off_t );
58 static int FreeTitleUnit ( title_unit_t * );
59 static int ReadVobuMap ( ifo_t * , vobu_map_t *, off_t );
60 static int FreeVobuMap ( vobu_map_t * );
61 static int ReadCellInf ( ifo_t * , cell_inf_t *, off_t );
62 static int FreeCellInf ( cell_inf_t * );
63 static int FreeTitleSet ( vts_t * );
65 /*****************************************************************************
67 *****************************************************************************/
68 static __inline__ u8* FillBuffer( ifo_t* p_ifo, u8* pi_buffer, off_t i_pos )
70 memset( pi_buffer, 0, DVD_LB_SIZE );
71 p_ifo->i_pos = lseek( p_ifo->i_fd, i_pos, SEEK_SET );
72 read( p_ifo->i_fd, pi_buffer, DVD_LB_SIZE );
77 static __inline__ u8 ReadByte( ifo_t * p_ifo, u8* pi_buffer, u8** pp_current )
81 if( *pp_current >= pi_buffer + DVD_LB_SIZE )
83 *pp_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_pos );
86 i_ret = *(*pp_current)++;
91 static __inline__ u16 ReadWord( ifo_t* p_ifo, u8* pi_buffer, u8** pp_current )
95 if( *pp_current >= pi_buffer + DVD_LB_SIZE - 2 )
97 *pp_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_pos );
100 i_ret = U16_AT(*pp_current);
106 static __inline__ u32 ReadDouble( ifo_t * p_ifo, u8* pi_buffer,
111 if( *pp_current >= pi_buffer + DVD_LB_SIZE - 4 )
113 *pp_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_pos );
116 i_ret = U32_AT(*pp_current);
122 static __inline__ u64 ReadQuad( ifo_t* p_ifo, u8* pi_buffer, u8** pp_current )
126 if( *pp_current >= pi_buffer + DVD_LB_SIZE - 8 )
128 *pp_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_pos );
131 i_ret = U64_AT(*pp_current);
137 static __inline__ void ReadBits( ifo_t* p_ifo, u8* pi_buffer, u8** pp_current,
138 u8* pi_dest, int i_nb )
140 if( *pp_current >= pi_buffer + DVD_LB_SIZE - i_nb )
142 *pp_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_pos );
145 memcpy( pi_dest, *pp_current, i_nb );
151 static __inline__ void DumpBits( ifo_t* p_ifo, u8* pi_buffer,
152 u8** pp_current, int i_nb )
154 if( *pp_current >= pi_buffer + DVD_LB_SIZE - i_nb )
156 *pp_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_pos );
167 /*****************************************************************************
168 * IfoCreate : Creates an ifo structure and prepares for parsing directly
170 *****************************************************************************/
171 int IfoCreate( thread_dvd_data_t * p_dvd )
173 p_dvd->p_ifo = malloc( sizeof(ifo_t) );
174 if( p_dvd->p_ifo == NULL )
176 intf_ErrMsg( "ifo error: unable to allocate memory. aborting" );
180 /* if we are here the dvd device has already been opened */
181 p_dvd->p_ifo->i_fd = p_dvd->i_fd;
186 /*****************************************************************************
187 * IfoInit : Reads information from the management table.
188 *****************************************************************************/
189 int IfoInit( ifo_t * p_ifo )
191 u8 pi_buffer[DVD_LB_SIZE];
198 /* find the start sector of video information on the dvd */
199 i_lba = UDFFindFile( p_ifo->i_fd, "/VIDEO_TS/VIDEO_TS.IFO");
201 p_ifo->i_off = (off_t)(i_lba) * DVD_LB_SIZE;
203 p_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_off );
204 //i_start = p_ifo->i_pos;
206 * read the video manager information table
208 #define manager_inf p_ifo->vmg.manager_inf
209 //fprintf( stderr, "VMGI\n" );
211 ReadBits( p_ifo, pi_buffer, &p_current, manager_inf.psz_id, 12 );
212 manager_inf.psz_id[12] = '\0';
213 manager_inf.i_vmg_end_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
214 DumpBits( p_ifo, pi_buffer, &p_current, 12 );
215 manager_inf.i_vmg_inf_end_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
216 DumpBits( p_ifo, pi_buffer, &p_current, 1 );
217 manager_inf.i_spec_ver = ReadByte( p_ifo, pi_buffer, &p_current );
218 manager_inf.i_cat = ReadDouble( p_ifo, pi_buffer, &p_current );
219 manager_inf.i_volume_nb = ReadWord( p_ifo, pi_buffer, &p_current );
220 manager_inf.i_volume = ReadWord( p_ifo, pi_buffer, &p_current );
221 manager_inf.i_disc_side = ReadByte( p_ifo, pi_buffer, &p_current );
222 DumpBits( p_ifo, pi_buffer, &p_current, 19 );
223 manager_inf.i_title_set_nb = ReadWord( p_ifo, pi_buffer, &p_current );
224 ReadBits( p_ifo, pi_buffer, &p_current, manager_inf.ps_provider_id, 32 );
225 manager_inf.i_pos_code = ReadQuad( p_ifo, pi_buffer, &p_current );
226 DumpBits( p_ifo, pi_buffer, &p_current, 24 );
227 manager_inf.i_vmg_inf_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
228 manager_inf.i_first_play_title_start_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
229 DumpBits( p_ifo, pi_buffer, &p_current, 56 );
230 manager_inf.i_vob_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
231 manager_inf.i_title_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
232 manager_inf.i_title_unit_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
233 manager_inf.i_parental_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
234 manager_inf.i_vts_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
235 manager_inf.i_text_data_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
236 manager_inf.i_cell_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
237 manager_inf.i_vobu_map_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
238 DumpBits( p_ifo, pi_buffer, &p_current, 32 );
239 // GETS( &manager_inf.video_atrt );
240 DumpBits( p_ifo, pi_buffer, &p_current, 2 );
241 DumpBits( p_ifo, pi_buffer, &p_current, 1 );
242 manager_inf.i_audio_nb = ReadByte( p_ifo, pi_buffer, &p_current );
243 //fprintf( stderr, "vmgi audio nb : %d\n", manager_inf.i_audio_nb );
244 for( i=0 ; i < 8 ; i++ )
246 i_temp = ReadQuad( p_ifo, pi_buffer, &p_current );
248 DumpBits( p_ifo, pi_buffer, &p_current, 17 );
249 manager_inf.i_spu_nb = ReadByte( p_ifo, pi_buffer, &p_current );
250 //fprintf( stderr, "vmgi subpic nb : %d\n", manager_inf.i_spu_nb );
251 for( i=0 ; i < manager_inf.i_spu_nb ; i++ )
253 ReadBits( p_ifo, pi_buffer, &p_current, (u8*)(&i_temp), 6 );
254 /* FIXME : take care of endianness */
258 * read first play title.
260 if( ReadTitle( p_ifo, &p_ifo->vmg.title, p_ifo->i_off +
261 manager_inf.i_first_play_title_start_byte ) < 0 )
267 * fills the title information structure.
269 #define title_inf p_ifo->vmg.title_inf
270 if( manager_inf.i_title_inf_start_sector )
272 p_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_off +
273 manager_inf.i_title_inf_start_sector *DVD_LB_SIZE );
274 //fprintf( stderr, "title inf %lld\n", p_ifo->i_pos );
276 title_inf.i_title_nb = ReadWord( p_ifo, pi_buffer, &p_current );
277 //fprintf( stderr, "title_inf: TTU nb %d\n", title_inf.i_title_nb );
278 DumpBits( p_ifo, pi_buffer, &p_current, 2 );
279 title_inf.i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
281 /* parsing of title attributes */
282 title_inf.p_attr = malloc( title_inf.i_title_nb *sizeof(title_attr_t) );
283 if( title_inf.p_attr == NULL )
285 intf_ErrMsg( "ifo error: out of memory in IfoInit" );
289 for( i = 0 ; i < title_inf.i_title_nb ; i++ )
291 title_inf.p_attr[i].i_play_type = ReadByte( p_ifo, pi_buffer, &p_current );
292 title_inf.p_attr[i].i_angle_nb = ReadByte( p_ifo, pi_buffer, &p_current );
293 title_inf.p_attr[i].i_chapter_nb = ReadWord( p_ifo, pi_buffer, &p_current );
294 title_inf.p_attr[i].i_parental_id = ReadWord( p_ifo, pi_buffer, &p_current );
295 title_inf.p_attr[i].i_title_set_num = ReadByte( p_ifo, pi_buffer, &p_current );
296 title_inf.p_attr[i].i_title_num = ReadByte( p_ifo, pi_buffer, &p_current );
297 title_inf.p_attr[i].i_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
298 //fprintf( stderr, "title_inf: %d %d %d\n",title_inf.p_attr[i].i_chapter_nb ,title_inf.p_attr[i].i_title_set_num,title_inf.p_attr[i].i_title_num );
303 title_inf.p_attr = NULL;
308 * fills the title unit structure.
310 if( manager_inf.i_title_unit_start_sector )
312 if( ReadTitleUnit( p_ifo, &p_ifo->vmg.title_unit, p_ifo->i_off +
313 manager_inf.i_title_unit_start_sector *DVD_LB_SIZE ) < 0 )
320 * fills the structure about parental information.
322 #define parental p_ifo->vmg.parental_inf
323 if( manager_inf.i_parental_inf_start_sector )
325 p_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_off +
326 manager_inf.i_parental_inf_start_sector *DVD_LB_SIZE );
327 i_start = p_ifo->i_pos;
329 //fprintf( stderr, "PTL\n" );
331 parental.i_country_nb = ReadWord( p_ifo, pi_buffer, &p_current );
332 parental.i_vts_nb = ReadWord( p_ifo, pi_buffer, &p_current );
333 parental.i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
335 parental.p_parental_desc = malloc( parental.i_country_nb *
336 sizeof(parental_desc_t) );
337 if( parental.p_parental_desc == NULL )
339 intf_ErrMsg( "ifo error: out of memory in IfoInit" );
343 for( i = 0 ; i < parental.i_country_nb ; i++ )
345 ReadBits( p_ifo, pi_buffer, &p_current,
346 parental.p_parental_desc[i].ps_country_code, 2 );
347 DumpBits( p_ifo, pi_buffer, &p_current, 2 );
348 parental.p_parental_desc[i].i_parental_mask_start_byte =
349 ReadWord( p_ifo, pi_buffer, &p_current );
350 DumpBits( p_ifo, pi_buffer, &p_current, 2 );
353 parental.p_parental_mask = malloc( parental.i_country_nb *
354 sizeof(parental_mask_t) );
355 if( parental.p_parental_mask == NULL )
357 intf_ErrMsg( "ifo erro: out of memory in IfoInit" );
361 for( i = 0 ; i < parental.i_country_nb ; i++ )
363 p_current = FillBuffer( p_ifo, pi_buffer, i_start +
364 parental.p_parental_desc[i].i_parental_mask_start_byte );
365 for( j = 0 ; j < 8 ; j++ )
367 parental.p_parental_mask[i].ppi_mask[j] =
368 malloc( ( parental.i_vts_nb + 1 ) *sizeof(u16) );
369 if( parental.p_parental_mask[i].ppi_mask[j] == NULL )
371 intf_ErrMsg( "ifo error: out of memory in IfoInit" );
374 for( k = 0 ; k < parental.i_vts_nb + 1 ; k++ )
376 parental.p_parental_mask[i].ppi_mask[j][k] =
377 ReadWord( p_ifo, pi_buffer, &p_current );
385 * information and attributes about for each vts.
387 #define vts_inf p_ifo->vmg.vts_inf
388 if( manager_inf.i_vts_inf_start_sector )
392 p_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_off +
393 manager_inf.i_vts_inf_start_sector *DVD_LB_SIZE );
394 i_start = p_ifo->i_pos;
396 //fprintf( stderr, "VTS ATTR\n" );
398 vts_inf.i_vts_nb = ReadWord( p_ifo, pi_buffer, &p_current );;
399 //fprintf( stderr, "VTS ATTR Nb: %d\n", vts_inf.i_vts_nb );
400 DumpBits( p_ifo, pi_buffer, &p_current, 2 );
401 vts_inf.i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
402 vts_inf.pi_vts_attr_start_byte =
403 malloc( vts_inf.i_vts_nb *sizeof(u32) );
404 if( vts_inf.pi_vts_attr_start_byte == NULL )
406 intf_ErrMsg( "ifo error: out of memory in IfoInit" );
410 for( i = 0 ; i < vts_inf.i_vts_nb ; i++ )
412 vts_inf.pi_vts_attr_start_byte[i] = ReadDouble( p_ifo, pi_buffer, &p_current );
415 vts_inf.p_vts_attr = malloc( vts_inf.i_vts_nb *sizeof(vts_attr_t) );
416 if( vts_inf.p_vts_attr == NULL )
418 intf_ErrMsg( "ifo erro: out of memory in IfoInit" );
422 for( i = 0 ; i < vts_inf.i_vts_nb ; i++ )
424 p_current = FillBuffer( p_ifo, pi_buffer, i_start +
425 vts_inf.pi_vts_attr_start_byte[i] );
426 vts_inf.p_vts_attr[i].i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
427 vts_inf.p_vts_attr[i].i_cat_app_type = ReadDouble( p_ifo, pi_buffer, &p_current );
428 // GETS( &vts_inf.p_vts_attr[i].vts_menu_video_attr );
429 DumpBits( p_ifo, pi_buffer, &p_current, 2 );
430 DumpBits( p_ifo, pi_buffer, &p_current, 1 );
431 vts_inf.p_vts_attr[i].i_vts_menu_audio_nb = ReadByte( p_ifo, pi_buffer, &p_current );
432 //fprintf( stderr, "m audio nb : %d\n", vts_inf.p_vts_attr[i].i_vts_menu_audio_nb );
433 for( j = 0 ; j < 8 ; j++ )
435 i_temp = ReadQuad( p_ifo, pi_buffer, &p_current );;
437 DumpBits( p_ifo, pi_buffer, &p_current, 17 );
438 vts_inf.p_vts_attr[i].i_vts_menu_spu_nb = ReadByte( p_ifo, pi_buffer, &p_current );
439 //fprintf( stderr, "m subp nb : %d\n", vts_inf.p_vts_attr[i].i_vts_menu_spu_nb );
440 for( j = 0 ; j < 28 ; j++ )
442 ReadBits( p_ifo, pi_buffer, &p_current, (u8*)(&i_temp), 6 );
443 /* FIXME : Fix endianness issue here */
445 DumpBits( p_ifo, pi_buffer, &p_current, 2 );
446 // GETS( &vts_inf.p_vts_attr[i].vtstt_video_vts_inf );
447 DumpBits( p_ifo, pi_buffer, &p_current, 2 );
448 DumpBits( p_ifo, pi_buffer, &p_current, 1 );
449 vts_inf.p_vts_attr[i].i_vts_title_audio_nb =
450 ReadDouble( p_ifo, pi_buffer, &p_current );
451 //fprintf( stderr, "tt audio nb : %d\n", vts_inf.p_vts_attr[i].i_vts_title_audio_nb );
452 for( j = 0 ; j < 8 ; j++ )
454 i_temp = ReadQuad( p_ifo, pi_buffer, &p_current );;
456 DumpBits( p_ifo, pi_buffer, &p_current, 17 );
457 vts_inf.p_vts_attr[i].i_vts_title_spu_nb = ReadByte( p_ifo, pi_buffer, &p_current );
458 //fprintf( stderr, "tt subp nb : %d\n", vts_inf.p_vts_attr[i].i_vts_title_spu_nb );
459 for( j=0 ; j<28/*vts_inf.p_vts_vts_inf[i].i_vtstt_subpic_nb*/ ; j++ )
461 ReadBits( p_ifo, pi_buffer, &p_current, (u8*)(&i_temp), 6 );
462 /* FIXME : Fix endianness issue here */
471 if( manager_inf.i_cell_inf_start_sector )
473 if( ReadCellInf( p_ifo, &p_ifo->vmg.cell_inf, p_ifo->i_off +
474 manager_inf.i_cell_inf_start_sector *DVD_LB_SIZE ) < 0 )
481 * global vob unit map.
483 if( manager_inf.i_vobu_map_start_sector )
485 if( ReadVobuMap( p_ifo, &p_ifo->vmg.vobu_map, p_ifo->i_off +
486 manager_inf.i_vobu_map_start_sector *DVD_LB_SIZE ) < 0 )
493 p_ifo->vts.b_initialized = 0;
495 intf_WarnMsg( 1, "ifo info: vmg initialized" );
500 /*****************************************************************************
501 * IfoTitleSet: Parse vts*.ifo files to fill the Video Title Set structure.
502 *****************************************************************************/
503 int IfoTitleSet( ifo_t * p_ifo )
505 u8 pi_buffer[DVD_LB_SIZE];
512 if( p_ifo->vts.b_initialized )
514 FreeTitleSet( &p_ifo->vts );
518 (off_t)( p_ifo->vmg.title_inf.p_attr[p_ifo->i_title-1].i_start_sector )
522 //fprintf(stderr, "offset: %lld\n" , i_off );
524 p_current = FillBuffer( p_ifo, pi_buffer, i_off );
525 //i_start = p_ifo->i_pos;
526 p_ifo->vts.i_pos = p_ifo->i_pos;
528 #define manager_inf p_ifo->vts.manager_inf
530 * reads manager information
532 //fprintf( stderr, "VTSI\n" );
534 ReadBits( p_ifo, pi_buffer, &p_current, manager_inf.psz_id , 12 );
535 manager_inf.psz_id[12] = '\0';
536 manager_inf.i_end_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
537 DumpBits( p_ifo, pi_buffer, &p_current, 12 );
538 manager_inf.i_inf_end_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
539 DumpBits( p_ifo, pi_buffer, &p_current, 1 );
540 manager_inf.i_spec_ver = ReadByte( p_ifo, pi_buffer, &p_current );
541 manager_inf.i_cat = ReadDouble( p_ifo, pi_buffer, &p_current );
542 DumpBits( p_ifo, pi_buffer, &p_current, 90 );
543 manager_inf.i_inf_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
544 DumpBits( p_ifo, pi_buffer, &p_current, 60 );
545 manager_inf.i_menu_vob_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
546 manager_inf.i_title_vob_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
547 manager_inf.i_title_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
548 manager_inf.i_title_unit_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
549 manager_inf.i_menu_unit_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
550 manager_inf.i_time_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
551 manager_inf.i_menu_cell_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
552 manager_inf.i_menu_vobu_map_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
553 manager_inf.i_cell_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
554 manager_inf.i_vobu_map_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
555 DumpBits( p_ifo, pi_buffer, &p_current, 24 );
556 // GETS( &manager_inf.m_video_atrt );
557 DumpBits( p_ifo, pi_buffer, &p_current, 2 );
558 DumpBits( p_ifo, pi_buffer, &p_current, 1 );
559 manager_inf.i_menu_audio_nb = ReadByte( p_ifo, pi_buffer, &p_current );
560 for( i = 0 ; i < 8 ; i++ )
562 i_temp = ReadQuad( p_ifo, pi_buffer, &p_current );
564 DumpBits( p_ifo, pi_buffer, &p_current, 17 );
565 manager_inf.i_menu_spu_nb = ReadByte( p_ifo, pi_buffer, &p_current );
566 for( i = 0 ; i < 28 ; i++ )
568 ReadBits( p_ifo, pi_buffer, &p_current, (u8*)(&i_temp), 6 );
569 /* FIXME : take care of endianness */
571 DumpBits( p_ifo, pi_buffer, &p_current, 2 );
572 // GETS( &manager_inf.video_atrt );
573 DumpBits( p_ifo, pi_buffer, &p_current, 2 );
574 DumpBits( p_ifo, pi_buffer, &p_current, 1 );
575 manager_inf.i_audio_nb = ReadByte( p_ifo, pi_buffer, &p_current );
576 //fprintf( stderr, "vtsi audio nb : %d\n", manager_inf.i_audio_nb );
577 for( i = 0 ; i < 8 ; i++ )
579 i_temp = ReadQuad( p_ifo, pi_buffer, &p_current );
580 //fprintf( stderr, "Audio %d: %llx\n", i, i_temp );
582 manager_inf.p_audio_attr[i].i_bar = i_temp & 0xff;
584 manager_inf.p_audio_attr[i].i_caption = i_temp & 0xff;
586 manager_inf.p_audio_attr[i].i_foo = i_temp & 0xff;
588 manager_inf.p_audio_attr[i].i_lang_code = i_temp & 0xffff;
590 manager_inf.p_audio_attr[i].i_num_channels = i_temp & 0x7;
592 manager_inf.p_audio_attr[i].i_test = i_temp & 0x1;
594 manager_inf.p_audio_attr[i].i_sample_freq = i_temp & 0x3;
596 manager_inf.p_audio_attr[i].i_quantization = i_temp & 0x3;
598 manager_inf.p_audio_attr[i].i_appl_mode = i_temp & 0x3;
600 manager_inf.p_audio_attr[i].i_type = i_temp & 0x3;
602 manager_inf.p_audio_attr[i].i_multichannel_extension = i_temp & 0x1;
604 manager_inf.p_audio_attr[i].i_coding_mode = i_temp & 0x7;
606 DumpBits( p_ifo, pi_buffer, &p_current, 17 );
607 manager_inf.i_spu_nb = ReadByte( p_ifo, pi_buffer, &p_current );
608 //fprintf( stderr, "vtsi subpic nb : %d\n", manager_inf.i_spu_nb );
609 for( i=0 ; i<manager_inf.i_spu_nb ; i++ )
611 ReadBits( p_ifo, pi_buffer, &p_current, (u8*)(&i_temp), 6 );
612 i_temp = hton64( i_temp ) >> 16;
613 //fprintf( stderr, "Subpic %d: %llx\n", i, i_temp );
614 manager_inf.p_spu_attr[i].i_caption = i_temp & 0xff;
616 manager_inf.p_spu_attr[i].i_lang_code = i_temp & 0xffff;
618 manager_inf.p_spu_attr[i].i_prefix = i_temp & 0xffff;
622 * reads title information: set of pointers to title
624 #define title_inf p_ifo->vts.title_inf
625 if( manager_inf.i_title_inf_start_sector )
627 p_current = FillBuffer( p_ifo, pi_buffer, p_ifo->vts.i_pos +
628 manager_inf.i_title_inf_start_sector *DVD_LB_SIZE );
630 i_start = p_ifo->i_pos;
632 //fprintf( stderr, "VTS PTR\n" );
634 title_inf.i_title_nb = ReadWord( p_ifo, pi_buffer, &p_current );
635 //fprintf( stderr, "VTS title_inf nb: %d\n", title_inf.i_title_nb );
636 DumpBits( p_ifo, pi_buffer, &p_current, 2 );
637 title_inf.i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
639 title_inf.pi_start_byte = malloc( title_inf.i_title_nb *sizeof(u32) );
640 if( title_inf.pi_start_byte == NULL )
642 intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
646 for( i = 0 ; i < title_inf.i_title_nb ; i++ )
648 title_inf.pi_start_byte[i] = ReadDouble( p_ifo, pi_buffer, &p_current );
652 title_inf.p_title_start = malloc( title_inf.i_title_nb
653 *sizeof(title_start_t) );
654 if( title_inf.p_title_start == NULL )
656 intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
660 for( i = 0 ; i < title_inf.i_title_nb ; i++ )
662 p_current = FillBuffer( p_ifo, pi_buffer, i_start +
663 title_inf.pi_start_byte[i] );
665 title_inf.p_title_start[i].i_program_chain_num =
666 ReadWord( p_ifo, pi_buffer, &p_current );
667 title_inf.p_title_start[i].i_program_num = ReadWord( p_ifo, pi_buffer, &p_current );
668 //fprintf( stderr, "VTS %d title_inf Pgc: %d Prg: %d\n", i,title_inf.p_title_start[i].i_program_chain_num, title_inf.p_title_start[i].i_program_num );
674 * menu unit information
676 if( manager_inf.i_menu_unit_start_sector )
678 if( ReadTitleUnit( p_ifo, &p_ifo->vts.menu_unit, p_ifo->vts.i_pos +
679 manager_inf.i_menu_unit_start_sector *DVD_LB_SIZE ) < 0 )
686 * title unit information
688 if( manager_inf.i_title_unit_start_sector )
690 if( ReadUnitInf( p_ifo, &p_ifo->vts.title_unit, p_ifo->vts.i_pos +
691 manager_inf.i_title_unit_start_sector *DVD_LB_SIZE ) < 0 )
698 * time map inforamtion
700 #define time_inf p_ifo->vts.time_inf
701 if( manager_inf.i_time_inf_start_sector )
703 u8 pi_buffer[DVD_LB_SIZE];
705 p_current = FillBuffer( p_ifo, pi_buffer, p_ifo->vts.i_pos +
706 manager_inf.i_time_inf_start_sector *DVD_LB_SIZE );
708 //fprintf( stderr, "TMAP\n" );
710 time_inf.i_nb = ReadWord( p_ifo, pi_buffer, &p_current );;
711 DumpBits( p_ifo, pi_buffer, &p_current, 2 );
712 time_inf.i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
714 time_inf.pi_start_byte = malloc( time_inf.i_nb *sizeof(u32) );
715 if( time_inf.pi_start_byte == NULL )
717 intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
721 for( i = 0 ; i < time_inf.i_nb ; i++ )
723 time_inf.pi_start_byte[i] = ReadDouble( p_ifo, pi_buffer, &p_current );
726 time_inf.p_time_map = malloc( time_inf.i_nb *sizeof(time_map_t) );
727 if( time_inf.p_time_map == NULL )
729 intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
733 for( i = 0 ; i < time_inf.i_nb ; i++ )
735 time_inf.p_time_map[i].i_time_unit = ReadByte( p_ifo, pi_buffer, &p_current );
736 DumpBits( p_ifo, pi_buffer, &p_current, 1 );
737 time_inf.p_time_map[i].i_entry_nb = ReadWord( p_ifo, pi_buffer, &p_current );
739 time_inf.p_time_map[i].pi_sector =
740 malloc( time_inf.p_time_map[i].i_entry_nb *sizeof(u32) );
741 if( time_inf.p_time_map[i].pi_sector == NULL )
743 intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
747 for( j = 0 ; j < time_inf.p_time_map[i].i_entry_nb ; j++ )
749 time_inf.p_time_map[i].pi_sector[j] = ReadDouble( p_ifo, pi_buffer, &p_current );
755 if( manager_inf.i_menu_cell_inf_start_sector )
757 if( ReadCellInf( p_ifo, &p_ifo->vts.menu_cell_inf, p_ifo->vts.i_pos +
758 manager_inf.i_menu_cell_inf_start_sector *DVD_LB_SIZE ) < 0 )
764 if( manager_inf.i_menu_vobu_map_start_sector )
766 if( ReadVobuMap( p_ifo, &p_ifo->vts.menu_vobu_map, p_ifo->vts.i_pos +
767 manager_inf.i_menu_vobu_map_start_sector *DVD_LB_SIZE ) < 0 )
773 if( manager_inf.i_cell_inf_start_sector )
775 if( ReadCellInf( p_ifo, &p_ifo->vts.cell_inf, p_ifo->vts.i_pos +
776 manager_inf.i_cell_inf_start_sector *DVD_LB_SIZE ) )
782 if( manager_inf.i_vobu_map_start_sector )
784 if( ReadVobuMap( p_ifo, &p_ifo->vts.vobu_map, p_ifo->vts.i_pos +
785 manager_inf.i_vobu_map_start_sector *DVD_LB_SIZE ) )
792 intf_WarnMsg( 2, "ifo info: vts %d initialized",
793 p_ifo->vmg.title_inf.p_attr[p_ifo->i_title-1].i_title_set_num );
795 p_ifo->vts.b_initialized = 1;
800 /*****************************************************************************
801 * FreeTitleSet : free all structures allocated by IfoTitleSet
802 *****************************************************************************/
803 static int FreeTitleSet( vts_t * p_vts )
807 if( p_vts->manager_inf.i_vobu_map_start_sector )
809 FreeVobuMap( &p_vts->vobu_map );
812 if( p_vts->manager_inf.i_cell_inf_start_sector )
814 FreeCellInf( &p_vts->cell_inf );
817 if( p_vts->manager_inf.i_menu_vobu_map_start_sector )
819 FreeVobuMap( &p_vts->menu_vobu_map );
822 if( p_vts->manager_inf.i_menu_cell_inf_start_sector )
824 FreeCellInf( &p_vts->menu_cell_inf );
827 if( p_vts->manager_inf.i_time_inf_start_sector )
829 for( i = 0 ; i < p_vts->time_inf.i_nb ; i++ )
831 free( p_vts->time_inf.p_time_map[i].pi_sector );
834 free( p_vts->time_inf.p_time_map );
835 free( p_vts->time_inf.pi_start_byte );
838 if( p_vts->manager_inf.i_title_unit_start_sector )
840 FreeUnitInf( &p_vts->title_unit );
843 if( p_vts->manager_inf.i_menu_unit_start_sector )
845 FreeTitleUnit( &p_vts->menu_unit );
848 if( p_vts->manager_inf.i_title_inf_start_sector )
850 free( p_vts->title_inf.pi_start_byte );
851 free( p_vts->title_inf.p_title_start );
854 p_vts->b_initialized = 0;
859 /*****************************************************************************
860 * IfoDestroy : Frees all the memory allocated to ifo structures
861 *****************************************************************************/
862 void IfoDestroy( ifo_t * p_ifo )
866 FreeTitleSet( &p_ifo->vts );
868 if( p_ifo->vmg.manager_inf.i_vobu_map_start_sector )
870 FreeVobuMap( &p_ifo->vmg.vobu_map );
873 if( p_ifo->vmg.manager_inf.i_cell_inf_start_sector )
875 FreeCellInf( &p_ifo->vmg.cell_inf );
878 if( p_ifo->vmg.manager_inf.i_vts_inf_start_sector )
880 free( p_ifo->vmg.vts_inf.p_vts_attr );
881 free( p_ifo->vmg.vts_inf.pi_vts_attr_start_byte );
884 /* free parental information structures */
885 if( p_ifo->vmg.manager_inf.i_parental_inf_start_sector )
887 for( i = 0 ; i < p_ifo->vmg.parental_inf.i_country_nb ; i++ )
889 for( j = 0 ; j < 8 ; j++ )
891 free( p_ifo->vmg.parental_inf.p_parental_mask[i].ppi_mask[j] );
895 free( p_ifo->vmg.parental_inf.p_parental_mask );
896 free( p_ifo->vmg.parental_inf.p_parental_desc );
899 if( p_ifo->vmg.manager_inf.i_title_unit_start_sector )
901 FreeTitleUnit( &p_ifo->vmg.title_unit );
904 if( p_ifo->vmg.manager_inf.i_title_inf_start_sector )
906 free( p_ifo->vmg.title_inf.p_attr );
909 FreeTitle( &p_ifo->vmg.title );
916 * Function common to Video Manager and Video Title set Processing
919 /*****************************************************************************
920 * ReadTitle : Fills the title structure.
921 *****************************************************************************
922 * Titles are logical stream units that correspond to a whole inside the dvd.
923 * Several title can point to the same part of the physical DVD, and give
924 * map to different anglesfor instance.
925 *****************************************************************************/
926 static int ReadTitle( ifo_t * p_ifo, title_t * p_title, off_t i_pos )
928 u8 pi_buffer[DVD_LB_SIZE];
933 p_current = FillBuffer( p_ifo, pi_buffer, i_pos );
935 i_start = p_ifo->i_pos;
937 //fprintf( stderr, "PGC @ %lld\n",p_ifo->i_pos );
939 DumpBits( p_ifo, pi_buffer, &p_current, 2);
940 p_title->i_chapter_nb = ReadByte( p_ifo, pi_buffer, &p_current );
941 p_title->i_cell_nb = ReadByte( p_ifo, pi_buffer, &p_current );
942 //fprintf( stderr, "title: Prg: %d Cell: %d\n",p_title->i_chapter_nb,p_title->i_cell_nb );
943 p_title->i_play_time = ReadDouble( p_ifo, pi_buffer, &p_current );
944 p_title->i_prohibited_user_op = ReadDouble( p_ifo, pi_buffer, &p_current );
945 for( i = 0 ; i < 8 ; i++ )
947 p_title->pi_audio_status[i] = ReadWord( p_ifo, pi_buffer, &p_current );
949 for( i = 0 ; i < 32 ; i++ )
951 p_title->pi_subpic_status[i] = ReadDouble( p_ifo, pi_buffer, &p_current );
953 p_title->i_next_title_num = ReadWord( p_ifo, pi_buffer, &p_current );
954 p_title->i_prev_title_num = ReadWord( p_ifo, pi_buffer, &p_current );
955 p_title->i_go_up_title_num = ReadWord( p_ifo, pi_buffer, &p_current );
956 //fprintf( stderr, "title: Prev: %d Next: %d Up: %d\n",pgc.i_prev_pgc_nb ,pgc.i_next_pgc_nb, pgc.i_goup_pgc_nb );
957 p_title->i_still_time = ReadByte( p_ifo, pi_buffer, &p_current );
958 p_title->i_play_mode = ReadByte( p_ifo, pi_buffer, &p_current );
959 for( i = 0 ; i < 16 ; i++ )
961 p_title->pi_yuv_color[i] = ReadDouble( p_ifo, pi_buffer, &p_current );
962 /* FIXME : We have to erase the extra bit */
964 p_title->i_command_start_byte = ReadWord( p_ifo, pi_buffer, &p_current );
965 p_title->i_chapter_map_start_byte = ReadWord( p_ifo, pi_buffer, &p_current );
966 p_title->i_cell_play_start_byte = ReadWord( p_ifo, pi_buffer, &p_current );
967 p_title->i_cell_pos_start_byte = ReadWord( p_ifo, pi_buffer, &p_current );
969 /* parsing of command_t */
970 if( p_title->i_command_start_byte )
972 p_current = FillBuffer( p_ifo, pi_buffer,
973 i_start + p_title->i_command_start_byte );
976 p_title->command.i_pre_command_nb = ReadWord( p_ifo, pi_buffer, &p_current );
977 p_title->command.i_post_command_nb = ReadWord( p_ifo, pi_buffer, &p_current );
978 p_title->command.i_cell_command_nb = ReadWord( p_ifo, pi_buffer, &p_current );
979 DumpBits( p_ifo, pi_buffer, &p_current, 2 );
981 /* pre-title commands */
982 if( p_title->command.i_pre_command_nb )
984 p_title->command.p_pre_command =
985 malloc( p_title->command.i_pre_command_nb
986 *sizeof(command_desc_t) );
988 if( p_title->command.p_pre_command == NULL )
990 intf_ErrMsg( "ifo error: out of memory in ReadTitle" );
994 for( i = 0 ; i < p_title->command.i_pre_command_nb ; i++ )
996 p_title->command.p_pre_command[i] = ReadQuad( p_ifo, pi_buffer, &p_current );
1001 p_title->command.p_pre_command = NULL;
1004 /* post-title commands */
1005 if( p_title->command.i_post_command_nb )
1007 p_title->command.p_post_command =
1008 malloc( p_title->command.i_post_command_nb
1009 *sizeof(command_desc_t) );
1011 if( p_title->command.p_post_command == NULL )
1013 intf_ErrMsg( "ifo error: out of memory in ReadTitle" );
1017 for( i=0 ; i<p_title->command.i_post_command_nb ; i++ )
1019 p_title->command.p_post_command[i] = ReadQuad( p_ifo, pi_buffer, &p_current );
1024 p_title->command.p_post_command = NULL;
1028 if( p_title->command.i_cell_command_nb )
1030 p_title->command.p_cell_command =
1031 malloc( p_title->command.i_cell_command_nb
1032 *sizeof(command_desc_t) );
1034 if( p_title->command.p_cell_command == NULL )
1036 intf_ErrMsg( "ifo error: out of memory in ReadTitle" );
1040 for( i=0 ; i<p_title->command.i_cell_command_nb ; i++ )
1042 p_title->command.p_cell_command[i] = ReadQuad( p_ifo, pi_buffer, &p_current );
1047 p_title->command.p_cell_command = NULL;
1051 /* parsing of chapter_map_t: it gives the entry cell for each chapter */
1052 if( p_title->i_chapter_map_start_byte )
1054 p_ifo->i_pos = lseek( p_ifo->i_fd,
1055 i_start + p_title->i_chapter_map_start_byte,
1058 p_title->chapter_map.pi_start_cell =
1059 malloc( p_title->i_chapter_nb *sizeof(chapter_map_t) );
1061 if( p_title->chapter_map.pi_start_cell == NULL )
1063 intf_ErrMsg( "ifo error: out of memory in Read Title" );
1067 ReadBits( p_ifo, pi_buffer, &p_current, p_title->chapter_map.pi_start_cell,
1068 p_title->i_chapter_nb );
1072 p_title->chapter_map.pi_start_cell = NULL;
1075 /* parsing of cell_play_t */
1076 if( p_title->i_cell_play_start_byte )
1078 p_current = FillBuffer( p_ifo, pi_buffer,
1079 i_start + p_title->i_cell_play_start_byte );
1081 p_title->p_cell_play = malloc( p_title->i_cell_nb
1082 *sizeof(cell_play_t) );
1084 if( p_title->p_cell_play == NULL )
1086 intf_ErrMsg( "ifo error: out of memory in ReadTitle" );
1090 for( i = 0 ; i < p_title->i_cell_nb ; i++ )
1092 p_title->p_cell_play[i].i_category = ReadWord( p_ifo, pi_buffer, &p_current );
1093 p_title->p_cell_play[i].i_still_time = ReadByte( p_ifo, pi_buffer, &p_current );
1094 p_title->p_cell_play[i].i_command_nb = ReadByte( p_ifo, pi_buffer, &p_current );
1095 p_title->p_cell_play[i].i_play_time = ReadDouble( p_ifo, pi_buffer, &p_current );
1096 p_title->p_cell_play[i].i_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
1097 p_title->p_cell_play[i].i_first_ilvu_vobu_esector =
1098 ReadDouble( p_ifo, pi_buffer, &p_current );
1099 p_title->p_cell_play[i].i_last_vobu_start_sector =
1100 ReadDouble( p_ifo, pi_buffer, &p_current );
1101 p_title->p_cell_play[i].i_end_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
1105 /* Parsing of cell_pos_t */
1106 if( p_title->i_cell_pos_start_byte )
1108 p_current = FillBuffer( p_ifo, pi_buffer,
1109 i_start + p_title->i_cell_pos_start_byte );
1111 p_title->p_cell_pos = malloc( p_title->i_cell_nb
1112 *sizeof(cell_pos_t) );
1114 if( p_title->p_cell_pos == NULL )
1116 intf_ErrMsg( "ifo error: out of memory" );
1120 for( i = 0 ; i < p_title->i_cell_nb ; i++ )
1122 p_title->p_cell_pos[i].i_vob_id = ReadWord( p_ifo, pi_buffer, &p_current );
1123 DumpBits( p_ifo, pi_buffer, &p_current, 1 );
1124 p_title->p_cell_pos[i].i_cell_id = ReadByte( p_ifo, pi_buffer, &p_current );
1131 /*****************************************************************************
1132 * FreeTitle: frees alla structure allocated by a call to ReadTitle
1133 *****************************************************************************/
1134 static int FreeTitle( title_t * p_title )
1136 if( p_title->i_command_start_byte )
1138 if( p_title->command.i_pre_command_nb )
1140 free( p_title->command.p_pre_command );
1143 if( p_title->command.i_post_command_nb )
1145 free( p_title->command.p_post_command );
1148 if( p_title->command.i_cell_command_nb )
1150 free( p_title->command.p_cell_command );
1153 if( p_title->i_chapter_map_start_byte )
1155 free( p_title->chapter_map.pi_start_cell );
1158 if( p_title->i_cell_play_start_byte )
1160 free( p_title->p_cell_play );
1163 if( p_title->i_cell_pos_start_byte )
1165 free( p_title->p_cell_pos );
1172 /*****************************************************************************
1173 * ReadUnitInf : Fills Menu Language Unit Table/ PGC Info Table
1174 *****************************************************************************/
1175 static int ReadUnitInf( ifo_t * p_ifo, unit_inf_t * p_unit_inf, off_t i_pos )
1177 u8 pi_buffer[DVD_LB_SIZE];
1182 p_current = FillBuffer( p_ifo, pi_buffer, i_pos );
1184 i_start = p_ifo->i_pos;
1185 //fprintf( stderr, "Unit\n" );
1187 p_unit_inf->i_title_nb = ReadWord( p_ifo, pi_buffer, &p_current );
1188 DumpBits( p_ifo, pi_buffer, &p_current, 2 );
1189 p_unit_inf->i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
1191 p_unit_inf->p_title =
1192 malloc( p_unit_inf->i_title_nb *sizeof(unit_title_t) );
1193 if( p_unit_inf->p_title == NULL )
1195 intf_ErrMsg( "ifo error: out of memory in ReadUnit" );
1199 for( i = 0 ; i < p_unit_inf->i_title_nb ; i++ )
1201 p_unit_inf->p_title[i].i_category_mask = ReadByte( p_ifo, pi_buffer, &p_current );
1202 p_unit_inf->p_title[i].i_category = ReadByte( p_ifo, pi_buffer, &p_current );
1203 p_unit_inf->p_title[i].i_parental_mask = ReadWord( p_ifo, pi_buffer, &p_current );
1204 p_unit_inf->p_title[i].i_title_start_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
1207 for( i = 0 ; i < p_unit_inf->i_title_nb ; i++ )
1209 //fprintf( stderr, "Unit: PGC %d @ %lld\n", i, p_ifo->i_pos );
1210 ReadTitle( p_ifo, &p_unit_inf->p_title[i].title, i_start +
1211 p_unit_inf->p_title[i].i_title_start_byte );
1217 /*****************************************************************************
1218 * FreeUnitInf : frees a structure allocated by ReadUnit
1219 *****************************************************************************/
1220 static int FreeUnitInf( unit_inf_t * p_unit_inf )
1222 if( p_unit_inf->p_title != NULL )
1224 free( p_unit_inf->p_title );
1231 /*****************************************************************************
1232 * ReadTitleUnit: Fills the Title Unit structure.
1233 *****************************************************************************/
1234 static int ReadTitleUnit( ifo_t * p_ifo, title_unit_t * p_title_unit,
1237 u8 pi_buffer[DVD_LB_SIZE];
1242 p_current = FillBuffer( p_ifo, pi_buffer, i_pos );
1243 i_start = p_ifo->i_pos;
1244 //fprintf( stderr, "Unit Table\n" );
1246 p_title_unit->i_unit_nb = ReadWord( p_ifo, pi_buffer, &p_current );
1247 DumpBits( p_ifo, pi_buffer, &p_current, 2 );
1248 p_title_unit->i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
1250 //fprintf(stderr, "Unit: nb %d end %d\n", p_title_unit->i_unit_nb, p_title_unit->i_end_byte );
1252 p_title_unit->p_unit = malloc( p_title_unit->i_unit_nb *sizeof(unit_t) );
1253 if( p_title_unit->p_unit == NULL )
1255 intf_ErrMsg( "ifo error: out of memory in ReadTitleUnit" );
1259 for( i = 0 ; i < p_title_unit->i_unit_nb ; i++ )
1261 ReadBits( p_ifo, pi_buffer, &p_current, p_title_unit->p_unit[i].ps_lang_code, 2 );
1262 DumpBits( p_ifo, pi_buffer, &p_current, 1 );
1263 p_title_unit->p_unit[i].i_existence_mask = ReadByte( p_ifo, pi_buffer, &p_current );
1264 p_title_unit->p_unit[i].i_unit_inf_start_byte =
1265 ReadDouble( p_ifo, pi_buffer, &p_current );
1268 p_title_unit->p_unit_inf =
1269 malloc( p_title_unit->i_unit_nb *sizeof(unit_inf_t) );
1270 if( p_title_unit->p_unit_inf == NULL )
1272 intf_ErrMsg( "ifo error: out of memory in ReadTitleUnit" );
1276 for( i = 0 ; i < p_title_unit->i_unit_nb ; i++ )
1278 ReadUnitInf( p_ifo, &p_title_unit->p_unit_inf[i], i_start +
1279 p_title_unit->p_unit[i].i_unit_inf_start_byte );
1285 /*****************************************************************************
1286 * FreeTitleUnit: frees a structure allocateed by ReadTitleUnit
1287 *****************************************************************************/
1288 static int FreeTitleUnit( title_unit_t * p_title_unit )
1292 if( p_title_unit->p_unit_inf != NULL )
1294 for( i = 0 ; i < p_title_unit->i_unit_nb ; i++ )
1296 FreeUnitInf( &p_title_unit->p_unit_inf[i] );
1299 free( p_title_unit->p_unit_inf );
1305 /*****************************************************************************
1306 * ReadCellInf : Fills the Cell Information structure.
1307 *****************************************************************************/
1308 static int ReadCellInf( ifo_t * p_ifo, cell_inf_t * p_cell_inf, off_t i_pos )
1310 u8 pi_buffer[DVD_LB_SIZE];
1315 p_current = FillBuffer( p_ifo, pi_buffer, i_pos );
1316 i_start = p_ifo->i_pos;
1317 //fprintf( stderr, "CELL ADD\n" );
1319 p_cell_inf->i_vob_nb = ReadWord( p_ifo, pi_buffer, &p_current );
1320 DumpBits( p_ifo, pi_buffer, &p_current, 2 );
1321 p_cell_inf->i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
1323 p_cell_inf->i_cell_nb = (p_cell_inf->i_end_byte - 8) / sizeof(cell_map_t);
1325 //fprintf( stderr, "Cell inf: vob %d end %d cell %d\n", p_cell_inf->i_vob_nb, p_cell_inf->i_end_byte, p_cell_inf->i_cell_nb );
1327 p_cell_inf->p_cell_map =
1328 malloc( p_cell_inf->i_cell_nb *sizeof(cell_map_t) );
1329 if( p_cell_inf->p_cell_map == NULL )
1331 intf_ErrMsg( "ifo error: out of memory in ReadCellInf" );
1335 for( i = 0 ; i < p_cell_inf->i_cell_nb ; i++ )
1337 p_cell_inf->p_cell_map[i].i_vob_id = ReadWord( p_ifo, pi_buffer, &p_current );
1338 p_cell_inf->p_cell_map[i].i_cell_id = ReadByte( p_ifo, pi_buffer, &p_current );
1339 DumpBits( p_ifo, pi_buffer, &p_current, 1 );
1340 p_cell_inf->p_cell_map[i].i_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
1341 p_cell_inf->p_cell_map[i].i_end_sector = ReadDouble( p_ifo, pi_buffer, &p_current );
1347 /*****************************************************************************
1348 * FreeCellInf : frees structures allocated by ReadCellInf
1349 *****************************************************************************/
1350 static int FreeCellInf( cell_inf_t * p_cell_inf )
1352 free( p_cell_inf->p_cell_map );
1357 /*****************************************************************************
1358 * ReadVobuMap : Fills the VOBU Map structure.
1359 *****************************************************************************/
1360 static int ReadVobuMap( ifo_t * p_ifo, vobu_map_t * p_vobu_map, off_t i_pos )
1362 u8 pi_buffer[DVD_LB_SIZE];
1367 p_current = FillBuffer( p_ifo, pi_buffer, i_pos );
1368 i_start = p_ifo->i_pos;
1369 //fprintf( stderr, "VOBU ADMAP\n" );
1371 p_vobu_map->i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current );
1372 i_max = ( i_start + p_vobu_map->i_end_byte + 1 - p_ifo->i_pos )
1375 p_vobu_map->pi_vobu_start_sector = malloc( i_max *sizeof(u32) );
1376 if( p_vobu_map->pi_vobu_start_sector == NULL )
1378 intf_ErrMsg( "ifo error: out of memory in ReadVobuMap" );
1382 for( i = 0 ; i < i_max ; i++ )
1384 p_vobu_map->pi_vobu_start_sector[i] = ReadDouble( p_ifo, pi_buffer, &p_current );
1390 /*****************************************************************************
1391 * FreeVobuMap: frees structures allocated by ReadVobuMap
1392 *****************************************************************************/
1393 static int FreeVobuMap( vobu_map_t * p_vobu_map )
1395 free( p_vobu_map->pi_vobu_start_sector );
1401 * IFO virtual machine : a set of commands that give the
1402 * interactive behaviour of the dvd
1406 #define OP_VAL_16(i) (ntoh16( com.data.pi_16[i]))
1407 #define OP_VAL_8(i) ((com.data.pi_8[i]))
1409 static char ifo_reg[][80]=
1411 "Menu_Language_Code",
1413 "SubPicture_Stream_#",
1419 "Highlighted_Button_#",
1422 "Karaoke_audio_mixing_mode",
1423 "Parental_mgmt_country_code",
1427 "Audio_language_code_setting",
1428 "Audio_language_extension_code",
1429 "SPU_language_code_setting",
1430 "SPU_language_extension_code",
1431 "?Player_Regional_Code",
1437 static char * IfoMath( char val )
1439 static char math_op[][10] =
1459 return (char *) math_op[val & 0x0f];
1463 char ifo_cmp[][10] =
1475 char ifo_parental[][10] =
1487 char ifo_menu_id[][80] =
1499 char * IfoMenuName( char index )
1501 return ifo_menu_id[index&0x07];
1504 static void IfoRegister( u16 i_data, u8 i_direct)
1508 if( 0/*isalpha( i_data >> 8 & 0xff )*/ )
1510 printf("'%c%c'", i_data>>8&0xff, i_data&0xff);
1514 printf("0x%02x", i_data);
1529 printf("s[%s]", ifo_reg[i_data]);
1542 printf("r[0x%02x]", i_data);
1548 static void IfoAdvanced( u8 *pi_code )
1550 u8 i_cmd = pi_code[0];
1556 printf( " Highlight button %d; ", pi_code[1]>>2 );
1561 printf( " Illegal " );
1566 printf( "ReSuME %d", pi_code[7] );
1568 else if( ( i_cmd & 0x06) == 0x02 )
1570 printf ("Link to %s cell ", ( i_cmd & 0x01 ) ? "prev" : "next");
1574 printf( "advanced (0x%02x) ", i_cmd );
1579 static void IfoJmp( ifo_command_t com )
1584 switch( com.i_sub_cmd )
1590 printf( "VTS 0x%02x", OP_VAL_8(3) );
1593 printf( "This VTS Title 0x%02x", OP_VAL_8(3) );
1596 printf( "This VTS Title 0x%02x Part 0x%04x",
1598 OP_VAL_8(0)<<8|OP_VAL_8(1));
1602 printf ("in SystemSpace ");
1603 switch (OP_VAL_8(3)>>4) {
1605 printf ("to play first PGC");
1608 printf ("to menu \"%s\"", decode_menuname (OP_VAL_8(3)));
1612 printf ("to VTS 0x%02x and TTN 0x%02x", OP_VAL_8(1), OP_VAL_8(2));
1615 printf ("to VMGM PGC number 0x%02x", OP_VAL_8(0)<<8 | OP_VAL_8(1));
1618 printf ("vts 0x%02x lu 0x%02x menu \"%s\"", OP_VAL_8(2), OP_VAL_8(1), decode_menuname (OP_VAL_8(3)));
1621 switch( OP_VAL_8(3)>>6 )
1624 printf( "to play first PGC" );
1627 printf( "to VMG title menu (?)" );
1630 printf( "vts 0x%02x lu 0x%02x menu \"%s\"",
1633 IfoMenuName( OP_VAL_8(3)&0xF ) );
1636 printf( "vmg pgc 0x%04x (?)", ( OP_VAL_8(0)<<8) | OP_VAL_8(1) );
1643 switch(OP_VAL_8(3)>>4) {
1645 printf ("system first pgc");
1648 printf ("system title menu");
1651 printf ("system menu \"%s\"", decode_menuname (OP_VAL_8(3)));
1654 printf ("system vmg pgc %02x ????", OP_VAL_8(0)<<8|OP_VAL_8(1));
1657 printf ("system lu 0x%02x menu \"%s\"", OP_VAL_8(2), decode_menuname (OP_VAL_8(3)));
1660 printf ("system vmg pgc 0x%02x", OP_VAL_8(0)<<8|OP_VAL_8(1));
1664 // OP_VAL_8(2) is number of cell
1665 // it is processed BEFORE switch
1666 // under some conditions, it is ignored
1667 // I don't understand exactly what it means
1668 printf( " ( spec cell 0x%02X ) ", OP_VAL_8(2) );
1670 switch( OP_VAL_8(3)>>6 )
1673 printf( "to FP PGC" );
1676 printf( "to VMG root menu (?)" );
1679 printf( "to VTS menu \"%s\" (?)",
1680 IfoMenuName(OP_VAL_8(3)&0xF) );
1683 printf( "vmg pgc 0x%02x (?)", (OP_VAL_8(0)<<8)|OP_VAL_8(1) );
1691 static void IfoLnk( ifo_command_t com )
1693 u16 i_button=OP_VAL_8(4)>>2;
1697 switch( com.i_sub_cmd )
1700 IfoAdvanced( &OP_VAL_8(4) );
1704 printf( "PGC 0x%02x", OP_VAL_16(2) );
1708 printf( "PTT 0x%02x", OP_VAL_16(2) );
1712 printf( "Program 0x%02x this PGC", OP_VAL_8(5) );
1716 printf( "Cell 0x%02x this PGC", OP_VAL_8(5) );
1724 printf( ", Highlight 0x%02x", OP_VAL_8(4)>>2 );
1729 void IfoSetSystem( ifo_command_t com )
1736 for( i=1; i<=3; i++ )
1738 if( OP_VAL_8(i)&0x80 )
1742 printf ("s[%s] = 0x%02x;", ifo_reg[i], OP_VAL_8(i)&0xf);
1746 printf ("s[%s] = r[0x%02x];", ifo_reg[i], OP_VAL_8(i)&0xf);
1752 if(OP_VAL_8(1]&0x80)
1753 printf ("s[%s] = 0x%02x;", reg_name[1], OP_VAL_8(1]&0xf);
1754 if(OP_VAL_8(2)&0x80)
1755 //DENT: lwhat about 0x7f here ???
1756 printf ("s[%s] = 0x%02x;", reg_name[2], OP_VAL_8(2)&0x7f);
1757 if(OP_VAL_8(3)&0x80)
1758 printf ("s[%s] = 0x%02x;", reg_name[3], OP_VAL_8(3)&0xf);
1760 if(OP_VAL_8(1)&0x80)
1761 printf ("s[%s] = r[0x%02x];", reg_name[1], OP_VAL_8(1)&0xf);
1762 if(OP_VAL_8(2)&0x80)
1763 printf ("s[%s] = r[0x%02x];", reg_name[2], OP_VAL_8(2)&0xf);
1764 if(OP_VAL_8(3)&0x80)
1765 printf ("s[%s] = r[0x%02x];", reg_name[3], OP_VAL_8(3)&0xf);
1773 printf( "s[%s] = 0x%02x", ifo_reg[9], OP_VAL_16(0) );
1777 printf( "s[%s] = r[0x%02x]", ifo_reg[9], OP_VAL_8(1)&0x0f );
1780 printf( "s[%s] = (s[%s]&0x7FFF)|0x%02x",
1781 ifo_reg[10], ifo_reg[10], OP_VAL_16(1)&0x8000);
1786 printf( "r[0x%02x] = 0x%02x", OP_VAL_8(3)&0x0f, OP_VAL_16(0) );
1790 printf ("r[r[0x%02x]] = r[0x%02x]",
1791 OP_VAL_8(3)&0x0f, OP_VAL_8(1)&0x0f);
1795 //actually only bits 00011100 00011100 are set
1798 printf ("s[%s] = 0x%02x", ifo_reg[11], OP_VAL_16(1));
1802 printf ("s[%s] = r[0x%02x]", ifo_reg[11], OP_VAL_8(3)&0x0f );
1807 //s[%s]=(r[%s]&0x3FF) | (0x%02x << 0xA);
1808 //but it is way too ugly
1811 printf( "s[%s] = 0x%02x", ifo_reg[8], OP_VAL_8(2)>>2 );
1815 printf( "s[%s] = r[0x%02x]", ifo_reg[8], OP_VAL_8(3)&0x0f );
1823 static void IfoSet( ifo_command_t com )
1825 IfoRegister( OP_VAL_16(0), 0 );
1826 printf( " %s ", IfoMath( com.i_cmd ) );
1827 IfoRegister( OP_VAL_16(1), com.i_direct );
1830 /*****************************************************************************
1831 * CommandRead : translates the command strings in ifo into command
1833 *****************************************************************************/
1834 void CommandRead( ifo_command_t com )
1836 u8* pi_code = (u8*)(&com);
1838 switch( com.i_type )
1851 printf ("if (r[0x%02x] %s ", OP_VAL_8(1)&0x0f,
1852 ifo_cmp[com.i_cmp]);
1853 IfoRegister (OP_VAL_16(1), com.i_dir_cmp);
1858 switch( com.i_sub_cmd )
1861 printf( "goto Line 0x%02x", OP_VAL_16(2) );
1865 printf( "stop VM" );
1869 printf( "Set Parental Level To %s and goto Line 0x%02x",
1870 ifo_parental[OP_VAL_8(4)&0x7],
1875 printf( "Illegal" );
1894 printf( "if (r[0x%02x] %s ", OP_VAL_8(4)&0x0f,
1895 ifo_cmp[com.i_cmp] );
1896 IfoRegister( OP_VAL_8(5), 0 );
1907 printf( "if (r[0x%02x] %s ", OP_VAL_8(1)&0x0f,
1908 ifo_cmp[com.i_cmp] );
1909 IfoRegister( OP_VAL_16(1), com.i_dir_cmp );
1923 IfoSetSystem( com );
1925 else if( com.i_cmp && !com.i_sub_cmd )
1927 printf ("if (r[0x%02x] %s ", OP_VAL_8(4)&0x0f, ifo_cmp[com.i_cmp]);
1928 IfoRegister( OP_VAL_8(5), 0 );
1930 IfoSetSystem( com );
1932 else if( !com.i_cmp && com.i_sub_cmd )
1935 IfoSetSystem( com );
1951 else if( com.i_cmp && !com.i_sub_cmd )
1953 printf ("if (r[0x%02x] %s ", OP_VAL_8(0)&0x0f, ifo_cmp[com.i_cmp]);
1954 IfoRegister( OP_VAL_16(2), com.i_dir_cmp );
1958 else if( !com.i_cmp && com.i_sub_cmd )
1972 * math command on r[opcode[1]] and
1973 * direct?be2me_16(OP_VAL_8(0)):reg[OP_VAL_8(1)] is executed
1974 * ( unless command is swap; then r[opcode[1]] and r[OP_VAL_8(1)]
1976 * boolean operation cmp on r[opcode[1]] and
1977 * dir_cmp?be2me_16(OP_VAL_8(1)[1]):reg[OP_VAL_8(3)] is executed
1978 * on true result, buttons(c[6], c[7]) is called
1979 * problem is 'what is buttons()'
1982 printf( "r[0x%X] ", pi_code[1] );
1983 printf( " %s ", IfoMath( com.i_cmd ) );
1984 if( com.i_cmd == 2 )
1986 printf( "r[0x%X] ", OP_VAL_8(1) );
1990 IfoRegister( OP_VAL_16(0), com.i_direct );
1994 printf( "if ( r[%d] %s ", pi_code[1], ifo_cmp[com.i_cmp] );
1995 IfoRegister( OP_VAL_8(1), com.i_dir_cmp );
1996 printf( " ) then {" );
1997 IfoAdvanced( &OP_VAL_8(4) );
2002 * opposite to case 4: boolean, math and buttons.
2008 if( !com.i_direct && com.i_dir_cmp )
2010 printf( "0x%X", OP_VAL_16(1) );
2014 IfoRegister( OP_VAL_8(3), 0 );
2015 if( OP_VAL_8(3)&0x80 )
2017 printf( "s[%s]", ifo_reg[OP_VAL_8(3)&0x1F] );
2021 printf( "r[0x%X]", OP_VAL_8(3)&0x1F);
2022 // 0x1F is either not a mistake,
2023 // or Microsoft programmer's mistake!!!
2027 printf( " %s r[0x%X] ", ifo_cmp[com.i_cmp],
2028 com.i_direct ? OP_VAL_8(2) : OP_VAL_8(1) );
2029 printf( " ) then {" );
2030 printf( "r[0x%X] ", pi_code[1] & 0xF );
2031 printf( " %s ", IfoMath( com.i_cmd ) );
2033 if( com.i_cmd == 0x02 ) // swap
2035 printf("r[0x%X] ", OP_VAL_8(0)&0x1F);
2041 printf( "0x%X", OP_VAL_16(0) );
2045 if( OP_VAL_8(0) & 0x80 )
2047 printf("s[%s]", ifo_reg[OP_VAL_8(0) & 0x1F] );
2051 printf("r[0x%X]", OP_VAL_8(0) & 0x1F );
2057 IfoAdvanced( &OP_VAL_8(4) );
2063 printf( "Unknown Command\n" );
2070 /*****************************************************************************
2071 * CommandPrint : print in clear text (I hope so !) what a command does
2072 *****************************************************************************/
2073 void CommandPrint( ifo_t ifo )