Commit 949a4ce2 authored by Laurent Aimar's avatar Laurent Aimar

* all: reworked stream output. Now it handles mutliples outputs from

one input, just type --sout "<first url>#<second url>#..." (Yes it
is awfull, but I need suggestion).
   udp: correctly update sequence number in rtp.
parent 4befbe94
......@@ -2,7 +2,7 @@
* stream_output.h : stream output module
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: stream_output.h,v 1.8 2003/02/25 17:17:43 fenrir Exp $
* $Id: stream_output.h,v 1.9 2003/03/11 19:02:30 fenrir Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Laurent Aimar <fenrir@via.ecp.fr>
......@@ -63,7 +63,6 @@ struct sout_packet_format_t
vlc_fourcc_t i_fourcc;
void *p_format; // WAVEFORMATEX or BITMAPINFOHEADER
};
struct sout_fifo_t
......@@ -76,23 +75,39 @@ struct sout_fifo_t
sout_buffer_t **pp_last;
};
/* for mux */
struct sout_input_t
{
vlc_mutex_t lock;
// vlc_mutex_t lock;
sout_instance_t *p_sout;
sout_packet_format_t input_format;
sout_fifo_t *p_fifo;
void *p_mux_data;
void *p_sys;
};
/* for packetizr */
struct sout_packetizer_input_t
{
sout_instance_t *p_sout;
sout_packet_format_t input_format;
// vlc_mutex_t lock;
int i_nb_inputs;
sout_input_t **pp_inputs;
int i_nb_mux; // not really used, just usefull with TAB_*
sout_mux_t **pp_mux;
};
#define SOUT_METHOD_NONE 0x00
#define SOUT_METHOD_FILE 0x10
#define SOUT_METHOD_NETWORK 0x20
struct sout_access_out_t
{
VLC_COMMON_MEMBERS
......@@ -123,38 +138,72 @@ struct sout_access_out_t
#define SOUT_MUX_CAP_ERR_UNKNOWN 0x01
#define SOUT_MUX_CAP_ERR_UNIMPLEMENTED 0x02
typedef struct sout_instance_sys_t sout_instance_sys_t;
struct sout_instance_t
typedef struct sout_mux_sys_t sout_mux_sys_t;
struct sout_mux_t
{
VLC_COMMON_MEMBERS
module_t *p_module;
sout_instance_t *p_sout;
char * psz_dest;
char * psz_access;
char * psz_mux;
char * psz_name;
int i_method;
char *psz_mux;
sout_access_out_t *p_access;
module_t *p_mux;
void *p_mux_data;
int i_mux_preheader;
int (* pf_mux_capacity) ( sout_instance_t *,
int i_preheader;
int (* pf_capacity) ( sout_mux_t *,
int, void *, void *);
int (* pf_mux_addstream )( sout_instance_t *,
int (* pf_addstream )( sout_mux_t *,
sout_input_t * );
int (* pf_mux_delstream )( sout_instance_t *,
int (* pf_delstream )( sout_mux_t *,
sout_input_t * );
int (* pf_mux ) ( sout_instance_t * );
int (* pf_mux ) ( sout_mux_t * );
vlc_mutex_t lock;
/* here are all inputs accepted by muxer */
int i_nb_inputs;
sout_input_t **pp_inputs;
/* mux private */
sout_mux_sys_t *p_sys;
// /* creater private */
// void *p_sys_owner;
/* XXX private to stream_output.c */
/* if muxer doesn't support adding stream at any time then we first wait
* for stream then we refuse all stream and start muxing */
vlc_bool_t b_add_stream_any_time;
vlc_bool_t b_waiting_stream;
/* we wait one second after first stream added */
mtime_t i_add_stream_start;
};
typedef struct sout_instance_sys_t sout_instance_sys_t;
struct sout_instance_t
{
VLC_COMMON_MEMBERS
/* complete sout string like udp/ts:239.255.12.42#file/ps://essai.ps */
char * psz_sout;
/* here are stored the parsed psz_sout */
int i_nb_dest;
char **ppsz_dest;
/* muxer data */
int i_preheader; /* max over all muxer */
int i_nb_mux;
sout_mux_t **pp_mux;
/* here are all packetizer inputs accepted by at least one muxer */
vlc_mutex_t lock;
int i_nb_inputs;
sout_packetizer_input_t **pp_inputs;
/* sout private */
sout_instance_sys_t *p_sys;
};
......@@ -178,9 +227,9 @@ VLC_EXPORT( sout_buffer_t *, sout_FifoShow, ( sout_fifo_t * ) );
#define sout_InputNew( a, b ) __sout_InputNew( VLC_OBJECT(a), b )
VLC_EXPORT( sout_input_t *, __sout_InputNew, ( vlc_object_t *, sout_packet_format_t * ) );
VLC_EXPORT( int, sout_InputDelete, ( sout_input_t * ) );
VLC_EXPORT( int, sout_InputSendBuffer, ( sout_input_t *, sout_buffer_t* ) );
VLC_EXPORT( sout_packetizer_input_t *, __sout_InputNew, ( vlc_object_t *, sout_packet_format_t * ) );
VLC_EXPORT( int, sout_InputDelete, ( sout_packetizer_input_t * ) );
VLC_EXPORT( int, sout_InputSendBuffer, ( sout_packetizer_input_t *, sout_buffer_t* ) );
VLC_EXPORT( sout_buffer_t*, sout_BufferNew, ( sout_instance_t *, size_t ) );
VLC_EXPORT( int, sout_BufferRealloc,( sout_instance_t *, sout_buffer_t*, size_t ) );
......
......@@ -3,7 +3,7 @@
* Collection of useful common types and macros definitions
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: vlc_common.h,v 1.57 2003/03/04 21:12:04 gbazin Exp $
* $Id: vlc_common.h,v 1.58 2003/03/11 19:02:30 fenrir Exp $
*
* Authors: Samuel Hocevar <sam@via.ecp.fr>
* Vincent Seguin <seguin@via.ecp.fr>
......@@ -247,9 +247,11 @@ typedef struct subpicture_sys_t subpicture_sys_t;
typedef struct sout_instance_t sout_instance_t;
typedef struct sout_fifo_t sout_fifo_t;
typedef struct sout_input_t sout_input_t;
typedef struct sout_packetizer_input_t sout_packetizer_input_t;
typedef struct sout_buffer_t sout_buffer_t;
typedef struct sout_packet_format_t sout_packet_format_t;
typedef struct sout_access_out_t sout_access_out_t;
typedef struct sout_mux_t sout_mux_t;
typedef struct sout_access_out_sys_t sout_access_out_sys_t;
/* Decoders */
......
......@@ -2,7 +2,7 @@
* udp.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: udp.c,v 1.5 2003/03/03 14:21:08 gbazin Exp $
* $Id: udp.c,v 1.6 2003/03/11 19:02:30 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
......@@ -125,18 +125,11 @@ static int Open( vlc_object_t *p_this )
return( VLC_EGENERIC );
}
if( p_access->psz_access != NULL &&
!strcmp( p_access->psz_access, "rtp" ) )
{
if( p_access->p_sout->psz_mux != NULL &&
*p_access->p_sout->psz_mux &&
strcmp( p_access->p_sout->psz_mux, "ts" ) &&
strcmp( p_access->p_sout->psz_mux, "ts_dvbpsi" ) )
{
msg_Err( p_access, "rtp ouput work only with ts payload" );
free( p_sys );
return( VLC_EGENERIC );
}
msg_Warn( p_access, "becarefull that rtp ouput work only with ts payload(not an error)" );
p_sys->b_rtpts = 1;
}
else
......@@ -203,9 +196,10 @@ static int Open( vlc_object_t *p_this )
return( VLC_EGENERIC );
}
srand( (uint32_t)mdate());
p_sys->p_buffer = NULL;
p_sys->i_sequence_number = 12; // FIXME should be random, used by rtp
p_sys->i_ssrc = 4212; // FIXME " " " " " "
p_sys->i_sequence_number = rand()&0xffff;
p_sys->i_ssrc = rand()&0xffffffff;
p_access->pf_write = Write;
p_access->pf_seek = Seek;
......@@ -300,10 +294,12 @@ static int Write( sout_access_out_t *p_access, sout_buffer_t *p_buffer )
/* add rtp/ts header */
p_sys->p_buffer->p_buffer[0] = 0x80;
p_sys->p_buffer->p_buffer[1] = 0x21; // mpeg2-ts
p_sys->p_buffer->p_buffer[2] =
( p_sys->i_sequence_number >> 8 )&0xff;
p_sys->p_buffer->p_buffer[3] =
p_sys->i_sequence_number&0xff;
p_sys->i_sequence_number++;
p_sys->p_buffer->p_buffer[4] = ( i_timestamp >> 24 )&0xff;
p_sys->p_buffer->p_buffer[5] = ( i_timestamp >> 16 )&0xff;
......
......@@ -2,7 +2,7 @@
* avi.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: avi.c,v 1.9 2003/03/03 14:21:08 gbazin Exp $
* $Id: avi.c,v 1.10 2003/03/11 19:02:30 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -63,13 +63,13 @@
static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
static int Capability(sout_instance_t *, int , void *, void * );
static int AddStream( sout_instance_t *, sout_input_t * );
static int DelStream( sout_instance_t *, sout_input_t * );
static int Mux ( sout_instance_t * );
static int Capability(sout_mux_t *, int , void *, void * );
static int AddStream( sout_mux_t *, sout_input_t * );
static int DelStream( sout_mux_t *, sout_input_t * );
static int Mux ( sout_mux_t * );
static sout_buffer_t *avi_HeaderCreateRIFF( sout_instance_t *p_sout );
static sout_buffer_t *avi_HeaderCreateidx1( sout_instance_t *p_sout );
static sout_buffer_t *avi_HeaderCreateRIFF( sout_mux_t * );
static sout_buffer_t *avi_HeaderCreateidx1( sout_mux_t * );
static void SetFCC( uint8_t *p, char *fcc )
{
......@@ -136,7 +136,7 @@ typedef struct avi_idx1_s
avi_idx1_entry_t *entry;
} avi_idx1_t;
typedef struct sout_mux_s
struct sout_mux_sys_t
{
int i_streams;
int i_stream_video;
......@@ -147,39 +147,39 @@ typedef struct sout_mux_s
avi_idx1_t idx1;
off_t i_idx1_size;
} sout_mux_t;
};
/*****************************************************************************
* Open:
*****************************************************************************/
static int Open( vlc_object_t *p_this )
{
sout_instance_t *p_sout = (sout_instance_t*)p_this;
sout_mux_t *p_mux;
sout_mux_t *p_mux = (sout_mux_t*)p_this;
sout_mux_sys_t *p_sys = p_mux->p_sys;
sout_buffer_t *p_hdr;
p_mux = malloc( sizeof( sout_mux_t ) );
p_mux->i_streams = 0;
p_mux->i_stream_video = -1;
p_mux->i_movi_size = 0;
p_sys = malloc( sizeof( sout_mux_sys_t ) );
p_sys->i_streams = 0;
p_sys->i_stream_video = -1;
p_sys->i_movi_size = 0;
p_mux->idx1.i_entry_count = 0;
p_mux->idx1.i_entry_max = 10000;
p_mux->idx1.entry = calloc( p_mux->idx1.i_entry_max, sizeof( avi_idx1_entry_t ) );
p_sys->idx1.i_entry_count = 0;
p_sys->idx1.i_entry_max = 10000;
p_sys->idx1.entry = calloc( p_sys->idx1.i_entry_max, sizeof( avi_idx1_entry_t ) );
msg_Info( p_sout, "Open" );
msg_Info( p_mux, "Open" );
p_sout->pf_mux_capacity = Capability;
p_sout->pf_mux_addstream = AddStream;
p_sout->pf_mux_delstream = DelStream;
p_sout->pf_mux = Mux;
p_sout->p_mux_data = (void*)p_mux;
p_sout->i_mux_preheader = 8; // (fourcc,length) header
p_mux->pf_capacity = Capability;
p_mux->pf_addstream = AddStream;
p_mux->pf_delstream = DelStream;
p_mux->pf_mux = Mux;
p_mux->p_sys = p_sys;
p_mux->i_preheader = 8; // (fourcc,length) header
/* room to add header at the end */
p_hdr = sout_BufferNew( p_sout, HDR_SIZE );
p_hdr = sout_BufferNew( p_mux->p_sout, HDR_SIZE );
memset( p_hdr->p_buffer, 0, HDR_SIZE );
sout_AccessOutWrite( p_sout->p_access, p_hdr );
sout_AccessOutWrite( p_mux->p_access, p_hdr );
return VLC_SUCCESS;
}
......@@ -190,24 +190,25 @@ static int Open( vlc_object_t *p_this )
static void Close( vlc_object_t * p_this )
{
sout_instance_t *p_sout = (sout_instance_t*)p_this;
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_t *p_mux = (sout_mux_t*)p_this;
sout_mux_sys_t *p_sys = p_mux->p_sys;
sout_buffer_t *p_hdr, *p_idx1;
int i_stream;
msg_Info( p_sout, "Close" );
msg_Info( p_mux, "Close" );
/* first create idx1 chunk (write at the end of the stream */
p_idx1 = avi_HeaderCreateidx1( p_sout );
p_mux->i_idx1_size = p_idx1->i_size;
sout_AccessOutWrite( p_sout->p_access, p_idx1 );
p_idx1 = avi_HeaderCreateidx1( p_mux );
p_sys->i_idx1_size = p_idx1->i_size;
sout_AccessOutWrite( p_mux->p_access, p_idx1 );
/* calculate some value for headers creations */
for( i_stream = 0; i_stream < p_mux->i_streams; i_stream++ )
for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
{
avi_stream_t *p_stream;
p_stream = &p_mux->stream[i_stream];
p_stream = &p_sys->stream[i_stream];
p_stream->f_fps = 25;
if( p_stream->i_duration > 0 )
......@@ -224,19 +225,19 @@ static void Close( vlc_object_t * p_this )
(uint64_t)p_stream->i_totalsize /
(uint64_t)p_stream->i_duration;
}
msg_Err( p_sout,"stream[%d] duration:%lld totalsize:%lld frames:%d fps:%f kb/s:%d",
msg_Err( p_mux, "stream[%d] duration:%lld totalsize:%lld frames:%d fps:%f kb/s:%d",
i_stream,
p_stream->i_duration/1000000, p_stream->i_totalsize,
p_stream->i_frames,
p_stream->f_fps, p_stream->i_bitrate/1024 );
}
p_hdr = avi_HeaderCreateRIFF( p_sout );
sout_AccessOutSeek( p_sout->p_access, 0 );
sout_AccessOutWrite( p_sout->p_access, p_hdr );
p_hdr = avi_HeaderCreateRIFF( p_mux );
sout_AccessOutSeek( p_mux->p_access, 0 );
sout_AccessOutWrite( p_mux->p_access, p_hdr );
}
static int Capability( sout_instance_t *p_sout, int i_query, void *p_args, void *p_answer )
static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer )
{
switch( i_query )
{
......@@ -248,27 +249,27 @@ static int Capability( sout_instance_t *p_sout, int i_query, void *p_args, void
}
}
static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
{
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_sys_t *p_sys = p_mux->p_sys;
avi_stream_t *p_stream;
if( p_mux->i_streams >= 100 )
if( p_sys->i_streams >= 100 )
{
msg_Err( p_sout, "too many streams" );
msg_Err( p_mux, "too many streams" );
return( -1 );
}
if( p_input->input_format.p_format == NULL )
{
msg_Err( p_sout, "stream descriptor missing" );
msg_Err( p_mux, "stream descriptor missing" );
return( -1 );
}
msg_Dbg( p_sout, "adding input" );
p_input->p_mux_data = malloc( sizeof( int ) );
msg_Dbg( p_mux, "adding input" );
p_input->p_sys = malloc( sizeof( int ) );
*((int*)p_input->p_mux_data) = p_mux->i_streams;
p_stream = &p_mux->stream[p_mux->i_streams];
*((int*)p_input->p_sys) = p_sys->i_streams;
p_stream = &p_sys->stream[p_sys->i_streams];
switch( p_input->input_format.i_cat )
{
......@@ -278,8 +279,8 @@ static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
(WAVEFORMATEX*)p_input->input_format.p_format;
p_stream->i_cat = AUDIO_ES;
p_stream->fcc[0] = '0' + p_mux->i_streams / 10;
p_stream->fcc[1] = '0' + p_mux->i_streams % 10;
p_stream->fcc[0] = '0' + p_sys->i_streams / 10;
p_stream->fcc[1] = '0' + p_sys->i_streams % 10;
p_stream->fcc[2] = 'w';
p_stream->fcc[3] = 'b';
......@@ -296,13 +297,13 @@ static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
(BITMAPINFOHEADER*)p_input->input_format.p_format;;
p_stream->i_cat = VIDEO_ES;
p_stream->fcc[0] = '0' + p_mux->i_streams / 10;
p_stream->fcc[1] = '0' + p_mux->i_streams % 10;
p_stream->fcc[0] = '0' + p_sys->i_streams / 10;
p_stream->fcc[1] = '0' + p_sys->i_streams % 10;
p_stream->fcc[2] = 'd';
p_stream->fcc[3] = 'c';
if( p_mux->i_stream_video < 0 )
if( p_sys->i_stream_video < 0 )
{
p_mux->i_stream_video = p_mux->i_streams;
p_sys->i_stream_video = p_sys->i_streams;
}
p_stream->p_wf = NULL;
p_stream->p_bih = malloc( p_bih->biSize );
......@@ -318,37 +319,36 @@ static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
p_stream->i_frames = 0;
p_stream->i_duration = 0;
p_mux->i_streams++;
p_sys->i_streams++;
return( 0 );
}
static int DelStream( sout_instance_t *p_sout, sout_input_t *p_input )
static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
{
// sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
msg_Dbg( p_sout, "removing input" );
msg_Dbg( p_mux, "removing input" );
free( p_input->p_mux_data ); p_input->p_mux_data = NULL;
free( p_input->p_sys ); p_input->p_sys = NULL;
return( 0 );
}
static int Mux ( sout_instance_t *p_sout )
static int Mux ( sout_mux_t *p_mux )
{
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_sys_t *p_sys = p_mux->p_sys;
avi_stream_t *p_stream;
int i_stream;
int i;
for( i = 0; i < p_sout->i_nb_inputs; i++ )
for( i = 0; i < p_mux->i_nb_inputs; i++ )
{
int i_count;
sout_fifo_t *p_fifo;
i_stream = *((int*)p_sout->pp_inputs[i]->p_mux_data );
p_stream = &p_mux->stream[i_stream];
i_stream = *((int*)p_mux->pp_inputs[i]->p_sys );
p_stream = &p_sys->stream[i_stream];
p_fifo = p_sout->pp_inputs[i]->p_fifo;
p_fifo = p_mux->pp_inputs[i]->p_fifo;
i_count = p_fifo->i_depth;
while( i_count > 0 )
{
......@@ -362,31 +362,31 @@ static int Mux ( sout_instance_t *p_sout )
p_stream->i_totalsize += p_data->i_size;
/* add idx1 entry for this frame */
p_idx = &p_mux->idx1.entry[p_mux->idx1.i_entry_count];
p_idx = &p_sys->idx1.entry[p_sys->idx1.i_entry_count];
memcpy( p_idx->fcc, p_stream->fcc, 4 );
p_idx->i_flags = AVIIF_KEYFRAME;
p_idx->i_pos = p_mux->i_movi_size + 4;
p_idx->i_pos = p_sys->i_movi_size + 4;
p_idx->i_length= p_data->i_size;
p_mux->idx1.i_entry_count++;
if( p_mux->idx1.i_entry_count >= p_mux->idx1.i_entry_max )
p_sys->idx1.i_entry_count++;
if( p_sys->idx1.i_entry_count >= p_sys->idx1.i_entry_max )
{
p_mux->idx1.i_entry_max += 10000;
p_mux->idx1.entry = realloc( p_mux->idx1.entry,
p_mux->idx1.i_entry_max * sizeof( avi_idx1_entry_t ) );
p_sys->idx1.i_entry_max += 10000;
p_sys->idx1.entry = realloc( p_sys->idx1.entry,
p_sys->idx1.i_entry_max * sizeof( avi_idx1_entry_t ) );
}
if( sout_BufferReallocFromPreHeader( p_sout, p_data, 8 ) )
if( sout_BufferReallocFromPreHeader( p_mux->p_sout, p_data, 8 ) )
{
/* there isn't enough data in preheader */
sout_buffer_t *p_hdr;
p_hdr = sout_BufferNew( p_sout, 8 );
p_hdr = sout_BufferNew( p_mux->p_sout, 8 );
SetFCC( p_hdr->p_buffer, p_stream->fcc );
SetDWLE( p_hdr->p_buffer + 4, p_data->i_size );
sout_AccessOutWrite( p_sout->p_access, p_hdr );
p_mux->i_movi_size += p_hdr->i_size;
sout_AccessOutWrite( p_mux->p_access, p_hdr );
p_sys->i_movi_size += p_hdr->i_size;
}
else
......@@ -397,12 +397,12 @@ static int Mux ( sout_instance_t *p_sout )
if( p_data->i_size & 0x01 )
{
sout_BufferRealloc( p_sout, p_data, p_data->i_size + 1 );
sout_BufferRealloc( p_mux->p_sout, p_data, p_data->i_size + 1 );
p_data->i_size += 1;
}
sout_AccessOutWrite( p_sout->p_access, p_data );
p_mux->i_movi_size += p_data->i_size;
sout_AccessOutWrite( p_mux->p_access, p_data );
p_sys->i_movi_size += p_data->i_size;
i_count--;
}
......@@ -511,10 +511,10 @@ static void bo_AddMem( buffer_out_t *p_bo, int i_size, uint8_t *p_mem )
bo_AddDWordLE( &_bo_sav_, p_bo->i_buffer - _bo_sav_.i_buffer - 4 ); \
return( i_err );
static int avi_HeaderAdd_avih( sout_instance_t *p_sout,
static int avi_HeaderAdd_avih( sout_mux_t *p_mux,
buffer_out_t *p_bo )
{
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_sys_t *p_sys = p_mux->p_sys;
avi_stream_t *p_video = NULL;
int i_stream;
uint32_t i_microsecperframe;
......@@ -522,9 +522,9 @@ static int avi_HeaderAdd_avih( sout_instance_t *p_sout,
int i_totalframes;
AVI_BOX_ENTER( "avih" );
if( p_mux->i_stream_video >= 0 )
if( p_sys->i_stream_video >= 0 )
{
p_video = &p_mux->stream[p_mux->i_stream_video];
p_video = &p_sys->stream[p_sys->i_stream_video];
if( p_video->i_frames <= 0 )
{
p_video = NULL;
......@@ -535,23 +535,23 @@ static int avi_HeaderAdd_avih( sout_instance_t *p_sout,
{
i_microsecperframe =
(uint32_t)( (float)1000000 /
(float)p_mux->stream[p_mux->i_stream_video].f_fps );
i_totalframes = p_mux->stream[p_mux->i_stream_video].i_frames;
(float)p_sys->stream[p_sys->i_stream_video].f_fps );
i_totalframes = p_sys->stream[p_sys->i_stream_video].i_frames;
}
else
{
msg_Warn( p_sout, "avi file without audio video track isn't a good idea..." );
msg_Warn( p_mux, "avi file without audio video track isn't a good idea..." );
i_microsecperframe = 0;
i_totalframes = 0;
}
for( i_stream = 0,i_maxbytespersec = 0; i_stream < p_mux->i_streams; i_stream++ )
for( i_stream = 0,i_maxbytespersec = 0; i_stream < p_sys->i_streams; i_stream++ )
{
if( p_mux->stream[p_mux->i_stream_video].i_duration > 0 )
if( p_sys->stream[p_sys->i_stream_video].i_duration > 0 )
{
i_maxbytespersec +=
p_mux->stream[p_mux->i_stream_video].i_totalsize /
p_mux->stream[p_mux->i_stream_video].i_duration;
p_sys->stream[p_sys->i_stream_video].i_totalsize /
p_sys->stream[p_sys->i_stream_video].i_duration;
}
}
......@@ -563,7 +563,7 @@ static int avi_HeaderAdd_avih( sout_instance_t *p_sout,
AVIF_ISINTERLEAVED ); /* flags */
bo_AddDWordLE( p_bo, i_totalframes );
bo_AddDWordLE( p_bo, 0 ); /* initial frame */
bo_AddDWordLE( p_bo, p_mux->i_streams ); /* streams count */
bo_AddDWordLE( p_bo, p_sys->i_streams ); /* streams count */
bo_AddDWordLE( p_bo, 1024 * 1024 ); /* suggested buffer size */
if( p_video )
{
......@@ -582,11 +582,10 @@ static int avi_HeaderAdd_avih( sout_instance_t *p_sout,
AVI_BOX_EXIT( 0 );
}
static int avi_HeaderAdd_strh( sout_instance_t *p_sout,
static int avi_HeaderAdd_strh( sout_mux_t *p_mux,
buffer_out_t *p_bo,
avi_stream_t *p_stream )
{
// sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
AVI_BOX_ENTER( "strh" );
switch( p_stream->i_cat )
......@@ -652,11 +651,10 @@ static int avi_HeaderAdd_strh( sout_instance_t *p_sout,
AVI_BOX_EXIT( 0 );
}
static int avi_HeaderAdd_strf( sout_instance_t *p_sout,
static int avi_HeaderAdd_strf( sout_mux_t *p_mux,
buffer_out_t *p_bo,
avi_stream_t *p_stream )
{
// sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
AVI_BOX_ENTER( "strf" );
switch( p_stream->i_cat )
......@@ -699,45 +697,44 @@ static int avi_HeaderAdd_strf( sout_instance_t *p_sout,
AVI_BOX_EXIT( 0 );
}
static int avi_HeaderAdd_strl( sout_instance_t *p_sout,
static int avi_HeaderAdd_strl( sout_mux_t *p_mux,
buffer_out_t *p_bo,
avi_stream_t *p_stream )
{
// sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
AVI_BOX_ENTER_LIST( "strl" );
avi_HeaderAdd_strh( p_sout, p_bo, p_stream );
avi_HeaderAdd_strf( p_sout, p_bo, p_stream );
avi_HeaderAdd_strh( p_mux, p_bo, p_stream );
avi_HeaderAdd_strf( p_mux, p_bo, p_stream );
AVI_BOX_EXIT( 0 );
}
static sout_buffer_t *avi_HeaderCreateRIFF( sout_instance_t *p_sout )
static sout_buffer_t *avi_HeaderCreateRIFF( sout_mux_t *p_mux )
{
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_sys_t *p_sys = p_mux->p_sys;
sout_buffer_t *p_hdr;
int i_stream;
int i_maxbytespersec;
int i_junk;
buffer_out_t bo;
p_hdr = sout_BufferNew( p_sout, HDR_SIZE );
p_hdr = sout_BufferNew( p_mux->p_sout, HDR_SIZE );
memset( p_hdr->p_buffer, 0, HDR_SIZE );
bo_Init( &bo, HDR_SIZE, p_hdr->p_buffer );
bo_AddFCC( &bo, "RIFF" );
bo_AddDWordLE( &bo, p_mux->i_movi_size + HDR_SIZE - 8 + p_mux->i_idx1_size );
bo_AddDWordLE( &bo, p_sys->i_movi_size + HDR_SIZE - 8 + p_sys->i_idx1_size );
bo_AddFCC( &bo, "AVI " );
bo_AddFCC( &bo, "LIST" );
bo_AddDWordLE( &bo, HDR_SIZE - 8);
bo_AddFCC( &bo, "hdrl" );
avi_HeaderAdd_avih( p_sout, &bo );
for( i_stream = 0,i_maxbytespersec = 0; i_stream < p_mux->i_streams; i_stream++ )
avi_HeaderAdd_avih( p_mux, &bo );
for( i_stream = 0,i_maxbytespersec = 0; i_stream < p_sys->i_streams; i_stream++ )
{
avi_HeaderAdd_strl( p_sout, &bo, &p_mux->stream[i_stream] );
avi_HeaderAdd_strl( p_mux, &bo, &p_sys->stream[i_stream] );
}
i_junk = HDR_SIZE - bo.i_buffer - 8 - 12;
......@@ -746,35 +743,35 @@ static sout_buffer_t *avi_HeaderCreateRIFF( sout_instance_t *p_sout )
bo.i_buffer += i_junk;
bo_AddFCC( &bo, "LIST" );
bo_AddDWordLE( &bo, p_mux->i_movi_size + 4 );
bo_AddDWordLE( &bo, p_sys->i_movi_size + 4 );
bo_AddFCC( &bo, "movi" );
return( p_hdr );
}
static sout_buffer_t * avi_HeaderCreateidx1( sout_instance_t *p_sout )
static sout_buffer_t * avi_HeaderCreateidx1( sout_mux_t *p_mux )
{
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_sys_t *p_sys = p_mux->p_sys;
sout_buffer_t *p_idx1;
uint32_t i_idx1_size;
unsigned int i;
buffer_out_t bo;
i_idx1_size = 16 * p_mux->idx1.i_entry_count;
i_idx1_size = 16 * p_sys->idx1.i_entry_count;
p_idx1 = sout_BufferNew( p_sout, i_idx1_size + 8 );
p_idx1 = sout_BufferNew( p_mux->p_sout, i_idx1_size + 8 );
memset( p_idx1->p_buffer, 0, i_idx1_size );
bo_Init( &bo, i_idx1_size, p_idx1->p_buffer );
bo_AddFCC( &bo, "idx1" );
bo_AddDWordLE( &bo, i_idx1_size );
for( i = 0; i < p_mux->idx1.i_entry_count; i++ )
for( i = 0; i < p_sys->idx1.i_entry_count; i++ )
{
bo_AddFCC( &bo, p_mux->idx1.entry[i].fcc );
bo_AddDWordLE( &bo, p_mux->idx1.entry[i].i_flags );
bo_AddDWordLE( &bo, p_mux->idx1.entry[i].i_pos );
bo_AddDWordLE( &bo, p_mux->idx1.entry[i].i_length );
bo_AddFCC( &bo, p_sys->idx1.entry[i].fcc );
bo_AddDWordLE( &bo, p_sys->idx1.entry[i].i_flags );
bo_AddDWordLE( &bo, p_sys->idx1.entry[i].i_pos );
bo_AddDWordLE( &bo, p_sys->idx1.entry[i].i_length );
}
return( p_idx1 );
......
......@@ -2,7 +2,7 @@
* dummy.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: dummy.c,v 1.6 2003/03/03 14:21:08 gbazin Exp $
* $Id: dummy.c,v 1.7 2003/03/11 19:02:30 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
......@@ -48,10 +48,10 @@
static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
static int Capability(sout_instance_t *, int, void *, void * );
static int AddStream( sout_instance_t *, sout_input_t * );
static int DelStream( sout_instance_t *, sout_input_t * );
static int Mux ( sout_instance_t * );
static int Capability(sout_mux_t *, int, void *, void * );
static int AddStream( sout_mux_t *, sout_input_t * );
static int DelStream( sout_mux_t *, sout_input_t * );
static int Mux ( sout_mux_t * );
/*****************************************************************************
* Module descriptor
......@@ -60,6 +60,7 @@ vlc_module_begin();
set_description( _("Dummy muxer") );
set_capability( "sout mux", 5 );
add_shortcut( "dummy" );
add_shortcut( "es" );
set_callbacks( Open, Close );
vlc_module_end();
......@@ -68,14 +69,14 @@ vlc_module_end();
*****************************************************************************/
static int Open( vlc_object_t *p_this )
{
sout_instance_t *p_sout = (sout_instance_t*)p_this;
sout_mux_t *p_mux = (sout_mux_t*)p_this;
msg_Info( p_sout, "Open" );
msg_Info( p_mux, "Open" );
p_sout->pf_mux_capacity = Capability;
p_sout->pf_mux_addstream = AddStream;
p_sout->pf_mux_delstream = DelStream;
p_sout->pf_mux = Mux;
p_mux->pf_capacity = Capability;
p_mux->pf_addstream = AddStream;
p_mux->pf_delstream = DelStream;
p_mux->pf_mux = Mux;
return VLC_SUCCESS;
}
......@@ -86,11 +87,12 @@ static int Open( vlc_object_t *p_this )
static void Close( vlc_object_t * p_this )
{
sout_instance_t *p_sout = (sout_instance_t*)p_this;
msg_Info( p_sout, "Close" );
sout_mux_t *p_mux = (sout_mux_t*)p_this;
msg_Info( p_mux, "Close" );
}
static int Capability( sout_instance_t *p_sout, int i_query, void *p_args, void *p_answer )
static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer )
{
switch( i_query )
{
......@@ -102,28 +104,28 @@ static int Capability( sout_instance_t *p_sout, int i_query, void *p_args, void
}
}
static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
{
msg_Dbg( p_sout, "adding input" );
msg_Dbg( p_mux, "adding input" );
return( 0 );
}
static int DelStream( sout_instance_t *p_sout, sout_input_t *p_input )
static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
{
msg_Dbg( p_sout, "removing input" );
msg_Dbg( p_mux, "removing input" );
return( 0 );
}
static int Mux ( sout_instance_t *p_sout )
static int Mux ( sout_mux_t *p_mux )
{
int i;
for( i = 0; i < p_sout->i_nb_inputs; i++ )
for( i = 0; i < p_mux->i_nb_inputs; i++ )
{
int i_count;
sout_fifo_t *p_fifo;
p_fifo = p_sout->pp_inputs[i]->p_fifo;
p_fifo = p_mux->pp_inputs[i]->p_fifo;
i_count = p_fifo->i_depth;
while( i_count > 0 )
{
......@@ -131,7 +133,7 @@ static int Mux ( sout_instance_t *p_sout )
p_data = sout_FifoGet( p_fifo );
sout_AccessOutWrite( p_sout->p_access, p_data );
sout_AccessOutWrite( p_mux->p_access, p_data );
i_count--;
}
......
......@@ -2,7 +2,7 @@
* ps.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: ps.c,v 1.10 2003/03/03 14:21:08 gbazin Exp $
* $Id: ps.c,v 1.11 2003/03/11 19:02:30 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
......@@ -51,10 +51,10 @@
static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
static int Capability(sout_instance_t *, int, void *, void * );
static int AddStream( sout_instance_t *, sout_input_t * );
static int DelStream( sout_instance_t *, sout_input_t * );
static int Mux ( sout_instance_t * );
static int Capability(sout_mux_t *, int, void *, void * );
static int AddStream( sout_mux_t *, sout_input_t * );
static int DelStream( sout_mux_t *, sout_input_t * );
static int Mux ( sout_mux_t * );
static void SetWBE ( uint8_t *p, uint16_t v )
{
......@@ -88,7 +88,7 @@ typedef struct ps_stream_s
} ps_stream_t;
typedef struct sout_mux_s
struct sout_mux_sys_t
{
int i_stream_id_mpga;
......@@ -101,34 +101,34 @@ typedef struct sout_mux_s
int i_pes_count;
int i_system_header;
} sout_mux_t;
};
/*****************************************************************************
* Open:
*****************************************************************************/
static int Open( vlc_object_t *p_this )
{
sout_instance_t *p_sout = (sout_instance_t*)p_this;
sout_mux_t *p_mux;
sout_mux_t *p_mux = (sout_mux_t*)p_this;
sout_mux_sys_t *p_sys;
msg_Info( p_sout, "Open" );
msg_Info( p_mux, "Open" );
p_mux = malloc( sizeof( sout_mux_t ) );
p_sys = malloc( sizeof( sout_mux_sys_t ) );
p_sout->pf_mux_capacity = Capability;
p_sout->pf_mux_addstream = AddStream;
p_sout->pf_mux_delstream = DelStream;
p_sout->pf_mux = Mux;
p_sout->p_mux_data = (void*)p_mux;
p_sout->i_mux_preheader = 30; // really enough for a pes header
p_mux->pf_capacity = Capability;
p_mux->pf_addstream = AddStream;
p_mux->pf_delstream = DelStream;
p_mux->pf_mux = Mux;
p_mux->p_sys = p_sys;
p_mux->i_preheader = 30; // really enough for a pes header
p_mux->i_stream_id_mpga = 0xc0;
p_mux->i_stream_id_a52 = 0x80;
p_mux->i_stream_id_mpgv = 0xe0;
p_mux->i_audio_bound = 0;
p_mux->i_video_bound = 0;
p_mux->i_system_header = 0;
p_mux->i_pes_count = 0;
p_sys->i_stream_id_mpga = 0xc0;
p_sys->i_stream_id_a52 = 0x80;
p_sys->i_stream_id_mpgv = 0xe0;
p_sys->i_audio_bound = 0;
p_sys->i_video_bound = 0;
p_sys->i_system_header = 0;
p_sys->i_pes_count = 0;
return VLC_SUCCESS;
}
......@@ -139,23 +139,22 @@ static int Open( vlc_object_t *p_this )
static void Close( vlc_object_t * p_this )
{
sout_instance_t *p_sout = (sout_instance_t*)p_this;
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_t *p_mux = (sout_mux_t*)p_this;
sout_mux_sys_t *p_sys = p_mux->p_sys;
sout_buffer_t *p_end;
msg_Info( p_sout, "Close" );
msg_Info( p_mux, "Close" );
p_end = sout_BufferNew( p_sout, 4 );
p_end = sout_BufferNew( p_mux->p_sout, 4 );
SetDWBE( p_end->p_buffer, 0x01b9 );
sout_AccessOutWrite( p_sout->p_access, p_end );
free( p_mux );
sout_AccessOutWrite( p_mux->p_access, p_end );
p_sout->p_mux_data = NULL;
free( p_sys );
}
static int Capability( sout_instance_t *p_sout, int i_query, void *p_args, void *p_answer )
static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer )
{
switch( i_query )
{
......@@ -167,13 +166,13 @@ static int Capability( sout_instance_t *p_sout, int i_query, void *p_args, void
}
}
static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
{
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_sys_t *p_sys = p_mux->p_sys;
ps_stream_t *p_stream;
msg_Dbg( p_sout, "adding input" );
p_input->p_mux_data = (void*)p_stream = malloc( sizeof( ps_stream_t ) );
msg_Dbg( p_mux, "adding input" );
p_input->p_sys = (void*)p_stream = malloc( sizeof( ps_stream_t ) );
p_stream->i_ok = 0;
switch( p_input->input_format.i_cat )
{
......@@ -182,9 +181,9 @@ static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
switch( p_input->input_format.i_fourcc )
{
case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
p_stream->i_stream_id = p_mux->i_stream_id_mpgv;
p_mux->i_stream_id_mpgv++;
p_mux->i_video_bound++;
p_stream->i_stream_id = p_sys->i_stream_id_mpgv;
p_sys->i_stream_id_mpgv++;
p_sys->i_video_bound++;
break;
default:
return( -1 );
......@@ -195,14 +194,14 @@ static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
{
case VLC_FOURCC( 'a', '5', '2', ' ' ):
case VLC_FOURCC( 'a', '5', '2', 'b' ):
p_stream->i_stream_id = p_mux->i_stream_id_a52 | ( 0xbd << 8 );
p_mux->i_stream_id_a52++;
p_mux->i_audio_bound++;
p_stream->i_stream_id = p_sys->i_stream_id_a52 | ( 0xbd << 8 );
p_sys->i_stream_id_a52++;
p_sys->i_audio_bound++;
break;
case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
p_stream->i_stream_id = p_mux->i_stream_id_mpga;
p_mux->i_stream_id_mpga++;
p_mux->i_audio_bound++;
p_stream->i_stream_id = p_sys->i_stream_id_mpga;
p_sys->i_stream_id_mpga++;
p_sys->i_audio_bound++;
break;
default:
return( -1 );
......@@ -213,23 +212,23 @@ static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
}
p_stream->i_ok = 1;
msg_Dbg( p_sout, "adding input stream_id:0x%x [OK]", p_stream->i_stream_id );
msg_Dbg( p_mux, "adding input stream_id:0x%x [OK]", p_stream->i_stream_id );
return( 0 );
}
static int DelStream( sout_instance_t *p_sout, sout_input_t *p_input )
static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
{
ps_stream_t *p_stream =(ps_stream_t*)p_input->p_mux_data;
ps_stream_t *p_stream =(ps_stream_t*)p_input->p_sys;
msg_Dbg( p_sout, "removing input" );
msg_Dbg( p_mux, "removing input" );
if( p_stream )
{
free( p_stream );
}
return( 0 );
return( VLC_SUCCESS );
}
static int MuxWritePackHeader( sout_instance_t *p_sout,
static int MuxWritePackHeader( sout_mux_t *p_mux,
mtime_t i_dts )
{
sout_buffer_t *p_hdr;
......@@ -238,7 +237,7 @@ static int MuxWritePackHeader( sout_instance_t *p_sout,
i_src = i_dts * 9 / 100;
p_hdr = sout_BufferNew( p_sout, 18 );
p_hdr = sout_BufferNew( p_mux->p_sout, 18 );
bits_initwrite( &bits, 14, p_hdr->p_buffer );
bits_write( &bits, 32, 0x01ba );
bits_write( &bits, 2, 0x01 ); // FIXME ??
......@@ -258,18 +257,18 @@ static int MuxWritePackHeader( sout_instance_t *p_sout,
bits_write( &bits, 5, 0x1f ); // FIXME reserved
bits_write( &bits, 3, 0 ); // stuffing bytes
p_hdr->i_size = 14;
sout_AccessOutWrite( p_sout->p_access, p_hdr );
sout_AccessOutWrite( p_mux->p_access, p_hdr );
return( 0 );
}
static int MuxWriteSystemHeader( sout_instance_t *p_sout )
static int MuxWriteSystemHeader( sout_mux_t *p_mux )
{
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_sys_t *p_sys = p_mux->p_sys;
sout_buffer_t *p_hdr;
bits_buffer_t bits;
p_hdr = sout_BufferNew( p_sout, 12 );
p_hdr = sout_BufferNew( p_mux->p_sout, 12 );
bits_initwrite( &bits, 12, p_hdr->p_buffer );
bits_write( &bits, 32, 0x01bb );
......@@ -278,7 +277,7 @@ static int MuxWriteSystemHeader( sout_instance_t *p_sout )
bits_write( &bits, 22, 0 ); // FIXME rate bound
bits_write( &bits, 1, 1 );
bits_write( &bits, 6, p_mux->i_audio_bound );
bits_write( &bits, 6, p_sys->i_audio_bound );
bits_write( &bits, 1, 0 ); // fixed flag
bits_write( &bits, 1, 0 ); // CSPS flag
bits_write( &bits, 1, 0 ); // system audio lock flag
......@@ -286,19 +285,19 @@ static int MuxWriteSystemHeader( sout_instance_t *p_sout )
bits_write( &bits, 1, 1 ); // marker bit
bits_write( &bits, 5, p_mux->i_video_bound );
bits_write( &bits, 5, p_sys->i_video_bound );
bits_write( &bits, 1, 0 ); // packet rate restriction flag
bits_write( &bits, 7, 0x7f ); // reserved bits
/* FIXME missing stream_id ... */
sout_AccessOutWrite( p_sout->p_access, p_hdr );
sout_AccessOutWrite( p_mux->p_access, p_hdr );
return( 0 );
}
/* return stream number to be muxed */
static int MuxGetStream( sout_instance_t *p_sout,
static int MuxGetStream( sout_mux_t *p_mux,
int *pi_stream,
mtime_t *pi_dts )
{
......@@ -306,11 +305,11 @@ static int MuxGetStream( sout_instance_t *p_sout,
int i_stream;
int i;
for( i = 0, i_dts = 0, i_stream = -1; i < p_sout->i_nb_inputs; i++ )
for( i = 0, i_dts = 0, i_stream = -1; i < p_mux->i_nb_inputs; i++ )
{
sout_fifo_t *p_fifo;
p_fifo = p_sout->pp_inputs[i]->p_fifo;
p_fifo = p_mux->pp_inputs[i]->p_fifo;
if( p_fifo->i_depth > 1 )
{
......@@ -342,9 +341,9 @@ static int MuxGetStream( sout_instance_t *p_sout,
}
static int Mux ( sout_instance_t *p_sout )
static int Mux ( sout_mux_t *p_mux )
{
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_sys_t *p_sys = p_mux->p_sys;
mtime_t i_dts;
int i_stream;
......@@ -355,30 +354,30 @@ static int Mux ( sout_instance_t *p_sout )
sout_fifo_t *p_fifo;
sout_buffer_t *p_data;
if( MuxGetStream( p_sout, &i_stream, &i_dts ) < 0 )
if( MuxGetStream( p_mux, &i_stream, &i_dts ) < 0 )
{
return( 0 );
return( VLC_SUCCESS );
}
p_input = p_sout->pp_inputs[i_stream];
p_input = p_mux->pp_inputs[i_stream];
p_fifo = p_input->p_fifo;
p_stream = (ps_stream_t*)p_input->p_mux_data;
p_stream = (ps_stream_t*)p_input->p_sys;
if( p_mux->i_pes_count % 30 == 0)
if( p_sys->i_pes_count % 30 == 0)
{
MuxWritePackHeader( p_sout, i_dts );
MuxWritePackHeader( p_mux, i_dts );
}
if( p_mux->i_pes_count % 300 == 0 )
if( p_sys->i_pes_count % 300 == 0 )
{
// MuxWriteSystemHeader( p_sout );
}
p_data = sout_FifoGet( p_fifo );
E_( EStoPES )( p_sout, &p_data, p_data, p_stream->i_stream_id, 1);
sout_AccessOutWrite( p_sout->p_access, p_data );
E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1);
sout_AccessOutWrite( p_mux->p_access, p_data );
p_mux->i_pes_count++;
p_sys->i_pes_count++;
}
return( 0 );
......
......@@ -2,7 +2,7 @@
* ts.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: ts.c,v 1.14 2003/03/03 14:21:08 gbazin Exp $
* $Id: ts.c,v 1.15 2003/03/11 19:02:30 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
......@@ -82,7 +82,7 @@ typedef struct ts_stream_s
uint8_t *p_decoder_specific_info;
} ts_stream_t;
typedef struct sout_mux_s
struct sout_mux_sys_t
{
int i_pcr_pid;
int i_stream_id_mpga;
......@@ -104,7 +104,7 @@ typedef struct sout_mux_s
int i_mpeg4_streams;
} sout_mux_t;
};
/*****************************************************************************
......@@ -114,21 +114,21 @@ static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
static int Capability(sout_instance_t *, int, void *, void * );
static int AddStream( sout_instance_t *, sout_input_t * );
static int DelStream( sout_instance_t *, sout_input_t * );
static int Mux ( sout_instance_t * );
static int Capability(sout_mux_t *, int, void *, void * );
static int AddStream( sout_mux_t *, sout_input_t * );
static int DelStream( sout_mux_t *, sout_input_t * );
static int Mux ( sout_mux_t * );
/* Reserve a pid and return it */
static int AllocatePID( sout_mux_t *p_mux )
static int AllocatePID( sout_mux_sys_t *p_sys )
{
return( ++p_mux->i_pid_free );
return( ++p_sys->i_pid_free );
}
static int GetPAT( sout_instance_t *p_sout, sout_buffer_t **pp_ts );
static int GetPMT( sout_instance_t *p_sout, sout_buffer_t **pp_ts );
static int GetPAT( sout_mux_t *p_mux, sout_buffer_t **pp_ts );
static int GetPMT( sout_mux_t *p_mux, sout_buffer_t **pp_ts );
/*****************************************************************************
* Module descriptor
......@@ -153,41 +153,41 @@ vlc_module_end();
*****************************************************************************/
static int Open( vlc_object_t *p_this )
{
sout_instance_t *p_sout = (sout_instance_t*)p_this;
sout_mux_t *p_mux;
sout_mux_t *p_mux =(sout_mux_t*)p_this;
sout_mux_sys_t *p_sys;
msg_Info( p_sout, "Open" );
msg_Info( p_mux, "Open" );
p_mux = malloc( sizeof( sout_mux_t ) );
p_sys = malloc( sizeof( sout_mux_sys_t ) );
p_sout->pf_mux_capacity = Capability;
p_sout->pf_mux_addstream = AddStream;
p_sout->pf_mux_delstream = DelStream;
p_sout->pf_mux = Mux;
p_sout->p_mux_data = (void*)p_mux;
p_sout->i_mux_preheader = 30; // really enough for a pes header
p_mux->pf_capacity = Capability;
p_mux->pf_addstream = AddStream;
p_mux->pf_delstream = DelStream;
p_mux->pf_mux = Mux;
p_mux->p_sys = p_sys;
p_mux->i_preheader = 30; // really enough for a pes header
srand( (uint32_t)mdate() );
p_mux->i_stream_id_mpga = 0xc0;
p_mux->i_stream_id_a52 = 0x80;
p_mux->i_stream_id_mpgv = 0xe0;
p_sys->i_stream_id_mpga = 0xc0;
p_sys->i_stream_id_a52 = 0x80;
p_sys->i_stream_id_mpgv = 0xe0;
p_mux->i_audio_bound = 0;
p_mux->i_video_bound = 0;
p_sys->i_audio_bound = 0;
p_sys->i_video_bound = 0;
p_mux->i_pat_version_number = rand() % 32;
p_mux->pat.i_pid = 0;
p_mux->pat.i_continuity_counter = 0;
p_sys->i_pat_version_number = rand() % 32;
p_sys->pat.i_pid = 0;
p_sys->pat.i_continuity_counter = 0;
p_mux->i_pmt_version_number = rand() % 32;
p_mux->pmt.i_pid = 0x10;
p_mux->pmt.i_continuity_counter = 0;
p_sys->i_pmt_version_number = rand() % 32;
p_sys->pmt.i_pid = 0x10;
p_sys->pmt.i_continuity_counter = 0;
p_mux->i_pid_free = 0x11;
p_mux->i_pcr_pid = 0x1fff;
p_sys->i_pid_free = 0x11;
p_sys->i_pcr_pid = 0x1fff;
p_mux->i_mpeg4_streams = 0;
p_sys->i_mpeg4_streams = 0;
return VLC_SUCCESS;
}
......@@ -198,16 +198,16 @@ static int Open( vlc_object_t *p_this )
static void Close( vlc_object_t * p_this )
{
sout_instance_t *p_sout = (sout_instance_t*)p_this;
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_t *p_mux = (sout_mux_t*)p_this;
sout_mux_sys_t *p_sys = p_mux->p_sys;
msg_Info( p_sout, "Close" );
msg_Info( p_mux, "Close" );
free( p_mux );
p_sout->p_mux_data = NULL;
free( p_sys );
p_mux->p_sys = NULL;
}
static int Capability( sout_instance_t *p_sout, int i_query, void *p_args, void *p_answer )
static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer )
{
switch( i_query )
{
......@@ -219,20 +219,20 @@ static int Capability( sout_instance_t *p_sout, int i_query, void *p_args, void
}
}
static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
{
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_sys_t *p_sys = p_mux->p_sys;
ts_stream_t *p_stream;
BITMAPINFOHEADER *p_bih;
WAVEFORMATEX *p_wf;
msg_Dbg( p_sout, "adding input" );
p_input->p_mux_data = (void*)p_stream = malloc( sizeof( ts_stream_t ) );
msg_Dbg( p_mux, "adding input" );
p_input->p_sys = (void*)p_stream = malloc( sizeof( ts_stream_t ) );
p_stream->i_pid = AllocatePID( p_mux );
if( p_mux->i_pcr_pid == 0x1fff )
p_stream->i_pid = AllocatePID( p_sys );
if( p_sys->i_pcr_pid == 0x1fff )
{
p_mux->i_pcr_pid = p_stream->i_pid;
p_sys->i_pcr_pid = p_stream->i_pid;
}
p_stream->i_continuity_counter = 0;
......@@ -243,13 +243,13 @@ static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
{
case VLC_FOURCC( 'm', 'p','g', 'v' ):
p_stream->i_stream_type = 0x02;
p_stream->i_stream_id = p_mux->i_stream_id_mpgv;
p_mux->i_stream_id_mpgv++;
p_stream->i_stream_id = p_sys->i_stream_id_mpgv;
p_sys->i_stream_id_mpgv++;
break;
case VLC_FOURCC( 'm', 'p','4', 'v' ):
p_stream->i_stream_type = 0x10;
p_stream->i_stream_id = 0xfa;
p_mux->i_mpeg4_streams++;
p_sys->i_mpeg4_streams++;
p_stream->i_es_id = p_stream->i_pid;
p_stream->i_sl_predefined = 0x01; // NULL SL header
break;
......@@ -268,7 +268,7 @@ static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
default:
return( -1 );
}
p_mux->i_video_bound++;
p_sys->i_video_bound++;
p_bih = (BITMAPINFOHEADER*)p_input->input_format.p_format;
if( p_bih )
{
......@@ -305,25 +305,25 @@ static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
case VLC_FOURCC( 'a', '5','2', ' ' ):
case VLC_FOURCC( 'a', '5','2', 'b' ):
p_stream->i_stream_type = 0x81;
p_stream->i_stream_id = p_mux->i_stream_id_a52;
p_mux->i_stream_id_a52++;
p_stream->i_stream_id = p_sys->i_stream_id_a52;
p_sys->i_stream_id_a52++;
break;
case VLC_FOURCC( 'm', 'p','4', 'a' ):
p_stream->i_stream_type = 0x11;
p_stream->i_stream_id = 0xfa;
p_mux->i_mpeg4_streams++;
p_sys->i_mpeg4_streams++;
p_stream->i_es_id = p_stream->i_pid;
p_stream->i_sl_predefined = 0x01; // NULL SL header
break;
case VLC_FOURCC( 'm', 'p','g', 'a' ):
p_stream->i_stream_type = 0x04;
p_stream->i_stream_id = p_mux->i_stream_id_mpga;
p_mux->i_stream_id_mpga++;
p_stream->i_stream_id = p_sys->i_stream_id_mpga;
p_sys->i_stream_id_mpga++;
break;
default:
return( -1 );
}
p_mux->i_audio_bound++;
p_sys->i_audio_bound++;
p_wf = (WAVEFORMATEX*)p_input->input_format.p_format;
if( p_wf && p_wf->cbSize > 0 )
{
......@@ -344,20 +344,20 @@ static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
return( -1 );
}
p_mux->i_ts_packet = 0; // force pat/pmt recreation
p_mux->i_pat_version_number++; p_mux->i_pat_version_number %= 32;
p_mux->i_pmt_version_number++; p_mux->i_pmt_version_number %= 32;
p_sys->i_ts_packet = 0; // force pat/pmt recreation
p_sys->i_pat_version_number++; p_sys->i_pat_version_number %= 32;
p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
return( 0 );
}
static int DelStream( sout_instance_t *p_sout, sout_input_t *p_input )
static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
{
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_sys_t *p_sys = p_mux->p_sys;
ts_stream_t *p_stream;
msg_Dbg( p_sout, "removing input" );
p_stream = (ts_stream_t*)p_input->p_mux_data;
msg_Dbg( p_mux, "removing input" );
p_stream = (ts_stream_t*)p_input->p_sys;
if( p_stream->p_decoder_specific_info )
{
......@@ -365,18 +365,18 @@ static int DelStream( sout_instance_t *p_sout, sout_input_t *p_input )
}
if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
{
p_mux->i_mpeg4_streams--;
p_sys->i_mpeg4_streams--;
}
p_mux->i_ts_packet = 0; // force pat/pmt recreation
p_mux->i_pat_version_number++; p_mux->i_pat_version_number %= 32;
p_mux->i_pmt_version_number++; p_mux->i_pmt_version_number %= 32;
p_sys->i_ts_packet = 0; // force pat/pmt recreation
p_sys->i_pat_version_number++; p_sys->i_pat_version_number %= 32;
p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
return( 0 );
}
static int MuxGetStream( sout_instance_t *p_sout,
static int MuxGetStream( sout_mux_t *p_mux,
int *pi_stream,
mtime_t *pi_dts )
{
......@@ -384,11 +384,11 @@ static int MuxGetStream( sout_instance_t *p_sout,
int i_stream;
int i;
for( i = 0, i_dts = 0, i_stream = -1; i < p_sout->i_nb_inputs; i++ )
for( i = 0, i_dts = 0, i_stream = -1; i < p_mux->i_nb_inputs; i++ )
{
sout_fifo_t *p_fifo;
p_fifo = p_sout->pp_inputs[i]->p_fifo;
p_fifo = p_mux->pp_inputs[i]->p_fifo;
if( p_fifo->i_depth > 1 )
{
......@@ -567,9 +567,9 @@ static void SetTSDate( sout_buffer_t *p_ts, mtime_t i_dts, mtime_t i_length )
}
}
static int Mux( sout_instance_t *p_sout )
static int Mux( sout_mux_t *p_mux )
{
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_sys_t *p_sys = p_mux->p_sys;
int i_stream;
sout_buffer_t *p_pat, *p_pmt, *p_ts;
......@@ -583,27 +583,27 @@ static int Mux( sout_instance_t *p_sout )
sout_fifo_t *p_fifo;
sout_buffer_t *p_data;
if( MuxGetStream( p_sout, &i_stream, &i_dts ) < 0 )
if( MuxGetStream( p_mux, &i_stream, &i_dts ) < 0 )
{
return( 0 );
}
p_input = p_sout->pp_inputs[i_stream];
p_input = p_mux->pp_inputs[i_stream];
p_fifo = p_input->p_fifo;
p_stream = (ts_stream_t*)p_input->p_mux_data;
p_stream = (ts_stream_t*)p_input->p_sys;
p_data = sout_FifoGet( p_fifo );
i_dts = p_data->i_dts;
i_length = p_data->i_length;
E_( EStoPES )( p_sout, &p_data, p_data, p_stream->i_stream_id, 1);
PEStoTS( p_sout, &p_data, p_data, p_stream );
E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1);
PEStoTS( p_mux->p_sout, &p_data, p_data, p_stream );
if( p_mux->i_ts_packet % 30 == 0 )
if( p_sys->i_ts_packet % 30 == 0 )
{
/* create pat/pmt */
GetPAT( p_sout, &p_pat );
GetPMT( p_sout, &p_pmt );
GetPAT( p_mux, &p_pat );
GetPMT( p_mux, &p_pmt );
p_ts = p_pat;
sout_BufferChain( &p_ts, p_pmt );
......@@ -614,10 +614,10 @@ static int Mux( sout_instance_t *p_sout )
p_ts = p_data;
}
p_mux->i_ts_packet++;
p_sys->i_ts_packet++;
SetTSDate( p_ts, i_dts, i_length );
sout_AccessOutWrite( p_sout->p_access, p_ts );
sout_AccessOutWrite( p_mux->p_access, p_ts );
}
return( 0 );
......@@ -708,14 +708,14 @@ static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
}
#if defined MODULE_NAME_IS_mux_ts
static int GetPAT( sout_instance_t *p_sout,
static int GetPAT( sout_mux_t *p_mux,
sout_buffer_t **pp_ts )
{
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_sys_t *p_sys = p_mux->p_sys;
sout_buffer_t *p_pat;
bits_buffer_t bits;
p_pat = sout_BufferNew( p_sout, 1024 );
p_pat = sout_BufferNew( p_mux->p_sout, 1024 );
p_pat->i_pts = 0;
p_pat->i_dts = 0;
......@@ -731,31 +731,31 @@ static int GetPAT( sout_instance_t *p_sout,
bits_write( &bits, 12, 13 ); // XXX for one program only XXX
bits_write( &bits, 16, 0x01 ); // FIXME stream id
bits_write( &bits, 2, 0x03 ); // FIXME
bits_write( &bits, 5, p_mux->i_pat_version_number );
bits_write( &bits, 5, p_sys->i_pat_version_number );
bits_write( &bits, 1, 1 ); // current_next_indicator
bits_write( &bits, 8, 0 ); // section number
bits_write( &bits, 8, 0 ); // last section number
bits_write( &bits, 16, 1 ); // program number
bits_write( &bits, 3, 0x07 ); // reserved
bits_write( &bits, 13, p_mux->pmt.i_pid ); // program map pid
bits_write( &bits, 13, p_sys->pmt.i_pid ); // program map pid
bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
p_pat->i_size = bits.i_data;
return( PEStoTS( p_sout, pp_ts, p_pat, &p_mux->pat ) );
return( PEStoTS( p_mux->p_sout, pp_ts, p_pat, &p_sys->pat ) );
}
static int GetPMT( sout_instance_t *p_sout,
static int GetPMT( sout_mux_t *p_mux,
sout_buffer_t **pp_ts )
{
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_sys_t *p_sys = p_mux->p_sys;
sout_buffer_t *p_pmt;
bits_buffer_t bits;
int i_stream;
p_pmt = sout_BufferNew( p_sout, 1024 );
p_pmt = sout_BufferNew( p_mux->p_sout, 1024 );
p_pmt->i_pts = 0;
p_pmt->i_dts = 0;
......@@ -768,26 +768,26 @@ static int GetPMT( sout_instance_t *p_sout,
bits_write( &bits, 1, 1 ); // section_syntax_indicator
bits_write( &bits, 1, 0 ); // 0
bits_write( &bits, 2, 0 ); // reserved FIXME
bits_write( &bits, 12, 13 + 5 * p_sout->i_nb_inputs );
bits_write( &bits, 12, 13 + 5 * p_mux->i_nb_inputs );
bits_write( &bits, 16, 1 ); // FIXME program number
bits_write( &bits, 2, 0 ); // FIXME
bits_write( &bits, 5, p_mux->i_pmt_version_number );
bits_write( &bits, 5, p_sys->i_pmt_version_number );
bits_write( &bits, 1, 0 ); // current_next_indicator
bits_write( &bits, 8, 0 ); // section number
bits_write( &bits, 8, 0 ); // last section number
bits_write( &bits, 3, 0 ); // reserved
bits_write( &bits, 13, p_mux->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
bits_write( &bits, 13, p_sys->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
bits_write( &bits, 4, 0 ); // reserved FIXME
bits_write( &bits, 12, 0 ); // program info len FIXME
for( i_stream = 0; i_stream < p_sout->i_nb_inputs; i_stream++ )
for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
{
ts_stream_t *p_stream;
p_stream = (ts_stream_t*)p_sout->pp_inputs[i_stream]->p_mux_data;
p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
bits_write( &bits, 3, 0 ); // reserved
......@@ -800,7 +800,7 @@ static int GetPMT( sout_instance_t *p_sout,
p_pmt->i_size = bits.i_data;
return( PEStoTS( p_sout, pp_ts, p_pmt, &p_mux->pmt ) );
return( PEStoTS( p_mux->p_sout, pp_ts, p_pmt, &p_sys->pmt ) );
}
#elif defined MODULE_NAME_IS_mux_ts_dvbpsi
......@@ -837,29 +837,29 @@ static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
return( p_first );
}
static int GetPAT( sout_instance_t *p_sout,
static int GetPAT( sout_mux_t *p_mux,
sout_buffer_t **pp_ts )
{
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_sys_t *p_sys = p_mux->p_sys;
sout_buffer_t *p_pat;
dvbpsi_pat_t pat;
dvbpsi_psi_section_t *p_section;
dvbpsi_InitPAT( &pat,
0x01, // i_ts_id
p_mux->i_pat_version_number,
p_sys->i_pat_version_number,
0); // b_current_next
/* add all program (only one) */
dvbpsi_PATAddProgram( &pat,
1, // i_number
p_mux->pmt.i_pid ); // i_pid
p_sys->pmt.i_pid ); // i_pid
p_section = dvbpsi_GenPATSections( &pat,
0 ); // max program per section
p_pat = WritePSISection( p_sout, p_section );
p_pat = WritePSISection( p_mux->p_sout, p_section );
PEStoTS( p_sout, pp_ts, p_pat, &p_mux->pat );
PEStoTS( p_mux->p_sout, pp_ts, p_pat, &p_sys->pat );
dvbpsi_DeletePSISections( p_section );
dvbpsi_EmptyPAT( &pat );
......@@ -877,25 +877,25 @@ static uint32_t GetDescriptorLength24b( int i_length )
return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
}
static int GetPMT( sout_instance_t *p_sout,
static int GetPMT( sout_mux_t *p_mux,
sout_buffer_t **pp_ts )
{
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_sys_t *p_sys = p_mux->p_sys;
sout_buffer_t *p_pmt;
dvbpsi_pmt_t pmt;
dvbpsi_pmt_es_t* p_es;
dvbpsi_pmt_es_t *p_es;
dvbpsi_psi_section_t *p_section;
int i_stream;
dvbpsi_InitPMT( &pmt,
0x01, // program number
p_mux->i_pmt_version_number,
p_sys->i_pmt_version_number,
1, // b_current_next
p_mux->i_pcr_pid );
p_sys->i_pcr_pid );
if( p_mux->i_mpeg4_streams > 0 )
if( p_sys->i_mpeg4_streams > 0 )
{
uint8_t iod[4096];
bits_buffer_t bits;
......@@ -918,10 +918,10 @@ static int GetPMT( sout_instance_t *p_sout,
bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
bits_write( &bits, 8, 0xfe ); // visualProfile( // )
bits_write( &bits, 8, 0xff ); // graphicProfile (no )
for( i_stream = 0; i_stream < p_sout->i_nb_inputs; i_stream++ )
for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
{
ts_stream_t *p_stream;
p_stream = (ts_stream_t*)p_sout->pp_inputs[i_stream]->p_mux_data;
p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
{
......@@ -957,7 +957,7 @@ static int GetPMT( sout_instance_t *p_sout,
bits_write( &bits, 8, 0x00 );
bits_write( &bits, 6, 0x00 );
msg_Err( p_sout,"Unsupported stream_type => broken IOD");
msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
}
bits_write( &bits, 1, 0x00 ); // UpStream
bits_write( &bits, 1, 0x01 ); // reserved
......@@ -998,7 +998,7 @@ static int GetPMT( sout_instance_t *p_sout,
bits_align( &bits );
break;
default:
msg_Err( p_sout,"Unsupported SL profile => broken IOD");
msg_Err( p_mux,"Unsupported SL profile => broken IOD");
break;
}
/* fix ESDescr length */
......@@ -1016,11 +1016,11 @@ static int GetPMT( sout_instance_t *p_sout,
bits.p_data );
}
for( i_stream = 0; i_stream < p_sout->i_nb_inputs; i_stream++ )
for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
{
ts_stream_t *p_stream;
p_stream = (ts_stream_t*)p_sout->pp_inputs[i_stream]->p_mux_data;
p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
p_es = dvbpsi_PMTAddES( &pmt,
p_stream->i_stream_type,
......@@ -1067,9 +1067,9 @@ static int GetPMT( sout_instance_t *p_sout,
p_section = dvbpsi_GenPMTSections( &pmt );
p_pmt = WritePSISection( p_sout, p_section );
p_pmt = WritePSISection( p_mux->p_sout, p_section );
PEStoTS( p_sout, pp_ts, p_pmt, &p_mux->pmt );
PEStoTS( p_mux->p_sout, pp_ts, p_pmt, &p_sys->pmt );
dvbpsi_DeletePSISections( p_section );
dvbpsi_EmptyPMT( &pmt );
......
......@@ -2,7 +2,7 @@
* ogg.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: ogg.c,v 1.2 2003/02/25 17:17:43 fenrir Exp $
* $Id: ogg.c,v 1.3 2003/03/11 19:02:30 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -42,10 +42,10 @@
static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
static int Capability( sout_instance_t *, int, void *, void * );
static int AddStream( sout_instance_t *, sout_input_t * );
static int DelStream( sout_instance_t *, sout_input_t * );
static int Mux ( sout_instance_t * );
static int Capability(sout_mux_t *, int, void *, void * );
static int AddStream( sout_mux_t *, sout_input_t * );
static int DelStream( sout_mux_t *, sout_input_t * );
static int Mux ( sout_mux_t * );
/*****************************************************************************
* Module descriptor
......@@ -121,12 +121,12 @@ typedef struct
} ogg_stream_t;
typedef struct sout_mux_s
struct sout_mux_sys_t
{
int b_write_header;
int i_streams;
} sout_mux_t;
};
#define SetWLE( p, v ) _SetWLE( (uint8_t*)p, v)
static void _SetWLE( uint8_t *p, uint16_t i_dw )
......@@ -151,28 +151,28 @@ static void _SetQWLE( uint8_t *p, uint64_t i_qw )
}
static void OggSetDate( sout_buffer_t *, mtime_t , mtime_t );
static sout_buffer_t *OggStreamFlush( sout_instance_t *, ogg_stream_state *, mtime_t );
static sout_buffer_t *OggStreamFlush( sout_mux_t *, ogg_stream_state *, mtime_t );
/*****************************************************************************
* Open:
*****************************************************************************/
static int Open( vlc_object_t *p_this )
{
sout_instance_t *p_sout = (sout_instance_t*)p_this;
sout_mux_t *p_mux;
sout_mux_t *p_mux = (sout_mux_t*)p_this;
sout_mux_sys_t *p_sys;
msg_Info( p_sout, "Open" );
msg_Info( p_mux, "Open" );
p_mux = malloc( sizeof( sout_mux_t ) );
p_mux->i_streams = 0;
p_mux->b_write_header = VLC_TRUE;
p_sys = malloc( sizeof( sout_mux_sys_t ) );
p_sys->i_streams = 0;
p_sys->b_write_header = VLC_TRUE;
p_sout->p_mux_data = (void*)p_mux;
p_sout->pf_mux_capacity = Capability;
p_sout->pf_mux_addstream = AddStream;
p_sout->pf_mux_delstream = DelStream;
p_sout->pf_mux = Mux;
p_sout->i_mux_preheader = 1;
p_mux->p_sys = p_sys;
p_mux->pf_capacity = Capability;
p_mux->pf_addstream = AddStream;
p_mux->pf_delstream = DelStream;
p_mux->pf_mux = Mux;
p_mux->i_preheader = 1;
return VLC_SUCCESS;
}
......@@ -183,15 +183,15 @@ static int Open( vlc_object_t *p_this )
static void Close( vlc_object_t * p_this )
{
sout_instance_t *p_sout = (sout_instance_t*)p_this;
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_t *p_mux = (sout_mux_t*)p_this;
sout_mux_sys_t *p_sys = p_mux->p_sys;
msg_Info( p_sout, "Close" );
msg_Info( p_mux, "Close" );
free( p_mux );
free( p_sys );
}
static int Capability( sout_instance_t *p_sout, int i_query, void *p_args, void *p_answer )
static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer )
{
switch( i_query )
{
......@@ -203,16 +203,16 @@ static int Capability( sout_instance_t *p_sout, int i_query, void *p_args, void
}
}
static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
{
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_sys_t *p_sys = p_mux->p_sys;
ogg_stream_t *p_stream;
BITMAPINFOHEADER *p_bih;
WAVEFORMATEX *p_wf;
msg_Dbg( p_sout, "adding input" );
p_input->p_mux_data = (void*)p_stream = malloc( sizeof( ogg_stream_t ) );
msg_Dbg( p_mux, "adding input" );
p_input->p_sys = (void*)p_stream = malloc( sizeof( ogg_stream_t ) );
p_stream->i_cat = p_input->input_format.i_cat;
p_stream->i_fourcc = p_input->input_format.i_fourcc;
......@@ -257,7 +257,7 @@ static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
}
break;
default:
FREE( p_input->p_mux_data );
FREE( p_input->p_sys );
return( VLC_EGENERIC );
}
break;
......@@ -302,48 +302,48 @@ static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
break;
case VLC_FOURCC( 'v', 'o', 'r', 'b' ):
default:
FREE( p_input->p_mux_data );
FREE( p_input->p_sys );
return( VLC_EGENERIC );
}
break;
default:
FREE( p_input->p_mux_data );
FREE( p_input->p_sys );
return( VLC_EGENERIC );
}
ogg_stream_init (&p_stream->os, rand ());
p_mux->i_streams++;
p_sys->i_streams++;
return( VLC_SUCCESS );
}
static int DelStream( sout_instance_t *p_sout, sout_input_t *p_input )
static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
{
ogg_stream_t *p_stream = (ogg_stream_t*)p_input->p_mux_data;
ogg_stream_t *p_stream = (ogg_stream_t*)p_input->p_sys;
sout_buffer_t *p_og;
msg_Dbg( p_sout, "removing input" );
msg_Dbg( p_mux, "removing input" );
/* flush all remaining data */
p_og = OggStreamFlush( p_sout, &p_stream->os, 0 );
p_og = OggStreamFlush( p_mux, &p_stream->os, 0 );
if( p_og )
{
OggSetDate( p_og, p_stream->i_dts, p_stream->i_length );
sout_AccessOutWrite( p_sout->p_access, p_og );
sout_AccessOutWrite( p_mux->p_access, p_og );
}
ogg_stream_clear( &p_stream->os );
FREE( p_input->p_mux_data );
FREE( p_input->p_sys );
return( 0 );
}
/*
* TODO move this function to src/stream_output.c (used by nearly all muxers)
*/
static int MuxGetStream( sout_instance_t *p_sout,
static int MuxGetStream( sout_mux_t *p_mux,
int *pi_stream,
mtime_t *pi_dts )
{
......@@ -351,11 +351,11 @@ static int MuxGetStream( sout_instance_t *p_sout,
int i_stream;
int i;
for( i = 0, i_dts = 0, i_stream = -1; i < p_sout->i_nb_inputs; i++ )
for( i = 0, i_dts = 0, i_stream = -1; i < p_mux->i_nb_inputs; i++ )
{
sout_fifo_t *p_fifo;
p_fifo = p_sout->pp_inputs[i]->p_fifo;
p_fifo = p_mux->pp_inputs[i]->p_fifo;
if( p_fifo->i_depth > 1 )
{
......@@ -385,7 +385,7 @@ static int MuxGetStream( sout_instance_t *p_sout,
}
static sout_buffer_t *OggStreamFlush( sout_instance_t *p_sout,
static sout_buffer_t *OggStreamFlush( sout_mux_t *p_mux,
ogg_stream_state *p_os,
mtime_t i_pts )
{
......@@ -402,7 +402,7 @@ static sout_buffer_t *OggStreamFlush( sout_instance_t *p_sout,
break;
}
i_size = og.header_len + og.body_len;
p_og = sout_BufferNew( p_sout, i_size);
p_og = sout_BufferNew( p_mux->p_sout, i_size);
memcpy( p_og->p_buffer,
og.header,
......@@ -422,7 +422,7 @@ static sout_buffer_t *OggStreamFlush( sout_instance_t *p_sout,
return( p_og_first );
}
static sout_buffer_t *OggStreamPageOut( sout_instance_t *p_sout,
static sout_buffer_t *OggStreamPageOut( sout_mux_t *p_mux,
ogg_stream_state *p_os,
mtime_t i_pts )
{
......@@ -439,7 +439,7 @@ static sout_buffer_t *OggStreamPageOut( sout_instance_t *p_sout,
break;
}
i_size = og.header_len + og.body_len;
p_og = sout_BufferNew( p_sout, i_size);
p_og = sout_BufferNew( p_mux->p_sout, i_size);
memcpy( p_og->p_buffer,
og.header,
......@@ -459,7 +459,7 @@ static sout_buffer_t *OggStreamPageOut( sout_instance_t *p_sout,
return( p_og_first );
}
static sout_buffer_t *OggCreateHeader( sout_instance_t *p_sout, mtime_t i_dts )
static sout_buffer_t *OggCreateHeader( sout_mux_t *p_mux, mtime_t i_dts )
{
sout_buffer_t *p_hdr = NULL;
sout_buffer_t *p_og;
......@@ -467,11 +467,11 @@ static sout_buffer_t *OggCreateHeader( sout_instance_t *p_sout, mtime_t i_dts )
int i;
/* write header for each stream */
for( i = 0; i < p_sout->i_nb_inputs; i++ )
for( i = 0; i < p_mux->i_nb_inputs; i++ )
{
ogg_stream_t *p_stream;
p_stream = (ogg_stream_t*)p_sout->pp_inputs[i]->p_mux_data;
p_stream = (ogg_stream_t*)p_mux->pp_inputs[i]->p_sys;
if( p_stream->i_fourcc == VLC_FOURCC( 'v', 'o', 'r', 'b' ) )
{
......@@ -508,7 +508,7 @@ static sout_buffer_t *OggCreateHeader( sout_instance_t *p_sout, mtime_t i_dts )
#endif
}
p_og = OggStreamFlush( p_sout, &p_stream->os, 0 );
p_og = OggStreamFlush( p_mux, &p_stream->os, 0 );
sout_BufferChain( &p_hdr, p_og );
}
......@@ -542,21 +542,21 @@ static void OggSetDate( sout_buffer_t *p_og, mtime_t i_dts, mtime_t i_length )
}
}
static int Mux ( sout_instance_t *p_sout )
static int Mux ( sout_mux_t *p_mux )
{
sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
sout_mux_sys_t *p_sys = p_mux->p_sys;
sout_buffer_t *p_og = NULL;
int i_stream;
mtime_t i_dts;
if( p_mux->b_write_header )
if( p_sys->b_write_header )
{
if( MuxGetStream( p_sout, &i_stream, &i_dts) < 0 )
if( MuxGetStream( p_mux, &i_stream, &i_dts) < 0 )
{
return( VLC_SUCCESS );
}
sout_BufferChain( &p_og, OggCreateHeader( p_sout, i_dts ) );
p_mux->b_write_header = VLC_FALSE;
sout_BufferChain( &p_og, OggCreateHeader( p_mux, i_dts ) );
p_sys->b_write_header = VLC_FALSE;
}
for( ;; )
......@@ -566,17 +566,17 @@ static int Mux ( sout_instance_t *p_sout )
sout_buffer_t *p_data;
ogg_packet op;
if( MuxGetStream( p_sout, &i_stream, &i_dts) < 0 )
if( MuxGetStream( p_mux, &i_stream, &i_dts) < 0 )
{
return( VLC_SUCCESS );
}
p_input = p_sout->pp_inputs[i_stream];
p_stream = (ogg_stream_t*)p_input->p_mux_data;
p_input = p_mux->pp_inputs[i_stream];
p_stream = (ogg_stream_t*)p_input->p_sys;
p_data = sout_FifoGet( p_input->p_fifo );
sout_BufferReallocFromPreHeader( p_sout, p_data, 1 );
sout_BufferReallocFromPreHeader( p_mux->p_sout, p_data, 1 );
p_data->p_buffer[0] = PACKET_IS_SYNCPOINT; // FIXME
op.packet = p_data->p_buffer;
......@@ -596,7 +596,7 @@ static int Mux ( sout_instance_t *p_sout )
ogg_stream_packetin( &p_stream->os, &op );
sout_BufferChain( &p_og,
OggStreamPageOut( p_sout,
OggStreamPageOut( p_mux,
&p_stream->os,
p_data->i_pts ) );
......@@ -605,7 +605,7 @@ static int Mux ( sout_instance_t *p_sout )
OggSetDate( p_og, p_stream->i_dts, p_stream->i_length );
p_stream->i_dts = -1;
p_stream->i_length = 0;;
sout_AccessOutWrite( p_sout->p_access, p_og );
sout_AccessOutWrite( p_mux->p_access, p_og );
p_og = NULL;
}
......@@ -618,7 +618,7 @@ static int Mux ( sout_instance_t *p_sout )
p_stream->i_length += p_data->i_length;
}
sout_BufferDelete( p_sout, p_data );
sout_BufferDelete( p_mux->p_sout, p_data );
}
return( VLC_SUCCESS );
......
......@@ -2,7 +2,7 @@
* a52.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: a52.c,v 1.1 2002/12/14 21:32:41 fenrir Exp $
* $Id: a52.c,v 1.2 2003/03/11 19:02:30 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
......@@ -44,7 +44,7 @@ typedef struct packetizer_s
bit_stream_t bit_stream;
/* Output properties */
sout_input_t *p_sout_input;
sout_packetizer_input_t *p_sout_input;
sout_packet_format_t output_format;
uint64_t i_samplescount;
......
......@@ -2,7 +2,7 @@
* copy.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: copy.c,v 1.4 2003/01/23 15:52:04 sam Exp $
* $Id: copy.c,v 1.5 2003/03/11 19:02:30 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
......@@ -44,7 +44,7 @@ typedef struct packetizer_thread_s
decoder_fifo_t *p_fifo;
/* Output properties */
sout_input_t *p_sout_input;
sout_packetizer_input_t *p_sout_input;
sout_packet_format_t output_format;
mtime_t i_pts_start;
......
......@@ -2,7 +2,7 @@
* mpeg4audio.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: mpeg4audio.c,v 1.2 2003/01/23 15:52:04 sam Exp $
* $Id: mpeg4audio.c,v 1.3 2003/03/11 19:02:31 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -59,7 +59,7 @@ typedef struct packetizer_thread_s
bit_stream_t bit_stream;
/* Output properties */
sout_input_t *p_sout_input;
sout_packetizer_input_t *p_sout_input;
sout_packet_format_t output_format;
mtime_t i_pts_start;
......
......@@ -2,7 +2,7 @@
* mpeg4video.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: mpeg4video.c,v 1.7 2003/01/23 15:52:04 sam Exp $
* $Id: mpeg4video.c,v 1.8 2003/03/11 19:02:31 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
......@@ -45,7 +45,7 @@ typedef struct packetizer_thread_s
decoder_fifo_t *p_fifo;
/* Output properties */
sout_input_t *p_sout_input;
sout_packetizer_input_t *p_sout_input;
sout_packet_format_t output_format;
mtime_t i_pts_start;
......
......@@ -2,7 +2,7 @@
* mpegaudio.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: mpegaudio.c,v 1.3 2003/02/18 00:51:40 fenrir Exp $
* $Id: mpegaudio.c,v 1.4 2003/03/11 19:02:31 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
......@@ -44,7 +44,7 @@ typedef struct packetizer_s
bit_stream_t bit_stream;
/* Output properties */
sout_input_t *p_sout_input;
sout_packetizer_input_t *p_sout_input;
sout_packet_format_t output_format;
uint64_t i_samplescount;
......
......@@ -2,7 +2,7 @@
* mpegvideo.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: mpegvideo.c,v 1.9 2003/02/26 13:51:36 gbazin Exp $
* $Id: mpegvideo.c,v 1.10 2003/03/11 19:02:31 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
......@@ -44,7 +44,7 @@ typedef struct packetizer_s
bit_stream_t bit_stream;
/* Output properties */
sout_input_t *p_sout_input;
sout_packetizer_input_t *p_sout_input;
sout_packet_format_t output_format;
mtime_t i_last_dts;
......
......@@ -2,11 +2,11 @@
* stream_output.c : stream output module
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: stream_output.c,v 1.16 2003/02/25 17:17:43 fenrir Exp $
* $Id: stream_output.c,v 1.17 2003/03/11 19:02:31 fenrir Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Laurent Aimar <fenrir@via.ecp.fr>
* Erioc Petit <titer@videolan.org>
* Eric Petit <titer@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
......@@ -37,9 +37,18 @@
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int InitInstance ( sout_instance_t * );
struct sout_instance_sys_t
static int InstanceNewOutput ( sout_instance_t *, char * );
static int InstanceMuxNew ( sout_instance_t *,
char *, char *, char * );
static sout_mux_t * MuxNew ( sout_instance_t*,
char *, sout_access_out_t * );
static sout_input_t *MuxAddStream ( sout_mux_t *, sout_packet_format_t * );
static void MuxDeleteStream ( sout_mux_t *, sout_input_t * );
static void MuxDelete ( sout_mux_t * );
#if 0
typedef struct
{
/* if muxer doesn't support adding stream at any time then we first wait
* for stream then we refuse all stream and start muxing */
......@@ -48,8 +57,93 @@ struct sout_instance_sys_t
/* we wait one second after first stream added */
mtime_t i_add_stream_start;
} sout_instance_sys_mux_t;
#endif
struct sout_instance_sys_t
{
int i_d_u_m_m_y;
};
/*
* Generic MRL parser
*
*/
/* <access>{options}/<way>{options}://<name> */
typedef struct mrl_option_s
{
struct mrl_option_s *p_next;
char *psz_name;
char *psz_value;
} mrl_option_t;
typedef struct
{
char *psz_access;
mrl_option_t *p_access_options;
char *psz_way;
mrl_option_t *p_way_options;
char *psz_name;
} mrl_t;
/* mrl_Parse: parse psz_mrl and fill p_mrl */
static int mrl_Parse( mrl_t *p_mrl, char *psz_mrl );
/* mrl_Clean: clean p_mrl after a call to mrl_Parse */
static void mrl_Clean( mrl_t *p_mrl );
/* some macro */
#define TAB_APPEND( count, tab, p ) \
if( (count) > 0 ) \
{ \
(tab) = realloc( (tab), sizeof( void ** ) * ( (count) + 1 ) ); \
} \
else \
{ \
(tab) = malloc( sizeof( void ** ) ); \
} \
(void**)(tab)[(count)] = (void*)(p); \
(count)++
#define TAB_FIND( count, tab, p, index ) \
{ \
int _i_; \
(index) = -1; \
for( _i_ = 0; _i_ < (count); _i_++ ) \
{ \
if((void**)(tab)[_i_]==(void*)(p)) \
{ \
(index) = _i_; \
break; \
} \
} \
}
#define TAB_REMOVE( count, tab, p ) \
{ \
int i_index; \
TAB_FIND( count, tab, p, i_index ); \
if( i_index >= 0 ) \
{ \
if( count > 1 ) \
{ \
memmove( ((void**)tab + i_index), \
((void**)tab + i_index+1), \
( (count) - i_index - 1 ) * sizeof( void* ) );\
} \
else \
{ \
free( tab ); \
(tab) = NULL; \
} \
(count)--; \
} \
}
#define FREE( p ) if( p ) { free( p ); (p) = NULL; }
/*****************************************************************************
* sout_NewInstance: creates a new stream output instance
......@@ -57,7 +151,8 @@ struct sout_instance_sys_t
sout_instance_t * __sout_NewInstance ( vlc_object_t *p_parent,
char * psz_dest )
{
sout_instance_t * p_sout;
sout_instance_t *p_sout;
char *psz_dup, *psz_parser, *psz_pos;
/* Allocate descriptor */
p_sout = vlc_object_create( p_parent, VLC_OBJECT_SOUT );
......@@ -67,61 +162,142 @@ sout_instance_t * __sout_NewInstance ( vlc_object_t *p_parent,
return NULL;
}
p_sout->psz_dest = strdup( psz_dest );
p_sout->psz_sout = NULL;
p_sout->i_nb_dest = 0;
p_sout->ppsz_dest = NULL;
p_sout->i_preheader = 0;
p_sout->i_nb_mux = 0;
p_sout->pp_mux = 0;
vlc_mutex_init( p_sout, &p_sout->lock );
p_sout->i_nb_inputs = 0;
p_sout->pp_inputs = NULL;
p_sout->p_sys = malloc( sizeof( sout_instance_sys_t ) );
/* now parse psz_sout */
psz_dup = strdup( psz_dest );
psz_parser = psz_dup;
if ( InitInstance( p_sout ) == -1 )
while( ( psz_pos = strchr( psz_parser, '#' ) ) != NULL )
{
*psz_pos++ = '\0';
if( InstanceNewOutput( p_sout, psz_parser ) )
{
msg_Err( p_sout, "adding `%s' failed", psz_parser );
}
psz_parser = psz_pos;
}
if( *psz_parser )
{
if( InstanceNewOutput( p_sout, psz_parser ) )
{
msg_Err( p_sout, "adding `%s' failed", psz_parser );
}
}
free( psz_dup );
if( p_sout->i_nb_dest <= 0 )
{
msg_Err( p_sout, "all sout failed" );
vlc_object_destroy( p_sout );
return NULL;
return( NULL );
}
vlc_object_attach( p_sout, p_parent );
return p_sout;
}
/*****************************************************************************
* sout_DeleteInstance: delete a previously allocated instance
*****************************************************************************/
void sout_DeleteInstance( sout_instance_t * p_sout )
{
int i;
/* Unlink object */
vlc_object_detach( p_sout );
/* *** free all string *** */
FREE( p_sout->psz_sout );
for( i = 0; i < p_sout->i_nb_dest; i++ )
{
FREE( p_sout->ppsz_dest[i] );
}
FREE( p_sout->ppsz_dest );
/* *** there shouldn't be any input ** */
if( p_sout->i_nb_inputs > 0 )
{
msg_Err( p_sout, "i_nb_inputs=%d > 0 !!!!!!", p_sout->i_nb_inputs );
msg_Err( p_sout, "mmmh I have a bad filling...", p_sout->i_nb_inputs );
}
vlc_mutex_destroy( &p_sout->lock );
/* *** remove all muxer *** */
for( i = 0; i < p_sout->i_nb_mux; i++ )
{
#define p_mux p_sout->pp_mux[i]
sout_AccessOutDelete( p_mux->p_access );
MuxDelete( p_mux );
#undef p_mux
}
FREE( p_sout->pp_mux );
#if 0
for( i = 0; i < p_sout->p_sys->i_nb_mux; i++ )
{
FREE( p_sout->p_sys->pp_mux[i] );
}
FREE( p_sout->p_sys->pp_mux );
#endif
/* Free structure */
vlc_object_destroy( p_sout );
}
/*****************************************************************************
* InitInstance: opens appropriate modules
*****************************************************************************/
static int InitInstance( sout_instance_t * p_sout )
static int InstanceNewOutput (sout_instance_t *p_sout, char *psz_dest )
{
mrl_t mrl;
char * psz_dup;
#if 0
/* Parse dest string. Syntax : [[<access>][/<mux>]:][<dest>] */
/* This code is identical to input.c:InitThread. FIXME : factorize it ? */
char * psz_parser = p_sout->psz_dest;
p_sout->psz_access = "";
p_sout->psz_mux = "";
p_sout->psz_name = "";
p_sout->p_access = NULL;
p_sout->p_mux = NULL;
p_sout->i_mux_preheader = 0;
p_sout->i_nb_inputs = 0;
p_sout->pp_inputs = NULL;
vlc_mutex_init( p_sout, &p_sout->lock );
p_sout->p_sys = malloc( sizeof( sout_instance_sys_t ) );
/* fixed after opening muxer */
p_sout->p_sys->b_add_stream_any_time = VLC_FALSE;
p_sout->p_sys->b_waiting_stream = VLC_TRUE;
p_sout->p_sys->i_add_stream_start = -1;
/* Skip the plug-in names */
char * psz_dup = strdup( psz_dest );
char * psz_parser = psz_dup;
char * psz_access = "";
char * psz_mux = "";
char * psz_name = "";
/* *** first parse psz_dest */
while( *psz_parser && *psz_parser != ':' )
{
psz_parser++;
}
#if defined( WIN32 ) || defined( UNDER_CE )
if( psz_parser - p_sout->psz_dest == 1 )
if( psz_parser - psz_dup == 1 )
{
msg_Warn( p_sout, "drive letter %c: found in source string",
*p_sout->psz_dest ) ;
*psz_dup ) ;
psz_parser = "";
}
#endif
if( !*psz_parser )
{
p_sout->psz_access = p_sout->psz_mux = "";
p_sout->psz_name = p_sout->psz_dest;
psz_access = psz_mux = "";
psz_name = psz_dup;
}
else
{
......@@ -133,25 +309,25 @@ static int InitInstance( sout_instance_t * p_sout )
psz_parser += 2 ;
}
p_sout->psz_name = psz_parser ;
psz_name = psz_parser ;
/* Come back to parse the access and mux plug-ins */
psz_parser = p_sout->psz_dest;
psz_parser = psz_dup;
if( !*psz_parser )
{
/* No access */
p_sout->psz_access = "";
psz_access = "";
}
else if( *psz_parser == '/' )
{
/* No access */
p_sout->psz_access = "";
psz_access = "";
psz_parser++;
}
else
{
p_sout->psz_access = psz_parser;
psz_access = psz_parser;
while( *psz_parser && *psz_parser != '/' )
{
......@@ -167,91 +343,93 @@ static int InitInstance( sout_instance_t * p_sout )
if( !*psz_parser )
{
/* No mux */
p_sout->psz_mux = "";
psz_mux = "";
}
else
{
p_sout->psz_mux = psz_parser;
psz_mux = psz_parser;
}
}
msg_Dbg( p_sout, "access `%s', mux `%s', name `%s'",
p_sout->psz_access, p_sout->psz_mux, p_sout->psz_name );
/* Find and open appropriate access module */
p_sout->p_access =
sout_AccessOutNew( p_sout, p_sout->psz_access, p_sout->psz_name );
if( p_sout->p_access == NULL )
{
msg_Err( p_sout, "no suitable sout access module for `%s/%s://%s'",
p_sout->psz_access, p_sout->psz_mux, p_sout->psz_name );
return -1;
}
psz_access, psz_mux, psz_name );
#endif
mrl_Parse( &mrl, psz_dest );
msg_Dbg( p_sout, "access `%s', mux `%s', name `%s'",
mrl.psz_access, mrl.psz_way, mrl.psz_name );
/* Find and open appropriate mux module */
p_sout->p_mux =
module_Need( p_sout, "sout mux", p_sout->psz_mux );
vlc_mutex_lock( &p_sout->lock );
/* *** create mux *** */
if( p_sout->p_mux == NULL )
if( InstanceMuxNew( p_sout, mrl.psz_way, mrl.psz_access, mrl.psz_name ) )
{
msg_Err( p_sout, "no suitable mux module for `%s/%s://%s'",
p_sout->psz_access, p_sout->psz_mux, p_sout->psz_name );
msg_Err( p_sout, "cannot create sout chain for %s/%s://%s",
mrl.psz_access, mrl.psz_way, mrl.psz_name );
sout_AccessOutDelete( p_sout->p_access );
return -1;
}
if( p_sout->pf_mux_capacity )
{
int b_answer;
if( p_sout->pf_mux_capacity( p_sout,
SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME,
NULL, (void*)&b_answer ) != SOUT_MUX_CAP_ERR_OK )
{
b_answer = VLC_FALSE;
mrl_Clean( &mrl );
vlc_mutex_unlock( &p_sout->lock );
return( VLC_EGENERIC );
}
if( b_answer )
mrl_Clean( &mrl );
/* *** finish all setup *** */
if( p_sout->psz_sout )
{
msg_Dbg( p_sout, "muxer support adding stream at any time" );
p_sout->p_sys->b_add_stream_any_time = VLC_TRUE;
p_sout->p_sys->b_waiting_stream = VLC_FALSE;
p_sout->psz_sout =
realloc( p_sout->psz_sout,
strlen( p_sout->psz_sout ) +2+1+ strlen( psz_dest ) );
strcat( p_sout->psz_sout, "#" );
strcat( p_sout->psz_sout, psz_dest );
}
else
{
p_sout->p_sys->b_add_stream_any_time = VLC_FALSE;
p_sout->p_sys->b_waiting_stream = VLC_TRUE;
p_sout->psz_sout = strdup( psz_dest );
}
}
p_sout->i_nb_inputs = 0;
p_sout->pp_inputs = NULL;
psz_dup = strdup( psz_dest );
TAB_APPEND( p_sout->i_nb_dest, p_sout->ppsz_dest, psz_dup );
vlc_mutex_unlock( &p_sout->lock );
return 0;
}
msg_Dbg( p_sout, "complete sout `%s'", p_sout->psz_sout );
return VLC_SUCCESS;
}
/*****************************************************************************
* sout_DeleteInstance: delete a previously allocated instance
*****************************************************************************/
void sout_DeleteInstance( sout_instance_t * p_sout )
static int InstanceMuxNew ( sout_instance_t *p_sout,
char *psz_mux, char *psz_access, char *psz_name )
{
/* Unlink object */
vlc_object_detach( p_sout );
if( p_sout->p_mux )
sout_access_out_t *p_access;
sout_mux_t *p_mux;
/* *** find and open appropriate access module *** */
p_access =
sout_AccessOutNew( p_sout, psz_access, psz_name );
if( p_access == NULL )
{
module_Unneed( p_sout, p_sout->p_mux );
msg_Err( p_sout, "no suitable sout access module for `%s/%s://%s'",
psz_access, psz_mux, psz_name );
return( VLC_EGENERIC );
}
if( p_sout->p_access )
/* *** find and open appropriate mux module *** */
p_mux = MuxNew( p_sout, psz_mux, p_access );
if( p_mux == NULL )
{
sout_AccessOutDelete( p_sout->p_access );
msg_Err( p_sout, "no suitable sout mux module for `%s/%s://%s'",
psz_access, psz_mux, psz_name );
sout_AccessOutDelete( p_access );
return( VLC_EGENERIC );
}
vlc_mutex_destroy( &p_sout->lock );
p_sout->i_preheader = __MAX( p_sout->i_preheader,
p_mux->i_preheader );
TAB_APPEND( p_sout->i_nb_mux, p_sout->pp_mux, p_mux );
/* Free structure */
vlc_object_destroy( p_sout );
}
return VLC_SUCCESS;
}
/*****************************************************************************
* sout_AccessOutNew: allocate a new access out
*****************************************************************************/
......@@ -279,8 +457,10 @@ sout_access_out_t *sout_AccessOutNew( sout_instance_t *p_sout,
if( !p_access->p_module )
{
free( p_access->psz_access );
free( p_access->psz_name );
vlc_object_destroy( p_access );
p_access = NULL;
return( NULL );
}
return p_access;
......@@ -318,15 +498,209 @@ int sout_AccessOutWrite( sout_access_out_t *p_access, sout_buffer_t *p_buffer )
static sout_input_t *SoutInputCreate( sout_instance_t *p_sout,
sout_packet_format_t *p_format )
{
sout_input_t *p_input;
p_input = malloc( sizeof( sout_input_t ) );
p_input->p_sout = p_sout;
memcpy( &p_input->input_format,
p_format,
sizeof( sout_packet_format_t ) );
p_input->p_fifo = sout_FifoCreate( p_sout );
p_input->p_sys = NULL;
return p_input;
}
static void SoutInputDestroy( sout_instance_t *p_sout,
sout_input_t *p_input )
{
sout_FifoDestroy( p_sout, p_input->p_fifo );
free( p_input );
}
/*****************************************************************************
* Mux*: create/destroy/manipulate muxer.
* XXX: for now they are private, but I will near export them
* to allow muxer creating private muxer (ogg in avi, flexmux in ts/ps)
*****************************************************************************/
/*****************************************************************************
* MuxNew: allocate a new mux
*****************************************************************************/
static sout_mux_t * MuxNew ( sout_instance_t *p_sout,
char *psz_mux,
sout_access_out_t *p_access )
{
sout_mux_t *p_mux;
p_mux = vlc_object_create( p_sout,
sizeof( sout_mux_t ) );
if( p_mux == NULL )
{
msg_Err( p_sout, "out of memory" );
return NULL;
}
p_mux->p_sout = p_sout;
p_mux->psz_mux = strdup( psz_mux);
p_mux->p_access = p_access;
p_mux->i_preheader = 0;
p_mux->pf_capacity = NULL;
p_mux->pf_addstream = NULL;
p_mux->pf_delstream = NULL;
p_mux->pf_mux = NULL;
p_mux->i_nb_inputs = 0;
p_mux->pp_inputs = NULL;
p_mux->p_sys = NULL;
p_mux->p_module = module_Need( p_mux,
"sout mux",
p_mux->psz_mux );
if( p_mux->p_module == NULL )
{
FREE( p_mux->psz_mux );
vlc_object_destroy( p_mux );
return NULL;
}
/* *** probe mux capacity *** */
if( p_mux->pf_capacity )
{
int b_answer;
if( p_mux->pf_capacity( p_mux,
SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME,
NULL, (void*)&b_answer ) != SOUT_MUX_CAP_ERR_OK )
{
b_answer = VLC_FALSE;
}
if( b_answer )
{
msg_Dbg( p_sout, "muxer support adding stream at any time" );
p_mux->b_add_stream_any_time = VLC_TRUE;
p_mux->b_waiting_stream = VLC_FALSE;
}
else
{
p_mux->b_add_stream_any_time = VLC_FALSE;
p_mux->b_waiting_stream = VLC_TRUE;
}
}
else
{
p_mux->b_add_stream_any_time = VLC_FALSE;
p_mux->b_waiting_stream = VLC_TRUE;
}
p_mux->i_add_stream_start = -1;
return p_mux;
}
static void MuxDelete ( sout_mux_t *p_mux )
{
if( p_mux->p_module )
{
module_Unneed( p_mux, p_mux->p_module );
}
free( p_mux->psz_mux );
vlc_object_destroy( p_mux );
}
static sout_input_t *MuxAddStream ( sout_mux_t *p_mux,
sout_packet_format_t *p_format )
{
sout_input_t *p_input;
if( !p_mux->b_add_stream_any_time && !p_mux->b_waiting_stream)
{
msg_Err( p_mux, "cannot add a new stream (unsuported while muxing for this format)" );
return NULL;
}
if( p_mux->i_add_stream_start < 0 )
{
/* we wait for one second */
p_mux->i_add_stream_start = mdate();
}
msg_Dbg( p_mux, "adding a new input" );
/* create a new sout input */
p_input = SoutInputCreate( p_mux->p_sout, p_format );
TAB_APPEND( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input );
if( p_mux->pf_addstream( p_mux, p_input ) < 0 )
{
msg_Err( p_mux, "cannot add this stream" );
MuxDeleteStream( p_mux, p_input );
return( NULL );
}
return( p_input );
}
static void MuxDeleteStream ( sout_mux_t *p_mux,
sout_input_t *p_input )
{
int i_index;
TAB_FIND( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input, i_index );
if( i_index >= 0 )
{
if( p_mux->pf_delstream( p_mux, p_input ) < 0 )
{
msg_Err( p_mux, "cannot del this stream from mux" );
}
/* remove the entry */
TAB_REMOVE( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input );
if( p_mux->i_nb_inputs == 0 )
{
msg_Warn( p_mux, "no more input stream for this mux" );
}
SoutInputDestroy( p_mux->p_sout, p_input );
}
}
static void MuxSendBuffer ( sout_mux_t *p_mux,
sout_input_t *p_input,
sout_buffer_t *p_buffer )
{
sout_FifoPut( p_input->p_fifo, p_buffer );
if( p_mux->b_waiting_stream )
{
if( p_mux->i_add_stream_start > 0 &&
p_mux->i_add_stream_start + (mtime_t)1000000 < mdate() )
{
/* more than 1 second, start muxing */
p_mux->b_waiting_stream = VLC_FALSE;
}
else
{
return;
}
}
p_mux->pf_mux( p_mux );
}
/*****************************************************************************
*
*****************************************************************************/
sout_input_t *__sout_InputNew( vlc_object_t *p_this,
sout_packetizer_input_t *__sout_InputNew( vlc_object_t *p_this,
sout_packet_format_t *p_format )
{
sout_instance_t *p_sout = NULL;
sout_input_t *p_input;
sout_packetizer_input_t *p_input;
int i_try;
int i_mux;
vlc_bool_t b_accepted = VLC_FALSE;
/* search an stream output */
for( i_try = 0; i_try < 12; i_try++ )
......@@ -348,59 +722,55 @@ sout_input_t *__sout_InputNew( vlc_object_t *p_this,
msg_Err( p_this, "cannot find any stream ouput" );
return( NULL );
}
if( !p_sout->p_sys->b_add_stream_any_time && !p_sout->p_sys->b_waiting_stream)
{
msg_Err( p_sout, "cannot add a new stream (unsuported while muxing for this format)" );
return( NULL );
}
msg_Dbg( p_sout, "adding a new input" );
if( p_sout->p_sys->i_add_stream_start < 0 )
{
/* we wait for one second */
p_sout->p_sys->i_add_stream_start = mdate();
}
/* create a new sout input */
p_input = malloc( sizeof( sout_input_t ) );
/* *** create a packetizer input *** */
p_input = malloc( sizeof( sout_packetizer_input_t ) );
p_input->p_sout = p_sout;
vlc_mutex_init( p_sout, &p_input->lock );
p_input->i_nb_inputs = 0;
p_input->pp_inputs = NULL;
p_input->i_nb_mux = 0;
p_input->pp_mux = NULL;
memcpy( &p_input->input_format,
p_format,
sizeof( sout_packet_format_t ) );
p_input->p_fifo = sout_FifoCreate( p_sout );
p_input->p_mux_data = NULL;
if( p_input->input_format.i_fourcc != VLC_FOURCC( 'n', 'u', 'l', 'l' ) )
if( p_format->i_fourcc == VLC_FOURCC( 'n', 'u', 'l', 'l' ) )
{
/* add this new one to p_sout */
vlc_object_release( p_sout );
return p_input;
}
vlc_mutex_lock( &p_sout->lock );
if( p_sout->i_nb_inputs == 0 )
/* *** add this input to all muxers *** */
for( i_mux = 0; i_mux < p_sout->i_nb_mux; i_mux++ )
{
p_sout->pp_inputs = malloc( sizeof( sout_input_t * ) );
}
else
sout_input_t *p_mux_input;
#define p_mux p_sout->pp_mux[i_mux]
p_mux_input = MuxAddStream( p_mux, p_format );
if( p_mux_input )
{
p_sout->pp_inputs = realloc( p_sout->pp_inputs,
sizeof( sout_input_t * ) *
( p_sout->i_nb_inputs + 1 ) );
TAB_APPEND( p_input->i_nb_inputs, p_input->pp_inputs, p_mux_input );
TAB_APPEND( p_input->i_nb_mux, p_input->pp_mux, p_mux );
b_accepted = VLC_TRUE;
}
#undef p_mux
}
p_sout->pp_inputs[p_sout->i_nb_inputs] = p_input;
p_sout->i_nb_inputs++;
if( p_sout->pf_mux_addstream( p_sout, p_input ) < 0 )
if( !b_accepted )
{
msg_Err( p_sout, "cannot add this stream" );
/* all muxer refuse this stream, so delete it */
free( p_input );
vlc_mutex_unlock( &p_sout->lock );
sout_InputDelete( p_input );
vlc_mutex_lock( &p_sout->lock );
p_input = NULL;
vlc_object_release( p_sout );
return( NULL );
}
TAB_APPEND( p_sout->i_nb_inputs, p_sout->pp_inputs, p_input );
vlc_mutex_unlock( &p_sout->lock );
}
vlc_object_release( p_sout );
......@@ -408,96 +778,65 @@ sout_input_t *__sout_InputNew( vlc_object_t *p_this,
}
int sout_InputDelete( sout_input_t *p_input )
int sout_InputDelete( sout_packetizer_input_t *p_input )
{
sout_instance_t *p_sout = p_input->p_sout;
int i_input;
msg_Dbg( p_sout, "removing an input" );
vlc_mutex_lock( &p_sout->lock );
sout_FifoDestroy( p_sout, p_input->p_fifo );
vlc_mutex_destroy( &p_input->lock );
for( i_input = 0; i_input < p_sout->i_nb_inputs; i_input++ )
/* *** remove this input to all muxers *** */
for( i_input = 0; i_input < p_input->i_nb_inputs; i_input++ )
{
if( p_sout->pp_inputs[i_input] == p_input )
{
break;
}
}
if( i_input < p_sout->i_nb_inputs )
{
if( p_sout->pf_mux_delstream( p_sout, p_input ) < 0 )
{
msg_Err( p_sout, "cannot del this stream from mux" );
MuxDeleteStream( p_input->pp_mux[i_input], p_input->pp_inputs[i_input] );
}
/* remove the entry */
if( p_sout->i_nb_inputs > 1 )
{
memmove( &p_sout->pp_inputs[i_input],
&p_sout->pp_inputs[i_input+1],
(p_sout->i_nb_inputs - i_input - 1) * sizeof( sout_input_t*) );
}
else
{
free( p_sout->pp_inputs );
}
p_sout->i_nb_inputs--;
TAB_REMOVE( p_sout->i_nb_inputs, p_sout->pp_inputs, p_input );
if( p_sout->i_nb_inputs == 0 )
{
msg_Warn( p_sout, "no more input stream" );
}
}
else if( p_input->input_format.i_fourcc != VLC_FOURCC( 'n', 'u', 'l', 'l' ) )
{
msg_Err( p_sout, "cannot find the input to be deleted" );
}
free( p_input->pp_inputs );
free( p_input->pp_mux );
free( p_input );
vlc_mutex_unlock( &p_sout->lock );
return( 0 );
}
int sout_InputSendBuffer( sout_input_t *p_input, sout_buffer_t *p_buffer )
int sout_InputSendBuffer( sout_packetizer_input_t *p_input, sout_buffer_t *p_buffer )
{
sout_instance_sys_t *p_sys = p_input->p_sout->p_sys;
// sout_instance_sys_t *p_sys = p_input->p_sout->p_sys;
/* msg_Dbg( p_input->p_sout,
"send buffer, size:%d", p_buffer->i_size ); */
if( p_input->input_format.i_fourcc != VLC_FOURCC( 'n', 'u', 'l', 'l' ) )
if( p_input->input_format.i_fourcc != VLC_FOURCC( 'n', 'u', 'l', 'l' ) &&
p_input->i_nb_inputs > 0 )
{
sout_FifoPut( p_input->p_fifo, p_buffer );
int i;
if( p_sys->b_waiting_stream )
{
if( p_sys->i_add_stream_start > 0 &&
p_sys->i_add_stream_start + (mtime_t)1000000 < mdate() )
{
/* more than 1 second, start muxing */
p_sys->b_waiting_stream = VLC_FALSE;
}
else
vlc_mutex_lock( &p_input->p_sout->lock );
for( i = 0; i < p_input->i_nb_inputs - 1; i++ )
{
return( 0 );
}
sout_buffer_t *p_dup;
p_dup = sout_BufferDuplicate( p_input->p_sout, p_buffer );
MuxSendBuffer( p_input->pp_mux[i],
p_input->pp_inputs[i],
p_dup );
}
vlc_mutex_lock( &p_input->p_sout->lock );
p_input->p_sout->pf_mux( p_input->p_sout );
MuxSendBuffer( p_input->pp_mux[p_input->i_nb_inputs-1],
p_input->pp_inputs[p_input->i_nb_inputs-1],
p_buffer );
vlc_mutex_unlock( &p_input->p_sout->lock );
}
else
{
sout_BufferDelete( p_input->p_sout, p_buffer );
}
return( 0 );
}
......@@ -612,26 +951,26 @@ sout_buffer_t *sout_FifoShow( sout_fifo_t *p_fifo )
sout_buffer_t *sout_BufferNew( sout_instance_t *p_sout, size_t i_size )
{
sout_buffer_t *p_buffer;
size_t i_prehader;
size_t i_preheader;
#ifdef DEBUG_BUFFER
msg_Dbg( p_sout, "allocating an new buffer, size:%d", (uint32_t)i_size );
#endif
p_buffer = malloc( sizeof( sout_buffer_t ) );
i_prehader = p_sout->i_mux_preheader;
i_preheader = p_sout->i_preheader;
if( i_size > 0 )
{
p_buffer->p_allocated_buffer = malloc( i_size + i_prehader );
p_buffer->p_buffer = p_buffer->p_allocated_buffer + i_prehader;
p_buffer->p_allocated_buffer = malloc( i_size + i_preheader );
p_buffer->p_buffer = p_buffer->p_allocated_buffer + i_preheader;
}
else
{
p_buffer->p_allocated_buffer = NULL;
p_buffer->p_buffer = NULL;
}
p_buffer->i_allocated_size = i_size + i_prehader;
p_buffer->i_allocated_size = i_size + i_preheader;
p_buffer->i_buffer_size = i_size;
p_buffer->i_size = i_size;
......@@ -646,7 +985,7 @@ sout_buffer_t *sout_BufferNew( sout_instance_t *p_sout, size_t i_size )
}
int sout_BufferRealloc( sout_instance_t *p_sout, sout_buffer_t *p_buffer, size_t i_size )
{
size_t i_prehader;
size_t i_preheader;
#ifdef DEBUG_BUFFER
msg_Dbg( p_sout,
......@@ -655,9 +994,9 @@ int sout_BufferRealloc( sout_instance_t *p_sout, sout_buffer_t *p_buffer, size_t
(uint32_t)i_size );
#endif
i_prehader = p_buffer->p_buffer - p_buffer->p_allocated_buffer;
i_preheader = p_buffer->p_buffer - p_buffer->p_allocated_buffer;
if( !( p_buffer->p_allocated_buffer = realloc( p_buffer->p_allocated_buffer, i_size + i_prehader ) ) )
if( !( p_buffer->p_allocated_buffer = realloc( p_buffer->p_allocated_buffer, i_size + i_preheader ) ) )
{
msg_Err( p_sout, "realloc failed" );
p_buffer->i_allocated_size = 0;
......@@ -666,9 +1005,9 @@ int sout_BufferRealloc( sout_instance_t *p_sout, sout_buffer_t *p_buffer, size_t
p_buffer->p_buffer = NULL;
return( -1 );
}
p_buffer->p_buffer = p_buffer->p_allocated_buffer + i_prehader;
p_buffer->p_buffer = p_buffer->p_allocated_buffer + i_preheader;
p_buffer->i_allocated_size = i_size + i_prehader;
p_buffer->i_allocated_size = i_size + i_preheader;
p_buffer->i_buffer_size = i_size;
return( 0 );
......@@ -741,3 +1080,218 @@ void sout_BufferChain( sout_buffer_t **pp_chain,
p->p_next = p_buffer;
}
}
#if 0
static int mrl_ParseOptions( mrl_option_t **pp_opt, char *psz_options )
{
mrl_option_t **pp_last = pp_opt;
char *psz_parser = strdup( psz_options );
*pp_last = NULL;
if( *psz_parser == '=' )
{
free( psz_parser );
return( VLC_EGENERIC );
}
if( *psz_parser == '{' )
{
free( psz_parser );
}
for( ;; )
{
char *psz_end;
mrl_option_t opt;
/* skip space */
while( *psz_parser && ( *psz_parser == ' ' || *psz_parser == '\t' || *psz_parser == ';' ) )
{
psz_parser++;
}
if( ( psz_end = strchr( psz_parser, '=' ) ) != NULL )
{
opt.p_next = NULL;
while( psz_end > psz_parser && ( *psz_end == ' ' || *psz_end == '\t' ) )
{
psz_end--;
}
if( psz_end - psz_parser <= 0 )
{
return( VLC_EGENERIC );
}
*psz_end = '\0';
opt.psz_name = strdup( psz_parser );
psz_parser = psz_end + 1;
if( ( psz_end = strchr( psz_parser, ';' ) ) == NULL &&
( psz_end = strchr( psz_parser, '}' ) ) == NULL )
{
psz_end = psz_parser + strlen( psz_parser ) + 1;
}
opt.psz_value = strdup( psz_parser );
fprintf( stderr, "option: name=`%s' value=`%s'\n",
opt.psz_name,
opt.psz_value );
psz_parser = psz_end + 1;
*pp_last = malloc( sizeof( mrl_option_t ) );
**pp_last = opt;
}
else
{
break;
}
}
}
#endif
static int mrl_Parse( mrl_t *p_mrl, char *psz_mrl )
{
char * psz_dup = strdupa( psz_mrl );
char * psz_parser = psz_dup;
char * psz_access = "";
char * psz_way = "";
char * psz_name = "";
/* *** first parse psz_dest */
while( *psz_parser && *psz_parser != ':' )
{
if( *psz_parser == '{' )
{
while( *psz_parser && *psz_parser != '}' )
{
psz_parser++;
}
if( *psz_parser )
{
psz_parser++;
}
}
else
{
psz_parser++;
}
}
#if defined( WIN32 ) || defined( UNDER_CE )
if( psz_parser - psz_dup == 1 )
{
msg_Warn( p_sout, "drive letter %c: found in source string",
*psz_dup ) ;
psz_parser = "";
}
#endif
if( !*psz_parser )
{
psz_access = psz_way = "";
psz_name = psz_dup;
}
else
{
*psz_parser++ = '\0';
/* let's skip '//' */
if( psz_parser[0] == '/' && psz_parser[1] == '/' )
{
psz_parser += 2 ;
}
psz_name = psz_parser ;
/* Come back to parse the access and mux plug-ins */
psz_parser = psz_dup;
if( !*psz_parser )
{
/* No access */
psz_access = "";
}
else if( *psz_parser == '/' )
{
/* No access */
psz_access = "";
psz_parser++;
}
else
{
psz_access = psz_parser;
while( *psz_parser && *psz_parser != '/' )
{
if( *psz_parser == '{' )
{
while( *psz_parser && *psz_parser != '}' )
{
psz_parser++;
}
if( *psz_parser )
{
psz_parser++;
}
}
else
{
psz_parser++;
}
}
if( *psz_parser == '/' )
{
*psz_parser++ = '\0';
}
}
if( !*psz_parser )
{
/* No mux */
psz_way = "";
}
else
{
psz_way = psz_parser;
}
}
#if 0
if( ( psz_parser = strchr( psz_access, '{' ) ) != NULL )
{
mrl_ParseOptions( &p_mrl->p_access_options, psz_parser );
*psz_parser = '\0';
}
if( ( psz_parser = strchr( psz_way, '{' ) ) != NULL )
{
mrl_ParseOptions( &p_mrl->p_way_options, psz_parser );
*psz_parser = '\0';
}
#endif
p_mrl->p_access_options = NULL;
p_mrl->p_way_options = NULL;
p_mrl->psz_access = strdup( psz_access );
p_mrl->psz_way = strdup( psz_way );
p_mrl->psz_name = strdup( psz_name );
return( VLC_SUCCESS );
}
/* mrl_Clean: clean p_mrl after a call to mrl_Parse */
static void mrl_Clean( mrl_t *p_mrl )
{
FREE( p_mrl->psz_access );
FREE( p_mrl->psz_way );
FREE( p_mrl->psz_name );
}
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