X-Git-Url: http://research.m1stereo.tv/gitweb?a=blobdiff_plain;f=src%2Fframework%2Fmlt_playlist.c;h=6ebf37af89576a6aa9c78d63e0e9514b3f98a00e;hb=76f260e441303164d9680fad0b52537a965e61b9;hp=c2f41915babec6b17031b4923c1015482851ceee;hpb=f1a97a77d0847a3cb4230ecf9fd088d1613e6540;p=melted diff --git a/src/framework/mlt_playlist.c b/src/framework/mlt_playlist.c index c2f4191..6ebf37a 100644 --- a/src/framework/mlt_playlist.c +++ b/src/framework/mlt_playlist.c @@ -43,6 +43,7 @@ typedef struct playlist_entry_s int repeat; mlt_position producer_length; mlt_event event; + int preservation_hack; } playlist_entry; @@ -99,7 +100,7 @@ mlt_playlist mlt_playlist_init( ) mlt_properties_set( mlt_playlist_properties( this ), "resource", "" ); mlt_properties_set( mlt_playlist_properties( this ), "mlt_type", "mlt_producer" ); mlt_properties_set_position( mlt_playlist_properties( this ), "in", 0 ); - mlt_properties_set_position( mlt_playlist_properties( this ), "out", 0 ); + mlt_properties_set_position( mlt_playlist_properties( this ), "out", -1 ); mlt_properties_set_position( mlt_playlist_properties( this ), "length", 0 ); this->size = 10; @@ -288,7 +289,7 @@ static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer source, /** Seek in the virtual playlist. */ -static mlt_service mlt_playlist_virtual_seek( mlt_playlist this ) +static mlt_service mlt_playlist_virtual_seek( mlt_playlist this, int *progressive ) { // Default producer to blank mlt_producer producer = NULL; @@ -335,17 +336,20 @@ static mlt_service mlt_playlist_virtual_seek( mlt_playlist this ) if ( producer != NULL ) { int count = this->list[ i ]->frame_count / this->list[ i ]->repeat; + *progressive = count == 1; mlt_producer_seek( producer, position % count ); } else if ( !strcmp( eof, "pause" ) && total > 0 ) { playlist_entry *entry = this->list[ this->count - 1 ]; + int count = entry->frame_count / entry->repeat; mlt_producer this_producer = mlt_playlist_producer( this ); mlt_producer_seek( this_producer, original - 1 ); producer = entry->producer; - mlt_producer_seek( producer, entry->frame_out ); + mlt_producer_seek( producer, entry->frame_out % count ); mlt_producer_set_speed( this_producer, 0 ); mlt_producer_set_speed( producer, 0 ); + *progressive = count == 1; } else if ( !strcmp( eof, "loop" ) && total > 0 ) { @@ -615,21 +619,25 @@ int mlt_playlist_remove( mlt_playlist this, int where ) this->list[ i - 1 ] = this->list[ i ]; this->count --; - // Decouple from mix_in/out if necessary - if ( mlt_properties_get_data( properties, "mix_in", NULL ) != NULL ) + if ( entry->preservation_hack == 0 ) { - mlt_properties mix = mlt_properties_get_data( properties, "mix_in", NULL ); - mlt_properties_set_data( mix, "mix_out", NULL, 0, NULL, NULL ); - } - if ( mlt_properties_get_data( properties, "mix_out", NULL ) != NULL ) - { - mlt_properties mix = mlt_properties_get_data( properties, "mix_out", NULL ); - mlt_properties_set_data( mix, "mix_in", NULL, 0, NULL, NULL ); + // Decouple from mix_in/out if necessary + if ( mlt_properties_get_data( properties, "mix_in", NULL ) != NULL ) + { + mlt_properties mix = mlt_properties_get_data( properties, "mix_in", NULL ); + mlt_properties_set_data( mix, "mix_out", NULL, 0, NULL, NULL ); + } + if ( mlt_properties_get_data( properties, "mix_out", NULL ) != NULL ) + { + mlt_properties mix = mlt_properties_get_data( properties, "mix_out", NULL ); + mlt_properties_set_data( mix, "mix_in", NULL, 0, NULL, NULL ); + } + + mlt_producer_clear( entry->producer ); } // Close the producer associated to the clip info mlt_event_close( entry->event ); - mlt_producer_clear( entry->producer ); mlt_producer_close( entry->producer ); // Correct position @@ -760,7 +768,8 @@ int mlt_playlist_split( mlt_playlist this, int clip, mlt_position position ) if ( error == 0 ) { playlist_entry *entry = this->list[ clip ]; - if ( position >= 0 && position < entry->frame_count ) + 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; @@ -799,6 +808,7 @@ int mlt_playlist_join( mlt_playlist this, int clip, int count, int merge ) playlist_entry *entry = this->list[ clip ]; mlt_playlist_append( new_clip, entry->producer ); mlt_playlist_repeat_clip( new_clip, i, entry->repeat ); + entry->preservation_hack = 1; mlt_playlist_remove( this, clip ); } mlt_events_unblock( mlt_playlist_properties( this ), this ); @@ -818,20 +828,25 @@ int mlt_playlist_mix( mlt_playlist this, int clip, int length, mlt_transition tr { playlist_entry *clip_a = this->list[ clip ]; playlist_entry *clip_b = this->list[ clip + 1 ]; - mlt_producer track_a; - mlt_producer track_b; + mlt_producer track_a = NULL; + mlt_producer track_b = NULL; mlt_tractor tractor = mlt_tractor_new( ); mlt_events_block( mlt_playlist_properties( this ), this ); - // TODO: Check length is valid for both clips and resize if necessary. + // Check length is valid for both clips and resize if necessary. + int max_size = clip_a->frame_count > clip_b->frame_count ? clip_a->frame_count : clip_b->frame_count; + length = length > max_size ? max_size : length; - // Create the a and b tracks/cuts - track_a = mlt_producer_cut( clip_a->producer, clip_a->frame_out - length + 1, clip_a->frame_out ); - track_b = mlt_producer_cut( clip_b->producer, clip_b->frame_in, clip_b->frame_in + length - 1 ); + // Create the a and b tracks/cuts if necessary - note that no cuts are required if the length matches + if ( length != clip_a->frame_count ) + track_a = mlt_producer_cut( clip_a->producer, clip_a->frame_out - length + 1, clip_a->frame_out ); + else + track_a = clip_a->producer; - // Temporary - for the benefit of westley serialisation - mlt_properties_set_int( mlt_producer_properties( track_a ), "cut", 1 ); - mlt_properties_set_int( mlt_producer_properties( track_b ), "cut", 1 ); + if ( length != clip_b->frame_count ) + track_b = mlt_producer_cut( clip_b->producer, clip_b->frame_in, clip_b->frame_in + length - 1 ); + else + track_b = clip_b->producer; // Set the tracks on the tractor mlt_tractor_set_track( tractor, track_a, 0 ); @@ -849,8 +864,19 @@ int mlt_playlist_mix( mlt_playlist this, int clip, int length, mlt_transition tr mlt_transition_set_in_and_out( transition, 0, length - 1 ); } + // Close our references to the tracks if we created new cuts above (the tracks can still be used here) + if ( track_a != clip_a->producer ) + mlt_producer_close( track_a ); + if ( track_b != clip_b->producer ) + mlt_producer_close( track_b ); + // Check if we have anything left on the right hand clip - if ( clip_b->frame_out - clip_b->frame_in > length ) + if ( track_b == clip_b->producer ) + { + clip_b->preservation_hack = 1; + mlt_playlist_remove( this, clip + 2 ); + } + else if ( clip_b->frame_out - clip_b->frame_in > length ) { mlt_playlist_resize_clip( this, clip + 2, clip_b->frame_in + length, clip_b->frame_out ); mlt_properties_set_data( mlt_producer_properties( clip_b->producer ), "mix_in", tractor, 0, NULL, NULL ); @@ -863,7 +889,12 @@ int mlt_playlist_mix( mlt_playlist this, int clip, int length, mlt_transition tr } // Check if we have anything left on the left hand clip - if ( clip_a->frame_out - clip_a->frame_in > length ) + if ( track_a == clip_a->producer ) + { + clip_a->preservation_hack = 1; + mlt_playlist_remove( this, clip ); + } + else if ( clip_a->frame_out - clip_a->frame_in > length ) { mlt_playlist_resize_clip( this, clip, clip_a->frame_in, clip_a->frame_out - length ); mlt_properties_set_data( mlt_producer_properties( clip_a->producer ), "mix_out", tractor, 0, NULL, NULL ); @@ -875,15 +906,53 @@ int mlt_playlist_mix( mlt_playlist this, int clip, int length, mlt_transition tr mlt_playlist_remove( this, clip ); } + // Unblock and force a fire off of change events to listeners mlt_events_unblock( mlt_playlist_properties( this ), this ); - mlt_events_fire( mlt_playlist_properties( this ), "producer-changed", NULL ); - mlt_producer_close( track_a ); - mlt_producer_close( track_b ); + mlt_playlist_virtual_refresh( this ); mlt_tractor_close( tractor ); } return error; } +/** Add a transition to an existing mix. +*/ + +int mlt_playlist_mix_add( mlt_playlist this, int clip, mlt_transition transition ) +{ + mlt_producer producer = mlt_producer_cut_parent( mlt_playlist_get_clip( this, clip ) ); + mlt_properties properties = producer != NULL ? mlt_producer_properties( producer ) : NULL; + mlt_tractor tractor = properties != NULL ? mlt_properties_get_data( properties, "mlt_mix", NULL ) : NULL; + int error = transition == NULL || tractor == NULL; + if ( error == 0 ) + { + mlt_field field = mlt_tractor_field( tractor ); + mlt_field_plant_transition( field, transition, 0, 1 ); + mlt_transition_set_in_and_out( transition, 0, this->list[ clip ]->frame_count - 1 ); + } + return error; +} + +/** Return the clip at the position. +*/ + +mlt_producer mlt_playlist_get_clip( mlt_playlist this, int clip ) +{ + if ( clip >= 0 && clip < this->count ) + return this->list[ clip ]->producer; + return NULL; +} + +/** Determine if the clip is a mix. +*/ + +int mlt_playlist_clip_is_mix( mlt_playlist this, int clip ) +{ + mlt_producer producer = mlt_producer_cut_parent( mlt_playlist_get_clip( this, clip ) ); + mlt_properties properties = producer != NULL ? mlt_producer_properties( producer ) : NULL; + mlt_tractor tractor = properties != NULL ? mlt_properties_get_data( properties, "mlt_mix", NULL ) : NULL; + return tractor != NULL; +} + /** Remove a mixed clip - ensure that the cuts included in the mix find their way back correctly on to the playlist. */ @@ -897,7 +966,8 @@ static int mlt_playlist_unmix( mlt_playlist this, int clip ) { mlt_producer producer = mlt_producer_cut_parent( this->list[ clip ]->producer ); mlt_properties properties = mlt_producer_properties( producer ); - error = mlt_properties_get_data( properties, "mlt_mix", NULL ) == NULL; + error = mlt_properties_get_data( properties, "mlt_mix", NULL ) == NULL || + this->list[ clip ]->preservation_hack; } if ( error == 0 ) @@ -991,8 +1061,11 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i // Get this mlt_playlist mlt_playlist this = producer->child; + // Need to ensure the frame is deinterlaced when repeating 1 frame + int progressive = 0; + // Get the real producer - mlt_service real = mlt_playlist_virtual_seek( this ); + mlt_service real = mlt_playlist_virtual_seek( this, &progressive ); // Get the frame mlt_service_get_frame( real, frame, index ); @@ -1002,6 +1075,13 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i if ( mlt_properties_get_int( properties, "end_of_clip" ) ) mlt_playlist_virtual_set_out( this ); + // Set the consumer progressive property + if ( progressive ) + { + mlt_properties_set_int( properties, "consumer_deinterlace", progressive ); + mlt_properties_set_int( properties, "test_audio", 1 ); + } + // Check for notifier and call with appropriate argument mlt_properties playlist_properties = mlt_producer_properties( producer ); void ( *notifier )( void * ) = mlt_properties_get_data( playlist_properties, "notifier", NULL );