* dvd_ifo.c: Functions for ifo parsing
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: dvd_ifo.c,v 1.3 2001/02/08 17:44:12 massiot Exp $
+ * $Id: dvd_ifo.c,v 1.22 2001/04/15 21:17:50 stef Exp $
*
* Author: Stéphane Borel <stef@via.ecp.fr>
*
+ * based on:
+ * - libifo by Thomas Mirlacher <dent@cosy.sbg.ac.at>
+ * - IFO structure documentation by Thomas Mirlacher, Björn Englund,
+ * Håkan Hjort
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
/*****************************************************************************
* Preamble
*****************************************************************************/
+#include "defs.h"
+#include "config.h"
+
#include <stdio.h>
+#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include "intf_msg.h"
#include "dvd_ifo.h"
+#include "dvd_udf.h"
+#include "dvd_css.h"
#include "input_dvd.h"
/*
- * 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 ; j<p_ifo->vmg.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 ; i<p_ifo->p_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 ; i<p_ifo->p_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;
+
+ return i_ret;
+}
- /* 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 ; i<p_ifo->vmg.pgci_ut.i_lu_nb ; i++ )
+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)->i_v0), \
- (int)((p_com)->i_v2), \
- (int)((p_com)->i_v4) ); */ \
- 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;
+
+ /* find the start sector of video information on the dvd */
+ i_lba = UDFFindFile( p_ifo->i_fd, "/VIDEO_TS/VIDEO_TS.IFO");
+
+ 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++ )
+ {
+ i_temp = ReadQuad( p_ifo, pi_buffer, &p_current );
+ }
+ 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++ )
+ {
+ ReadBits( p_ifo, pi_buffer, &p_current, (u8*)(&i_temp), 6 );
+ /* FIXME : take care of endianness */
+ }
-//fprintf( stderr, "PGC\n" );
+ /*
+ * 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 )
+ {
+ return -1;
+ }
- 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++ )
+ /*
+ * fills the title information structure.
+ */
+#define title_inf p_ifo->vmg.title_inf
+ if( manager_inf.i_title_inf_start_sector )
{
- GETS( &pgc.pi_audio_status[i] );
+ 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 );
+ }
}
- for( i=0 ; i<32 ; i++ )
+ else
{
- GETL( &pgc.pi_subpic_status[i] );
+ title_inf.p_attr = NULL;
}
- 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++ )
+#undef title_inf
+
+ /*
+ * fills the title unit structure.
+ */
+ if( manager_inf.i_title_unit_start_sector )
{
- GETL( &pgc.pi_yuv_color[i] );
- /* FIXME : We have to erase the extra bit */
+ 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;
+ }
}
- 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 ; i<pgc.com_tab.i_pre_com_nb ; i++ )
+
+ /*
+ * 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 )
+ {
+ intf_ErrMsg( "ifo erro: out of memory in IfoInit" );
+ return -1;
+ }
+
+ for( i = 0 ; i < vts_inf.i_vts_nb ; i++ )
{
- 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 )
+ 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 ; i<pgc.com_tab.i_post_com_nb ; i++ )
+ DumpBits( p_ifo, pi_buffer, &p_current, 17 );
+ vts_inf.p_vts_attr[i].i_vts_menu_spu_nb = ReadByte( p_ifo, pi_buffer, &p_current );
+//fprintf( stderr, "m subp nb : %d\n", vts_inf.p_vts_attr[i].i_vts_menu_spu_nb );
+ for( j = 0 ; j < 28 ; j++ )
{
- GETCOMMAND( &pgc.com_tab.p_post_com[i] );
+ ReadBits( p_ifo, pi_buffer, &p_current, (u8*)(&i_temp), 6 );
+ /* FIXME : Fix endianness issue here */
}
- }
- if( pgc.com_tab.i_cell_com_nb )
- {
- pgc.com_tab.p_cell_com =
- malloc(pgc.com_tab.i_cell_com_nb *sizeof(ifo_command_t));
- if( pgc.com_tab.p_cell_com == NULL )
+ DumpBits( p_ifo, pi_buffer, &p_current, 2 );
+ // GETS( &vts_inf.p_vts_attr[i].vtstt_video_vts_inf );
+DumpBits( p_ifo, pi_buffer, &p_current, 2 );
+ DumpBits( p_ifo, pi_buffer, &p_current, 1 );
+ vts_inf.p_vts_attr[i].i_vts_title_audio_nb =
+ ReadDouble( p_ifo, pi_buffer, &p_current );
+//fprintf( stderr, "tt audio nb : %d\n", vts_inf.p_vts_attr[i].i_vts_title_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 ; i<pgc.com_tab.i_cell_com_nb ; i++ )
+ DumpBits( p_ifo, pi_buffer, &p_current, 17 );
+ vts_inf.p_vts_attr[i].i_vts_title_spu_nb = ReadByte( p_ifo, pi_buffer, &p_current );
+//fprintf( stderr, "tt subp nb : %d\n", vts_inf.p_vts_attr[i].i_vts_title_spu_nb );
+ for( j=0 ; j<28/*vts_inf.p_vts_vts_inf[i].i_vtstt_subpic_nb*/ ; j++ )
{
- GETCOMMAND( &pgc.com_tab.p_cell_com[i] );
+ ReadBits( p_ifo, pi_buffer, &p_current, (u8*)(&i_temp), 6 );
+ /* FIXME : Fix endianness issue here */
}
}
}
- /* Parsing of pgc_prg_map_t */
- if( pgc.i_prg_map_sbyte )
+#undef vts_inf
+
+ /*
+ * global cell map.
+ */
+ if( manager_inf.i_cell_inf_start_sector )
{
- p_ifo->i_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 ; i<pgc.i_cell_nb ; i++ )
+ if( ReadVobuMap( p_ifo, &p_ifo->vmg.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 ; i<pgc.i_cell_nb ; i++ )
- {
- GETS( &pgc.p_cell_pos_inf[i].i_vob_id );
- FLUSH( 1 );
- GETC( &pgc.p_cell_pos_inf[i].i_cell_id );
- }
- }
+#undef manager_inf
+
+ p_ifo->vts.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;
+
+ if( p_ifo->vts.b_initialized )
+ {
+ FreeTitleSet( &p_ifo->vts );
+ }
-//fprintf( stderr, "Unit\n" );
+ i_off =
+ (off_t)( p_ifo->vmg.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" );
- 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 )
+ 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++ )
{
- intf_ErrMsg( "Out of memory" );
- p_ifo->b_error = 1;
- return inf;
+ i_temp = ReadQuad( p_ifo, pi_buffer, &p_current );
}
- for( i=0 ; i<inf.i_srp_nb ; i++ )
+ 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++ )
{
- GETC( &inf.p_srp[i].i_pgc_cat_mask );
- GETC( &inf.p_srp[i].i_pgc_cat );
- GETS( &inf.p_srp[i].i_par_mask );
- GETL( &inf.p_srp[i].i_pgci_sbyte );
+ ReadBits( p_ifo, pi_buffer, &p_current, (u8*)(&i_temp), 6 );
+ /* FIXME : take care of endianness */
}
- for( i=0 ; i<inf.i_srp_nb ; i++ )
+ 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++ )
{
- p_ifo->i_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 );
- }
+ 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<manager_inf.i_spu_nb ; i++ )
+ {
+ ReadBits( p_ifo, pi_buffer, &p_current, (u8*)(&i_temp), 6 );
+ i_temp = hton64( i_temp ) >> 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;
+ }
+
+ /*
+ * 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 );
- return inf;
-}
+ 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;
+ }
-/*****************************************************************************
- * 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;
+ for( i = 0 ; i < title_inf.i_title_nb ; i++ )
+ {
+ title_inf.pi_start_byte[i] = ReadDouble( p_ifo, pi_buffer, &p_current );
+ }
-//fprintf( stderr, "Unit Table\n" );
+ /* 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;
+ }
- 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;
+ 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 ; i<pgci.i_lu_nb ; i++ )
+#undef title_inf
+
+ /*
+ * menu unit information
+ */
+ if( manager_inf.i_menu_unit_start_sector )
{
- GET( pgci.p_lu[i].ps_lang_code, 2 );
- FLUSH( 1 );
- GETC( &pgci.p_lu[i].i_existence_mask );
- GETL( &pgci.p_lu[i].i_lu_sbyte );
+ if( ReadTitleUnit( p_ifo, &p_ifo->vts.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 ; i<pgci.i_lu_nb ; i++ )
+
+ /*
+ * time map inforamtion
+ */
+#define time_inf p_ifo->vts.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;
- int i, i_max;
- off_t i_start = p_ifo->i_pos;
+//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 );
- i_max = ( i_start + c_adt.i_ebyte + 1 - p_ifo->i_pos ) / sizeof(cell_inf_t);
- c_adt.p_cell_inf = malloc( i_max *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<i_max ; 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 ; i<i_max ; i++ )
+ if( manager_inf.i_vobu_map_start_sector )
{
- GETL( &map.pi_vobu_ssector[i] );
+ if( ReadVobuMap( p_ifo, &p_ifo->vts.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 );
+
+ p_ifo->vts.b_initialized = 1;
- return map;
+ 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 );
+ }
+
+ free( p_vts->time_inf.p_time_map );
+ free( p_vts->time_inf.pi_start_byte );
+ }
-//fprintf( stderr, "PTR\n" );
+ if( p_vts->manager_inf.i_title_unit_start_sector )
+ {
+ FreeUnitInf( &p_vts->title_unit );
+ }
- 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_menu_unit_start_sector )
{
- intf_ErrMsg( "Out of memory" );
- p_ifo->b_error = 1;
- return ptr;
+ FreeTitleUnit( &p_vts->menu_unit );
}
- for( i=0 ; i<ptr.i_ttu_nb ; i++ )
+
+ if( p_vts->manager_inf.i_title_inf_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 );
+ free( p_vts->title_inf.pi_start_byte );
+ free( p_vts->title_inf.p_title_start );
}
- return ptr;
+ 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 ; i<par.i_country_nb ; i++ )
+
+ if( p_ifo->vmg.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 ; i<par.i_country_nb ; i++ )
+
+ /* free parental information structures */
+ if( p_ifo->vmg.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 )
+ for( j = 0 ; j < 8 ; j++ )
{
- intf_ErrMsg( "Out of memory" );
- p_ifo->b_error = 1;
- return par;
- }
- for( k=0 ; k<par.i_vts_nb ; k++ )
- {
- GETS( &par.p_ptl_mask[i].ppi_ptl_mask[j][k] );
+ free( p_ifo->vmg.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 );
+ }
+
+ 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 );
}
- return par;
+ 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 );
+
+ i_start = p_ifo->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 )
+//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 ; i<atrt.i_vts_nb ; i++ )
+ for( i = 0 ; i < 32 ; i++ )
{
- GETL( &atrt.pi_vts_atrt_sbyte[i] );
- }
- atrt.p_vts_atrt = malloc( atrt.i_vts_nb *sizeof(vts_atrt_t) );
- if( atrt.p_vts_atrt == NULL )
+ p_title->pi_subpic_status[i] = ReadDouble( p_ifo, pi_buffer, &p_current );
+ }
+ 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 ; i<atrt.i_vts_nb ; i++ )
+ p_title->i_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 ; i<p_title->command.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 ; i<p_title->command.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 ; i<mat.i_subpic_nb ; i++ )
+
+ for( i = 0 ; i < p_unit_inf->i_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 0;
+}
+
+/*****************************************************************************
+ * 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 mat;
+ return 0;
}
+
/*****************************************************************************
- * ReadVTSTitlePointer : Fills the Part Of Title Search Pointer structure.
+ * 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" );
-//fprintf( stderr, "PTR\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 );
- 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 )
+//fprintf(stderr, "Unit: nb %d end %d\n", p_title_unit->i_unit_nb, p_title_unit->i_end_byte );
+
+ 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 ; i<ptr.i_ttu_nb ; i++ )
+
+ for( i = 0 ; i < p_title_unit->i_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 ; i<ptr.i_ttu_nb ; i++ )
+
+ for( i = 0 ; i < p_title_unit->i_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 )
- {
- intf_ErrMsg( "Out of memory" );
- p_ifo->b_error = 1;
- return tmap;
- }
- for( i=0 ; i<tmap.i_nb ; i++ )
- {
- GETL( &tmap.pi_sbyte[i] );
- }
- tmap.p_tmap = malloc( tmap.i_nb *sizeof(tmap_t) );
- if( tmap.p_tmap == NULL )
+ if( p_title_unit->p_unit_inf != NULL )
{
- intf_ErrMsg( "Out of memory" );
- p_ifo->b_error = 1;
- return tmap;
- }
- for( i=0 ; i<tmap.i_nb ; i++ )
- {
- GETC( &tmap.p_tmap[i].i_time_unit );
- FLUSH( 1 );
- GETS( &tmap.p_tmap[i].i_entry_nb );
- tmap.p_tmap[i].pi_sector =
- malloc( tmap.p_tmap[i].i_entry_nb *sizeof(u32) );
- if( tmap.p_tmap[i].pi_sector == NULL )
- {
- intf_ErrMsg( "Out of memory" );
- p_ifo->b_error = 1;
- return tmap;
- }
- for( j=0 ; j<tmap.p_tmap[i].i_entry_nb ; j++ )
+ for( i = 0 ; i < p_title_unit->i_unit_nb ; i++ )
{
- GETL( &tmap.p_tmap[i].pi_sector[j] );
+ FreeUnitInf( &p_title_unit->p_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;
+
+ p_current = FillBuffer( p_ifo, pi_buffer, i_pos );
+ i_start = p_ifo->i_pos;
+//fprintf( stderr, "CELL ADD\n" );
- vts.i_pos = p_ifo->i_pos;
+ 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 );
- vts.mat = ReadVTSInfMat( p_ifo );
- if( vts.mat.i_ptt_srpt_ssector )
+ 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_ptt_srpt_ssector *DVD_LB_SIZE,
- SEEK_SET );
- vts.ptt_srpt = ReadVTSTitlePointer( p_ifo );
+ intf_ErrMsg( "ifo error: out of memory in ReadCellInf" );
+ return -1;
}
- if( vts.mat.i_m_pgci_ut_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_m_pgci_ut_ssector *DVD_LB_SIZE,
- SEEK_SET );
- vts.pgci_ut = ReadUnitTable( 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 );
}
- if( vts.mat.i_pgcit_ssector )
+
+ return 0;
+}
+
+/*****************************************************************************
+ * FreeCellInf : frees structures allocated by ReadCellInf
+ *****************************************************************************/
+static int FreeCellInf( cell_inf_t * p_cell_inf )
+{
+ free( p_cell_inf->p_cell_map );
+
+ return 0;
+}
+
+/*****************************************************************************
+ * ReadVobuMap : Fills the VOBU Map structure.
+ *****************************************************************************/
+static int ReadVobuMap( ifo_t * p_ifo, vobu_map_t * p_vobu_map, off_t i_pos )
+{
+ 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" );
+
+ 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);
+
+ p_vobu_map->pi_vobu_start_sector = malloc( i_max *sizeof(u32) );
+ if( p_vobu_map->pi_vobu_start_sector == NULL )
{
- 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 );
+ intf_ErrMsg( "ifo error: out of memory in ReadVobuMap" );
+ return -1;
}
- if( vts.mat.i_tmap_ti_ssector )
+
+ for( i = 0 ; i < i_max ; i++ )
{
- 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 );
+ p_vobu_map->pi_vobu_start_sector[i] = ReadDouble( p_ifo, pi_buffer, &p_current );
}
- if( vts.mat.i_m_c_adt_ssector )
+
+ return 0;
+}
+
+/*****************************************************************************
+ * FreeVobuMap: frees structures allocated by ReadVobuMap
+ *****************************************************************************/
+static int FreeVobuMap( vobu_map_t * p_vobu_map )
+{
+ free( p_vobu_map->pi_vobu_start_sector );
+
+ return 0;
+}
+
+/*
+ * IFO virtual machine : a set of commands that give the
+ * interactive behaviour of the dvd
+ */
+#if 0
+
+#define OP_VAL_16(i) (ntoh16( com.data.pi_16[i]))
+#define OP_VAL_8(i) ((com.data.pi_8[i]))
+
+static char ifo_reg[][80]=
+{
+ "Menu_Language_Code",
+ "Audio_Stream_#",
+ "SubPicture_Stream_#",
+ "Angle_#",
+ "VTS_#",
+ "VTS_Title_#",
+ "PGC_#",
+ "PTT_#",
+ "Highlighted_Button_#",
+ "Nav_Timer",
+ "TimedPGC",
+ "Karaoke_audio_mixing_mode",
+ "Parental_mgmt_country_code",
+ "Parental_Level",
+ "Player_Video_Cfg",
+ "Player_Audio_Cfg",
+ "Audio_language_code_setting",
+ "Audio_language_extension_code",
+ "SPU_language_code_setting",
+ "SPU_language_extension_code",
+ "?Player_Regional_Code",
+ "Reserved_21",
+ "Reserved_22",
+ "Reserved_23"
+};
+
+static char * IfoMath( char val )
+{
+ static char math_op[][10] =
+ {
+ "none",
+ "=",
+ "<->", // swap
+ "+=",
+ "-=",
+ "*=",
+ "/=",
+ "%=",
+ "rnd", // rnd
+ "&=",
+ "|=",
+ "^=",
+ "??", // invalid
+ "??", // invalid
+ "??", // invalid
+ "??" // invalid
+ };
+
+ return (char *) math_op[val & 0x0f];
+}
+
+
+char ifo_cmp[][10] =
+{
+ "none",
+ "&&",
+ "==",
+ "!=",
+ ">=",
+ ">",
+ "<",
+ "<="
+};
+
+char ifo_parental[][10] =
+{
+ "0",
+ "G",
+ "2",
+ "PG",
+ "PG-13",
+ "5",
+ "R",
+ "NC-17"
+};
+
+char ifo_menu_id[][80] =
+{
+ "-0-",
+ "-1-",
+ "Title (VTS menu)",
+ "Root",
+ "Sub-Picture",
+ "Audio",
+ "Angle",
+ "Part of Title",
+};
+
+char * IfoMenuName( char index )
+{
+ return ifo_menu_id[index&0x07];
+}
+
+static void IfoRegister( u16 i_data, u8 i_direct)
+{
+ if( i_direct )
{
- 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( 0/*isalpha( i_data >> 8 & 0xff )*/ )
+ {
+ printf("'%c%c'", i_data>>8&0xff, i_data&0xff);
+ }
+ else
+ {
+ printf("0x%02x", i_data);
+ }
}
- if( vts.mat.i_m_vobu_admap_ssector )
+ else
{
- 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( i_data & 0x80 )
+ {
+ i_data &= 0x1f;
+
+ if( i_data > 0x17 )
+ {
+ printf("s[ILL]");
+ }
+ else
+ {
+ printf("s[%s]", ifo_reg[i_data]);
+ }
+ }
+ else
+ {
+ i_data &= 0x1f;
+
+ if( i_data > 0xf )
+ {
+ printf("r[ILL]");
+ }
+ else
+ {
+ printf("r[0x%02x]", i_data);
+ }
+ }
}
- if( vts.mat.i_c_adt_ssector )
+}
+
+static void IfoAdvanced( u8 *pi_code )
+{
+ u8 i_cmd = pi_code[0];
+
+ printf(" { ");
+
+ if( pi_code[1]>>2 )
{
- 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 );
+ printf( " Highlight button %d; ", pi_code[1]>>2 );
}
- if( vts.mat.i_vobu_admap_ssector )
+
+ if( i_cmd == 0xff )
{
- 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 );
+ printf( " Illegal " );
}
- return vts;
+ if( i_cmd == 0x00 )
+ {
+ printf( "ReSuME %d", pi_code[7] );
+ }
+ else if( ( i_cmd & 0x06) == 0x02 )
+ { // XX01Y
+ printf ("Link to %s cell ", ( i_cmd & 0x01 ) ? "prev" : "next");
+ }
+ else
+ {
+ printf( "advanced (0x%02x) ", i_cmd );
+ }
+ printf(" } ");
}
-/*
- * DVD Information Management
- */
+static void IfoJmp( ifo_command_t com )
+{
-/*****************************************************************************
- * IfoRead : Function that fills structure and calls specified functions
- * to do it.
- *****************************************************************************/
-void IfoRead( ifo_t* p_ifo )
+ printf ("jmp ");
+
+ switch( com.i_sub_cmd )
+ {
+ case 0x01:
+ printf( "Exit" );
+ break;
+ case 0x02:
+ printf( "VTS 0x%02x", OP_VAL_8(3) );
+ break;
+ case 0x03:
+ printf( "This VTS Title 0x%02x", OP_VAL_8(3) );
+ break;
+ case 0x05:
+ printf( "This VTS Title 0x%02x Part 0x%04x",
+ OP_VAL_8(3),
+ OP_VAL_8(0)<<8|OP_VAL_8(1));
+ break;
+ case 0x06:
+#if 0
+ printf ("in SystemSpace ");
+ switch (OP_VAL_8(3)>>4) {
+ case 0x00:
+ printf ("to play first PGC");
+ break;
+ case 0x01: {
+ printf ("to menu \"%s\"", decode_menuname (OP_VAL_8(3)));
+ }
+ break;
+ case 0x02:
+ printf ("to VTS 0x%02x and TTN 0x%02x", OP_VAL_8(1), OP_VAL_8(2));
+ break;
+ case 0x03:
+ printf ("to VMGM PGC number 0x%02x", OP_VAL_8(0)<<8 | OP_VAL_8(1));
+ break;
+ case 0x08:
+ printf ("vts 0x%02x lu 0x%02x menu \"%s\"", OP_VAL_8(2), OP_VAL_8(1), decode_menuname (OP_VAL_8(3)));
+ break;
+#else
+ switch( OP_VAL_8(3)>>6 )
+ {
+ case 0x00:
+ printf( "to play first PGC" );
+ break;
+ case 0x01:
+ printf( "to VMG title menu (?)" );
+ break;
+ case 0x02:
+ printf( "vts 0x%02x lu 0x%02x menu \"%s\"",
+ OP_VAL_8(2),
+ OP_VAL_8(1),
+ IfoMenuName( OP_VAL_8(3)&0xF ) );
+ break;
+ case 0x03:
+ printf( "vmg pgc 0x%04x (?)", ( OP_VAL_8(0)<<8) | OP_VAL_8(1) );
+ break;
+#endif
+ }
+ break;
+ case 0x08:
+#if 0
+ switch(OP_VAL_8(3)>>4) {
+ case 0x00:
+ printf ("system first pgc");
+ break;
+ case 0x01:
+ printf ("system title menu");
+ break;
+ case 0x02:
+ printf ("system menu \"%s\"", decode_menuname (OP_VAL_8(3)));
+ break;
+ case 0x03:
+ printf ("system vmg pgc %02x ????", OP_VAL_8(0)<<8|OP_VAL_8(1));
+ break;
+ case 0x08:
+ printf ("system lu 0x%02x menu \"%s\"", OP_VAL_8(2), decode_menuname (OP_VAL_8(3)));
+ break;
+ case 0x0c:
+ printf ("system vmg pgc 0x%02x", OP_VAL_8(0)<<8|OP_VAL_8(1));
+ break;
+ }
+#else
+ // OP_VAL_8(2) is number of cell
+ // it is processed BEFORE switch
+ // under some conditions, it is ignored
+ // I don't understand exactly what it means
+ printf( " ( spec cell 0x%02X ) ", OP_VAL_8(2) );
+
+ switch( OP_VAL_8(3)>>6 )
+ {
+ case 0:
+ printf( "to FP PGC" );
+ break;
+ case 1:
+ printf( "to VMG root menu (?)" );
+ break;
+ case 2:
+ printf( "to VTS menu \"%s\" (?)",
+ IfoMenuName(OP_VAL_8(3)&0xF) );
+ break;
+ case 3:
+ printf( "vmg pgc 0x%02x (?)", (OP_VAL_8(0)<<8)|OP_VAL_8(1) );
+ break;
+ }
+#endif
+ break;
+ }
+}
+
+static void IfoLnk( ifo_command_t com )
{
- int i;
- off_t i_off;
+ u16 i_button=OP_VAL_8(4)>>2;
+
+ printf ("lnk to ");
- p_ifo->vmg = ReadVMG( p_ifo );
- p_ifo->p_vts = malloc( p_ifo->vmg.mat.i_tts_nb *sizeof(vts_t) );
- if( p_ifo->p_vts == NULL )
+ switch( com.i_sub_cmd )
{
- intf_ErrMsg( "Out of memory" );
- p_ifo->b_error = 1;
+ case 0x01:
+ IfoAdvanced( &OP_VAL_8(4) );
+ break;
+
+ case 0x04:
+ printf( "PGC 0x%02x", OP_VAL_16(2) );
+ break;
+
+ case 0x05:
+ printf( "PTT 0x%02x", OP_VAL_16(2) );
+ break;
+
+ case 0x06:
+ printf( "Program 0x%02x this PGC", OP_VAL_8(5) );
+ break;
+
+ case 0x07:
+ printf( "Cell 0x%02x this PGC", OP_VAL_8(5) );
+ break;
+ default:
return;
}
- for( i=0 ; i<1/*p_ifo->vmg.mat.i_tts_nb*/ ; i++ )
+
+ if( i_button )
{
+ printf( ", Highlight 0x%02x", OP_VAL_8(4)>>2 );
+ }
+
+}
- intf_WarnMsg( 3, "######### VTS %d #############\n", i+1 );
+void IfoSetSystem( ifo_command_t com )
+{
+ switch( com.i_cmd )
+ {
+ case 1: {
+ int i;
- i_off = 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 );
- /* FIXME : use udf filesystem to avoid this */
- IfoFindVTS( p_ifo );
- p_ifo->p_vts[i] = ReadVTS( p_ifo );
+ for( i=1; i<=3; i++ )
+ {
+ if( OP_VAL_8(i)&0x80 )
+ {
+ if( com.i_direct )
+ {
+ printf ("s[%s] = 0x%02x;", ifo_reg[i], OP_VAL_8(i)&0xf);
+ }
+ else
+ {
+ printf ("s[%s] = r[0x%02x];", ifo_reg[i], OP_VAL_8(i)&0xf);
+ }
+ }
+ }
+#if 0
+ if(op->direct) {
+ if(OP_VAL_8(1]&0x80)
+ printf ("s[%s] = 0x%02x;", reg_name[1], OP_VAL_8(1]&0xf);
+ if(OP_VAL_8(2)&0x80)
+//DENT: lwhat about 0x7f here ???
+ printf ("s[%s] = 0x%02x;", reg_name[2], OP_VAL_8(2)&0x7f);
+ if(OP_VAL_8(3)&0x80)
+ printf ("s[%s] = 0x%02x;", reg_name[3], OP_VAL_8(3)&0xf);
+ } else {
+ if(OP_VAL_8(1)&0x80)
+ printf ("s[%s] = r[0x%02x];", reg_name[1], OP_VAL_8(1)&0xf);
+ if(OP_VAL_8(2)&0x80)
+ printf ("s[%s] = r[0x%02x];", reg_name[2], OP_VAL_8(2)&0xf);
+ if(OP_VAL_8(3)&0x80)
+ printf ("s[%s] = r[0x%02x];", reg_name[3], OP_VAL_8(3)&0xf);
+ }
+#endif
+ }
+ break;
+ case 2:
+ if( com.i_direct )
+ {
+ printf( "s[%s] = 0x%02x", ifo_reg[9], OP_VAL_16(0) );
+ }
+ else
+ {
+ printf( "s[%s] = r[0x%02x]", ifo_reg[9], OP_VAL_8(1)&0x0f );
+ }
+
+ printf( "s[%s] = (s[%s]&0x7FFF)|0x%02x",
+ ifo_reg[10], ifo_reg[10], OP_VAL_16(1)&0x8000);
+ break;
+ case 3:
+ if( com.i_direct )
+ {
+ printf( "r[0x%02x] = 0x%02x", OP_VAL_8(3)&0x0f, OP_VAL_16(0) );
+ }
+ else
+ {
+ printf ("r[r[0x%02x]] = r[0x%02x]",
+ OP_VAL_8(3)&0x0f, OP_VAL_8(1)&0x0f);
+ }
+ break;
+ case 4:
+ //actually only bits 00011100 00011100 are set
+ if( com.i_direct )
+ {
+ printf ("s[%s] = 0x%02x", ifo_reg[11], OP_VAL_16(1));
+ }
+ else
+ {
+ printf ("s[%s] = r[0x%02x]", ifo_reg[11], OP_VAL_8(3)&0x0f );
+ }
+ break;
+ case 6:
+ //actually,
+ //s[%s]=(r[%s]&0x3FF) | (0x%02x << 0xA);
+ //but it is way too ugly
+ if( com.i_direct )
+ {
+ printf( "s[%s] = 0x%02x", ifo_reg[8], OP_VAL_8(2)>>2 );
+ }
+ else
+ {
+ printf( "s[%s] = r[0x%02x]", ifo_reg[8], OP_VAL_8(3)&0x0f );
+ }
+ break;
+ default:
+ printf ("unknown");
}
- return;
}
-/*
- * IFO virtual machine : a set of commands that give the behaviour of the dvd
- */
-#if 0
+static void IfoSet( ifo_command_t com )
+{
+ IfoRegister( OP_VAL_16(0), 0 );
+ printf( " %s ", IfoMath( com.i_cmd ) );
+ IfoRegister( OP_VAL_16(1), com.i_direct );
+}
+
/*****************************************************************************
* CommandRead : translates the command strings in ifo into command
* structures.
switch( com.i_type )
{
- case 0: /* Goto */
- if( !pi_code[1] )
+ /* Goto */
+ case 0:
+ /* Main command */
+ if( !pi_code[1] )
+ {
+ printf( "NOP\n" );
+ }
+ else
+ {
+ if( com.i_cmp )
{
- fprintf( stderr, "NOP\n" );
+ printf ("if (r[0x%02x] %s ", OP_VAL_8(1)&0x0f,
+ ifo_cmp[com.i_cmp]);
+ IfoRegister (OP_VAL_16(1), com.i_dir_cmp);
+ printf (") ");
}
- else if( cmd.i_cmp )
+
+ /* Sub command */
+ switch( com.i_sub_cmd )
{
-
+ case 1:
+ printf( "goto Line 0x%02x", OP_VAL_16(2) );
+ break;
+
+ case 2:
+ printf( "stop VM" );
+ break;
+
+ case 3:
+ printf( "Set Parental Level To %s and goto Line 0x%02x",
+ ifo_parental[OP_VAL_8(4)&0x7],
+ OP_VAL_8(5) );
+ break;
+
+ default:
+ printf( "Illegal" );
+ break;
}
- break;
- case 1: /* Lnk */
- break;
- case 2: /* SetSystem */
- break;
- case 3: /* Set */
- break;
- case 4: /* */
- break;
- case 5: /* */
- break;
- case 6: /* */
- break;
- default:
- fprintf( stderr, "Unknown Command\n" );
- break;
- }
+ }
+ break;
- return;
-}
+ /* Lnk */
+ case 1:
+ /* Main command */
+ if( !pi_code[1] )
+ {
+ printf( "NOP\n" );
+ }
+ else
+ {
+ if( com.i_direct )
+ {
+ if( com.i_cmp )
+ {
+ printf( "if (r[0x%02x] %s ", OP_VAL_8(4)&0x0f,
+ ifo_cmp[com.i_cmp] );
+ IfoRegister( OP_VAL_8(5), 0 );
+ printf( ") " );
+ }
+
+ /* Sub command */
+ IfoJmp( com );
+ }
+ else
+ {
+ if( com.i_cmp )
+ {
+ printf( "if (r[0x%02x] %s ", OP_VAL_8(1)&0x0f,
+ ifo_cmp[com.i_cmp] );
+ IfoRegister( OP_VAL_16(1), com.i_dir_cmp );
+ printf( ") " );
+ }
+
+ /* Sub command */
+ IfoLnk( com );
+ }
+ }
+ break;
-/*****************************************************************************
- * IfoGoto
- *****************************************************************************/
-static void IfoGoto( ifo_command_t cmd )
-{
-
+ /* SetSystem */
+ case 2:
+ if( !pi_code[1] )
+ {
+ IfoSetSystem( com );
+ }
+ else if( com.i_cmp && !com.i_sub_cmd )
+ {
+ printf ("if (r[0x%02x] %s ", OP_VAL_8(4)&0x0f, ifo_cmp[com.i_cmp]);
+ IfoRegister( OP_VAL_8(5), 0 );
+ printf (") ");
+ IfoSetSystem( com );
+ }
+ else if( !com.i_cmp && com.i_sub_cmd )
+ {
+ printf( "if (" );
+ IfoSetSystem( com );
+ printf( ") " );
+ IfoLnk( com );
+ }
+ else
+ {
+ printf("nop");
+ }
+ break;
- return;
-}
+ /* Set */
+ case 3:
+ if( ! pi_code[1] )
+ {
+ IfoSet( com );
+ }
+ else if( com.i_cmp && !com.i_sub_cmd )
+ {
+ printf ("if (r[0x%02x] %s ", OP_VAL_8(0)&0x0f, ifo_cmp[com.i_cmp]);
+ IfoRegister( OP_VAL_16(2), com.i_dir_cmp );
+ printf (") ");
+ IfoSet( com );
+ }
+ else if( !com.i_cmp && com.i_sub_cmd )
+ {
+ printf ("if (");
+ IfoSet( com );
+ printf (") ");
+ IfoLnk( com );
+ }
+ else
+ {
+ printf( "nop" );
+ }
+ break;
+
+ /*
+ * math command on r[opcode[1]] and
+ * direct?be2me_16(OP_VAL_8(0)):reg[OP_VAL_8(1)] is executed
+ * ( unless command is swap; then r[opcode[1]] and r[OP_VAL_8(1)]
+ * are swapped )
+ * boolean operation cmp on r[opcode[1]] and
+ * dir_cmp?be2me_16(OP_VAL_8(1)[1]):reg[OP_VAL_8(3)] is executed
+ * on true result, buttons(c[6], c[7]) is called
+ * problem is 'what is buttons()'
+ */
+ case 4:
+ printf( "r[0x%X] ", pi_code[1] );
+ printf( " %s ", IfoMath( com.i_cmd ) );
+ if( com.i_cmd == 2 )
+ {
+ printf( "r[0x%X] ", OP_VAL_8(1) );
+ }
+ else
+ {
+ IfoRegister( OP_VAL_16(0), com.i_direct );
+ }
+ printf("; ");
+
+ printf( "if ( r[%d] %s ", pi_code[1], ifo_cmp[com.i_cmp] );
+ IfoRegister( OP_VAL_8(1), com.i_dir_cmp );
+ printf( " ) then {" );
+ IfoAdvanced( &OP_VAL_8(4) );
+ printf( "}" );
+ break;
+
+ /*
+ * opposite to case 4: boolean, math and buttons.
+ */
+ case 5:
+ case 6:
+ printf("if (");
+
+ if( !com.i_direct && com.i_dir_cmp )
+ {
+ printf( "0x%X", OP_VAL_16(1) );
+ }
+ else
+ {
+ IfoRegister( OP_VAL_8(3), 0 );
+ if( OP_VAL_8(3)&0x80 )
+ {
+ printf( "s[%s]", ifo_reg[OP_VAL_8(3)&0x1F] );
+ }
+ else
+ {
+ printf( "r[0x%X]", OP_VAL_8(3)&0x1F);
+ // 0x1F is either not a mistake,
+ // or Microsoft programmer's mistake!!!
+ }
+ }
+
+ printf( " %s r[0x%X] ", ifo_cmp[com.i_cmp],
+ com.i_direct ? OP_VAL_8(2) : OP_VAL_8(1) );
+ printf( " ) then {" );
+ printf( "r[0x%X] ", pi_code[1] & 0xF );
+ printf( " %s ", IfoMath( com.i_cmd ) );
+
+ if( com.i_cmd == 0x02 ) // swap
+ {
+ printf("r[0x%X] ", OP_VAL_8(0)&0x1F);
+ }
+ else
+ {
+ if( com.i_direct )
+ {
+ printf( "0x%X", OP_VAL_16(0) );
+ }
+ else
+ {
+ if( OP_VAL_8(0) & 0x80 )
+ {
+ printf("s[%s]", ifo_reg[OP_VAL_8(0) & 0x1F] );
+ }
+ else
+ {
+ printf("r[0x%X]", OP_VAL_8(0) & 0x1F );
+ }
+ }
+ }
+
+ printf("; ");
+ IfoAdvanced( &OP_VAL_8(4) );
+ printf("}");
+
+ break;
+
+ default:
+ printf( "Unknown Command\n" );
+ break;
+ }
-/*****************************************************************************
- * IfoLnk
- *****************************************************************************/
-static void IfoLnk( ifo_t* p_ifo )
-{
return;
}
/*****************************************************************************
- * IfoJmp
+ * CommandPrint : print in clear text (I hope so !) what a command does
*****************************************************************************/
-static void IfoJmp( ifo_t* p_ifo )
+void CommandPrint( ifo_t ifo )
{
return;
}
+
#endif