From: Dan Dennedy Date: Tue, 16 Aug 2011 05:16:08 +0000 (-0700) Subject: Add 'all' property to xml consumer. X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=6d9f806fc2fd9c9a857c1c6a7a1c8274598a3d1c;p=mlt Add 'all' property to xml consumer. Makes the consumer process all frames before serializing to XML. --- diff --git a/src/modules/xml/Makefile b/src/modules/xml/Makefile index 8f2a4314..caa092c9 100644 --- a/src/modules/xml/Makefile +++ b/src/modules/xml/Makefile @@ -1,6 +1,6 @@ CFLAGS += -I../.. -LDFLAGS += -L../../framework -lmlt +LDFLAGS += -L../../framework -lmlt -lpthread include ../../../config.mak diff --git a/src/modules/xml/consumer_xml.c b/src/modules/xml/consumer_xml.c index c9823110..60ceaef0 100644 --- a/src/modules/xml/consumer_xml.c +++ b/src/modules/xml/consumer_xml.c @@ -25,6 +25,7 @@ #include #include #include +#include #define ID_SIZE 128 @@ -52,7 +53,9 @@ typedef struct serialise_context_s* serialise_context; */ static int consumer_start( mlt_consumer parent ); +static int consumer_stop( mlt_consumer parent ); static int consumer_is_stopped( mlt_consumer this ); +static void *consumer_thread( void *arg ); static void serialise_service( serialise_context context, mlt_service service, xmlNode *node ); typedef enum @@ -155,9 +158,13 @@ mlt_consumer consumer_xml_init( mlt_profile profile, mlt_service_type type, cons { // Allow thread to be started/stopped this->start = consumer_start; + this->stop = consumer_stop; this->is_stopped = consumer_is_stopped; mlt_properties_set( MLT_CONSUMER_PROPERTIES( this ), "resource", arg ); + mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( this ), "real_time", -1 ); + mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( this ), "prefill", 1 ); + mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( this ), "terminate_on_pause", 1 ); // Return the consumer produced return this; @@ -576,20 +583,20 @@ static void serialise_service( serialise_context context, mlt_service service, x char *resource = mlt_properties_get( properties, "resource" ); // Recurse on multitrack's tracks - if ( strcmp( resource, "" ) == 0 ) + if ( resource && strcmp( resource, "" ) == 0 ) { serialise_multitrack( context, service, node ); break; } // Recurse on playlist's clips - else if ( strcmp( resource, "" ) == 0 ) + else if ( resource && strcmp( resource, "" ) == 0 ) { serialise_playlist( context, service, node ); } // Recurse on tractor's producer - else if ( strcmp( resource, "" ) == 0 ) + else if ( resource && strcmp( resource, "" ) == 0 ) { context->pass = 0; serialise_tractor( context, service, node ); @@ -711,73 +718,174 @@ xmlDocPtr xml_make_doc( mlt_consumer consumer, mlt_service service ) return doc; } -static int consumer_start( mlt_consumer this ) + +static void output_xml( mlt_consumer this ) { - xmlDocPtr doc = NULL; - // Get the producer service mlt_service service = mlt_service_producer( MLT_CONSUMER_SERVICE( this ) ); - if ( service != NULL ) - { - mlt_properties properties = MLT_CONSUMER_PROPERTIES( this ); - char *resource = mlt_properties_get( properties, "resource" ); + mlt_properties properties = MLT_CONSUMER_PROPERTIES( this ); + char *resource = mlt_properties_get( properties, "resource" ); + xmlDocPtr doc = NULL; - // Set the title if provided - if ( mlt_properties_get( properties, "title" ) ) - mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), "title", mlt_properties_get( properties, "title" ) ); - else if ( mlt_properties_get( MLT_SERVICE_PROPERTIES( service ), "title" ) == NULL ) - mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), "title", "Anonymous Submission" ); + if ( !service ) return; - // Check for a root on the consumer properties and pass to service - if ( mlt_properties_get( properties, "root" ) ) - mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), "root", mlt_properties_get( properties, "root" ) ); + // Set the title if provided + if ( mlt_properties_get( properties, "title" ) ) + mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), "title", mlt_properties_get( properties, "title" ) ); + else if ( mlt_properties_get( MLT_SERVICE_PROPERTIES( service ), "title" ) == NULL ) + mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), "title", "Anonymous Submission" ); - // Specify roots in other cases... - if ( resource != NULL && mlt_properties_get( properties, "root" ) == NULL ) - { - // Get the current working directory - char *cwd = getcwd( NULL, 0 ); - mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), "root", cwd ); - free( cwd ); - } + // Check for a root on the consumer properties and pass to service + if ( mlt_properties_get( properties, "root" ) ) + mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), "root", mlt_properties_get( properties, "root" ) ); - // Make the document - doc = xml_make_doc( this, service ); + // Specify roots in other cases... + if ( resource != NULL && mlt_properties_get( properties, "root" ) == NULL ) + { + // Get the current working directory + char *cwd = getcwd( NULL, 0 ); + mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), "root", cwd ); + free( cwd ); + } - // Handle the output - if ( resource == NULL || !strcmp( resource, "" ) ) - { - xmlDocFormatDump( stdout, doc, 1 ); - } - else if ( strchr( resource, '.' ) == NULL ) - { - xmlChar *buffer = NULL; - int length = 0; - xmlDocDumpMemoryEnc( doc, &buffer, &length, "utf-8" ); - mlt_properties_set( properties, resource, _s(buffer) ); + // Make the document + doc = xml_make_doc( this, service ); + + // Handle the output + if ( resource == NULL || !strcmp( resource, "" ) ) + { + xmlDocFormatDump( stdout, doc, 1 ); + } + else if ( strchr( resource, '.' ) == NULL ) + { + xmlChar *buffer = NULL; + int length = 0; + xmlDocDumpMemoryEnc( doc, &buffer, &length, "utf-8" ); + mlt_properties_set( properties, resource, _s(buffer) ); #ifdef WIN32 - xmlFreeFunc xmlFree = NULL; - xmlMemGet( &xmlFree, NULL, NULL, NULL); + xmlFreeFunc xmlFree = NULL; + xmlMemGet( &xmlFree, NULL, NULL, NULL); #endif - xmlFree( buffer ); - } - else + xmlFree( buffer ); + } + else + { + xmlSaveFormatFileEnc( resource, doc, "utf-8", 1 ); + } + + // Close the document + xmlFreeDoc( doc ); +} +static int consumer_start( mlt_consumer this ) +{ + mlt_properties properties = MLT_CONSUMER_PROPERTIES( this ); + + if ( mlt_properties_get_int( properties, "all" ) ) + { + // Check that we're not already running + if ( !mlt_properties_get_int( properties, "running" ) ) { - xmlSaveFormatFileEnc( resource, doc, "utf-8", 1 ); + // Allocate a thread + pthread_t *thread = calloc( 1, sizeof( pthread_t ) ); + + // Assign the thread to properties + mlt_properties_set_data( properties, "thread", thread, sizeof( pthread_t ), free, NULL ); + + // Set the running state + mlt_properties_set_int( properties, "running", 1 ); + mlt_properties_set_int( properties, "joined", 0 ); + + // Create the thread + pthread_create( thread, NULL, consumer_thread, this ); } - - // Close the document - xmlFreeDoc( doc ); } - - mlt_consumer_stop( this ); + else + { + output_xml( this ); + mlt_consumer_stop( this ); + mlt_consumer_stopped( this ); + } + return 0; +} - mlt_consumer_stopped( this ); +static int consumer_is_stopped( mlt_consumer this ) +{ + mlt_properties properties = MLT_CONSUMER_PROPERTIES( this ); + return !mlt_properties_get_int( properties, "running" ); +} + +static int consumer_stop( mlt_consumer this ) +{ + // Get the properties + mlt_properties properties = MLT_CONSUMER_PROPERTIES( this ); + + // Check that we're running + if ( !mlt_properties_get_int( properties, "joined" ) ) + { + // Get the thread + pthread_t *thread = mlt_properties_get_data( properties, "thread", NULL ); + + // Stop the thread + mlt_properties_set_int( properties, "running", 0 ); + mlt_properties_set_int( properties, "joined", 1 ); + + // Wait for termination + if ( thread ) + pthread_join( *thread, NULL ); + } return 0; } -static int consumer_is_stopped( mlt_consumer this ) +static void *consumer_thread( void *arg ) { - return 1; + // Map the argument to the object + mlt_consumer this = arg; + + // Get the properties + mlt_properties properties = MLT_CONSUMER_PROPERTIES( this ); + + // Convenience functionality + int terminate_on_pause = mlt_properties_get_int( properties, "terminate_on_pause" ); + int terminated = 0; + + // Frame and size + mlt_frame frame = NULL; + + // Loop while running + while( !terminated && mlt_properties_get_int( properties, "running" ) ) + { + // Get the frame + frame = mlt_consumer_rt_frame( this ); + + // Check for termination + if ( terminate_on_pause && frame != NULL ) + terminated = mlt_properties_get_double( MLT_FRAME_PROPERTIES( frame ), "_speed" ) == 0.0; + + // Check that we have a frame to work with + if ( frame ) + { + int width = 0, height = 0; + int frequency = mlt_properties_get_int( properties, "frequency" ); + int channels = mlt_properties_get_int( properties, "channels" ); + int samples = 0; + mlt_image_format iformat = mlt_image_yuv422; + mlt_audio_format aformat = mlt_audio_s16; + uint8_t *buffer; + + mlt_frame_get_image( frame, &buffer, &iformat, &width, &height, 0 ); + mlt_frame_get_audio( frame, (void**) &buffer, &aformat, &frequency, &channels, &samples ); + + // Close the frame + mlt_events_fire( properties, "consumer-frame-show", frame, NULL ); + mlt_frame_close( frame ); + } + } + output_xml( this ); + + // Indicate that the consumer is stopped + mlt_properties_set_int( properties, "running", 0 ); + mlt_consumer_stopped( this ); + + return NULL; } diff --git a/src/modules/xml/consumer_xml.yml b/src/modules/xml/consumer_xml.yml index d729dd2e..894eff99 100644 --- a/src/modules/xml/consumer_xml.yml +++ b/src/modules/xml/consumer_xml.yml @@ -28,3 +28,16 @@ parameters: mutable: no default: stdout widget: fileopen + - identifier: all + title: Process all frames + type: integer + description: > + Without this option, the XML consumer does not process any frames + and simply serializes the service network. However, some filters (.e.g, + videostab) require two passes where the first pass performs some + analysis and stores the result in a property. Therefore, set this + property to 1 (true) to cause the consumer to process all frames + before serializing to XML. + minimum: 0 + maximum: 1 + default: 0