#!/bin/sh
export version=0.8.9
-export soversion=5
+export soversion=6
show_help()
{
pthread_mutex_lock( &self->queue_mutex );
while( self->ahead && mlt_deque_count( self->queue ) >= buffer )
pthread_cond_wait( &self->queue_cond, &self->queue_mutex );
- mlt_deque_push_back( self->queue, frame );
+ if ( self->is_purge )
+ {
+ mlt_frame_close( frame );
+ self->is_purge = 0;
+ }
+ else
+ {
+ mlt_deque_push_back( self->queue, frame );
+ }
pthread_cond_broadcast( &self->queue_cond );
pthread_mutex_unlock( &self->queue_mutex );
pthread_cond_broadcast( &self->done_cond );
pthread_mutex_unlock( &self->done_mutex );
}
- mlt_events_fire( properties, "consumer-thread-stopped" );
+ mlt_events_fire( properties, "consumer-thread-stopped", NULL );
return NULL;
}
void mlt_consumer_purge( mlt_consumer self )
{
- if ( self && self->ahead )
+ if ( self )
{
+ pthread_mutex_lock( &self->put_mutex );
+ if ( self->put ) {
+ mlt_frame_close( self->put );
+ self->put = NULL;
+ }
+ pthread_cond_broadcast( &self->put_cond );
+ pthread_mutex_unlock( &self->put_mutex );
+
if ( self->ahead && self->real_time )
pthread_mutex_lock( &self->queue_mutex );
+
+ if ( self->purge )
+ self->purge( self );
+
while ( mlt_deque_count( self->queue ) )
mlt_frame_close( mlt_deque_pop_back( self->queue ) );
- if ( self->ahead && self->real_time ) {
+ if ( self->ahead && self->real_time )
+ {
+ self->is_purge = 1;
pthread_cond_broadcast( &self->queue_cond );
pthread_mutex_unlock( &self->queue_mutex );
+ if ( abs( self->real_time ) > 1 )
+ {
+ pthread_mutex_lock( &self->done_mutex );
+ pthread_cond_broadcast( &self->done_cond );
+ pthread_mutex_unlock( &self->done_mutex );
+ }
}
+
+ pthread_mutex_lock( &self->put_mutex );
+ if ( self->put ) {
+ mlt_frame_close( self->put );
+ self->put = NULL;
+ }
+ pthread_cond_broadcast( &self->put_cond );
+ pthread_mutex_unlock( &self->put_mutex );
}
}
while ( self->ahead && mlt_deque_count( self->queue ) < buffer )
{
frame = mlt_consumer_get_frame( self );
- if ( ! frame )
- return frame;
- pthread_mutex_lock( &self->queue_mutex );
- mlt_deque_push_back( self->queue, frame );
- pthread_cond_signal( &self->queue_cond );
- pthread_mutex_unlock( &self->queue_mutex );
+ if ( frame )
+ {
+ pthread_mutex_lock( &self->queue_mutex );
+ mlt_deque_push_back( self->queue, frame );
+ pthread_cond_signal( &self->queue_cond );
+ pthread_mutex_unlock( &self->queue_mutex );
+ }
}
// Wait if not realtime.
- mlt_frame head_frame = MLT_FRAME( mlt_deque_peek_front( self->queue ) );
- while ( self->ahead && self->real_time < 0 &&
- !( head_frame && mlt_properties_get_int( MLT_FRAME_PROPERTIES( head_frame ), "rendered" ) ) )
+ while ( self->ahead && self->real_time < 0 && !self->is_purge &&
+ !( mlt_properties_get_int( MLT_FRAME_PROPERTIES( MLT_FRAME( mlt_deque_peek_front( self->queue ) ) ), "rendered" ) ) )
{
pthread_mutex_lock( &self->done_mutex );
pthread_cond_wait( &self->done_cond, &self->done_mutex );
pthread_mutex_unlock( &self->done_mutex );
}
-
+
// Get the frame from the queue.
pthread_mutex_lock( &self->queue_mutex );
frame = mlt_deque_pop_front( self->queue );
pthread_mutex_unlock( &self->queue_mutex );
+ if ( ! frame ) {
+ self->is_purge = 0;
+ return frame;
+ }
// Adapt the worker process head to the runtime conditions.
if ( self->real_time > 0 )
{
- if ( frame && mlt_properties_get_int( MLT_FRAME_PROPERTIES( frame ), "rendered" ) )
+ if ( mlt_properties_get_int( MLT_FRAME_PROPERTIES( frame ), "rendered" ) )
{
self->consecutive_dropped = 0;
if ( self->process_head > threads && self->consecutive_rendered >= self->process_head )
}
}
}
-
+ if ( self->is_purge ) {
+ self->is_purge = 0;
+ mlt_frame_close( frame );
+ frame = NULL;
+ }
return frame;
}
*/
int ( *is_stopped )( mlt_consumer );
+ /** Purge the consumer of buffered data (virtual function).
+ *
+ * \param mlt_consumer a consumer
+ */
+ void ( *purge )( mlt_consumer );
+
/** The destructor virtual function
*
* \param mlt_consumer a consumer
int put_active;
mlt_event event_listener;
mlt_position position;
+ int is_purge;
/* additional fields added for the parallel work queue */
mlt_deque worker_threads;
SDL_Rect rect;
uint8_t *buffer;
int bpp;
+ int is_purge;
};
/** Forward references to static functions.
static int consumer_start( mlt_consumer parent );
static int consumer_stop( mlt_consumer parent );
static int consumer_is_stopped( mlt_consumer parent );
+static void consumer_purge( mlt_consumer parent );
static void consumer_close( mlt_consumer parent );
static void *consumer_thread( void * );
static int consumer_get_dimensions( int *width, int *height );
parent->start = consumer_start;
parent->stop = consumer_stop;
parent->is_stopped = consumer_is_stopped;
+ parent->purge = consumer_purge;
// Register specific events
mlt_events_register( self->properties, "consumer-sdl-event", ( mlt_transmitter )consumer_sdl_event );
return !self->running;
}
+void consumer_purge( mlt_consumer parent )
+{
+ consumer_sdl self = parent->child;
+ if ( self->running )
+ {
+ pthread_mutex_lock( &self->video_mutex );
+ while ( mlt_deque_count( self->queue ) )
+ mlt_frame_close( mlt_deque_pop_back( self->queue ) );
+ self->is_purge = 1;
+ pthread_cond_broadcast( &self->video_cond );
+ pthread_mutex_unlock( &self->video_mutex );
+ }
+}
+
static int sdl_lock_display( )
{
pthread_mutex_lock( &mlt_sdl_mutex );
// Push this frame to the back of the queue
pthread_mutex_lock( &self->video_mutex );
- mlt_deque_push_back( self->queue, frame );
- pthread_cond_broadcast( &self->video_cond );
+ if ( self->is_purge )
+ {
+ mlt_frame_close( frame );
+ frame = NULL;
+ self->is_purge = 0;
+ }
+ else
+ {
+ mlt_deque_push_back( self->queue, frame );
+ pthread_cond_broadcast( &self->video_cond );
+ }
pthread_mutex_unlock( &self->video_mutex );
// Calculate the next playtime
pthread_cond_t refresh_cond;
pthread_mutex_t refresh_mutex;
int refresh_count;
+ int is_purge;
};
/** Forward references to static functions.
static int consumer_start( mlt_consumer parent );
static int consumer_stop( mlt_consumer parent );
static int consumer_is_stopped( mlt_consumer parent );
+static void consumer_purge( mlt_consumer parent );
static void consumer_close( mlt_consumer parent );
static void *consumer_thread( void * );
static void consumer_refresh_cb( mlt_consumer sdl, mlt_consumer self, char *name );
parent->start = consumer_start;
parent->stop = consumer_stop;
parent->is_stopped = consumer_is_stopped;
+ parent->purge = consumer_purge;
// Initialize the refresh handler
pthread_cond_init( &self->refresh_cond, NULL );
return !self->running;
}
+void consumer_purge( mlt_consumer parent )
+{
+ consumer_sdl self = parent->child;
+ if ( self->running )
+ {
+ pthread_mutex_lock( &self->video_mutex );
+ while ( mlt_deque_count( self->queue ) )
+ mlt_frame_close( mlt_deque_pop_back( self->queue ) );
+ self->is_purge = 1;
+ pthread_cond_broadcast( &self->video_cond );
+ pthread_mutex_unlock( &self->video_mutex );
+ }
+}
+
static void sdl_fill_audio( void *udata, uint8_t *stream, int len )
{
consumer_sdl self = udata;
mlt_properties properties = self->properties;
if ( self->running && !mlt_consumer_is_stopped( &self->parent ) )
mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
-
return 0;
}
if ( self->running && speed )
{
pthread_mutex_lock( &self->video_mutex );
- mlt_deque_push_back( self->queue, frame );
- pthread_cond_broadcast( &self->video_cond );
+ if ( self->is_purge )
+ {
+ mlt_frame_close( frame );
+ self->is_purge = 0;
+ }
+ else
+ {
+ mlt_deque_push_back( self->queue, frame );
+ pthread_cond_broadcast( &self->video_cond );
+ }
pthread_mutex_unlock( &self->video_mutex );
// Calculate the next playtime
static int consumer_start( mlt_consumer parent );
static int consumer_stop( mlt_consumer parent );
static int consumer_is_stopped( mlt_consumer parent );
+static void consumer_purge( mlt_consumer parent );
static void consumer_close( mlt_consumer parent );
static void *consumer_thread( void * );
static void consumer_frame_show_cb( mlt_consumer sdl, mlt_consumer self, mlt_frame frame );
parent->start = consumer_start;
parent->stop = consumer_stop;
parent->is_stopped = consumer_is_stopped;
+ parent->purge = consumer_purge;
self->joined = 1;
mlt_events_listen( MLT_CONSUMER_PROPERTIES( self->play ), self, "consumer-frame-show", ( mlt_listener )consumer_frame_show_cb );
mlt_events_listen( MLT_CONSUMER_PROPERTIES( self->still ), self, "consumer-frame-show", ( mlt_listener )consumer_frame_show_cb );
return !self->running;
}
+void consumer_purge( mlt_consumer parent )
+{
+ consumer_sdl self = parent->child;
+ if ( self->running )
+ mlt_consumer_purge( self->play );
+}
+
static void *consumer_thread( void *arg )
{
// Identify the arg