X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=plugins%2Fdvd%2Fdvd_ifo.c;h=97524b9bac455327ffe09f8f9d265685f4393ce8;hb=5427a369c4a6ef96ab69119879e32360b301f737;hp=a19970bb2c5b91cabca379dc923d4bfcd0452198;hpb=16247a7506c02836d0e33ba4633f8e02bb5ea81a;p=vlc diff --git a/plugins/dvd/dvd_ifo.c b/plugins/dvd/dvd_ifo.c index a19970bb2c..97524b9bac 100644 --- a/plugins/dvd/dvd_ifo.c +++ b/plugins/dvd/dvd_ifo.c @@ -2,7 +2,7 @@ * dvd_ifo.c: Functions for ifo parsing ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: dvd_ifo.c,v 1.8 2001/02/15 21:03:27 stef Exp $ + * $Id: dvd_ifo.c,v 1.22 2001/04/15 21:17:50 stef Exp $ * * Author: Stéphane Borel * @@ -29,7 +29,11 @@ /***************************************************************************** * Preamble *****************************************************************************/ +#include "defs.h" +#include "config.h" + #include +#include #include #include #include @@ -38,1102 +42,1368 @@ #include "intf_msg.h" #include "dvd_ifo.h" +#include "dvd_udf.h" +#include "dvd_css.h" #include "input_dvd.h" -void CommandRead( ifo_command_t ); - /* - * IFO Management. + * Local prototypes */ +void CommandRead ( command_desc_t ); +static int ReadTitle ( ifo_t * , title_t *, off_t ); +static int FreeTitle ( title_t * ); +static int ReadUnitInf ( ifo_t * , unit_inf_t *, off_t ); +static int FreeUnitInf ( unit_inf_t * ); +static int ReadTitleUnit ( ifo_t * , title_unit_t *, off_t ); +static int FreeTitleUnit ( title_unit_t * ); +static int ReadVobuMap ( ifo_t * , vobu_map_t *, off_t ); +static int FreeVobuMap ( vobu_map_t * ); +static int ReadCellInf ( ifo_t * , cell_inf_t *, off_t ); +static int FreeCellInf ( cell_inf_t * ); +static int FreeTitleSet ( vts_t * ); /***************************************************************************** - * IfoFindVMG : When reading directly on a device, finds the offset to the - * beginning of video_ts.ifo. + * ReadByte and so *****************************************************************************/ -static int IfoFindVMG( ifo_t* p_ifo ) +static __inline__ u8* FillBuffer( ifo_t* p_ifo, u8* pi_buffer, off_t i_pos ) { - char psz_ifo_start[12] = "DVDVIDEO-VMG"; - char psz_test[12]; + memset( pi_buffer, 0, DVD_LB_SIZE ); + p_ifo->i_pos = lseek( p_ifo->i_fd, i_pos, SEEK_SET ); + read( p_ifo->i_fd, pi_buffer, DVD_LB_SIZE ); + + return pi_buffer; +} - read( p_ifo->i_fd, psz_test, 12 ); +static __inline__ u8 ReadByte( ifo_t * p_ifo, u8* pi_buffer, u8** pp_current ) +{ + u8 i_ret; - while( strncmp( psz_test, psz_ifo_start, 12 ) != 0 ) + if( *pp_current > pi_buffer + DVD_LB_SIZE ) { - /* The start of ifo file is on a sector boundary */ - p_ifo->i_pos = lseek( p_ifo->i_fd, - p_ifo->i_pos + DVD_LB_SIZE, - SEEK_SET ); - read( p_ifo->i_fd, psz_test, 12 ); + *pp_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_pos + DVD_LB_SIZE ); } - p_ifo->i_off = p_ifo->i_pos; -fprintf( stderr, "VMG Off : %lld\n", (long long)(p_ifo->i_off) ); + i_ret = *(*pp_current)++; - return 0; + return i_ret; } -/***************************************************************************** - * IfoFindVTS : beginning of vts_*.ifo. - *****************************************************************************/ -static int IfoFindVTS( ifo_t* p_ifo ) +static __inline__ u16 ReadWord( ifo_t* p_ifo, u8* pi_buffer, u8** pp_current ) { - char psz_ifo_start[12] = "DVDVIDEO-VTS"; - char psz_test[12]; - - read( p_ifo->i_fd, psz_test, 12 ); + u16 i_ret; - while( strncmp( psz_test, psz_ifo_start, 12 ) != 0 ) + if( *pp_current > pi_buffer + DVD_LB_SIZE - 2 ) { - /* The start of ifo file is on a sector boundary */ - p_ifo->i_pos = lseek( p_ifo->i_fd, - p_ifo->i_pos + DVD_LB_SIZE, - SEEK_SET ); - read( p_ifo->i_fd, psz_test, 12 ); + *pp_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_pos + DVD_LB_SIZE ); } - p_ifo->i_off = p_ifo->i_pos; -fprintf( stderr, "VTS Off : %lld\n", (long long)(p_ifo->i_off) ); + i_ret = U16_AT(*pp_current); + (*pp_current) += 2; - return 0; + return i_ret; } -/***************************************************************************** - * IfoInit : Creates an ifo structure and prepares for parsing directly - * on DVD device. - *****************************************************************************/ -ifo_t IfoInit( int i_fd ) +static __inline__ u32 ReadDouble( ifo_t * p_ifo, u8* pi_buffer, + u8** pp_current ) { - ifo_t ifo; - - /* If we are here the dvd device has already been opened */ - ifo.i_fd = i_fd; - /* No data at the beginning of the disk - * 512000 bytes is just another value :) */ - ifo.i_pos = lseek( ifo.i_fd, 250 *DVD_LB_SIZE, SEEK_SET ); - /* FIXME : use udf filesystem to find the beginning of the file */ - IfoFindVMG( &ifo ); - - return ifo; + u32 i_ret; + + if( *pp_current > pi_buffer + DVD_LB_SIZE - 4 ) + { + *pp_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_pos + DVD_LB_SIZE); +// intf_WarnMsg( 1, "new buffer in double @ %lld", p_ifo->i_pos ); + } + + i_ret = U32_AT(*pp_current); + (*pp_current) += 4; + + return i_ret; } -/***************************************************************************** - * IfoEnd : Frees all the memory allocated to ifo structures - *****************************************************************************/ -void IfoEnd( ifo_t* p_ifo ) +static __inline__ u64 ReadQuad( ifo_t* p_ifo, u8* pi_buffer, u8** pp_current ) { - int i,j; + u64 i_ret; - /* Free structures from video title sets */ - for( j=0 ; jvmg.mat.i_tts_nb ; j++ ) + if( *pp_current > pi_buffer + DVD_LB_SIZE - 8 ) { - free( p_ifo->p_vts[j].vobu_admap.pi_vobu_ssector ); - free( p_ifo->p_vts[j].c_adt.p_cell_inf ); - free( p_ifo->p_vts[j].m_vobu_admap.pi_vobu_ssector ); - free( p_ifo->p_vts[j].m_c_adt.p_cell_inf ); - for( i=0 ; ip_vts[j].tmap_ti.i_nb ; i++ ) - { - free( p_ifo->p_vts[j].tmap_ti.p_tmap[i].pi_sector ); - } - free( p_ifo->p_vts[j].tmap_ti.pi_sbyte ); - free( p_ifo->p_vts[j].tmap_ti.p_tmap ); - free( p_ifo->p_vts[j].pgci_ti.p_srp ); - for( i=0 ; ip_vts[j].pgci_ut.i_lu_nb ; i++ ) - { - free( p_ifo->p_vts[j].pgci_ut.p_pgci_inf[i].p_srp ); - } - free( p_ifo->p_vts[j].pgci_ut.p_pgci_inf ); - free( p_ifo->p_vts[j].pgci_ut.p_lu ); + *pp_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_pos + DVD_LB_SIZE ); } - free( p_ifo->p_vts ); + i_ret = U64_AT(*pp_current); + (*pp_current) += 8; - /* Free structures from video manager */ - free( p_ifo->vmg.vobu_admap.pi_vobu_ssector ); - free( p_ifo->vmg.c_adt.p_cell_inf ); - for( i=0 ; ivmg.pgci_ut.i_lu_nb ; i++ ) + return i_ret; +} + +static __inline__ void ReadBits( ifo_t* p_ifo, u8* pi_buffer, u8** pp_current, + u8* pi_dest, int i_nb ) +{ + if( *pp_current > pi_buffer + DVD_LB_SIZE - i_nb ) { - free( p_ifo->vmg.pgci_ut.p_pgci_inf[i].p_srp ); + *pp_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_pos + DVD_LB_SIZE ); } - free( p_ifo->vmg.pgci_ut.p_pgci_inf ); - free( p_ifo->vmg.pgci_ut.p_lu ); - for( i=1 ; i<=8 ; i++ ) + + memcpy( pi_dest, *pp_current, i_nb ); + *pp_current += i_nb; + + return; +} + +static __inline__ void DumpBits( ifo_t* p_ifo, u8* pi_buffer, + u8** pp_current, int i_nb ) +{ + if( *pp_current > pi_buffer + DVD_LB_SIZE - i_nb ) { - free( p_ifo->vmg.ptl_mait.p_ptl_mask->ppi_ptl_mask[i] ); + *pp_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_pos + DVD_LB_SIZE ); } - free( p_ifo->vmg.ptl_mait.p_ptl_desc ); - free( p_ifo->vmg.ptl_mait.p_ptl_mask ); - free( p_ifo->vmg.vts_atrt.pi_vts_atrt_sbyte ); - free( p_ifo->vmg.vts_atrt.p_vts_atrt ); - free( p_ifo->vmg.pgc.p_cell_pos_inf ); - free( p_ifo->vmg.pgc.p_cell_play_inf ); - free( p_ifo->vmg.pgc.prg_map.pi_entry_cell ); - free( p_ifo->vmg.pgc.com_tab.p_cell_com ); - free( p_ifo->vmg.pgc.com_tab.p_post_com ); - free( p_ifo->vmg.pgc.com_tab.p_pre_com ); + + *pp_current += i_nb; return; } /* - * Macros to process ifo files + * IFO Management. */ - -#define GET( p_field , i_len ) \ - { \ - read( p_ifo->i_fd , (p_field) , (i_len) ); \ -/*fprintf(stderr, "Pos : %lld Val : %llx\n", \ - (long long)(p_ifo->i_pos - i_start), \ - (long long)*(p_field) ); */ \ - p_ifo->i_pos += i_len; \ - } - -#define GETC( p_field ) \ - { \ - read( p_ifo->i_fd , (p_field) , 1 ); \ -/*fprintf(stderr, "Pos : %lld Value : %d\n", \ - (long long)(p_ifo->i_pos - i_start), \ - *(p_field) );*/ \ - p_ifo->i_pos += 1; \ - } - -#define GETS( p_field ) \ - { \ - read( p_ifo->i_fd , (p_field) , 2 ); \ - *(p_field) = ntohs( *(p_field) ); \ -/*fprintf(stderr, "Pos : %lld Value : %d\n", \ - (long long)(p_ifo->i_pos - i_start), \ - *(p_field) );*/ \ - p_ifo->i_pos += 2; \ - } - -#define GETL( p_field ) \ - { \ - read( p_ifo->i_fd , (p_field) , 4 ); \ - *(p_field) = ntohl( *(p_field) ); \ -/*fprintf(stderr, "Pos : %lld Value : %d\n", \ - (long long)(p_ifo->i_pos - i_start), \ - *(p_field) );*/ \ - p_ifo->i_pos += 4; \ - } - -#define GETLL( p_field ) \ - { \ - read( p_ifo->i_fd , (p_field) , 8 ); \ - *(p_field) = ntoh64( *(p_field) ); \ -/*fprintf(stderr, "Pos : %lld Value : %lld\n", \ - (long long)(p_ifo->i_pos - i_start), \ - *(p_field) );*/ \ - p_ifo->i_pos += 8; \ - } - -#define FLUSH( i_len ) \ - { \ -/*fprintf(stderr, "Pos : %lld\n", (long long)(p_ifo->i_pos - i_start));*/ \ - p_ifo->i_pos = lseek( p_ifo->i_fd , \ - p_ifo->i_pos + (i_len), SEEK_SET ); \ +/***************************************************************************** + * IfoCreate : Creates an ifo structure and prepares for parsing directly + * on DVD device + *****************************************************************************/ +int IfoCreate( thread_dvd_data_t * p_dvd ) +{ + p_dvd->p_ifo = malloc( sizeof(ifo_t) ); + if( p_dvd->p_ifo == NULL ) + { + intf_ErrMsg( "ifo error: unable to allocate memory. aborting" ); + return -1; } -/* - * Function common to Video Manager and Video Title set Processing - */ + /* if we are here the dvd device has already been opened */ + p_dvd->p_ifo->i_fd = p_dvd->i_fd; + + return 0; +} /***************************************************************************** - * ReadPGC : Fills the Program Chain structure. + * IfoInit : Reads information from the management table. *****************************************************************************/ -#define GETCOMMAND( p_com ) \ - { \ - read( p_ifo->i_fd , (p_com) , 8 ); \ -/*fprintf(stderr, "Pos : %lld Type : %d direct : %d cmd : %d dircmp : %d cmp : %d subcmd : %d v0 : %d v2 : %d v4 : %d\n", \ - (long long)(p_ifo->i_pos - i_start), \ - (int)((p_com)->i_type), \ - (int)((p_com)->i_direct), \ - (int)((p_com)->i_cmd), \ - (int)((p_com)->i_dir_cmp), \ - (int)((p_com)->i_cmp), \ - (int)((p_com)->i_sub_cmd), \ - (int)((p_com)->data.pi_16[0]), \ - (int)((p_com)->data.pi_16[1]), \ - (int)((p_com)->data.pi_16[2]));*/ \ -/* CommandRead( *(p_com) );*/ \ - p_ifo->i_pos += 8; \ - } - -static pgc_t ReadPGC( ifo_t* p_ifo ) +int IfoInit( ifo_t * p_ifo ) { - pgc_t pgc; - int i; - off_t i_start = p_ifo->i_pos; + u8 pi_buffer[DVD_LB_SIZE]; + u8* p_current; + u64 i_temp; + u32 i_lba; + int i, j, k; + off_t i_start; -//fprintf( stderr, "PGC\n" ); + /* find the start sector of video information on the dvd */ + i_lba = UDFFindFile( p_ifo->i_fd, "/VIDEO_TS/VIDEO_TS.IFO"); - FLUSH(2); - GETC( &pgc.i_prg_nb ); - GETC( &pgc.i_cell_nb ); - GETL( &pgc.i_play_time ); - GETL( &pgc.i_prohibited_user_op ); - for( i=0 ; i<8 ; i++ ) + p_ifo->i_off = (off_t)(i_lba) * DVD_LB_SIZE; + + p_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_off ); +//i_start = p_ifo->i_pos; + /* + * read the video manager information table + */ +#define manager_inf p_ifo->vmg.manager_inf +//fprintf( stderr, "VMGI\n" ); + + ReadBits( p_ifo, pi_buffer, &p_current, manager_inf.psz_id, 12 ); + manager_inf.psz_id[12] = '\0'; + manager_inf.i_vmg_end_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + DumpBits( p_ifo, pi_buffer, &p_current, 12 ); + manager_inf.i_vmg_inf_end_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + DumpBits( p_ifo, pi_buffer, &p_current, 1 ); + manager_inf.i_spec_ver = ReadByte( p_ifo, pi_buffer, &p_current ); + manager_inf.i_cat = ReadDouble( p_ifo, pi_buffer, &p_current ); + manager_inf.i_volume_nb = ReadWord( p_ifo, pi_buffer, &p_current ); + manager_inf.i_volume = ReadWord( p_ifo, pi_buffer, &p_current ); + manager_inf.i_disc_side = ReadByte( p_ifo, pi_buffer, &p_current ); + DumpBits( p_ifo, pi_buffer, &p_current, 19 ); + manager_inf.i_title_set_nb = ReadWord( p_ifo, pi_buffer, &p_current ); + ReadBits( p_ifo, pi_buffer, &p_current, manager_inf.ps_provider_id, 32 ); + manager_inf.i_pos_code = ReadQuad( p_ifo, pi_buffer, &p_current ); + DumpBits( p_ifo, pi_buffer, &p_current, 24 ); + manager_inf.i_vmg_inf_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current ); + manager_inf.i_first_play_title_start_byte = ReadDouble( p_ifo, pi_buffer, &p_current ); + DumpBits( p_ifo, pi_buffer, &p_current, 56 ); + manager_inf.i_vob_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + manager_inf.i_title_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + manager_inf.i_title_unit_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + manager_inf.i_parental_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + manager_inf.i_vts_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + manager_inf.i_text_data_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + manager_inf.i_cell_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + manager_inf.i_vobu_map_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + DumpBits( p_ifo, pi_buffer, &p_current, 32 ); +// GETS( &manager_inf.video_atrt ); +DumpBits( p_ifo, pi_buffer, &p_current, 2 ); + DumpBits( p_ifo, pi_buffer, &p_current, 1 ); + manager_inf.i_audio_nb = ReadByte( p_ifo, pi_buffer, &p_current ); +//fprintf( stderr, "vmgi audio nb : %d\n", manager_inf.i_audio_nb ); + for( i=0 ; i < 8 ; i++ ) { - GETS( &pgc.pi_audio_status[i] ); + i_temp = ReadQuad( p_ifo, pi_buffer, &p_current ); } - for( i=0 ; i<32 ; i++ ) + DumpBits( p_ifo, pi_buffer, &p_current, 17 ); + manager_inf.i_spu_nb = ReadByte( p_ifo, pi_buffer, &p_current ); +//fprintf( stderr, "vmgi subpic nb : %d\n", manager_inf.i_spu_nb ); + for( i=0 ; i < manager_inf.i_spu_nb ; i++ ) { - GETL( &pgc.pi_subpic_status[i] ); + ReadBits( p_ifo, pi_buffer, &p_current, (u8*)(&i_temp), 6 ); + /* FIXME : take care of endianness */ } - GETS( &pgc.i_next_pgc_nb ); - GETS( &pgc.i_prev_pgc_nb ); - GETS( &pgc.i_goup_pgc_nb ); - GETC( &pgc.i_still_time ); - GETC( &pgc.i_play_mode ); - for( i=0 ; i<16 ; i++ ) + + /* + * read first play title. + */ + if( ReadTitle( p_ifo, &p_ifo->vmg.title, p_ifo->i_off + + manager_inf.i_first_play_title_start_byte ) < 0 ) { - GETL( &pgc.pi_yuv_color[i] ); - /* FIXME : We have to erase the extra bit */ + return -1; } - GETS( &pgc.i_com_tab_sbyte ); - GETS( &pgc.i_prg_map_sbyte ); - GETS( &pgc.i_cell_play_inf_sbyte ); - GETS( &pgc.i_cell_pos_inf_sbyte ); - - /* Parsing of pgc_com_tab_t */ - if( pgc.i_com_tab_sbyte ) - { - p_ifo->i_pos = lseek( p_ifo->i_fd, i_start - + pgc.i_com_tab_sbyte, SEEK_SET ); - GETS( &pgc.com_tab.i_pre_com_nb ); - GETS( &pgc.com_tab.i_post_com_nb ); - GETS( &pgc.com_tab.i_cell_com_nb ); - FLUSH( 2 ); - if( pgc.com_tab.i_pre_com_nb ) - { - pgc.com_tab.p_pre_com = - malloc(pgc.com_tab.i_pre_com_nb *sizeof(ifo_command_t)); - if( pgc.com_tab.p_pre_com == NULL ) - { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return pgc; - } - for( i=0 ; ivmg.title_inf + if( manager_inf.i_title_inf_start_sector ) + { + p_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_off + + manager_inf.i_title_inf_start_sector *DVD_LB_SIZE ); +//fprintf( stderr, "title inf %lld\n", p_ifo->i_pos ); + + title_inf.i_title_nb = ReadWord( p_ifo, pi_buffer, &p_current ); +//fprintf( stderr, "title_inf: TTU nb %d\n", title_inf.i_title_nb ); + DumpBits( p_ifo, pi_buffer, &p_current, 2 ); + title_inf.i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current ); + + /* parsing of title attributes */ + title_inf.p_attr = malloc( title_inf.i_title_nb *sizeof(title_attr_t) ); + if( title_inf.p_attr == NULL ) + { + intf_ErrMsg( "ifo error: out of memory in IfoInit" ); + return -1; + } + + for( i = 0 ; i < title_inf.i_title_nb ; i++ ) + { + title_inf.p_attr[i].i_play_type = ReadByte( p_ifo, pi_buffer, &p_current ); + title_inf.p_attr[i].i_angle_nb = ReadByte( p_ifo, pi_buffer, &p_current ); + title_inf.p_attr[i].i_chapter_nb = ReadWord( p_ifo, pi_buffer, &p_current ); + title_inf.p_attr[i].i_parental_id = ReadWord( p_ifo, pi_buffer, &p_current ); + title_inf.p_attr[i].i_title_set_num = ReadByte( p_ifo, pi_buffer, &p_current ); + title_inf.p_attr[i].i_title_num = ReadByte( p_ifo, pi_buffer, &p_current ); + title_inf.p_attr[i].i_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); +//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 ); + } + } + else + { + title_inf.p_attr = NULL; + } +#undef title_inf + + /* + * fills the title unit structure. + */ + if( manager_inf.i_title_unit_start_sector ) + { + if( ReadTitleUnit( p_ifo, &p_ifo->vmg.title_unit, p_ifo->i_off + + manager_inf.i_title_unit_start_sector *DVD_LB_SIZE ) < 0 ) + { + return -1; + } + } + + /* + * fills the structure about parental information. + */ +#define parental p_ifo->vmg.parental_inf + if( manager_inf.i_parental_inf_start_sector ) + { + p_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_off + + manager_inf.i_parental_inf_start_sector *DVD_LB_SIZE ); + i_start = p_ifo->i_pos; + +//fprintf( stderr, "PTL\n" ); + + parental.i_country_nb = ReadWord( p_ifo, pi_buffer, &p_current ); + parental.i_vts_nb = ReadWord( p_ifo, pi_buffer, &p_current ); + parental.i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current ); + + parental.p_parental_desc = malloc( parental.i_country_nb * + sizeof(parental_desc_t) ); + if( parental.p_parental_desc == NULL ) + { + intf_ErrMsg( "ifo error: out of memory in IfoInit" ); + return -1; + } + + for( i = 0 ; i < parental.i_country_nb ; i++ ) + { + ReadBits( p_ifo, pi_buffer, &p_current, + parental.p_parental_desc[i].ps_country_code, 2 ); + DumpBits( p_ifo, pi_buffer, &p_current, 2 ); + parental.p_parental_desc[i].i_parental_mask_start_byte = + ReadWord( p_ifo, pi_buffer, &p_current ); + DumpBits( p_ifo, pi_buffer, &p_current, 2 ); + } + + parental.p_parental_mask = malloc( parental.i_country_nb * + sizeof(parental_mask_t) ); + if( parental.p_parental_mask == NULL ) + { + intf_ErrMsg( "ifo erro: out of memory in IfoInit" ); + return -1; + } + + for( i = 0 ; i < parental.i_country_nb ; i++ ) + { + p_current = FillBuffer( p_ifo, pi_buffer, i_start + + parental.p_parental_desc[i].i_parental_mask_start_byte ); + for( j = 0 ; j < 8 ; j++ ) { - GETCOMMAND( &pgc.com_tab.p_pre_com[i] ); + parental.p_parental_mask[i].ppi_mask[j] = + malloc( ( parental.i_vts_nb + 1 ) *sizeof(u16) ); + if( parental.p_parental_mask[i].ppi_mask[j] == NULL ) + { + intf_ErrMsg( "ifo error: out of memory in IfoInit" ); + return -1; + } + for( k = 0 ; k < parental.i_vts_nb + 1 ; k++ ) + { + parental.p_parental_mask[i].ppi_mask[j][k] = + ReadWord( p_ifo, pi_buffer, &p_current ); + } } } - if( pgc.com_tab.i_post_com_nb ) + } +#undef parental + + /* + * information and attributes about for each vts. + */ +#define vts_inf p_ifo->vmg.vts_inf + if( manager_inf.i_vts_inf_start_sector ) + { + u64 i_temp; + + p_current = FillBuffer( p_ifo, pi_buffer, p_ifo->i_off + + manager_inf.i_vts_inf_start_sector *DVD_LB_SIZE ); + i_start = p_ifo->i_pos; + +//fprintf( stderr, "VTS ATTR\n" ); + + vts_inf.i_vts_nb = ReadWord( p_ifo, pi_buffer, &p_current );; +//fprintf( stderr, "VTS ATTR Nb: %d\n", vts_inf.i_vts_nb ); + DumpBits( p_ifo, pi_buffer, &p_current, 2 ); + vts_inf.i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current ); + vts_inf.pi_vts_attr_start_byte = + malloc( vts_inf.i_vts_nb *sizeof(u32) ); + if( vts_inf.pi_vts_attr_start_byte == NULL ) + { + intf_ErrMsg( "ifo error: out of memory in IfoInit" ); + return -1; + } + + for( i = 0 ; i < vts_inf.i_vts_nb ; i++ ) + { + vts_inf.pi_vts_attr_start_byte[i] = ReadDouble( p_ifo, pi_buffer, &p_current ); + } + + vts_inf.p_vts_attr = malloc( vts_inf.i_vts_nb *sizeof(vts_attr_t) ); + if( vts_inf.p_vts_attr == NULL ) { - pgc.com_tab.p_post_com = - malloc(pgc.com_tab.i_post_com_nb *sizeof(ifo_command_t)); - if( pgc.com_tab.p_post_com == NULL ) + intf_ErrMsg( "ifo erro: out of memory in IfoInit" ); + return -1; + } + + for( i = 0 ; i < vts_inf.i_vts_nb ; i++ ) + { + p_current = FillBuffer( p_ifo, pi_buffer, i_start + + vts_inf.pi_vts_attr_start_byte[i] ); + vts_inf.p_vts_attr[i].i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current ); + vts_inf.p_vts_attr[i].i_cat_app_type = ReadDouble( p_ifo, pi_buffer, &p_current ); + // GETS( &vts_inf.p_vts_attr[i].vts_menu_video_attr ); +DumpBits( p_ifo, pi_buffer, &p_current, 2 ); + DumpBits( p_ifo, pi_buffer, &p_current, 1 ); + vts_inf.p_vts_attr[i].i_vts_menu_audio_nb = ReadByte( p_ifo, pi_buffer, &p_current ); +//fprintf( stderr, "m audio nb : %d\n", vts_inf.p_vts_attr[i].i_vts_menu_audio_nb ); + for( j = 0 ; j < 8 ; j++ ) { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return pgc; + i_temp = ReadQuad( p_ifo, pi_buffer, &p_current );; } - for( i=0 ; ib_error = 1; - return pgc; + i_temp = ReadQuad( p_ifo, pi_buffer, &p_current );; } - for( i=0 ; ii_pos = lseek( p_ifo->i_fd, i_start - + pgc.i_prg_map_sbyte, SEEK_SET ); - pgc.prg_map.pi_entry_cell = malloc( pgc.i_prg_nb *sizeof(u8) ); - if( pgc.prg_map.pi_entry_cell == NULL ) + if( ReadCellInf( p_ifo, &p_ifo->vmg.cell_inf, p_ifo->i_off + + manager_inf.i_cell_inf_start_sector *DVD_LB_SIZE ) < 0 ) { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return pgc; + return -1; } - GET( pgc.prg_map.pi_entry_cell, pgc.i_prg_nb ); - /* FIXME : check endianness here */ } - /* Parsing of cell_play_inf_t */ - if( pgc.i_cell_play_inf_sbyte ) + + /* + * global vob unit map. + */ + if( manager_inf.i_vobu_map_start_sector ) { - p_ifo->i_pos = lseek( p_ifo->i_fd, i_start - + pgc.i_cell_play_inf_sbyte, SEEK_SET ); - pgc.p_cell_play_inf = malloc( pgc.i_cell_nb *sizeof(cell_play_inf_t) ); - if( pgc.p_cell_play_inf == NULL ) - { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return pgc; - } - for( i=0 ; ivmg.vobu_map, p_ifo->i_off + + manager_inf.i_vobu_map_start_sector *DVD_LB_SIZE ) < 0 ) { - GETS( &pgc.p_cell_play_inf[i].i_cat ); - GETC( &pgc.p_cell_play_inf[i].i_still_time ); - GETC( &pgc.p_cell_play_inf[i].i_com_nb ); - GETL( &pgc.p_cell_play_inf[i].i_play_time ); - GETL( &pgc.p_cell_play_inf[i].i_entry_sector ); - GETL( &pgc.p_cell_play_inf[i].i_first_ilvu_vobu_esector ); - GETL( &pgc.p_cell_play_inf[i].i_lvobu_ssector ); - GETL( &pgc.p_cell_play_inf[i].i_lsector ); + return -1; } } - /* Parsing of cell_pos_inf_map */ - if( pgc.i_cell_pos_inf_sbyte ) - { - p_ifo->i_pos = lseek( p_ifo->i_fd, i_start - + pgc.i_cell_pos_inf_sbyte, SEEK_SET ); - pgc.p_cell_pos_inf = malloc( pgc.i_cell_nb *sizeof(cell_pos_inf_t) ); - if( pgc.p_cell_play_inf == NULL ) - { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return pgc; - } - for( i=0 ; ivts.b_initialized = 0; + + intf_WarnMsg( 1, "ifo info: vmg initialized" ); - return pgc; + return 0; } /***************************************************************************** - * ReadUnit : Fills Menu Language Unit Table/ PGC Info Table + * IfoTitleSet: Parse vts*.ifo files to fill the Video Title Set structure. *****************************************************************************/ -static pgci_inf_t ReadUnit( ifo_t* p_ifo ) +int IfoTitleSet( ifo_t * p_ifo ) { - pgci_inf_t inf; - int i; - off_t i_start = p_ifo->i_pos; + u8 pi_buffer[DVD_LB_SIZE]; + u8 * p_current; + off_t i_off; + off_t i_start; + u64 i_temp; + int i, j; -//fprintf( stderr, "Unit\n" ); - - GETS( &inf.i_srp_nb ); - FLUSH( 2 ); - GETL( &inf.i_lu_ebyte ); - inf.p_srp = malloc( inf.i_srp_nb *sizeof(pgci_srp_t) ); - if( inf.p_srp == NULL ) + if( p_ifo->vts.b_initialized ) { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return inf; + FreeTitleSet( &p_ifo->vts ); } - for( i=0 ; ivmg.title_inf.p_attr[p_ifo->i_title-1].i_start_sector ) + * DVD_LB_SIZE + + p_ifo->i_off; + +//fprintf(stderr, "offset: %lld\n" , i_off ); + + p_current = FillBuffer( p_ifo, pi_buffer, i_off ); +//i_start = p_ifo->i_pos; + p_ifo->vts.i_pos = p_ifo->i_pos; + +#define manager_inf p_ifo->vts.manager_inf + /* + * reads manager information + */ +//fprintf( stderr, "VTSI\n" ); + + ReadBits( p_ifo, pi_buffer, &p_current, manager_inf.psz_id , 12 ); + manager_inf.psz_id[12] = '\0'; + manager_inf.i_end_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + DumpBits( p_ifo, pi_buffer, &p_current, 12 ); + manager_inf.i_inf_end_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + DumpBits( p_ifo, pi_buffer, &p_current, 1 ); + manager_inf.i_spec_ver = ReadByte( p_ifo, pi_buffer, &p_current ); + manager_inf.i_cat = ReadDouble( p_ifo, pi_buffer, &p_current ); + DumpBits( p_ifo, pi_buffer, &p_current, 90 ); + manager_inf.i_inf_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current ); + DumpBits( p_ifo, pi_buffer, &p_current, 60 ); + manager_inf.i_menu_vob_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + manager_inf.i_title_vob_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + manager_inf.i_title_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + manager_inf.i_title_unit_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + manager_inf.i_menu_unit_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + manager_inf.i_time_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + manager_inf.i_menu_cell_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + manager_inf.i_menu_vobu_map_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + manager_inf.i_cell_inf_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + manager_inf.i_vobu_map_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + DumpBits( p_ifo, pi_buffer, &p_current, 24 ); +// GETS( &manager_inf.m_video_atrt ); +DumpBits( p_ifo, pi_buffer, &p_current, 2 ); + DumpBits( p_ifo, pi_buffer, &p_current, 1 ); + manager_inf.i_menu_audio_nb = ReadByte( p_ifo, pi_buffer, &p_current ); + for( i = 0 ; i < 8 ; i++ ) + { + i_temp = ReadQuad( p_ifo, pi_buffer, &p_current ); + } + DumpBits( p_ifo, pi_buffer, &p_current, 17 ); + manager_inf.i_menu_spu_nb = ReadByte( p_ifo, pi_buffer, &p_current ); + for( i = 0 ; i < 28 ; i++ ) + { + ReadBits( p_ifo, pi_buffer, &p_current, (u8*)(&i_temp), 6 ); + /* FIXME : take care of endianness */ } - for( i=0 ; ii_pos = lseek( p_ifo->i_fd, - i_start + inf.p_srp[i].i_pgci_sbyte, - SEEK_SET ); - inf.p_srp[i].pgc = ReadPGC( p_ifo ); + DumpBits( p_ifo, pi_buffer, &p_current, 2 ); +// GETS( &manager_inf.video_atrt ); +DumpBits( p_ifo, pi_buffer, &p_current, 2 ); + DumpBits( p_ifo, pi_buffer, &p_current, 1 ); + manager_inf.i_audio_nb = ReadByte( p_ifo, pi_buffer, &p_current ); +//fprintf( stderr, "vtsi audio nb : %d\n", manager_inf.i_audio_nb ); + for( i = 0 ; i < 8 ; i++ ) + { + i_temp = ReadQuad( p_ifo, pi_buffer, &p_current ); +//fprintf( stderr, "Audio %d: %llx\n", i, i_temp ); + i_temp >>= 8; + manager_inf.p_audio_attr[i].i_bar = i_temp & 0xff; + i_temp >>= 8; + manager_inf.p_audio_attr[i].i_caption = i_temp & 0xff; + i_temp >>= 8; + manager_inf.p_audio_attr[i].i_foo = i_temp & 0xff; + i_temp >>= 8; + manager_inf.p_audio_attr[i].i_lang_code = i_temp & 0xffff; + i_temp >>= 16; + manager_inf.p_audio_attr[i].i_num_channels = i_temp & 0x7; + i_temp >>= 3; + manager_inf.p_audio_attr[i].i_test = i_temp & 0x1; + i_temp >>= 1; + manager_inf.p_audio_attr[i].i_sample_freq = i_temp & 0x3; + i_temp >>= 2; + manager_inf.p_audio_attr[i].i_quantization = i_temp & 0x3; + i_temp >>= 2; + manager_inf.p_audio_attr[i].i_appl_mode = i_temp & 0x3; + i_temp >>= 2; + manager_inf.p_audio_attr[i].i_type = i_temp & 0x3; + i_temp >>= 2; + manager_inf.p_audio_attr[i].i_multichannel_extension = i_temp & 0x1; + i_temp >>= 1; + manager_inf.p_audio_attr[i].i_coding_mode = i_temp & 0x7; + } + DumpBits( p_ifo, pi_buffer, &p_current, 17 ); + manager_inf.i_spu_nb = ReadByte( p_ifo, pi_buffer, &p_current ); +//fprintf( stderr, "vtsi subpic nb : %d\n", manager_inf.i_spu_nb ); + for( i=0 ; i> 16; +//fprintf( stderr, "Subpic %d: %llx\n", i, i_temp ); + manager_inf.p_spu_attr[i].i_caption = i_temp & 0xff; + i_temp >>= 16; + manager_inf.p_spu_attr[i].i_lang_code = i_temp & 0xffff; + i_temp >>= 16; + manager_inf.p_spu_attr[i].i_prefix = i_temp & 0xffff; } - return inf; -} + /* + * reads title information: set of pointers to title + */ +#define title_inf p_ifo->vts.title_inf + if( manager_inf.i_title_inf_start_sector ) + { + p_current = FillBuffer( p_ifo, pi_buffer, p_ifo->vts.i_pos + + manager_inf.i_title_inf_start_sector *DVD_LB_SIZE ); -/***************************************************************************** - * ReadUnitTable : Fills the PGCI Unit structure. - *****************************************************************************/ -static pgci_ut_t ReadUnitTable( ifo_t* p_ifo ) -{ - pgci_ut_t pgci; - int i; - off_t i_start = p_ifo->i_pos; + i_start = p_ifo->i_pos; + +//fprintf( stderr, "VTS PTR\n" ); + + title_inf.i_title_nb = ReadWord( p_ifo, pi_buffer, &p_current ); +//fprintf( stderr, "VTS title_inf nb: %d\n", title_inf.i_title_nb ); + DumpBits( p_ifo, pi_buffer, &p_current, 2 ); + title_inf.i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current ); + + title_inf.pi_start_byte = malloc( title_inf.i_title_nb *sizeof(u32) ); + if( title_inf.pi_start_byte == NULL ) + { + intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" ); + return -1; + } -//fprintf( stderr, "Unit Table\n" ); + for( i = 0 ; i < title_inf.i_title_nb ; i++ ) + { + title_inf.pi_start_byte[i] = ReadDouble( p_ifo, pi_buffer, &p_current ); + } - GETS( &pgci.i_lu_nb ); - FLUSH( 2 ); - GETL( &pgci.i_ebyte ); - pgci.p_lu = malloc( pgci.i_lu_nb *sizeof(pgci_lu_t) ); - if( pgci.p_lu == NULL ) - { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return pgci; + /* Parsing of tts */ + title_inf.p_title_start = malloc( title_inf.i_title_nb + *sizeof(title_start_t) ); + if( title_inf.p_title_start == NULL ) + { + intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" ); + return -1; + } + + for( i = 0 ; i < title_inf.i_title_nb ; i++ ) + { + p_current = FillBuffer( p_ifo, pi_buffer, i_start + + title_inf.pi_start_byte[i] ); + + title_inf.p_title_start[i].i_program_chain_num = + ReadWord( p_ifo, pi_buffer, &p_current ); + title_inf.p_title_start[i].i_program_num = ReadWord( p_ifo, pi_buffer, &p_current ); +//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 ); + } } - for( i=0 ; ivts.menu_unit, p_ifo->vts.i_pos + + manager_inf.i_menu_unit_start_sector *DVD_LB_SIZE ) < 0 ) + { + return -1; + } } - pgci.p_pgci_inf = malloc( pgci.i_lu_nb *sizeof(pgci_inf_t) ); - if( pgci.p_pgci_inf == NULL ) + + /* + * title unit information + */ + if( manager_inf.i_title_unit_start_sector ) { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return pgci; + if( ReadUnitInf( p_ifo, &p_ifo->vts.title_unit, p_ifo->vts.i_pos + + manager_inf.i_title_unit_start_sector *DVD_LB_SIZE ) < 0 ) + { + return -1; + } } - for( i=0 ; ivts.time_inf + if( manager_inf.i_time_inf_start_sector ) { - p_ifo->i_pos = lseek( p_ifo->i_fd, i_start + - pgci.p_lu[i].i_lu_sbyte, - SEEK_SET ); - pgci.p_pgci_inf[i] = ReadUnit( p_ifo ); - } + u8 pi_buffer[DVD_LB_SIZE]; - return pgci; -} + p_current = FillBuffer( p_ifo, pi_buffer, p_ifo->vts.i_pos + + manager_inf.i_time_inf_start_sector *DVD_LB_SIZE ); -/***************************************************************************** - * ReadCellInf : Fills the Cell Information structure. - *****************************************************************************/ -static c_adt_t ReadCellInf( ifo_t* p_ifo ) -{ - c_adt_t c_adt; - off_t i_start = p_ifo->i_pos; - int i; +//fprintf( stderr, "TMAP\n" ); -//fprintf( stderr, "CELL ADD\n" ); + time_inf.i_nb = ReadWord( p_ifo, pi_buffer, &p_current );; + DumpBits( p_ifo, pi_buffer, &p_current, 2 ); + time_inf.i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current ); + + time_inf.pi_start_byte = malloc( time_inf.i_nb *sizeof(u32) ); + if( time_inf.pi_start_byte == NULL ) + { + intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" ); + return -1; + } + + for( i = 0 ; i < time_inf.i_nb ; i++ ) + { + time_inf.pi_start_byte[i] = ReadDouble( p_ifo, pi_buffer, &p_current ); + } + + time_inf.p_time_map = malloc( time_inf.i_nb *sizeof(time_map_t) ); + if( time_inf.p_time_map == NULL ) + { + intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" ); + return -1; + } + + for( i = 0 ; i < time_inf.i_nb ; i++ ) + { + time_inf.p_time_map[i].i_time_unit = ReadByte( p_ifo, pi_buffer, &p_current ); + DumpBits( p_ifo, pi_buffer, &p_current, 1 ); + time_inf.p_time_map[i].i_entry_nb = ReadWord( p_ifo, pi_buffer, &p_current ); + + time_inf.p_time_map[i].pi_sector = + malloc( time_inf.p_time_map[i].i_entry_nb *sizeof(u32) ); + if( time_inf.p_time_map[i].pi_sector == NULL ) + { + intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" ); + return -1; + } + + for( j = 0 ; j < time_inf.p_time_map[i].i_entry_nb ; j++ ) + { + time_inf.p_time_map[i].pi_sector[j] = ReadDouble( p_ifo, pi_buffer, &p_current ); + } + } + } +#undef time_inf - GETS( &c_adt.i_vob_nb ); - FLUSH( 2 ); - GETL( &c_adt.i_ebyte ); - c_adt.i_cell_nb = - ( i_start + c_adt.i_ebyte + 1 - p_ifo->i_pos ) / sizeof(cell_inf_t); - c_adt.p_cell_inf = malloc( c_adt.i_cell_nb *sizeof(cell_inf_t) ); - if( c_adt.p_cell_inf == NULL ) + if( manager_inf.i_menu_cell_inf_start_sector ) { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return c_adt; + if( ReadCellInf( p_ifo, &p_ifo->vts.menu_cell_inf, p_ifo->vts.i_pos + + manager_inf.i_menu_cell_inf_start_sector *DVD_LB_SIZE ) < 0 ) + { + return -1; + } } - for( i = 0 ; i < c_adt.i_cell_nb ; i++ ) + + if( manager_inf.i_menu_vobu_map_start_sector ) { - GETS( &c_adt.p_cell_inf[i].i_vob_id ); - GETC( &c_adt.p_cell_inf[i].i_cell_id ); - FLUSH( 1 ); - GETL( &c_adt.p_cell_inf[i].i_ssector ); - GETL( &c_adt.p_cell_inf[i].i_esector ); + if( ReadVobuMap( p_ifo, &p_ifo->vts.menu_vobu_map, p_ifo->vts.i_pos + + manager_inf.i_menu_vobu_map_start_sector *DVD_LB_SIZE ) < 0 ) + { + return -1; + } } - - return c_adt; -} -/***************************************************************************** - * ReadMap : Fills the VOBU Map structure. - *****************************************************************************/ -static vobu_admap_t ReadMap( ifo_t* p_ifo ) -{ - vobu_admap_t map; - int i, i_max; - off_t i_start = p_ifo->i_pos; - -//fprintf( stderr, "VOBU ADMAP\n" ); + if( manager_inf.i_cell_inf_start_sector ) + { + if( ReadCellInf( p_ifo, &p_ifo->vts.cell_inf, p_ifo->vts.i_pos + + manager_inf.i_cell_inf_start_sector *DVD_LB_SIZE ) ) + { + return -1; + } + } - GETL( &map.i_ebyte ); - i_max = ( i_start + map.i_ebyte + 1 - p_ifo->i_pos ) / sizeof(u32); - map.pi_vobu_ssector = malloc( i_max *sizeof(u32) ); - for( i=0 ; ivts.vobu_map, p_ifo->vts.i_pos + + manager_inf.i_vobu_map_start_sector *DVD_LB_SIZE ) ) + { + return -1; + } } +#undef manager_inf + + intf_WarnMsg( 2, "ifo info: vts %d initialized", + p_ifo->vmg.title_inf.p_attr[p_ifo->i_title-1].i_title_set_num ); - return map; + p_ifo->vts.b_initialized = 1; + + return 0; } - -/* - * Video Manager Information Processing. - * This is what is contained in video_ts.ifo. - */ /***************************************************************************** - * ReadVMGInfMat : Fills the Management Information structure. + * FreeTitleSet : free all structures allocated by IfoTitleSet *****************************************************************************/ -static vmgi_mat_t ReadVMGInfMat( ifo_t* p_ifo ) +static int FreeTitleSet( vts_t * p_vts ) { - vmgi_mat_t mat; - int i; -// off_t i_start = p_ifo->i_pos; + int i; -//fprintf( stderr, "VMGI\n" ); + if( p_vts->manager_inf.i_vobu_map_start_sector ) + { + FreeVobuMap( &p_vts->vobu_map ); + } - GET( mat.psz_id , 12 ); - mat.psz_id[12] = '\0'; - GETL( &mat.i_lsector ); - FLUSH( 12 ); - GETL( &mat.i_i_lsector ); - FLUSH( 1 ); - GETC( &mat.i_spec_ver ); - GETL( &mat.i_cat ); - GETS( &mat.i_vol_nb ); - GETS( &mat.i_vol ); - GETC( &mat.i_disc_side ); - FLUSH( 19 ); - GETS( &mat.i_tts_nb ); - GET( mat.ps_provider_id, 32 ); - GETLL( &mat.i_pos_code ); - FLUSH( 24 ); - GETL( &mat.i_i_mat_ebyte ); - GETL( &mat.i_fp_pgc_sbyte ); - FLUSH( 56 ); - GETL( &mat.i_vobs_ssector ); - GETL( &mat.i_ptt_srpt_ssector ); - GETL( &mat.i_pgci_ut_ssector ); - GETL( &mat.i_ptl_mait_ssector ); - GETL( &mat.i_vts_atrt_ssector ); - GETL( &mat.i_txtdt_mg_ssector ); - GETL( &mat.i_c_adt_ssector ); - GETL( &mat.i_vobu_admap_ssector ); - FLUSH( 32 ); - GETS( &mat.i_video_atrt ); - FLUSH( 1 ); - GETC( &mat.i_audio_nb ); -//fprintf( stderr, "vmgi audio nb : %d\n", mat.i_audio_nb ); - for( i=0 ; i < 8 ; i++ ) + if( p_vts->manager_inf.i_cell_inf_start_sector ) { - GETLL( &mat.pi_audio_atrt[i] ); + FreeCellInf( &p_vts->cell_inf ); } - FLUSH( 17 ); - GETC( &mat.i_subpic_nb ); -//fprintf( stderr, "vmgi subpic nb : %d\n", mat.i_subpic_nb ); - for( i=0 ; i < mat.i_subpic_nb ; i++ ) + + if( p_vts->manager_inf.i_menu_vobu_map_start_sector ) { - GET( &mat.pi_subpic_atrt[i], 6 ); - /* FIXME : take care of endianness */ + FreeVobuMap( &p_vts->menu_vobu_map ); } - return mat; -} + if( p_vts->manager_inf.i_menu_cell_inf_start_sector ) + { + FreeCellInf( &p_vts->menu_cell_inf ); + } -/***************************************************************************** - * ReadVMGTitlePointer : Fills the Part Of Title Search Pointer structure. - *****************************************************************************/ -static vmg_ptt_srpt_t ReadVMGTitlePointer( ifo_t* p_ifo ) -{ - vmg_ptt_srpt_t ptr; - int i; -// off_t i_start = p_ifo->i_pos; + if( p_vts->manager_inf.i_time_inf_start_sector ) + { + for( i = 0 ; i < p_vts->time_inf.i_nb ; i++ ) + { + free( p_vts->time_inf.p_time_map[i].pi_sector ); + } -//fprintf( stderr, "PTR\n" ); + free( p_vts->time_inf.p_time_map ); + free( p_vts->time_inf.pi_start_byte ); + } - GETS( &ptr.i_ttu_nb ); - FLUSH( 2 ); - GETL( &ptr.i_ebyte ); - /* Parsing of tts */ - ptr.p_tts = malloc( ptr.i_ttu_nb *sizeof(tts_t) ); - if( ptr.p_tts == NULL ) + if( p_vts->manager_inf.i_title_unit_start_sector ) { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return ptr; + FreeUnitInf( &p_vts->title_unit ); } - for( i=0 ; imanager_inf.i_menu_unit_start_sector ) { - GETC( &ptr.p_tts[i].i_play_type ); - GETC( &ptr.p_tts[i].i_angle_nb ); - GETS( &ptr.p_tts[i].i_ptt_nb ); - GETS( &ptr.p_tts[i].i_parental_id ); - GETC( &ptr.p_tts[i].i_tts_nb ); - GETC( &ptr.p_tts[i].i_vts_ttn ); - GETL( &ptr.p_tts[i].i_ssector ); + FreeTitleUnit( &p_vts->menu_unit ); } - return ptr; + if( p_vts->manager_inf.i_title_inf_start_sector ) + { + free( p_vts->title_inf.pi_start_byte ); + free( p_vts->title_inf.p_title_start ); + } + + p_vts->b_initialized = 0; + + return 0; } /***************************************************************************** - * ReadParentalInf : Fills the Parental Management structure. + * IfoDestroy : Frees all the memory allocated to ifo structures *****************************************************************************/ -static vmg_ptl_mait_t ReadParentalInf( ifo_t* p_ifo ) +void IfoDestroy( ifo_t * p_ifo ) { - vmg_ptl_mait_t par; - int i, j, k; - off_t i_start = p_ifo->i_pos; + int i, j; -//fprintf( stderr, "PTL\n" ); + FreeTitleSet( &p_ifo->vts ); - GETS( &par.i_country_nb ); - GETS( &par.i_vts_nb ); - GETL( &par.i_ebyte ); - par.p_ptl_desc = malloc( par.i_country_nb *sizeof(vmg_ptl_mai_desc_t) ); - if( par.p_ptl_desc == NULL ) + if( p_ifo->vmg.manager_inf.i_vobu_map_start_sector ) { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return par; + FreeVobuMap( &p_ifo->vmg.vobu_map ); } - for( i=0 ; ivmg.manager_inf.i_cell_inf_start_sector ) { - GET( par.p_ptl_desc[i].ps_country_code, 2 ); - FLUSH( 2 ); - GETS( &par.p_ptl_desc[i].i_ptl_mai_sbyte ); - FLUSH( 2 ); + FreeCellInf( &p_ifo->vmg.cell_inf ); } - par.p_ptl_mask = malloc( par.i_country_nb *sizeof(vmg_ptl_mask_t) ); - if( par.p_ptl_mask == NULL ) + + if( p_ifo->vmg.manager_inf.i_vts_inf_start_sector ) { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return par; + free( p_ifo->vmg.vts_inf.p_vts_attr ); + free( p_ifo->vmg.vts_inf.pi_vts_attr_start_byte ); } - for( i=0 ; ivmg.manager_inf.i_parental_inf_start_sector ) { - p_ifo->i_pos = lseek( p_ifo->i_fd, i_start + - par.p_ptl_desc[i].i_ptl_mai_sbyte, SEEK_SET ); - for( j=1 ; j<=8 ; j++ ) + for( i = 0 ; i < p_ifo->vmg.parental_inf.i_country_nb ; i++ ) { - par.p_ptl_mask[i].ppi_ptl_mask[j] = - malloc( par.i_vts_nb *sizeof(u16) ); - if( par.p_ptl_mask[i].ppi_ptl_mask[j] == NULL ) - { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return par; - } - for( k=0 ; kvmg.parental_inf.p_parental_mask[i].ppi_mask[j] ); } } + + free( p_ifo->vmg.parental_inf.p_parental_mask ); + free( p_ifo->vmg.parental_inf.p_parental_desc ); } - return par; + if( p_ifo->vmg.manager_inf.i_title_unit_start_sector ) + { + FreeTitleUnit( &p_ifo->vmg.title_unit ); + } + + if( p_ifo->vmg.manager_inf.i_title_inf_start_sector ) + { + free( p_ifo->vmg.title_inf.p_attr ); + } + + FreeTitle( &p_ifo->vmg.title ); + + free( p_ifo ); + + return; } +/* + * Function common to Video Manager and Video Title set Processing + */ /***************************************************************************** - * ReadVTSAttr : Fills the structure about VTS attributes. + * ReadTitle : Fills the title structure. + ***************************************************************************** + * Titles are logical stream units that correspond to a whole inside the dvd. + * Several title can point to the same part of the physical DVD, and give + * map to different anglesfor instance. *****************************************************************************/ -static vmg_vts_atrt_t ReadVTSAttr( ifo_t* p_ifo ) +static int ReadTitle( ifo_t * p_ifo, title_t * p_title, off_t i_pos ) { - vmg_vts_atrt_t atrt; - int i, j; - off_t i_start = p_ifo->i_pos; + u8 pi_buffer[DVD_LB_SIZE]; + u8 * p_current; + off_t i_start; + int i; -//fprintf( stderr, "VTS ATTR\n" ); + p_current = FillBuffer( p_ifo, pi_buffer, i_pos ); - GETS( &atrt.i_vts_nb ); - FLUSH( 2 ); - GETL( &atrt.i_ebyte ); - atrt.pi_vts_atrt_sbyte = malloc( atrt.i_vts_nb *sizeof(u32) ); - if( atrt.pi_vts_atrt_sbyte == NULL ) + i_start = p_ifo->i_pos; + +//fprintf( stderr, "PGC @ %lld\n",p_ifo->i_pos ); + + DumpBits( p_ifo, pi_buffer, &p_current, 2); + p_title->i_chapter_nb = ReadByte( p_ifo, pi_buffer, &p_current ); + p_title->i_cell_nb = ReadByte( p_ifo, pi_buffer, &p_current ); +//fprintf( stderr, "title: Prg: %d Cell: %d\n",p_title->i_chapter_nb,p_title->i_cell_nb ); + p_title->i_play_time = ReadDouble( p_ifo, pi_buffer, &p_current ); + p_title->i_prohibited_user_op = ReadDouble( p_ifo, pi_buffer, &p_current ); + for( i = 0 ; i < 8 ; i++ ) { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return atrt; + p_title->pi_audio_status[i] = ReadWord( p_ifo, pi_buffer, &p_current ); } - for( i=0 ; ipi_subpic_status[i] = ReadDouble( p_ifo, pi_buffer, &p_current ); } - atrt.p_vts_atrt = malloc( atrt.i_vts_nb *sizeof(vts_atrt_t) ); - if( atrt.p_vts_atrt == NULL ) + p_title->i_next_title_num = ReadWord( p_ifo, pi_buffer, &p_current ); + p_title->i_prev_title_num = ReadWord( p_ifo, pi_buffer, &p_current ); + p_title->i_go_up_title_num = ReadWord( p_ifo, pi_buffer, &p_current ); +//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 ); + p_title->i_still_time = ReadByte( p_ifo, pi_buffer, &p_current ); + p_title->i_play_mode = ReadByte( p_ifo, pi_buffer, &p_current ); + for( i = 0 ; i < 16 ; i++ ) { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return atrt; + p_title->pi_yuv_color[i] = ReadDouble( p_ifo, pi_buffer, &p_current ); + /* FIXME : We have to erase the extra bit */ } - for( i=0 ; ii_command_start_byte = ReadWord( p_ifo, pi_buffer, &p_current ); + p_title->i_chapter_map_start_byte = ReadWord( p_ifo, pi_buffer, &p_current ); + p_title->i_cell_play_start_byte = ReadWord( p_ifo, pi_buffer, &p_current ); + p_title->i_cell_pos_start_byte = ReadWord( p_ifo, pi_buffer, &p_current ); + + /* parsing of command_t */ + if( p_title->i_command_start_byte ) { - p_ifo->i_pos = lseek( p_ifo->i_fd, i_start + - atrt.pi_vts_atrt_sbyte[i], - SEEK_SET ); - GETL( &atrt.p_vts_atrt[i].i_ebyte ); - GETL( &atrt.p_vts_atrt[i].i_cat_app_type ); - GETS( &atrt.p_vts_atrt[i].i_vtsm_video_atrt ); - FLUSH( 1 ); - GETC( &atrt.p_vts_atrt[i].i_vtsm_audio_nb ); -//fprintf( stderr, "m audio nb : %d\n", atrt.p_vts_atrt[i].i_vtsm_audio_nb ); - for( j=0 ; j<8 ; j++ ) + p_current = FillBuffer( p_ifo, pi_buffer, + i_start + p_title->i_command_start_byte ); + + /* header */ + p_title->command.i_pre_command_nb = ReadWord( p_ifo, pi_buffer, &p_current ); + p_title->command.i_post_command_nb = ReadWord( p_ifo, pi_buffer, &p_current ); + p_title->command.i_cell_command_nb = ReadWord( p_ifo, pi_buffer, &p_current ); + DumpBits( p_ifo, pi_buffer, &p_current, 2 ); + + /* pre-title commands */ + if( p_title->command.i_pre_command_nb ) { - GETLL( &atrt.p_vts_atrt[i].pi_vtsm_audio_atrt[j] ); + p_title->command.p_pre_command = + malloc( p_title->command.i_pre_command_nb + *sizeof(command_desc_t) ); + + if( p_title->command.p_pre_command == NULL ) + { + intf_ErrMsg( "ifo error: out of memory in ReadTitle" ); + return -1; + } + + for( i = 0 ; i < p_title->command.i_pre_command_nb ; i++ ) + { + p_title->command.p_pre_command[i] = ReadQuad( p_ifo, pi_buffer, &p_current ); + } } - FLUSH( 17 ); - GETC( &atrt.p_vts_atrt[i].i_vtsm_subpic_nb ); -//fprintf( stderr, "m subp nb : %d\n", atrt.p_vts_atrt[i].i_vtsm_subpic_nb ); - for( j=0 ; j<28 ; j++ ) + else { - GET( &atrt.p_vts_atrt[i].pi_vtsm_subpic_atrt[j], 6 ); - /* FIXME : Fix endianness issue here */ + p_title->command.p_pre_command = NULL; } - FLUSH( 2 ); - GETS( &atrt.p_vts_atrt[i].i_vtstt_video_atrt ); - FLUSH( 1 ); - GETL( &atrt.p_vts_atrt[i].i_vtstt_audio_nb ); -//fprintf( stderr, "tt audio nb : %d\n", atrt.p_vts_atrt[i].i_vtstt_audio_nb ); - for( j=0 ; j<8 ; j++ ) + + /* post-title commands */ + if( p_title->command.i_post_command_nb ) { - GETLL( &atrt.p_vts_atrt[i].pi_vtstt_audio_atrt[j] ); + p_title->command.p_post_command = + malloc( p_title->command.i_post_command_nb + *sizeof(command_desc_t) ); + + if( p_title->command.p_post_command == NULL ) + { + intf_ErrMsg( "ifo error: out of memory in ReadTitle" ); + return -1; + } + + for( i=0 ; icommand.i_post_command_nb ; i++ ) + { + p_title->command.p_post_command[i] = ReadQuad( p_ifo, pi_buffer, &p_current ); + } } - FLUSH( 17 ); - GETC( &atrt.p_vts_atrt[i].i_vtstt_subpic_nb ); -//fprintf( stderr, "tt subp nb : %d\n", atrt.p_vts_atrt[i].i_vtstt_subpic_nb ); - for( j=0 ; j<28/*atrt.p_vts_atrt[i].i_vtstt_subpic_nb*/ ; j++ ) + else { - GET( &atrt.p_vts_atrt[i].pi_vtstt_subpic_atrt[j], 6 ); - /* FIXME : Fix endianness issue here */ + p_title->command.p_post_command = NULL; } - } - return atrt; -} - -/***************************************************************************** - * ReadVMG : Parse video_ts.ifo file to fill the Video Manager structure. - *****************************************************************************/ -static vmg_t ReadVMG( ifo_t* p_ifo ) -{ - vmg_t vmg; + /* cell commands */ + if( p_title->command.i_cell_command_nb ) + { + p_title->command.p_cell_command = + malloc( p_title->command.i_cell_command_nb + *sizeof(command_desc_t) ); - p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off, SEEK_SET); - vmg.mat = ReadVMGInfMat( p_ifo ); - p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + - vmg.mat.i_fp_pgc_sbyte, SEEK_SET ); - vmg.pgc = ReadPGC( p_ifo ); - if( vmg.mat.i_ptt_srpt_ssector ) - { - p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + - vmg.mat.i_ptt_srpt_ssector *DVD_LB_SIZE, - SEEK_SET ); - vmg.ptt_srpt = ReadVMGTitlePointer( p_ifo ); + if( p_title->command.p_cell_command == NULL ) + { + intf_ErrMsg( "ifo error: out of memory in ReadTitle" ); + return -1; + } + + for( i=0 ; icommand.i_cell_command_nb ; i++ ) + { + p_title->command.p_cell_command[i] = ReadQuad( p_ifo, pi_buffer, &p_current ); + } + } + else + { + p_title->command.p_cell_command = NULL; + } } - if( vmg.mat.i_pgci_ut_ssector ) + + /* parsing of chapter_map_t: it gives the entry cell for each chapter */ + if( p_title->i_chapter_map_start_byte ) { - p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + - vmg.mat.i_pgci_ut_ssector *DVD_LB_SIZE, - SEEK_SET ); - vmg.pgci_ut = ReadUnitTable( p_ifo ); + p_ifo->i_pos = lseek( p_ifo->i_fd, + i_start + p_title->i_chapter_map_start_byte, + SEEK_SET ); + + p_title->chapter_map.pi_start_cell = + malloc( p_title->i_chapter_nb *sizeof(chapter_map_t) ); + + if( p_title->chapter_map.pi_start_cell == NULL ) + { + intf_ErrMsg( "ifo error: out of memory in Read Title" ); + return -1; + } + + ReadBits( p_ifo, pi_buffer, &p_current, p_title->chapter_map.pi_start_cell, + p_title->i_chapter_nb ); } - if( vmg.mat.i_ptl_mait_ssector ) + else { - p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + - vmg.mat.i_ptl_mait_ssector *DVD_LB_SIZE, - SEEK_SET ); - vmg.ptl_mait = ReadParentalInf( p_ifo ); + p_title->chapter_map.pi_start_cell = NULL; } - if( vmg.mat.i_vts_atrt_ssector ) + + /* parsing of cell_play_t */ + if( p_title->i_cell_play_start_byte ) { - p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + - vmg.mat.i_vts_atrt_ssector *DVD_LB_SIZE, - SEEK_SET ); - vmg.vts_atrt = ReadVTSAttr( p_ifo ); + p_current = FillBuffer( p_ifo, pi_buffer, + i_start + p_title->i_cell_play_start_byte ); + + p_title->p_cell_play = malloc( p_title->i_cell_nb + *sizeof(cell_play_t) ); + + if( p_title->p_cell_play == NULL ) + { + intf_ErrMsg( "ifo error: out of memory in ReadTitle" ); + return -1; + } + + for( i = 0 ; i < p_title->i_cell_nb ; i++ ) + { + p_title->p_cell_play[i].i_category = ReadWord( p_ifo, pi_buffer, &p_current ); + p_title->p_cell_play[i].i_still_time = ReadByte( p_ifo, pi_buffer, &p_current ); + p_title->p_cell_play[i].i_command_nb = ReadByte( p_ifo, pi_buffer, &p_current ); + p_title->p_cell_play[i].i_play_time = ReadDouble( p_ifo, pi_buffer, &p_current ); + p_title->p_cell_play[i].i_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + p_title->p_cell_play[i].i_first_ilvu_vobu_esector = + ReadDouble( p_ifo, pi_buffer, &p_current ); + p_title->p_cell_play[i].i_last_vobu_start_sector = + ReadDouble( p_ifo, pi_buffer, &p_current ); + p_title->p_cell_play[i].i_end_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); + } } - if( vmg.mat.i_c_adt_ssector ) + + /* Parsing of cell_pos_t */ + if( p_title->i_cell_pos_start_byte ) { - p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + - vmg.mat.i_c_adt_ssector *DVD_LB_SIZE, - SEEK_SET ); - vmg.c_adt = ReadCellInf( p_ifo ); - } - if( vmg.mat.i_vobu_admap_ssector ) + p_current = FillBuffer( p_ifo, pi_buffer, + i_start + p_title->i_cell_pos_start_byte ); + + p_title->p_cell_pos = malloc( p_title->i_cell_nb + *sizeof(cell_pos_t) ); + + if( p_title->p_cell_pos == NULL ) + { + intf_ErrMsg( "ifo error: out of memory" ); + return -1; + } + + for( i = 0 ; i < p_title->i_cell_nb ; i++ ) + { + p_title->p_cell_pos[i].i_vob_id = ReadWord( p_ifo, pi_buffer, &p_current ); + DumpBits( p_ifo, pi_buffer, &p_current, 1 ); + p_title->p_cell_pos[i].i_cell_id = ReadByte( p_ifo, pi_buffer, &p_current ); + } + } + + return 0; +} + +/***************************************************************************** + * FreeTitle: frees alla structure allocated by a call to ReadTitle + *****************************************************************************/ +static int FreeTitle( title_t * p_title ) +{ + if( p_title->i_command_start_byte ) { - p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + - vmg.mat.i_vobu_admap_ssector *DVD_LB_SIZE, - SEEK_SET ); - vmg.vobu_admap = ReadMap( p_ifo ); + if( p_title->command.i_pre_command_nb ) + { + free( p_title->command.p_pre_command ); + } + + if( p_title->command.i_post_command_nb ) + { + free( p_title->command.p_post_command ); + } + + if( p_title->command.i_cell_command_nb ) + { + free( p_title->command.p_cell_command ); + } + + if( p_title->i_chapter_map_start_byte ) + { + free( p_title->chapter_map.pi_start_cell ); + } + + if( p_title->i_cell_play_start_byte ) + { + free( p_title->p_cell_play ); + } + + if( p_title->i_cell_pos_start_byte ) + { + free( p_title->p_cell_pos ); + } } - return vmg; -} -/* - * Video Title Set Information Processing. - * This is what is contained in vts_*.ifo. - */ + return 0; +} /***************************************************************************** - * ReadVTSInfMat : Fills the Title Set Information structure. + * ReadUnitInf : Fills Menu Language Unit Table/ PGC Info Table *****************************************************************************/ -static vtsi_mat_t ReadVTSInfMat( ifo_t* p_ifo ) +static int ReadUnitInf( ifo_t * p_ifo, unit_inf_t * p_unit_inf, off_t i_pos ) { - vtsi_mat_t mat; - int i; -// off_t i_start = p_ifo->i_pos; + u8 pi_buffer[DVD_LB_SIZE]; + u8 * p_current; + off_t i_start; + int i; -//fprintf( stderr, "VTSI\n" ); + p_current = FillBuffer( p_ifo, pi_buffer, i_pos ); - GET( mat.psz_id , 12 ); - mat.psz_id[12] = '\0'; - GETL( &mat.i_lsector ); - FLUSH( 12 ); - GETL( &mat.i_i_lsector ); - FLUSH( 1 ); - GETC( &mat.i_spec_ver ); - GETL( &mat.i_cat ); - FLUSH( 90 ); - GETL( &mat.i_mat_ebyte ); - FLUSH( 60 ); - GETL( &mat.i_m_vobs_ssector ); - GETL( &mat.i_tt_vobs_ssector ); - GETL( &mat.i_ptt_srpt_ssector ); - GETL( &mat.i_pgcit_ssector ); - GETL( &mat.i_m_pgci_ut_ssector ); - GETL( &mat.i_tmap_ti_ssector ); - GETL( &mat.i_m_c_adt_ssector ); - GETL( &mat.i_m_vobu_admap_ssector ); - GETL( &mat.i_c_adt_ssector ); - GETL( &mat.i_vobu_admap_ssector ); - FLUSH( 24 ); - GETS( &mat.i_m_video_atrt ); - FLUSH( 1 ); - GETC( &mat.i_m_audio_nb ); - for( i=0 ; i<8 ; i++ ) - { - GETLL( &mat.pi_m_audio_atrt[i] ); - } - FLUSH( 17 ); - GETC( &mat.i_m_subpic_nb ); - for( i=0 ; i<28 ; i++ ) - { - GET( &mat.pi_m_subpic_atrt[i], 6 ); - /* FIXME : take care of endianness */ + i_start = p_ifo->i_pos; +//fprintf( stderr, "Unit\n" ); + + p_unit_inf->i_title_nb = ReadWord( p_ifo, pi_buffer, &p_current ); + DumpBits( p_ifo, pi_buffer, &p_current, 2 ); + p_unit_inf->i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current ); + + p_unit_inf->p_title = + malloc( p_unit_inf->i_title_nb *sizeof(unit_title_t) ); + if( p_unit_inf->p_title == NULL ) + { + intf_ErrMsg( "ifo error: out of memory in ReadUnit" ); + return -1; } - FLUSH( 2 ); - GETS( &mat.i_video_atrt ); - FLUSH( 1 ); - GETC( &mat.i_audio_nb ); -//fprintf( stderr, "vtsi audio nb : %d\n", mat.i_audio_nb ); - for( i=0 ; i<8 ; i++ ) + + for( i = 0 ; i < p_unit_inf->i_title_nb ; i++ ) { - GETLL( &mat.pi_audio_atrt[i] ); + p_unit_inf->p_title[i].i_category_mask = ReadByte( p_ifo, pi_buffer, &p_current ); + p_unit_inf->p_title[i].i_category = ReadByte( p_ifo, pi_buffer, &p_current ); + p_unit_inf->p_title[i].i_parental_mask = ReadWord( p_ifo, pi_buffer, &p_current ); + p_unit_inf->p_title[i].i_title_start_byte = ReadDouble( p_ifo, pi_buffer, &p_current ); } - FLUSH( 17 ); - GETC( &mat.i_subpic_nb ); -//fprintf( stderr, "vtsi subpic nb : %d\n", mat.i_subpic_nb ); - for( i=0 ; ii_title_nb ; i++ ) { - GET( &mat.pi_subpic_atrt[i], 6 ); - /* FIXME : take care of endianness */ +//fprintf( stderr, "Unit: PGC %d @ %lld\n", i, p_ifo->i_pos ); + ReadTitle( p_ifo, &p_unit_inf->p_title[i].title, i_start + + p_unit_inf->p_title[i].i_title_start_byte ); } - return mat; + return 0; } /***************************************************************************** - * ReadVTSTitlePointer : Fills the Part Of Title Search Pointer structure. + * FreeUnitInf : frees a structure allocated by ReadUnit + *****************************************************************************/ +static int FreeUnitInf( unit_inf_t * p_unit_inf ) +{ + if( p_unit_inf->p_title != NULL ) + { + free( p_unit_inf->p_title ); + } + + return 0; +} + + +/***************************************************************************** + * ReadTitleUnit: Fills the Title Unit structure. *****************************************************************************/ -static vts_ptt_srpt_t ReadVTSTitlePointer( ifo_t* p_ifo ) +static int ReadTitleUnit( ifo_t * p_ifo, title_unit_t * p_title_unit, + off_t i_pos ) { - vts_ptt_srpt_t ptr; + u8 pi_buffer[DVD_LB_SIZE]; + u8 * p_current; int i; - off_t i_start = p_ifo->i_pos; + off_t i_start; + + p_current = FillBuffer( p_ifo, pi_buffer, i_pos ); + i_start = p_ifo->i_pos; +//fprintf( stderr, "Unit Table\n" ); + + p_title_unit->i_unit_nb = ReadWord( p_ifo, pi_buffer, &p_current ); + DumpBits( p_ifo, pi_buffer, &p_current, 2 ); + p_title_unit->i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current ); -//fprintf( stderr, "PTR\n" ); +//fprintf(stderr, "Unit: nb %d end %d\n", p_title_unit->i_unit_nb, p_title_unit->i_end_byte ); - GETS( &ptr.i_ttu_nb ); - FLUSH( 2 ); - GETL( &ptr.i_ebyte ); - ptr.pi_ttu_sbyte = malloc( ptr.i_ttu_nb *sizeof(u32) ); - if( ptr.pi_ttu_sbyte == NULL ) + p_title_unit->p_unit = malloc( p_title_unit->i_unit_nb *sizeof(unit_t) ); + if( p_title_unit->p_unit == NULL ) { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return ptr; + intf_ErrMsg( "ifo error: out of memory in ReadTitleUnit" ); + return -1; } - for( i=0 ; ii_unit_nb ; i++ ) { - GETL( &ptr.pi_ttu_sbyte[i] ); + ReadBits( p_ifo, pi_buffer, &p_current, p_title_unit->p_unit[i].ps_lang_code, 2 ); + DumpBits( p_ifo, pi_buffer, &p_current, 1 ); + p_title_unit->p_unit[i].i_existence_mask = ReadByte( p_ifo, pi_buffer, &p_current ); + p_title_unit->p_unit[i].i_unit_inf_start_byte = + ReadDouble( p_ifo, pi_buffer, &p_current ); } - /* Parsing of tts */ - ptr.p_ttu = malloc( ptr.i_ttu_nb *sizeof(ttu_t) ); - if( ptr.p_ttu == NULL ) + + p_title_unit->p_unit_inf = + malloc( p_title_unit->i_unit_nb *sizeof(unit_inf_t) ); + if( p_title_unit->p_unit_inf == NULL ) { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return ptr; + intf_ErrMsg( "ifo error: out of memory in ReadTitleUnit" ); + return -1; } - for( i=0 ; ii_unit_nb ; i++ ) { - p_ifo->i_pos = lseek( p_ifo->i_fd, i_start + - ptr.pi_ttu_sbyte[i], SEEK_SET ); - GETS( &ptr.p_ttu[i].i_pgc_nb ); - GETS( &ptr.p_ttu[i].i_prg_nb ); + ReadUnitInf( p_ifo, &p_title_unit->p_unit_inf[i], i_start + + p_title_unit->p_unit[i].i_unit_inf_start_byte ); } - return ptr; + return 0; } /***************************************************************************** - * ReadVTSTimeMap : Fills the time map table + * FreeTitleUnit: frees a structure allocateed by ReadTitleUnit *****************************************************************************/ -static vts_tmap_ti_t ReadVTSTimeMap( ifo_t* p_ifo ) +static int FreeTitleUnit( title_unit_t * p_title_unit ) { - vts_tmap_ti_t tmap; - int i,j; -// off_t i_start = p_ifo->i_pos; - -//fprintf( stderr, "TMAP\n" ); + int i; - GETS( &tmap.i_nb ); - FLUSH( 2 ); - GETL( &tmap.i_ebyte ); - tmap.pi_sbyte = malloc( tmap.i_nb *sizeof(u32) ); - if( tmap.pi_sbyte == NULL ) + if( p_title_unit->p_unit_inf != NULL ) { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return tmap; - } - for( i=0 ; ib_error = 1; - return tmap; - } - for( i=0 ; ii_unit_nb ; i++ ) { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return tmap; - } - for( j=0 ; jp_unit_inf[i] ); } + + free( p_title_unit->p_unit_inf ); } - return tmap; + return 0; } - /***************************************************************************** - * ReadVTS : Parse vts*.ifo files to fill the Video Title Set structure. + * ReadCellInf : Fills the Cell Information structure. *****************************************************************************/ -static vts_t ReadVTS( ifo_t* p_ifo ) +static int ReadCellInf( ifo_t * p_ifo, cell_inf_t * p_cell_inf, off_t i_pos ) { - vts_t vts; + u8 pi_buffer[DVD_LB_SIZE]; + u8 * p_current; + off_t i_start; + int i; - vts.i_pos = p_ifo->i_pos; + p_current = FillBuffer( p_ifo, pi_buffer, i_pos ); + i_start = p_ifo->i_pos; +//fprintf( stderr, "CELL ADD\n" ); - vts.mat = ReadVTSInfMat( p_ifo ); - if( vts.mat.i_ptt_srpt_ssector ) - { - p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + - vts.mat.i_ptt_srpt_ssector *DVD_LB_SIZE, - SEEK_SET ); - vts.ptt_srpt = ReadVTSTitlePointer( p_ifo ); - } - if( vts.mat.i_m_pgci_ut_ssector ) - { - p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + - vts.mat.i_m_pgci_ut_ssector *DVD_LB_SIZE, - SEEK_SET ); - vts.pgci_ut = ReadUnitTable( p_ifo ); - } - if( vts.mat.i_pgcit_ssector ) - { - p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + - vts.mat.i_pgcit_ssector *DVD_LB_SIZE, - SEEK_SET ); - vts.pgci_ti = ReadUnit( p_ifo ); - } - if( vts.mat.i_tmap_ti_ssector ) - { - p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + - vts.mat.i_tmap_ti_ssector *DVD_LB_SIZE, - SEEK_SET ); - vts.tmap_ti = ReadVTSTimeMap( p_ifo ); - } - if( vts.mat.i_m_c_adt_ssector ) - { - p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + - vts.mat.i_m_c_adt_ssector *DVD_LB_SIZE, - SEEK_SET ); - vts.m_c_adt = ReadCellInf( p_ifo ); - } - if( vts.mat.i_m_vobu_admap_ssector ) - { - p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + - vts.mat.i_m_vobu_admap_ssector *DVD_LB_SIZE, - SEEK_SET ); - vts.m_vobu_admap = ReadMap( p_ifo ); - } - if( vts.mat.i_c_adt_ssector ) + p_cell_inf->i_vob_nb = ReadWord( p_ifo, pi_buffer, &p_current ); + DumpBits( p_ifo, pi_buffer, &p_current, 2 ); + p_cell_inf->i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current ); + + p_cell_inf->i_cell_nb = (p_cell_inf->i_end_byte/* - 7*/) / sizeof(cell_map_t); + +//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 ); + + p_cell_inf->p_cell_map = + malloc( p_cell_inf->i_cell_nb *sizeof(cell_map_t) ); + if( p_cell_inf->p_cell_map == NULL ) { - p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + - vts.mat.i_c_adt_ssector *DVD_LB_SIZE, - SEEK_SET ); - vts.c_adt = ReadCellInf( p_ifo ); + intf_ErrMsg( "ifo error: out of memory in ReadCellInf" ); + return -1; } - if( vts.mat.i_vobu_admap_ssector ) + + for( i = 0 ; i < p_cell_inf->i_cell_nb ; i++ ) { - p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + - vts.mat.i_vobu_admap_ssector *DVD_LB_SIZE, - SEEK_SET ); - vts.vobu_admap = ReadMap( p_ifo ); + p_cell_inf->p_cell_map[i].i_vob_id = ReadWord( p_ifo, pi_buffer, &p_current ); + p_cell_inf->p_cell_map[i].i_cell_id = ReadByte( p_ifo, pi_buffer, &p_current ); + DumpBits( p_ifo, pi_buffer, &p_current, 1 ); + p_cell_inf->p_cell_map[i].i_start_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); +// fprintf(stderr, "sector[%d] %d (%lld)\n", i,ntohl(*(u32*)(p_current)), p_ifo->i_pos); + p_cell_inf->p_cell_map[i].i_end_sector = ReadDouble( p_ifo, pi_buffer, &p_current ); } - - return vts; + + return 0; } -/* - * DVD Information Management - */ +/***************************************************************************** + * FreeCellInf : frees structures allocated by ReadCellInf + *****************************************************************************/ +static int FreeCellInf( cell_inf_t * p_cell_inf ) +{ + free( p_cell_inf->p_cell_map ); + + return 0; +} /***************************************************************************** - * IfoRead : Function that fills structure and calls specified functions - * to do it. + * ReadVobuMap : Fills the VOBU Map structure. *****************************************************************************/ -void IfoRead( ifo_t* p_ifo ) +static int ReadVobuMap( ifo_t * p_ifo, vobu_map_t * p_vobu_map, off_t i_pos ) { - int i; - off_t i_off; + u8 pi_buffer[DVD_LB_SIZE]; + u8 * p_current; + off_t i_start; + int i, i_max; + + p_current = FillBuffer( p_ifo, pi_buffer, i_pos ); + i_start = p_ifo->i_pos; +//fprintf( stderr, "VOBU ADMAP\n" ); - /* Video Manager Initialization */ - intf_WarnMsg( 2, "ifo: initializing VMG" ); - p_ifo->vmg = ReadVMG( p_ifo ); + p_vobu_map->i_end_byte = ReadDouble( p_ifo, pi_buffer, &p_current ); + i_max = ( i_start + p_vobu_map->i_end_byte + 1 - p_ifo->i_pos ) + / sizeof(u32); - /* Video Title Sets initialization */ - p_ifo->p_vts = malloc( p_ifo->vmg.mat.i_tts_nb *sizeof(vts_t) ); - if( p_ifo->p_vts == NULL ) + p_vobu_map->pi_vobu_start_sector = malloc( i_max *sizeof(u32) ); + if( p_vobu_map->pi_vobu_start_sector == NULL ) { - intf_ErrMsg( "Out of memory" ); - p_ifo->b_error = 1; - return; + intf_ErrMsg( "ifo error: out of memory in ReadVobuMap" ); + return -1; } - for( i=0 ; ivmg.mat.i_tts_nb ; i++ ) + + for( i = 0 ; i < i_max ; i++ ) { + p_vobu_map->pi_vobu_start_sector[i] = ReadDouble( p_ifo, pi_buffer, &p_current ); + } - intf_WarnMsg( 2, "ifo: initializing VTS %d", i+1 ); + return 0; +} - i_off = (off_t)(p_ifo->vmg.ptt_srpt.p_tts[i].i_ssector) *DVD_LB_SIZE; - p_ifo->i_pos = lseek( p_ifo->i_fd, i_off, SEEK_SET ); -fprintf( stderr, "%lld\n" , p_ifo->i_pos ); +/***************************************************************************** + * FreeVobuMap: frees structures allocated by ReadVobuMap + *****************************************************************************/ +static int FreeVobuMap( vobu_map_t * p_vobu_map ) +{ + free( p_vobu_map->pi_vobu_start_sector ); - /* FIXME : use udf filesystem to avoid this */ - IfoFindVTS( p_ifo ); - p_ifo->p_vts[i] = ReadVTS( p_ifo ); - } - return; + return 0; } /* * IFO virtual machine : a set of commands that give the * interactive behaviour of the dvd */ -#if 1 +#if 0 #define OP_VAL_16(i) (ntoh16( com.data.pi_16[i])) #define OP_VAL_8(i) ((com.data.pi_8[i]))