Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

es.c

00001 /*****************************************************************************
00002  * es.c: Elementary stream output module
00003  *****************************************************************************
00004  * Copyright (C) 2003-2004 the VideoLAN team
00005  * $Id: es.c 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Laurent Aimar <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00024 /*****************************************************************************
00025  * Preamble
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  * Module descriptor
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  * Exported prototypes
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  * Open:
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  * Close:
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     /* *** get access name *** */
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     /* *** get mux name *** */
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     /* Get url (%d expanded as a codec count, %c expanded as codec fcc ) */
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     /* *** find and open appropriate access module *** */
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     /* *** find and open appropriate mux module *** */
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 

Generated on Tue Dec 20 10:14:49 2005 for vlc-0.8.4a by  doxygen 1.4.2