Support for auto and user requested stream_filter.
authorLaurent Aimar <fenrir@videolan.org>
Mon, 8 Dec 2008 21:34:33 +0000 (22:34 +0100)
committerLaurent Aimar <fenrir@videolan.org>
Tue, 9 Dec 2008 20:13:03 +0000 (21:13 +0100)
include/vlc_stream.h
src/Makefile.am
src/input/input.c
src/input/stream.c
src/input/stream.h
src/input/stream_filter.c [new file with mode: 0644]
src/input/var.c

index 4e4864c..f8365da 100644 (file)
@@ -53,17 +53,18 @@ struct stream_t
 {
     VLC_COMMON_MEMBERS
 
-    /* Module properties */
+    /* Module properties for stream filter */
     module_t    *p_module;
 
-    /* For stream filter they will hold an array of stream sources */
-    int      i_source;
-    stream_t **pp_source;
+    /* Stream source for stream filter */
+    stream_t *p_source;
 
     /* */
     int      (*pf_read)   ( stream_t *, void *p_read, unsigned int i_read );
     int      (*pf_peek)   ( stream_t *, const uint8_t **pp_peek, unsigned int i_peek );
     int      (*pf_control)( stream_t *, int i_query, va_list );
+
+    /* */
     void     (*pf_destroy)( stream_t *);
 
     /* Private data for module */
@@ -95,10 +96,14 @@ enum stream_query_e
     STREAM_CONTROL_ACCESS,  /* arg1= int i_access_query, args   res: can fail
                              if access unreachable or access control answer */
 
+    /* You should update size of source if any and then update size 
+     * FIXME find a way to avoid it */
+    STREAM_UPDATE_SIZE,
+
+    /* */
     STREAM_GET_CONTENT_TYPE,    /**< arg1= char **         res=can fail */
 
-    /* SET_RECORD:
-     * XXX only data read through stream_Read/Block will be recorded */
+    /* XXX only data read through stream_Read/Block will be recorded */
     STREAM_SET_RECORD_STATE,     /**< arg1=bool, arg2=const char *psz_ext (if arg1 is true)  res=can fail */
 };
 
index 21ebf5d..8507f90 100644 (file)
@@ -327,6 +327,7 @@ SOURCES_libvlc_common = \
        input/vlm_internal.h \
        input/stream.c \
        input/stream_demux.c \
+       input/stream_filter.c \
        input/stream_memory.c \
        input/subtitles.c \
        input/var.c \
index f7057e6..9e76bb8 100644 (file)
@@ -1933,8 +1933,8 @@ static bool Control( input_thread_t *p_input, int i_type,
                 {
                     es_out_SetTime( p_input->p->p_es_out, -1 );
 
-                    access_Control( p_access, ACCESS_SET_TITLE, i_title );
-                    stream_AccessReset( p_input->p->input.p_stream );
+                    stream_Control( p_input->p->input.p_stream, STREAM_CONTROL_ACCESS,
+                                    ACCESS_SET_TITLE, i_title );
                 }
             }
             break;
@@ -2012,9 +2012,8 @@ static bool Control( input_thread_t *p_input, int i_type,
                 {
                     es_out_SetTime( p_input->p->p_es_out, -1 );
 
-                    access_Control( p_access, ACCESS_SET_SEEKPOINT,
-                                    i_seekpoint );
-                    stream_AccessReset( p_input->p->input.p_stream );
+                    stream_Control( p_input->p->input.p_stream, STREAM_CONTROL_ACCESS,
+                                    ACCESS_SET_SEEKPOINT, i_seekpoint );
                 }
             }
             break;
@@ -2256,7 +2255,7 @@ static int UpdateTitleSeekpointFromAccess( input_thread_t *p_input )
     {
         input_SendEventTitle( p_input, p_access->info.i_title );
 
-        stream_AccessUpdate( p_input->p->input.p_stream );
+        stream_Control( p_input->p->input.p_stream, STREAM_UPDATE_SIZE );
 
         p_access->info.i_update &= ~INPUT_UPDATE_TITLE;
     }
@@ -2515,6 +2514,10 @@ static int InputSourceInit( input_thread_t *p_input,
             var_Set( p_input, "can-seek", val );
         }
 
+        /* TODO (maybe)
+         * do not let stream_AccessNew access input-list
+         * but give it a list of access ? */
+
         /* Autodetect extra files if none specified */
         char *psz_input_list = var_CreateGetNonEmptyString( p_input, "input-list" );
         if( !psz_input_list )
@@ -2528,7 +2531,7 @@ static int InputSourceInit( input_thread_t *p_input,
         /* Create the stream_t */
         in->p_stream = stream_AccessNew( in->p_access, p_input->b_preparsing );
 
-        /* Restor old value */
+        /* Restore old value */
         if( !psz_input_list )
             var_SetString( p_input, "input-list", "" );
         free( psz_input_list );
@@ -2539,6 +2542,37 @@ static int InputSourceInit( input_thread_t *p_input,
             goto error;
         }
 
+        /* Add auto stream filter */
+        for( ;; )
+        {
+            stream_t *p_filter = stream_FilterNew( in->p_stream, NULL );
+            if( !p_filter )
+                break;
+
+            msg_Dbg( p_input, "Inserted a stream filter" );
+            in->p_stream = p_filter;
+        }
+
+        /* Add user stream filter */
+        psz_tmp = psz = var_GetNonEmptyString( p_input, "stream-filter" );
+        while( psz && *psz )
+        {
+            stream_t *p_filter;
+            char *psz_end = strchr( psz, ':' );
+
+            if( psz_end )
+                *psz_end++ = '\0';
+
+            p_filter = stream_FilterNew( in->p_stream, psz );
+            if( p_filter )
+                in->p_stream = p_filter;
+            else
+                msg_Warn( p_input, "failed to insert stream filter %s", psz );
+
+            psz = psz_end;
+        }
+        free( psz_tmp );
+
         /* Open a demuxer */
         if( *psz_demux == '\0' && *in->p_access->psz_demux )
         {
@@ -2597,7 +2631,7 @@ static int InputSourceInit( input_thread_t *p_input,
     if( demux_Control( in->p_demux, DEMUX_CAN_RECORD, &in->b_can_stream_record ) )
         in->b_can_stream_record = false;
 #ifdef ENABLE_SOUT
-    if( !var_CreateGetBool( p_input, "input-record-native" ) )
+    if( !var_GetBool( p_input, "input-record-native" ) )
         in->b_can_stream_record = false;
     var_SetBool( p_input, "can-record", true );
 #else
index 4f9701f..f7e3f43 100644 (file)
@@ -531,9 +531,9 @@ static void UStreamDestroy( stream_t *s )
 }
 
 /****************************************************************************
- * stream_AccessReset:
+ * AStreamControlReset:
  ****************************************************************************/
-void stream_AccessReset( stream_t *s )
+static void AStreamControlReset( stream_t *s )
 {
     stream_sys_t *p_sys = s->p_sys;
 
@@ -578,9 +578,9 @@ void stream_AccessReset( stream_t *s )
 }
 
 /****************************************************************************
- * stream_AccessUpdate:
+ * AStreamControlUpdate:
  ****************************************************************************/
-void stream_AccessUpdate( stream_t *s )
+static void AStreamControlUpdate( stream_t *s )
 {
     stream_sys_t *p_sys = s->p_sys;
 
@@ -657,16 +657,27 @@ static int AStreamControl( stream_t *s, int i_query, va_list args )
             return VLC_EGENERIC;
 
         case STREAM_CONTROL_ACCESS:
+        {
             i_int = (int) va_arg( args, int );
             if( i_int != ACCESS_SET_PRIVATE_ID_STATE &&
                 i_int != ACCESS_SET_PRIVATE_ID_CA &&
-                i_int != ACCESS_GET_PRIVATE_ID_STATE )
+                i_int != ACCESS_GET_PRIVATE_ID_STATE &&
+                i_int != ACCESS_SET_TITLE &&
+                i_int != ACCESS_SET_SEEKPOINT )
             {
                 msg_Err( s, "Hey, what are you thinking ?"
                             "DON'T USE STREAM_CONTROL_ACCESS !!!" );
                 return VLC_EGENERIC;
             }
-            return access_vaControl( p_access, i_int, args );
+            int i_ret = access_vaControl( p_access, i_int, args );
+            if( i_int == ACCESS_SET_TITLE || i_int == ACCESS_SET_SEEKPOINT )
+                AStreamControlReset( s );
+            return i_ret;
+        }
+
+        case STREAM_UPDATE_SIZE:
+            AStreamControlUpdate( s );
+            return VLC_SUCCESS;
 
         case STREAM_GET_CONTENT_TYPE:
             return access_Control( p_access, ACCESS_GET_CONTENT_TYPE,
index 66e3921..1a2d50a 100644 (file)
@@ -46,9 +46,10 @@ void stream_CommonDelete( stream_t * );
 
 /* */
 stream_t *stream_AccessNew( access_t *p_access, bool );
-void stream_AccessDelete( stream_t *s );
-void stream_AccessReset( stream_t *s );
-void stream_AccessUpdate( stream_t *s );
+
+/* */
+stream_t *stream_FilterNew( stream_t *p_source,
+                            const char *psz_stream_filter );
 
 #endif
 
diff --git a/src/input/stream_filter.c b/src/input/stream_filter.c
new file mode 100644 (file)
index 0000000..7ad7d6a
--- /dev/null
@@ -0,0 +1,73 @@
+/*****************************************************************************
+ * stream_filter.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.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_stream.h>
+#include <libvlc.h>
+
+#include "stream.h"
+
+static void StreamDelete( stream_t * );
+
+stream_t *stream_FilterNew( stream_t *p_source,
+                            const char *psz_stream_filter )
+{
+    stream_t *s;
+
+    s = stream_CommonNew( VLC_OBJECT( p_source ) );
+    if( s == NULL )
+        return NULL;
+
+    /* */
+    s->p_source = p_source;
+
+    /* */
+    vlc_object_attach( s, p_source );
+
+    s->p_module = module_need( s, "stream_filter", psz_stream_filter, true );
+
+    if( !s->p_module )
+    {
+        stream_CommonDelete( s );
+        return NULL;
+    }
+
+    s->pf_destroy = StreamDelete;
+
+    return s;
+}
+
+static void StreamDelete( stream_t *s )
+{
+    module_unneed( s, s->p_module );
+
+    if( s->p_source )
+        stream_Delete( s->p_source );
+
+    stream_CommonDelete( s );
+}
+
index 35b638e..3b67f6c 100644 (file)
@@ -488,10 +488,14 @@ void input_ConfigVarInit ( input_thread_t *p_input )
     var_Create( p_input, "cache", VLC_VAR_FLOAT );
     var_SetFloat( p_input, "cache", 0.0 );
 
+    /* */
+    var_Create( p_input, "input-record-native", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
+
     /* */
     var_Create( p_input, "access-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
     var_Create( p_input, "access", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
     var_Create( p_input, "demux", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
+    var_Create( p_input, "stream-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
 
     /* Meta */
     var_Create( p_input, "meta-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT );