Commit 97c3185d authored by Stéphane Borel's avatar Stéphane Borel

 First serie of changes in DVD module for the forthcoming interface menus
 There is a new capability in input type modules for setting the
attributes of a new area. It is set to NULL for PS and TS plugins.
 It should be called for every title change, chapter change,
audio mode change or spu channel change.

But this part of code is not used at the moment, and is not completed
yet.
parent a6fe4de4
......@@ -2,7 +2,7 @@
* input.h: structures of the input not exported to other modules
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: input.h,v 1.29 2001/02/12 13:20:14 massiot Exp $
* $Id: input.h,v 1.30 2001/02/20 02:53:13 stef Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -57,6 +57,8 @@ struct pgrm_descriptor_s * input_FindProgram( struct input_thread_s *, u16 );
struct pgrm_descriptor_s * input_AddProgram ( struct input_thread_s *,
u16, size_t );
void input_DelProgram( struct input_thread_s *, struct pgrm_descriptor_s * );
struct input_area_s * input_AddArea( struct input_thread_s * );
void input_DelArea ( struct input_thread_s *, struct input_area_s * );
void input_DumpStream( struct input_thread_s * );
struct es_descriptor_s * input_FindES( struct input_thread_s *, u16 );
struct es_descriptor_s * input_AddES ( struct input_thread_s *,
......
......@@ -4,7 +4,7 @@
* control the pace of reading.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: input_ext-intf.h,v 1.22 2001/02/19 19:08:59 massiot Exp $
* $Id: input_ext-intf.h,v 1.23 2001/02/20 02:53:13 stef Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -50,6 +50,9 @@ typedef struct es_descriptor_s
boolean_t b_audio; /* is the stream an audio stream that
* will need to be discarded with
* fast forward and slow motion ? */
char psz_desc[20]; /* description of ES: audio language
* for instance ; NULL if not
* available */
/* Demultiplexer information */
void * p_demux_data;
......@@ -131,6 +134,33 @@ typedef struct pgrm_descriptor_s
#define SYNCHRO_START 1
#define SYNCHRO_REINIT 2
/*****************************************************************************
* input_area_t
*****************************************************************************
* Attributes for current area (title for DVD)
*****************************************************************************/
typedef struct input_area_s
{
/* selected area attributes */
int i_id; /* identificator for area */
off_t i_start; /* start offset of area */
off_t i_size; /* total size of the area
* (in arbitrary units) */
/* navigation parameters */
off_t i_tell; /* actual location in the area
* (in arbitrary units) */
off_t i_seek; /* next requested location
* (changed by the interface thread */
/* area subdivision */
int i_part_nb; /* number of parts (chapter for DVD)*/
int i_part; /* currently selected part */
/* offset to plugin related data */
off_t i_plugin_data;
} input_area_t;
/*****************************************************************************
* stream_descriptor_t
*****************************************************************************
......@@ -146,26 +176,14 @@ typedef struct stream_descriptor_s
/* Input method data */
boolean_t b_pace_control; /* can we read when we want ? */
boolean_t b_seekable; /* can we do lseek() ? */
/* if (b_seekable) : */
off_t i_size; /* total size of the file
* (in arbitrary units) */
off_t i_tell; /* actual location in the file
* (in arbitrary units) */
off_t i_seek; /* next requested location (changed
* by the interface thread */
int i_area_nb;
input_area_t ** pp_areas; /* list of areas in stream == offset
* interval with own properties */
u32 i_mux_rate; /* the rate we read the stream (in
* units of 50 bytes/s) ; 0 if undef */
/* For DVD streams: */
int i_title_nb;
int * pi_chapter; /* Number of chapter for each title */
char ** ppsz_audio; /* Audio language names */
char ** ppsz_spu; /* Sub-pictures names */
int i_title; /* selected title */
int i_chapter; /* selected chapter */
int i_audio; /* selected audio stream */
int i_spu; /* selected spu */
/* New status and rate requested by the interface */
int i_new_status, i_new_rate;
vlc_cond_t stream_wait; /* interface -> input in case of a
......
......@@ -81,6 +81,9 @@ typedef struct function_list_s
void ( * pf_close )( struct input_thread_s * );
void ( * pf_end ) ( struct input_thread_s * );
int ( * pf_set_area ) ( struct input_thread_s *,
int, int, int, int );
int ( * pf_read ) ( struct input_thread_s *,
struct data_packet_s *
pp_packets[] );
......
......@@ -2,7 +2,7 @@
* dvd_css.c: Functions for DVD authentification and unscrambling
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: dvd_css.c,v 1.10 2001/02/18 01:42:04 stef Exp $
* $Id: dvd_css.c,v 1.11 2001/02/20 02:53:13 stef Exp $
*
* Author: Stphane Borel <stef@via.ecp.fr>
*
......@@ -659,8 +659,8 @@ static void CSSCryptKey( int i_key_type, int i_varient,
static int CSSCracker( int i_start,
unsigned char * p_crypted,
unsigned char * p_decrypted,
DVD_key_t * p_sector_key,
DVD_key_t * p_key )
dvd_key_t * p_sector_key,
dvd_key_t * p_key )
{
unsigned char pi_buffer[10];
unsigned int i_t1, i_t2, i_t3, i_t4, i_t5, i_t6;
......@@ -1027,19 +1027,19 @@ css_t CSSInit( int i_fd )
}
/*****************************************************************************
* CSSGetKeys : get the title keys.
* CSSGetKey : get title key.
* The DVD should have been opened and authenticated before.
*****************************************************************************/
int CSSGetKeys( css_t * p_css )
int CSSGetKey( css_t * p_css )
{
/*
* Title key cracking method from Ethan Hawke,
* with Frank A. Stevenson algorithm.
* Does not use any player key table and ioctls.
*/
u8 pi_buf[0x800] ;
DVD_key_t key;
title_key_t p_title_key[10] ;
u8 pi_buf[0x800];
dvd_key_t pi_key;
title_key_t p_title_key[10];
off_t i_pos;
boolean_t b_encrypted;
boolean_t b_stop_scanning;
......@@ -1052,163 +1052,160 @@ int CSSGetKeys( css_t * p_css )
int i_highest;
int i,j,k;
for( i_title = 0 ; i_title < p_css->i_title_nb ; i_title++ )
{
/* Initialization for each title */
memset( p_title_key, 0, 10 );
memset( &key, 0, 10 );
b_encrypted = 0;
b_stop_scanning = 0;
i_registered_keys = 0 ;
i_total_keys_found = 0 ;
i_highest = 0;
/* Position of the title on the disc */
i_pos = p_css->p_title_key[i_title].i;
memset( p_title_key, 0, 10 );
memset( &pi_key, 0, 10 );
b_encrypted = 0;
b_stop_scanning = 0;
i_registered_keys = 0 ;
i_total_keys_found = 0 ;
i_highest = 0;
/* Position of the title on the disc */
i_title = p_css->i_title;
i_pos = p_css->i_title_pos;
//fprintf( stderr, "CSS %d start pos: %lld\n", i_title, i_pos );
do {
i_pos = lseek( p_css->i_fd, i_pos, SEEK_SET );
i_bytes_read = read( p_css->i_fd, pi_buf, 0x800 );
do {
i_pos = lseek( p_css->i_fd, i_pos, SEEK_SET );
i_bytes_read = read( p_css->i_fd, pi_buf, 0x800 );
/* PES_scrambling_control */
if( pi_buf[0x14] & 0x30 )
{
b_encrypted = 1;
i_best_plen = 0;
i_best_p = 0;
/* PES_scrambling_control */
if( pi_buf[0x14] & 0x30 )
{
b_encrypted = 1;
i_best_plen = 0;
i_best_p = 0;
for( i = 2 ; i < 0x30 ; i++ )
for( i = 2 ; i < 0x30 ; i++ )
{
for( j = i ; ( j < 0x80 ) &&
( pi_buf[0x7F - (j%i)] == pi_buf[0x7F-j] ) ; j++ );
{
for( j = i ; ( j < 0x80 ) &&
( pi_buf[0x7F - (j%i)] == pi_buf[0x7F-j] ) ; j++ );
if( ( j > i_best_plen ) && ( j > i ) )
{
if( ( j > i_best_plen ) && ( j > i ) )
{
i_best_plen = j;
i_best_p = i;
}
i_best_plen = j;
i_best_p = i;
}
}
}
if( ( i_best_plen > 20 ) && ( i_best_plen / i_best_p >= 2) )
if( ( i_best_plen > 20 ) && ( i_best_plen / i_best_p >= 2) )
{
i = CSSCracker( 0, &pi_buf[0x80],
&pi_buf[0x80 - ( i_best_plen / i_best_p) *i_best_p],
(dvd_key_t*)&pi_buf[0x54],
&pi_key );
while( i>=0 )
{
i = CSSCracker( 0, &pi_buf[0x80],
&pi_buf[0x80 - ( i_best_plen / i_best_p) *i_best_p],
(DVD_key_t*)&pi_buf[0x54],
&key );
while( i>=0 )
k = 0;
for( j=0 ; j<i_registered_keys ; j++ )
{
k = 0;
for( j=0 ; j<i_registered_keys ; j++ )
if( memcmp( &(p_title_key[j].pi_key),
&pi_key, sizeof(dvd_key_t) ) == 0 )
{
if( memcmp( &(p_title_key[j].key),
&key, sizeof(DVD_key_t) ) == 0 )
{
p_title_key[j].i++;
i_total_keys_found++;
k = 1;
}
}
if( k == 0 )
{
memcpy( &(p_title_key[i_registered_keys].key),
&key, sizeof(DVD_key_t) );
p_title_key[i_registered_keys++].i = 1;
p_title_key[j].i_occ++;
i_total_keys_found++;
k = 1;
}
i = CSSCracker( i, &pi_buf[0x80],
&pi_buf[0x80 -( i_best_plen / i_best_p) *i_best_p],
(DVD_key_t*)&pi_buf[0x54], &key);
}
/* Stop search if we find one occurance of the key
* I have never found a DVD for which it is not enough
* but we should take care of that */
if( i_registered_keys == 1 && p_title_key[0].i >= 1 )
if( k == 0 )
{
b_stop_scanning = 1;
memcpy( &(p_title_key[i_registered_keys].pi_key),
&pi_key, sizeof(dvd_key_t) );
p_title_key[i_registered_keys++].i_occ = 1;
i_total_keys_found++;
}
i = CSSCracker( i, &pi_buf[0x80],
&pi_buf[0x80 - ( i_best_plen / i_best_p) *i_best_p],
(dvd_key_t*)&pi_buf[0x54], &pi_key);
}
/* Stop search if we find one occurance of the key
* I have never found a DVD for which it is not enough
* but we should take care of that */
if( i_registered_keys == 1 && p_title_key[0].i_occ >= 1 )
{
b_stop_scanning = 1;
}
}
}
i_pos += i_bytes_read;
} while( i_bytes_read == 0x800 && !b_stop_scanning);
i_pos += i_bytes_read;
} while( i_bytes_read == 0x800 && !b_stop_scanning);
if( b_stop_scanning)
{
intf_WarnMsg( 1,
"CSS: Found enough occurancies of the same key." );
}
if( b_stop_scanning)
{
intf_WarnMsg( 1,
"CSS: Found enough occurancies of the same key." );
}
if( !b_encrypted )
{
intf_WarnMsg( 3, "CSS: This file was _NOT_ encrypted!");
return(0);
}
if( !b_encrypted )
{
intf_WarnMsg( 3, "CSS: This file was _NOT_ encrypted!");
return(0);
}
if( b_encrypted && i_registered_keys == 0 )
{
intf_ErrMsg( "CSS: Unable to determine keys from file.");
return(1);
}
if( b_encrypted && i_registered_keys == 0 )
{
intf_ErrMsg( "CSS: Unable to determine keys from file.");
return(1);
}
for( i = 0 ; i < i_registered_keys - 1 ; i++ )
for( i = 0 ; i < i_registered_keys - 1 ; i++ )
{
for( j = i + 1 ; j < i_registered_keys ; j++ )
{
for( j = i + 1 ; j < i_registered_keys ; j++ )
if( p_title_key[j].i_occ > p_title_key[i].i_occ )
{
if( p_title_key[j].i > p_title_key[i].i )
{
memcpy( &key, &(p_title_key[j].key), sizeof(DVD_key_t) );
k = p_title_key[j].i;
memcpy( &pi_key, &(p_title_key[j].pi_key), sizeof(dvd_key_t) );
k = p_title_key[j].i_occ;
memcpy( &(p_title_key[j].key),
&(p_title_key[i].key), sizeof(DVD_key_t) );
p_title_key[j].i = p_title_key[i].i;
memcpy( &(p_title_key[j].pi_key),
&(p_title_key[i].pi_key), sizeof(dvd_key_t) );
p_title_key[j].i_occ = p_title_key[i].i_occ;
memcpy( &(p_title_key[i].key),&key, sizeof(DVD_key_t) );
p_title_key[i].i = k;
}
memcpy( &(p_title_key[i].pi_key),&pi_key, sizeof(dvd_key_t) );
p_title_key[i].i_occ = k;
}
}
}
#ifdef STATS
intf_WarnMsg( 1, " Key(s) & key probability\n---------------------");
intf_WarnMsg( 1, " Key(s) & key probability\n---------------------");
#endif
for( i=0 ; i<i_registered_keys ; i++ )
{
for( i=0 ; i<i_registered_keys ; i++ )
{
#ifdef STATS
intf_WarnMsg( 1, "%d) %02X %02X %02X %02X %02X - %3.2f%%", i,
p_title_key[i].key[0], p_title_key[i].key[1],
p_title_key[i].key[2], p_title_key[i].key[3],
p_title_key[i].key[4],
p_title_key[i].i * 100.0 / i_total_keys_found );
intf_WarnMsg( 1, "%d) %02X %02X %02X %02X %02X - %3.2f%%", i,
p_title_key[i].key[0], p_title_key[i].key[1],
p_title_key[i].key[2], p_title_key[i].key[3],
p_title_key[i].key[4],
p_title_key[i].i_occ * 100.0 / i_total_keys_found );
#endif
if( p_title_key[i_highest].i * 100.0 / i_total_keys_found
<= p_title_key[i].i*100.0 / i_total_keys_found )
{
i_highest = i;
}
if( p_title_key[i_highest].i_occ * 100.0 / i_total_keys_found
<= p_title_key[i].i_occ*100.0 / i_total_keys_found )
{
i_highest = i;
}
}
/* The "find the key with the highest probability" code
* is untested, as I haven't been able to find a VOB that
* produces multiple keys (RT)
*/
intf_WarnMsg( 3, "CSS: Title %d key: %02X %02X %02X %02X %02X",
i_title + 1,
p_title_key[i_highest].key[0],
p_title_key[i_highest].key[1],
p_title_key[i_highest].key[2],
p_title_key[i_highest].key[3],
p_title_key[i_highest].key[4] );
memcpy( p_css->p_title_key[i_title].key,
p_title_key[i_highest].key, KEY_SIZE );
}
/* The "find the key with the highest probability" code
* is untested, as I haven't been able to find a VOB that
* produces multiple keys (RT)
*/
intf_WarnMsg( 3, "CSS: Title %d key: %02X %02X %02X %02X %02X",
i_title + 1,
p_title_key[i_highest].pi_key[0],
p_title_key[i_highest].pi_key[1],
p_title_key[i_highest].pi_key[2],
p_title_key[i_highest].pi_key[3],
p_title_key[i_highest].pi_key[4] );
memcpy( p_css->pi_title_key,
p_title_key[i_highest].pi_key, KEY_SIZE );
return 0;
}
......@@ -1219,7 +1216,7 @@ int CSSGetKeys( css_t * p_css )
* sec : sector to descramble
* key : title key for this sector
*****************************************************************************/
int CSSDescrambleSector( DVD_key_t key, u8* pi_sec )
int CSSDescrambleSector( dvd_key_t pi_key, u8* pi_sec )
{
unsigned int i_t1, i_t2, i_t3, i_t4, i_t5, i_t6;
u8* pi_end = pi_sec + 0x800;
......@@ -1227,10 +1224,10 @@ int CSSDescrambleSector( DVD_key_t key, u8* pi_sec )
/* PES_scrambling_control */
if( pi_sec[0x14] & 0x30)
{
i_t1 = ((key)[0] ^ pi_sec[0x54]) | 0x100;
i_t2 = (key)[1] ^ pi_sec[0x55];
i_t3 = (((key)[2]) | ((key)[3] << 8) |
((key)[4] << 16)) ^ ((pi_sec[0x56]) |
i_t1 = ((pi_key)[0] ^ pi_sec[0x54]) | 0x100;
i_t2 = (pi_key)[1] ^ pi_sec[0x55];
i_t3 = (((pi_key)[2]) | ((pi_key)[3] << 8) |
((pi_key)[4] << 16)) ^ ((pi_sec[0x56]) |
(pi_sec[0x57] << 8) | (pi_sec[0x58] << 16));
i_t4 = i_t3 & 7;
i_t3 = i_t3 * 2 + 8 - i_t4;
......
......@@ -2,7 +2,7 @@
* dvd_css.h: Structures for DVD authentification and unscrambling
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: dvd_css.h,v 1.3 2001/02/15 21:03:27 stef Exp $
* $Id: dvd_css.h,v 1.4 2001/02/20 02:53:13 stef Exp $
*
* Author: Stphane Borel <stef@via.ecp.fr>
*
......@@ -10,7 +10,7 @@
* - css-auth by Derek Fawcus <derek@spider.com>
* - DVD CSS ioctls example program by Andrew T. Veliath <andrewtv@usa.net>
* - DeCSSPlus by Ethan Hawke
* - The Divide and conquer attack by Frank A. Stevenson<frank@funcom.com>
* - The Divide and conquer attack by Frank A. Stevenson <frank@funcom.com>
*
* 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
......@@ -28,24 +28,21 @@
*****************************************************************************/
#define KEY_SIZE 5
typedef u8 DVD_key_t[KEY_SIZE];
typedef u8 dvd_key_t[KEY_SIZE];
typedef struct disc_s
{
u8 pi_challenge[2*KEY_SIZE];
u8 pi_key1[KEY_SIZE];
u8 pi_key2[KEY_SIZE];
u8 pi_key_check[KEY_SIZE];
dvd_key_t pi_key1;
dvd_key_t pi_key2;
dvd_key_t pi_key_check;
u8 i_varient;
} disc_t;
typedef struct title_key_s
{
off_t i; /* This signification of this parameter
depends on the function it is called from :
*from DVDInit -> i == position
*from CSSGetKeys -> i == nb occurence */
DVD_key_t key;
int i_occ;
dvd_key_t pi_key;
} title_key_t;
typedef struct css_s
......@@ -55,6 +52,7 @@ typedef struct css_s
int i_agid;
disc_t disc;
u8 pi_disc_key[2048];
int i_title_nb;
title_key_t* p_title_key;
int i_title;
off_t i_title_pos;
dvd_key_t pi_title_key;
} css_t;
......@@ -2,7 +2,7 @@
* dvd_ifo.c: Functions for ifo parsing
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: dvd_ifo.c,v 1.10 2001/02/19 03:12:26 stef Exp $
* $Id: dvd_ifo.c,v 1.11 2001/02/20 02:53:13 stef Exp $
*
* Author: Stphane Borel <stef@via.ecp.fr>
*
......@@ -41,7 +41,11 @@
#include "dvd_udf.h"
#include "input_dvd.h"
void CommandRead( ifo_command_t );
/*
* Local prototypes
*/
static vmg_t ReadVMG ( ifo_t* );
void CommandRead( ifo_command_t );
/*
* IFO Management.
......@@ -64,6 +68,10 @@ ifo_t IfoInit( int i_fd )
ifo.i_off = (off_t)(i_lba) * DVD_LB_SIZE;
ifo.i_pos = lseek( ifo.i_fd, ifo.i_off, SEEK_SET );
/* Video Manager Initialization */
intf_WarnMsg( 2, "ifo: initializing VMG" );
ifo.vmg = ReadVMG( &ifo );
return ifo;
}
......@@ -72,6 +80,7 @@ ifo_t IfoInit( int i_fd )
*****************************************************************************/
void IfoEnd( ifo_t* p_ifo )
{
#if 0
int i,j;
/* Free structures from video title sets */
......@@ -121,7 +130,7 @@ void IfoEnd( ifo_t* p_ifo )
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 );
#endif
return;
}
......@@ -215,11 +224,12 @@ static pgc_t ReadPGC( ifo_t* p_ifo )
int i;
off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "PGC\n" );
fprintf( stderr, "PGC\n" );
FLUSH(2);
GETC( &pgc.i_prg_nb );
GETC( &pgc.i_cell_nb );
fprintf( stderr, "PGC: Prg: %d Cell: %d\n", pgc.i_prg_nb, pgc.i_cell_nb );
GETL( &pgc.i_play_time );
GETL( &pgc.i_prohibited_user_op );
for( i=0 ; i<8 ; i++ )
......@@ -233,6 +243,7 @@ static pgc_t ReadPGC( ifo_t* p_ifo )
GETS( &pgc.i_next_pgc_nb );
GETS( &pgc.i_prev_pgc_nb );
GETS( &pgc.i_goup_pgc_nb );
fprintf( stderr, "PGC: Prev: %d Next: %d Up: %d\n",pgc.i_prev_pgc_nb ,pgc.i_next_pgc_nb, pgc.i_goup_pgc_nb );
GETC( &pgc.i_still_time );
GETC( &pgc.i_play_mode );
for( i=0 ; i<16 ; i++ )
......@@ -371,7 +382,7 @@ static pgci_inf_t ReadUnit( ifo_t* p_ifo )
int i;
off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "Unit\n" );
fprintf( stderr, "Unit\n" );
GETS( &inf.i_srp_nb );
FLUSH( 2 );
......@@ -395,6 +406,7 @@ static pgci_inf_t ReadUnit( ifo_t* p_ifo )
p_ifo->i_pos = lseek( p_ifo->i_fd,
i_start + inf.p_srp[i].i_pgci_sbyte,
SEEK_SET );
fprintf( stderr, "Unit: PGC %d\n", i );
inf.p_srp[i].pgc = ReadPGC( p_ifo );
}
......@@ -410,7 +422,7 @@ static pgci_ut_t ReadUnitTable( ifo_t* p_ifo )
int i;
off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "Unit Table\n" );
fprintf( stderr, "Unit Table\n" );
GETS( &pgci.i_lu_nb );
FLUSH( 2 );
......@@ -577,9 +589,10 @@ static vmg_ptt_srpt_t ReadVMGTitlePointer( ifo_t* p_ifo )
int i;
// off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "PTR\n" );
fprintf( stderr, "PTR\n" );
GETS( &ptr.i_ttu_nb );
fprintf( stderr, "PTR: TTU nb %d\n", ptr.i_ttu_nb );
FLUSH( 2 );
GETL( &ptr.i_ebyte );
/* Parsing of tts */
......@@ -599,7 +612,7 @@ static vmg_ptt_srpt_t ReadVMGTitlePointer( ifo_t* p_ifo )
GETC( &ptr.p_tts[i].i_tts_nb );
GETC( &ptr.p_tts[i].i_vts_ttn );
GETL( &ptr.p_tts[i].i_ssector );
//fprintf( stderr, "PTR: %d %d %d\n",ptr.p_tts[i].i_tts_nb,ptr.p_tts[i].i_vts_ttn, ptr.p_tts[i].i_ssector );
fprintf( stderr, "PTR: %d %d %d\n", ptr.p_tts[i].i_ptt_nb, ptr.p_tts[i].i_tts_nb,ptr.p_tts[i].i_vts_ttn );
}
return ptr;
......@@ -673,9 +686,10 @@ static vmg_vts_atrt_t ReadVTSAttr( ifo_t* p_ifo )
int i, j;
off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "VTS ATTR\n" );
fprintf( stderr, "VTS ATTR\n" );
GETS( &atrt.i_vts_nb );
fprintf( stderr, "VTS ATTR Nb: %d\n", atrt.i_vts_nb );
FLUSH( 2 );
GETL( &atrt.i_ebyte );
atrt.pi_vts_atrt_sbyte = malloc( atrt.i_vts_nb *sizeof(u32) );
......@@ -880,9 +894,10 @@ static vts_ptt_srpt_t ReadVTSTitlePointer( ifo_t* p_ifo )
int i;
off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "PTR\n" );
fprintf( stderr, "VTS PTR\n" );
GETS( &ptr.i_ttu_nb );
fprintf( stderr, "VTS PTR nb: %d\n", ptr.i_ttu_nb );
FLUSH( 2 );
GETL( &ptr.i_ebyte );
ptr.pi_ttu_sbyte = malloc( ptr.i_ttu_nb *sizeof(u32) );
......@@ -910,6 +925,7 @@ static vts_ptt_srpt_t ReadVTSTitlePointer( ifo_t* p_ifo )
ptr.pi_ttu_sbyte[i], SEEK_SET );
GETS( &ptr.p_ttu[i].i_pgc_nb );
GETS( &ptr.p_ttu[i].i_prg_nb );
fprintf( stderr, "VTS %d PTR Pgc: %d Prg: %d\n", i,ptr.p_ttu[i].i_pgc_nb, ptr.p_ttu[i].i_prg_nb );
}
return ptr;
......@@ -971,11 +987,21 @@ static vts_tmap_ti_t ReadVTSTimeMap( ifo_t* p_ifo )
/*****************************************************************************
* ReadVTS : Parse vts*.ifo files to fill the Video Title Set structure.
* IfoReadVTS : Parse vts*.ifo files to fill the Video Title Set structure.
*****************************************************************************/
static vts_t ReadVTS( ifo_t* p_ifo )
int IfoReadVTS( ifo_t* p_ifo )
{
vts_t vts;
off_t i_off;
int i_title;
intf_WarnMsg( 2, "ifo: initializing VTS %d", p_ifo->i_title );
i_title = p_ifo->i_title;
i_off = (off_t)( p_ifo->vmg.ptt_srpt.p_tts[i_title].i_ssector ) *DVD_LB_SIZE
+ p_ifo->i_off;
p_ifo->i_pos = lseek( p_ifo->i_fd, i_off, SEEK_SET );
vts.i_pos = p_ifo->i_pos;
......@@ -1037,13 +1063,15 @@ static vts_t ReadVTS( ifo_t* p_ifo )
vts.vobu_admap = ReadMap( p_ifo );
}
return vts;
p_ifo->vts = vts;
return 0;
}
/*
* DVD Information Management
*/
#if 0
/*****************************************************************************
* IfoRead : Function that fills structure and calls specified functions
* to do it.
......@@ -1053,10 +1081,6 @@ void IfoRead( ifo_t* p_ifo )
int i;
off_t i_off;
/* Video Manager Initialization */
intf_WarnMsg( 2, "ifo: initializing VMG" );
p_ifo->vmg = ReadVMG( p_ifo );
/* Video Title Sets initialization */
p_ifo->p_vts = malloc( p_ifo->vmg.mat.i_tts_nb *sizeof(vts_t) );
if( p_ifo->p_vts == NULL )
......@@ -1085,7 +1109,7 @@ void IfoRead( ifo_t* p_ifo )
return;
}
#endif
/*
* IFO virtual machine : a set of commands that give the
* interactive behaviour of the dvd
......
......@@ -2,7 +2,7 @@
* dvd_ifo.h: Structures for ifo parsing
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: dvd_ifo.h,v 1.6 2001/02/15 21:03:27 stef Exp $
* $Id: dvd_ifo.h,v 1.7 2001/02/20 02:53:13 stef Exp $
*
* Author: Stphane Borel <stef@via.ecp.fr>
*
......@@ -491,9 +491,11 @@ typedef struct ifo_s
off_t i_pos;
/* Error Management */
boolean_t b_error;
/* Current title set number */
int i_title;
/* Structure described in video_ts */
vmg_t vmg;
/* Table of vts ifos */
vts_t * p_vts;
/* Vts ifo for current title set */
vts_t vts;
} ifo_t;
......@@ -10,7 +10,7 @@
* -dvd_udf to find files
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: input_dvd.c,v 1.14 2001/02/19 03:12:26 stef Exp $
* $Id: input_dvd.c,v 1.15 2001/02/20 02:53:13 stef Exp $
*
* Author: Stphane Borel <stef@via.ecp.fr>
*
......@@ -241,6 +241,7 @@ static int DVDRead ( struct input_thread_s *, data_packet_t ** );
static void DVDInit ( struct input_thread_s * );
static void DVDEnd ( struct input_thread_s * );
static void DVDSeek ( struct input_thread_s *, off_t );
static int DVDSetArea ( struct input_thread_s *, int, int, int, int );
static int DVDRewind ( struct input_thread_s * );
/*****************************************************************************
......@@ -256,6 +257,7 @@ void input_getfunctions( function_list_t * p_function_list )
input.pf_close = input_FileClose;
input.pf_end = DVDEnd;
input.pf_read = DVDRead;
input.pf_set_area = DVDSetArea;
input.pf_demux = input_DemuxPS;
input.pf_new_packet = input_NetlistNewPacket;
input.pf_new_pes = input_NetlistNewPES;
......@@ -338,17 +340,18 @@ static int DVDCheckCSS( input_thread_t * p_input )
}
/*****************************************************************************
* DVDSetRegion: initialize input data for title x, chapter y.
* DVDSetArea: initialize input data for title x, chapter y.
* It should be called for each user navigation request, and to change
* audio or sub-picture streams.
* ---
* Take care that i_title and i_chapter start from 0.
*****************************************************************************/
static int DVDSetRegionParameters( input_thread_t * p_input,
int i_title, int i_chapter,
int i_audio, int i_spu )
static int DVDSetArea( input_thread_t * p_input,
int i_title, int i_chapter,
int i_audio, int i_spu )
{
thread_dvd_data_t * p_method;
es_descriptor_t * p_es;
off_t i_start;
off_t i_size;
pgc_t * p_pgc;
......@@ -356,14 +359,31 @@ static int DVDSetRegionParameters( input_thread_t * p_input,
int i_end_cell;
int i_index;
int i_cell;
int i_nb;
int i_id;
int i;
p_method = (thread_dvd_data_t*)p_input->p_plugin_data;
/* Set selected title start and size */
p_input->stream.i_title = i_title;
/* Ifo structures reading */
p_method->ifo.i_title = i_title;
IfoReadVTS( &(p_method->ifo) );
intf_WarnMsg( 2, "Ifo: VTS initialized" );
p_pgc = &p_method->ifo.p_vts[i_title].pgci_ti.p_srp[0].pgc;
#if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
if( p_method->b_encrypted )
{
p_method->css.i_title = i_title;
p_method->css.i_title_pos =
p_method->ifo.vts.i_pos +
p_method->ifo.vts.mat.i_tt_vobs_ssector * DVD_LB_SIZE;
CSSGetKey( &(p_method->css) );
intf_WarnMsg( 2, "CSS: VTS key initialized" );
}
#endif
/* Set selected title start and size */
p_pgc = &p_method->ifo.vts.pgci_ti.p_srp[0].pgc;
/* Find cell index in Program chain */
i_index = p_pgc->prg_map.pi_entry_cell[i_chapter] - 1;
......@@ -371,38 +391,96 @@ static int DVDSetRegionParameters( input_thread_t * p_input,
/* Search for cell_index in cell adress_table */
i_cell = 0;
while( p_pgc->p_cell_pos_inf[i_index].i_vob_id >
p_method->ifo.p_vts[i_title].c_adt.p_cell_inf[i_cell].i_vob_id )
p_method->ifo.vts.c_adt.p_cell_inf[i_cell].i_vob_id )
{
i_cell++;
}
while( p_pgc->p_cell_pos_inf[i_index].i_cell_id >
p_method->ifo.p_vts[i_title].c_adt.p_cell_inf[i_cell].i_cell_id )
p_method->ifo.vts.c_adt.p_cell_inf[i_cell].i_cell_id )
{
i_cell++;
}
i_start_cell = i_cell;
i_end_cell = i_start_cell + p_pgc->i_cell_nb - 1;
intf_WarnMsg( 2, "DVD: Start cell: %d End Cell: %d",
intf_WarnMsg( 3, "DVD: Start cell: %d End Cell: %d",
i_start_cell, i_end_cell );
p_method->i_start_cell = i_start_cell;
p_method->i_end_cell = i_end_cell;
/* start is : beginning of vts + offset to vobs + offset to vob x */
i_start = p_method->ifo.p_vts[i_title].i_pos + DVD_LB_SIZE *
( p_method->ifo.p_vts[i_title].mat.i_tt_vobs_ssector +
p_method->ifo.p_vts[i_title].c_adt.p_cell_inf[i_start_cell].i_ssector );
p_method->i_start_byte = i_start;
i_start = p_method->ifo.vts.i_pos + DVD_LB_SIZE *
( p_method->ifo.vts.mat.i_tt_vobs_ssector +
p_method->ifo.vts.c_adt.p_cell_inf[i_start_cell].i_ssector );
i_start = lseek( p_input->i_handle, i_start, SEEK_SET );
intf_WarnMsg( 3, "DVD: VOBstart at: %lld", i_start );
intf_WarnMsg( 2, "DVD: VOBstart at: %lld", i_start );
i_size = (off_t)
( p_method->ifo.p_vts[i_title].c_adt.p_cell_inf[i_end_cell].i_esector -
p_method->ifo.p_vts[i_title].c_adt.p_cell_inf[i_start_cell].i_ssector + 1 )
( p_method->ifo.vts.c_adt.p_cell_inf[i_end_cell].i_esector -
p_method->ifo.vts.c_adt.p_cell_inf[i_start_cell].i_ssector + 1 )
*DVD_LB_SIZE;
intf_WarnMsg( 3, "DVD: stream size: %lld", i_size );
intf_WarnMsg( 2, "DVD: stream size: %lld", i_size );
#if 0
p_es = NULL;
vlc_mutex_lock( &p_input->stream.stream_lock );
/* ES 0 -> video MPEG2 */
intf_WarnMsg( 1, "DVD: Video MPEG2 stream" );
p_es = input_AddES( p_input, p_input->stream.pp_programs[0], 0xe0, 0 );
p_es->i_stream_id = 0xe0;
p_es->i_type = MPEG2_VIDEO_ES;
input_SelectES( p_input, p_es );
/* Audio ES, in the order they appear in .ifo */
i_nb = p_method->ifo.vts.mat.i_audio_nb;
intf_WarnMsg( 1, "DVD: Audio streams %d", i_nb );
for( i = 0 ; i < i_nb ; i++ )
{
i_id = ( ( 0x80 + i ) << 8 ) | 0xbd;
p_es = input_AddES( p_input,
p_input->stream.pp_programs[0], i_id, 0 );
p_es->i_stream_id = 0xbd;
p_es->i_type = AC3_AUDIO_ES;
p_es->b_audio = 1;
// p_es->psz_desc = p_method->ifo.vts.mat.pi_audio_attr[i];
if( i == 0 )
{
input_SelectES( p_input, p_es );
}
}
/* Sub Picture ES */
i_nb = p_method->ifo.vts.mat.i_subpic_nb;
intf_WarnMsg( 1, "DVD: Subpic streams %d", i_nb );
for( i = 0 ; i < i_nb ; i++ )
{
i_id = ( ( 0x20 + i ) << 8 ) | 0xbd;
p_es = input_AddES( p_input,
p_input->stream.pp_programs[0], i_id, 0 );
p_es->i_stream_id = 0xbd;
p_es->i_type = DVD_SPU_ES;
// p_es->psz_desc = p_method->ifo.vts.mat.pi_subpic_attr[i];
if( i == 0 )
{
input_SelectES( p_input, p_es );
}
}
/* area definition */
p_input->stream.pp_areas[0]->i_start = i_start;
p_input->stream.pp_areas[0]->i_size = i_size;
/* No PSM to read in DVD mode */
p_input->stream.pp_programs[0]->b_is_ok = 1;
vlc_mutex_unlock( &p_input->stream.stream_lock );
#else
if( p_input->stream.b_seekable )
{
......@@ -443,7 +521,7 @@ static int DVDSetRegionParameters( input_thread_t * p_input,
}
/* File too big. */
if( p_input->stream.i_tell > INPUT_PREPARSE_LENGTH )
if( p_input->stream.pp_areas[0]->i_tell > INPUT_PREPARSE_LENGTH )
{
break;
}
......@@ -453,7 +531,7 @@ static int DVDSetRegionParameters( input_thread_t * p_input,
/* i_tell is an indicator from the beginning of the stream,
* not of the DVD */
p_input->stream.i_tell = 0;
p_input->stream.pp_areas[0]->i_tell = 0;
if( p_demux_data->b_has_PSM )
{
......@@ -528,7 +606,7 @@ static int DVDSetRegionParameters( input_thread_t * p_input,
#endif
/* FIXME : ugly kludge */
p_input->stream.i_size = i_size;
p_input->stream.pp_areas[0]->i_size = i_size;
vlc_mutex_unlock( &p_input->stream.stream_lock );
}
......@@ -539,11 +617,11 @@ static int DVDSetRegionParameters( input_thread_t * p_input,
p_input->stream.pp_programs[0]->b_is_ok = 0;
/* FIXME : ugly kludge */
p_input->stream.i_size = i_size;
p_input->stream.pp_areas[0]->i_size = i_size;
vlc_mutex_unlock( &p_input->stream.stream_lock );
}
#endif
return 0;
}
......@@ -554,6 +632,7 @@ static int DVDSetRegionParameters( input_thread_t * p_input,
static void DVDInit( input_thread_t * p_input )
{
thread_dvd_data_t * p_method;
int i;
if( (p_method = malloc( sizeof(thread_dvd_data_t) )) == NULL )
{
......@@ -575,9 +654,11 @@ static void DVDInit( input_thread_t * p_input )
/* Reading structures initialisation */
input_NetlistInit( p_input, 4096, 4096, DVD_LB_SIZE,
p_method->i_read_once );
intf_WarnMsg( 2, "DVD: Netlist initialized" );
/* Ifo initialisation */
p_method->ifo = IfoInit( p_input->i_handle );
intf_WarnMsg( 2, "Ifo: VMG initialized" );
/* CSS initialisation */
if( p_method->b_encrypted )
......@@ -591,44 +672,7 @@ static void DVDInit( input_thread_t * p_input )
intf_ErrMsg( "CSS fatal error" );
return;
}
#else
intf_ErrMsg( "Unscrambling not supported" );
p_input->b_error = 1;
return;
#endif
}
/* Ifo structures reading */
IfoRead( &(p_method->ifo) );
intf_WarnMsg( 3, "Ifo: Initialized" );
/* CSS title keys decryption */
if( p_method->b_encrypted )
{
#if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
int i;
p_method->css.i_title_nb = p_method->ifo.vmg.mat.i_tts_nb;
if( (p_method->css.p_title_key =
malloc( p_method->css.i_title_nb *sizeof(title_key_t) ) ) == NULL )
{
intf_ErrMsg( "Out of memory" );
p_input->b_error = 1;
return;
}
for( i=0 ; i<p_method->css.i_title_nb ; i++ )
{
p_method->css.p_title_key[i].i =
p_method->ifo.p_vts[i].i_pos +
p_method->ifo.p_vts[i].mat.i_tt_vobs_ssector * DVD_LB_SIZE;
}
CSSGetKeys( &(p_method->css) );
intf_WarnMsg( 3, "CSS: initialized" );
intf_WarnMsg( 2, "CSS: initialized" );
#else
intf_ErrMsg( "Unscrambling not supported" );
p_input->b_error = 1;
......@@ -640,16 +684,43 @@ static void DVDInit( input_thread_t * p_input )
input_InitStream( p_input, sizeof( stream_ps_data_t ) );
input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) );
/* Set stream data */
/* Set stream and area data */
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.i_title_nb = p_method->ifo.vmg.mat.i_tts_nb;
/* FIXME: We consider here that one title is one title set
* it is not true !!! */
#define area p_input->stream.pp_areas
/* We start from 1 here since area 0 is reserved for video_ts.vob */
for( i = 1 ; i < p_method->ifo.vmg.mat.i_tts_nb ; i++ )
{
input_AddArea( p_input );
/* Should not be so simple eventually :
* are title Program Chains, or still something else ? */
area[i]->i_id = i;
/* Absolute start offset and size
* We can only set that with vts ifo, so we do it during the
* first call to DVDSetArea */
area[i]->i_start = 0;
area[i]->i_size = 0;
/* Number of chapter */
area[i]->i_part_nb = 0;
area[i]->i_part = 1;
/* Offset to vts_i_0.ifo */
area[i]->i_plugin_data = p_method->ifo.i_off +
( p_method->ifo.vmg.ptt_srpt.p_tts[i-1].i_ssector * DVD_LB_SIZE );
}
#undef area
vlc_mutex_unlock( &p_input->stream.stream_lock );
/* By default, set all parameters to 0 */
/* FIXME: wrong kludge to get title nb */
DVDSetRegionParameters( p_input,
p_method->ifo.vmg.ptt_srpt.p_tts[0].i_tts_nb - 1,
0, 0, 0 );
/* FIXME: wrong kludge to get first title number */
DVDSetArea( p_input, p_method->ifo.vmg.ptt_srpt.p_tts[0].i_tts_nb - 1,
0, 0, 0 );
return;
}
......@@ -705,9 +776,8 @@ static int DVDRead( input_thread_t * p_input,
{
for( i=0 ; i<p_method->i_read_once ; i++ )
{
CSSDescrambleSector(
p_method->css.p_title_key[p_input->stream.i_title].key,
p_vec[i].iov_base );
CSSDescrambleSector( p_method->css.pi_title_key,
p_vec[i].iov_base );
((u8*)(p_vec[i].iov_base))[0x14] &= 0x8F;
}
}
......@@ -772,7 +842,7 @@ static int DVDRead( input_thread_t * p_input,
pp_packets[i_packet] = NULL;
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.i_tell += p_method->i_read_once *DVD_LB_SIZE;
p_input->stream.pp_areas[0]->i_tell += p_method->i_read_once *DVD_LB_SIZE;
vlc_mutex_unlock( &p_input->stream.stream_lock );
return( 0 );
......@@ -800,14 +870,14 @@ static void DVDSeek( input_thread_t * p_input, off_t i_off )
p_method = ( thread_dvd_data_t * )p_input->p_plugin_data;
/* We have to take care of offset of beginning of title */
i_pos = i_off + p_method->i_start_byte;
i_pos = i_off + p_input->stream.pp_areas[0]->i_start;
/* With DVD, we have to be on a sector boundary */
i_pos = i_pos & (~0x7ff);
i_pos = lseek( p_input->i_handle, i_pos, SEEK_SET );
p_input->stream.i_tell = i_pos - p_method->i_start_byte;
p_input->stream.pp_areas[0]->i_tell = i_pos - p_input->stream.pp_areas[0]->i_start;
return;
}
......@@ -53,6 +53,7 @@ typedef struct thread_dvd_data_s
* Prototypes in dvd_ifo.c
*****************************************************************************/
struct ifo_s IfoInit( int );
int IfoReadVTS( struct ifo_s * );
void IfoRead( struct ifo_s * );
void IfoEnd( ifo_t * );
......@@ -62,7 +63,7 @@ void IfoEnd( ifo_t * );
#if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
int CSSTest ( int );
struct css_s CSSInit ( int );
int CSSGetKeys ( struct css_s * );
int CSSGetKey ( struct css_s * );
int CSSDescrambleSector( u8 * , u8 * );
#endif
......@@ -438,7 +438,8 @@ on_hscale_button_release_event (GtkWidget *widget,
if( p_intf->p_input != NULL )
{
i_seek = (p_adj->value * p_intf->p_input->stream.i_size) / 100;
i_seek = (p_adj->value *
p_intf->p_input->stream.pp_areas[0]->i_size) / 100;
input_Seek( p_intf->p_input, i_seek );
}
p_intf->p_sys->b_scale_isfree = 1;
......
......@@ -2,7 +2,7 @@
* intf_gnome.c: Gnome interface
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: intf_gnome.c,v 1.13 2001/02/16 06:37:09 sam Exp $
* $Id: intf_gnome.c,v 1.14 2001/02/20 02:53:13 stef Exp $
*
* Authors:
*
......@@ -253,8 +253,8 @@ static gint GnomeManage( gpointer p_data )
p_adj = gtk_range_get_adjustment ( GTK_RANGE( p_scale ) );
/* Update the value */
p_adj->value = ( 100. * p_intf->p_input->stream.i_tell )
/ p_intf->p_input->stream.i_size;
p_adj->value = ( 100. * p_intf->p_input->stream.pp_areas[0]->i_tell )
/ p_intf->p_input->stream.pp_areas[0]->i_size;
/* Gtv does it this way. Why not. */
gtk_range_set_adjustment ( GTK_RANGE( p_scale ), p_adj );
......
......@@ -2,7 +2,7 @@
* input_ps.c: PS demux and packet management
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: input_ps.c,v 1.6 2001/02/16 09:25:03 sam Exp $
* $Id: input_ps.c,v 1.7 2001/02/20 02:53:13 stef Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -84,6 +84,7 @@ void input_getfunctions( function_list_t * p_function_list )
input.pf_open = input_FileOpen;
input.pf_close = input_FileClose;
input.pf_end = PSEnd;
input.pf_set_area = NULL;
input.pf_read = PSRead;
input.pf_demux = input_DemuxPS;
input.pf_new_packet = NewPacket;
......@@ -201,14 +202,14 @@ static void PSInit( input_thread_t * p_input )
}
/* File too big. */
if( p_input->stream.i_tell > INPUT_PREPARSE_LENGTH )
if( p_input->stream.pp_areas[0]->i_tell > INPUT_PREPARSE_LENGTH )
{
break;
}
}
rewind( p_method->stream );
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.i_tell = 0;
p_input->stream.pp_areas[0]->i_tell = 0;
if( p_demux_data->b_has_PSM )
{
/* (The PSM decoder will care about spawning the decoders) */
......@@ -324,7 +325,7 @@ static __inline__ int SafeRead( input_thread_t * p_input, byte_t * p_buffer,
}
}
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.i_tell += i_len;
p_input->stream.pp_areas[0]->i_tell += i_len;
vlc_mutex_unlock( &p_input->stream.stream_lock );
return( 0 );
}
......@@ -466,7 +467,7 @@ static void PSSeek( input_thread_t * p_input, off_t i_position )
/* A little bourrin but should work for a while --Meuuh */
fseeko( p_method->stream, i_position, SEEK_SET );
p_input->stream.i_tell = i_position;
p_input->stream.pp_areas[0]->i_tell = i_position;
}
/*
......
......@@ -2,7 +2,7 @@
* input_ts.c: TS demux and netlist management
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: input_ts.c,v 1.3 2001/02/16 09:25:03 sam Exp $
* $Id: input_ts.c,v 1.4 2001/02/20 02:53:13 stef Exp $
*
* Authors:
*
......@@ -76,6 +76,7 @@ void input_getfunctions( function_list_t * p_function_list )
input.pf_open = input_FileOpen;
input.pf_close = input_FileClose;
input.pf_end = TSEnd;
input.pf_set_area = NULL;
input.pf_read = TSRead;
input.pf_demux = input_DemuxTS;
input.pf_new_packet = input_NetlistNewPacket;
......
......@@ -4,7 +4,7 @@
* decoders.
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: input.c,v 1.84 2001/02/19 19:08:59 massiot Exp $
* $Id: input.c,v 1.85 2001/02/20 02:53:13 stef Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -106,9 +106,14 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
p_input->stream.i_selected_es_number = 0;
p_input->stream.i_pgrm_number = 0;
p_input->stream.i_new_status = p_input->stream.i_new_rate = 0;
p_input->stream.i_seek = NO_SEEK;
p_input->stream.i_mux_rate = 0;
p_input->stream.i_area_nb = 0;
p_input->stream.pp_areas = NULL;
/* By default there is one areas in a stream */
input_AddArea( p_input );
p_input->stream.pp_areas[0]->i_seek = NO_SEEK;
/* Initialize stream control properties. */
p_input->stream.control.i_status = PLAYING_S;
p_input->stream.control.i_rate = DEFAULT_RATE;
......@@ -209,11 +214,11 @@ static void RunThread( input_thread_t *p_input )
#endif
vlc_mutex_lock( &p_input->stream.stream_lock );
if( p_input->stream.i_seek != NO_SEEK )
if( p_input->stream.pp_areas[0]->i_seek != NO_SEEK )
{
if( p_input->stream.b_seekable && p_input->pf_seek != NULL )
{
p_input->pf_seek( p_input, p_input->stream.i_seek );
p_input->pf_seek( p_input, p_input->stream.pp_areas[0]->i_seek );
for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
{
......@@ -227,7 +232,7 @@ static void RunThread( input_thread_t *p_input )
p_pgrm->i_synchro_state = SYNCHRO_REINIT;
}
}
p_input->stream.i_seek = NO_SEEK;
p_input->stream.pp_areas[0]->i_seek = NO_SEEK;
}
vlc_mutex_unlock( &p_input->stream.stream_lock );
......@@ -444,7 +449,7 @@ void input_FileOpen( input_thread_t * p_input )
|| S_ISBLK(stat_info.st_mode) )
{
p_input->stream.b_seekable = 1;
p_input->stream.i_size = stat_info.st_size;
p_input->stream.pp_areas[0]->i_size = stat_info.st_size;
}
else if( S_ISFIFO(stat_info.st_mode)
#ifndef SYS_BEOS
......@@ -453,7 +458,7 @@ void input_FileOpen( input_thread_t * p_input )
)
{
p_input->stream.b_seekable = 0;
p_input->stream.i_size = 0;
p_input->stream.pp_areas[0]->i_size = 0;
}
else
{
......@@ -464,7 +469,7 @@ void input_FileOpen( input_thread_t * p_input )
return;
}
p_input->stream.i_tell = 0;
p_input->stream.pp_areas[0]->i_tell = 0;
vlc_mutex_unlock( &p_input->stream.stream_lock );
intf_Msg( "input: opening %s", p_input->p_source );
......
......@@ -138,10 +138,10 @@ void input_SetRate( input_thread_t * p_input, int i_mode )
void input_Seek( input_thread_t * p_input, off_t i_position )
{
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.i_seek = i_position;
p_input->stream.pp_areas[0]->i_seek = i_position;
intf_Msg( "input: seeking position %lld/%lld", i_position,
p_input->stream.i_size );
p_input->stream.pp_areas[0]->i_size );
vlc_cond_signal( &p_input->stream.stream_wait );
vlc_mutex_unlock( &p_input->stream.stream_lock );
......
......@@ -2,7 +2,7 @@
* input_programs.c: es_descriptor_t, pgrm_descriptor_t management
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: input_programs.c,v 1.31 2001/02/08 17:44:12 massiot Exp $
* $Id: input_programs.c,v 1.32 2001/02/20 02:53:13 stef Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -226,6 +226,91 @@ void input_DelProgram( input_thread_t * p_input, pgrm_descriptor_t * p_pgrm )
free( p_pgrm );
}
/*****************************************************************************
* input_AddArea: add and init an area descriptor
*****************************************************************************
* This area descriptor will be referenced in the given stream descriptor
*****************************************************************************/
input_area_t * input_AddArea( input_thread_t * p_input )
{
/* Where to add the pgrm */
int i_area_index = p_input->stream.i_area_nb;
intf_DbgMsg("Adding description for area %d", i_area_index );
/* Add an entry to the list of program associated with the stream */
p_input->stream.i_area_nb++;
p_input->stream.pp_areas = realloc( p_input->stream.pp_areas,
p_input->stream.i_area_nb
* sizeof(input_area_t *) );
if( p_input->stream.pp_areas == NULL )
{
intf_ErrMsg( "Unable to realloc memory in input_AddArea" );
return( NULL );
}
/* Allocate the structure to store this description */
p_input->stream.pp_areas[i_area_index] =
malloc( sizeof(input_area_t) );
if( p_input->stream.pp_areas[i_area_index] == NULL )
{
intf_ErrMsg( "Unable to allocate memory in input_AddArea" );
return( NULL );
}
/* Init this entry */
p_input->stream.pp_areas[i_area_index]->i_id = 0;
p_input->stream.pp_areas[i_area_index]->i_start = 0;
p_input->stream.pp_areas[i_area_index]->i_size = 0;
p_input->stream.pp_areas[i_area_index]->i_tell = 0;
p_input->stream.pp_areas[i_area_index]->i_seek = 0;
p_input->stream.pp_areas[i_area_index]->i_part_nb = 0;
p_input->stream.pp_areas[i_area_index]->i_part= 0;
return p_input->stream.pp_areas[i_area_index];
}
/*****************************************************************************
* input_DelArea: destroy a area descriptor
*****************************************************************************
* All ES descriptions referenced in the descriptor will be deleted.
*****************************************************************************/
void input_DelArea( input_thread_t * p_input, input_area_t * p_area )
{
int i_area_index;
ASSERT( p_area );
intf_DbgMsg("Deleting description for area %d", p_area->i_number);
/* Find the area in the areas table */
for( i_area_index = 0; i_area_index < p_input->stream.i_area_nb;
i_area_index++ )
{
if( p_input->stream.pp_areas[i_area_index] == p_area )
break;
}
/* Remove this area from the stream's list of areas */
p_input->stream.i_area_nb--;
p_input->stream.pp_areas[i_area_index] =
p_input->stream.pp_areas[p_input->stream.i_area_nb];
p_input->stream.pp_areas = realloc( p_input->stream.pp_areas,
p_input->stream.i_area_nb
* sizeof(input_area_t *) );
if( p_input->stream.i_area_nb && p_input->stream.pp_areas == NULL)
{
intf_ErrMsg( "input error: unable to realloc area list"
" in input_Delarea" );
}
/* Free the description of this area */
free( p_area );
}
/*****************************************************************************
* input_FindES: returns a pointer to an ES described by its ID
*****************************************************************************/
......@@ -399,7 +484,7 @@ void input_DumpStream( input_thread_t * p_input )
intf_Msg( "input info: Dumping stream ID 0x%x", S.i_stream_id );
if( S.b_seekable )
intf_Msg( "input info: seekable stream, position: %lld/%lld",
S.i_tell, S.i_size );
S.pp_areas[0].i_tell, S.pp_areas[0].i_size );
else
intf_Msg( "input info: %s", S.b_pace_control ? "pace controlled" :
"pace un-controlled" );
......
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