]> git.sesse.net Git - vlc/blobdiff - modules/stream_out/record.c
Win32: prepare for Dshow freq and video standard options
[vlc] / modules / stream_out / record.c
index ebd84300300d336762564fd8f107b3adc25b37f3..4f8255f73f92f34597739803eb37d92858026921 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * record.c: record stream output module
  *****************************************************************************
- * Copyright (C) 2008 the VideoLAN team
+ * Copyright (C) 2008-2009 the VideoLAN team
  * $Id$
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
@@ -35,7 +35,8 @@
 #include <vlc_plugin.h>
 #include <vlc_block.h>
 #include <vlc_sout.h>
-#include <vlc_charset.h>
+#include <vlc_fs.h>
+#include <assert.h>
 
 /*****************************************************************************
  * Exported prototypes
@@ -48,23 +49,24 @@ static void     Close   ( vlc_object_t * );
  *****************************************************************************/
 #define DST_PREFIX_TEXT N_("Destination prefix")
 #define DST_PREFIX_LONGTEXT N_( \
-       "Prefix of the destination file automatically generated" )
+    "Prefix of the destination file automatically generated" )
 
 #define SOUT_CFG_PREFIX "sout-record-"
 
-vlc_module_begin();
-    set_description( N_("Record stream output") );
-    set_capability( "sout stream", 0 );
-    add_shortcut( "record" );
+vlc_module_begin ()
+    set_description( N_("Record stream output") )
+    set_capability( "sout stream", 0 )
+    add_shortcut( "record" )
+    set_shortname( N_("Record") )
 
-    set_category( CAT_SOUT );
-    set_subcategory( SUBCAT_SOUT_STREAM );
+    set_category( CAT_SOUT )
+    set_subcategory( SUBCAT_SOUT_STREAM )
 
-       add_string( SOUT_CFG_PREFIX "dst-prefix", "", NULL, DST_PREFIX_TEXT,
-                DST_PREFIX_LONGTEXT, true );
+    add_string( SOUT_CFG_PREFIX "dst-prefix", "", NULL, DST_PREFIX_TEXT,
+                DST_PREFIX_LONGTEXT, true )
 
-    set_callbacks( Open, Close );
-vlc_module_end();
+    set_callbacks( Open, Close )
+vlc_module_end ()
 
 /* */
 static const char *const ppsz_sout_options[] = {
@@ -93,7 +95,7 @@ struct sout_stream_id_t
 
 struct sout_stream_sys_t
 {
-       char *psz_prefix;
+    char *psz_prefix;
 
     sout_stream_t *p_out;
 
@@ -119,23 +121,23 @@ static void OutputSend( sout_stream_t *p_stream, sout_stream_id_t *id, block_t *
 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_stream_sys_t *p_sys;
 
     p_stream->pf_add    = Add;
     p_stream->pf_del    = Del;
     p_stream->pf_send   = Send;
 
     p_stream->p_sys = p_sys = malloc( sizeof(*p_sys) );
-       if( !p_sys )
-               return VLC_ENOMEM;
+    if( !p_sys )
+        return VLC_ENOMEM;
 
-       config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options, p_stream->p_cfg );
+    config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options, p_stream->p_cfg );
 
     p_sys->p_out = NULL;
-       p_sys->psz_prefix = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "dst-prefix" );
-       if( !p_sys->psz_prefix  )
+    p_sys->psz_prefix = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "dst-prefix" );
+    if( !p_sys->psz_prefix  )
     {
-               p_sys->psz_prefix = strdup( "sout-record-" );
+        p_sys->psz_prefix = strdup( "sout-record-" );
         if( !p_sys->psz_prefix )
         {
             free( p_sys );
@@ -146,11 +148,11 @@ static int Open( vlc_object_t *p_this )
     p_sys->i_date_start = -1;
     p_sys->i_size = 0;
 #ifdef OPTIMIZE_MEMORY
-    p_sys->i_max_wait = 5*1000000; /* 5s */
-    p_sys->i_max_size = 1*1000000; /* 1 Mbyte */
+    p_sys->i_max_wait = 5*CLOCK_FREQ; /* 5s */
+    p_sys->i_max_size = 1*1024*1024; /* 1 MiB */
 #else
-    p_sys->i_max_wait = 30*1000000; /* 30s */
-    p_sys->i_max_size = 20*1000000; /* 20 Mbyte */
+    p_sys->i_max_wait = 30*CLOCK_FREQ; /* 30s */
+    p_sys->i_max_size = 20*1024*1024; /* 20 MiB */
 #endif
     p_sys->b_drop = false;
     p_sys->i_dts_start = 0;
@@ -164,15 +166,15 @@ static int Open( vlc_object_t *p_this )
  *****************************************************************************/
 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_t *p_stream = (sout_stream_t*)p_this;
+    sout_stream_sys_t *p_sys = p_stream->p_sys;
 
     if( p_sys->p_out )
-        sout_StreamDelete( p_sys->p_out );
+        sout_StreamChainDelete( p_sys->p_out, p_sys->p_out );
 
     TAB_CLEAN( p_sys->i_id, p_sys->id );
-       free( p_sys->psz_prefix );
-       free( p_sys );
+    free( p_sys->psz_prefix );
+    free( p_sys );
 }
 
 /*****************************************************************************
@@ -180,7 +182,7 @@ static void Close( vlc_object_t * p_this )
  *****************************************************************************/
 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
 {
-       sout_stream_sys_t *p_sys = p_stream->p_sys;
+    sout_stream_sys_t *p_sys = p_stream->p_sys;
     sout_stream_id_t *id;
 
     id = malloc( sizeof(*id) );
@@ -201,18 +203,20 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
 
 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
 {
-       sout_stream_sys_t *p_sys = p_stream->p_sys;
+    sout_stream_sys_t *p_sys = p_stream->p_sys;
 
     if( !p_sys->p_out )
         OutputStart( p_stream );
 
     if( id->p_first )
         block_ChainRelease( id->p_first );
-    es_format_Clean( &id->fmt );
 
+    assert( !id->id || p_sys->p_out );
     if( id->id )
         sout_StreamIdDel( p_sys->p_out, id->id );
 
+    es_format_Clean( &id->fmt );
+
     TAB_REMOVE( p_sys->i_id, p_sys->id, id );
 
     if( p_sys->i_id <= 0 )
@@ -229,7 +233,7 @@ static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
                  block_t *p_buffer )
 {
-       sout_stream_sys_t *p_sys = p_stream->p_sys;
+    sout_stream_sys_t *p_sys = p_stream->p_sys;
 
     if( p_sys->i_date_start < 0 )
         p_sys->i_date_start = mdate();
@@ -237,7 +241,7 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
         ( mdate() - p_sys->i_date_start > p_sys->i_max_wait ||
           p_sys->i_size > p_sys->i_max_size ) )
     {
-        msg_Dbg( p_stream, "Staring recording, waited %ds and %dbyte",
+        msg_Dbg( p_stream, "Starting recording, waited %ds and %dbyte",
                  (int)((mdate() - p_sys->i_date_start)/1000000), (int)p_sys->i_size );
         OutputStart( p_stream );
     }
@@ -263,37 +267,36 @@ typedef struct
  * Do not do non native and non standard association !
  * Muxer will be probe if no entry found */
 static const muxer_properties_t p_muxers[] = {
-    M( "raw", "mp3", 1,         VLC_FOURCC('m','p','g','a') ),
-    M( "raw", "a52", 1,         VLC_FOURCC('a','5','2',' ') ),
-    M( "raw", "dts", 1,         VLC_FOURCC('d','t','s',' ') ),
-    M( "raw", "mpc", 1,         VLC_FOURCC('m','p','c',' ') ),
-    M( "raw", "ape", 1,         VLC_FOURCC('A','P','E',' ') ),
+    M( "raw", "mp3", 1,         VLC_CODEC_MPGA ),
+    M( "raw", "a52", 1,         VLC_CODEC_A52 ),
+    M( "raw", "dts", 1,         VLC_CODEC_DTS ),
+    M( "raw", "mpc", 1,         VLC_CODEC_MUSEPACK7, VLC_CODEC_MUSEPACK8 ),
+    M( "raw", "ape", 1,         VLC_CODEC_APE ),
 
-    M( "wav", "wav", 1,         VLC_FOURCC('a','r','a','w'), VLC_FOURCC('u','8',' ',' '), VLC_FOURCC('s','1','6','l'),
-                                VLC_FOURCC('s','2','4','l'), VLC_FOURCC('s','3','2','l'), VLC_FOURCC('f','l','3','2') ), 
+    M( "wav", "wav", 1,         VLC_CODEC_U8,   VLC_CODEC_S16L,
+                                VLC_CODEC_S24L, VLC_CODEC_S32L, VLC_CODEC_FL32 ),
 
-    //M( "ffmpeg{mux=flac}", "flac", 1, VLC_FOURCC('f','l','a','c') ), BROKEN
+    //M( "ffmpeg{mux=flac}", "flac", 1, VLC_CODEC_FLAC ), BROKEN
 
-    M( "ogg", "ogg", INT_MAX,   VLC_FOURCC('v','o','r','b'), VLC_FOURCC('s','p','x',' '), VLC_FOURCC('f','l','a','c'),
-                                VLC_FOURCC('s','u','b','t'), VLC_FOURCC('t','h','e','o'), VLC_FOURCC('d','r','a','c')  ),
+    M( "ogg", "ogg", INT_MAX,   VLC_CODEC_VORBIS, VLC_CODEC_SPEEX,  VLC_CODEC_FLAC,
+                                VLC_CODEC_SUBT,   VLC_CODEC_THEORA, VLC_CODEC_DIRAC  ),
 
-    M( "asf", "asf", 127,       VLC_FOURCC('w','m','a','1'), VLC_FOURCC('w','m','a','2'), VLC_FOURCC('w','m','a',' '),
-                                VLC_FOURCC('w','m','a','p'), VLC_FOURCC('w','m','a','l'),
-                                VLC_FOURCC('W','M','V','1'), VLC_FOURCC('W','M','V','2'), VLC_FOURCC('W','M','V','3') ),
+    M( "asf", "asf", 127,       VLC_CODEC_WMA1, VLC_CODEC_WMA2, VLC_CODEC_WMAP, VLC_CODEC_WMAL, VLC_CODEC_WMAS,
+                                VLC_CODEC_WMV1, VLC_CODEC_WMV2, VLC_CODEC_WMV3, VLC_CODEC_VC1 ),
 
-    M( "mp4", "mp4", INT_MAX,   VLC_FOURCC('m','p','4','a'), VLC_FOURCC('h','2','6','4'), VLC_FOURCC('m','p','4','v'), 
-                                VLC_FOURCC('s','u','b','t') ),
+    M( "mp4", "mp4", INT_MAX,   VLC_CODEC_MP4A, VLC_CODEC_H264, VLC_CODEC_MP4V,
+                                VLC_CODEC_SUBT ),
 
-    M( "ps", "ps", 16/* FIXME*/,VLC_FOURCC('m','p','g','v'), VLC_FOURCC('m','p','1','v'), VLC_FOURCC('m','p','2','v'), 
-                                VLC_FOURCC('m','p','g','a'), VLC_FOURCC('l','p','c','m'), VLC_FOURCC('a','5','2',' '),
-                                VLC_FOURCC('d','t','s',' '),
-                                VLC_FOURCC('s','p','u',' ') ),
+    M( "ps", "mpg", 16/* FIXME*/,VLC_CODEC_MPGV,
+                                VLC_CODEC_MPGA, VLC_CODEC_DVD_LPCM, VLC_CODEC_A52,
+                                VLC_CODEC_DTS,
+                                VLC_CODEC_SPU ),
 
-    M( "ts", "ts", 8000,        VLC_FOURCC('m','p','g','v'), VLC_FOURCC('m','p','1','v'), VLC_FOURCC('m','p','2','v'), 
-                                VLC_FOURCC('h','2','6','4'),
-                                VLC_FOURCC('m','p','g','a'), VLC_FOURCC('l','p','c','m'), VLC_FOURCC('a','5','2',' '),
-                                VLC_FOURCC('d','t','s',' '), VLC_FOURCC('m','p','4','a'),
-                                VLC_FOURCC('d','v','b','s'), VLC_FOURCC('t','e','l','x') ),
+    M( "ts", "ts", 8000,        VLC_CODEC_MPGV,
+                                VLC_CODEC_H264,
+                                VLC_CODEC_MPGA, VLC_CODEC_DVD_LPCM, VLC_CODEC_A52,
+                                VLC_CODEC_DTS,  VLC_CODEC_MP4A,
+                                VLC_CODEC_DVBS, VLC_CODEC_TELETEXT ),
 
     M( NULL, NULL, 0, 0 )
 };
@@ -303,21 +306,31 @@ static int OutputNew( sout_stream_t *p_stream,
                       const char *psz_muxer, const char *psz_prefix, const char *psz_extension  )
 {
     sout_stream_sys_t *p_sys = p_stream->p_sys;
-    char *psz_output;
+    char *psz_file = NULL;
+    char *psz_output = NULL;
     int i_count;
 
-    if( asprintf( &psz_output, "std{access=file,mux='%s',dst='%s%s%s'}",
-                  psz_muxer, psz_prefix, psz_extension ? "." : "", psz_extension ? psz_extension : "" ) < 0 )
-        return -1;
+    if( asprintf( &psz_file, "%s%s%s",
+                  psz_prefix, psz_extension ? "." : "", psz_extension ? psz_extension : "" ) < 0 )
+    {
+        psz_file = NULL;
+        goto error;
+    }
+
+    if( asprintf( &psz_output, "std{access=file,mux='%s',dst='%s'}",
+                  psz_muxer, psz_file ) < 0 )
+    {
+        psz_output = NULL;
+        goto error;
+    }
 
     /* Create the output */
     msg_Dbg( p_stream, "Using record output `%s'", psz_output );
-    p_sys->p_out = sout_StreamNew( p_stream->p_sout, psz_output );
 
-    free( psz_output );
+    p_sys->p_out = sout_StreamChainNew( p_stream->p_sout, psz_output, NULL, NULL );
 
     if( !p_sys->p_out )
-        return -1;
+        goto error;
 
     /* Add es */
     i_count = 0;
@@ -330,12 +343,25 @@ static int OutputNew( sout_stream_t *p_stream,
             i_count++;
     }
 
+    if( psz_file && psz_extension )
+        var_SetString( p_stream->p_libvlc, "record-file", psz_file );
+
+    free( psz_file );
+    free( psz_output );
+
     return i_count;
+
+error:
+
+    free( psz_file );
+    free( psz_output );
+    return -1;
+
 }
 
 static void OutputStart( sout_stream_t *p_stream )
 {
-       sout_stream_sys_t *p_sys = p_stream->p_sys;
+    sout_stream_sys_t *p_sys = p_stream->p_sys;
 
     /* */
     if( p_sys->b_drop )
@@ -348,7 +374,7 @@ static void OutputStart( sout_stream_t *p_stream )
     const char *psz_muxer = NULL;
     const char *psz_extension = NULL;
 
-    /* Look for prefered muxer 
+    /* Look for preferred muxer
      * TODO we could insert transcode in a few cases like
      * s16l <-> s16b
      */
@@ -389,11 +415,11 @@ static void OutputStart( sout_stream_t *p_stream )
     {
         static const char *ppsz_muxers[][2] = {
             { "avi", "avi" }, { "mp4", "mp4" }, { "ogg", "ogg" },
-            { "asf", "asf" }, {  "ts",  "ts" }, {  "ps",  "ps" },
+            { "asf", "asf" }, {  "ts",  "ts" }, {  "ps", "mpg" },
 #if 0
             // XXX ffmpeg sefault really easily if you try an unsupported codec
             // mov and avi at least segfault
-            { "ffmpeg{mux=avi}", "avi" }, 
+            { "ffmpeg{mux=avi}", "avi" },
             { "ffmpeg{mux=mov}", "mov" },
             { "ffmpeg{mux=mp4}", "mp4" },
             { "ffmpeg{mux=nsv}", "nsv" },
@@ -409,7 +435,7 @@ static void OutputStart( sout_stream_t *p_stream )
         {
             char *psz_file;
             int i_es;
-            
+
             psz_file = tempnam( NULL, "vlc" );
             if( !psz_file )
                 continue;
@@ -419,7 +445,7 @@ static void OutputStart( sout_stream_t *p_stream )
 
             if( i_es < 0 )
             {
-                utf8_unlink( psz_file );
+                vlc_unlink( psz_file );
                 free( psz_file );
                 continue;
             }
@@ -434,7 +460,7 @@ static void OutputStart( sout_stream_t *p_stream )
                 id->id = NULL;
             }
             if( p_sys->p_out )
-                sout_StreamDelete( p_sys->p_out );
+                sout_StreamChainDelete( p_sys->p_out, p_sys->p_out );
             p_sys->p_out = NULL;
 
             if( i_es > i_best_es )
@@ -445,7 +471,7 @@ static void OutputStart( sout_stream_t *p_stream )
                 if( i_best_es >= p_sys->i_id )
                     break;
             }
-            utf8_unlink( psz_file );
+            vlc_unlink( psz_file );
             free( psz_file );
         }
 
@@ -514,7 +540,7 @@ static void OutputStart( sout_stream_t *p_stream )
 
 static void OutputSend( sout_stream_t *p_stream, sout_stream_id_t *id, block_t *p_block )
 {
-       sout_stream_sys_t *p_sys = p_stream->p_sys;
+    sout_stream_sys_t *p_sys = p_stream->p_sys;
 
     if( id->id )
     {
@@ -528,7 +554,7 @@ static void OutputSend( sout_stream_t *p_stream, sout_stream_id_t *id, block_t *
                 id->b_wait_start = false;
             }
 
-            if( ( p_block->i_flags & (BLOCK_FLAG_TYPE_I|BLOCK_FLAG_TYPE_P|BLOCK_FLAG_TYPE_B|BLOCK_FLAG_TYPE_PB) ) == 0 )
+            if( ( p_block->i_flags & BLOCK_FLAG_TYPE_MASK ) == 0 )
                 id->b_wait_key = false;
         }
         if( id->b_wait_start )