X-Git-Url: http://research.m1stereo.tv/gitweb?a=blobdiff_plain;f=src%2Fframework%2Fmlt_consumer.c;h=04ef94e2ee366984acb65dda79260b10685605de;hb=51f99c29759e71318c4c575f8a68cf1b5d1c5137;hp=8ed90c7256dce4effaa2c1bdbbc9982c07d3af19;hpb=e5fd66367b6f976e3bcb0ada98408afcb40cb2ce;p=melted diff --git a/src/framework/mlt_consumer.c b/src/framework/mlt_consumer.c index 8ed90c7..04ef94e 100644 --- a/src/framework/mlt_consumer.c +++ b/src/framework/mlt_consumer.c @@ -25,12 +25,16 @@ #include "mlt_producer.h" #include "mlt_frame.h" #include "mlt_profile.h" +#include "mlt_log.h" #include #include #include #include +/** Define this if you want an automatic deinterlace (if necessary) when the + * consumer's producer is not running at normal speed. + */ #undef DEINTERLACE_ON_NOT_NORMAL_SPEED static void mlt_consumer_frame_render( mlt_listener listener, mlt_properties owner, mlt_service this, void **args ); @@ -38,6 +42,16 @@ static void mlt_consumer_frame_show( mlt_listener listener, mlt_properties owner static void mlt_consumer_property_changed( mlt_service owner, mlt_consumer this, char *name ); static void apply_profile_properties( mlt_consumer this, mlt_profile profile, mlt_properties properties ); +/** Initialize a consumer service. + * + * \public \memberof mlt_consumer_s + * \param this the consumer to initialize + * \param child a pointer to the object for the subclass + * \param profile the \p mlt_profile_s to use (optional but recommended, + * uses the environment variable MLT if this is NULL) + * \return true if there was an error + */ + int mlt_consumer_init( mlt_consumer this, void *child, mlt_profile profile ) { int error = 0; @@ -95,6 +109,14 @@ int mlt_consumer_init( mlt_consumer this, void *child, mlt_profile profile ) return error; } +/** Convert the profile into properties on the consumer. + * + * \private \memberof mlt_consumer_s + * \param this a consumer + * \param profile a profile + * \param properties a properties list (typically, the consumer's) + */ + static void apply_profile_properties( mlt_consumer this, mlt_profile profile, mlt_properties properties ) { mlt_event_block( this->event_listener ); @@ -113,6 +135,14 @@ static void apply_profile_properties( mlt_consumer this, mlt_profile profile, ml mlt_event_unblock( this->event_listener ); } +/** The property-changed event listener + * + * \private \memberof mlt_consumer_s + * \param owner the service a service (ignored) + * \param this the consumer + * \param name the name of the property that changed + */ + static void mlt_consumer_property_changed( mlt_service owner, mlt_consumer this, char *name ) { if ( !strcmp( name, "profile" ) ) @@ -224,12 +254,34 @@ static void mlt_consumer_property_changed( mlt_service owner, mlt_consumer this, } } +/** The transmitter for the consumer-frame-show event + * + * Invokes the listener. + * + * \private \memberof mlt_consumer_s + * \param listener a function pointer that will be invoked + * \param owner a properties list that will be passed to \p listener + * \param this a service that will be passed to \p listener + * \param args an array of pointers - the first entry is passed as a string to \p listener + */ + static void mlt_consumer_frame_show( mlt_listener listener, mlt_properties owner, mlt_service this, void **args ) { if ( listener != NULL ) listener( owner, this, ( mlt_frame )args[ 0 ] ); } +/** The transmitter for the consumer-frame-render event + * + * Invokes the listener. + * + * \private \memberof mlt_consumer_s + * \param listener a function pointer that will be invoked + * \param owner a properties list that will be passed to \p listener + * \param this a service that will be passed to \p listener + * \param args an array of pointers - the first entry is passed as a string to \p listener + */ + static void mlt_consumer_frame_render( mlt_listener listener, mlt_properties owner, mlt_service this, void **args ) { if ( listener != NULL ) @@ -237,7 +289,11 @@ static void mlt_consumer_frame_render( mlt_listener listener, mlt_properties own } /** Create a new consumer. -*/ + * + * \public \memberof mlt_consumer_s + * \param profile a profile (optional, but recommended) + * \return a new consumer + */ mlt_consumer mlt_consumer_new( mlt_profile profile ) { @@ -253,7 +309,12 @@ mlt_consumer mlt_consumer_new( mlt_profile profile ) } /** Get the parent service object. -*/ + * + * \public \memberof mlt_consumer_s + * \param this a consumer + * \return the parent service class + * \see MLT_CONSUMER_SERVICE + */ mlt_service mlt_consumer_service( mlt_consumer this ) { @@ -261,7 +322,12 @@ mlt_service mlt_consumer_service( mlt_consumer this ) } /** Get the consumer properties. -*/ + * + * \public \memberof mlt_consumer_s + * \param this a consumer + * \return the consumer's properties list + * \see MLT_CONSUMER_PROPERTIES + */ mlt_properties mlt_consumer_properties( mlt_consumer this ) { @@ -269,7 +335,15 @@ mlt_properties mlt_consumer_properties( mlt_consumer this ) } /** Connect the consumer to the producer. -*/ + * + * \public \memberof mlt_consumer_s + * \param this a consumer + * \param producer a producer + * \return > 0 warning, == 0 success, < 0 serious error, + * 1 = this service does not accept input, + * 2 = the producer is invalid, + * 3 = the producer is already registered with this consumer + */ int mlt_consumer_connect( mlt_consumer this, mlt_service producer ) { @@ -277,7 +351,11 @@ int mlt_consumer_connect( mlt_consumer this, mlt_service producer ) } /** Start the consumer. -*/ + * + * \public \memberof mlt_consumer_s + * \param this a consumer + * \return true if there was an error + */ int mlt_consumer_start( mlt_consumer this ) { @@ -342,9 +420,15 @@ int mlt_consumer_start( mlt_consumer this ) return 0; } -/** An alternative method to feed frames into the consumer - only valid if - the consumer itself is not connected. -*/ +/** An alternative method to feed frames into the consumer. + * + * Only valid if the consumer itself is not connected. + * + * \public \memberof mlt_consumer_s + * \param this a consumer + * \param frame a frame + * \return true (ignore this for now) + */ int mlt_consumer_put_frame( mlt_consumer this, mlt_frame frame ) { @@ -381,7 +465,11 @@ int mlt_consumer_put_frame( mlt_consumer this, mlt_frame frame ) } /** Protected method for consumer to get frames from connected service -*/ + * + * \public \memberof mlt_consumer_s + * \param this a consumer + * \return a frame + */ mlt_frame mlt_consumer_get_frame( mlt_consumer this ) { @@ -448,6 +536,13 @@ mlt_frame mlt_consumer_get_frame( mlt_consumer this ) return frame; } +/** Compute the time difference between now and a time value. + * + * \private \memberof mlt_consumer_s + * \param time1 a time value to be compared against now + * \return the difference in microseconds + */ + static inline long time_difference( struct timeval *time1 ) { struct timeval time2; @@ -457,6 +552,13 @@ static inline long time_difference( struct timeval *time1 ) return time1->tv_sec * 1000000 + time1->tv_usec - time2.tv_sec * 1000000 - time2.tv_usec; } +/** The thread procedure for asynchronously pulling frames through the service + * network connected to a consumer. + * + * \private \memberof mlt_consumer_s + * \param arg a consumer + */ + static void *consumer_read_ahead_thread( void *arg ) { // The argument is the consumer @@ -643,6 +745,12 @@ static void *consumer_read_ahead_thread( void *arg ) return NULL; } +/** Start the read/render thread. + * + * \private \memberof mlt_consumer_s + * \param this a consumer + */ + static void consumer_read_ahead_start( mlt_consumer this ) { // We're running now @@ -678,6 +786,12 @@ static void consumer_read_ahead_start( mlt_consumer this ) } } +/** Stop the read/render thread. + * + * \private \memberof mlt_consumer_s + * \param this a consumer + */ + static void consumer_read_ahead_stop( mlt_consumer this ) { // Make sure we're running @@ -714,6 +828,12 @@ static void consumer_read_ahead_stop( mlt_consumer this ) } } +/** Flush the read/render thread's buffer. + * + * \public \memberof mlt_consumer_s + * \param this a consumer + */ + void mlt_consumer_purge( mlt_consumer this ) { if ( this->ahead ) @@ -726,6 +846,17 @@ void mlt_consumer_purge( mlt_consumer this ) } } +/** Get the next frame from the producer connected to a consumer. + * + * Typically, one uses this instead of \p mlt_consumer_get_frame to make + * the asynchronous/real-time behavior configurable at runtime. + * You should close the frame returned from this when you are done with it. + * + * \public \memberof mlt_consumer_s + * \param this a consumer + * \return a frame + */ + mlt_frame mlt_consumer_rt_frame( mlt_consumer this ) { // Frame to return @@ -771,7 +902,10 @@ mlt_frame mlt_consumer_rt_frame( mlt_consumer this ) } /** Callback for the implementation to indicate a stopped condition. -*/ + * + * \public \memberof mlt_consumer_s + * \param this a consumer + */ void mlt_consumer_stopped( mlt_consumer this ) { @@ -781,28 +915,31 @@ void mlt_consumer_stopped( mlt_consumer this ) } /** Stop the consumer. -*/ + * + * \public \memberof mlt_consumer_s + * \param this a consumer + * \return true if there was an error + */ int mlt_consumer_stop( mlt_consumer this ) { // Get the properies mlt_properties properties = MLT_CONSUMER_PROPERTIES( this ); - char *debug = mlt_properties_get( MLT_CONSUMER_PROPERTIES( this ), "debug" ); // Just in case... - if ( debug ) fprintf( stderr, "%s: stopping put waiting\n", debug ); + mlt_log( MLT_CONSUMER_SERVICE( this ), MLT_LOG_DEBUG, "stopping put waiting\n" ); pthread_mutex_lock( &this->put_mutex ); this->put_active = 0; pthread_cond_broadcast( &this->put_cond ); pthread_mutex_unlock( &this->put_mutex ); // Stop the consumer - if ( debug ) fprintf( stderr, "%s: stopping consumer\n", debug ); + mlt_log( MLT_CONSUMER_SERVICE( this ), MLT_LOG_DEBUG, "stopping consumer\n" ); if ( this->stop != NULL ) this->stop( this ); // Check if the user has requested real time or not and stop if necessary - if ( debug ) fprintf( stderr, "%s: stopping read_ahead\n", debug ); + mlt_log( MLT_CONSUMER_SERVICE( this ), MLT_LOG_DEBUG, "stopping read_ahead\n" ); if ( mlt_properties_get_int( properties, "real_time" ) ) consumer_read_ahead_stop( this ); @@ -813,13 +950,17 @@ int mlt_consumer_stop( mlt_consumer this ) if ( mlt_properties_get( properties, "post" ) ) system( mlt_properties_get( properties, "post" ) ); - if ( debug ) fprintf( stderr, "%s: stopped\n", debug ); + mlt_log( MLT_CONSUMER_SERVICE( this ), MLT_LOG_DEBUG, "stopped\n" ); return 0; } /** Determine if the consumer is stopped. -*/ + * + * \public \memberof mlt_consumer_s + * \param this a consumer + * \return true if the consumer is stopped + */ int mlt_consumer_is_stopped( mlt_consumer this ) { @@ -830,8 +971,11 @@ int mlt_consumer_is_stopped( mlt_consumer this ) return 0; } -/** Close the consumer. -*/ +/** Close and destroy the consumer. + * + * \public \memberof mlt_consumer_s + * \param this a consumer + */ void mlt_consumer_close( mlt_consumer this ) {