]> git.sesse.net Git - mlt/commitdiff
add multi consumer (non-functional)
authorDan Dennedy <dan@dennedy.org>
Sat, 5 Nov 2011 22:44:42 +0000 (15:44 -0700)
committerDan Dennedy <dan@dennedy.org>
Sat, 12 Nov 2011 20:07:39 +0000 (12:07 -0800)
src/modules/core/Makefile
src/modules/core/consumer_multi.c [new file with mode: 0644]
src/modules/core/consumer_multi.yml [new file with mode: 0644]
src/modules/core/factory.c

index cf3332e488bb72624e48d86bd6b43ca6f7a682b1..31edacd94d6c6b7965a2f67b3851c2ba71702689 100644 (file)
@@ -39,6 +39,7 @@ OBJS = factory.o \
           transition_luma.o \
           transition_mix.o \
           transition_region.o \
+          consumer_multi.o \
           consumer_null.o
 
 ASM_OBJS = 
diff --git a/src/modules/core/consumer_multi.c b/src/modules/core/consumer_multi.c
new file mode 100644 (file)
index 0000000..b9818e6
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2011 Ushodaya Enterprises Limited
+ * Author: Dan Dennedy <dan@dennedy.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <framework/mlt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+
+// Forward references
+static int start( mlt_consumer consumer );
+static int stop( mlt_consumer consumer );
+static int is_stopped( mlt_consumer consumer );
+static void *consumer_thread( void *arg );
+static void consumer_close( mlt_consumer consumer );
+
+/** Initialise the consumer.
+*/
+
+mlt_consumer consumer_multi_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_consumer consumer = mlt_consumer_new( profile );
+
+       if ( consumer )
+       {
+               // Assign callbacks
+               consumer->close = consumer_close;
+               consumer->start = start;
+               consumer->stop = stop;
+               consumer->is_stopped = is_stopped;
+       }
+
+       return consumer;
+}
+
+/** Start the consumer.
+*/
+
+static int start( mlt_consumer consumer )
+{
+       // Check that we're not already running
+       if ( is_stopped( consumer ) )
+       {
+               mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
+               pthread_t *thread = calloc( 1, sizeof( pthread_t ) );
+
+               // Assign the thread to properties with automatic dealloc
+               mlt_properties_set_data( properties, "thread", thread, sizeof( pthread_t ), free, NULL );
+
+               // Set the running state
+               mlt_properties_set_int( properties, "running", 1 );
+
+               // Create the thread
+               pthread_create( thread, NULL, consumer_thread, consumer );
+       }
+       return 0;
+}
+
+/** Stop the consumer.
+*/
+
+static int stop( mlt_consumer consumer )
+{
+       // Check that we're running
+       if ( !is_stopped( consumer ) )
+       {
+               mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
+               pthread_t *thread = mlt_properties_get_data( properties, "thread", NULL );
+
+               // Stop the thread
+               mlt_properties_set_int( properties, "running", 0 );
+
+               // Wait for termination
+               if ( thread )
+                       pthread_join( *thread, NULL );
+       }
+
+       return 0;
+}
+
+/** Determine if the consumer is stopped.
+*/
+
+static int is_stopped( mlt_consumer consumer )
+{
+       return !mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( consumer ), "running" );
+}
+
+/** The main thread - the argument is simply the consumer.
+*/
+
+static void *consumer_thread( void *arg )
+{
+       mlt_consumer consumer = arg;
+       mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
+       mlt_frame frame = NULL;
+
+       // Determine whether to stop at end-of-media
+       int terminate_on_pause = mlt_properties_get_int( properties, "terminate_on_pause" );
+       int terminated = 0;
+
+       // Loop while running
+       while ( !terminated && mlt_properties_get_int( properties, "running" ) )
+       {
+               // Get the next frame
+               frame = mlt_consumer_rt_frame( consumer );
+
+               // Check for termination
+               if ( terminate_on_pause && frame )
+                       terminated = mlt_properties_get_double( MLT_FRAME_PROPERTIES( frame ), "_speed" ) == 0.0;
+
+               // Check that we have a frame to work with
+               if ( frame )
+               {
+                       // Close the frame
+                       mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
+                       mlt_frame_close( frame );
+               }
+       }
+
+       // Indicate that the consumer is stopped
+       mlt_properties_set_int( properties, "running", 0 );
+       mlt_consumer_stopped( consumer );
+
+       return NULL;
+}
+
+/** Close the consumer.
+*/
+
+static void consumer_close( mlt_consumer consumer )
+{
+       mlt_consumer_stop( consumer );
+       // Close the parent
+       mlt_consumer_close( consumer );
+       free( consumer );
+}
diff --git a/src/modules/core/consumer_multi.yml b/src/modules/core/consumer_multi.yml
new file mode 100644 (file)
index 0000000..f3c01c9
--- /dev/null
@@ -0,0 +1,21 @@
+schema_version: 0.1
+type: consumer
+identifier: multi
+title: Multiple outputs
+version: 1
+copyright: Copyright (C) 2011 Ushodaya Enterprises Limited
+license: LGPL
+language: en
+creator: Dan Dennedy
+tags:
+  - Audio
+  - Video
+description: Use multiple consumers with the same producer.
+parameters:
+  - identifier: argument
+    title: Number of consumers
+    type: integer
+    required: yes
+    widget: spinner
+    minimum: 0
+    default: 1
index aee7cce30a64fdbc694b2a1b6330ec67c36934c7..2396562591154c56c7431400a8a9f6ee39f210d1 100644 (file)
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <limits.h>
 
+extern mlt_consumer consumer_multi_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
 extern mlt_consumer consumer_null_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
 extern mlt_filter filter_audiochannels_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
 extern mlt_filter filter_audioconvert_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
@@ -66,6 +67,7 @@ static mlt_properties metadata( mlt_service_type type, const char *id, void *dat
 
 MLT_REPOSITORY
 {
+       MLT_REGISTER( consumer_type, "multi", consumer_multi_init );
        MLT_REGISTER( consumer_type, "null", consumer_null_init );
        MLT_REGISTER( filter_type, "audiochannels", filter_audiochannels_init );
        MLT_REGISTER( filter_type, "audioconvert", filter_audioconvert_init );
@@ -105,6 +107,7 @@ MLT_REPOSITORY
        MLT_REGISTER( transition_type, "mix", transition_mix_init );
        MLT_REGISTER( transition_type, "region", transition_region_init );
 
+       MLT_REGISTER_METADATA( consumer_type, "multi", metadata, "consumer_multi.yml" );
        MLT_REGISTER_METADATA( filter_type, "audiowave", metadata, "filter_audiowave.yml" );
        MLT_REGISTER_METADATA( filter_type, "brightness", metadata, "filter_brightness.yml" );
        MLT_REGISTER_METADATA( filter_type, "channelcopy", metadata, "filter_channelcopy.yml" );