X-Git-Url: http://research.m1stereo.tv/gitweb?a=blobdiff_plain;f=src%2Fframework%2Fmlt_playlist.c;h=0e29e3fb07b565b450a3788df61eee1298cd6dfc;hb=77a1a6728272d122e878834539761ac574f6c1da;hp=0787bfb6a2a0100d8b390cf9a870f4befd5684be;hpb=1a661f8a89220fc5cb26eabea46e2bf33ca31ed6;p=melted diff --git a/src/framework/mlt_playlist.c b/src/framework/mlt_playlist.c index 0787bfb..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 ) ) { @@ -286,52 +306,59 @@ static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer source, return mlt_playlist_virtual_refresh( this ); } -/** Seek in the virtual playlist. -*/ - -static mlt_service mlt_playlist_virtual_seek( mlt_playlist this, int *progressive ) +static mlt_producer mlt_playlist_locate( mlt_playlist this, mlt_position *position, int *clip, int *total ) { - // Default producer to blank + // Default producer to NULL mlt_producer producer = NULL; - // Map playlist position to real producer in virtual playlist - mlt_position position = mlt_producer_frame( &this->parent ); - - mlt_position original = position; - - // Total number of frames - int64_t total = 0; - - // Get the properties - mlt_properties properties = mlt_playlist_properties( this ); - - // Get the eof handling - char *eof = mlt_properties_get( properties, "eof" ); - - // Index for the main loop - int i = 0; - // Loop for each producer until found - for ( i = 0; i < this->count; i ++ ) + for ( *clip = 0; *clip < this->count; *clip += 1 ) { // Increment the total - total += this->list[ i ]->frame_count; + *total += this->list[ *clip ]->frame_count; // Check if the position indicates that we have found the clip // Note that 0 length clips get skipped automatically - if ( position < this->list[ i ]->frame_count ) + if ( *position < this->list[ *clip ]->frame_count ) { // Found it, now break - producer = this->list[ i ]->producer; + producer = this->list[ *clip ]->producer; break; } else { // Decrement position by length of this entry - position -= this->list[ i ]->frame_count; + *position -= this->list[ *clip ]->frame_count; } } + return producer; +} + +/** Seek in the virtual playlist. +*/ + +static mlt_service mlt_playlist_virtual_seek( mlt_playlist this, int *progressive ) +{ + // Map playlist position to real producer in virtual playlist + mlt_position position = mlt_producer_frame( &this->parent ); + + // Keep the original position since we change it while iterating through the list + mlt_position original = position; + + // Clip index and total + int i = 0; + int total = 0; + + // Locate the producer for the position + mlt_producer producer = mlt_playlist_locate( this, &position, &i, &total ); + + // Get the properties + mlt_properties properties = mlt_playlist_properties( this ); + + // Get the eof handling + char *eof = mlt_properties_get( properties, "eof" ); + // Seek in real producer to relative position if ( producer != NULL ) { @@ -742,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 ) ) @@ -771,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 ); } @@ -932,7 +977,7 @@ int mlt_playlist_mix_add( mlt_playlist this, int clip, mlt_transition transition return error; } -/** Return the clip at the position. +/** Return the clip at the clip index. */ mlt_producer mlt_playlist_get_clip( mlt_playlist this, int clip ) @@ -942,6 +987,25 @@ mlt_producer mlt_playlist_get_clip( mlt_playlist this, int clip ) return NULL; } +/** Return the clip at the specified position. +*/ + +mlt_producer mlt_playlist_get_clip_at( mlt_playlist this, int position ) +{ + int index = 0, total = 0; + return mlt_playlist_locate( this, &position, &index, &total ); +} + +/** Return the clip index of the specified position. +*/ + +int mlt_playlist_get_clip_index_at( mlt_playlist this, int position ) +{ + int index = 0, total = 0; + mlt_playlist_locate( this, &position, &index, &total ); + return index; +} + /** Determine if the clip is a mix. */ @@ -1053,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; @@ -1067,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 ); @@ -1078,7 +1225,7 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i // Set the consumer progressive property if ( progressive ) { - mlt_properties_set_int( properties, "consumer_progressive", progressive ); + mlt_properties_set_int( properties, "consumer_deinterlace", progressive ); mlt_properties_set_int( properties, "test_audio", 1 ); }