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, void *, void *);
int (* pf_mux_addstream )( sout_instance_t *,
sout_input_t * );
int (* pf_mux_delstream )( sout_instance_t *,
sout_input_t * );
int (* pf_mux ) ( sout_instance_t * );
int i_preheader;
int (* pf_capacity) ( sout_mux_t *,
int, void *, void *);
int (* pf_addstream )( sout_mux_t *,
sout_input_t * );
int (* pf_delstream )( sout_mux_t *,
sout_input_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_buffer_t *p_hdr;
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",
i_stream,
p_stream->i_duration/1000000, p_stream->i_totalsize,
p_stream->i_frames,
p_stream->f_fps, p_stream->i_bitrate/1024 );
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;
avi_stream_t *p_stream;
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;
avi_stream_t *p_stream;
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,20 +511,20 @@ 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;
avi_stream_t *p_video = NULL;
sout_mux_sys_t *p_sys = p_mux->p_sys;
avi_stream_t *p_video = NULL;
int i_stream;
uint32_t i_microsecperframe;
int i_maxbytespersec;
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 );