]> git.sesse.net Git - vlc/commitdiff
Moved stream record to its own module.
authorLaurent Aimar <fenrir@videolan.org>
Tue, 9 Dec 2008 20:06:12 +0000 (21:06 +0100)
committerLaurent Aimar <fenrir@videolan.org>
Tue, 9 Dec 2008 20:13:03 +0000 (21:13 +0100)
include/vlc_input.h
modules/stream_filter/Modules.am
modules/stream_filter/record.c [new file with mode: 0644]
src/input/input.c
src/input/input_internal.h
src/input/stream.c
src/libvlccore.sym

index 912abdff13a31af57700b79b289c9dabe17319c1..048be2d6af039b04deccdb6c9a1caab0e7e733a8 100644 (file)
@@ -423,6 +423,12 @@ struct input_thread_t
     input_thread_private_t *p;
 };
 
+/**
+ * Record prefix string.
+ * TODO make it configurable.
+ */
+#define INPUT_RECORD_PREFIX "vlc-record-%Y-%m-%d-%H:%M:%S-$ N-$ p"
+
 /*****************************************************************************
  * Input events and variables
  *****************************************************************************/
@@ -689,4 +695,9 @@ VLC_EXPORT( void, input_DecoderDecode,( decoder_t *, block_t * ) );
  */
 VLC_EXPORT( void, input_SplitMRL, ( const char **ppsz_access, const char **ppsz_demux, char **ppsz_path, char *psz_dup ) );
 
+/**
+ * This function creates a sane filename path.
+ */
+VLC_EXPORT( char *, input_CreateFilename, ( vlc_object_t *, const char *psz_path, const char *psz_prefix, const char *psz_extension ) );
+
 #endif
index 8b137891791fe96927ad78e64b0aad7bded08bdc..59e31023adeee64b835fc0ea666d5e78bb0cbd0c 100644 (file)
@@ -1 +1,6 @@
+SOURCES_stream_filter_record = record.c
+
+libvlc_LTLIBRARIES += \
+   libstream_filter_record_plugin.la \
+   $(NULL)
 
diff --git a/modules/stream_filter/record.c b/modules/stream_filter/record.c
new file mode 100644 (file)
index 0000000..2ab138f
--- /dev/null
@@ -0,0 +1,245 @@
+/*****************************************************************************
+ * record.c
+ *****************************************************************************
+ * Copyright (C) 2008 Laurent Aimar
+ * $Id$
+ *
+ * Author: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+
+#include <assert.h>
+#include <vlc_stream.h>
+#include <vlc_input.h>
+#include <vlc_charset.h>
+
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+static int  Open ( vlc_object_t * );
+static void Close( vlc_object_t * );
+
+vlc_module_begin()
+    set_category( CAT_INPUT )
+    set_subcategory( SUBCAT_INPUT_STREAM_FILTER )
+    set_description( N_("Internal stream record") )
+    set_capability( "stream_filter", 0 )
+    set_callbacks( Open, Close )
+vlc_module_end()
+
+/*****************************************************************************
+ *
+ *****************************************************************************/
+struct stream_sys_t
+{
+    bool b_active;
+
+    FILE *f;        /* TODO it could be replaced by access_output_t one day */
+    bool b_error;
+};
+
+
+/****************************************************************************
+ * Local prototypes
+ ****************************************************************************/
+static int  Read   ( stream_t *, void *p_read, unsigned int i_read );
+static int  Peek   ( stream_t *, const uint8_t **pp_peek, unsigned int i_peek );
+static int  Control( stream_t *, int i_query, va_list );
+
+static int  Start  ( stream_t *, const char *psz_extension );
+static int  Stop   ( stream_t * );
+static void Write  ( stream_t *, const uint8_t *p_buffer, size_t i_buffer );
+
+/****************************************************************************
+ * Open
+ ****************************************************************************/
+static int Open ( vlc_object_t *p_this )
+{
+    stream_t *s = (stream_t*)p_this;
+    stream_sys_t *p_sys;
+
+    /* */
+    s->p_sys = p_sys = malloc( sizeof( *p_sys ) );
+    if( !p_sys )
+        return VLC_ENOMEM;
+
+    p_sys->b_active = false;
+
+    /* */
+    s->pf_read = Read;
+    s->pf_peek = Peek;
+    s->pf_control = Control;
+
+    return VLC_SUCCESS;
+}
+
+/****************************************************************************
+ * Close
+ ****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+    stream_t *s = (stream_t*)p_this;
+    stream_sys_t *p_sys = s->p_sys;
+
+    if( p_sys->b_active )
+        Stop( s );
+
+    free( p_sys );
+}
+
+/****************************************************************************
+ * Stream filters functions
+ ****************************************************************************/
+static int Read( stream_t *s, void *p_read, unsigned int i_read )
+{
+    stream_sys_t *p_sys = s->p_sys;
+    void *p_record = p_read;
+
+    /* Allocate a temporary buffer for record when no p_read */
+    if( p_sys->b_active && !p_record )
+        p_record = malloc( i_read );
+
+    /* */
+    const int i_record = stream_Read( s->p_source, p_record, i_read );
+
+    /* Dump read data */
+    if( p_sys->b_active )
+    {
+        if( p_record && i_record > 0 )
+            Write( s, p_record, i_record );
+        if( !p_read )
+            free( p_record );
+    }
+
+    return i_record;
+}
+
+static int Peek( stream_t *s, const uint8_t **pp_peek, unsigned int i_peek )
+{
+    return stream_Peek( s->p_source, pp_peek, i_peek );
+}
+
+static int Control( stream_t *s, int i_query, va_list args )
+{
+    if( i_query != STREAM_SET_RECORD_STATE )
+        return stream_vaControl( s->p_source, i_query, args );
+
+    bool b_active = (bool)va_arg( args, int );
+    const char *psz_extension = NULL;
+    if( b_active )
+        psz_extension = (const char*)va_arg( args, const char* );
+
+    if( !s->p_sys->b_active == !b_active )
+        return VLC_SUCCESS;
+
+    if( b_active )
+        return Start( s, psz_extension );
+    else
+        return Stop( s );
+}
+
+/****************************************************************************
+ * Helpers
+ ****************************************************************************/
+static int Start( stream_t *s, const char *psz_extension )
+{
+    stream_sys_t *p_sys = s->p_sys;
+
+    char *psz_file;
+    FILE *f;
+
+    /* */
+    if( !psz_extension )
+        psz_extension = "dat";
+
+    /* Retreive path */
+    char *psz_path = var_CreateGetString( s, "input-record-path" );
+    if( !psz_path || *psz_path == '\0' )
+    {
+        free( psz_path );
+        psz_path = strdup( config_GetHomeDir() );
+    }
+
+    if( !psz_path )
+        return VLC_ENOMEM;
+
+    /* Create file name
+     * TODO allow prefix configuration */
+    psz_file = input_CreateFilename( VLC_OBJECT(s), psz_path, INPUT_RECORD_PREFIX, psz_extension );
+
+    free( psz_path );
+
+    if( !psz_file )
+        return VLC_ENOMEM;
+
+    f = utf8_fopen( psz_file, "wb" );
+    if( !f )
+    {
+        free( psz_file );
+        return VLC_EGENERIC;
+    }
+    msg_Dbg( s, "Recording into %s", psz_file );
+    free( psz_file );
+
+    /* */
+    p_sys->f = f;
+    p_sys->b_active = true;
+    p_sys->b_error = false;
+    return VLC_SUCCESS;
+}
+static int Stop( stream_t *s )
+{
+    stream_sys_t *p_sys = s->p_sys;
+
+    assert( p_sys->b_active );
+
+    msg_Dbg( s, "Recording completed" );
+    fclose( p_sys->f );
+    p_sys->b_active = false;
+    return VLC_SUCCESS;
+}
+
+static void Write( stream_t *s, const uint8_t *p_buffer, size_t i_buffer )
+{
+    stream_sys_t *p_sys = s->p_sys;
+
+    assert( p_sys->b_active );
+
+    if( i_buffer > 0 )
+    {
+        const bool b_previous_error = p_sys->b_error;
+        const size_t i_written = fwrite( p_buffer, 1, i_buffer, p_sys->f );
+
+        p_sys->b_error = i_written != i_buffer;
+
+        /* TODO maybe a intf_UserError or something like that ? */
+        if( p_sys->b_error && !b_previous_error )
+            msg_Err( s, "Failed to record data (begin)" );
+        else if( !p_sys->b_error && b_previous_error )
+            msg_Err( s, "Failed to record data (end)" );
+    }
+}
index 9e76bb82ee1a00a49d2f0d1ad91568984c8cb944..b026ee607172b61351e59a5c3d9d5f3c01d1322f 100644 (file)
@@ -2573,6 +2573,18 @@ static int InputSourceInit( input_thread_t *p_input,
         }
         free( psz_tmp );
 
+        /* Add record filter if usefull */
+        if( var_GetBool( p_input, "input-record-native" ) )
+        {
+            stream_t *p_filter;
+
+            p_filter = stream_FilterNew( in->p_stream, "stream_filter_record" );
+            if( p_filter )
+                in->p_stream = p_filter;
+            else
+                var_SetBool( p_input, "input-record-native", false );
+        }
+
         /* Open a demuxer */
         if( *psz_demux == '\0' && *in->p_access->psz_demux )
         {
index b0b43a8f636aff0ba6b276261564287eda1efd6e..978de5d83335606b7963533f910dba62a00e2cc9 100644 (file)
@@ -231,9 +231,4 @@ void input_ConfigVarInit ( input_thread_t * );
 char **subtitles_Detect( input_thread_t *, char* path, const char *fname );
 int subtitles_Filter( const char *);
 
-/* Helpers FIXME to export without input_ prefix */
-char *input_CreateFilename( vlc_object_t *p_obj, const char *psz_path, const char *psz_prefix, const char *psz_extension );
-
-#define INPUT_RECORD_PREFIX "vlc-record-%Y-%m-%d-%H:%M:%S-$ N-$ p"
-
 #endif
index f7e3f432ffbd366e21ddceca5db7a62f5dac496d..b50a1a3bb3796455b60749e2c8df8d4d7670b4ab 100644 (file)
@@ -185,15 +185,6 @@ struct stream_sys_t
 
     /* Preparse mode ? */
     bool      b_quick;
-
-    /* */
-    struct
-    {
-        bool b_active;
-
-        FILE *f;        /* TODO it could be replaced by access_output_t one day */
-        bool b_error;
-    } record;
 };
 
 /* Method 1: */
@@ -215,8 +206,6 @@ static int AStreamControl( stream_t *s, int i_query, va_list );
 static void AStreamDestroy( stream_t *s );
 static void UStreamDestroy( stream_t *s );
 static int  ASeek( stream_t *s, int64_t i_pos );
-static int  ARecordSetState( stream_t *s, bool b_record, const char *psz_extension );
-static void ARecordWrite( stream_t *s, const uint8_t *p_buffer, size_t i_buffer );
 
 /****************************************************************************
  * stream_CommonNew: create an empty stream structure
@@ -321,8 +310,6 @@ stream_t *stream_AccessNew( access_t *p_access, bool b_quick )
     else
         p_sys->method = STREAM_METHOD_STREAM;
 
-    p_sys->record.b_active = false;
-
     p_sys->i_pos = p_access->info.i_pos;
 
     /* Stats */
@@ -498,9 +485,6 @@ static void AStreamDestroy( stream_t *s )
 
     vlc_object_detach( s );
 
-    if( p_sys->record.b_active )
-        ARecordSetState( s, false, NULL );
-
     if( p_sys->method == STREAM_METHOD_BLOCK )
         block_ChainRelease( p_sys->block.p_first );
     else
@@ -604,11 +588,9 @@ static int AStreamControl( stream_t *s, int i_query, va_list args )
     stream_sys_t *p_sys = s->p_sys;
     access_t     *p_access = p_sys->p_access;
 
-    bool *p_bool;
-    bool b_bool;
-    const char *psz_string;
-    int64_t    *pi_64, i_64;
-    int        i_int;
+    bool    *p_bool;
+    int64_t *pi_64, i_64;
+    int     i_int;
 
     switch( i_query )
     {
@@ -683,12 +665,6 @@ static int AStreamControl( stream_t *s, int i_query, va_list args )
             return access_Control( p_access, ACCESS_GET_CONTENT_TYPE,
                                     va_arg( args, char ** ) );
         case STREAM_SET_RECORD_STATE:
-            b_bool = (bool)va_arg( args, int );
-            psz_string = NULL;
-            if( b_bool )
-                psz_string = (const char*)va_arg( args, const char* );
-            return ARecordSetState( s, b_bool, psz_string );
-
         default:
             msg_Err( s, "invalid stream_vaControl query=0x%x", i_query );
             return VLC_EGENERIC;
@@ -696,100 +672,6 @@ static int AStreamControl( stream_t *s, int i_query, va_list args )
     return VLC_SUCCESS;
 }
 
-/****************************************************************************
- * ARecord*: record stream functions
- ****************************************************************************/
-static int  ARecordStart( stream_t *s, const char *psz_extension )
-{
-    stream_sys_t *p_sys = s->p_sys;
-
-    char *psz_file;
-    FILE *f;
-
-    /* */
-    if( !psz_extension )
-        psz_extension = "dat";
-
-    /* Retreive path */
-    char *psz_path = var_CreateGetString( s, "input-record-path" );
-    if( !psz_path || *psz_path == '\0' )
-    {
-        free( psz_path );
-        psz_path = strdup( config_GetHomeDir() );
-    }
-
-    if( !psz_path )
-        return VLC_ENOMEM;
-
-    /* Create file name
-     * TODO allow prefix configuration */
-    psz_file = input_CreateFilename( VLC_OBJECT(s), psz_path, INPUT_RECORD_PREFIX, psz_extension );
-
-    free( psz_path );
-
-    if( !psz_file )
-        return VLC_ENOMEM;
-
-    f = utf8_fopen( psz_file, "wb" );
-    if( !f )
-    {
-        free( psz_file );
-        return VLC_EGENERIC;
-    }
-    msg_Dbg( s, "Recording into %s", psz_file );
-    free( psz_file );
-
-    /* */
-    p_sys->record.f = f;
-    p_sys->record.b_active = true;
-    p_sys->record.b_error = false;
-    return VLC_SUCCESS;
-}
-static int  ARecordStop( stream_t *s )
-{
-    stream_sys_t *p_sys = s->p_sys;
-
-    assert( p_sys->record.b_active );
-
-    msg_Dbg( s, "Recording completed" );
-    fclose( p_sys->record.f );
-    p_sys->record.b_active = false;
-    return VLC_SUCCESS;
-}
-
-static int  ARecordSetState( stream_t *s, bool b_record, const char *psz_extension )
-{
-    stream_sys_t *p_sys = s->p_sys;
-
-    if( !!p_sys->record.b_active == !!b_record )
-        return VLC_SUCCESS;
-
-    if( b_record )
-        return ARecordStart( s, psz_extension );
-    else
-        return ARecordStop( s );
-}
-static void ARecordWrite( stream_t *s, const uint8_t *p_buffer, size_t i_buffer )
-{
-    stream_sys_t *p_sys = s->p_sys;
-
-    assert( p_sys->record.b_active );
-
-    if( i_buffer > 0 )
-    {
-        const bool b_previous_error = p_sys->record.b_error;
-        const size_t i_written = fwrite( p_buffer, 1, i_buffer, p_sys->record.f );
-
-        p_sys->record.b_error = i_written != i_buffer;
-
-        /* TODO maybe a intf_UserError or something like that ? */
-        if( p_sys->record.b_error && !b_previous_error )
-            msg_Err( s, "Failed to record data (begin)" );
-        else if( !p_sys->record.b_error && b_previous_error )
-            msg_Err( s, "Failed to record data (end)" );
-    }
-}
-
 /****************************************************************************
  * Method 1:
  ****************************************************************************/
@@ -864,16 +746,12 @@ static int AStreamReadBlock( stream_t *s, void *p_read, unsigned int i_read )
     stream_sys_t *p_sys = s->p_sys;
 
     uint8_t *p_data = p_read;
-    uint8_t *p_record = p_data;
     unsigned int i_data = 0;
 
     /* It means EOF */
     if( p_sys->block.p_current == NULL )
         return 0;
 
-    if( p_sys->record.b_active && !p_data )
-        p_record = p_data = malloc( i_read );
-
     if( p_data == NULL )
     {
         /* seek within this stream if possible, else use plain old read and discard */
@@ -918,14 +796,6 @@ static int AStreamReadBlock( stream_t *s, void *p_read, unsigned int i_read )
         }
     }
 
-    if( p_sys->record.b_active )
-    {
-        if( i_data > 0 && p_record != NULL)
-            ARecordWrite( s, p_record, i_data );
-        if( !p_read )
-            free( p_record );
-    }
-
     p_sys->i_pos += i_data;
     return i_data;
 }
@@ -1205,15 +1075,11 @@ static int AStreamReadStream( stream_t *s, void *p_read, unsigned int i_read )
     stream_track_t *tk = &p_sys->stream.tk[p_sys->stream.i_tk];
 
     uint8_t *p_data = (uint8_t *)p_read;
-    uint8_t *p_record = p_data;
     unsigned int i_data = 0;
 
     if( tk->i_start >= tk->i_end )
         return 0; /* EOF */
 
-    if( p_sys->record.b_active && !p_data )
-        p_record = p_data = malloc( i_read );
-
     if( p_data == NULL )
     {
         /* seek within this stream if possible, else use plain old read and discard */
@@ -1277,14 +1143,6 @@ static int AStreamReadStream( stream_t *s, void *p_read, unsigned int i_read )
         }
     }
 
-    if( p_sys->record.b_active )
-    {
-        if( i_data > 0 && p_record != NULL)
-            ARecordWrite( s, p_record, i_data );
-        if( !p_read )
-            free( p_record );
-    }
-
     return i_data;
 }
 
index 83920897c94caa90baa1fc27b7132732ced810f7..ccfaa270ba4e6117202c1d4ad79843b07fecacac 100644 (file)
@@ -156,6 +156,7 @@ image_HandlerDelete
 InitMD5
 input_Control
 __input_CreateThread
+input_CreateFilename
 input_DecoderDecode
 input_DecoderDelete
 input_DecoderNew