1
mirror of https://code.videolan.org/videolan/vlc synced 2024-09-04 09:11:33 +02:00

-New function for DVD reading, that is able to read multiple blocks

(I've chosen 32 now), that doesn't use any memcpy anymore and is also much
faster. It is ready now for cell positioning in multi-angle DVD (to come
soon).

-DVD specific netlist adapted to 2048 bytes long blocks that contain
several data_packets.

-Modification in mpeg_system.c to use p_payload_start instead of
p_buffer (necessary for DVD plugin). It does not break other plugins
since they set p_payload_start to p_buffer

-New field i_read_once in input_thread_s to be able to read more than
the TS related 7 packets ; i_read_once is set to INPUT_READ_ONCE by
defaults but plugins can change it during initialisation.

Please check that nothing is broken :)
This commit is contained in:
Stéphane Borel 2001-03-02 03:32:46 +00:00
parent 2fe30f260b
commit 917d257428
9 changed files with 684 additions and 71 deletions

View File

@ -300,6 +300,7 @@ PLUGIN_DUMMY = plugins/dummy/dummy.o \
PLUGIN_DVD = plugins/dvd/dvd.o \
plugins/dvd/input_dvd.o \
plugins/dvd/dvd_netlist.o \
plugins/dvd/dvd_ioctl.o \
plugins/dvd/dvd_ifo.o \
plugins/dvd/dvd_udf.o \

View File

@ -2,7 +2,7 @@
* input_ext-dec.h: structures exported to the VideoLAN decoders
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: input_ext-dec.h,v 1.22 2001/02/08 17:44:12 massiot Exp $
* $Id: input_ext-dec.h,v 1.23 2001/03/02 03:32:46 stef Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Michel Kaempf <maxx@via.ecp.fr>
@ -40,6 +40,8 @@ typedef struct data_packet_s
byte_t * p_payload_end; /* guess ? :-) */
boolean_t b_discard_payload; /* is the packet messed up ? */
int * pi_refcount;
/* Used to chain the TS packets that carry data for a same PES or PSI */
struct data_packet_s * p_next;
} data_packet_t;

View File

@ -4,7 +4,7 @@
* control the pace of reading.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: input_ext-intf.h,v 1.26 2001/02/22 17:00:20 massiot Exp $
* $Id: input_ext-intf.h,v 1.27 2001/03/02 03:32:46 stef Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
@ -278,6 +278,8 @@ typedef struct input_thread_s
char * p_source;
int i_handle; /* socket or file descriptor */
int i_read_once; /* number of packet read by
* pf_read once */
void * p_method_data; /* data of the packet manager */
void * p_plugin_data; /* data of the plugin */

525
plugins/dvd/dvd_netlist.c Normal file
View File

@ -0,0 +1,525 @@
/*****************************************************************************
* dvd_netlist.c: Specific netlist for DVD packets
* ---
* The original is in src/input.
* There is only one major change from input_netlist.c : data is now a
* pointer to an offset in iovec ; and iovec has a reference counter. It
* will only be given back to netlist when refcount is zero.
*****************************************************************************
* Copyright (C) 1998, 1999, 2000, 2001 VideoLAN
* $Id: dvd_netlist.c,v 1.1 2001/03/02 03:32:46 stef Exp $
*
* Authors: Henri Fallon <henri@videolan.org>
* Stéphane Borel <stef@videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "defs.h"
#include <stdlib.h>
#include <sys/types.h>
#include <sys/uio.h> /* struct iovec */
#include <unistd.h>
#include "config.h"
#include "common.h"
#include "threads.h" /* mutex */
#include "mtime.h"
#include "intf_msg.h" /* intf_*Msg */
#include "stream_control.h"
#include "input_ext-intf.h"
#include "input_ext-dec.h"
#include "input.h"
#include "dvd_netlist.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
/*****************************************************************************
* DVDNetlistInit: allocates netlist buffers and init indexes
* ---
* Changes from input_NetList: we have to give the length of the buffer which
* is different from i_nb_data now, since we may have several data pointers
* in one iovec. Thus we can only delete an iovec when its refcount is 0.
* We only received a buffer with a GetIovec whereas NewPacket gives a pointer.
*
* Warning: i_nb_iovec, i_nb_data, i_nb_pes have to be 2^x
*****************************************************************************/
int DVDNetlistInit( input_thread_t * p_input,
int i_nb_iovec, int i_nb_data, int i_nb_pes,
size_t i_buffer_size, int i_read_once )
{
unsigned int i_loop;
netlist_t * p_netlist;
/* First we allocate and initialise our netlist struct */
p_input->p_method_data = malloc(sizeof(netlist_t));
if ( p_input->p_method_data == NULL )
{
intf_ErrMsg("Unable to malloc the DVD netlist struct");
return (-1);
}
p_netlist = (netlist_t *) p_input->p_method_data;
/* Nb of packets read once by input */
p_netlist->i_read_once = i_read_once;
/* allocate the buffers */
p_netlist->p_buffers = malloc( i_nb_iovec *i_buffer_size );
if ( p_netlist->p_buffers == NULL )
{
intf_ErrMsg ("Unable to malloc in DVD netlist initialization (1)");
return (-1);
}
/* table of pointers to data packets */
p_netlist->p_data = malloc( i_nb_data *sizeof(data_packet_t) );
if ( p_netlist->p_data == NULL )
{
intf_ErrMsg ("Unable to malloc in DVD netlist initialization (2)");
return (-1);
}
/* table of pointer to PES packets */
p_netlist->p_pes = malloc( i_nb_pes *sizeof(pes_packet_t) );
if ( p_netlist->p_pes == NULL )
{
intf_ErrMsg ("Unable to malloc in DVD netlist initialization (3)");
return (-1);
}
/* allocate the FIFOs : tables of free pointers */
p_netlist->pp_free_data =
malloc( i_nb_data *sizeof(data_packet_t *) );
if ( p_netlist->pp_free_data == NULL )
{
intf_ErrMsg ("Unable to malloc in DVD netlist initialization (4)");
}
p_netlist->pp_free_pes =
malloc( i_nb_pes *sizeof(pes_packet_t *) );
if ( p_netlist->pp_free_pes == NULL )
{
intf_ErrMsg ("Unable to malloc in DVD netlist initialization (5)");
}
p_netlist->p_free_iovec =
malloc( (i_nb_iovec + p_netlist->i_read_once) * sizeof(struct iovec) );
if ( p_netlist->p_free_iovec == NULL )
{
intf_ErrMsg ("Unable to malloc in DVD netlist initialization (6)");
}
/* table for reference counter of iovecs */
p_netlist->pi_refcount = malloc( i_nb_iovec *sizeof(int) );
if ( p_netlist->pi_refcount == NULL )
{
intf_ErrMsg ("Unable to malloc in DVD netlist initialization (7)");
return (-1);
}
/* Fill the data FIFO */
for ( i_loop = 0; i_loop < i_nb_data; i_loop++ )
{
p_netlist->pp_free_data[i_loop] =
p_netlist->p_data + i_loop;
}
/* Fill the PES FIFO */
for ( i_loop = 0; i_loop < i_nb_pes ; i_loop++ )
{
p_netlist->pp_free_pes[i_loop] =
p_netlist->p_pes + i_loop;
}
/* Deal with the iovec */
for ( i_loop = 0; i_loop < i_nb_iovec; i_loop++ )
{
p_netlist->p_free_iovec[i_loop].iov_base =
p_netlist->p_buffers + i_loop * i_buffer_size;
p_netlist->p_free_iovec[i_loop].iov_len = i_buffer_size;
}
/* initialize reference counters */
memset( p_netlist->pi_refcount, 0, i_nb_iovec *sizeof(int) );
/* vlc_mutex_init */
vlc_mutex_init (&p_netlist->lock);
/* initialize indexes */
p_netlist->i_iovec_start = 0;
p_netlist->i_iovec_end = i_nb_iovec - 1;
p_netlist->i_data_start = 0;
p_netlist->i_data_end = i_nb_data - 1;
p_netlist->i_pes_start = 0;
p_netlist->i_pes_end = i_nb_pes - 1;
/* we give (nb - 1) to use & instead of %
* if you really need nb you have to add 1 */
p_netlist->i_nb_iovec = i_nb_iovec - 1;
p_netlist->i_nb_data = i_nb_data - 1;
p_netlist->i_nb_pes = i_nb_pes - 1;
p_netlist->i_buffer_size = i_buffer_size;
return (0); /* Everything went all right */
}
/*****************************************************************************
* DVDGetiovec: returns an iovec pointer for a readv() operation
*****************************************************************************
* We return an iovec vector, so that readv can read many packets at a time,
* and we set pp_data to direct to the fifo pointer, which will allow us
* to get the corresponding data_packet.
*****************************************************************************/
struct iovec * DVDGetiovec( void * p_method_data )
{
netlist_t * p_netlist;
/* cast */
p_netlist = ( netlist_t * ) p_method_data;
/* check */
if( (
(p_netlist->i_iovec_end - p_netlist->i_iovec_start)
& p_netlist->i_nb_iovec ) < p_netlist->i_read_once )
{
intf_ErrMsg("Empty iovec FIFO. Unable to allocate memory");
return (NULL);
}
/* readv only takes contiguous buffers
* so, as a solution, we chose to have a FIFO a bit longer
* than i_nb_data, and copy the begining of the FIFO to its end
* if the readv needs to go after the end */
if( p_netlist->i_nb_iovec - p_netlist->i_iovec_start + 1 <
p_netlist->i_read_once )
{
memcpy( &p_netlist->p_free_iovec[p_netlist->i_nb_iovec + 1],
p_netlist->p_free_iovec,
(p_netlist->i_read_once -
(p_netlist->i_nb_iovec + 1 - p_netlist->i_iovec_start))
* sizeof(struct iovec)
);
}
return p_netlist->p_free_iovec + p_netlist->i_iovec_start;
}
/*****************************************************************************
* DVDMviovec: move the iovec pointer by one after a readv() operation and
* gives a data_packet corresponding to iovec in p_data
*****************************************************************************/
void DVDMviovec( void * p_method_data, int i_nb_iovec,
struct data_packet_s ** pp_data )
{
netlist_t * p_netlist;
unsigned int i_loop = 0;
/* cast */
p_netlist = (netlist_t *)p_method_data;
/* lock */
vlc_mutex_lock( &p_netlist->lock );
/* Fills a table of pointers to packets associated with the io_vec's */
while( i_loop < i_nb_iovec )
{
pp_data[i_loop] = p_netlist->pp_free_data[p_netlist->i_data_start];
pp_data[i_loop]->p_buffer =
p_netlist->p_free_iovec[p_netlist->i_iovec_start].iov_base;
pp_data[i_loop]->pi_refcount = p_netlist->pi_refcount +
p_netlist->i_iovec_start;
p_netlist->i_iovec_start ++;
p_netlist->i_iovec_start &= p_netlist->i_nb_iovec;
p_netlist->i_data_start ++;
p_netlist->i_data_start &= p_netlist->i_nb_data;
i_loop ++;
}
/* unlock */
vlc_mutex_unlock( &p_netlist->lock );
}
/*****************************************************************************
* DVDNewPtr: returns a free data_packet_t
* Gives a pointer ; its fields need to be initialized
*****************************************************************************/
struct data_packet_s * DVDNewPtr( void * p_method_data )
{
netlist_t * p_netlist;
struct data_packet_s * p_return;
/* cast */
p_netlist = ( netlist_t * ) p_method_data;
#ifdef DEBUG
if( i_buffer_size > p_netlist->i_buffer_size )
{
/* This should not happen */
intf_ErrMsg( "Netlist packet too small !" );
return NULL;
}
#endif
/* lock */
vlc_mutex_lock ( &p_netlist->lock );
/* check */
if ( p_netlist->i_data_start == p_netlist->i_data_end )
{
intf_ErrMsg("Empty Data FIFO in netlist. Unable to allocate memory");
return ( NULL );
}
p_return = (p_netlist->pp_free_data[p_netlist->i_data_start]);
p_netlist->i_data_start++;
p_netlist->i_data_start &= p_netlist->i_nb_data;
/* unlock */
vlc_mutex_unlock (&p_netlist->lock);
return ( p_return );
}
/*****************************************************************************
* DVDNewPacket: returns a free data_packet_t, and takes a corresponding
* storage iovec
*****************************************************************************/
struct data_packet_s * DVDNewPacket( void * p_method_data,
size_t i_buffer_size )
{
netlist_t * p_netlist;
struct data_packet_s * p_packet;
/* cast */
p_netlist = (netlist_t *)p_method_data;
/* lock */
vlc_mutex_lock( &p_netlist->lock );
/* check */
if ( p_netlist->i_iovec_start == p_netlist->i_iovec_end )
{
intf_ErrMsg("Empty io_vec FIFO in netlist. Unable to allocate memory");
return ( NULL );
}
if ( p_netlist->i_data_start == p_netlist->i_data_end )
{
intf_ErrMsg("Empty Data FIFO in netlist. Unable to allocate memory");
return ( NULL );
}
/* Gives an io_vec and associated data */
p_packet = p_netlist->pp_free_data[p_netlist->i_data_start];
p_packet->p_buffer =
p_netlist->p_free_iovec[p_netlist->i_iovec_start].iov_base;
p_packet->p_payload_start = p_packet->p_buffer;
p_packet->p_payload_end =
p_packet->p_buffer + i_buffer_size;
p_packet->pi_refcount = p_netlist->pi_refcount + p_netlist->i_iovec_start;
p_netlist->i_iovec_start ++;
p_netlist->i_iovec_start &= p_netlist->i_nb_iovec;
p_netlist->i_data_start ++;
p_netlist->i_data_start &= p_netlist->i_nb_data;
/* unlock */
vlc_mutex_unlock( &p_netlist->lock );
return p_packet;
}
/*****************************************************************************
* DVDNewPES: returns a free pes_packet_t
*****************************************************************************/
struct pes_packet_s * DVDNewPES( void * p_method_data )
{
netlist_t * p_netlist;
pes_packet_t * p_return;
/* cast */
p_netlist = (netlist_t *) p_method_data;
/* lock */
vlc_mutex_lock ( &p_netlist->lock );
/* check */
if ( p_netlist->i_pes_start == p_netlist->i_pes_end )
{
intf_ErrMsg("Empty PES FIFO in netlist - Unable to allocate memory");
return ( NULL );
}
/* allocate */
p_return = p_netlist->pp_free_pes[p_netlist->i_pes_start];
p_netlist->i_pes_start++;
p_netlist->i_pes_start &= p_netlist->i_nb_pes;
/* unlock */
vlc_mutex_unlock (&p_netlist->lock);
/* initialize PES */
p_return->b_data_alignment =
p_return->b_discontinuity =
p_return->i_pts = p_return->i_dts = 0;
p_return->i_pes_size = 0;
p_return->p_first = NULL;
return ( p_return );
}
/*****************************************************************************
* DVDDeletePacket: puts a data_packet_t back into the netlist
*****************************************************************************/
void DVDDeletePacket( void * p_method_data, data_packet_t * p_data )
{
netlist_t * p_netlist;
/* cast */
p_netlist = (netlist_t *) p_method_data;
/* lock */
vlc_mutex_lock ( &p_netlist->lock );
/* Delete data_packet */
p_netlist->i_data_end ++;
p_netlist->i_data_end &= p_netlist->i_nb_data;
p_netlist->pp_free_data[p_netlist->i_data_end] = p_data;
/* Update reference counter */
(*p_data->pi_refcount)--;
if( (*p_data->pi_refcount) == 0 )
{
p_netlist->i_iovec_end++;
p_netlist->i_iovec_end &= p_netlist->i_nb_iovec;
p_netlist->p_free_iovec[p_netlist->i_iovec_end].iov_base =
p_data->p_buffer;
}
/* re initialize for next time */
p_data->p_next = NULL;
p_data->b_discard_payload = 0;
/* unlock */
vlc_mutex_unlock (&p_netlist->lock);
}
/*****************************************************************************
* DVDDeletePES: puts a pes_packet_t back into the netlist
*****************************************************************************/
void DVDDeletePES( void * p_method_data, pes_packet_t * p_pes )
{
netlist_t * p_netlist;
data_packet_t * p_current_packet,* p_next_packet;
/* cast */
p_netlist = (netlist_t *)p_method_data;
/* lock */
vlc_mutex_lock ( &p_netlist->lock );
/* delete free p_pes->p_first, p_next ... */
p_current_packet = p_pes->p_first;
while ( p_current_packet != NULL )
{
/* copy of NetListDeletePacket, duplicate code avoid many locks */
p_netlist->i_data_end ++;
p_netlist->i_data_end &= p_netlist->i_nb_data;
/* re initialize*/
p_current_packet->p_payload_start = p_current_packet->p_buffer;
p_netlist->pp_free_data[p_netlist->i_data_end] = p_current_packet;
/* Update reference counter */
(*p_current_packet->pi_refcount)--;
if( (*p_current_packet->pi_refcount) == 0 )
{
p_netlist->i_iovec_end++;
p_netlist->i_iovec_end &= p_netlist->i_nb_iovec;
p_netlist->p_free_iovec[p_netlist->i_iovec_end].iov_base =
p_current_packet->p_buffer;
}
p_next_packet = p_current_packet->p_next;
p_current_packet->p_next = NULL;
p_current_packet = p_next_packet;
}
/* delete our current PES packet */
p_netlist->i_pes_end ++;
p_netlist->i_pes_end &= p_netlist->i_nb_pes;
p_netlist->pp_free_pes[p_netlist->i_pes_end] = p_pes;
/* unlock */
vlc_mutex_unlock (&p_netlist->lock);
}
/*****************************************************************************
* DVDNetlistEnd: frees all allocated structures
*****************************************************************************/
void DVDNetlistEnd( input_thread_t * p_input)
{
netlist_t * p_netlist;
/* cast */
p_netlist = ( netlist_t * ) p_input->p_method_data;
/* destroy the mutex lock */
vlc_mutex_destroy (&p_netlist->lock);
/* free the FIFO, the buffer, and the netlist structure */
free (p_netlist->pp_free_data);
free (p_netlist->pp_free_pes);
free (p_netlist->pi_refcount);
free (p_netlist->p_pes);
free (p_netlist->p_data);
free (p_netlist->p_buffers);
/* free the netlist */
free (p_netlist);
}

75
plugins/dvd/dvd_netlist.h Normal file
View File

@ -0,0 +1,75 @@
/*****************************************************************************
* dvd_netlist.h: Specific netlist structures for DVD packets
*****************************************************************************
* Copyright (C) 1998, 1999, 2000, 2001 VideoLAN
* $Id: dvd_netlist.h,v 1.1 2001/03/02 03:32:46 stef Exp $
*
* Authors: Henri Fallon <henri@videolan.org>
* Stéphane Borel <stef@videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* netlist_t: structure to manage a netlist
*****************************************************************************/
typedef struct netlist_s
{
vlc_mutex_t lock;
size_t i_buffer_size;
/* Buffers */
byte_t * p_buffers; /* Big malloc'ed area */
data_packet_t * p_data; /* malloc'ed area */
pes_packet_t * p_pes; /* malloc'ed area */
/* FIFOs of free packets */
data_packet_t ** pp_free_data;
pes_packet_t ** pp_free_pes;
struct iovec * p_free_iovec;
/* FIFO size */
unsigned int i_nb_iovec;
unsigned int i_nb_pes;
unsigned int i_nb_data;
/* Index */
unsigned int i_iovec_start, i_iovec_end;
unsigned int i_data_start, i_data_end;
unsigned int i_pes_start, i_pes_end;
/* Reference counters for iovec */
unsigned int * pi_refcount;
/* Nb of packets read once */
unsigned int i_read_once;
} netlist_t;
/*****************************************************************************
* Prototypes
*****************************************************************************/
int DVDNetlistInit( struct input_thread_s *,
int , int, int, size_t, int );
struct iovec * DVDGetiovec( void * p_method_data );
void DVDMviovec( void * , int, struct data_packet_s **);
struct data_packet_s * DVDNewPtr( void * );
struct data_packet_s * DVDNewPacket( void *, size_t );
struct pes_packet_s * DVDNewPES( void * );
void DVDDeletePacket( void *, struct data_packet_s * );
void DVDDeletePES( void *, struct pes_packet_s * );
void DVDNetlistEnd( struct input_thread_s * );

View File

@ -10,7 +10,7 @@
* -dvd_udf to find files
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: input_dvd.c,v 1.21 2001/02/26 12:16:28 sam Exp $
* $Id: input_dvd.c,v 1.22 2001/03/02 03:32:46 stef Exp $
*
* Author: Stéphane Borel <stef@via.ecp.fr>
*
@ -65,8 +65,8 @@
#include "input_ext-dec.h"
#include "input.h"
#include "input_netlist.h"
#include "dvd_netlist.h"
#include "dvd_ifo.h"
#include "dvd_css.h"
#include "input_dvd.h"
@ -262,10 +262,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list )
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;
input.pf_delete_packet = input_NetlistDeletePacket;
input.pf_delete_pes = input_NetlistDeletePES;
input.pf_new_packet = DVDNewPacket;
input.pf_new_pes = DVDNewPES;
input.pf_delete_packet = DVDDeletePacket;
input.pf_delete_pes = DVDDeletePES;
input.pf_rewind = DVDRewind;
input.pf_seek = DVDSeek;
#undef input
@ -487,7 +487,8 @@ static int DVDSetArea( input_thread_t * p_input,
{
#if 0
fprintf( stderr, "Audio %d: %x %x %x %x %x %x\n", i,
fprintf( stderr, "Audio %d: %x %x %x %x %x %x %x\n", i,
p_method->ifo.vts.mat.p_audio_atrt[i].i_num_channels,
p_method->ifo.vts.mat.p_audio_atrt[i].i_coding_mode,
p_method->ifo.vts.mat.p_audio_atrt[i].i_multichannel_extension,
p_method->ifo.vts.mat.p_audio_atrt[i].i_type,
@ -674,15 +675,17 @@ static void DVDInit( input_thread_t * p_input )
p_input->p_method_data = NULL;
p_method->i_fd = p_input->i_handle;
/* FIXME: read several packets once */
p_method->i_read_once = 1;
p_method->i_block_once = 32;
p_input->i_read_once = 128;
p_method->b_encrypted = DVDCheckCSS( p_input );
lseek( p_input->i_handle, 0, SEEK_SET );
/* Reading structures initialisation */
input_NetlistInit( p_input, 4096, 4096, DVD_LB_SIZE,
p_method->i_read_once );
DVDNetlistInit( p_input, 4096, 16384, 4096, DVD_LB_SIZE,
p_method->i_block_once );
intf_WarnMsg( 2, "DVD: Netlist initialized" );
/* Ifo initialisation */
@ -781,7 +784,7 @@ static void DVDEnd( input_thread_t * p_input )
// IfoEnd( (ifo_t*)(&p_input->p_plugin_data->ifo ) );
free( p_input->stream.p_demux_data );
free( p_input->p_plugin_data );
input_NetlistEnd( p_input );
DVDNetlistEnd( p_input );
}
/*****************************************************************************
@ -791,59 +794,57 @@ static void DVDEnd( input_thread_t * p_input )
* EOF.
*****************************************************************************/
static int DVDRead( input_thread_t * p_input,
data_packet_t ** pp_packets )
data_packet_t ** pp_packets )
{
thread_dvd_data_t * p_method;
netlist_t * p_netlist;
struct iovec * p_vec;
struct data_packet_s * p_data;
struct data_packet_s * pp_data[p_input->i_read_once];
u8 * pi_cur;
int i_packet_size;
int i_iovec;
int i_packet;
int i_pos;
int i;
boolean_t b_first_packet;
p_method = ( thread_dvd_data_t * ) p_input->p_plugin_data;
p_netlist = ( netlist_t * ) p_input->p_method_data;
/* Get an iovec pointer */
if( ( p_vec = input_NetlistGetiovec( p_netlist ) ) == NULL )
if( ( p_vec = DVDGetiovec( p_netlist ) ) == NULL )
{
intf_ErrMsg( "DVD: read error" );
return -1;
}
/* Reads from DVD */
readv( p_input->i_handle, p_vec, p_method->i_read_once );
if( p_method->b_encrypted )
{
for( i=0 ; i<p_method->i_read_once ; i++ )
{
CSSDescrambleSector( p_method->css.pi_title_key,
p_vec[i].iov_base );
((u8*)(p_vec[i].iov_base))[0x14] &= 0x8F;
}
}
readv( p_input->i_handle, p_vec, p_method->i_block_once );
/* Update netlist indexes */
input_NetlistMviovec( p_netlist, p_method->i_read_once, &p_data );
DVDMviovec( p_netlist, p_method->i_block_once, pp_data );
i_packet = 0;
/* Read headers to compute payload length */
for( i = 0 ; i < p_method->i_read_once ; i++ )
for( i_iovec = 0 ; i_iovec < p_method->i_block_once ; i_iovec++ )
{
if( p_method->b_encrypted )
{
CSSDescrambleSector( p_method->css.pi_title_key,
p_vec[i_iovec].iov_base );
((u8*)(p_vec[i_iovec].iov_base))[0x14] &= 0x8F;
}
i_pos = 0;
b_first_packet = 1;
while( i_pos < p_netlist->i_buffer_size )
{
pi_cur = (u8*)(p_vec[i].iov_base + i_pos);
pi_cur = (u8*)(p_vec[i_iovec].iov_base + i_pos);
/*default header */
if( U32_AT( pi_cur ) != 0x1BA )
{
/* That's the case for all packets, except pack header. */
i_packet_size = U16_AT( pi_cur + 4 );
pp_packets[i_packet] = DVDNewPtr( p_netlist );
}
else
{
@ -863,31 +864,33 @@ static int DVDRead( input_thread_t * p_input,
intf_ErrMsg( "Unable to determine stream type" );
return( -1 );
}
}
if( b_first_packet )
{
p_data->b_discard_payload = 0;
b_first_packet = 0;
}
else
{
p_data = input_NetlistNewPacket( p_netlist ,
i_packet_size + 6 );
memcpy( p_data->p_buffer,
p_vec[i].iov_base + i_pos , i_packet_size + 6 );
pp_packets[i_packet] = pp_data[i_iovec];
}
p_data->p_payload_end = p_data->p_payload_start + i_packet_size + 6;
pp_packets[i_packet] = p_data;
(*pp_data[i_iovec]->pi_refcount)++;
pp_packets[i_packet]->pi_refcount = pp_data[i_iovec]->pi_refcount;
pp_packets[i_packet]->p_buffer = pp_data[i_iovec]->p_buffer;
pp_packets[i_packet]->p_payload_start =
pp_packets[i_packet]->p_buffer + i_pos;
pp_packets[i_packet]->p_payload_end =
pp_packets[i_packet]->p_payload_start + i_packet_size + 6;
i_packet++;
i_pos += i_packet_size + 6;
}
}
pp_packets[i_packet] = NULL;
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.p_selected_area->i_tell +=
p_method->i_read_once *DVD_LB_SIZE;
p_method->i_block_once *DVD_LB_SIZE;
vlc_mutex_unlock( &p_input->stream.stream_lock );
return( 0 );

View File

@ -33,7 +33,9 @@ typedef struct thread_dvd_data_s
{
int i_fd; // File descriptor of device
boolean_t b_encrypted; // CSS encryption
int i_read_once; // NB of bytes read by DVDRead
int i_block_once; // Nb of block read once by
// readv
int i_chapter_nb;
off_t i_start;

View File

@ -4,7 +4,7 @@
* decoders.
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: input.c,v 1.87 2001/02/20 09:10:36 sam Exp $
* $Id: input.c,v 1.88 2001/03/02 03:32:46 stef Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
@ -89,6 +89,9 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
return( NULL );
}
/* Packets read once */
p_input->i_read_once = INPUT_READ_ONCE;
/* Initialize thread properties */
p_input->b_die = 0;
p_input->b_error = 0;
@ -193,7 +196,6 @@ void input_DestroyThread( input_thread_t *p_input, int *pi_status )
*****************************************************************************/
static void RunThread( input_thread_t *p_input )
{
data_packet_t * pp_packets[INPUT_READ_ONCE];
int i_error, i;
if( InitThread( p_input ) )
@ -209,6 +211,7 @@ static void RunThread( input_thread_t *p_input )
while( !p_input->b_die && !p_input->b_error && !p_input->b_eof )
{
data_packet_t * pp_packets[p_input->i_read_once];
#ifdef STATS
p_input->c_loops++;
@ -241,7 +244,7 @@ static void RunThread( input_thread_t *p_input )
i_error = p_input->pf_read( p_input, pp_packets );
/* Demultiplex read packets. */
for( i = 0; i < INPUT_READ_ONCE && pp_packets[i] != NULL; i++ )
for( i = 0; i < p_input->i_read_once && pp_packets[i] != NULL; i++ )
{
p_input->pf_demux( p_input, pp_packets[i] );
}

View File

@ -2,7 +2,7 @@
* mpeg_system.c: TS, PS and PES management
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: mpeg_system.c,v 1.38 2001/02/21 04:38:59 henri Exp $
* $Id: mpeg_system.c,v 1.39 2001/03/02 03:32:46 stef Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Michel Lespinasse <walken@via.ecp.fr>
@ -500,11 +500,11 @@ static u16 GetID( data_packet_t * p_data )
{
u16 i_id;
i_id = p_data->p_buffer[3]; /* stream_id */
i_id = p_data->p_payload_start[3]; /* stream_id */
if( i_id == 0xBD )
{
/* stream_private_id */
i_id |= p_data->p_buffer[ 9 + p_data->p_buffer[8] ] << 8;
i_id |= p_data->p_payload_start[ 9 + p_data->p_payload_start[8] ] << 8;
}
return( i_id );
}
@ -528,7 +528,7 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
}
if( p_demux->b_has_PSM
&& p_demux->i_PSM_version == (p_data->p_buffer[6] & 0x1F) )
&& p_demux->i_PSM_version == (p_data->p_payload_start[6] & 0x1F) )
{
/* Already got that one. */
return;
@ -536,7 +536,7 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
intf_DbgMsg( "Building PSM" );
p_demux->b_has_PSM = 1;
p_demux->i_PSM_version = p_data->p_buffer[6] & 0x1F;
p_demux->i_PSM_version = p_data->p_payload_start[6] & 0x1F;
/* Go to elementary_stream_map_length, jumping over
* program_stream_info. */
@ -647,7 +647,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input,
u32 i_code;
es_descriptor_t * p_es = NULL;
i_code = U32_AT( p_data->p_buffer );
i_code = U32_AT( p_data->p_payload_start );
if( i_code > 0x1BC ) /* ES start code */
{
u16 i_id;
@ -685,7 +685,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input,
i_id, 0 );
if( p_es != NULL )
{
p_es->i_stream_id = p_data->p_buffer[3];
p_es->i_stream_id = p_data->p_payload_start[3];
/* Set stream type and auto-spawn. */
if( (i_id & 0xF0) == 0xE0 )
@ -777,7 +777,7 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
boolean_t b_trash = 0;
es_descriptor_t * p_es = NULL;
i_code = U32_AT( p_data->p_buffer );
i_code = U32_AT( p_data->p_payload_start );
if( i_code <= 0x1BC )
{
switch( i_code )
@ -788,30 +788,30 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
mtime_t scr_time;
u32 i_mux_rate;
if( (p_data->p_buffer[4] & 0xC0) == 0x40 )
if( (p_data->p_payload_start[4] & 0xC0) == 0x40 )
{
/* MPEG-2 */
scr_time =
((mtime_t)(p_data->p_buffer[4] & 0x38) << 27) |
((mtime_t)(U32_AT(p_data->p_buffer + 4) & 0x03FFF800)
((mtime_t)(p_data->p_payload_start[4] & 0x38) << 27) |
((mtime_t)(U32_AT(p_data->p_payload_start + 4) & 0x03FFF800)
<< 4) |
((mtime_t)(U32_AT(p_data->p_buffer + 6) & 0x03FFF800)
((mtime_t)(U32_AT(p_data->p_payload_start + 6) & 0x03FFF800)
>> 11);
/* mux_rate */
i_mux_rate = (U32_AT(p_data->p_buffer + 10) & 0xFFFFFC00);
i_mux_rate = (U32_AT(p_data->p_payload_start + 10) & 0xFFFFFC00);
}
else
{
/* MPEG-1 SCR is like PTS. */
scr_time =
((mtime_t)(p_data->p_buffer[4] & 0x0E) << 29) |
(((mtime_t)U16_AT(p_data->p_buffer + 5) << 14)
((mtime_t)(p_data->p_payload_start[4] & 0x0E) << 29) |
(((mtime_t)U16_AT(p_data->p_payload_start + 5) << 14)
- (1 << 14)) |
((mtime_t)U16_AT(p_data->p_buffer + 7) >> 1);
((mtime_t)U16_AT(p_data->p_payload_start + 7) >> 1);
/* mux_rate */
i_mux_rate = (U32_AT(p_data->p_buffer + 8) & 0x8FFFFE);
i_mux_rate = (U32_AT(p_data->p_payload_start + 8) & 0x8FFFFE);
}
/* Call the pace control. */
input_ClockManageRef( p_input, p_input->stream.pp_programs[0],