LDFLAGS_a52tofloat32="${LDFLAGS_a52tofloat32} -lm")
AC_CHECK_LIB(m,pow,
LDFLAGS_ffmpeg="${LDFLAGS_ffmpeg} -lm"
+ LDFLAGS_stream_out_transcode="${LDFLAGS_stream_out_transcode} -lm"
LDFLAGS_imdct="${LDFLAGS_imdct} -lm"
LDFLAGS_imdct3dn="${LDFLAGS_imdct3dn} -lm"
LDFLAGS_imdctsse="${LDFLAGS_imdctsse} -lm"
PLUGINS="${PLUGINS} packetizer_mpeg4video packetizer_mpeg4audio"
PLUGINS="${PLUGINS} packetizer_copy"
- PLUGINS="${PLUGINS} vout_encoder"
+ PLUGINS="${PLUGINS} stream_out_dummy stream_out_standard stream_out_es"
+ PLUGINS="${PLUGINS} stream_out_duplicate stream_out_display"
dnl Ogg/ogm
AC_CHECK_HEADERS(ogg/ogg.h, [
then
CPPFLAGS_ffmpeg="${CPPFLAGS_ffmpeg} -I${with_ffmpeg}/include/ffmpeg"
LDFLAGS_ffmpeg="${LDFLAGS_ffmpeg} -L${with_ffmpeg}/lib"
+
+ CPPFLAGS_stream_out_transcode="${CPPFLAGS_stream_out_transcode} -I${with_ffmpeg}/include/ffmpeg"
+ LDFLAGS_stream_out_transcode="${LDFLAGS_stream_out_transcode} -L${with_ffmpeg}/lib"
+
fi
dnl Add postprocessing modules
then
dnl Use a custom libffmpeg
AC_MSG_RESULT(${real_ffmpeg_tree}/libavcodec/libavcodec.a)
- BUILTINS="${BUILTINS} ffmpeg"
+ BUILTINS="${BUILTINS} ffmpeg stream_out_transcode"
LDFLAGS_ffmpeg="${LDFLAGS_ffmpeg} -L${real_ffmpeg_tree}/libavcodec -lavcodec"
CPPFLAGS_ffmpeg="${CPPFLAGS_ffmpeg} -I${real_ffmpeg_tree}/libavcodec"
+
+ LDFLAGS_stream_out_transcode="${LDFLAGS_stream_out_transcode} -L${real_ffmpeg_tree}/libavcodec -lavcodec"
+ CPPFLAGS_stream_out_transcode="${CPPFLAGS_stream_out_transcode} -I${real_ffmpeg_tree}/libavcodec"
+
else
dnl The given libavcodec wasn't built
AC_MSG_RESULT(no)
CPPFLAGS="${CPPFLAGS_save} ${CPPFLAGS_ffmpeg}"
LDFLAGS="${LDFLAGS_save} ${LDFLAGS_ffmpeg}"
AC_CHECK_LIB(avcodec, avcodec_init, [
- BUILTINS="${BUILTINS} ffmpeg"
- LDFLAGS_ffmpeg="${LDFLAGS_ffmpeg} -lavcodec" ],
+ BUILTINS="${BUILTINS} ffmpeg stream_out_transcode"
+ LDFLAGS_ffmpeg="${LDFLAGS_ffmpeg} -lavcodec"
+ LDFLAGS_stream_out_transcode="${LDFLAGS_stream_out_transcode} -lavcodec" ],
[ AC_MSG_ERROR([Cannot find libavcodec library...]) ])
LDFLAGS="${LDFLAGS_save}"
CPPFLAGS="${CPPFLAGS_save}"
* control the pace of reading.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
- * $Id: input_ext-intf.h,v 1.87 2003/03/24 17:15:29 gbazin Exp $
+ * $Id: input_ext-intf.h,v 1.88 2003/04/13 20:00:20 fenrir Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
count_t c_packets; /* total packets read */
count_t c_invalid_packets; /* invalid packets read */
+
+ /* XXX hack: to force a decoder instead of mode based on sout */
+ vlc_bool_t b_force_decoder;
};
/* Special PID values - note that the PID is only on 13 bits, and that values
* stream_output.h : stream output module
*****************************************************************************
* Copyright (C) 2002 VideoLAN
- * $Id: stream_output.h,v 1.9 2003/03/11 19:02:30 fenrir Exp $
+ * $Id: stream_output.h,v 1.10 2003/04/13 20:00:20 fenrir Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Laurent Aimar <fenrir@via.ecp.fr>
struct sout_buffer_t *p_next;
};
-struct sout_packet_format_t
+struct sout_format_t
{
- int i_cat; // AUDIO_ES, VIDEO_ES, SPU_ES
+ int i_cat;
vlc_fourcc_t i_fourcc;
- void *p_format; // WAVEFORMATEX or BITMAPINFOHEADER
+ /* audio */
+ int i_sample_rate;
+ int i_channels;
+ int i_block_align;
+
+ /* video */
+ int i_width;
+ int i_height;
+
+ int i_bitrate;
+ int i_extra_data;
+ uint8_t *p_extra_data;
+
};
struct sout_fifo_t
sout_buffer_t **pp_last;
};
+typedef struct sout_stream_id_t sout_stream_id_t;
+
/* for mux */
struct sout_input_t
{
-// vlc_mutex_t lock;
-
- sout_instance_t *p_sout;
+ sout_instance_t *p_sout;
- sout_packet_format_t input_format;
- sout_fifo_t *p_fifo;
+ sout_format_t *p_fmt;
+ sout_fifo_t *p_fifo;
- void *p_sys;
+ void *p_sys;
};
-/* for packetizr */
+/* for packetizer */
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;
+ sout_instance_t *p_sout;
- int i_nb_mux; // not really used, just usefull with TAB_*
- sout_mux_t **pp_mux;
+ sout_format_t *p_fmt;
+ sout_stream_id_t *id;
};
+
#define SOUT_METHOD_NONE 0x00
#define SOUT_METHOD_FILE 0x10
#define SOUT_METHOD_NETWORK 0x20
+typedef struct sout_access_out_sys_t sout_access_out_sys_t;
struct sout_access_out_t
{
VLC_COMMON_MEMBERS
mtime_t i_add_stream_start;
};
+
+
+struct sout_cfg_t
+{
+ sout_cfg_t *p_next;
+
+ char *psz_name;
+ char *psz_value;
+};
+
+typedef struct sout_stream_sys_t sout_stream_sys_t;
+struct sout_stream_t
+{
+ VLC_COMMON_MEMBERS
+
+ module_t *p_module;
+ sout_instance_t *p_sout;
+
+ char *psz_name;
+ sout_cfg_t *p_cfg;
+ char *psz_next;
+
+ /* add, remove a stream */
+ sout_stream_id_t * (*pf_add) ( sout_stream_t *, sout_format_t * );
+ int (*pf_del) ( sout_stream_t *, sout_stream_id_t * );
+
+ /* manage a packet */
+ int (*pf_send)( sout_stream_t *, sout_stream_id_t *, sout_buffer_t* );
+
+ /* private */
+ sout_stream_sys_t *p_sys;
+};
+
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;
+ char * psz_chain;
/* 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_stream_t *p_stream;
/* sout private */
sout_instance_sys_t *p_sys;
};
+/* 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)--; \
+ } \
+ }
+
+static inline sout_cfg_t *sout_cfg_find( sout_cfg_t *p_cfg, char *psz_name )
+{
+ while( p_cfg && strcmp( p_cfg->psz_name, psz_name ) )
+ {
+ p_cfg = p_cfg->p_next;
+ }
+ return p_cfg;
+}
-
+static inline char *sout_cfg_find_value( sout_cfg_t *p_cfg, char *psz_name )
+{
+ while( p_cfg && strcmp( p_cfg->psz_name, psz_name ) )
+ {
+ p_cfg = p_cfg->p_next;
+ }
+
+ if( p_cfg && p_cfg->psz_value )
+ {
+ return( p_cfg->psz_value );
+ }
+
+ return NULL;
+}
/*****************************************************************************
* Prototypes
*****************************************************************************/
#define sout_InputNew( a, b ) __sout_InputNew( VLC_OBJECT(a), b )
-VLC_EXPORT( sout_packetizer_input_t *, __sout_InputNew, ( vlc_object_t *, sout_packet_format_t * ) );
+VLC_EXPORT( sout_packetizer_input_t *, __sout_InputNew, ( vlc_object_t *, sout_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( int, sout_AccessOutSeek, ( sout_access_out_t *, off_t ) );
VLC_EXPORT( int, sout_AccessOutWrite, ( sout_access_out_t *, sout_buffer_t * ) );
+VLC_EXPORT( sout_mux_t *, sout_MuxNew, ( sout_instance_t*, char *, sout_access_out_t * ) );
+VLC_EXPORT( sout_input_t *, sout_MuxAddStream, ( sout_mux_t *, sout_format_t * ) );
+VLC_EXPORT( void, sout_MuxDeleteStream, ( sout_mux_t *, sout_input_t * ) );
+VLC_EXPORT( void, sout_MuxDelete, ( sout_mux_t * ) );
+VLC_EXPORT( void, sout_MuxSendBuffer, ( sout_mux_t *, sout_input_t *, sout_buffer_t * ) );
+
+VLC_EXPORT( char *, sout_cfg_parser, ( char **, sout_cfg_t **, char * ) );
+VLC_EXPORT( sout_stream_t *, sout_stream_new, ( sout_instance_t *, char *psz_chain ) );
+VLC_EXPORT( void, sout_stream_delete, ( sout_stream_t *p_stream ) );
+
* Collection of useful common types and macros definitions
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: vlc_common.h,v 1.59 2003/03/17 18:02:11 sam Exp $
+ * $Id: vlc_common.h,v 1.60 2003/04/13 20:00:20 fenrir Exp $
*
* Authors: Samuel Hocevar <sam@via.ecp.fr>
* Vincent Seguin <seguin@via.ecp.fr>
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;
-
+typedef struct sout_stream_t sout_stream_t;
+typedef struct sout_cfg_t sout_cfg_t;
+typedef struct sout_format_t sout_format_t;
/* Decoders */
typedef struct decoder_fifo_t decoder_fifo_t;
mux/Modules.am \
mux/mpeg/Modules.am \
packetizer/Modules.am \
+ stream_out/Modules.am \
video_chroma/Modules.am \
video_filter/Modules.am \
video_filter/deinterlace/Modules.am \
* avi.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
- * $Id: avi.c,v 1.11 2003/03/31 03:46:11 fenrir Exp $
+ * $Id: avi.c,v 1.12 2003/04/13 20:00:21 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
(uint64_t)p_stream->i_totalsize /
(uint64_t)p_stream->i_duration;
}
- msg_Err( p_mux, "stream[%d] duration:%lld totalsize:%lld frames:%d fps:%f kb/s:%d",
- i_stream,
- (int64_t)p_stream->i_duration / (int64_t)1000000,
- p_stream->i_totalsize,
- p_stream->i_frames,
- p_stream->f_fps, p_stream->i_bitrate/1024 );
+ msg_Info( p_mux, "stream[%d] duration:%lld totalsize:%lld frames:%d fps:%f kb/s:%d",
+ i_stream,
+ (int64_t)p_stream->i_duration / (int64_t)1000000,
+ p_stream->i_totalsize,
+ p_stream->i_frames,
+ p_stream->f_fps, p_stream->i_bitrate/1024 );
}
p_hdr = avi_HeaderCreateRIFF( p_mux );
msg_Err( p_mux, "too many streams" );
return( -1 );
}
- if( p_input->input_format.p_format == NULL )
- {
- msg_Err( p_mux, "stream descriptor missing" );
- return( -1 );
- }
msg_Dbg( p_mux, "adding input" );
p_input->p_sys = malloc( sizeof( int ) );
*((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 )
+ switch( p_input->p_fmt->i_cat )
{
case AUDIO_ES:
+ p_stream->i_cat = AUDIO_ES;
+ 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';
+
+ p_stream->p_bih = NULL;
+
+ p_stream->p_wf = malloc( sizeof( WAVEFORMATEX ) + p_input->p_fmt->i_extra_data );
+#define p_wf p_stream->p_wf
+ p_wf->cbSize = p_input->p_fmt->i_extra_data;
+ if( p_wf->cbSize > 0 )
+ {
+ memcpy( &p_wf[1],
+ p_input->p_fmt->p_extra_data,
+ p_input->p_fmt->i_extra_data );
+ }
+ p_wf->nChannels = p_input->p_fmt->i_channels;
+ p_wf->nSamplesPerSec = p_input->p_fmt->i_sample_rate;
+ p_wf->nBlockAlign = p_input->p_fmt->i_block_align;
+ p_wf->nAvgBytesPerSec= p_input->p_fmt->i_bitrate / 8;
+ p_wf->wBitsPerSample = 0;
+
+ switch( p_input->p_fmt->i_fourcc )
{
- WAVEFORMATEX *p_wf =
- (WAVEFORMATEX*)p_input->input_format.p_format;
-
- p_stream->i_cat = AUDIO_ES;
- 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';
-
- p_stream->p_bih = NULL;
- p_stream->p_wf = malloc( sizeof( WAVEFORMATEX ) + p_wf->cbSize );
- memcpy( p_stream->p_wf,
- p_wf,
- sizeof( WAVEFORMATEX ) + p_wf->cbSize);
+ case VLC_FOURCC( 'a', '5', '2', ' ' ):
+ p_wf->wFormatTag = WAVE_FORMAT_A52;
+ break;
+ case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
+ p_wf->wFormatTag = WAVE_FORMAT_MPEGLAYER3;
+ break;
+ case VLC_FOURCC( 'w', 'm', 'a', '1' ):
+ p_wf->wFormatTag = WAVE_FORMAT_WMA1;
+ break;
+ case VLC_FOURCC( 'w', 'm', 'a', '2' ):
+ p_wf->wFormatTag = WAVE_FORMAT_WMA2;
+ break;
+ case VLC_FOURCC( 'w', 'm', 'a', '3' ):
+ p_wf->wFormatTag = WAVE_FORMAT_WMA3;
+ break;
+ default:
+ return VLC_EGENERIC;
}
+#undef p_wf
break;
case VIDEO_ES:
+ p_stream->i_cat = VIDEO_ES;
+ 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_sys->i_stream_video < 0 )
{
- BITMAPINFOHEADER *p_bih =
- (BITMAPINFOHEADER*)p_input->input_format.p_format;;
-
- p_stream->i_cat = VIDEO_ES;
- 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_sys->i_stream_video < 0 )
- {
- p_sys->i_stream_video = p_sys->i_streams;
- }
- p_stream->p_wf = NULL;
- p_stream->p_bih = malloc( p_bih->biSize );
- memcpy( p_stream->p_bih,
- p_bih,
- p_bih->biSize );
+ p_sys->i_stream_video = p_sys->i_streams;
}
+ p_stream->p_wf = NULL;
+ p_stream->p_bih = malloc( sizeof( BITMAPINFOHEADER ) + p_input->p_fmt->i_extra_data );
+#define p_bih p_stream->p_bih
+ p_bih->biSize = sizeof( BITMAPINFOHEADER ) + p_input->p_fmt->i_extra_data;
+ if( p_input->p_fmt->i_extra_data > 0 )
+ {
+ memcpy( &p_bih[1],
+ p_input->p_fmt->p_extra_data,
+ p_input->p_fmt->i_extra_data );
+ }
+ p_bih->biWidth = p_input->p_fmt->i_width;
+ p_bih->biHeight= p_input->p_fmt->i_height;
+ p_bih->biPlanes= 1;
+ p_bih->biBitCount = 24;
+ p_bih->biSizeImage = 0;
+ p_bih->biXPelsPerMeter = 0;
+ p_bih->biYPelsPerMeter = 0;
+ p_bih->biClrUsed = 0;
+ p_bih->biClrImportant = 0;
+ switch( p_input->p_fmt->i_fourcc )
+ {
+ case VLC_FOURCC( 'm', 'p', '4', 'v' ):
+ p_bih->biCompression = VLC_FOURCC( 'X', 'V', 'I', 'D' );
+ break;
+ default:
+ p_bih->biCompression = p_input->p_fmt->i_fourcc;
+ break;
+ }
+#undef p_bih
break;
default:
- return( -1 );
+ return( VLC_EGENERIC );
}
p_stream->i_totalsize = 0;
p_stream->i_frames = 0;
p_sys->i_streams++;
- return( 0 );
+ return( VLC_SUCCESS );
}
static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
p_data->i_size += 1;
}
- sout_AccessOutWrite( p_mux->p_access, p_data );
p_sys->i_movi_size += p_data->i_size;
+ sout_AccessOutWrite( p_mux->p_access, p_data );
i_count--;
}
if( i_samplesize > 1 )
{
i_scale = i_samplesize;
- i_rate = i_scale * p_stream->i_bitrate / 8;
+ i_rate = /*i_scale **/ p_stream->i_bitrate / 8;
}
else
{
* ps.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
- * $Id: ps.c,v 1.11 2003/03/11 19:02:30 fenrir Exp $
+ * $Id: ps.c,v 1.12 2003/04/13 20:00:21 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
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 )
+ switch( p_input->p_fmt->i_cat )
{
case VIDEO_ES:
- switch( p_input->input_format.i_fourcc )
+ switch( p_input->p_fmt->i_fourcc )
{
case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
p_stream->i_stream_id = p_sys->i_stream_id_mpgv;
}
break;
case AUDIO_ES:
- switch( p_input->input_format.i_fourcc )
+ switch( p_input->p_fmt->i_fourcc )
{
case VLC_FOURCC( 'a', '5', '2', ' ' ):
case VLC_FOURCC( 'a', '5', '2', 'b' ):
* ts.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
- * $Id: ts.c,v 1.15 2003/03/11 19:02:30 fenrir Exp $
+ * $Id: ts.c,v 1.16 2003/04/13 20:00:21 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
{
sout_mux_sys_t *p_sys = p_mux->p_sys;
ts_stream_t *p_stream;
- BITMAPINFOHEADER *p_bih;
- WAVEFORMATEX *p_wf;
msg_Dbg( p_mux, "adding input" );
p_input->p_sys = (void*)p_stream = malloc( sizeof( ts_stream_t ) );
}
p_stream->i_continuity_counter = 0;
- switch( p_input->input_format.i_cat )
+ switch( p_input->p_fmt->i_cat )
{
case VIDEO_ES:
- switch( p_input->input_format.i_fourcc )
+ switch( p_input->p_fmt->i_fourcc )
{
case VLC_FOURCC( 'm', 'p','g', 'v' ):
p_stream->i_stream_type = 0x02;
return( -1 );
}
p_sys->i_video_bound++;
- p_bih = (BITMAPINFOHEADER*)p_input->input_format.p_format;
- if( p_bih )
- {
- p_stream->i_bih_codec = p_input->input_format.i_fourcc;
- p_stream->i_bih_width = p_bih->biWidth;
- p_stream->i_bih_height = p_bih->biHeight;
- }
- else
- {
- p_stream->i_bih_codec = 0x0;
- p_stream->i_bih_width = 0;
- p_stream->i_bih_height = 0;
- }
- if( p_bih && p_bih->biSize > sizeof( BITMAPINFOHEADER ) )
+ p_stream->i_bih_codec = p_input->p_fmt->i_fourcc;
+ p_stream->i_bih_width = p_input->p_fmt->i_width;
+ p_stream->i_bih_height = p_input->p_fmt->i_height;
+
+ p_stream->i_decoder_specific_info_len = p_input->p_fmt->i_extra_data;
+ if( p_stream->i_decoder_specific_info_len > 0 )
{
- p_stream->i_decoder_specific_info_len =
- p_bih->biSize - sizeof( BITMAPINFOHEADER );
p_stream->p_decoder_specific_info =
malloc( p_stream->i_decoder_specific_info_len );
memcpy( p_stream->p_decoder_specific_info,
- &p_bih[1],
- p_stream->i_decoder_specific_info_len );
+ p_input->p_fmt->p_extra_data,
+ p_input->p_fmt->i_extra_data );
}
else
{
p_stream->p_decoder_specific_info = NULL;
- p_stream->i_decoder_specific_info_len = 0;
}
break;
+
case AUDIO_ES:
- switch( p_input->input_format.i_fourcc )
+ switch( p_input->p_fmt->i_fourcc )
{
case VLC_FOURCC( 'a', '5','2', ' ' ):
case VLC_FOURCC( 'a', '5','2', 'b' ):
return( -1 );
}
p_sys->i_audio_bound++;
- p_wf = (WAVEFORMATEX*)p_input->input_format.p_format;
- if( p_wf && p_wf->cbSize > 0 )
+
+ p_stream->i_decoder_specific_info_len = p_input->p_fmt->i_extra_data;
+ if( p_stream->i_decoder_specific_info_len > 0 )
{
- p_stream->i_decoder_specific_info_len = p_wf->cbSize;
p_stream->p_decoder_specific_info =
malloc( p_stream->i_decoder_specific_info_len );
memcpy( p_stream->p_decoder_specific_info,
- &p_wf[1],
- p_stream->i_decoder_specific_info_len );
+ p_input->p_fmt->p_extra_data,
+ p_input->p_fmt->i_extra_data );
}
else
{
p_stream->p_decoder_specific_info = NULL;
- p_stream->i_decoder_specific_info_len = 0;
}
break;
default:
* ogg.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
- * $Id: ogg.c,v 1.4 2003/03/31 03:46:11 fenrir Exp $
+ * $Id: ogg.c,v 1.5 2003/04/13 20:00:21 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
sout_mux_sys_t *p_sys = p_mux->p_sys;
ogg_stream_t *p_stream;
- BITMAPINFOHEADER *p_bih;
- WAVEFORMATEX *p_wf;
-
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;
+ p_stream->i_cat = p_input->p_fmt->i_cat;
+ p_stream->i_fourcc = p_input->p_fmt->i_fourcc;
p_stream->i_packet_no = 0;
p_stream->header.i_packet_type = PACKET_TYPE_HEADER;
- switch( p_input->input_format.i_cat )
+ switch( p_input->p_fmt->i_cat )
{
case VIDEO_ES:
- p_bih = (BITMAPINFOHEADER*)p_input->input_format.p_format;
- switch( p_input->input_format.i_fourcc )
+ switch( p_input->p_fmt->i_fourcc )
{
case VLC_FOURCC( 'm', 'p','4', 'v' ):
case VLC_FOURCC( 'D', 'I','V', '3' ):
memcpy( p_stream->header.stream_type,
"video ",
8 );
- if( p_input->input_format.i_fourcc == VLC_FOURCC( 'm', 'p','4', 'v' ) )
+ if( p_input->p_fmt->i_fourcc == VLC_FOURCC( 'm', 'p','4', 'v' ) )
{
memcpy( p_stream->header.sub_type, "XVID", 4 );
}
- else if( p_input->input_format.i_fourcc == VLC_FOURCC( 'D', 'I','V', '3' ) )
+ else if( p_input->p_fmt->i_fourcc == VLC_FOURCC( 'D', 'I','V', '3' ) )
{
memcpy( p_stream->header.sub_type, "DIV3", 4 );
}
SetDWLE( &p_stream->header.i_default_len, 0 ); /* ??? */
SetDWLE( &p_stream->header.i_buffer_size, 1024*1024 );
SetWLE( &p_stream->header.i_bits_per_sample, 0 );
- if( p_bih )
- {
- SetDWLE( &p_stream->header.header.video.i_width, p_bih->biWidth );
- SetDWLE( &p_stream->header.header.video.i_height, p_bih->biHeight );
- }
- else
- {
- SetDWLE( &p_stream->header.header.video.i_width, 0 );
- SetDWLE( &p_stream->header.header.video.i_height, 0 );
- }
+ SetDWLE( &p_stream->header.header.video.i_width, p_input->p_fmt->i_width );
+ SetDWLE( &p_stream->header.header.video.i_height, p_input->p_fmt->i_height );
break;
default:
FREE( p_input->p_sys );
}
break;
case AUDIO_ES:
- p_wf = (WAVEFORMATEX*)p_input->input_format.p_format;
- switch( p_input->input_format.i_fourcc )
+ switch( p_input->p_fmt->i_fourcc )
{
case VLC_FOURCC( 'm', 'p','g', 'a' ):
case VLC_FOURCC( 'a', '5','2', ' ' ):
memcpy( p_stream->header.stream_type,
"audio ",
8 );
- if( p_input->input_format.i_fourcc == VLC_FOURCC( 'm', 'p','g', 'a' ) )
+ if( p_input->p_fmt->i_fourcc == VLC_FOURCC( 'm', 'p','g', 'a' ) )
{
memcpy( p_stream->header.sub_type, "55 ", 4 );
}
- else if( p_input->input_format.i_fourcc == VLC_FOURCC( 'a', '5','2', ' ' ) )
+ else if( p_input->p_fmt->i_fourcc == VLC_FOURCC( 'a', '5','2', ' ' ) )
{
memcpy( p_stream->header.sub_type, "2000", 4 );
}
SetQWLE( &p_stream->header.i_time_unit, 1000000 ); /* is it used ? */
SetDWLE( &p_stream->header.i_default_len, 0 ); /* ??? */
SetDWLE( &p_stream->header.i_buffer_size, 30*1024 );
- if( p_wf )
- {
- SetQWLE( &p_stream->header.i_samples_per_unit, p_wf->nSamplesPerSec );
- SetWLE( &p_stream->header.i_bits_per_sample, p_wf->wBitsPerSample );
- SetDWLE( &p_stream->header.header.audio.i_channels, p_wf->nChannels );
- SetDWLE( &p_stream->header.header.audio.i_block_align, p_wf->nBlockAlign );
- SetDWLE( &p_stream->header.header.audio.i_avgbytespersec, p_wf->nAvgBytesPerSec );
- }
- else
- {
- /* perhaps it's better to fail */
- SetQWLE( &p_stream->header.i_samples_per_unit, 44100 );
- SetWLE( &p_stream->header.i_bits_per_sample, 0 );
- SetDWLE( &p_stream->header.header.audio.i_channels, 2 );
- SetDWLE( &p_stream->header.header.audio.i_block_align, 0 );
- SetDWLE( &p_stream->header.header.audio.i_avgbytespersec, 0 );
- }
+ SetQWLE( &p_stream->header.i_samples_per_unit, p_input->p_fmt->i_sample_rate );
+ SetWLE( &p_stream->header.i_bits_per_sample, 0 );
+ SetDWLE( &p_stream->header.header.audio.i_channels, p_input->p_fmt->i_channels );
+ SetDWLE( &p_stream->header.header.audio.i_block_align, p_input->p_fmt->i_block_align );
+ SetDWLE( &p_stream->header.header.audio.i_avgbytespersec, 0 );
break;
case VLC_FOURCC( 'v', 'o', 'r', 'b' ):
default:
* a52.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
- * $Id: a52.c,v 1.3 2003/03/31 03:46:11 fenrir Exp $
+ * $Id: a52.c,v 1.4 2003/04/13 20:00:21 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
/* Output properties */
sout_packetizer_input_t *p_sout_input;
- sout_packet_format_t output_format;
+ sout_format_t output_format;
uint64_t i_samplescount;
p_pack->output_format.i_cat = AUDIO_ES;
p_pack->output_format.i_fourcc = VLC_FOURCC( 'a', '5', '2', ' ' );
- p_pack->output_format.p_format = NULL;
-
p_pack->p_sout_input = NULL;
p_pack->i_samplescount = 0;
if( !p_pack->p_sout_input )
{
- /* add a input for the stream ouput */
- WAVEFORMATEX *p_wf;
-
- p_wf = malloc( sizeof( WAVEFORMATEX ) );
- p_pack->output_format.p_format = (void*)p_wf;
-
- p_wf->wFormatTag = WAVE_FORMAT_A52;
- p_wf->nChannels = i_channels;
- p_wf->nSamplesPerSec = i_samplerate;
- p_wf->nAvgBytesPerSec = 0;
- p_wf->nBlockAlign = 1;
- p_wf->wBitsPerSample = 0;
- p_wf->cbSize = 0;
+ p_pack->output_format.i_sample_rate = i_samplerate;
+ p_pack->output_format.i_channels = i_channels;
+ p_pack->output_format.i_block_align = 0;
+ p_pack->output_format.i_bitrate = 0;
+ p_pack->output_format.i_extra_data = 0;
+ p_pack->output_format.p_extra_data = NULL;
p_pack->p_sout_input =
sout_InputNew( p_pack->p_fifo,
* copy.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
- * $Id: copy.c,v 1.6 2003/03/31 03:46:11 fenrir Exp $
+ * $Id: copy.c,v 1.7 2003/04/13 20:00:21 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
/* Output properties */
sout_packetizer_input_t *p_sout_input;
- sout_packet_format_t output_format;
+ sout_format_t output_format;
// mtime_t i_last_pts;
p_pack->output_format.i_fourcc = VLC_FOURCC( 'd', 'v', 's', 'l' );
p_pack->output_format.i_cat = VIDEO_ES;
break;
+ case VLC_FOURCC( 'S', 'V', 'Q', '1' ):
+ p_pack->output_format.i_fourcc = VLC_FOURCC( 'S', 'V', 'Q', '1' );
+ p_pack->output_format.i_cat = VIDEO_ES;
+ break;
- default:
- p_pack->output_format.i_fourcc = p_pack->p_fifo->i_fourcc;
- p_pack->output_format.i_cat = UNKNOWN_ES;
+ case VLC_FOURCC( 'w', 'm', 'a', '1' ):
+ p_pack->output_format.i_fourcc = VLC_FOURCC( 'w', 'm', 'a', '1' );
+ p_pack->output_format.i_cat = AUDIO_ES;
+ break;
+ case VLC_FOURCC( 'w', 'm', 'a', '2' ):
+ p_pack->output_format.i_fourcc = VLC_FOURCC( 'w', 'm', 'a', '2' );
+ p_pack->output_format.i_cat = AUDIO_ES;
break;
+
+ default:
+ msg_Err( p_pack->p_fifo, "unknown es type !!" );
+ return VLC_EGENERIC;
+ //p_pack->output_format.i_fourcc = p_pack->p_fifo->i_fourcc;
+ //p_pack->output_format.i_cat = UNKNOWN_ES;
+ //break;
}
switch( p_pack->output_format.i_cat )
WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex;
if( p_wf )
{
- p_pack->output_format.p_format = malloc( sizeof( WAVEFORMATEX ) + p_wf->cbSize );
- memcpy( p_pack->output_format.p_format, p_wf, sizeof( WAVEFORMATEX ) + p_wf->cbSize );
+ p_pack->output_format.i_sample_rate = p_wf->nSamplesPerSec;
+ p_pack->output_format.i_channels = p_wf->nChannels;
+ p_pack->output_format.i_block_align = p_wf->nBlockAlign;
+ p_pack->output_format.i_bitrate = p_wf->nAvgBytesPerSec * 8;
+ p_pack->output_format.i_extra_data = p_wf->cbSize;
+ if( p_wf->cbSize > 0 )
+ {
+ p_pack->output_format.p_extra_data =
+ malloc( p_pack->output_format.i_extra_data );
+ memcpy( p_pack->output_format.p_extra_data,
+ &p_wf[1],
+ p_pack->output_format.i_extra_data );
+ }
+ else
+ {
+ p_pack->output_format.p_extra_data = NULL;
+ }
}
else
{
- p_pack->output_format.p_format = NULL;
+ p_pack->output_format.i_sample_rate = 0;
+ p_pack->output_format.i_channels = 0;
+ p_pack->output_format.i_block_align = 0;
+ p_pack->output_format.i_bitrate = 0;
+ p_pack->output_format.i_extra_data = 0;
+ p_pack->output_format.p_extra_data = NULL;
}
}
break;
case VIDEO_ES:
{
BITMAPINFOHEADER *p_bih = (BITMAPINFOHEADER*)p_pack->p_fifo->p_bitmapinfoheader;
+
+ p_pack->output_format.i_bitrate = 0;
if( p_bih )
{
- p_pack->output_format.p_format = malloc( p_bih->biSize );
- memcpy( p_pack->output_format.p_format, p_bih, p_bih->biSize );
- if( p_pack->output_format.i_fourcc == VLC_FOURCC( 'm', 'p', '4', 'v' ) )
- {
- p_bih->biCompression = VLC_FOURCC( 'd', 'i', 'v', 'x' );
- }
- else
+ p_pack->output_format.i_width = p_bih->biWidth;
+ p_pack->output_format.i_height = p_bih->biHeight;
+ p_pack->output_format.i_extra_data = p_bih->biSize - sizeof( BITMAPINFOHEADER );
+ if( p_pack->output_format.i_extra_data > 0 )
{
- p_bih->biCompression = p_pack->output_format.i_fourcc;
+ p_pack->output_format.p_extra_data =
+ malloc( p_pack->output_format.i_extra_data );
+ memcpy( p_pack->output_format.p_extra_data,
+ &p_bih[1],
+ p_pack->output_format.i_extra_data );
}
-
}
else
{
- p_pack->output_format.p_format = NULL;
+ p_pack->output_format.i_width = 0;
+ p_pack->output_format.i_height = 0;
+ p_pack->output_format.i_extra_data = 0;
+ p_pack->output_format.p_extra_data = NULL;
}
}
break;
+
default:
- p_pack->output_format.p_format = NULL;
- break;
+ return VLC_EGENERIC;
}
p_pack->p_sout_input =
if( !p_pack->p_sout_input )
{
msg_Err( p_pack->p_fifo, "cannot add a new stream" );
- return( -1 );
+ return VLC_EGENERIC;
}
// p_pack->i_last_pts = 0;
- return( 0 );
+ return( VLC_SUCCESS );
}
/*****************************************************************************
if( i_pts <= 0 ) //&& p_pack->i_last_pts <= 0 )
{
- msg_Err( p_pack->p_fifo, "need pts != 0" );
+ msg_Dbg( p_pack->p_fifo, "need pts != 0" );
input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
return;
}
* mpeg4audio.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
- * $Id: mpeg4audio.c,v 1.4 2003/03/31 03:46:11 fenrir Exp $
+ * $Id: mpeg4audio.c,v 1.5 2003/04/13 20:00:21 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
/* Output properties */
sout_packetizer_input_t *p_sout_input;
- sout_packet_format_t output_format;
+ sout_format_t output_format;
// mtime_t i_pts_start;
mtime_t i_last_pts;
if( p_wf && p_wf->cbSize > 0)
{
uint8_t *p_config = (uint8_t*)&p_wf[1];
- int i_wf = sizeof( WAVEFORMATEX ) + p_wf->cbSize;
- int i_index;
+ int i_index;
-
- p_pack->p_wf = malloc( i_wf );
- memcpy( p_pack->p_wf,
- p_wf,
- i_wf );
- p_pack->output_format.i_cat = AUDIO_ES;
- p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', '4', 'a' );
- p_pack->output_format.p_format = p_pack->p_wf;
p_pack->b_adts = 0;
i_index = ( ( p_config[0] << 1 ) | ( p_config[1] >> 7 ) )&0x0f;
"aac %dHz %d samples/frame",
p_pack->i_sample_rate,
p_pack->i_frame_size );
+
+ p_pack->output_format.i_cat = AUDIO_ES;
+ p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', '4', 'a' );
+ p_pack->output_format.i_sample_rate = p_pack->i_sample_rate;
+ p_pack->output_format.i_channels = p_wf->nChannels;
+ p_pack->output_format.i_block_align = 0;
+ p_pack->output_format.i_bitrate = 0;
+
+ p_pack->output_format.i_extra_data = p_wf->cbSize;
+ p_pack->output_format.p_extra_data = malloc( p_wf->cbSize );
+ memcpy( p_pack->output_format.p_extra_data,
+ &p_wf[1],
+ p_wf->cbSize );
}
else
{
* mpeg4video.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
- * $Id: mpeg4video.c,v 1.9 2003/03/31 03:46:11 fenrir Exp $
+ * $Id: mpeg4video.c,v 1.10 2003/04/13 20:00:21 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
/* Output properties */
sout_packetizer_input_t *p_sout_input;
- sout_packet_format_t output_format;
+ sout_format_t output_format;
mtime_t i_last_pts;
/* create stream input output */
p_pack->output_format.i_cat = VIDEO_ES;
p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', '4', 'v' );
- p_pack->output_format.p_format = malloc( p_bih->biSize );
- memcpy( p_pack->output_format.p_format, p_bih, p_bih->biSize );
+ p_pack->output_format.i_width = p_bih->biWidth;
+ p_pack->output_format.i_height = p_bih->biHeight;
+ p_pack->output_format.i_bitrate= 0;
+
+ p_pack->output_format.i_extra_data = p_pack->i_vol;
+ p_pack->output_format.p_extra_data = malloc( p_pack->i_vol );
+ memcpy( p_pack->output_format.p_extra_data,
+ p_pack->p_vol,
+ p_pack->i_vol );
msg_Warn( p_pack->p_fifo, "opening with vol size:%d", p_pack->i_vol );
p_pack->p_sout_input =
p_pack->p_vol = 0;
p_pack->output_format.i_cat = UNKNOWN_ES;
p_pack->output_format.i_fourcc = VLC_FOURCC( 'n', 'u', 'l', 'l' );
- p_pack->output_format.p_format = NULL;
+ p_pack->output_format.i_width = 0;
+ p_pack->output_format.i_height = 0;
+ p_pack->output_format.i_bitrate= 0;
+ p_pack->output_format.i_extra_data = 0;
+ p_pack->output_format.p_extra_data = NULL;
p_pack->p_sout_input =
sout_InputNew( p_pack->p_fifo,
}
i_pts = p_pes->i_pts;
+#if 0
if( i_pts <= 0 && p_pack->i_last_pts <= 0 )
{
- msg_Err( p_pack->p_fifo, "need a starting pts" );
+ msg_Dbg( p_pack->p_fifo, "need a starting pts" );
input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
return;
}
+#endif
i_size = p_pes->i_pes_size;
if( i_size > 0 )
if( p_vol_end != NULL && p_vol_begin < p_vol_end )
{
- BITMAPINFOHEADER *p_bih;
-
p_pack->i_vol = p_vol_end - p_vol_begin;
msg_Dbg( p_pack->p_fifo, "Reopening output" );
p_pack->output_format.i_cat = VIDEO_ES;
p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', '4', 'v' );
- p_pack->output_format.p_format =
- (void*)p_bih = malloc( sizeof( BITMAPINFOHEADER ) + p_pack->i_vol);
-
- p_bih->biSize = sizeof( BITMAPINFOHEADER ) + p_pack->i_vol;
- p_bih->biWidth = 0;
- p_bih->biHeight = 0;
- p_bih->biPlanes = 1;
- p_bih->biBitCount = 24;
- p_bih->biCompression = VLC_FOURCC( 'd', 'i', 'v', 'x' );
- p_bih->biSizeImage = 0;
- p_bih->biXPelsPerMeter = 0;
- p_bih->biYPelsPerMeter = 0;
- p_bih->biClrUsed = 0;
- p_bih->biClrImportant = 0;
- memcpy( &p_bih[1], p_pack->p_vol, p_pack->i_vol );
+
+ p_pack->output_format.i_width = 0;
+ p_pack->output_format.i_height = 0;
+ p_pack->output_format.i_bitrate= 0;
+
+ p_pack->output_format.i_extra_data = p_pack->i_vol;
+ p_pack->output_format.p_extra_data = malloc( p_pack->i_vol );
+ memcpy( p_pack->output_format.p_extra_data,
+ p_pack->p_vol,
+ p_pack->i_vol );
p_pack->p_sout_input =
sout_InputNew( p_pack->p_fifo,
}
}
- sout_InputSendBuffer( p_pack->p_sout_input,
+ if( i_pts > 0 )
+ {
+ sout_InputSendBuffer( p_pack->p_sout_input,
+ p_sout_buffer );
+ }
+ else
+ {
+ sout_BufferDelete( p_pack->p_sout_input->p_sout,
p_sout_buffer );
+ }
}
input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
* mpegaudio.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
- * $Id: mpegaudio.c,v 1.5 2003/03/31 03:46:11 fenrir Exp $
+ * $Id: mpegaudio.c,v 1.6 2003/04/13 20:00:21 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
/* Output properties */
sout_packetizer_input_t *p_sout_input;
- sout_packet_format_t output_format;
+ sout_format_t output_format;
uint64_t i_samplescount;
uint32_t i_samplespersecond;
p_pack->output_format.i_cat = AUDIO_ES;
p_pack->output_format.i_fourcc = p_pack->p_fifo->i_fourcc;
+ p_pack->output_format.i_sample_rate = 0;
+ p_pack->output_format.i_channels = 0;
+ p_pack->output_format.i_block_align = 0;
+ p_pack->output_format.i_bitrate = 0;
+ p_pack->output_format.i_extra_data = 0;
+ p_pack->output_format.p_extra_data = NULL;
- p_pack->output_format.p_format = NULL;
p_pack->p_sout_input = NULL;
if( !p_pack->p_sout_input )
{
/* add a input for the stream ouput */
- WAVEFORMATEX *p_wf;
-
- p_wf = malloc( sizeof( WAVEFORMATEX ) );
- p_pack->output_format.p_format = (void*)p_wf;
-
- p_wf->wFormatTag = WAVE_FORMAT_MPEG;
- p_wf->nChannels = i_channels;
- p_wf->nSamplesPerSec = i_samplerate;
- p_wf->nAvgBytesPerSec = 0;
- p_wf->nBlockAlign = 1;
- p_wf->wBitsPerSample = 0;
- p_wf->cbSize = 0; // FIXME there are more field for mpegaudio
+ p_pack->output_format.i_sample_rate = i_samplerate;
+ p_pack->output_format.i_channels = i_channels;
+ p_pack->output_format.i_block_align = 1;
+ p_pack->output_format.i_bitrate = 0;
p_pack->p_sout_input =
sout_InputNew( p_pack->p_fifo,
* mpegvideo.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
- * $Id: mpegvideo.c,v 1.11 2003/03/31 03:46:11 fenrir Exp $
+ * $Id: mpegvideo.c,v 1.12 2003/04/13 20:00:21 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
/* Output properties */
sout_packetizer_input_t *p_sout_input;
- sout_packet_format_t output_format;
+ sout_format_t output_format;
mtime_t i_last_dts;
mtime_t i_last_ref_pts;
p_pack->output_format.i_cat = VIDEO_ES;
p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'v');
+ p_pack->output_format.i_width = 0;
+ p_pack->output_format.i_height = 0;
+ p_pack->output_format.i_bitrate= 0;
+ p_pack->output_format.i_extra_data = 0;
+ p_pack->output_format.p_extra_data = NULL;
p_pack->p_sout_input = NULL;
byte_t p_temp[512];/* 150 bytes is the maximal size
of a sequence_header + sequence_extension */
int i_frame_rate_code;
- BITMAPINFOHEADER *p_bih;
- p_bih = malloc( sizeof( BITMAPINFOHEADER ) );
- p_pack->output_format.p_format = (void*)p_bih;
/* skip data until we find a sequence_header_code */
/* TODO: store skipped somewhere so can send it to the mux
i_pos = 0;
GetChunk( &p_pack->bit_stream, p_temp, 4 ); i_pos += 4;
- p_bih->biSize = sizeof( BITMAPINFOHEADER );
/* horizontal_size_value */
- p_bih->biWidth = ShowBits( &p_pack->bit_stream, 12 );
+ p_pack->output_format.i_width = ShowBits( &p_pack->bit_stream, 12 );
/* vertical_size_value */
- p_bih->biHeight = ShowBits( &p_pack->bit_stream, 24 ) & 0xFFF;
+ p_pack->output_format.i_height= ShowBits( &p_pack->bit_stream, 24 ) & 0xFFF;
/* frame_rate_code */
i_frame_rate_code = ShowBits( &p_pack->bit_stream, 32 ) & 0xF;
- p_bih->biPlanes = 1;
- p_bih->biBitCount = 0;
- p_bih->biCompression = VLC_FOURCC( 'm', 'p', 'g', '2' );
- p_bih->biSizeImage = 0;
- p_bih->biXPelsPerMeter = 0;
- p_bih->biYPelsPerMeter = 0;
- p_bih->biClrUsed = 0;
- p_bih->biClrImportant = 0;
/* copy headers */
GetChunk( &p_pack->bit_stream, p_temp + i_pos, 7 ); i_pos += 7;
msg_Warn( p_pack->p_fifo,
"creating input (image size %dx%d, frame rate %.2f)",
- p_bih->biWidth, p_bih->biHeight, p_pack->d_frame_rate );
+ p_pack->output_format.i_width,
+ p_pack->output_format.i_height,
+ p_pack->d_frame_rate );
/* now we have informations to create the input */
p_pack->p_sout_input = sout_InputNew( p_pack->p_fifo,
}
p_pack->i_last_ref_pts =
- p_pack->i_last_dts + 40000; /* FIXME */
+ p_pack->i_last_dts +
+ (mtime_t)( 1000000 / p_pack->d_frame_rate); /* FIXME */
CopyUntilNextStartCode( p_pack, p_sout_buffer, &i_pos );
}
else if( i_code == 0x100 ) /* Picture */
return;
}
+#if 1
if( i_dts > 0 )
{
- p_pack->i_last_dts = i_dts;
- }
- if( i_pts > 0 )
- {
- p_pack->i_last_ref_pts =
- i_pts - i_temporal_ref *
- (mtime_t)( 1000000 / p_pack->d_frame_rate );
+ //if( i_dts - p_pack->i_last_dts > 200000 ||
+ // i_dts - p_pack->i_last_dts < 200000 )
+ {
+ p_pack->i_last_dts = i_dts;
+ if( i_pts > 0 )
+ {
+ p_pack->i_last_ref_pts = i_pts -
+ i_temporal_ref * (mtime_t)( 1000000 / p_pack->d_frame_rate );
+ }
+ }
}
+#endif
p_sout_buffer->i_dts = p_pack->i_last_dts;
p_sout_buffer->i_pts = p_pack->i_last_ref_pts +
--- /dev/null
+SOURCES_stream_out_dummy = modules/stream_out/dummy.c
+SOURCES_stream_out_standard = modules/stream_out/standard.c
+SOURCES_stream_out_transcode = modules/stream_out/transcode.c
+SOURCES_stream_out_duplicate = modules/stream_out/duplicate.c
+SOURCES_stream_out_es = modules/stream_out/es.c
+SOURCES_stream_out_display = modules/stream_out/display.c
--- /dev/null
+/*****************************************************************************
+ * display.c
+ *****************************************************************************
+ * Copyright (C) 2001, 2002 VideoLAN
+ * $Id: display.c,v 1.1 2003/04/13 20:00:21 fenrir Exp $
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+#include <vlc/sout.h>
+
+#include "codecs.h"
+
+/*****************************************************************************
+ * Exported prototypes
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+
+static sout_stream_id_t *Add ( sout_stream_t *, sout_format_t * );
+static int Del ( sout_stream_t *, sout_stream_id_t * );
+static int Send( sout_stream_t *, sout_stream_id_t *, sout_buffer_t* );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("Display stream") );
+ set_capability( "sout stream", 50 );
+ add_shortcut( "display" );
+ set_callbacks( Open, Close );
+vlc_module_end();
+
+struct sout_stream_sys_t
+{
+ input_thread_t *p_input;
+
+ vlc_bool_t b_audio;
+ vlc_bool_t b_video;
+
+ mtime_t i_delay;
+};
+
+/*****************************************************************************
+ * Open:
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ sout_stream_t *p_stream = (sout_stream_t*)p_this;
+ sout_stream_sys_t *p_sys;
+ char *val;
+ p_sys = malloc( sizeof( sout_stream_sys_t ) );
+ p_sys->p_input = vlc_object_find( p_stream, VLC_OBJECT_INPUT, FIND_ANYWHERE );
+ if( !p_sys->p_input )
+ {
+ msg_Err( p_stream, "cannot find p_input" );
+ free( p_sys );
+ return VLC_EGENERIC;
+ }
+
+ p_sys->b_audio = VLC_TRUE;
+ p_sys->b_video = VLC_TRUE;
+ p_sys->i_delay = 100*1000;
+ if( sout_cfg_find( p_stream->p_cfg, "noaudio" ) )
+ {
+ p_sys->b_audio = VLC_FALSE;
+ }
+ if( sout_cfg_find( p_stream->p_cfg, "novideo" ) )
+ {
+ p_sys->b_video = VLC_FALSE;
+ }
+ if( ( val = sout_cfg_find_value( p_stream->p_cfg, "delay" ) ) )
+ {
+ p_sys->i_delay = (mtime_t)atoi( val ) * (mtime_t)1000;
+ }
+
+ p_stream->pf_add = Add;
+ p_stream->pf_del = Del;
+ p_stream->pf_send = Send;
+
+ p_stream->p_sys = p_sys;
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Close:
+ *****************************************************************************/
+
+static void Close( vlc_object_t * p_this )
+{
+ sout_stream_t *p_stream = (sout_stream_t*)p_this;
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+
+ vlc_object_release( p_sys->p_input );
+
+ free( p_sys );
+}
+
+struct sout_stream_id_t
+{
+ es_descriptor_t *p_es;
+};
+
+
+static sout_stream_id_t * Add ( sout_stream_t *p_stream, sout_format_t *p_fmt )
+{
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+ sout_stream_id_t *id;
+
+ if( ( p_fmt->i_cat == AUDIO_ES && !p_sys->b_audio )||
+ ( p_fmt->i_cat == VIDEO_ES && !p_sys->b_video ) )
+ {
+ return NULL;
+ }
+
+ id = malloc( sizeof( sout_stream_id_t ) );
+
+ vlc_mutex_lock( &p_sys->p_input->stream.stream_lock );
+ id->p_es = input_AddES( p_sys->p_input,
+ NULL, /* no program */
+ 12, /* es_id */
+ 0 ); /* no extra data */
+
+ if( !id->p_es )
+ {
+ vlc_mutex_unlock( &p_sys->p_input->stream.stream_lock );
+
+ msg_Err( p_stream, "cannot create es" );
+ free( id );
+ return NULL;
+ }
+ id->p_es->i_stream_id = 1;
+ id->p_es->i_cat = UNKNOWN_ES; //p_fmt->i_cat;
+ id->p_es->i_fourcc = p_fmt->i_fourcc;
+ id->p_es->b_force_decoder = VLC_TRUE;
+ switch( p_fmt->i_cat )
+ {
+ case AUDIO_ES:
+ id->p_es->p_bitmapinfoheader = NULL;
+ id->p_es->p_waveformatex =
+ malloc( sizeof( WAVEFORMATEX ) + p_fmt->i_extra_data );
+#define p_wf ((WAVEFORMATEX*)id->p_es->p_waveformatex)
+ p_wf->wFormatTag = WAVE_FORMAT_UNKNOWN;
+ p_wf->nChannels = p_fmt->i_channels;
+ p_wf->nSamplesPerSec = p_fmt->i_sample_rate;
+ p_wf->nAvgBytesPerSec= p_fmt->i_bitrate / 8;
+ p_wf->nBlockAlign = p_fmt->i_block_align;
+ p_wf->wBitsPerSample = 0;
+ p_wf->cbSize = p_fmt->i_extra_data;
+ if( p_fmt->i_extra_data > 0 )
+ {
+ memcpy( &p_wf[1],
+ p_fmt->p_extra_data,
+ p_fmt->i_extra_data );
+ }
+#undef p_wf
+ break;
+ case VIDEO_ES:
+ id->p_es->p_waveformatex = NULL;
+ id->p_es->p_bitmapinfoheader = malloc( sizeof( BITMAPINFOHEADER ) + p_fmt->i_extra_data );
+#define p_bih ((BITMAPINFOHEADER*)id->p_es->p_bitmapinfoheader)
+ p_bih->biSize = sizeof( BITMAPINFOHEADER ) + p_fmt->i_extra_data;
+ p_bih->biWidth = p_fmt->i_width;
+ p_bih->biHeight = p_fmt->i_height;
+ p_bih->biPlanes = 0;
+ p_bih->biBitCount = 0;
+ p_bih->biCompression = 0;
+ p_bih->biSizeImage = 0;
+ p_bih->biXPelsPerMeter = 0;
+ p_bih->biYPelsPerMeter = 0;
+ p_bih->biClrUsed = 0;
+ p_bih->biClrImportant = 0;
+ if( p_fmt->i_extra_data > 0 )
+ {
+ memcpy( &p_bih[1],
+ p_fmt->p_extra_data,
+ p_fmt->i_extra_data );
+ }
+#undef p_bih
+ break;
+ default:
+ msg_Err( p_stream, "unknown es type" );
+ free( id );
+ return NULL;
+ }
+
+ if( input_SelectES( p_sys->p_input, id->p_es ) )
+ {
+ input_DelES( p_sys->p_input, id->p_es );
+ vlc_mutex_unlock( &p_sys->p_input->stream.stream_lock );
+
+ msg_Err( p_stream, "cannot select es" );
+ free( id );
+ return NULL;
+ }
+ vlc_mutex_unlock( &p_sys->p_input->stream.stream_lock );
+
+ return id;
+}
+
+static int Del ( sout_stream_t *p_stream, sout_stream_id_t *id )
+{
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+
+ input_DelES( p_sys->p_input, id->p_es );
+
+ free( id );
+
+ return VLC_SUCCESS;
+}
+
+static int Send ( sout_stream_t *p_stream, sout_stream_id_t *id, sout_buffer_t *p_buffer )
+{
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+
+ while( p_buffer )
+ {
+ sout_buffer_t *p_next;
+ pes_packet_t *p_pes;
+ data_packet_t *p_data;
+
+ if( p_buffer->i_size > 0 )
+ {
+ if( !( p_pes = input_NewPES( p_sys->p_input->p_method_data ) ) )
+ {
+ msg_Err( p_stream, "cannot allocate new PES" );
+ return VLC_EGENERIC;
+ }
+ if( !( p_data = input_NewPacket( p_sys->p_input->p_method_data, p_buffer->i_size ) ) )
+ {
+ msg_Err( p_stream, "cannot allocate new data_packet" );
+ return VLC_EGENERIC;
+ }
+ p_pes->i_dts = p_buffer->i_dts + p_sys->i_delay;
+ p_pes->i_pts = p_buffer->i_pts + p_sys->i_delay;
+ p_pes->p_first = p_pes->p_last = p_data;
+ p_pes->i_nb_data = 1;
+ p_pes->i_pes_size = p_buffer->i_size;
+
+ p_stream->p_vlc->pf_memcpy( p_data->p_payload_start,
+ p_buffer->p_buffer,
+ p_buffer->i_size );
+
+ if( id->p_es->p_decoder_fifo )
+ {
+ input_DecodePES( id->p_es->p_decoder_fifo, p_pes );
+ }
+ else
+ {
+ input_DeletePES( p_sys->p_input->p_method_data, p_pes );
+ }
+ }
+
+ /* *** go to next buffer *** */
+ p_next = p_buffer->p_next;
+ sout_BufferDelete( p_stream->p_sout, p_buffer );
+ p_buffer = p_next;
+ }
+
+ return VLC_SUCCESS;
+}
+
--- /dev/null
+/*****************************************************************************
+ * dummy.c
+ *****************************************************************************
+ * Copyright (C) 2001, 2002 VideoLAN
+ * $Id: dummy.c,v 1.1 2003/04/13 20:00:21 fenrir Exp $
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/sout.h>
+
+/*****************************************************************************
+ * Exported prototypes
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+
+static sout_stream_id_t *Add ( sout_stream_t *, sout_format_t * );
+static int Del ( sout_stream_t *, sout_stream_id_t * );
+static int Send( sout_stream_t *, sout_stream_id_t *, sout_buffer_t* );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("Dummy stream") );
+ set_capability( "sout stream", 50 );
+ add_shortcut( "dummy" );
+ set_callbacks( Open, Close );
+vlc_module_end();
+
+/*****************************************************************************
+ * Open:
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ sout_stream_t *p_stream = (sout_stream_t*)p_this;
+
+ p_stream->pf_add = Add;
+ p_stream->pf_del = Del;
+ p_stream->pf_send = Send;
+
+ p_stream->p_sys = NULL;
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Close:
+ *****************************************************************************/
+
+static void Close( vlc_object_t * p_this )
+{
+ sout_stream_t *p_stream = (sout_stream_t*)p_this;
+
+}
+
+struct sout_stream_id_t
+{
+ int i_d_u_m_m_y;
+};
+
+
+static sout_stream_id_t * Add ( sout_stream_t *p_stream, sout_format_t *p_fmt )
+{
+ sout_stream_id_t *id;
+
+ id = malloc( sizeof( sout_stream_id_t ) );
+ id->i_d_u_m_m_y = 0;
+
+ return id;
+}
+
+static int Del ( sout_stream_t *p_stream, sout_stream_id_t *id )
+{
+ free( id );
+
+ return VLC_SUCCESS;
+}
+
+static int Send ( sout_stream_t *p_stream, sout_stream_id_t *id, sout_buffer_t *p_buffer )
+{
+ sout_buffer_t *p_next;
+
+ while( p_buffer )
+ {
+ p_next = p_buffer->p_next;
+
+ sout_BufferDelete( p_stream->p_sout, p_buffer );
+ p_buffer = p_next;
+ }
+
+ return VLC_SUCCESS;
+}
+
--- /dev/null
+/*****************************************************************************
+ * duplicate.c
+ *****************************************************************************
+ * Copyright (C) 2001, 2002 VideoLAN
+ * $Id: duplicate.c,v 1.1 2003/04/13 20:00:21 fenrir Exp $
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/sout.h>
+
+/*****************************************************************************
+ * Exported prototypes
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+
+static sout_stream_id_t *Add ( sout_stream_t *, sout_format_t * );
+static int Del ( sout_stream_t *, sout_stream_id_t * );
+static int Send( sout_stream_t *, sout_stream_id_t *, sout_buffer_t* );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("Duplicate stream") );
+ set_capability( "sout stream", 50 );
+ add_shortcut( "duplicate" );
+ add_shortcut( "dup" );
+ set_callbacks( Open, Close );
+vlc_module_end();
+
+
+struct sout_stream_sys_t
+{
+ int i_nb_streams;
+ sout_stream_t **pp_streams;
+};
+
+struct sout_stream_id_t
+{
+ int i_nb_ids;
+ void **pp_ids;
+};
+
+/*****************************************************************************
+ * Open:
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ sout_stream_t *p_stream = (sout_stream_t*)p_this;
+ sout_stream_sys_t *p_sys;
+ sout_cfg_t *p_cfg;
+
+ msg_Dbg( p_stream, "creating a duplication" );
+
+ p_sys = malloc( sizeof( sout_stream_sys_t ) );
+ p_sys->i_nb_streams = 0;
+ p_sys->pp_streams = NULL;
+
+ for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next )
+ {
+ if( !strncmp( p_cfg->psz_name, "dst", strlen( "dst" ) ) )
+ {
+ sout_stream_t *s;
+
+ msg_Dbg( p_stream, " * adding `%s'", p_cfg->psz_value );
+ s = sout_stream_new( p_stream->p_sout, p_cfg->psz_value );
+
+ TAB_APPEND( p_sys->i_nb_streams, p_sys->pp_streams, s );
+ }
+ }
+
+ if( p_sys->i_nb_streams == 0 )
+ {
+ msg_Err( p_stream, "no destination given" );
+ free( p_sys );
+
+ return VLC_EGENERIC;
+ }
+
+ p_stream->pf_add = Add;
+ p_stream->pf_del = Del;
+ p_stream->pf_send = Send;
+
+ p_stream->p_sys = p_sys;
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Close:
+ *****************************************************************************/
+
+static void Close( vlc_object_t * p_this )
+{
+ sout_stream_t *p_stream = (sout_stream_t*)p_this;
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+
+ int i;
+
+ msg_Dbg( p_stream, "closing a duplication" );
+ for( i = 0; i < p_sys->i_nb_streams; i++ )
+ {
+ sout_stream_delete( p_sys->pp_streams[i] );
+ }
+ free( p_sys->pp_streams );
+
+ free( p_sys );
+}
+
+
+
+static sout_stream_id_t * Add ( sout_stream_t *p_stream, sout_format_t *p_fmt )
+{
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+ sout_stream_id_t *id;
+ int i_stream;
+
+ id = malloc( sizeof( sout_stream_id_t ) );
+ id->i_nb_ids = 0;
+ id->pp_ids = NULL;
+
+ for( i_stream = 0; i_stream < p_sys->i_nb_streams; i_stream++ )
+ {
+ void *id_new;
+
+ /* XXX not the same sout_stream_id_t definition ... */
+ id_new = (void*)p_sys->pp_streams[i_stream]->pf_add( p_sys->pp_streams[i_stream], p_fmt );
+ TAB_APPEND( id->i_nb_ids, id->pp_ids, id_new );
+ }
+
+ if( id->i_nb_ids <= 0 )
+ {
+ free( id );
+ return NULL;
+ }
+
+ return id;
+}
+
+static int Del ( sout_stream_t *p_stream, sout_stream_id_t *id )
+{
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+ int i_stream;
+
+ for( i_stream = 0; i_stream < p_sys->i_nb_streams; i_stream++ )
+ {
+ if( id->pp_ids[i_stream] )
+ {
+ p_sys->pp_streams[i_stream]->pf_del( p_sys->pp_streams[i_stream],
+ id->pp_ids[i_stream] );
+ }
+ }
+
+ free( id->pp_ids );
+ free( id );
+ return VLC_SUCCESS;
+}
+
+static int Send ( sout_stream_t *p_stream, sout_stream_id_t *id, sout_buffer_t *p_buffer )
+{
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+ int i_stream;
+
+ for( i_stream = 0; i_stream < p_sys->i_nb_streams - 1; i_stream++ )
+ {
+ sout_buffer_t *p_dup;
+
+ if( id->pp_ids[i_stream] )
+ {
+ p_dup = sout_BufferDuplicate( p_stream->p_sout, p_buffer );
+
+ p_sys->pp_streams[i_stream]->pf_send( p_sys->pp_streams[i_stream],
+ id->pp_ids[i_stream],
+ p_dup );
+ }
+ }
+
+ i_stream = p_sys->i_nb_streams - 1;
+ if( id->pp_ids[i_stream] )
+ {
+ p_sys->pp_streams[i_stream]->pf_send( p_sys->pp_streams[i_stream],
+ id->pp_ids[i_stream],
+ p_buffer);
+ }
+
+ return VLC_SUCCESS;
+}
+
--- /dev/null
+/*****************************************************************************
+ * es.c
+ *****************************************************************************
+ * Copyright (C) 2001, 2002 VideoLAN
+ * $Id: es.c,v 1.1 2003/04/13 20:00:21 fenrir Exp $
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+#include <vlc/sout.h>
+
+#define FREE( p ) if( p ) { free( p ); (p) = NULL; }
+/*****************************************************************************
+ * Exported prototypes
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+
+static sout_stream_id_t *Add ( sout_stream_t *, sout_format_t * );
+static int Del ( sout_stream_t *, sout_stream_id_t * );
+static int Send( sout_stream_t *, sout_stream_id_t *, sout_buffer_t* );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("ES stream") );
+ set_capability( "sout stream", 50 );
+ add_shortcut( "es" );
+ add_shortcut( "es" );
+ set_callbacks( Open, Close );
+vlc_module_end();
+
+struct sout_stream_sys_t
+{
+ int i_count_audio;
+ int i_count_video;
+ int i_count;
+
+ char *psz_mux;
+ char *psz_mux_audio;
+ char *psz_mux_video;
+
+ char *psz_access;
+ char *psz_access_audio;
+ char *psz_access_video;
+
+ char *psz_url;
+ char *psz_url_audio;
+ char *psz_url_video;
+};
+
+/*****************************************************************************
+ * Open:
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ sout_stream_t *p_stream = (sout_stream_t*)p_this;
+ sout_stream_sys_t *p_sys;
+
+ //p_sout->i_preheader = __MAX( p_sout->i_preheader, p_mux->i_preheader );
+
+ p_sys = malloc( sizeof( sout_stream_sys_t ) );
+
+ p_sys->i_count = 0;
+ p_sys->i_count_audio = 0;
+ p_sys->i_count_video = 0;
+
+ p_sys->psz_access = sout_cfg_find_value( p_stream->p_cfg, "access" );
+ p_sys->psz_access_audio = sout_cfg_find_value( p_stream->p_cfg, "acesss_audio" );
+ p_sys->psz_access_video = sout_cfg_find_value( p_stream->p_cfg, "access_video" );
+
+
+ p_sys->psz_mux = sout_cfg_find_value( p_stream->p_cfg, "mux" );
+ p_sys->psz_mux_audio = sout_cfg_find_value( p_stream->p_cfg, "mux_audio" );
+ p_sys->psz_mux_video = sout_cfg_find_value( p_stream->p_cfg, "mux_video" );
+
+ p_sys->psz_url = sout_cfg_find_value( p_stream->p_cfg, "url" );
+ p_sys->psz_url_audio = sout_cfg_find_value( p_stream->p_cfg, "url_audio" );
+ p_sys->psz_url_video = sout_cfg_find_value( p_stream->p_cfg, "url_video" );
+
+ p_stream->pf_add = Add;
+ p_stream->pf_del = Del;
+ p_stream->pf_send = Send;
+
+ p_stream->p_sys = p_sys;
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Close:
+ *****************************************************************************/
+
+static void Close( vlc_object_t * p_this )
+{
+ sout_stream_t *p_stream = (sout_stream_t*)p_this;
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+
+ free( p_sys );
+}
+
+struct sout_stream_id_t
+{
+ sout_input_t *p_input;
+ sout_mux_t *p_mux;
+};
+
+static char * es_print_url( char *psz_fmt, vlc_fourcc_t i_fourcc, int i_count, char *psz_access, char *psz_mux )
+{
+ char *psz_url, *p;
+
+ if( psz_fmt == NULL || !*psz_fmt )
+ {
+ psz_fmt = "stream-%n-%c.%m";
+ }
+
+ p = psz_url = malloc( 4096 );
+ memset( p, 0, 4096 );
+ for( ;; )
+ {
+ if( *psz_fmt == '\0' )
+ {
+ *p = '\0';
+ break;
+ }
+
+ if( *psz_fmt != '%' )
+ {
+ *p++ = *psz_fmt++;
+ }
+ else
+ {
+ if( psz_fmt[1] == 'n' )
+ {
+ p += sprintf( p, "%d", i_count );
+ }
+ else if( psz_fmt[1] == 'c' )
+ {
+ p += sprintf( p, "%4.4s", (char*)&i_fourcc );
+ }
+ else if( psz_fmt[1] == 'm' )
+ {
+ p += sprintf( p, "%s", psz_mux );
+ }
+ else if( psz_fmt[1] == 'a' )
+ {
+ p += sprintf( p, "%s", psz_access );
+ }
+ else if( psz_fmt[1] != '\0' )
+ {
+ p += sprintf( p, "%c%c", psz_fmt[0], psz_fmt[1] );
+ }
+ else
+ {
+ p += sprintf( p, "%c", psz_fmt[0] );
+ *p++ = '\0';
+ break;
+ }
+ psz_fmt += 2;
+ }
+ }
+
+ return( psz_url );
+}
+
+static sout_stream_id_t * Add ( sout_stream_t *p_stream, sout_format_t *p_fmt )
+{
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+ sout_instance_t *p_sout = p_stream->p_sout;
+ sout_stream_id_t *id;
+
+ char *psz_access;
+ char *psz_mux;
+ char *psz_url;
+
+ sout_access_out_t *p_access;
+ sout_mux_t *p_mux;
+
+ /* *** get access name *** */
+ if( p_fmt->i_cat == AUDIO_ES && p_sys->psz_access_audio )
+ {
+ psz_access = p_sys->psz_access_audio;
+ }
+ else if( p_fmt->i_cat == VIDEO_ES && p_sys->psz_access_video )
+ {
+ psz_access = p_sys->psz_access_video;
+ }
+ else
+ {
+ psz_access = p_sys->psz_access;
+ }
+
+ /* *** get mux name *** */
+ if( p_fmt->i_cat == AUDIO_ES && p_sys->psz_mux_audio )
+ {
+ psz_mux = p_sys->psz_mux_audio;
+ }
+ else if( p_fmt->i_cat == VIDEO_ES && p_sys->psz_mux_video )
+ {
+ psz_mux = p_sys->psz_mux_video;
+ }
+ else
+ {
+ psz_mux = p_sys->psz_mux;
+ }
+
+ /* *** get url (%d expanded as a codec count, %c expanded as codec fcc ) *** */
+ if( p_fmt->i_cat == AUDIO_ES && p_sys->psz_url_audio )
+ {
+ psz_url = es_print_url( p_sys->psz_url_audio, p_fmt->i_fourcc, p_sys->i_count_audio, psz_access, psz_mux );
+ }
+ else if( p_fmt->i_cat == VIDEO_ES && p_sys->psz_url_video )
+ {
+ psz_url = es_print_url( p_sys->psz_url_video, p_fmt->i_fourcc, p_sys->i_count_video, psz_access, psz_mux );
+ }
+ else
+ {
+ int i_count;
+ if( p_fmt->i_cat == VIDEO_ES )
+ {
+ i_count = p_sys->i_count_video;
+ }
+ else if( p_fmt->i_cat == AUDIO_ES )
+ {
+ i_count = p_sys->i_count_audio;
+ }
+ else
+ {
+ i_count = p_sys->i_count;
+ }
+
+ psz_url = es_print_url( p_sys->psz_url, p_fmt->i_fourcc, i_count, psz_access, psz_mux );
+ }
+
+ p_sys->i_count++;
+ if( p_fmt->i_cat == VIDEO_ES )
+ {
+ p_sys->i_count_video++;
+ }
+ else if( p_fmt->i_cat == AUDIO_ES )
+ {
+ p_sys->i_count_audio++;
+ }
+ msg_Dbg( p_stream, "creating `%s/%s://%s'",
+ psz_access, psz_mux, psz_url );
+
+ /* *** find and open appropriate access module *** */
+ p_access = sout_AccessOutNew( p_sout, psz_access, psz_url );
+ if( p_access == NULL )
+ {
+ msg_Err( p_stream, "no suitable sout access module for `%s/%s://%s'",
+ psz_access, psz_mux, psz_url );
+ return( NULL );
+ }
+
+ /* *** find and open appropriate mux module *** */
+ p_mux = sout_MuxNew( p_sout, psz_mux, p_access );
+ if( p_mux == NULL )
+ {
+ msg_Err( p_stream, "no suitable sout mux module for `%s/%s://%s'",
+ psz_access, psz_mux, psz_url );
+ sout_AccessOutDelete( p_access );
+ return( NULL );
+ }
+
+ /* XXX beurk */
+ p_sout->i_preheader = __MAX( p_sout->i_preheader, p_mux->i_preheader );
+
+ id = malloc( sizeof( sout_stream_id_t ) );
+ id->p_mux = p_mux;
+ id->p_input = sout_MuxAddStream( p_mux, p_fmt );
+
+ if( id->p_input == NULL )
+ {
+ free( id );
+
+ sout_MuxDelete( p_mux );
+ sout_AccessOutDelete( p_access );
+ free( id );
+ return NULL;
+ }
+
+ return id;
+}
+
+static int Del ( sout_stream_t *p_stream, sout_stream_id_t *id )
+{
+ sout_access_out_t *p_access = id->p_mux->p_access;
+
+ sout_MuxDeleteStream( id->p_mux, id->p_input );
+ sout_AccessOutDelete( p_access );
+
+ free( id );
+ return VLC_SUCCESS;
+}
+
+static int Send ( sout_stream_t *p_stream, sout_stream_id_t *id, sout_buffer_t *p_buffer )
+{
+ sout_MuxSendBuffer( id->p_mux, id->p_input, p_buffer );
+
+ return VLC_SUCCESS;
+}
+
--- /dev/null
+/*****************************************************************************
+ * standard.c
+ *****************************************************************************
+ * Copyright (C) 2001, 2002 VideoLAN
+ * $Id: standard.c,v 1.1 2003/04/13 20:00:21 fenrir Exp $
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/sout.h>
+
+/*****************************************************************************
+ * Exported prototypes
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+
+static sout_stream_id_t *Add ( sout_stream_t *, sout_format_t * );
+static int Del ( sout_stream_t *, sout_stream_id_t * );
+static int Send( sout_stream_t *, sout_stream_id_t *, sout_buffer_t* );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("Standard stream") );
+ set_capability( "sout stream", 50 );
+ add_shortcut( "standard" );
+ add_shortcut( "std" );
+ set_callbacks( Open, Close );
+vlc_module_end();
+
+struct sout_stream_sys_t
+{
+ sout_mux_t *p_mux;
+};
+
+/*****************************************************************************
+ * Open:
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ sout_stream_t *p_stream = (sout_stream_t*)p_this;
+ sout_instance_t *p_sout = p_stream->p_sout;
+ sout_stream_sys_t *p_sys;
+
+ char *psz_mux = sout_cfg_find_value( p_stream->p_cfg, "mux" );
+ char *psz_access = sout_cfg_find_value( p_stream->p_cfg, "access" );
+ char *psz_url = sout_cfg_find_value( p_stream->p_cfg, "url" );
+
+ sout_access_out_t *p_access;
+ sout_mux_t *p_mux;
+
+ msg_Dbg( p_this, "creating `%s/%s://%s'",
+ psz_access, psz_mux, psz_url );
+
+ /* *** find and open appropriate access module *** */
+ p_access = sout_AccessOutNew( p_sout, psz_access, psz_url );
+ if( p_access == NULL )
+ {
+ msg_Err( p_stream, "no suitable sout access module for `%s/%s://%s'",
+ psz_access, psz_mux, psz_url );
+ return( VLC_EGENERIC );
+ }
+ msg_Dbg( p_stream, "access opened" );
+
+ /* *** find and open appropriate mux module *** */
+ p_mux = sout_MuxNew( p_sout, psz_mux, p_access );
+ if( p_mux == NULL )
+ {
+ msg_Err( p_stream, "no suitable sout mux module for `%s/%s://%s'",
+ psz_access, psz_mux, psz_url );
+
+ sout_AccessOutDelete( p_access );
+ return( VLC_EGENERIC );
+ }
+ msg_Dbg( p_stream, "mux opened" );
+
+ /* XXX beurk */
+ p_sout->i_preheader = __MAX( p_sout->i_preheader, p_mux->i_preheader );
+
+ p_sys = malloc( sizeof( sout_stream_sys_t ) );
+ p_sys->p_mux = p_mux;
+
+ p_stream->pf_add = Add;
+ p_stream->pf_del = Del;
+ p_stream->pf_send = Send;
+
+ p_stream->p_sys = p_sys;
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Close:
+ *****************************************************************************/
+
+static void Close( vlc_object_t * p_this )
+{
+ sout_stream_t *p_stream = (sout_stream_t*)p_this;
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+
+ sout_access_out_t *p_access = p_sys->p_mux->p_access;
+
+
+ sout_MuxDelete( p_sys->p_mux );
+ sout_AccessOutDelete( p_access );
+
+ free( p_sys );
+}
+
+struct sout_stream_id_t
+{
+ sout_input_t *p_input;
+};
+
+
+static sout_stream_id_t * Add ( sout_stream_t *p_stream, sout_format_t *p_fmt )
+{
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+ sout_stream_id_t *id;
+
+ id = malloc( sizeof( sout_stream_id_t ) );
+ if( ( id->p_input = sout_MuxAddStream( p_sys->p_mux, p_fmt ) ) == NULL )
+ {
+ free( id );
+
+ return NULL;
+ }
+
+ return id;
+}
+
+static int Del ( sout_stream_t *p_stream, sout_stream_id_t *id )
+{
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+
+ sout_MuxDeleteStream( p_sys->p_mux, id->p_input );
+
+ free( id );
+
+ return VLC_SUCCESS;
+}
+
+static int Send ( sout_stream_t *p_stream, sout_stream_id_t *id, sout_buffer_t *p_buffer )
+{
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+
+ sout_MuxSendBuffer( p_sys->p_mux, id->p_input, p_buffer );
+
+ return VLC_SUCCESS;
+}
+
--- /dev/null
+/*****************************************************************************
+ * transcode.c
+ *****************************************************************************
+ * Copyright (C) 2001, 2002 VideoLAN
+ * $Id: transcode.c,v 1.1 2003/04/13 20:00:21 fenrir Exp $
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+#include <vlc/sout.h>
+
+#include "/home/fenrir/videolan/ffmpeg/libavcodec/avcodec.h"
+
+/*****************************************************************************
+ * Exported prototypes
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+
+static sout_stream_id_t *Add ( sout_stream_t *, sout_format_t * );
+static int Del ( sout_stream_t *, sout_stream_id_t * );
+static int Send( sout_stream_t *, sout_stream_id_t *, sout_buffer_t* );
+
+static int transcode_audio_ffmpeg_new ( sout_stream_t *, sout_stream_id_t * );
+static void transcode_audio_ffmpeg_close ( sout_stream_t *, sout_stream_id_t * );
+static int transcode_audio_ffmpeg_process( sout_stream_t *, sout_stream_id_t *, sout_buffer_t *, sout_buffer_t ** );
+
+static int transcode_video_ffmpeg_new ( sout_stream_t *, sout_stream_id_t * );
+static void transcode_video_ffmpeg_close ( sout_stream_t *, sout_stream_id_t * );
+static int transcode_video_ffmpeg_process( sout_stream_t *, sout_stream_id_t *, sout_buffer_t *, sout_buffer_t ** );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ set_description( _("Transcode stream") );
+ set_capability( "sout stream", 50 );
+ add_shortcut( "transcode" );
+ set_callbacks( Open, Close );
+vlc_module_end();
+
+struct sout_stream_sys_t
+{
+ sout_stream_t *p_out;
+
+ vlc_fourcc_t i_acodec; // codec audio (0 if not transcode)
+ int i_sample_rate;
+ int i_channels;
+ int i_abitrate;
+
+ vlc_fourcc_t i_vcodec; // " video " " " "
+ int i_vbitrate;
+ int i_width;
+ int i_height;
+ vlc_bool_t b_deinterlace;
+
+ int i_crop_top;
+ int i_crop_bottom;
+ int i_crop_right;
+ int i_crop_left;
+};
+
+/*****************************************************************************
+ * Open:
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ sout_stream_t *p_stream = (sout_stream_t*)p_this;
+ sout_stream_sys_t *p_sys;
+ char *codec;
+
+ p_sys = malloc( sizeof( sout_stream_sys_t ) );
+ p_sys->p_out = sout_stream_new( p_stream->p_sout, p_stream->psz_next );
+
+ p_sys->i_acodec = 0;
+ p_sys->i_sample_rate = 0;
+ p_sys->i_channels = 0;
+ p_sys->i_abitrate = 0;
+
+ p_sys->i_vcodec = 0;
+ p_sys->i_vbitrate = 0;
+ p_sys->i_width = 0;
+ p_sys->i_height = 0;
+ p_sys->b_deinterlace= VLC_FALSE;
+
+ p_sys->i_crop_top = 0;
+ p_sys->i_crop_bottom= 0;
+ p_sys->i_crop_right = 0;
+ p_sys->i_crop_left = 0;
+
+ if( ( codec = sout_cfg_find_value( p_stream->p_cfg, "acodec" ) ) )
+ {
+ char fcc[4] = " ";
+ char *val;
+
+ memcpy( fcc, codec, strlen( codec ) );
+
+ p_sys->i_acodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
+
+ if( ( val = sout_cfg_find_value( p_stream->p_cfg, "samplerate" ) ) )
+ {
+ p_sys->i_sample_rate = atoi( val );
+ }
+ if( ( val = sout_cfg_find_value( p_stream->p_cfg, "channels" ) ) )
+ {
+ p_sys->i_channels = atoi( val );
+ }
+ if( ( val = sout_cfg_find_value( p_stream->p_cfg, "ab" ) ) )
+ {
+ p_sys->i_abitrate = atoi( val );
+ }
+
+ msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
+ fcc,
+ p_sys->i_sample_rate, p_sys->i_channels,
+ p_sys->i_abitrate / 1024 );
+ }
+
+ if( ( codec = sout_cfg_find_value( p_stream->p_cfg, "vcodec" ) ) )
+ {
+ char fcc[4] = " ";
+ char *val;
+
+ memcpy( fcc, codec, strlen( codec ) );
+
+ p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
+
+ if( ( val = sout_cfg_find_value( p_stream->p_cfg, "width" ) ) )
+ {
+ p_sys->i_width = atoi( val );
+ }
+ if( ( val = sout_cfg_find_value( p_stream->p_cfg, "height" ) ) )
+ {
+ p_sys->i_height = atoi( val );
+ }
+ if( ( val = sout_cfg_find_value( p_stream->p_cfg, "vb" ) ) )
+ {
+ p_sys->i_vbitrate = atoi( val );
+ }
+ if( sout_cfg_find( p_stream->p_cfg, "deinterlace" ) )
+ {
+ p_sys->b_deinterlace = VLC_TRUE;
+ }
+ /* crop */
+ if( ( val = sout_cfg_find_value( p_stream->p_cfg, "croptop" ) ) )
+ {
+ p_sys->i_crop_top = atoi( val );
+ }
+ if( ( val = sout_cfg_find_value( p_stream->p_cfg, "cropbottom" ) ) )
+ {
+ p_sys->i_crop_bottom = atoi( val );
+ }
+ if( ( val = sout_cfg_find_value( p_stream->p_cfg, "cropleft" ) ) )
+ {
+ p_sys->i_crop_left = atoi( val );
+ }
+ if( ( val = sout_cfg_find_value( p_stream->p_cfg, "cropright" ) ) )
+ {
+ p_sys->i_crop_right = atoi( val );
+ }
+
+ msg_Dbg( p_stream, "codec video=%4.4s %dx%d %dkb/s",
+ fcc,
+ p_sys->i_width, p_sys->i_height,
+ p_sys->i_vbitrate / 1024 );
+ }
+
+ if( !p_sys->p_out )
+ {
+ msg_Err( p_stream, "cannot create chain" );
+ free( p_sys );
+ return VLC_EGENERIC;
+ }
+ p_stream->pf_add = Add;
+ p_stream->pf_del = Del;
+ p_stream->pf_send = Send;
+
+ p_stream->p_sys = p_sys;
+
+ avcodec_init();
+ avcodec_register_all();
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Close:
+ *****************************************************************************/
+
+static void Close( vlc_object_t * p_this )
+{
+ sout_stream_t *p_stream = (sout_stream_t*)p_this;
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+
+ sout_stream_delete( p_sys->p_out );
+ free( p_sys );
+}
+
+struct sout_stream_id_t
+{
+ vlc_fourcc_t b_transcode;
+ sout_format_t f_src; // only if transcoding
+ sout_format_t f_dst; // " " "
+
+ /* id of the out stream */
+ void *id;
+
+ /* ffmpeg part */
+ AVCodec *ff_dec;
+ AVCodecContext *ff_dec_c;
+
+
+ vlc_fourcc_t b_enc_inited;
+ AVCodec *ff_enc;
+ AVCodecContext *ff_enc_c;
+
+ mtime_t i_dts;
+ mtime_t i_length;
+
+ int i_buffer_in;
+ int i_buffer_in_pos;
+ uint8_t *p_buffer_in;
+
+ int i_buffer;
+ int i_buffer_pos;
+ uint8_t *p_buffer;
+
+ int i_buffer_out;
+ int i_buffer_out_pos;
+ uint8_t *p_buffer_out;
+
+ AVFrame *p_ff_pic;
+ AVFrame *p_ff_pic_tmp0; // to do deinterlace
+ AVFrame *p_ff_pic_tmp1; // to do pix conversion
+ AVFrame *p_ff_pic_tmp2; // to do resample
+
+ ImgReSampleContext *p_vresample;
+};
+
+
+static sout_stream_id_t * Add ( sout_stream_t *p_stream, sout_format_t *p_fmt )
+{
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+ sout_stream_id_t *id;
+
+ id = malloc( sizeof( sout_stream_id_t ) );
+ id->i_dts = 0;
+ if( p_fmt->i_cat == AUDIO_ES && p_sys->i_acodec != 0 )
+ {
+ msg_Dbg( p_stream,
+ "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
+ (char*)&p_fmt->i_fourcc,
+ (char*)&p_sys->i_acodec );
+
+ /* src format */
+ memcpy( &id->f_src, p_fmt, sizeof( sout_format_t ) );
+
+ /* create dst format */
+ id->f_dst.i_cat = AUDIO_ES;
+ id->f_dst.i_fourcc = p_sys->i_acodec;
+ id->f_dst.i_sample_rate = p_sys->i_sample_rate > 0 ? p_sys->i_sample_rate : id->f_src.i_sample_rate;
+ id->f_dst.i_channels = p_sys->i_channels > 0 ? p_sys->i_channels : id->f_src.i_channels;
+ id->f_dst.i_bitrate = p_sys->i_abitrate > 0 ? p_sys->i_abitrate : 64000;
+ id->f_dst.i_block_align = 0;
+ id->f_dst.i_extra_data = 0;
+ id->f_dst.p_extra_data = NULL;
+
+ /* build decoder -> filter -> encoder */
+ if( transcode_audio_ffmpeg_new( p_stream, id ) )
+ {
+ msg_Err( p_stream, "cannot create audio chain" );
+ free( id );
+ return NULL;
+ }
+
+ /* open output stream */
+ id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->f_dst );
+ id->b_transcode = VLC_TRUE;
+ }
+ else if( p_fmt->i_cat == VIDEO_ES && p_sys->i_vcodec != 0 )
+ {
+ msg_Dbg( p_stream,
+ "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
+ (char*)&p_fmt->i_fourcc,
+ (char*)&p_sys->i_vcodec );
+
+ memcpy( &id->f_src, p_fmt, sizeof( sout_format_t ) );
+
+ /* create dst format */
+ id->f_dst.i_cat = VIDEO_ES;
+ id->f_dst.i_fourcc = p_sys->i_vcodec;
+ id->f_dst.i_width = p_sys->i_width ; //> 0 ? p_sys->i_width : id->f_src.i_width;
+ id->f_dst.i_height = p_sys->i_height; // > 0 ? p_sys->i_height: id->f_src.i_height;
+ id->f_dst.i_bitrate = p_sys->i_vbitrate > 0 ? p_sys->i_vbitrate : 800*1000;
+ id->f_dst.i_extra_data = 0;
+ id->f_dst.p_extra_data = NULL;
+
+ /* build decoder -> filter -> encoder */
+ if( transcode_video_ffmpeg_new( p_stream, id ) )
+ {
+ msg_Err( p_stream, "cannot create video chain" );
+ free( id );
+ return NULL;
+ }
+
+ /* open output stream */
+ id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->f_dst );
+ id->b_transcode = VLC_TRUE;
+ }
+ else
+ {
+ msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')", (char*)&p_fmt->i_fourcc );
+ id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt );
+ id->b_transcode = VLC_FALSE;
+
+ if( id->id == NULL )
+ {
+ free( id );
+ return NULL;
+ }
+ }
+
+ return id;
+}
+
+static int Del ( sout_stream_t *p_stream, sout_stream_id_t *id )
+{
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+
+ if( id->b_transcode )
+ {
+ if( id->f_src.i_cat == AUDIO_ES )
+ {
+ transcode_audio_ffmpeg_close( p_stream, id );
+ }
+ else if( id->f_src.i_cat == VIDEO_ES )
+ {
+ transcode_video_ffmpeg_close( p_stream, id );
+ }
+ }
+
+ p_sys->p_out->pf_del( p_sys->p_out, id->id );
+ free( id );
+
+ return VLC_SUCCESS;
+}
+
+static int Send ( sout_stream_t *p_stream, sout_stream_id_t *id, sout_buffer_t *p_buffer )
+{
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+
+ if( id->b_transcode )
+ {
+ sout_buffer_t *p_buffer_out;
+ if( id->f_src.i_cat == AUDIO_ES )
+ {
+ transcode_audio_ffmpeg_process( p_stream, id, p_buffer, &p_buffer_out );
+ }
+ else if( id->f_src.i_cat == VIDEO_ES )
+ {
+ transcode_video_ffmpeg_process( p_stream, id, p_buffer, &p_buffer_out );
+ }
+ sout_BufferDelete( p_stream->p_sout, p_buffer );
+
+ if( p_buffer_out )
+ {
+ return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer_out );
+ }
+ return VLC_SUCCESS;
+ }
+ else
+ {
+ return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer );
+ }
+}
+
+/****************************************************************************
+ * ffmpeg decoder reencocdr part
+ ****************************************************************************/
+
+static struct
+{
+ vlc_fourcc_t i_fcc;
+ int i_ff_codec;
+} fourcc_to_ff_code[] =
+{
+ /* audio */
+ { VLC_FOURCC( 'm', 'p', 'g', 'a' ), CODEC_ID_MP2 },
+ { VLC_FOURCC( 'a', '5', '2', ' ' ), CODEC_ID_AC3 },
+ { VLC_FOURCC( 'a', 'c', '3', ' ' ), CODEC_ID_AC3 },
+ { VLC_FOURCC( 'w', 'm', 'a', '1' ), CODEC_ID_WMAV1 },
+ { VLC_FOURCC( 'w', 'm', 'a', '2' ), CODEC_ID_WMAV2 },
+
+ /* video */
+ { VLC_FOURCC( 'm', 'p', '4', 'v'), CODEC_ID_MPEG4 },
+ { VLC_FOURCC( 'm', 'p', 'g', 'v' ), CODEC_ID_MPEG1VIDEO },
+ { VLC_FOURCC( 'D', 'I', 'V', '1' ), CODEC_ID_MSMPEG4V1 },
+ { VLC_FOURCC( 'D', 'I', 'V', '2' ), CODEC_ID_MSMPEG4V2 },
+ { VLC_FOURCC( 'D', 'I', 'V', '3' ), CODEC_ID_MSMPEG4V3 },
+ { VLC_FOURCC( 'H', '2', '6', '3' ), CODEC_ID_H263 },
+ { VLC_FOURCC( 'I', '2', '6', '3' ), CODEC_ID_H263I },
+ { VLC_FOURCC( 'W', 'M', 'V', '1' ), CODEC_ID_WMV1 },
+ { VLC_FOURCC( 'W', 'M', 'V', '2' ), CODEC_ID_WMV2 },
+ { VLC_FOURCC( 'M', 'J', 'P', 'G' ), CODEC_ID_MJPEG },
+ { VLC_FOURCC( 'm', 'j', 'p', 'b' ), CODEC_ID_MJPEGB },
+ { VLC_FOURCC( 'd', 'v', 's', 'l' ), CODEC_ID_DVVIDEO },
+ { VLC_FOURCC( 'S', 'V', 'Q', '1' ), CODEC_ID_SVQ1 },
+
+ { VLC_FOURCC( 0, 0, 0, 0 ), 0 }
+};
+
+static inline int get_ff_codec( vlc_fourcc_t i_fcc )
+{
+ int i;
+
+ for( i = 0; fourcc_to_ff_code[i].i_fcc != 0; i++ )
+ {
+ if( fourcc_to_ff_code[i].i_fcc == i_fcc )
+ {
+ return fourcc_to_ff_code[i].i_ff_codec;
+ }
+ }
+
+ return 0;
+}
+
+static int transcode_audio_ffmpeg_new ( sout_stream_t *p_stream, sout_stream_id_t *id )
+{
+ int i_ff_codec;
+
+ /* find decoder */
+
+ i_ff_codec = get_ff_codec( id->f_src.i_fourcc );
+ if( i_ff_codec == 0 )
+ {
+ msg_Err( p_stream, "cannot find decoder" );
+ return VLC_EGENERIC;
+ }
+
+ id->ff_dec = avcodec_find_decoder( i_ff_codec );
+ if( !id->ff_dec )
+ {
+ msg_Err( p_stream, "cannot find decoder" );
+ return VLC_EGENERIC;
+ }
+
+ id->ff_dec_c = avcodec_alloc_context();
+ id->ff_dec_c->sample_rate = id->f_src.i_sample_rate;
+ id->ff_dec_c->channels = id->f_src.i_channels;
+ id->ff_dec_c->block_align = id->f_src.i_block_align;
+ id->ff_dec_c->bit_rate = id->f_src.i_bitrate;
+
+ id->ff_dec_c->extradata_size = id->f_src.i_extra_data;
+ id->ff_dec_c->extradata = id->f_src.p_extra_data;
+ if( avcodec_open( id->ff_dec_c, id->ff_dec ) )
+ {
+ msg_Err( p_stream, "cannot open decoder" );
+ return VLC_EGENERIC;
+ }
+
+ /* find encoder */
+ i_ff_codec = get_ff_codec( id->f_dst.i_fourcc );
+ if( i_ff_codec == 0 )
+ {
+ msg_Err( p_stream, "cannot find encoder" );
+ return VLC_EGENERIC;
+ }
+
+ id->ff_enc = avcodec_find_encoder( i_ff_codec );
+ if( !id->ff_enc )
+ {
+ msg_Err( p_stream, "cannot find encoder" );
+ return VLC_EGENERIC;
+ }
+
+ id->ff_enc_c = avcodec_alloc_context();
+ id->ff_enc_c->bit_rate = id->f_dst.i_bitrate;
+ id->ff_enc_c->sample_rate = id->f_dst.i_sample_rate;
+ id->ff_enc_c->channels = id->f_dst.i_channels;
+
+ if( avcodec_open( id->ff_enc_c, id->ff_enc ) )
+ {
+ msg_Err( p_stream, "cannot open encoder" );
+ return VLC_EGENERIC;
+ }
+
+
+ id->i_buffer_in = AVCODEC_MAX_AUDIO_FRAME_SIZE;
+ id->i_buffer_in_pos = 0;
+ id->p_buffer_in = malloc( id->i_buffer_in );
+
+ id->i_buffer = AVCODEC_MAX_AUDIO_FRAME_SIZE;
+ id->i_buffer_pos = 0;
+ id->p_buffer = malloc( id->i_buffer );
+
+ id->i_buffer_out = AVCODEC_MAX_AUDIO_FRAME_SIZE;
+ id->i_buffer_out_pos = 0;
+ id->p_buffer_out = malloc( id->i_buffer_out );
+
+ return VLC_SUCCESS;
+}
+
+static void transcode_audio_ffmpeg_close ( sout_stream_t *p_stream, sout_stream_id_t *id )
+{
+ avcodec_close( id->ff_dec_c );
+ avcodec_close( id->ff_enc_c );
+
+ free( id->ff_dec_c );
+ free( id->ff_enc_c );
+
+ free( id->p_buffer );
+}
+
+static int transcode_audio_ffmpeg_process( sout_stream_t *p_stream, sout_stream_id_t *id,
+ sout_buffer_t *in, sout_buffer_t **out )
+{
+ *out = NULL;
+
+ /* gather data into p_buffer_in */
+ id->i_dts = in->i_dts -
+ (mtime_t)1000000 *
+ (mtime_t)(id->i_buffer_pos / 2 / id->ff_enc_c->channels )/
+ (mtime_t)id->ff_enc_c->sample_rate;
+
+ memcpy( &id->p_buffer_in[id->i_buffer_in_pos],
+ in->p_buffer,
+ in->i_size );
+ id->i_buffer_in_pos += in->i_size;
+
+ /* decode as many data as possible */
+ for( ;; )
+ {
+ int i_buffer_size;
+ int i_used;
+
+ i_buffer_size = id->i_buffer - id->i_buffer_pos;
+
+ i_used = avcodec_decode_audio( id->ff_dec_c,
+ (int16_t*)&id->p_buffer[id->i_buffer_pos], &i_buffer_size,
+ id->p_buffer_in, id->i_buffer_in_pos );
+
+ //msg_Warn( p_stream, "avcodec_decode_audio: %d used", i_used );
+ id->i_buffer_pos += i_buffer_size;
+
+ if( i_used < 0 )
+ {
+ msg_Warn( p_stream, "error");
+ id->i_buffer_in_pos = 0;
+ break;
+ }
+ else if( i_used < id->i_buffer_in_pos )
+ {
+ memmove( id->p_buffer_in,
+ &id->p_buffer_in[i_used],
+ id->i_buffer_in - i_used );
+ id->i_buffer_in_pos -= i_used;
+ }
+ else
+ {
+ id->i_buffer_in_pos = 0;
+ break;
+ }
+ }
+
+ /* encode as many data as possible */
+ for( ;; )
+ {
+ int i_frame_size = id->ff_enc_c->frame_size * 2 * id->ff_enc_c->channels;
+ int i_out_size;
+ sout_buffer_t *p_out;
+
+ if( id->i_buffer_pos < i_frame_size )
+ {
+ break;
+ }
+
+ //msg_Warn( p_stream, "avcodec_encode_audio: frame size%d", i_frame_size);
+ i_out_size = avcodec_encode_audio( id->ff_enc_c,
+ id->p_buffer_out, id->i_buffer_out,
+ (int16_t*)id->p_buffer );
+
+ if( i_out_size <= 0 )
+ {
+ break;
+ }
+ memmove( id->p_buffer,
+ &id->p_buffer[i_frame_size],
+ id->i_buffer - i_frame_size );
+ id->i_buffer_pos -= i_frame_size;
+
+ p_out = sout_BufferNew( p_stream->p_sout, i_out_size );
+ memcpy( p_out->p_buffer, id->p_buffer_out, i_out_size );
+ p_out->i_size = i_out_size;
+ p_out->i_length = (mtime_t)1000000 * (mtime_t)id->ff_enc_c->frame_size / (mtime_t)id->ff_enc_c->sample_rate;
+ /* FIXME */
+ p_out->i_dts = id->i_dts;
+ p_out->i_pts = id->i_dts;
+
+ /* update dts */
+ id->i_dts += p_out->i_length;
+
+ //msg_Warn( p_stream, "frame dts=%lld len %lld out=%d", p_out->i_dts, p_out->i_length, i_out_size );
+ sout_BufferChain( out, p_out );
+ }
+
+ return VLC_SUCCESS;
+}
+
+
+/*
+ * video
+ */
+static int transcode_video_ffmpeg_new ( sout_stream_t *p_stream, sout_stream_id_t *id )
+{
+ int i_ff_codec;
+
+ /* find decoder */
+ i_ff_codec = get_ff_codec( id->f_src.i_fourcc );
+ if( i_ff_codec == 0 )
+ {
+ msg_Err( p_stream, "cannot find decoder" );
+ return VLC_EGENERIC;
+ }
+
+ id->ff_dec = avcodec_find_decoder( i_ff_codec );
+ if( !id->ff_dec )
+ {
+ msg_Err( p_stream, "cannot find decoder" );
+ return VLC_EGENERIC;
+ }
+
+ id->ff_dec_c = avcodec_alloc_context();
+ id->ff_dec_c->width = id->f_src.i_width;
+ id->ff_dec_c->height = id->f_src.i_height;
+ //id->ff_dec_c->bit_rate = id->f_src.i_bitrate;
+ id->ff_dec_c->extradata_size= id->f_src.i_extra_data;
+ id->ff_dec_c->extradata = id->f_src.p_extra_data;
+ id->ff_dec_c->workaround_bugs = FF_BUG_AUTODETECT;
+ id->ff_dec_c->error_resilience= -1;
+ if( id->ff_dec->capabilities & CODEC_CAP_TRUNCATED )
+ {
+ id->ff_dec_c->flags |= CODEC_FLAG_TRUNCATED;
+ }
+
+ if( avcodec_open( id->ff_dec_c, id->ff_dec ) < 0 )
+ {
+ msg_Err( p_stream, "cannot open decoder" );
+ return VLC_EGENERIC;
+ }
+#if 1
+ if( i_ff_codec == CODEC_ID_MPEG4 && id->ff_dec_c->extradata_size > 0 )
+ {
+ int b_gotpicture;
+ AVFrame frame;
+
+ avcodec_decode_video( id->ff_dec_c, &frame,
+ &b_gotpicture,
+ id->ff_dec_c->extradata, id->ff_dec_c->extradata_size );
+ }
+#endif
+
+ /* find encoder */
+ i_ff_codec = get_ff_codec( id->f_dst.i_fourcc );
+ if( i_ff_codec == 0 )
+ {
+ msg_Err( p_stream, "cannot find encoder" );
+ return VLC_EGENERIC;
+ }
+
+ id->ff_enc = avcodec_find_encoder( i_ff_codec );
+ if( !id->ff_enc )
+ {
+ msg_Err( p_stream, "cannot find encoder" );
+ return VLC_EGENERIC;
+ }
+
+ id->ff_enc_c = avcodec_alloc_context();
+ id->ff_enc_c->width = id->f_dst.i_width;
+ id->ff_enc_c->height = id->f_dst.i_height;
+ id->ff_enc_c->bit_rate = id->f_dst.i_bitrate;
+ id->ff_enc_c->frame_rate = 25 ; // FIXME as it break mpeg
+ id->ff_enc_c->frame_rate_base= 1;
+ id->ff_enc_c->gop_size = 25;
+ id->ff_enc_c->qmin = 2;
+ id->ff_enc_c->qmax = 31;
+#if 0
+ /* XXX open it when we have the first frame */
+ if( avcodec_open( id->ff_enc_c, id->ff_enc ) )
+ {
+ msg_Err( p_stream, "cannot open encoder" );
+ return VLC_EGENERIC;
+ }
+#endif
+ id->b_enc_inited = VLC_FALSE;
+ id->i_buffer_in = 0;
+ id->i_buffer_in_pos = 0;
+ id->p_buffer_in = NULL;
+
+ id->i_buffer = 3*1024*1024;
+ id->i_buffer_pos = 0;
+ id->p_buffer = malloc( id->i_buffer );
+
+ id->i_buffer_out = 0;
+ id->i_buffer_out_pos = 0;
+ id->p_buffer_out = NULL;
+
+ id->p_ff_pic = avcodec_alloc_frame();
+ id->p_ff_pic_tmp0 = NULL;
+ id->p_ff_pic_tmp1 = NULL;
+ id->p_ff_pic_tmp2 = NULL;
+ id->p_vresample = NULL;
+ return VLC_SUCCESS;
+}
+
+static void transcode_video_ffmpeg_close ( sout_stream_t *p_stream, sout_stream_id_t *id )
+{
+ avcodec_close( id->ff_dec_c );
+ if( id->b_enc_inited )
+ {
+ avcodec_close( id->ff_enc_c );
+ }
+
+ if( id->p_ff_pic)
+ {
+ free( id->p_ff_pic );
+ }
+
+ if( id->p_ff_pic_tmp0 )
+ {
+ free( id->p_ff_pic_tmp0->data[0] );
+ free( id->p_ff_pic_tmp0 );
+ }
+ if( id->p_ff_pic_tmp1)
+ {
+ free( id->p_ff_pic_tmp1->data[0] );
+ free( id->p_ff_pic_tmp1 );
+ }
+ if( id->p_ff_pic_tmp2)
+ {
+ free( id->p_ff_pic_tmp2->data[0] );
+ free( id->p_ff_pic_tmp2 );
+ }
+ if( id->p_vresample )
+ {
+ free( id->p_vresample );
+ }
+
+ free( id->ff_dec_c );
+ free( id->ff_enc_c );
+
+ free( id->p_buffer );
+}
+
+static int transcode_video_ffmpeg_process( sout_stream_t *p_stream, sout_stream_id_t *id,
+ sout_buffer_t *in, sout_buffer_t **out )
+{
+ int i_used;
+ int i_out;
+ int b_gotpicture;
+ AVFrame *frame;
+
+ int i_data;
+ uint8_t *p_data;
+
+ *out = NULL;
+
+ i_data = in->i_size;
+ p_data = in->p_buffer;
+
+ for( ;; )
+ {
+ /* decode frame */
+ frame = id->p_ff_pic;
+ i_used = avcodec_decode_video( id->ff_dec_c, frame,
+ &b_gotpicture,
+ p_data, i_data );
+
+ if( i_used < 0 )
+ {
+ msg_Warn( p_stream, "error");
+ return VLC_EGENERIC;
+ }
+ i_data -= i_used;
+ p_data += i_used;
+
+ if( !b_gotpicture )
+ {
+ return VLC_SUCCESS;
+ }
+
+ if( !id->b_enc_inited )
+ {
+ /* XXX hack because of copy packetizer and mpeg4video that can failed
+ detecting size */
+ if( id->ff_enc_c->width == 0 || id->ff_enc_c->height == 0 )
+ {
+ id->ff_enc_c->width = id->ff_dec_c->width;
+ id->ff_enc_c->height = id->ff_dec_c->height;
+ }
+
+ if( avcodec_open( id->ff_enc_c, id->ff_enc ) )
+ {
+ msg_Err( p_stream, "cannot open encoder" );
+ return VLC_EGENERIC;
+ }
+ id->b_enc_inited = VLC_TRUE;
+ }
+
+
+ /* deinterlace */
+ if( p_stream->p_sys->b_deinterlace )
+ {
+ if( id->p_ff_pic_tmp0 == NULL )
+ {
+ int i_size;
+ uint8_t *buf;
+ id->p_ff_pic_tmp0 = avcodec_alloc_frame();
+ i_size = avpicture_get_size( id->ff_dec_c->pix_fmt,
+ id->ff_dec_c->width, id->ff_dec_c->height );
+
+ buf = malloc( i_size );
+
+ avpicture_fill( (AVPicture*)id->p_ff_pic_tmp0, buf,
+ id->ff_enc_c->pix_fmt,
+ id->ff_dec_c->width, id->ff_dec_c->height );
+ }
+
+ avpicture_deinterlace( (AVPicture*)id->p_ff_pic_tmp0, (AVPicture*)frame,
+ id->ff_dec_c->pix_fmt,
+ id->ff_dec_c->width, id->ff_dec_c->height );
+
+ frame = id->p_ff_pic_tmp0;
+ }
+
+ /* convert pix format */
+ if( id->ff_dec_c->pix_fmt != id->ff_enc_c->pix_fmt )
+ {
+ if( id->p_ff_pic_tmp1 == NULL )
+ {
+ int i_size;
+ uint8_t *buf;
+ id->p_ff_pic_tmp1 = avcodec_alloc_frame();
+ i_size = avpicture_get_size( id->ff_enc_c->pix_fmt,
+ id->ff_dec_c->width, id->ff_dec_c->height );
+
+ buf = malloc( i_size );
+
+ avpicture_fill( (AVPicture*)id->p_ff_pic_tmp1, buf,
+ id->ff_enc_c->pix_fmt,
+ id->ff_dec_c->width, id->ff_dec_c->height );
+ }
+
+ img_convert( (AVPicture*)id->p_ff_pic_tmp1, id->ff_enc_c->pix_fmt,
+ (AVPicture*)frame, id->ff_dec_c->pix_fmt,
+ id->ff_dec_c->width, id->ff_dec_c->height );
+
+ frame = id->p_ff_pic_tmp1;
+ }
+
+ /* convert size and crop */
+ if( ( id->ff_dec_c->width != id->ff_enc_c->width ) ||
+ ( id->ff_dec_c->height != id->ff_enc_c->height ) )
+ {
+ if( id->p_ff_pic_tmp2 == NULL )
+ {
+ int i_size;
+ uint8_t *buf;
+ id->p_ff_pic_tmp2 = avcodec_alloc_frame();
+ i_size = avpicture_get_size( id->ff_enc_c->pix_fmt,
+ id->ff_enc_c->width, id->ff_enc_c->height );
+
+ buf = malloc( i_size );
+
+ avpicture_fill( (AVPicture*)id->p_ff_pic_tmp2, buf,
+ id->ff_enc_c->pix_fmt,
+ id->ff_enc_c->width, id->ff_enc_c->height );
+
+ id->p_vresample =
+ img_resample_full_init( id->ff_enc_c->width, id->ff_enc_c->height,
+ id->ff_dec_c->width, id->ff_dec_c->height,
+ p_stream->p_sys->i_crop_top,
+ p_stream->p_sys->i_crop_bottom,
+ p_stream->p_sys->i_crop_left,
+ p_stream->p_sys->i_crop_right );
+ }
+
+ img_resample( id->p_vresample, (AVPicture*)id->p_ff_pic_tmp2, (AVPicture*)frame );
+
+ frame = id->p_ff_pic_tmp2;
+ }
+
+ /* encode frame */
+ i_out = avcodec_encode_video( id->ff_enc_c, id->p_buffer, id->i_buffer, frame );
+
+ if( i_out > 0 )
+ {
+ sout_buffer_t *p_out;
+ p_out = sout_BufferNew( p_stream->p_sout, i_out );
+
+ memcpy( p_out->p_buffer, id->p_buffer, i_out );
+
+ p_out->i_size = i_out;
+ p_out->i_length = in->i_length;
+ p_out->i_dts = in->i_dts;
+ p_out->i_pts = in->i_dts; /* FIXME */
+
+ sout_BufferChain( out, p_out );
+ }
+
+ if( i_data <= 0 )
+ {
+ return VLC_SUCCESS;
+ }
+ }
+
+ return VLC_SUCCESS;
+}
+
* input_dec.c: Functions for the management of decoders
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: input_dec.c,v 1.59 2003/03/04 13:21:19 massiot Exp $
+ * $Id: input_dec.c,v 1.60 2003/04/13 20:00:21 fenrir Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
}
p_fifo->p_module = NULL;
- /* If we are in sout mode, search first for packetizer module then
- * codec to do transcoding */
+ /* If we are in sout mode, search for packetizer module */
psz_sout = config_GetPsz( p_input, "sout" );
- if( psz_sout != NULL && *psz_sout != 0 )
+ if( !p_es->b_force_decoder && psz_sout != NULL && *psz_sout != 0 )
{
vlc_bool_t b_sout = VLC_TRUE;
if( b_sout )
{
- vlc_bool_t b_reencode = VLC_FALSE;
-
- if( p_es->i_cat == AUDIO_ES )
- {
- char *psz_sout_acodec = config_GetPsz( p_input, "sout-acodec" );
- if( psz_sout_acodec != NULL && *psz_sout_acodec != '\0' )
- {
- msg_Dbg( p_input, "audio reencoding requested -> unsupported" );
- b_reencode = VLC_TRUE;
- }
- }
- else if( p_es->i_cat == VIDEO_ES )
- {
- char *psz_sout_vcodec = config_GetPsz( p_input, "sout-vcodec" );
- if( psz_sout_vcodec != NULL && *psz_sout_vcodec != '\0' )
- {
- msg_Dbg( p_input, "video reencoding requested" );
- /* force encoder video output */
- config_PutPsz( p_input, "vout", "encoder" );
- b_reencode = VLC_TRUE;
- }
- }
-
- if( !b_reencode )
- {
- /* we don't want to reencode so search for a packetizer */
- p_fifo->p_module =
- module_Need( p_fifo, "packetizer", "$packetizer" );
- }
- else
- {
- /* get a suitable decoder module to do reencoding*/
- p_fifo->p_module = module_Need( p_fifo, "decoder", "$codec" );
- }
+ p_fifo->p_module =
+ module_Need( p_fifo, "packetizer", "$packetizer" );
}
}
else
p_fifo->p_module = module_Need( p_fifo, "decoder", "$codec" );
}
+ if( psz_sout )
+ {
+ free( psz_sout );
+ }
+
if( p_fifo->p_module == NULL )
{
msg_Err( p_fifo, "no suitable decoder module for fourcc `%4.4s'.\nVLC probably does not support this sound or video format.",
* input_programs.c: es_descriptor_t, pgrm_descriptor_t management
*****************************************************************************
* Copyright (C) 1999-2002 VideoLAN
- * $Id: input_programs.c,v 1.103 2003/03/12 05:26:46 sam Exp $
+ * $Id: input_programs.c,v 1.104 2003/04/13 20:00:21 fenrir Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
p_es->i_demux_fd = 0;
p_es->c_packets = 0;
p_es->c_invalid_packets = 0;
+ p_es->b_force_decoder = VLC_FALSE;
if( i_data_len )
{
* stream_output.c : stream output module
*****************************************************************************
* Copyright (C) 2002 VideoLAN
- * $Id: stream_output.c,v 1.23 2003/03/31 03:46:11 fenrir Exp $
+ * $Id: stream_output.c,v 1.24 2003/04/13 20:00:21 fenrir Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Laurent Aimar <fenrir@via.ecp.fr>
/*****************************************************************************
* Local prototypes
*****************************************************************************/
-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 */
- 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;
-
-} sout_instance_sys_mux_t;
-#endif
-
-struct sout_instance_sys_t
-{
- int i_d_u_m_m_y;
-};
-
+static char *sout_stream_chain_to_str( char * );
/*
* 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_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; }
/*****************************************************************************
char * psz_dest )
{
sout_instance_t *p_sout;
- char *psz_dup, *psz_parser, *psz_pos;
- /* Allocate descriptor */
+ /* *** Allocate descriptor *** */
p_sout = vlc_object_create( p_parent, VLC_OBJECT_SOUT );
if( p_sout == NULL )
{
return NULL;
}
- p_sout->psz_sout = NULL;
-
- p_sout->i_nb_dest = 0;
- p_sout->ppsz_dest = NULL;
-
+ /* *** init descriptor *** */
+ p_sout->psz_sout = strdup( psz_dest );
p_sout->i_preheader = 0;
- p_sout->i_nb_mux = 0;
- p_sout->pp_mux = 0;
+ p_sout->p_sys = NULL;
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;
-
- while( ( psz_pos = strchr( psz_parser, '#' ) ) != NULL )
+ if( psz_dest && psz_dest[0] == '#' )
{
- *psz_pos++ = '\0';
-
- if( InstanceNewOutput( p_sout, psz_parser ) )
- {
- msg_Err( p_sout, "adding `%s' failed", psz_parser );
- }
-
- psz_parser = psz_pos;
+ p_sout->psz_chain = strdup( &psz_dest[1] );
}
-
- if( *psz_parser )
+ else
{
- if( InstanceNewOutput( p_sout, psz_parser ) )
- {
- msg_Err( p_sout, "adding `%s' failed", psz_parser );
- }
+ p_sout->psz_chain = sout_stream_chain_to_str( psz_dest );
}
- free( psz_dup );
+ p_sout->p_stream = sout_stream_new( p_sout, p_sout->psz_chain );
- if( p_sout->i_nb_dest <= 0 )
+ if( p_sout->p_stream == NULL )
{
- msg_Err( p_sout, "all sout failed" );
+ msg_Err( p_sout, "stream chained failed for `%s'", p_sout->psz_chain );
+
+ FREE( p_sout->psz_sout );
+ FREE( p_sout->psz_chain );
+
vlc_object_destroy( p_sout );
return( NULL );
}
*****************************************************************************/
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 );
+ FREE( p_sout->psz_chain );
- 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 feeling..." );
- }
+ sout_stream_delete( p_sout->p_stream );
vlc_mutex_destroy( &p_sout->lock );
- /* *** remove all muxer *** */
- for( i = 0; i < p_sout->i_nb_mux; i++ )
- {
- sout_access_out_t *p_access;
-#define p_mux p_sout->pp_mux[i]
-
- p_access = p_mux->p_access;
-
- MuxDelete( p_mux );
- sout_AccessOutDelete( p_access );
-#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 */
+ /* *** free structure *** */
vlc_object_destroy( p_sout );
}
-
-
/*****************************************************************************
- * InitInstance: opens appropriate modules
+ * Packetizer/Input
*****************************************************************************/
-static int InstanceNewOutput (sout_instance_t *p_sout, char *psz_dest )
+sout_packetizer_input_t *__sout_InputNew( vlc_object_t *p_this,
+ sout_format_t *p_fmt )
{
- 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 ? */
+ sout_instance_t *p_sout = NULL;
+ sout_packetizer_input_t *p_input;
- 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 - psz_dup == 1 )
- {
- msg_Warn( p_sout, "drive letter %c: found in source string",
- *psz_dup ) ;
- psz_parser = "";
- }
-#endif
+ int i_try;
- if( !*psz_parser )
- {
- psz_access = psz_mux = "";
- psz_name = psz_dup;
- }
- else
+ /* search an stream output */
+ for( i_try = 0; i_try < 12; i_try++ )
{
- *psz_parser++ = '\0';
-
- /* let's skip '//' */
- if( psz_parser[0] == '/' && psz_parser[1] == '/' )
+ p_sout = vlc_object_find( p_this, VLC_OBJECT_SOUT, FIND_ANYWHERE );
+ if( p_sout )
{
- psz_parser += 2 ;
+ break;
}
- psz_name = psz_parser ;
-
- /* Come back to parse the access and mux plug-ins */
- psz_parser = psz_dup;
+ msleep( 100*1000 );
+ msg_Dbg( p_this, "waiting for sout" );
+ }
- if( !*psz_parser )
- {
- /* No access */
- psz_access = "";
- }
- else if( *psz_parser == '/' )
- {
- /* No access */
- psz_access = "";
- psz_parser++;
- }
- else
- {
- psz_access = psz_parser;
+ if( !p_sout )
+ {
+ msg_Err( p_this, "cannot find any stream ouput" );
+ return( NULL );
+ }
- while( *psz_parser && *psz_parser != '/' )
- {
- psz_parser++;
- }
+ msg_Dbg( p_sout, "adding a new input" );
- if( *psz_parser == '/' )
- {
- *psz_parser++ = '\0';
- }
- }
+ /* *** create a packetizer input *** */
+ p_input = malloc( sizeof( sout_packetizer_input_t ) );
+ p_input->p_sout = p_sout;
+ p_input->p_fmt = p_fmt;
- if( !*psz_parser )
- {
- /* No mux */
- psz_mux = "";
- }
- else
- {
- psz_mux = psz_parser;
- }
+ if( p_fmt->i_fourcc == VLC_FOURCC( 'n', 'u', 'l', 'l' ) )
+ {
+ vlc_object_release( p_sout );
+ return p_input;
}
- msg_Dbg( p_sout, "access `%s', mux `%s', name `%s'",
- 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 );
-
+ /* *** add it to the stream chain */
vlc_mutex_lock( &p_sout->lock );
- /* *** create mux *** */
-
- if( InstanceMuxNew( p_sout, mrl.psz_way, mrl.psz_access, mrl.psz_name ) )
- {
- msg_Err( p_sout, "cannot create sout chain for %s/%s://%s",
- mrl.psz_access, mrl.psz_way, mrl.psz_name );
+ p_input->id = p_sout->p_stream->pf_add( p_sout->p_stream,
+ p_fmt );
+ vlc_mutex_unlock( &p_sout->lock );
- mrl_Clean( &mrl );
- vlc_mutex_unlock( &p_sout->lock );
- return( VLC_EGENERIC );
- }
- mrl_Clean( &mrl );
+ vlc_object_release( p_sout );
- /* *** finish all setup *** */
- if( p_sout->psz_sout )
- {
- 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
+ if( p_input->id == NULL )
{
- p_sout->psz_sout = strdup( psz_dest );
+ free( p_input );
+ return( 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 );
-
- msg_Dbg( p_sout, "complete sout `%s'", p_sout->psz_sout );
- return VLC_SUCCESS;
+ return( p_input );
}
-static int InstanceMuxNew ( sout_instance_t *p_sout,
- char *psz_mux, char *psz_access, char *psz_name )
+
+int sout_InputDelete( sout_packetizer_input_t *p_input )
{
- sout_access_out_t *p_access;
- sout_mux_t *p_mux;
+ sout_instance_t *p_sout = p_input->p_sout;
+
+ msg_Dbg( p_sout, "removing an input" );
- /* *** find and open appropriate access module *** */
- p_access =
- sout_AccessOutNew( p_sout, psz_access, psz_name );
- if( p_access == NULL )
+ if( p_input->p_fmt->i_fourcc != VLC_FOURCC( 'n', 'u', 'l', 'l' ) )
{
- msg_Err( p_sout, "no suitable sout access module for `%s/%s://%s'",
- psz_access, psz_mux, psz_name );
- return( VLC_EGENERIC );
+ vlc_mutex_lock( &p_sout->lock );
+ p_sout->p_stream->pf_del( p_sout->p_stream, p_input->id );
+ vlc_mutex_unlock( &p_sout->lock );
}
- /* *** find and open appropriate mux module *** */
- p_mux = MuxNew( p_sout, psz_mux, p_access );
- if( p_mux == NULL )
- {
- msg_Err( p_sout, "no suitable sout mux module for `%s/%s://%s'",
- psz_access, psz_mux, psz_name );
+ free( p_input );
- sout_AccessOutDelete( p_access );
- return( VLC_EGENERIC );
- }
+ return( VLC_SUCCESS);
+}
- 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 );
+int sout_InputSendBuffer( sout_packetizer_input_t *p_input, sout_buffer_t *p_buffer )
+{
+ sout_instance_t *p_sout = p_input->p_sout;
+
+ if( p_input->p_fmt->i_fourcc == VLC_FOURCC( 'n', 'u', 'l', 'l' ) )
+ {
+ sout_BufferDelete( p_input->p_sout, p_buffer );
+ return VLC_SUCCESS;
+ }
- return VLC_SUCCESS;
+ return( p_sout->p_stream->pf_send( p_sout->p_stream, p_input->id, p_buffer ) );
}
+
/*****************************************************************************
* sout_AccessOutNew: allocate a new access out
*****************************************************************************/
}
-
-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 * sout_MuxNew ( sout_instance_t *p_sout,
+ char *psz_mux,
+ sout_access_out_t *p_access )
{
sout_mux_t *p_mux;
return p_mux;
}
-static void MuxDelete ( sout_mux_t *p_mux )
+void sout_MuxDelete ( sout_mux_t *p_mux )
{
if( p_mux->p_module )
{
vlc_object_destroy( p_mux );
}
-static sout_input_t *MuxAddStream ( sout_mux_t *p_mux,
- sout_packet_format_t *p_format )
+sout_input_t *sout_MuxAddStream( sout_mux_t *p_mux,
+ sout_format_t *p_fmt )
{
sout_input_t *p_input;
}
msg_Dbg( p_mux, "adding a new input" );
+
/* create a new sout input */
- p_input = SoutInputCreate( p_mux->p_sout, p_format );
+ p_input = malloc( sizeof( sout_input_t ) );
+ p_input->p_sout = p_mux->p_sout;
+ p_input->p_fmt = p_fmt;
+ p_input->p_fifo = sout_FifoCreate( p_mux->p_sout );
+ p_input->p_sys = NULL;
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 );
+ sout_MuxDeleteStream( p_mux, p_input );
return( NULL );
}
return( p_input );
}
-static void MuxDeleteStream ( sout_mux_t *p_mux,
- sout_input_t *p_input )
+void sout_MuxDeleteStream ( sout_mux_t *p_mux,
+ sout_input_t *p_input )
{
int i_index;
msg_Warn( p_mux, "no more input stream for this mux" );
}
- SoutInputDestroy( p_mux->p_sout, p_input );
+ sout_FifoDestroy( p_mux->p_sout, p_input->p_fifo );
+ free( p_input );
}
}
-static void MuxSendBuffer ( sout_mux_t *p_mux,
- sout_input_t *p_input,
- sout_buffer_t *p_buffer )
+void sout_MuxSendBuffer ( sout_mux_t *p_mux,
+ sout_input_t *p_input,
+ sout_buffer_t *p_buffer )
{
sout_FifoPut( p_input->p_fifo, p_buffer );
p_mux->pf_mux( p_mux );
}
-/*****************************************************************************
- *
- *****************************************************************************/
-sout_packetizer_input_t *__sout_InputNew( vlc_object_t *p_this,
- sout_packet_format_t *p_format )
-{
- sout_instance_t *p_sout = NULL;
- 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++ )
- {
- p_sout = vlc_object_find( p_this, VLC_OBJECT_SOUT, FIND_ANYWHERE );
- if( !p_sout )
- {
- msleep( 100*1000 );
- msg_Dbg( p_this, "waiting for sout" );
- }
- else
- {
- break;
- }
- }
-
- if( !p_sout )
- {
- msg_Err( p_this, "cannot find any stream ouput" );
- return( NULL );
- }
- msg_Dbg( p_sout, "adding a new input" );
-
- /* *** create a packetizer input *** */
- p_input = malloc( sizeof( sout_packetizer_input_t ) );
- p_input->p_sout = p_sout;
- 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 ) );
-
- if( p_format->i_fourcc == VLC_FOURCC( 'n', 'u', 'l', 'l' ) )
- {
- vlc_object_release( p_sout );
- return p_input;
- }
-
- vlc_mutex_lock( &p_sout->lock );
- /* *** add this input to all muxers *** */
- for( i_mux = 0; i_mux < p_sout->i_nb_mux; i_mux++ )
- {
- 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 )
- {
- 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
- }
-
- if( !b_accepted )
- {
- /* all muxer refuse this stream, so delete it */
- free( p_input );
-
- vlc_mutex_unlock( &p_sout->lock );
- 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 );
-
- return( 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 );
-
- /* *** remove this input to all muxers *** */
- for( i_input = 0; i_input < p_input->i_nb_inputs; i_input++ )
- {
- MuxDeleteStream( p_input->pp_mux[i_input], p_input->pp_inputs[i_input] );
- }
-
- TAB_REMOVE( p_sout->i_nb_inputs, p_sout->pp_inputs, p_input );
-
- 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_packetizer_input_t *p_input, sout_buffer_t *p_buffer )
-{
-// 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' ) &&
- p_input->i_nb_inputs > 0 )
- {
- int i;
-
- vlc_mutex_lock( &p_input->p_sout->lock );
- for( i = 0; i < p_input->i_nb_inputs - 1; i++ )
- {
- 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 );
- }
- 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 );
-}
sout_fifo_t *sout_FifoCreate( sout_instance_t *p_sout )
{
}
}
-#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 = strdup( psz_mrl );
}
}
-#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 );
}
+/****************************************************************************
+ ****************************************************************************
+ **
+ **
+ **
+ ****************************************************************************
+ ****************************************************************************/
+
+/* create a complete chain */
+/* chain format:
+ module{option=*:option=*}[:module{option=*:...}]
+ */
+
+static char *_strndup( char *str, int i_len )
+{
+ char *p;
+
+ p = malloc( i_len + 1 );
+ strncpy( p, str, i_len );
+ p[i_len] = '\0';
+
+ return( p );
+}
+
+/*
+ * parse module{options=str, option="str "}:
+ * return a pointer on the rest
+ * XXX: psz_chain is modified
+ */
+#define SKIPSPACE( p ) { while( *p && ( *p == ' ' || *p == '\t' ) ) p++; }
+/* go accross " " and { } */
+static char *_get_chain_end( char *str )
+{
+ char *p = str;
+
+ SKIPSPACE( p );
+
+ for( ;; )
+ {
+ if( *p == '{' || *p == '"' || *p == '\'')
+ {
+ char c;
+
+ if( *p == '{' )
+ {
+ c = '}';
+ }
+ else
+ {
+ c = *p;
+ }
+ p++;
+
+ for( ;; )
+ {
+ if( *p == '\0' )
+ {
+ return p;
+ }
+
+ if( *p == c )
+ {
+ p++;
+ return p;
+ }
+ else if( *p == '{' && c == '}' )
+ {
+ p = _get_chain_end( p );
+ }
+ else
+ {
+ p++;
+ }
+ }
+ }
+ else if( *p == '\0' || *p == ',' || *p == '}' || *p == ' ' || *p == '\t' )
+ {
+ return p;
+ }
+ else
+ {
+ p++;
+ }
+ }
+}
+
+char * sout_cfg_parser( char **ppsz_name, sout_cfg_t **pp_cfg, char *psz_chain )
+{
+ sout_cfg_t *p_cfg = NULL;
+ char *p = psz_chain;
+
+ *ppsz_name = NULL;
+ *pp_cfg = NULL;
+
+ SKIPSPACE( p );
+
+ while( *p && *p != '{' && *p != ':' && *p != ' ' && *p != '\t' )
+ {
+ p++;
+ }
+
+ if( p == psz_chain )
+ {
+ return NULL;
+ }
+
+ *ppsz_name = _strndup( psz_chain, p - psz_chain );
+
+ //fprintf( stderr, "name=%s - rest=%s\n", *ppsz_name, p );
+
+ SKIPSPACE( p );
+
+ if( *p == '{' )
+ {
+ char *psz_name;
+
+ p++;
+
+ for( ;; )
+ {
+ sout_cfg_t cfg;
+
+ SKIPSPACE( p );
+
+ psz_name = p;
+
+ while( *p && *p != '=' && *p != ',' && *p != '}' && *p != ' ' && *p != '\t' )
+ {
+ p++;
+ }
+
+ //fprintf( stderr, "name=%s - rest=%s\n", psz_name, p );
+ if( p == psz_name )
+ {
+ fprintf( stderr, "invalid options (empty)" );
+ break;
+ }
+
+ cfg.psz_name = _strndup( psz_name, p - psz_name );
+
+ SKIPSPACE( p );
+
+ if( *p == '=' )
+ {
+ char *end;
+
+ p++;
+#if 0
+ SKIPSPACE( p );
+
+ if( *p == '"' )
+ {
+ char *end;
+
+ p++;
+ end = strchr( p, '"' );
+
+ if( end )
+ {
+// fprintf( stderr, "##%s -- %s\n", p, end );
+ cfg.psz_value = _strndup( p, end - p );
+ p = end + 1;
+ }
+ else
+ {
+ cfg.psz_value = strdup( p );
+ p += strlen( p );
+ }
+
+ }
+ else
+ {
+ psz_value = p;
+ while( *p && *p != ',' && *p != '}' && *p != ' ' && *p != '\t' )
+ {
+ p++;
+ }
+ cfg.psz_value = _strndup( psz_value, p - psz_value );
+ }
+#endif
+ end = _get_chain_end( p );
+ if( end <= p )
+ {
+ cfg.psz_value = NULL;
+ }
+ else
+ {
+ if( *p == '\'' || *p =='"' || *p == '{' )
+ {
+ p++;
+ end--;
+ }
+ if( end <= p )
+ {
+ cfg.psz_value = NULL;
+ }
+ else
+ {
+ cfg.psz_value = _strndup( p, end - p );
+ }
+ }
+
+ p = end;
+ SKIPSPACE( p );
+ }
+ else
+ {
+ cfg.psz_value = NULL;
+ }
+
+ cfg.p_next = NULL;
+ if( p_cfg )
+ {
+ p_cfg->p_next = malloc( sizeof( sout_cfg_t ) );
+ memcpy( p_cfg->p_next, &cfg, sizeof( sout_cfg_t ) );
+
+ p_cfg = p_cfg->p_next;
+ }
+ else
+ {
+ p_cfg = malloc( sizeof( sout_cfg_t ) );
+ memcpy( p_cfg, &cfg, sizeof( sout_cfg_t ) );
+
+ *pp_cfg = p_cfg;
+ }
+
+ if( *p == ',' )
+ {
+ p++;
+ }
+
+ if( *p == '}' )
+ {
+ p++;
+
+ break;
+ }
+ }
+ }
+
+ if( *p == ':' )
+ {
+ return( strdup( p + 1 ) );
+ }
+
+ return( NULL );
+}
+
+
+
+
+
+/*
+ * XXX name and p_cfg are used (-> do NOT free them)
+ */
+sout_stream_t *sout_stream_new( sout_instance_t *p_sout,
+ char *psz_chain )
+{
+ sout_stream_t *p_stream;
+
+ p_stream = vlc_object_create( p_sout, sizeof( sout_stream_t ) );
+
+ if( !p_stream )
+ {
+ msg_Err( p_sout, "out of memory" );
+ return NULL;
+ }
+
+ p_stream->p_sout = p_sout;
+ p_stream->p_sys = NULL;
+
+ p_stream->psz_next = sout_cfg_parser( &p_stream->psz_name, &p_stream->p_cfg, psz_chain);
+ msg_Dbg( p_sout, "stream=`%s'", p_stream->psz_name );
+
+ p_stream->p_module =
+ module_Need( p_stream, "sout stream", p_stream->psz_name );
+
+ if( !p_stream->p_module )
+ {
+ /* FIXME */
+ vlc_object_destroy( p_stream );
+ return NULL;
+ }
+
+ return p_stream;
+}
+
+void sout_stream_delete( sout_stream_t *p_stream )
+{
+ sout_cfg_t *p_cfg;
+
+ msg_Dbg( p_stream, "destroying chain... (name=%s)", p_stream->psz_name );
+ module_Unneed( p_stream, p_stream->p_module );
+
+ FREE( p_stream->psz_name );
+ FREE( p_stream->psz_next );
+
+ p_cfg = p_stream->p_cfg;
+ while( p_cfg != NULL )
+ {
+ sout_cfg_t *p_next;
+
+ p_next = p_cfg->p_next;
+
+ FREE( p_cfg->psz_name );
+ FREE( p_cfg->psz_value );
+ free( p_cfg );
+
+ p_cfg = p_next;
+ }
+
+ msg_Dbg( p_stream, "destroying chain done" );
+ vlc_object_destroy( p_stream );
+}
+
+static char *sout_stream_chain_to_str( char *psz_url )
+{
+ mrl_t mrl;
+ char *psz_chain;
+
+ mrl_Parse( &mrl, psz_url );
+
+ psz_chain = malloc( 100 + strlen( mrl.psz_way ) + strlen( mrl.psz_access ) + strlen( mrl.psz_name ) );
+
+ sprintf( psz_chain, "std{mux=%s,access=%s,url=\"%s\"", mrl.psz_way, mrl.psz_access, mrl.psz_name );
+
+ return( psz_chain );
+}