From 77a1a6728272d122e878834539761ac574f6c1da Mon Sep 17 00:00:00 2001 From: lilo_booter Date: Thu, 11 Nov 2004 19:19:26 +0000 Subject: [PATCH] Playlist and blank rearrangement, fix for mlt_consumer and NULL git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@519 d19143bc-622f-0410-bfdd-b5b2a6649095 --- src/framework/mlt_consumer.c | 40 +++++++++-- src/framework/mlt_playlist.c | 143 ++++++++++++++++++++++++++++++++++++--- src/framework/mlt_playlist.h | 3 + src/framework/mlt_producer.c | 23 +++++-- src/framework/mlt_producer.h | 1 + src/framework/mlt_transition.c | 3 +- src/modules/dv/consumer_libdv.c | 10 +++ 7 files changed, 200 insertions(+), 23 deletions(-) diff --git a/src/framework/mlt_consumer.c b/src/framework/mlt_consumer.c index ae79cf9..c6babd8 100644 --- a/src/framework/mlt_consumer.c +++ b/src/framework/mlt_consumer.c @@ -154,6 +154,10 @@ int mlt_consumer_start( mlt_consumer this ) // Determine if there's a test card producer char *test_card = mlt_properties_get( properties, "test_card" ); + // Just to make sure nothing is hanging around... + mlt_frame_close( this->put ); + this->put = NULL; + // Deal with it now. if ( test_card != NULL ) { @@ -206,9 +210,16 @@ int mlt_consumer_put_frame( mlt_consumer this, mlt_frame frame ) if ( mlt_service_producer( service ) == NULL ) { + struct timeval now; + struct timespec tm; pthread_mutex_lock( &this->put_mutex ); - if ( this->put != NULL ) - pthread_cond_wait( &this->put_cond, &this->put_mutex ); + while ( !mlt_consumer_is_stopped( this ) && this->put != NULL ) + { + gettimeofday( &now, NULL ); + tm.tv_sec = now.tv_sec + 1; + tm.tv_nsec = now.tv_usec * 1000; + pthread_cond_timedwait( &this->put_cond, &this->put_mutex, &tm ); + } if ( this->put == NULL ) this->put = frame; else @@ -241,9 +252,16 @@ mlt_frame mlt_consumer_get_frame( mlt_consumer this ) // Get the frame if ( mlt_service_producer( service ) == NULL && mlt_properties_get_int( properties, "put_mode" ) ) { + struct timeval now; + struct timespec tm; pthread_mutex_lock( &this->put_mutex ); - if ( this->put == NULL ) - pthread_cond_wait( &this->put_cond, &this->put_mutex ); + while ( !mlt_consumer_is_stopped( this ) && this->put == NULL ) + { + gettimeofday( &now, NULL ); + tm.tv_sec = now.tv_sec + 1; + tm.tv_nsec = now.tv_usec * 1000; + pthread_cond_timedwait( &this->put_cond, &this->put_mutex, &tm ); + } frame = this->put; this->put = NULL; pthread_cond_broadcast( &this->put_cond ); @@ -251,8 +269,12 @@ mlt_frame mlt_consumer_get_frame( mlt_consumer this ) if ( frame != NULL ) mlt_service_apply_filters( service, frame, 0 ); } + else if ( mlt_service_producer( service ) != NULL ) + { + mlt_service_get_frame( service, &frame, 0 ); + } - if ( frame != NULL || mlt_service_get_frame( service, &frame, 0 ) == 0 ) + if ( frame != NULL ) { // Get the frame properties mlt_properties frame_properties = mlt_frame_properties( frame ); @@ -360,12 +382,17 @@ static void *consumer_read_ahead_thread( void *arg ) mlt_deque_push_back( this->queue, frame ); pthread_cond_broadcast( &this->cond ); pthread_mutex_unlock( &this->mutex ); + time_wait += time_difference( &ante ); // Get the next frame frame = mlt_consumer_get_frame( this ); time_frame += time_difference( &ante ); + // If there's no frame, we're probably stopped... + if ( frame == NULL ) + continue; + // Increment the count count ++; @@ -536,7 +563,8 @@ mlt_frame mlt_consumer_rt_frame( mlt_consumer this ) frame = mlt_consumer_get_frame( this ); // This isn't true, but from the consumers perspective it is - mlt_properties_set_int( mlt_frame_properties( frame ), "rendered", 1 ); + if ( frame != NULL ) + mlt_properties_set_int( mlt_frame_properties( frame ), "rendered", 1 ); } return frame; diff --git a/src/framework/mlt_playlist.c b/src/framework/mlt_playlist.c index ddcc28f..0e29e3f 100644 --- a/src/framework/mlt_playlist.c +++ b/src/framework/mlt_playlist.c @@ -169,9 +169,8 @@ static int mlt_playlist_virtual_refresh( mlt_playlist this ) } // Check if the length of the producer has changed - if ( this->list[ i ]->producer != &this->blank && - ( this->list[ i ]->frame_in != mlt_producer_get_in( producer ) || - this->list[ i ]->frame_out != mlt_producer_get_out( producer ) ) ) + if ( this->list[ i ]->frame_in != mlt_producer_get_in( producer ) || + this->list[ i ]->frame_out != mlt_producer_get_out( producer ) ) { // This clip should be removed... if ( current_length < 1 ) @@ -222,17 +221,38 @@ static void mlt_playlist_listener( mlt_producer producer, mlt_playlist this ) static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer source, mlt_position in, mlt_position out ) { - char *resource = source != NULL ? mlt_properties_get( mlt_producer_properties( source ), "resource" ) : NULL; mlt_producer producer = NULL; mlt_properties properties = NULL; mlt_properties parent = NULL; // If we have a cut, then use the in/out points from the cut - if ( resource == NULL || !strcmp( resource, "blank" ) ) + if ( mlt_producer_is_blank( source ) ) { - producer = &this->blank; + // Make sure the blank is long enough to accomodate the length specified + if ( out - in + 1 > mlt_producer_get_length( &this->blank ) ) + { + mlt_properties blank_props = mlt_producer_properties( &this->blank ); + mlt_events_block( blank_props, blank_props ); + mlt_producer_set_in_and_out( &this->blank, in, out ); + mlt_events_unblock( blank_props, blank_props ); + } + + // Now make sure the cut comes from this this->blank + if ( source == NULL ) + { + producer = mlt_producer_cut( &this->blank, in, out ); + } + else if ( !mlt_producer_is_cut( source ) || mlt_producer_cut_parent( source ) != &this->blank ) + { + producer = mlt_producer_cut( &this->blank, in, out ); + } + else + { + producer = source; + mlt_properties_inc_ref( mlt_producer_properties( producer ) ); + } + properties = mlt_producer_properties( producer ); - mlt_properties_inc_ref( properties ); } else if ( mlt_producer_is_cut( source ) ) { @@ -749,6 +769,18 @@ int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_position in, mlt_ playlist_entry *entry = this->list[ clip ]; mlt_producer producer = entry->producer; + if ( mlt_producer_is_blank( producer ) ) + { + // Make sure the blank is long enough to accomodate the length specified + if ( out - in + 1 > mlt_producer_get_length( &this->blank ) ) + { + mlt_properties blank_props = mlt_producer_properties( &this->blank ); + mlt_events_block( blank_props, blank_props ); + mlt_producer_set_in_and_out( &this->blank, in, out ); + mlt_events_unblock( blank_props, blank_props ); + } + } + if ( in <= -1 ) in = 0; if ( out <= -1 || out >= mlt_producer_get_length( producer ) ) @@ -778,14 +810,20 @@ int mlt_playlist_split( mlt_playlist this, int clip, mlt_position position ) position = position < 0 ? entry->frame_count + position - 1 : position; if ( position >= 0 && position <= entry->frame_count ) { - mlt_producer split = NULL; int in = entry->frame_in; int out = entry->frame_out; mlt_events_block( mlt_playlist_properties( this ), this ); mlt_playlist_resize_clip( this, clip, in, in + position ); - split = mlt_producer_cut( entry->producer, in + position + 1, out ); - mlt_playlist_insert( this, split, clip + 1, 0, -1 ); - mlt_producer_close( split ); + if ( !mlt_producer_is_blank( entry->producer ) ) + { + mlt_producer split = mlt_producer_cut( entry->producer, in + position + 1, out ); + mlt_playlist_insert( this, split, clip + 1, 0, -1 ); + mlt_producer_close( split ); + } + else + { + mlt_playlist_insert( this, &this->blank, clip + 1, 0, out - position - 1 ); + } mlt_events_unblock( mlt_playlist_properties( this ), this ); mlt_events_fire( mlt_playlist_properties( this ), "producer-changed", NULL ); } @@ -1079,11 +1117,87 @@ static int mlt_playlist_resize_mix( mlt_playlist this, int clip, int in, int out return error; } +/** Consolodate adjacent blank producers. +*/ + +void mlt_playlist_consolidate_blanks( mlt_playlist this, int keep_length ) +{ + if ( this != NULL ) + { + int i = 0; + mlt_properties properties = mlt_playlist_properties( this ); + + mlt_events_block( properties, properties ); + for ( i = 1; i < this->count; i ++ ) + { + playlist_entry *left = this->list[ i - 1 ]; + playlist_entry *right = this->list[ i ]; + + if ( mlt_producer_cut_parent( left->producer ) == mlt_producer_cut_parent( right->producer ) && + mlt_producer_is_blank( left->producer ) ) + { + mlt_playlist_resize_clip( this, i - 1, 0, left->frame_count + right->frame_count - 1 ); + mlt_playlist_remove( this, i -- ); + } + } + + if ( !keep_length ) + { + playlist_entry *last = this->list[ this->count - 1 ]; + if ( mlt_producer_is_blank( last->producer ) ) + mlt_playlist_remove( this, this->count - 1 ); + } + + mlt_events_unblock( properties, properties ); + mlt_playlist_virtual_refresh( this ); + } +} + +/** Determine if the specified clip index is a blank. +*/ + +int mlt_playlist_is_blank( mlt_playlist this, int clip ) +{ + return this == NULL || mlt_producer_is_blank( mlt_playlist_get_clip( this, clip ) ); +} + +/** Replace the specified clip with a blank and return the clip. +*/ + +mlt_producer mlt_playlist_replace_with_blank( mlt_playlist this, int clip ) +{ + mlt_producer producer = NULL; + if ( !mlt_playlist_is_blank( this, clip ) ) + { + playlist_entry *entry = this->list[ clip ]; + int in = entry->frame_in; + int out = entry->frame_out; + mlt_properties properties = mlt_playlist_properties( this ); + producer = entry->producer; + mlt_properties_inc_ref( mlt_producer_properties( producer ) ); + mlt_events_block( properties, properties ); + mlt_playlist_remove( this, clip ); + mlt_playlist_blank( this, out - in ); + mlt_playlist_move( this, this->count - 1, clip ); + mlt_producer_set_in_and_out( producer, in, out ); + mlt_events_unblock( properties, properties ); + mlt_playlist_virtual_refresh( this ); + } + return producer; +} + /** Get the current frame. */ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index ) { + // Check that we have a producer + if ( producer == NULL ) + { + *frame = mlt_frame_init( ); + return 0; + } + // Get this mlt_playlist mlt_playlist this = producer->child; @@ -1093,6 +1207,13 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i // Get the real producer mlt_service real = mlt_playlist_virtual_seek( this, &progressive ); + // Check that we have a producer + if ( real == NULL ) + { + *frame = mlt_frame_init( ); + return 0; + } + // Get the frame mlt_service_get_frame( real, frame, index ); diff --git a/src/framework/mlt_playlist.h b/src/framework/mlt_playlist.h index 50b236d..ca193c9 100644 --- a/src/framework/mlt_playlist.h +++ b/src/framework/mlt_playlist.h @@ -71,6 +71,9 @@ extern mlt_producer mlt_playlist_get_clip( mlt_playlist self, int clip ); extern mlt_producer mlt_playlist_get_clip_at( mlt_playlist self, int position ); extern int mlt_playlist_get_clip_index_at( mlt_playlist self, int position ); extern int mlt_playlist_clip_is_mix( mlt_playlist self, int clip ); +extern void mlt_playlist_consolidate_blanks( mlt_playlist self, int keep_length ); +extern int mlt_playlist_is_blank( mlt_playlist self, int clip ); +extern mlt_producer mlt_playlist_replace_with_blank( mlt_playlist self, int clip ); extern void mlt_playlist_close( mlt_playlist self ); #endif diff --git a/src/framework/mlt_producer.c b/src/framework/mlt_producer.c index 17945f7..9ed89af 100644 --- a/src/framework/mlt_producer.c +++ b/src/framework/mlt_producer.c @@ -162,6 +162,14 @@ int mlt_producer_is_mix( mlt_producer this ) return tractor != NULL; } +/** Determine if the producer is a blank [from a playlist]. +*/ + +int mlt_producer_is_blank( mlt_producer this ) +{ + return this == NULL || !strcmp( mlt_properties_get( mlt_producer_properties( mlt_producer_cut_parent( this ) ), "resource" ), "blank" ); +} + /** Obtain the parent producer. */ @@ -187,7 +195,7 @@ mlt_producer mlt_producer_cut( mlt_producer this, int in, int out ) // Special case - allow for a cut of the entire producer (this will squeeze all other cuts to 0) if ( in <= 0 ) in = 0; - if ( out >= mlt_producer_get_playtime( parent ) ) + if ( out >= mlt_producer_get_playtime( parent ) && !mlt_producer_is_blank( this ) ) out = mlt_producer_get_playtime( parent ) - 1; mlt_properties_inc_ref( parent_props ); @@ -310,7 +318,7 @@ int mlt_producer_set_in_and_out( mlt_producer this, mlt_position in, mlt_positio if ( out < 0 ) out = 0; - else if ( out > mlt_producer_get_length( this ) ) + else if ( out > mlt_producer_get_length( this ) && !mlt_producer_is_blank( this ) ) out = mlt_producer_get_length( this ); // Swap ins and outs if wrong @@ -393,9 +401,9 @@ void mlt_producer_prepare_next( mlt_producer this ) static int producer_get_frame( mlt_service service, mlt_frame_ptr frame, int index ) { int result = 1; - mlt_producer this = service->child; + mlt_producer this = service != NULL ? service->child : NULL; - if ( !mlt_producer_is_cut( this ) ) + if ( this != NULL && !mlt_producer_is_cut( this ) ) { // Get the properties of this producer mlt_properties properties = mlt_producer_properties( this ); @@ -443,7 +451,7 @@ static int producer_get_frame( mlt_service service, mlt_frame_ptr frame, int ind if ( mlt_properties_get_data( properties, "_producer", NULL ) == NULL ) mlt_properties_set_data( properties, "_producer", service, 0, NULL, NULL ); } - else + else if ( this != NULL ) { // Get the speed of the cut double speed = mlt_producer_get_speed( this ); @@ -491,6 +499,11 @@ static int producer_get_frame( mlt_service service, mlt_frame_ptr frame, int ind mlt_properties_set_double( mlt_frame_properties( *frame ), "_speed", speed ); mlt_producer_prepare_next( this ); } + else + { + *frame = mlt_frame_init( ); + result = 0; + } return result; } diff --git a/src/framework/mlt_producer.h b/src/framework/mlt_producer.h index f79e192..a0c3356 100644 --- a/src/framework/mlt_producer.h +++ b/src/framework/mlt_producer.h @@ -68,6 +68,7 @@ extern mlt_filter mlt_producer_filter( mlt_producer self, int index ); extern mlt_producer mlt_producer_cut( mlt_producer self, int in, int out ); extern int mlt_producer_is_cut( mlt_producer self ); extern int mlt_producer_is_mix( mlt_producer self ); +extern int mlt_producer_is_blank( mlt_producer self ); extern mlt_producer mlt_producer_cut_parent( mlt_producer self ); extern int mlt_producer_optimise( mlt_producer self ); extern void mlt_producer_close( mlt_producer self ); diff --git a/src/framework/mlt_transition.c b/src/framework/mlt_transition.c index 1d2d3c3..7606ab1 100644 --- a/src/framework/mlt_transition.c +++ b/src/framework/mlt_transition.c @@ -182,6 +182,7 @@ static int transition_get_frame( mlt_service service, mlt_frame_ptr frame, int i int b_track = mlt_properties_get_int( properties, "b_track" ); mlt_position in = mlt_properties_get_position( properties, "in" ); mlt_position out = mlt_properties_get_position( properties, "out" ); + int always_active = mlt_properties_get_int( properties, "always_active" ); if ( ( index == a_track || index == b_track ) && !( this->a_held || this->b_held ) ) { @@ -196,7 +197,7 @@ static int transition_get_frame( mlt_service service, mlt_frame_ptr frame, int i { // Determine if we're in the right time zone mlt_position position = mlt_frame_get_position( this->a_frame ); - if ( position >= in && position <= out ) + if ( always_active || ( position >= in && position <= out ) ) { if ( !accepts_blanks && ( this->b_frame == NULL || ( mlt_frame_is_test_card( this->b_frame ) && mlt_frame_is_test_audio( this->b_frame ) ) ) ) { diff --git a/src/modules/dv/consumer_libdv.c b/src/modules/dv/consumer_libdv.c index 6dce526..cc3542f 100644 --- a/src/modules/dv/consumer_libdv.c +++ b/src/modules/dv/consumer_libdv.c @@ -373,6 +373,9 @@ static void *consumer_thread( void *arg ) // Get the properties mlt_properties properties = mlt_consumer_properties( this ); + // Get the terminate_on_pause property + int top = mlt_properties_get_int( properties, "terminate_on_pause" ); + // Get the handling methods int ( *video )( mlt_consumer, uint8_t *, mlt_frame ) = mlt_properties_get_data( properties, "video", NULL ); int ( *audio )( mlt_consumer, uint8_t *, mlt_frame ) = mlt_properties_get_data( properties, "audio", NULL ); @@ -394,6 +397,13 @@ static void *consumer_thread( void *arg ) // Check that we have a frame to work with if ( frame != NULL ) { + // Terminate on pause + if ( top && mlt_properties_get_double( mlt_frame_properties( frame ), "_speed" ) == 0 ) + { + mlt_frame_close( frame ); + break; + } + // Obtain the dv_encoder if ( libdv_get_encoder( this, frame ) != NULL ) { -- 1.7.4.4