Commit 83b13fcb authored by Stéphane Borel's avatar Stéphane Borel

Rewrite most functions in DVD plugin. Some old bugs might have been
solved in the operation. The plugin some be more readable now, and
should produce fewaer segfaults (I hope so :p)
parent 97d95892
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* dvd.h: thread structure of the DVD plugin * dvd.h: thread structure of the DVD plugin
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: dvd.h,v 1.1 2002/03/06 01:20:56 stef Exp $ * $Id: dvd.h,v 1.2 2002/03/08 22:58:12 stef Exp $
* *
* Author: Stéphane Borel <stef@via.ecp.fr> * Author: Stéphane Borel <stef@via.ecp.fr>
* *
...@@ -45,19 +45,19 @@ typedef struct thread_dvd_data_s ...@@ -45,19 +45,19 @@ typedef struct thread_dvd_data_s
int i_chapter_nb; int i_chapter_nb;
int i_chapter; int i_chapter;
boolean_t b_new_chapter;
int i_angle_nb; int i_angle_nb;
int i_angle; int i_angle;
int i_angle_cell; /* cell index in the current angle */
int i_cell; /* cell index in adress map */ int i_map_cell; /* cell index in adress map */
int i_prg_cell; /* cell index in program map */ int i_prg_cell; /* cell index in program map */
int i_angle_cell; /* cell index in the current angle */
int i_sector; int i_vts_start; /* offset to beginning of vts */
int i_end_sector; /* last sector of current cell */ int i_vts_lb; /* sector in vts */
int i_end_lb; /* last sector of current cell */
int i_title_start;
int i_start;
int i_size; int i_size;
/* Structure that contains all information of the DVD */ /* Structure that contains all information of the DVD */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* -dvd_udf to find files * -dvd_udf to find files
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: dvd_access.c,v 1.2 2002/03/06 12:26:35 stef Exp $ * $Id: dvd_access.c,v 1.3 2002/03/08 22:58:12 stef Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -104,6 +104,10 @@ void _M( access_getfunctions)( function_list_t * p_function_list ) ...@@ -104,6 +104,10 @@ void _M( access_getfunctions)( function_list_t * p_function_list )
* Data access functions * Data access functions
*/ */
#define DVDLB p_dvd->i_vts_start + p_dvd->i_vts_lb
#define DVDTell LB2OFF( p_dvd->i_vts_start + p_dvd->i_vts_lb ) \
- p_input->stream.p_selected_area->i_start
/***************************************************************************** /*****************************************************************************
* DVDOpen: open dvd * DVDOpen: open dvd
*****************************************************************************/ *****************************************************************************/
...@@ -221,15 +225,16 @@ static int DVDOpen( struct input_thread_s *p_input ) ...@@ -221,15 +225,16 @@ static int DVDOpen( struct input_thread_s *p_input )
p_area = p_input->stream.pp_areas[p_dvd->i_title]; p_area = p_input->stream.pp_areas[p_dvd->i_title];
p_dvd->i_chapter = p_dvd->i_chapter < p_area->i_part_nb ? p_dvd->i_chapter = p_dvd->i_chapter <= p_area->i_part_nb ?
p_dvd->i_chapter : 1; p_dvd->i_chapter : 1;
p_area->i_part = p_dvd->i_chapter; p_area->i_part = p_dvd->i_chapter;
p_dvd->b_new_chapter = 0;
p_dvd->i_audio_nb = 0; p_dvd->i_audio_nb = 0;
p_dvd->i_spu_nb = 0; p_dvd->i_spu_nb = 0;
/* set title, chapter, audio and subpic */ /* set title, chapter, audio and subpic */
if( DVDSetArea( p_input, p_area ) ) if( DVDSetArea( p_input, p_area ) < 0 )
{ {
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
return -1; return -1;
...@@ -276,7 +281,8 @@ static int DVDSetProgram( input_thread_t * p_input, ...@@ -276,7 +281,8 @@ static int DVDSetProgram( input_thread_t * p_input,
/* DVD is actually mono-program: we only need the current angle /* DVD is actually mono-program: we only need the current angle
* number, so copy the data between programs */ * number, so copy the data between programs */
memcpy( p_program, p_input->stream.p_selected_program, memcpy( p_program,
p_input->stream.p_selected_program,
sizeof(pgrm_descriptor_t) ); sizeof(pgrm_descriptor_t) );
p_program->i_number = i_angle; p_program->i_number = i_angle;
p_input->stream.p_selected_program = p_program; p_input->stream.p_selected_program = p_program;
...@@ -287,13 +293,15 @@ static int DVDSetProgram( input_thread_t * p_input, ...@@ -287,13 +293,15 @@ static int DVDSetProgram( input_thread_t * p_input,
{ {
if( ( p_program->i_number - p_dvd->i_angle ) < 0 ) if( ( p_program->i_number - p_dvd->i_angle ) < 0 )
{ {
p_dvd->i_cell = 0; /* we have to go backwards */
p_dvd->i_map_cell = 0;
} }
p_dvd->i_prg_cell += ( p_program->i_number - p_dvd->i_angle ); p_dvd->i_prg_cell += ( p_program->i_number - p_dvd->i_angle );
p_dvd->i_map_cell = CellPrg2Map( p_dvd );
p_dvd->i_map_cell += p_dvd->i_angle_cell;
p_dvd->i_vts_lb = CellStartSector( p_dvd );
p_dvd->i_end_lb = CellEndSector( p_dvd );
p_dvd->i_angle = p_program->i_number; p_dvd->i_angle = p_program->i_number;
DVDFindSector( p_dvd );
p_dvd->i_cell += p_dvd->i_angle_cell;
} }
else else
{ {
...@@ -313,12 +321,60 @@ static int DVDSetProgram( input_thread_t * p_input, ...@@ -313,12 +321,60 @@ static int DVDSetProgram( input_thread_t * p_input,
* Take care that i_title starts from 0 (vmg) and i_chapter start from 1. * Take care that i_title starts from 0 (vmg) and i_chapter start from 1.
* Note that you have to take the lock before entering here. * Note that you have to take the lock before entering here.
*****************************************************************************/ *****************************************************************************/
static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) #define vmg p_dvd->p_ifo->vmg
#define vts p_dvd->p_ifo->vts
static void DVDFlushStream( input_thread_t * p_input )
{
if( p_input->stream.pp_programs != NULL )
{
/* We don't use input_EndStream here since
* we keep area structures */
while( p_input->stream.i_es_number )
{
input_DelES( p_input, p_input->stream.pp_es[0] );
}
while( p_input->stream.i_pgrm_number )
{
input_DelProgram( p_input, p_input->stream.pp_programs[0] );
}
if( p_input->stream.pp_selected_es )
{
free( p_input->stream.pp_selected_es );
p_input->stream.pp_selected_es = NULL;
}
p_input->stream.i_selected_es_number = 0;
}
return;
}
static int DVDReadAngle( input_thread_t * p_input )
{ {
thread_dvd_data_t * p_dvd; thread_dvd_data_t * p_dvd;
int i_vts_title; int i_angle_nb;
int i; int i;
p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
i_angle_nb = vmg.title_inf.p_attr[p_dvd->i_title-1].i_angle_nb;
input_AddProgram( p_input, 1, sizeof( stream_ps_data_t ) );
p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
for( i = 1 ; i < i_angle_nb ; i++ )
{
input_AddProgram( p_input, i+1, 0 );
}
return i_angle_nb;
}
static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
{
thread_dvd_data_t * p_dvd;
p_dvd = (thread_dvd_data_t*)(p_input->p_access_data); p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
/* we can't use the interface slider until initilization is complete */ /* we can't use the interface slider until initilization is complete */
...@@ -326,34 +382,29 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -326,34 +382,29 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
if( p_area != p_input->stream.p_selected_area ) if( p_area != p_input->stream.p_selected_area )
{ {
int i_vts_title;
u32 i_start;
u32 i_size;
/* Reset the Chapter position of the old title */ /* Reset the Chapter position of the old title */
p_input->stream.p_selected_area->i_part = 0; p_input->stream.p_selected_area->i_part = 1;
p_input->stream.p_selected_area = p_area; p_input->stream.p_selected_area = p_area;
/* /*
* We have to load all title information * We have to load all title information
*/ */
/* Change the default area */
/* title number: it is not vts nb!, /* title number as it appears in the interface list */
* it is what appears in the interface list */
p_dvd->i_title = p_area->i_id; p_dvd->i_title = p_area->i_id;
p_dvd->p_ifo->i_title = p_dvd->i_title;
/* set number of chapters of current title */
p_dvd->i_chapter_nb = p_area->i_part_nb; p_dvd->i_chapter_nb = p_area->i_part_nb;
/* ifo vts */ if( IfoTitleSet( p_dvd->p_ifo, p_dvd->i_title ) < 0 )
if( IfoTitleSet( p_dvd->p_ifo ) < 0 )
{ {
intf_ErrMsg( "dvd error: fatal error in vts ifo" ); intf_ErrMsg( "dvd error: fatal error in vts ifo" );
free( p_dvd ); free( p_dvd );
p_input->b_error = 1;
return -1; return -1;
} }
#define vmg p_dvd->p_ifo->vmg
#define vts p_dvd->p_ifo->vts
/* title position inside the selected vts */ /* title position inside the selected vts */
i_vts_title = vmg.title_inf.p_attr[p_dvd->i_title-1].i_title_num; i_vts_title = vmg.title_inf.p_attr[p_dvd->i_title-1].i_title_num;
p_dvd->i_title_id = p_dvd->i_title_id =
...@@ -362,120 +413,66 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -362,120 +413,66 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
intf_WarnMsg( 3, "dvd: title %d vts_title %d pgc %d", intf_WarnMsg( 3, "dvd: title %d vts_title %d pgc %d",
p_dvd->i_title, i_vts_title, p_dvd->i_title_id ); p_dvd->i_title, i_vts_title, p_dvd->i_title_id );
/*
* Set selected title start and size
*/
/* title set offset XXX: convert to block values */ /* title set offset XXX: convert to block values */
p_dvd->i_title_start = p_dvd->i_vts_start =
vts.i_pos + vts.manager_inf.i_title_vob_start_sector; vts.i_pos + vts.manager_inf.i_title_vob_start_sector;
/* last video cell */ /* last cell */
p_dvd->i_cell = 0; intf_WarnMsg( 4, "prg_cell nb %d", vts.title_unit.p_title[p_dvd->i_title_id-1].title.i_cell_nb );
p_dvd->i_prg_cell = -1 + p_dvd->i_prg_cell = -1 +
vts.title_unit.p_title[p_dvd->i_title_id-1].title.i_cell_nb; vts.title_unit.p_title[p_dvd->i_title_id-1].title.i_cell_nb;
p_dvd->i_map_cell = 0;
p_dvd->i_map_cell = CellPrg2Map( p_dvd );
i_size = CellEndSector( p_dvd );
if( DVDFindCell( p_dvd ) < 0 ) /* first cell */
{ p_dvd->i_prg_cell = 0;
intf_ErrMsg( "dvd error: can't find title end" ); p_dvd->i_map_cell = 0;
p_input->b_error = 1; p_dvd->i_map_cell = CellPrg2Map ( p_dvd );
return -1; p_dvd->i_vts_lb = CellStartSector( p_dvd );
} p_dvd->i_end_lb = CellEndSector ( p_dvd );
/* temporary hack to fix size in some dvds */
if( p_dvd->i_cell >= vts.cell_inf.i_cell_nb )
{
p_dvd->i_cell = vts.cell_inf.i_cell_nb - 1;
}
p_dvd->i_sector = 0;
p_dvd->i_size = vts.cell_inf.p_cell_map[p_dvd->i_cell].i_end_sector;
if( DVDChapterSelect( p_dvd, 1 ) < 0 )
{
intf_ErrMsg( "dvd error: can't find first chapter" );
p_input->b_error = 1;
return -1;
}
/* Force libdvdcss to check its title key. /* Force libdvdcss to check its title key.
* It is only useful for title cracking method. Methods using the * It is only useful for title cracking method. Methods using the
* decrypted disc key are fast enough to check the key at each seek */ * decrypted disc key are fast enough to check the key at each seek */
if( ( i_start = dvdcss_seek( p_dvd->dvdhandle, DVDLB,
if( dvdcss_seek( p_dvd->dvdhandle, p_dvd->i_start, DVDCSS_SEEK_KEY ) ) < 0 )
DVDCSS_SEEK_KEY ) < 0 )
{ {
intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) ); intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
return -1; return -1;
} }
p_dvd->i_size -= p_dvd->i_sector + 1; i_size -= p_dvd->i_vts_lb + 1;
IfoPrintTitle( p_dvd );
/* Area definition */ /* Area definition */
p_input->stream.p_selected_area->i_start = LB2OFF( p_dvd->i_start ); p_input->stream.p_selected_area->i_start = LB2OFF( i_start );
p_input->stream.p_selected_area->i_size = LB2OFF( p_dvd->i_size ); p_input->stream.p_selected_area->i_size = LB2OFF( i_size );
/* /* Destroy obsolete ES by reinitializing programs */
* Destroy obsolete ES by reinitializing programs DVDFlushStream( p_input );
* and find all ES in title with ifo data
*/
if( p_input->stream.pp_programs != NULL )
{
/* We don't use input_EndStream here since
* we keep area structures */
while( p_input->stream.i_es_number )
{
input_DelES( p_input, p_input->stream.pp_es[0] );
}
while( p_input->stream.i_pgrm_number )
{
input_DelProgram( p_input, p_input->stream.pp_programs[0] );
}
if( p_input->stream.pp_selected_es )
{
free( p_input->stream.pp_selected_es );
p_input->stream.pp_selected_es = NULL;
}
p_input->stream.i_selected_es_number = 0;
}
/* /* Angle management: angles are handled through programs */
* Angle management: angles are handled through programs p_dvd->i_angle_nb = DVDReadAngle( p_input );
*/
p_dvd->i_angle_nb = vmg.title_inf.p_attr[p_dvd->i_title-1].i_angle_nb;
if( ( p_dvd->i_angle <= 0 ) || p_dvd->i_angle > p_dvd->i_angle_nb ) if( ( p_dvd->i_angle <= 0 ) || p_dvd->i_angle > p_dvd->i_angle_nb )
{ {
p_dvd->i_angle = 1; p_dvd->i_angle = 1;
} }
input_AddProgram( p_input, 1, sizeof( stream_ps_data_t ) );
p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
for( i = 1 ; i < p_dvd->i_angle_nb ; i++ )
{
input_AddProgram( p_input, i+1, 0 );
}
DVDSetProgram( p_input, DVDSetProgram( p_input,
p_input->stream.pp_programs[p_dvd->i_angle-1] ); p_input->stream.pp_programs[p_dvd->i_angle-1] );
intf_WarnMsg( 3, "dvd info: title start: %d size: %d",
i_start, i_size );
IfoPrintTitle( p_dvd );
/* No PSM to read in DVD mode, we already have all information */ /* No PSM to read in DVD mode, we already have all information */
p_input->stream.p_selected_program->b_is_ok = 1; p_input->stream.p_selected_program->b_is_ok = 1;
/* Find all ES in title with ifo data */
DVDReadVideo( p_input ); DVDReadVideo( p_input );
DVDReadAudio( p_input ); DVDReadAudio( p_input );
DVDReadSPU ( p_input );
DVDReadSPU( p_input );
/* FIXME: hack to check that the demuxer is ready, and set
* the decoders */
if( p_input->p_demux_module ) if( p_input->p_demux_module )
{ {
DVDLaunchDecoders( p_input ); DVDLaunchDecoders( p_input );
...@@ -486,38 +483,11 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -486,38 +483,11 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
{ {
p_area = p_input->stream.p_selected_area; p_area = p_input->stream.p_selected_area;
} }
#undef vts
#undef vmg
/*
* Chapter selection
*/
if( p_area->i_part != p_dvd->i_chapter )
{
if( ( p_area->i_part > 0 ) &&
( p_area->i_part <= p_area->i_part_nb ))
{
if( DVDChapterSelect( p_dvd, p_area->i_part ) < 0 )
{
intf_ErrMsg( "dvd error: can't set chapter in area" );
p_input->b_error = 1;
return -1;
}
p_input->stream.p_selected_area->i_part = p_dvd->i_chapter; /* Chapter selection */
p_input->stream.p_selected_area->i_tell = p_dvd->i_chapter = DVDSetChapter( p_dvd, p_area->i_part );
LB2OFF( p_dvd->i_start ) - p_area->i_start;
intf_WarnMsg( 4, "dvd info: chapter %d start at: %lld", p_input->stream.p_selected_area->i_tell = DVDTell;
p_area->i_part, p_area->i_tell );
}
else
{
p_area->i_part = 1;
p_dvd->i_chapter = 1;
}
}
/* warn interface that something has changed */ /* warn interface that something has changed */
p_input->stream.b_seekable = 1; p_input->stream.b_seekable = 1;
...@@ -525,6 +495,8 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -525,6 +495,8 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
return 0; return 0;
} }
#undef vts
#undef vmg
#define title \ #define title \
p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_title_id-1].title p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_title_id-1].title
...@@ -539,108 +511,49 @@ static int DVDRead( input_thread_t * p_input, ...@@ -539,108 +511,49 @@ static int DVDRead( input_thread_t * p_input,
byte_t * p_buffer, size_t i_count ) byte_t * p_buffer, size_t i_count )
{ {
thread_dvd_data_t * p_dvd; thread_dvd_data_t * p_dvd;
int i_block_once; int i_read;
int i_read_blocks;
int i_read_total;
int i_sector;
int i_blocks; int i_blocks;
boolean_t b_eoc; int i_block_once = 0;
p_dvd = (thread_dvd_data_t *)(p_input->p_access_data); p_dvd = (thread_dvd_data_t *)(p_input->p_access_data);
i_sector = 0; i_read = 0;
i_read_total = 0;
i_read_blocks = 0;
b_eoc = 0;
i_blocks = OFF2LB(i_count); i_blocks = OFF2LB(i_count);
while( i_blocks ) while( i_blocks )
{ {
i_sector = p_dvd->i_title_start + p_dvd->i_sector; if( ( i_block_once = __MIN( LbMaxOnce( p_dvd ), i_blocks ) ) <= 0 )
i_block_once = p_dvd->i_end_sector - p_dvd->i_sector + 1;
/* Get the position of the next cell if we're at cell end */
if( i_block_once <= 0 )
{
int i_angle;
p_dvd->i_cell++;
p_dvd->i_angle_cell++;
/* Find cell index in adress map */
if( DVDFindSector( p_dvd ) < 0 )
{ {
intf_ErrMsg( "dvd error: can't find next cell" ); /* EOT */
return 1; break;
} }
/* Position the fd pointer on the right address */ if( i_block_once != dvdcss_read( p_dvd->dvdhandle, p_buffer,
if( ( i_sector = dvdcss_seek( p_dvd->dvdhandle, i_block_once, DVDCSS_READ_DECRYPT ) )
p_dvd->i_title_start + p_dvd->i_sector,
DVDCSS_SEEK_MPEG ) ) < 0 )
{ {
intf_ErrMsg( "dvd error: %s",
dvdcss_error( p_dvd->dvdhandle ) );
return -1; return -1;
} }
/* update chapter : it will be easier when we have navigation i_blocks -= i_block_once;
* ES support */ i_read += i_block_once;
if( p_dvd->i_chapter < ( p_dvd->i_chapter_nb - 1 ) ) p_buffer += LB2OFF( i_block_once );
{
if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
{
i_angle = p_dvd->i_angle - 1;
}
else
{
i_angle = 0;
}
if( title.chapter_map.pi_start_cell[p_dvd->i_chapter] <=
( p_dvd->i_prg_cell - i_angle + 1 ) )
{
p_dvd->i_chapter++;
b_eoc = 1;
}
}
i_block_once = p_dvd->i_end_sector - p_dvd->i_sector + 1;
}
/* The number of blocks read is the max between the requested
* value and the leaving block in the cell */
if( i_block_once > i_blocks )
{
i_block_once = i_blocks;
}
/* Reads from DVD */
i_read_blocks = dvdcss_read( p_dvd->dvdhandle, p_buffer,
i_block_once, DVDCSS_READ_DECRYPT );
i_blocks -= i_read_blocks;
p_buffer += LB2OFF( i_read_blocks );
i_read_total += i_read_blocks;
/* Update global position */ /* Update global position */
p_dvd->i_sector += i_read_blocks; p_dvd->i_vts_lb += i_block_once;
} }
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.p_selected_area->i_tell = p_input->stream.p_selected_area->i_tell += LB2OFF( i_read );
LB2OFF( i_sector + i_read_total ) - if( p_dvd->b_new_chapter )
p_input->stream.p_selected_area->i_start;
if( b_eoc )
{ {
/* We modify i_part only at end of chapter not to erase
* some modification from the interface */
p_input->stream.p_selected_area->i_part = p_dvd->i_chapter; p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
p_dvd->b_new_chapter = 0;
} }
if( p_input->stream.p_selected_area->i_tell if( ( p_input->stream.p_selected_area->i_tell
>= p_input->stream.p_selected_area->i_size ) >= p_input->stream.p_selected_area->i_size )
|| ( i_block_once < 0 ) )
{ {
if( ( p_dvd->i_title + 1 ) >= p_input->stream.i_area_nb ) if( ( p_dvd->i_title + 1 ) >= p_input->stream.i_area_nb )
{ {
...@@ -657,7 +570,7 @@ static int DVDRead( input_thread_t * p_input, ...@@ -657,7 +570,7 @@ static int DVDRead( input_thread_t * p_input,
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
return LB2OFF( i_read_total ); return LB2OFF( i_read );
} }
/***************************************************************************** /*****************************************************************************
...@@ -670,101 +583,30 @@ static int DVDRead( input_thread_t * p_input, ...@@ -670,101 +583,30 @@ static int DVDRead( input_thread_t * p_input,
static void DVDSeek( input_thread_t * p_input, off_t i_off ) static void DVDSeek( input_thread_t * p_input, off_t i_off )
{ {
thread_dvd_data_t * p_dvd; thread_dvd_data_t * p_dvd;
int i_block;
int i_prg_cell;
int i_cell;
int i_chapter;
int i_angle;
p_dvd = ( thread_dvd_data_t * )(p_input->p_access_data); p_dvd = ( thread_dvd_data_t * )(p_input->p_access_data);
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
/* we have to take care of offset of beginning of title */ p_dvd->i_vts_lb = OFF2LB(i_off + p_input->stream.p_selected_area->i_start)
p_dvd->i_sector = OFF2LB(i_off + p_input->stream.p_selected_area->i_start) - p_dvd->i_vts_start;
- p_dvd->i_title_start;
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
i_prg_cell = 0; p_dvd->i_prg_cell = Lb2CellPrg( p_dvd );
i_chapter = 0; p_dvd->i_map_cell = Lb2CellMap( p_dvd );
/* parse vobu address map to find program cell */ if( CellIsInterleaved( p_dvd ) )
while( title.p_cell_play[i_prg_cell].i_end_sector < p_dvd->i_sector )
{ {
i_prg_cell++;
}
p_dvd->i_prg_cell = i_prg_cell;
if( DVDChooseAngle( p_dvd ) < 0 )
{
p_input->b_error = 1;
return;
}
p_dvd->i_cell = 0;
/* Find first title cell which is inside program cell */
if( DVDFindCell( p_dvd ) < 0 )
{
/* no following cell : we're at eof */
intf_ErrMsg( "dvd error: cell seeking failed" );
p_input->b_error = 1;
return;
}
i_cell = p_dvd->i_cell;
#define cell p_dvd->p_ifo->vts.cell_inf.p_cell_map[i_cell]
/* parse cell address map to find title cell containing sector */
while( cell.i_end_sector < p_dvd->i_sector )
{
i_cell++;
}
p_dvd->i_cell = i_cell;
/* if we're inside a multi-angle zone, we have to choose i_sector /* if we're inside a multi-angle zone, we have to choose i_sector
* in the current angle ; we can't do it all the time since cells * in the current angle ; we can't do it all the time since cells
* can be very wide out of such zones */ * can be very wide out of such zones */
if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 ) p_dvd->i_vts_lb = CellStartSector( p_dvd );
{
p_dvd->i_sector = __MAX(
cell.i_start_sector,
title.p_cell_play[p_dvd->i_prg_cell].i_start_sector );
}
p_dvd->i_end_sector = __MIN(
cell.i_end_sector,
title.p_cell_play[p_dvd->i_prg_cell].i_end_sector );
#undef cell
/* update chapter */
if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
{
i_angle = p_dvd->i_angle - 1;
}
else
{
i_angle = 0;
}
if( p_dvd->i_chapter_nb > 1 )
{
while( ( title.chapter_map.pi_start_cell[i_chapter] <=
( p_dvd->i_prg_cell - i_angle + 1 ) ) &&
( i_chapter < ( p_dvd->i_chapter_nb - 1 ) ) )
{
i_chapter++;
}
}
else
{
i_chapter = 1;
} }
p_dvd->i_chapter = i_chapter; p_dvd->i_end_lb = CellEndSector ( p_dvd );
p_dvd->i_chapter = CellPrg2Chapter( p_dvd );
if( ( i_block = dvdcss_seek( p_dvd->dvdhandle, if( dvdcss_seek( p_dvd->dvdhandle, DVDLB,
p_dvd->i_title_start + p_dvd->i_sector, DVDCSS_SEEK_MPEG ) < 0 )
DVDCSS_SEEK_MPEG ) ) < 0 )
{ {
intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) ); intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
p_input->b_error = 1; p_input->b_error = 1;
...@@ -773,12 +615,11 @@ static void DVDSeek( input_thread_t * p_input, off_t i_off ) ...@@ -773,12 +615,11 @@ static void DVDSeek( input_thread_t * p_input, off_t i_off )
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.p_selected_area->i_part = p_dvd->i_chapter; p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
p_input->stream.p_selected_area->i_tell = p_input->stream.p_selected_area->i_tell = DVDTell;
LB2OFF ( i_block ) - p_input->stream.p_selected_area->i_start;
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
intf_WarnMsg( 4, "Program Cell: %d Cell: %d Chapter: %d", intf_WarnMsg( 4, "Program Cell: %d Cell: %d Chapter: %d tell %lld",
p_dvd->i_prg_cell, p_dvd->i_cell, p_dvd->i_chapter ); p_dvd->i_prg_cell, p_dvd->i_map_cell, p_dvd->i_chapter, DVDTell );
return; return;
} }
......
/* dvd_es.c: functions to find and select ES /* dvd_es.c: functions to find and select ES
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: dvd_es.c,v 1.1 2002/03/06 01:20:56 stef Exp $ * $Id: dvd_es.c,v 1.2 2002/03/08 22:58:12 stef Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -70,27 +70,37 @@ void DVDLaunchDecoders( input_thread_t * p_input ); ...@@ -70,27 +70,37 @@ void DVDLaunchDecoders( input_thread_t * p_input );
#define vmg p_dvd->p_ifo->vmg #define vmg p_dvd->p_ifo->vmg
#define vts p_dvd->p_ifo->vts #define vts p_dvd->p_ifo->vts
#define ADDES( stream_id, private_id, type, cat, lang ) \
i_id = ( (private_id) << 8 ) | (stream_id); \
p_es = input_AddES( p_input, NULL, i_id, 0 ); \
p_es->i_stream_id = (stream_id); \
p_es->i_type = (type); \
p_es->i_cat = (cat); \
if( lang ) \
{ \
strcpy( p_es->psz_desc, DecodeLanguage( hton16( lang ) ) ); \
}
/***************************************************************************** /*****************************************************************************
* DVDReadVideo * DVDReadVideo: read video ES
*****************************************************************************/ *****************************************************************************/
void DVDReadVideo( input_thread_t * p_input ) void DVDReadVideo( input_thread_t * p_input )
{ {
thread_dvd_data_t * p_dvd; thread_dvd_data_t * p_dvd;
es_descriptor_t * p_es; es_descriptor_t * p_es;
int i_id;
p_dvd = (thread_dvd_data_t*)(p_input->p_access_data); p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
/* ES 0 -> video MPEG2 */ /* ES 0 -> video MPEG2 */
IfoPrintVideo( p_dvd ); IfoPrintVideo( p_dvd );
p_es = input_AddES( p_input, NULL, 0xe0, 0 ); ADDES( 0xe0, 0, MPEG2_VIDEO_ES, VIDEO_ES, 0 );
p_es->i_stream_id = 0xe0;
p_es->i_type = MPEG2_VIDEO_ES;
p_es->i_cat = VIDEO_ES;
} }
/***************************************************************************** /*****************************************************************************
* DVDReadAudio * DVDReadAudio: read audio ES
*****************************************************************************/ *****************************************************************************/
#define audio_status \ #define audio_status \
vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_audio_status[i-1] vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_audio_status[i-1]
...@@ -99,10 +109,12 @@ void DVDReadAudio( input_thread_t * p_input ) ...@@ -99,10 +109,12 @@ void DVDReadAudio( input_thread_t * p_input )
{ {
thread_dvd_data_t * p_dvd; thread_dvd_data_t * p_dvd;
es_descriptor_t * p_es; es_descriptor_t * p_es;
int i_lang;
int i_id; int i_id;
int i; int i;
p_dvd = (thread_dvd_data_t*)(p_input->p_access_data); p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
p_dvd->i_audio_nb = 0;
/* Audio ES, in the order they appear in .ifo */ /* Audio ES, in the order they appear in .ifo */
for( i = 1 ; i <= vts.manager_inf.i_audio_nb ; i++ ) for( i = 1 ; i <= vts.manager_inf.i_audio_nb ; i++ )
...@@ -113,44 +125,30 @@ void DVDReadAudio( input_thread_t * p_input ) ...@@ -113,44 +125,30 @@ void DVDReadAudio( input_thread_t * p_input )
if( audio_status.i_available ) if( audio_status.i_available )
{ {
p_dvd->i_audio_nb++; p_dvd->i_audio_nb++;
i_lang = vts.manager_inf.p_audio_attr[i-1].i_lang_code;
i_id = audio_status.i_position;
switch( vts.manager_inf.p_audio_attr[i-1].i_coding_mode ) switch( vts.manager_inf.p_audio_attr[i-1].i_coding_mode )
{ {
case 0x00: /* AC3 */ case 0x00: /* AC3 */
i_id = ( ( 0x80 + audio_status.i_position ) << 8 ) | 0xbd; ADDES( 0xbd, 0x80 + audio_status.i_position,
p_es = input_AddES( p_input, NULL, i_id, 0 ); AC3_AUDIO_ES, AUDIO_ES, i_lang );
p_es->i_stream_id = 0xbd;
p_es->i_type = AC3_AUDIO_ES;
p_es->b_audio = 1; p_es->b_audio = 1;
p_es->i_cat = AUDIO_ES;
strcpy( p_es->psz_desc, DecodeLanguage( hton16(
vts.manager_inf.p_audio_attr[i-1].i_lang_code ) ) );
strcat( p_es->psz_desc, " (ac3)" ); strcat( p_es->psz_desc, " (ac3)" );
break; break;
case 0x02: case 0x02:
case 0x03: /* MPEG audio */ case 0x03: /* MPEG audio */
i_id = 0xc0 + audio_status.i_position; ADDES( 0xc0 + audio_status.i_position, 0,
p_es = input_AddES( p_input, NULL, i_id, 0 ); MPEG2_AUDIO_ES, AUDIO_ES, i_lang );
p_es->i_stream_id = i_id;
p_es->i_type = MPEG2_AUDIO_ES;
p_es->b_audio = 1; p_es->b_audio = 1;
p_es->i_cat = AUDIO_ES;
strcpy( p_es->psz_desc, DecodeLanguage( hton16(
vts.manager_inf.p_audio_attr[i-1].i_lang_code ) ) );
strcat( p_es->psz_desc, " (mpeg)" ); strcat( p_es->psz_desc, " (mpeg)" );
break; break;
case 0x04: /* LPCM */ case 0x04: /* LPCM */
ADDES( 0xbd, 0xa0 + audio_status.i_position,
i_id = ( ( 0xa0 + audio_status.i_position ) << 8 ) | 0xbd; LPCM_AUDIO_ES, AUDIO_ES, i_lang );
p_es = input_AddES( p_input, NULL, i_id, 0 );
p_es->i_stream_id = 0xbd;
p_es->i_type = LPCM_AUDIO_ES;
p_es->b_audio = 1; p_es->b_audio = 1;
p_es->i_cat = AUDIO_ES;
strcpy( p_es->psz_desc, DecodeLanguage( hton16(
vts.manager_inf.p_audio_attr[i-1].i_lang_code ) ) );
strcat( p_es->psz_desc, " (lpcm)" ); strcat( p_es->psz_desc, " (lpcm)" );
break; break;
...@@ -170,7 +168,7 @@ void DVDReadAudio( input_thread_t * p_input ) ...@@ -170,7 +168,7 @@ void DVDReadAudio( input_thread_t * p_input )
#undef audio_status #undef audio_status
/***************************************************************************** /*****************************************************************************
* DVDReadSPU: Read subpictures ES * DVDReadSPU: read subpictures ES
*****************************************************************************/ *****************************************************************************/
#define spu_status \ #define spu_status \
vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_spu_status[i-1] vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_spu_status[i-1]
...@@ -183,6 +181,7 @@ void DVDReadSPU( input_thread_t * p_input ) ...@@ -183,6 +181,7 @@ void DVDReadSPU( input_thread_t * p_input )
int i; int i;
p_dvd = (thread_dvd_data_t*)(p_input->p_access_data); p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
p_dvd->i_spu_nb = 0;
for( i = 1 ; i <= vts.manager_inf.i_spu_nb; i++ ) for( i = 1 ; i <= vts.manager_inf.i_spu_nb; i++ )
{ {
...@@ -199,31 +198,24 @@ void DVDReadSPU( input_thread_t * p_input ) ...@@ -199,31 +198,24 @@ void DVDReadSPU( input_thread_t * p_input )
switch( vts.manager_inf.video_attr.i_perm_displ ) switch( vts.manager_inf.video_attr.i_perm_displ )
{ {
case 1: case 1:
i_id = ( ( 0x20 + spu_status.i_position_pan ) << 8 ) i_id = spu_status.i_position_pan;
| 0xbd;
break; break;
case 2: case 2:
i_id = ( ( 0x20 + spu_status.i_position_letter ) << 8 ) i_id = spu_status.i_position_letter;
| 0xbd;
break; break;
default: default:
i_id = ( ( 0x20 + spu_status.i_position_wide ) << 8 ) i_id = spu_status.i_position_wide;
| 0xbd;
break; break;
} }
} }
else else
{ {
/* 4:3 */ /* 4:3 */
i_id = ( ( 0x20 + spu_status.i_position_43 ) << 8 ) i_id = spu_status.i_position_43;
| 0xbd;
} }
p_es = input_AddES( p_input, NULL, i_id, 0 );
p_es->i_stream_id = 0xbd; ADDES( 0xbd, 0x20 + i_id, DVD_SPU_ES, SPU_ES,
p_es->i_type = DVD_SPU_ES; vts.manager_inf.p_spu_attr[i-1].i_lang_code );
p_es->i_cat = SPU_ES;
strcpy( p_es->psz_desc, DecodeLanguage( hton16(
vts.manager_inf.p_spu_attr[i-1].i_lang_code ) ) );
} }
} }
} }
...@@ -233,7 +225,7 @@ void DVDReadSPU( input_thread_t * p_input ) ...@@ -233,7 +225,7 @@ void DVDReadSPU( input_thread_t * p_input )
#undef vmg #undef vmg
/***************************************************************************** /*****************************************************************************
* DVDLaunchDecoders * DVDLaunchDecoders: select ES for video, audio and spu
*****************************************************************************/ *****************************************************************************/
void DVDLaunchDecoders( input_thread_t * p_input ) void DVDLaunchDecoders( input_thread_t * p_input )
{ {
...@@ -250,17 +242,16 @@ void DVDLaunchDecoders( input_thread_t * p_input ) ...@@ -250,17 +242,16 @@ void DVDLaunchDecoders( input_thread_t * p_input )
} }
/* Select audio stream */ /* Select audio stream */
if( p_main->b_audio ) if( p_main->b_audio && p_dvd->i_audio_nb > 0 )
{ {
/* For audio: first one if none or a not existing one specified */ /* For audio: first one if none or a not existing one specified */
i_audio = config_GetIntVariable( INPUT_CHANNEL_VAR ); i_audio = config_GetIntVariable( INPUT_CHANNEL_VAR );
if( i_audio < 0 || i_audio > p_dvd->i_audio_nb ) if( i_audio <= 0 || i_audio > p_dvd->i_audio_nb )
{ {
config_PutIntVariable( INPUT_CHANNEL_VAR, 1 ); config_PutIntVariable( INPUT_CHANNEL_VAR, 1 );
i_audio = 1; i_audio = 1;
} }
if( i_audio > 0 && p_dvd->i_audio_nb > 0 )
{
if( config_GetIntVariable( AOUT_SPDIF_VAR ) || if( config_GetIntVariable( AOUT_SPDIF_VAR ) ||
( config_GetIntVariable( INPUT_AUDIO_VAR ) == ( config_GetIntVariable( INPUT_AUDIO_VAR ) ==
REQUESTED_AC3 ) ) REQUESTED_AC3 ) )
...@@ -284,10 +275,9 @@ void DVDLaunchDecoders( input_thread_t * p_input ) ...@@ -284,10 +275,9 @@ void DVDLaunchDecoders( input_thread_t * p_input )
p_input->stream.pp_es[i_audio] ); p_input->stream.pp_es[i_audio] );
} }
} }
}
/* Select subtitle */ /* Select subtitle */
if( p_main->b_video ) if( p_main->b_video && p_dvd->i_spu_nb > 0 )
{ {
/* for spu, default is none */ /* for spu, default is none */
i_spu = config_GetIntVariable( INPUT_SUBTITLE_VAR ); i_spu = config_GetIntVariable( INPUT_SUBTITLE_VAR );
...@@ -296,7 +286,7 @@ void DVDLaunchDecoders( input_thread_t * p_input ) ...@@ -296,7 +286,7 @@ void DVDLaunchDecoders( input_thread_t * p_input )
config_PutIntVariable( INPUT_SUBTITLE_VAR, 0 ); config_PutIntVariable( INPUT_SUBTITLE_VAR, 0 );
i_spu = 0; i_spu = 0;
} }
if( i_spu > 0 && p_dvd->i_spu_nb > 0 ) if( i_spu > 0 )
{ {
i_spu += p_dvd->p_ifo->vts.manager_inf.i_audio_nb; i_spu += p_dvd->p_ifo->vts.manager_inf.i_audio_nb;
input_SelectES( p_input, p_input->stream.pp_es[i_spu] ); input_SelectES( p_input, p_input->stream.pp_es[i_spu] );
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* dvd_ifo.c: Functions for ifo parsing * dvd_ifo.c: Functions for ifo parsing
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: dvd_ifo.c,v 1.44 2002/03/06 01:20:56 stef Exp $ * $Id: dvd_ifo.c,v 1.45 2002/03/08 22:58:12 stef Exp $
* *
* Authors: Stphane Borel <stef@via.ecp.fr> * Authors: Stphane Borel <stef@via.ecp.fr>
* German Tischler <tanis@gaspode.franken.de> * German Tischler <tanis@gaspode.franken.de>
...@@ -438,7 +438,7 @@ int IfoInit( ifo_t * p_ifo ) ...@@ -438,7 +438,7 @@ int IfoInit( ifo_t * p_ifo )
/***************************************************************************** /*****************************************************************************
* IfoTitleSet: Parse vts*.ifo files to fill the Video Title Set structure. * IfoTitleSet: Parse vts*.ifo files to fill the Video Title Set structure.
*****************************************************************************/ *****************************************************************************/
int IfoTitleSet( ifo_t * p_ifo ) int IfoTitleSet( ifo_t * p_ifo, int i_title )
{ {
u8 p_buf[DVD_LB_SIZE]; u8 p_buf[DVD_LB_SIZE];
u8 * p_tmp; u8 * p_tmp;
...@@ -453,7 +453,7 @@ int IfoTitleSet( ifo_t * p_ifo ) ...@@ -453,7 +453,7 @@ int IfoTitleSet( ifo_t * p_ifo )
FreeTitleSet( &p_ifo->vts ); FreeTitleSet( &p_ifo->vts );
} }
i_off = p_ifo->vmg.title_inf.p_attr[p_ifo->i_title-1].i_start_sector i_off = p_ifo->vmg.title_inf.p_attr[i_title-1].i_start_sector
+ p_ifo->i_start; + p_ifo->i_start;
//fprintf(stderr, "offset: %d\n" , i_off ); //fprintf(stderr, "offset: %d\n" , i_off );
...@@ -748,8 +748,8 @@ int IfoTitleSet( ifo_t * p_ifo ) ...@@ -748,8 +748,8 @@ int IfoTitleSet( ifo_t * p_ifo )
} }
#undef MGINF #undef MGINF
intf_WarnMsg( 2, "ifo info: vts %d initialized", intf_WarnMsg( 4, "ifo info: vts %d initialized",
p_ifo->vmg.title_inf.p_attr[p_ifo->i_title-1].i_title_set_num ); p_ifo->vmg.title_inf.p_attr[i_title-1].i_title_set_num );
p_ifo->vts.b_initialized = 1; p_ifo->vts.b_initialized = 1;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* dvd_ifo.h: Structures for ifo parsing * dvd_ifo.h: Structures for ifo parsing
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: dvd_ifo.h,v 1.17 2001/06/12 22:14:44 sam Exp $ * $Id: dvd_ifo.h,v 1.18 2002/03/08 22:58:12 stef Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -543,7 +543,6 @@ typedef struct ifo_s ...@@ -543,7 +543,6 @@ typedef struct ifo_s
int i_pos; /* Position of stream pointer */ int i_pos; /* Position of stream pointer */
boolean_t b_error; /* Error Management */ boolean_t b_error; /* Error Management */
vmg_t vmg; /* Structure described in video_ts */ vmg_t vmg; /* Structure described in video_ts */
int i_title; /* Current title number */
vts_t vts; /* Vts ifo for current title set */ vts_t vts; /* Vts ifo for current title set */
/* Remap buffer for unaligned reads */ /* Remap buffer for unaligned reads */
...@@ -559,6 +558,6 @@ struct thread_dvd_data_s; ...@@ -559,6 +558,6 @@ struct thread_dvd_data_s;
int IfoCreate ( struct thread_dvd_data_s * ); int IfoCreate ( struct thread_dvd_data_s * );
int IfoInit ( struct ifo_s * ); int IfoInit ( struct ifo_s * );
int IfoTitleSet ( struct ifo_s * ); int IfoTitleSet ( struct ifo_s *, int );
void IfoDestroy ( struct ifo_s * ); void IfoDestroy ( struct ifo_s * );
/* dvd_seek.c: functions to navigate through DVD. /* dvd_seek.c: functions to navigate through DVD.
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: dvd_seek.c,v 1.1 2002/03/06 01:20:56 stef Exp $ * $Id: dvd_seek.c,v 1.2 2002/03/08 22:58:12 stef Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -64,159 +64,255 @@ ...@@ -64,159 +64,255 @@
p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_title_id-1].title p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_title_id-1].title
#define cell p_dvd->p_ifo->vts.cell_inf #define cell p_dvd->p_ifo->vts.cell_inf
/***************************************************************************** int CellIsInterleaved( thread_dvd_data_t * p_dvd )
* DVDFindCell: adjust the title cell index with the program cell {
*****************************************************************************/ return title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000;
int DVDFindCell( thread_dvd_data_t * p_dvd ) }
u32 CellPrg2Map( thread_dvd_data_t * p_dvd )
{ {
int i_cell; u32 i_cell;
int i_index;
i_cell = p_dvd->i_cell; i_cell = p_dvd->i_map_cell;
i_index = p_dvd->i_prg_cell;
if( i_cell >= cell.i_cell_nb ) if( i_cell >= cell.i_cell_nb )
{ {
return -1; return -1;
} }
while( ( ( title.p_cell_pos[i_index].i_vob_id != while( ( ( title.p_cell_pos[p_dvd->i_prg_cell].i_vob_id !=
cell.p_cell_map[i_cell].i_vob_id ) || cell.p_cell_map[i_cell].i_vob_id ) ||
( title.p_cell_pos[i_index].i_cell_id != ( title.p_cell_pos[p_dvd->i_prg_cell].i_cell_id !=
cell.p_cell_map[i_cell].i_cell_id ) ) && cell.p_cell_map[i_cell].i_cell_id ) ) &&
( i_cell < cell.i_cell_nb - 1 ) ) ( i_cell < cell.i_cell_nb ) )
{ {
i_cell++; i_cell++;
} }
/* if( i_cell >= cell.i_cell_nb )
intf_WarnMsg( 12, "FindCell: i_cell %d i_index %d found %d nb %d", {
p_dvd->i_cell, return -1;
p_dvd->i_prg_cell, }
i_cell,
cell.i_cell_nb );
*/
p_dvd->i_cell = i_cell; return i_cell;
}
return 0; u32 CellAngleOffset( thread_dvd_data_t * p_dvd, u32 i_prg_cell )
{
u32 i_cell_off;
/* basic handling of angles */
switch( ( ( title.p_cell_play[i_prg_cell].i_category & 0xf000 )
>> 12 ) )
{
/* we enter a muli-angle section */
case 0x5:
i_cell_off = p_dvd->i_angle - 1;
p_dvd->i_angle_cell = 0;
break;
/* we exit a multi-angle section */
case 0x9:
case 0xd:
i_cell_off = p_dvd->i_angle_nb - p_dvd->i_angle;
break;
default:
i_cell_off = 0;
}
return i_cell_off;
} }
#undef cell u32 CellStartSector( thread_dvd_data_t * p_dvd )
{
return __MAX( cell.p_cell_map[p_dvd->i_map_cell].i_start_sector,
title.p_cell_play[p_dvd->i_prg_cell].i_start_sector );
}
/***************************************************************************** u32 CellEndSector( thread_dvd_data_t * p_dvd )
* DVDFindSector: find cell index in adress map from index in
* information table program map and give corresponding sectors.
*****************************************************************************/
int DVDFindSector( thread_dvd_data_t * p_dvd )
{ {
return __MIN( cell.p_cell_map[p_dvd->i_map_cell].i_end_sector,
title.p_cell_play[p_dvd->i_prg_cell].i_end_sector );
}
u32 NextCellPrg( thread_dvd_data_t * p_dvd )
{
u32 i_cell = p_dvd->i_prg_cell;
if( p_dvd->i_sector > title.p_cell_play[p_dvd->i_prg_cell].i_end_sector ) if( p_dvd->i_vts_lb > title.p_cell_play[i_cell].i_end_sector )
{ {
p_dvd->i_prg_cell++; i_cell ++;
i_cell += CellAngleOffset( p_dvd, i_cell );
if( DVDChooseAngle( p_dvd ) < 0 ) if( i_cell >= title.i_cell_nb )
{ {
return -1; return -1;
} }
} }
if( DVDFindCell( p_dvd ) < 0 ) return i_cell;
}
u32 Lb2CellPrg( thread_dvd_data_t * p_dvd )
{
u32 i_cell = 0;
while( p_dvd->i_vts_lb > title.p_cell_play[i_cell].i_end_sector )
{
i_cell ++;
i_cell += CellAngleOffset( p_dvd, i_cell );
if( i_cell >= title.i_cell_nb )
{ {
intf_ErrMsg( "dvd error: can't find sector" );
return -1; return -1;
} }
}
/* Find start and end sectors of new cell */ return i_cell;
#if 1 }
p_dvd->i_sector = __MAX(
p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_start_sector, u32 Lb2CellMap( thread_dvd_data_t * p_dvd )
title.p_cell_play[p_dvd->i_prg_cell].i_start_sector ); {
p_dvd->i_end_sector = __MIN( u32 i_cell = 0;
p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_end_sector,
title.p_cell_play[p_dvd->i_prg_cell].i_end_sector );
#else
p_dvd->i_sector = title.p_cell_play[p_dvd->i_prg_cell].i_start_sector;
p_dvd->i_end_sector = title.p_cell_play[p_dvd->i_prg_cell].i_end_sector;
#endif
/* while( p_dvd->i_vts_lb > cell.p_cell_map[i_cell].i_end_sector )
intf_WarnMsg( 12, "cell: %d sector1: 0x%x end1: 0x%x\n" {
"index: %d sector2: 0x%x end2: 0x%x\n" i_cell ++;
"category: 0x%x ilvu end: 0x%x vobu start 0x%x",
p_dvd->i_cell,
p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_start_sector,
p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_end_sector,
p_dvd->i_prg_cell,
title.p_cell_play[p_dvd->i_prg_cell].i_start_sector,
title.p_cell_play[p_dvd->i_prg_cell].i_end_sector,
title.p_cell_play[p_dvd->i_prg_cell].i_category,
title.p_cell_play[p_dvd->i_prg_cell].i_first_ilvu_vobu_esector,
title.p_cell_play[p_dvd->i_prg_cell].i_last_vobu_start_sector );
*/
return 0; if( i_cell >= cell.i_cell_nb )
{
return -1;
}
}
return i_cell;
} }
/***************************************************************************** u32 LbMaxOnce( thread_dvd_data_t * p_dvd )
* DVDChapterSelect: find the cell corresponding to requested chapter
*****************************************************************************/
int DVDChapterSelect( thread_dvd_data_t * p_dvd, int i_chapter )
{ {
u32 i_block_once = p_dvd->i_end_lb - p_dvd->i_vts_lb + 1;
/* Find cell index in Program chain for current chapter */ /* Get the position of the next cell if we're at cell end */
p_dvd->i_prg_cell = title.chapter_map.pi_start_cell[i_chapter-1] - 1; if( i_block_once <= 0 )
p_dvd->i_cell = 0; {
p_dvd->i_sector = 0; p_dvd->i_map_cell++;
p_dvd->i_angle_cell++;
DVDChooseAngle( p_dvd ); if( ( p_dvd->i_prg_cell = NextCellPrg( p_dvd ) ) < 0 )
{
/* EOF */
return 0;
}
/* Search for cell_index in cell adress_table and initialize if( ( p_dvd->i_map_cell = CellPrg2Map( p_dvd ) ) < 0 )
* start sector */
if( DVDFindSector( p_dvd ) < 0 )
{ {
intf_ErrMsg( "dvd error: can't select chapter" ); return 0;
return -1;
} }
/* start is : beginning of vts vobs + offset to vob x */ p_dvd->i_vts_lb = CellStartSector( p_dvd );
p_dvd->i_start = p_dvd->i_title_start + p_dvd->i_sector; p_dvd->i_end_lb = CellEndSector( p_dvd );
/* Position the fd pointer on the right address */ /* Position the fd pointer on the right address */
if( ( p_dvd->i_start = dvdcss_seek( p_dvd->dvdhandle, if( ( dvdcss_seek( p_dvd->dvdhandle,
p_dvd->i_start, p_dvd->i_vts_start + p_dvd->i_vts_lb,
DVDCSS_SEEK_MPEG ) ) < 0 ) DVDCSS_SEEK_MPEG ) ) < 0 )
{ {
intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) ); intf_ErrMsg( "dvd error: %s",
return -1; dvdcss_error( p_dvd->dvdhandle ) );
return 0;
} }
p_dvd->i_chapter = i_chapter; p_dvd->i_chapter = NextChapter( p_dvd );
return 0;
i_block_once = p_dvd->i_end_lb - p_dvd->i_vts_lb + 1;
}
return i_block_once;
} }
/*****************************************************************************
* DVDChooseAngle: select the cell corresponding to the selected angle int CellPrg2Chapter( thread_dvd_data_t * p_dvd )
*****************************************************************************/
int DVDChooseAngle( thread_dvd_data_t * p_dvd )
{ {
/* basic handling of angles */ int i_chapter = 1;
switch( ( ( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 ) int i_cell = p_dvd->i_prg_cell;
>> 12 ) )
if( CellIsInterleaved( p_dvd ) )
{ {
/* we enter a muli-angle section */ i_cell -= (p_dvd->i_angle - 1);
case 0x5: }
p_dvd->i_prg_cell += p_dvd->i_angle - 1;
p_dvd->i_angle_cell = 0; while( title.chapter_map.pi_start_cell[i_chapter] <= i_cell+1 )
break; {
/* we exit a multi-angle section */ i_chapter ++;
case 0x9: if( i_chapter >= p_dvd->i_chapter_nb )
case 0xd: {
p_dvd->i_prg_cell += p_dvd->i_angle_nb - p_dvd->i_angle; return p_dvd->i_chapter_nb;
break; }
} }
return i_chapter;
}
int NextChapter( thread_dvd_data_t * p_dvd )
{
int i_cell = p_dvd->i_prg_cell;
if( CellIsInterleaved( p_dvd ) )
{
i_cell -= (p_dvd->i_angle - 1);
}
if( title.chapter_map.pi_start_cell[p_dvd->i_chapter] <= i_cell+1 )
{
p_dvd->i_chapter++;
if( p_dvd->i_chapter >= p_dvd->i_chapter_nb )
{
return 0; return 0;
}
p_dvd->b_new_chapter = 1;
return p_dvd->i_chapter;
}
return p_dvd->i_chapter;
}
int DVDSetChapter( thread_dvd_data_t * p_dvd, int i_chapter )
{
if( i_chapter <= 0 || i_chapter > p_dvd->i_chapter_nb )
{
i_chapter = 1;
}
if( p_dvd->i_chapter != i_chapter )
{
/* Find cell index in Program chain for current chapter */
p_dvd->i_prg_cell = title.chapter_map.pi_start_cell[i_chapter-1] - 1;
p_dvd->i_prg_cell += CellAngleOffset( p_dvd, p_dvd->i_prg_cell );
if( i_chapter < p_dvd->i_chapter )
{
p_dvd->i_map_cell = 0;
}
p_dvd->i_map_cell = CellPrg2Map( p_dvd );
p_dvd->i_vts_lb = CellStartSector( p_dvd );
p_dvd->i_end_lb = CellEndSector( p_dvd );
/* Position the fd pointer on the right address */
if( dvdcss_seek( p_dvd->dvdhandle,
p_dvd->i_vts_start + p_dvd->i_vts_lb,
DVDCSS_SEEK_MPEG ) < 0 )
{
intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
return -1;
}
intf_WarnMsg( 4, "dvd info: chapter %d prg_cell %d map_cell %d",
i_chapter, p_dvd->i_prg_cell, p_dvd->i_map_cell );
}
return i_chapter;
} }
#undef cell
#undef title #undef title
/* dvd_seek.h: DVD access plugin. /* dvd_seek.h: DVD access plugin.
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: dvd_seek.h,v 1.1 2002/03/06 01:20:56 stef Exp $ * $Id: dvd_seek.h,v 1.2 2002/03/08 22:58:12 stef Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -20,7 +20,18 @@ ...@@ -20,7 +20,18 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ *****************************************************************************/
int DVDChooseAngle( thread_dvd_data_t * ); int CellIsInterleaved( thread_dvd_data_t * );
int DVDFindCell( thread_dvd_data_t * ); u32 CellAngleOffset ( thread_dvd_data_t *, u32 );
int DVDFindSector( thread_dvd_data_t * ); u32 CellPrg2Map ( thread_dvd_data_t * );
int DVDChapterSelect( thread_dvd_data_t *, int ); u32 CellStartSector ( thread_dvd_data_t * );
u32 CellEndSector ( thread_dvd_data_t * );
u32 NextCellPrg ( thread_dvd_data_t * );
u32 Lb2CellPrg ( thread_dvd_data_t * );
u32 Lb2CellMap ( thread_dvd_data_t * );
u32 LbMaxOnce ( thread_dvd_data_t * );
int CellPrg2Chapter ( thread_dvd_data_t * );
int NextChapter ( thread_dvd_data_t * );
int DVDSetChapter ( thread_dvd_data_t *, int );
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* found in .ifo. * found in .ifo.
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: dvd_summary.c,v 1.14 2002/03/06 01:20:56 stef Exp $ * $Id: dvd_summary.c,v 1.15 2002/03/08 22:58:12 stef Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -68,13 +68,11 @@ ...@@ -68,13 +68,11 @@
****************************************************************************/ ****************************************************************************/
void IfoPrintTitle( thread_dvd_data_t * p_dvd ) void IfoPrintTitle( thread_dvd_data_t * p_dvd )
{ {
intf_WarnMsg( 5, "dvd info: title %d, %d chapter%s, %d angle%s, " intf_WarnMsg( 5, "dvd info: title %d, %d chapter%s, %d angle%s",
"vobstart at %d blocks, stream size %d blocks",
p_dvd->i_title, p_dvd->i_chapter_nb, p_dvd->i_title, p_dvd->i_chapter_nb,
(p_dvd->i_chapter_nb == 1) ? "" : "s", (p_dvd->i_chapter_nb == 1) ? "" : "s",
p_dvd->i_angle_nb, p_dvd->i_angle_nb,
(p_dvd->i_angle_nb == 1) ? "" : "s", (p_dvd->i_angle_nb == 1) ? "" : "s" );
p_dvd->i_start, p_dvd->i_size );
} }
/**************************************************************************** /****************************************************************************
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment