00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdlib.h>
00028 #include <string.h>
00029
00030 #include <vlc/vlc.h>
00031 #include <vlc/input.h>
00032 #include <vlc/sout.h>
00033
00034
00035
00036
00037 #define ACCESS_TEXT N_("Output access method")
00038 #define ACCESS_LONGTEXT N_( \
00039 "Allows you to specify the output access method used for the streaming " \
00040 "output." )
00041 #define ACCESSA_TEXT N_("Audio output access method")
00042 #define ACCESSA_LONGTEXT N_( \
00043 "Allows you to specify the output access method used for the audio " \
00044 "streaming output." )
00045 #define ACCESSV_TEXT N_("Video output access method")
00046 #define ACCESSV_LONGTEXT N_( \
00047 "Allows you to specify the output access method used for the video " \
00048 "streaming output." )
00049
00050 #define MUX_TEXT N_("Output muxer")
00051 #define MUX_LONGTEXT N_( \
00052 "Allows you to specify the muxer used for the streaming output." )
00053 #define MUXA_TEXT N_("Audio output muxer")
00054 #define MUXA_LONGTEXT N_( \
00055 "Allows you to specify the muxer used for the audio streaming output." )
00056 #define MUXV_TEXT N_("Video output muxer")
00057 #define MUXV_LONGTEXT N_( \
00058 "Allows you to specify the muxer used for the video streaming output." )
00059
00060 #define DEST_TEXT N_("Output URL")
00061 #define DEST_LONGTEXT N_( \
00062 "Allows you to specify the output URL used for the streaming output." )
00063 #define DESTA_TEXT N_("Audio output URL")
00064 #define DESTA_LONGTEXT N_( \
00065 "Allows you to specify the output URL used for the audio streaming " \
00066 "output." )
00067 #define DESTV_TEXT N_("Video output URL")
00068 #define DESTV_LONGTEXT N_( \
00069 "Allows you to specify the output URL used for the video streaming " \
00070 "output." )
00071
00072 static int Open ( vlc_object_t * );
00073 static void Close ( vlc_object_t * );
00074
00075 #define SOUT_CFG_PREFIX "sout-es-"
00076
00077 vlc_module_begin();
00078 set_shortname( "ES" );
00079 set_description( _("Elementary stream output") );
00080 set_capability( "sout stream", 50 );
00081 add_shortcut( "es" );
00082 set_category( CAT_SOUT );
00083 set_subcategory( SUBCAT_SOUT_STREAM );
00084
00085 add_string( SOUT_CFG_PREFIX "access", "", NULL, ACCESS_TEXT,
00086 ACCESS_LONGTEXT, VLC_TRUE );
00087 add_string( SOUT_CFG_PREFIX "access-audio", "", NULL, ACCESSA_TEXT,
00088 ACCESSA_LONGTEXT, VLC_TRUE );
00089 add_string( SOUT_CFG_PREFIX "access-video", "", NULL, ACCESSV_TEXT,
00090 ACCESSV_LONGTEXT, VLC_TRUE );
00091
00092 add_string( SOUT_CFG_PREFIX "mux", "", NULL, MUX_TEXT,
00093 MUX_LONGTEXT, VLC_TRUE );
00094 add_string( SOUT_CFG_PREFIX "mux-audio", "", NULL, MUXA_TEXT,
00095 MUXA_LONGTEXT, VLC_TRUE );
00096 add_string( SOUT_CFG_PREFIX "mux-video", "", NULL, MUXV_TEXT,
00097 MUXV_LONGTEXT, VLC_TRUE );
00098
00099 add_string( SOUT_CFG_PREFIX "dst", "", NULL, DEST_TEXT,
00100 DEST_LONGTEXT, VLC_TRUE );
00101 add_string( SOUT_CFG_PREFIX "dst-audio", "", NULL, DESTA_TEXT,
00102 DESTA_LONGTEXT, VLC_TRUE );
00103 add_string( SOUT_CFG_PREFIX "dst-video", "", NULL, DESTV_TEXT,
00104 DESTV_LONGTEXT, VLC_TRUE );
00105
00106 set_callbacks( Open, Close );
00107 vlc_module_end();
00108
00109
00110 #define FREE( p ) if( p ) { free( p ); (p) = NULL; }
00111
00112
00113
00114 static const char *ppsz_sout_options[] = {
00115 "access", "access-audio", "access-video",
00116 "mux", "mux-audio", "mux-video",
00117 "dst", "dst-audio", "dst-video",
00118 NULL
00119 };
00120
00121 static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
00122 static int Del ( sout_stream_t *, sout_stream_id_t * );
00123 static int Send( sout_stream_t *, sout_stream_id_t *, block_t* );
00124
00125 struct sout_stream_sys_t
00126 {
00127 int i_count_audio;
00128 int i_count_video;
00129 int i_count;
00130
00131 char *psz_mux;
00132 char *psz_mux_audio;
00133 char *psz_mux_video;
00134
00135 char *psz_access;
00136 char *psz_access_audio;
00137 char *psz_access_video;
00138
00139 char *psz_dst;
00140 char *psz_dst_audio;
00141 char *psz_dst_video;
00142 };
00143
00144
00145
00146
00147 static int Open( vlc_object_t *p_this )
00148 {
00149 sout_stream_t *p_stream = (sout_stream_t*)p_this;
00150 sout_stream_sys_t *p_sys;
00151 vlc_value_t val;
00152
00153 sout_CfgParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options, p_stream->p_cfg );
00154 p_sys = malloc( sizeof( sout_stream_sys_t ) );
00155
00156 p_sys->i_count = 0;
00157 p_sys->i_count_audio = 0;
00158 p_sys->i_count_video = 0;
00159
00160 var_Get( p_stream, SOUT_CFG_PREFIX "access", &val );
00161 p_sys->psz_access = val.psz_string;
00162 var_Get( p_stream, SOUT_CFG_PREFIX "access-audio", &val );
00163 p_sys->psz_access_audio = val.psz_string;
00164 var_Get( p_stream, SOUT_CFG_PREFIX "access-video", &val );
00165 p_sys->psz_access_video = val.psz_string;
00166
00167 var_Get( p_stream, SOUT_CFG_PREFIX "mux", &val );
00168 p_sys->psz_mux = val.psz_string;
00169 var_Get( p_stream, SOUT_CFG_PREFIX "mux-audio", &val );
00170 p_sys->psz_mux_audio = val.psz_string;
00171 var_Get( p_stream, SOUT_CFG_PREFIX "mux-video", &val );
00172 p_sys->psz_mux_video = val.psz_string;
00173
00174 var_Get( p_stream, SOUT_CFG_PREFIX "dst", &val );
00175 p_sys->psz_dst = val.psz_string;
00176 var_Get( p_stream, SOUT_CFG_PREFIX "dst-audio", &val );
00177 p_sys->psz_dst_audio = val.psz_string;
00178 var_Get( p_stream, SOUT_CFG_PREFIX "dst-video", &val );
00179 p_sys->psz_dst_video = val.psz_string;
00180
00181 p_stream->pf_add = Add;
00182 p_stream->pf_del = Del;
00183 p_stream->pf_send = Send;
00184
00185 p_stream->p_sys = p_sys;
00186
00187 return VLC_SUCCESS;
00188 }
00189
00190
00191
00192
00193
00194 static void Close( vlc_object_t * p_this )
00195 {
00196 sout_stream_t *p_stream = (sout_stream_t*)p_this;
00197 sout_stream_sys_t *p_sys = p_stream->p_sys;
00198
00199 free( p_sys->psz_access );
00200 free( p_sys->psz_access_audio );
00201 free( p_sys->psz_access_video );
00202
00203 free( p_sys->psz_mux );
00204 free( p_sys->psz_mux_audio );
00205 free( p_sys->psz_mux_video );
00206
00207 free( p_sys->psz_dst );
00208 free( p_sys->psz_dst_audio );
00209 free( p_sys->psz_dst_video );
00210
00211 free( p_sys );
00212 }
00213
00214 struct sout_stream_id_t
00215 {
00216 sout_input_t *p_input;
00217 sout_mux_t *p_mux;
00218 };
00219
00220 static char * es_print_url( char *psz_fmt, vlc_fourcc_t i_fourcc, int i_count,
00221 char *psz_access, char *psz_mux )
00222 {
00223 char *psz_dst, *p;
00224
00225 if( psz_fmt == NULL || !*psz_fmt )
00226 {
00227 psz_fmt = "stream-%n-%c.%m";
00228 }
00229
00230 p = psz_dst = malloc( 4096 );
00231 memset( p, 0, 4096 );
00232 for( ;; )
00233 {
00234 if( *psz_fmt == '\0' )
00235 {
00236 *p = '\0';
00237 break;
00238 }
00239
00240 if( *psz_fmt != '%' )
00241 {
00242 *p++ = *psz_fmt++;
00243 }
00244 else
00245 {
00246 if( psz_fmt[1] == 'n' )
00247 {
00248 p += sprintf( p, "%d", i_count );
00249 }
00250 else if( psz_fmt[1] == 'c' )
00251 {
00252 p += sprintf( p, "%4.4s", (char*)&i_fourcc );
00253 }
00254 else if( psz_fmt[1] == 'm' )
00255 {
00256 p += sprintf( p, "%s", psz_mux );
00257 }
00258 else if( psz_fmt[1] == 'a' )
00259 {
00260 p += sprintf( p, "%s", psz_access );
00261 }
00262 else if( psz_fmt[1] != '\0' )
00263 {
00264 p += sprintf( p, "%c%c", psz_fmt[0], psz_fmt[1] );
00265 }
00266 else
00267 {
00268 p += sprintf( p, "%c", psz_fmt[0] );
00269 *p++ = '\0';
00270 break;
00271 }
00272 psz_fmt += 2;
00273 }
00274 }
00275
00276 return( psz_dst );
00277 }
00278
00279 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
00280 {
00281 sout_stream_sys_t *p_sys = p_stream->p_sys;
00282 sout_instance_t *p_sout = p_stream->p_sout;
00283 sout_stream_id_t *id;
00284
00285 char *psz_access;
00286 char *psz_mux;
00287 char *psz_dst;
00288
00289 sout_access_out_t *p_access;
00290 sout_mux_t *p_mux;
00291
00292
00293 if( p_fmt->i_cat == AUDIO_ES && p_sys->psz_access_audio && *p_sys->psz_access_audio )
00294 {
00295 psz_access = p_sys->psz_access_audio;
00296 }
00297 else if( p_fmt->i_cat == VIDEO_ES && p_sys->psz_access_video && *p_sys->psz_access_video )
00298 {
00299 psz_access = p_sys->psz_access_video;
00300 }
00301 else
00302 {
00303 psz_access = p_sys->psz_access;
00304 }
00305
00306
00307 if( p_fmt->i_cat == AUDIO_ES && p_sys->psz_mux_audio && *p_sys->psz_mux_audio )
00308 {
00309 psz_mux = p_sys->psz_mux_audio;
00310 }
00311 else if( p_fmt->i_cat == VIDEO_ES && p_sys->psz_mux_video && *p_sys->psz_mux_video )
00312 {
00313 psz_mux = p_sys->psz_mux_video;
00314 }
00315 else
00316 {
00317 psz_mux = p_sys->psz_mux;
00318 }
00319
00320
00321 if( p_fmt->i_cat == AUDIO_ES && p_sys->psz_dst_audio && *p_sys->psz_dst_audio )
00322 {
00323 psz_dst = es_print_url( p_sys->psz_dst_audio, p_fmt->i_codec,
00324 p_sys->i_count_audio, psz_access, psz_mux );
00325 }
00326 else if( p_fmt->i_cat == VIDEO_ES && p_sys->psz_dst_video && *p_sys->psz_dst_video )
00327 {
00328 psz_dst = es_print_url( p_sys->psz_dst_video, p_fmt->i_codec,
00329 p_sys->i_count_video, psz_access, psz_mux );
00330 }
00331 else
00332 {
00333 int i_count;
00334 if( p_fmt->i_cat == VIDEO_ES )
00335 {
00336 i_count = p_sys->i_count_video;
00337 }
00338 else if( p_fmt->i_cat == AUDIO_ES )
00339 {
00340 i_count = p_sys->i_count_audio;
00341 }
00342 else
00343 {
00344 i_count = p_sys->i_count;
00345 }
00346
00347 psz_dst = es_print_url( p_sys->psz_dst, p_fmt->i_codec,
00348 i_count, psz_access, psz_mux );
00349 }
00350
00351 p_sys->i_count++;
00352 if( p_fmt->i_cat == VIDEO_ES )
00353 {
00354 p_sys->i_count_video++;
00355 }
00356 else if( p_fmt->i_cat == AUDIO_ES )
00357 {
00358 p_sys->i_count_audio++;
00359 }
00360 msg_Dbg( p_stream, "creating `%s/%s://%s'",
00361 psz_access, psz_mux, psz_dst );
00362
00363
00364 p_access = sout_AccessOutNew( p_sout, psz_access, psz_dst );
00365 if( p_access == NULL )
00366 {
00367 msg_Err( p_stream, "no suitable sout access module for `%s/%s://%s'",
00368 psz_access, psz_mux, psz_dst );
00369 return( NULL );
00370 }
00371
00372
00373 p_mux = sout_MuxNew( p_sout, psz_mux, p_access );
00374 if( p_mux == NULL )
00375 {
00376 msg_Err( p_stream, "no suitable sout mux module for `%s/%s://%s'",
00377 psz_access, psz_mux, psz_dst );
00378 sout_AccessOutDelete( p_access );
00379 return( NULL );
00380 }
00381
00382 id = malloc( sizeof( sout_stream_id_t ) );
00383 id->p_mux = p_mux;
00384 id->p_input = sout_MuxAddStream( p_mux, p_fmt );
00385
00386 if( id->p_input == NULL )
00387 {
00388 free( id );
00389
00390 sout_MuxDelete( p_mux );
00391 sout_AccessOutDelete( p_access );
00392 free( id );
00393 return NULL;
00394 }
00395
00396 return id;
00397 }
00398
00399 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
00400 {
00401 sout_access_out_t *p_access = id->p_mux->p_access;
00402
00403 sout_MuxDeleteStream( id->p_mux, id->p_input );
00404 sout_AccessOutDelete( p_access );
00405
00406 free( id );
00407 return VLC_SUCCESS;
00408 }
00409
00410 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
00411 block_t *p_buffer )
00412 {
00413 sout_MuxSendBuffer( id->p_mux, id->p_input, p_buffer );
00414
00415 return VLC_SUCCESS;
00416 }
00417