killall miracle does not work. requires killall -HUP
STOP does not play the test card (white silence) (=pause)
USTA when stopped reports "paused"
-REW when stopped does not rewind to the beginning of the clip.
CLEAN removes all clips (as opposed to leaving the currently playing one)
USET eof=pause is partially supported
-SIN/SOUT do not leave the unit in a paused state
Different Intentional Behaviour
killall miracle does not work. requires killall -HUP
STOP does not play the test card (white silence) (=pause)
USTA when stopped reports "paused"
-REW when stopped does not rewind to the beginning of the clip.
CLEAN removes all clips (as opposed to leaving the currently playing one)
USET eof=pause is partially supported
-SIN/SOUT do not leave the unit in a paused state
Different Intentional Behaviour
void mlt_consumer_close( mlt_consumer this )
{
- if ( this->close != NULL )
- this->close( this );
+ // Get the childs close function
+ void ( *consumer_close )( ) = this->close;
+
+ // Make sure it only gets called once
+ this->close = NULL;
+
+ // Call the childs close if available
+ if ( consumer_close != NULL )
+ consumer_close( this );
else
mlt_service_close( &this->parent );
}
*/
#include "config.h"
-#include "mlt_factory.h"
+#include "mlt.h"
#include "mlt_repository.h"
-#include "mlt_properties.h"
#include <stdlib.h>
#include <string.h>
int mlt_factory_init( char *prefix )
{
- // If no directory is specified, default to install directory
- if ( prefix == NULL )
- prefix = PREFIX_DATA;
-
- // Store the prefix for later retrieval
- mlt_prefix = strdup( prefix );
-
- // Create the object list.
- object_list = calloc( sizeof( struct mlt_properties_s ), 1 );
- mlt_properties_init( object_list, NULL );
-
- // Create a repository for each service type
- producers = mlt_repository_init( object_list, prefix, "producers.dat", "mlt_create_producer" );
- filters = mlt_repository_init( object_list, prefix, "filters.dat", "mlt_create_filter" );
- transitions = mlt_repository_init( object_list, prefix, "transitions.dat", "mlt_create_transition" );
- consumers = mlt_repository_init( object_list, prefix, "consumers.dat", "mlt_create_consumer" );
+ // Only initialise once
+ if ( mlt_prefix == NULL )
+ {
+ // If no directory is specified, default to install directory
+ if ( prefix == NULL )
+ prefix = PREFIX_DATA;
+
+ // Store the prefix for later retrieval
+ mlt_prefix = strdup( prefix );
+
+ // Create the object list.
+ object_list = calloc( sizeof( struct mlt_properties_s ), 1 );
+ mlt_properties_init( object_list, NULL );
+
+ // Create a repository for each service type
+ producers = mlt_repository_init( object_list, prefix, "producers.dat", "mlt_create_producer" );
+ filters = mlt_repository_init( object_list, prefix, "filters.dat", "mlt_create_filter" );
+ transitions = mlt_repository_init( object_list, prefix, "transitions.dat", "mlt_create_transition" );
+ consumers = mlt_repository_init( object_list, prefix, "consumers.dat", "mlt_create_consumer" );
+ }
return 0;
}
mlt_producer mlt_factory_producer( char *service, void *input )
{
- return ( mlt_producer )mlt_repository_fetch( producers, service, input );
+ mlt_producer obj = mlt_repository_fetch( producers, service, input );
+ if ( obj != NULL )
+ {
+ mlt_properties properties = mlt_producer_properties( obj );
+ mlt_properties_set( properties, "mlt_type", "producer" );
+ mlt_properties_set( properties, "mlt_service", service );
+ }
+ return obj;
}
/** Fetch a filter from the repository.
mlt_filter mlt_factory_filter( char *service, void *input )
{
- return ( mlt_filter )mlt_repository_fetch( filters, service, input );
+ mlt_filter obj = mlt_repository_fetch( filters, service, input );
+ if ( obj != NULL )
+ {
+ mlt_properties properties = mlt_filter_properties( obj );
+ mlt_properties_set( properties, "mlt_type", "filter" );
+ mlt_properties_set( properties, "mlt_service", service );
+ }
+ return obj;
}
/** Fetch a transition from the repository.
mlt_transition mlt_factory_transition( char *service, void *input )
{
- return ( mlt_transition )mlt_repository_fetch( transitions, service, input );
+ mlt_transition obj = mlt_repository_fetch( transitions, service, input );
+ if ( obj != NULL )
+ {
+ mlt_properties properties = mlt_transition_properties( obj );
+ mlt_properties_set( properties, "mlt_type", "transition" );
+ mlt_properties_set( properties, "mlt_service", service );
+ }
+ return obj;
}
/** Fetch a consumer from the repository
mlt_consumer mlt_factory_consumer( char *service, void *input )
{
- return ( mlt_consumer )mlt_repository_fetch( consumers, service, input );
+ mlt_consumer obj = mlt_repository_fetch( consumers, service, input );
+ if ( obj != NULL )
+ {
+ mlt_properties properties = mlt_consumer_properties( obj );
+ mlt_properties_set( properties, "mlt_type", "consumer" );
+ mlt_properties_set( properties, "mlt_service", service );
+ }
+ return obj;
}
/** Close the factory.
void mlt_factory_close( )
{
- mlt_repository_close( producers );
- mlt_repository_close( filters );
- mlt_repository_close( transitions );
- mlt_repository_close( consumers );
- mlt_properties_close( object_list );
- free( mlt_prefix );
- free( object_list );
+ if ( mlt_prefix != NULL )
+ {
+ mlt_repository_close( producers );
+ mlt_repository_close( filters );
+ mlt_repository_close( transitions );
+ mlt_repository_close( consumers );
+ mlt_properties_close( object_list );
+ free( mlt_prefix );
+ free( object_list );
+ mlt_prefix = NULL;
+ }
}
return this->multitrack;
}
+/** Get the tractor.
+*/
+
+mlt_tractor mlt_field_tractor( mlt_field this )
+{
+ return this->tractor;
+}
+
/** Get the properties associated to this field.
*/
extern mlt_field mlt_field_init( );
extern mlt_service mlt_field_service( mlt_field this );
+extern mlt_tractor mlt_field_tractor( mlt_field this );
extern mlt_multitrack mlt_field_multitrack( mlt_field this );
extern mlt_properties mlt_field_properties( mlt_field this );
extern int mlt_field_plant_filter( mlt_field this, mlt_filter that, int track );
service->get_frame = filter_get_frame;
// Default in, out, track properties
- mlt_properties_set_timecode( properties, "in", 0 );
- mlt_properties_set_timecode( properties, "out", 0 );
+ mlt_properties_set_position( properties, "in", 0 );
+ mlt_properties_set_position( properties, "out", 0 );
mlt_properties_set_int( properties, "track", 0 );
return 0;
{
mlt_properties properties = mlt_service_properties( &this->parent );
this->producer = producer;
- mlt_properties_set_timecode( properties, "in", 0 );
- mlt_properties_set_timecode( properties, "out", 0 );
+ mlt_properties_set_position( properties, "in", 0 );
+ mlt_properties_set_position( properties, "out", 0 );
mlt_properties_set_int( properties, "track", index );
}
/** Tune the in/out points.
*/
-void mlt_filter_set_in_and_out( mlt_filter this, mlt_timecode in, mlt_timecode out )
+void mlt_filter_set_in_and_out( mlt_filter this, mlt_position in, mlt_position out )
{
mlt_properties properties = mlt_service_properties( &this->parent );
- mlt_properties_set_timecode( properties, "in", in );
- mlt_properties_set_timecode( properties, "out", out );
+ mlt_properties_set_position( properties, "in", in );
+ mlt_properties_set_position( properties, "out", out );
}
/** Return the track that this filter is operating on.
/** Get the in point.
*/
-mlt_timecode mlt_filter_get_in( mlt_filter this )
+mlt_position mlt_filter_get_in( mlt_filter this )
{
mlt_properties properties = mlt_service_properties( &this->parent );
- return mlt_properties_get_timecode( properties, "in" );
+ return mlt_properties_get_position( properties, "in" );
}
/** Get the out point.
*/
-mlt_timecode mlt_filter_get_out( mlt_filter this )
+mlt_position mlt_filter_get_out( mlt_filter this )
{
mlt_properties properties = mlt_service_properties( &this->parent );
- return mlt_properties_get_timecode( properties, "out" );
+ return mlt_properties_get_position( properties, "out" );
}
/** Process the frame.
{
if ( !mlt_frame_is_test_card( *frame ) )
{
- mlt_timecode timecode = mlt_frame_get_timecode( *frame );
- if ( timecode >= in && ( out == 0 || timecode < out ) )
+ mlt_position position = mlt_frame_get_position( *frame );
+ if ( position >= in && ( out == 0 || position < out ) )
*frame = filter_process( this, *frame );
}
return 0;
extern mlt_service mlt_filter_service( mlt_filter this );
extern mlt_properties mlt_filter_properties( mlt_filter this );
extern int mlt_filter_connect( mlt_filter this, mlt_service producer, int index );
-extern void mlt_filter_set_in_and_out( mlt_filter this, mlt_timecode in, mlt_timecode out );
+extern void mlt_filter_set_in_and_out( mlt_filter this, mlt_position in, mlt_position out );
extern int mlt_filter_get_track( mlt_filter this );
-extern mlt_timecode mlt_filter_get_in( mlt_filter this );
-extern mlt_timecode mlt_filter_get_out( mlt_filter this );
+extern mlt_position mlt_filter_get_in( mlt_filter this );
+extern mlt_position mlt_filter_get_out( mlt_filter this );
extern void mlt_filter_close( mlt_filter );
#endif
mlt_properties_init( properties, this );
// Set default properties on the frame
- mlt_properties_set_timecode( properties, "timecode", 0.0 );
+ mlt_properties_set_position( properties, "position", 0.0 );
mlt_properties_set_data( properties, "image", NULL, 0, NULL, NULL );
mlt_properties_set_int( properties, "width", 720 );
mlt_properties_set_int( properties, "height", 576 );
return mlt_properties_set_double( properties, "aspect_ratio", value );
}
-/** Get the timecode of this frame.
+/** Get the position of this frame.
*/
-mlt_timecode mlt_frame_get_timecode( mlt_frame this )
+mlt_position mlt_frame_get_position( mlt_frame this )
{
mlt_properties properties = mlt_frame_properties( this );
- return mlt_properties_get_timecode( properties, "timecode" );
+ return mlt_properties_get_position( properties, "position" );
}
-/** Set the timecode of this frame.
+/** Set the position of this frame.
*/
-int mlt_frame_set_timecode( mlt_frame this, mlt_timecode value )
+int mlt_frame_set_position( mlt_frame this, mlt_position value )
{
mlt_properties properties = mlt_frame_properties( this );
- return mlt_properties_set_timecode( properties, "timecode", value );
+ return mlt_properties_set_position( properties, "position", value );
}
/** Stack a get_image callback.
int i, j;
mlt_frame_get_audio( this, &p_dest, format, &frequency_dest, &channels_dest, &samples_dest );
- //fprintf( stderr, "frame dest samples %d channels %d timecode %f\n", samples_dest, channels_dest, mlt_properties_get_timecode( mlt_frame_properties( this ), "timecode" ) );
+ //fprintf( stderr, "frame dest samples %d channels %d position %f\n", samples_dest, channels_dest, mlt_properties_get_position( mlt_frame_properties( this ), "position" ) );
mlt_frame_get_audio( that, &p_src, format, &frequency_src, &channels_src, &samples_src );
//fprintf( stderr, "frame src samples %d channels %d\n", samples_src, channels_src );
if ( channels_src > 6 )
extern int mlt_frame_is_test_card( mlt_frame this );
extern double mlt_frame_get_aspect_ratio( mlt_frame this );
extern int mlt_frame_set_aspect_ratio( mlt_frame this, double value );
-extern mlt_timecode mlt_frame_get_timecode( mlt_frame this );
-extern int mlt_frame_set_timecode( mlt_frame this, mlt_timecode value );
+extern mlt_position mlt_frame_get_position( mlt_frame this );
+extern int mlt_frame_set_position( mlt_frame this, mlt_position value );
extern int mlt_frame_get_image( mlt_frame this, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable );
extern uint8_t *mlt_frame_get_alpha_mask( mlt_frame this );
return mlt_service_properties( mlt_multitrack_service( this ) );
}
-/** Initialise timecode related information.
+/** Initialise position related information.
*/
void mlt_multitrack_refresh( mlt_multitrack this )
mlt_properties properties = mlt_multitrack_properties( this );
// We need to ensure that the multitrack reports the longest track as its length
- mlt_timecode length = 0;
+ mlt_position length = 0;
// We need to ensure that fps are the same on all services
double fps = 0;
}
// Update multitrack properties now - we'll not destroy the in point here
- mlt_properties_set_timecode( properties, "length", length );
- mlt_properties_set_timecode( properties, "out", length );
+ mlt_properties_set_position( properties, "length", length );
+ mlt_properties_set_position( properties, "out", length );
mlt_properties_set_double( properties, "fps", fps );
}
0.0, 1.0, b0.0, 0.1, b1.1, 1.1, 0.1, 0.2, [out of playlist2], [out of playlist1]
*/
-mlt_timecode mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int index )
+mlt_position mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int index )
{
int first = 1;
- mlt_timecode position = 0;
+ mlt_position position = 0;
int i = 0;
// Loop through each of the tracks
// We only consider playlists
if ( playlist != NULL )
{
- // Locate the smallest timecode
+ // Locate the smallest position
if ( first )
{
// First position found
else
{
// Obtain the clip position in this playlist
- mlt_timecode position2 = mlt_playlist_clip( playlist, whence, index );
+ //mlt_position position2 = mlt_playlist_clip( playlist, whence, index );
// If this position is prior to the first, then use it
- if ( position2 < position )
- position = position2;
+ //if ( position2 < position )
+ //position = position2;
}
}
+ else
+ {
+ fprintf( stderr, "track %d isn't a playlist\n", index );
+ }
}
}
// Get the producer for this track
mlt_producer producer = this->list[ index ];
- // Obtain the current timecode
+ // Obtain the current position
uint64_t position = mlt_producer_frame( parent );
// Make sure we're at the same point
- mlt_producer_seek_frame( producer, position );
+ mlt_producer_seek( producer, position );
// Get the frame from the producer
mlt_service_get_frame( mlt_producer_service( producer ), frame, 0 );
// Generate a test frame
*frame = mlt_frame_init( );
- // Update timecode on the frame we're creating
- mlt_frame_set_timecode( *frame, mlt_producer_position( parent ) );
+ // Update position on the frame we're creating
+ mlt_frame_set_position( *frame, mlt_producer_position( parent ) );
// Move on to the next frame
if ( index >= this->count )
extern mlt_service mlt_multitrack_service( mlt_multitrack this );
extern mlt_properties mlt_multitrack_properties( mlt_multitrack this );
extern int mlt_multitrack_connect( mlt_multitrack this, mlt_producer producer, int track );
-extern mlt_timecode mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int index );
+extern mlt_position mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int index );
extern void mlt_multitrack_close( mlt_multitrack this );
#endif
typedef struct
{
mlt_producer producer;
- int64_t frame_in;
- int64_t frame_out;
- int64_t frame_count;
- mlt_timecode playtime;
+ mlt_position frame_in;
+ mlt_position frame_out;
+ mlt_position frame_count;
}
playlist_entry;
return mlt_producer_properties( &this->parent );
}
+/** Refresh the playlist after a clip has been changed.
+*/
+
static int mlt_playlist_virtual_refresh( mlt_playlist this )
{
int i = 0;
// Get the fps of the first producer
double fps = mlt_properties_get_double( mlt_playlist_properties( this ), "first_fps" );
- mlt_timecode playtime = 0;
+ mlt_position frame_count = 0;
for ( i = 0; i < this->count; i ++ )
{
mlt_properties_set_double( mlt_producer_properties( producer ), "fps", fps );
}
- // Update the playtime for this clip
- playtime += this->list[ i ]->playtime;
+ // Update the frame_count for this clip
+ frame_count += this->list[ i ]->frame_count;
}
// Refresh all properties
mlt_properties_set_double( mlt_playlist_properties( this ), "first_fps", fps );
mlt_properties_set_double( mlt_playlist_properties( this ), "fps", fps == 0 ? 25 : fps );
- mlt_properties_set_timecode( mlt_playlist_properties( this ), "length", playtime );
- mlt_properties_set_timecode( mlt_playlist_properties( this ), "out", playtime );
+ mlt_properties_set_position( mlt_playlist_properties( this ), "length", frame_count );
+ mlt_properties_set_position( mlt_playlist_properties( this ), "out", frame_count );
return 0;
}
/** Append to the virtual playlist.
*/
-static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer producer, int64_t in, int64_t out )
+static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer producer, mlt_position in, mlt_position out )
{
- double fps = mlt_properties_get_double( mlt_playlist_properties( this ), "fps" );
- double playtime = ( double )( out - in + 1 ) / fps;
-
// Check that we have room
if ( this->count >= this->size )
{
this->list[ this->count ]->frame_in = in;
this->list[ this->count ]->frame_out = out;
this->list[ this->count ]->frame_count = out - in + 1;
- this->list[ this->count ]->playtime = playtime;
mlt_producer_set_speed( producer, 0 );
mlt_producer producer = NULL;
// Map playlist position to real producer in virtual playlist
- mlt_timecode pos = mlt_producer_position( &this->parent );
- int64_t position = mlt_producer_frame_position( &this->parent, pos );
+ mlt_position position = mlt_producer_frame( &this->parent );
+
+ // 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" );
- // Loop through the virtual playlist
+ // Index for the main loop
int i = 0;
+ // Loop for each producer until found
for ( i = 0; i < this->count; i ++ )
{
// Increment the total
total += this->list[ i ]->frame_count;
+ // Check if the position indicates that we have found the clip
if ( position < this->list[ i ]->frame_count )
{
// Found it, now break
if ( producer != NULL )
{
position += this->list[ i ]->frame_in;
- position += mlt_producer_frame_position( producer, mlt_producer_get_in( producer ) );
- mlt_producer_seek_frame( producer, position );
+ mlt_producer_seek( producer, position );
}
else if ( !strcmp( eof, "pause" ) && total > 0 )
{
playlist_entry *entry = this->list[ this->count - 1 ];
mlt_producer this_producer = mlt_playlist_producer( this );
- mlt_producer_seek_frame( this_producer, total - 1 );
+ mlt_producer_seek( this_producer, total - 1 - mlt_producer_get_in( this_producer ) );
producer = entry->producer;
- position = mlt_producer_frame_position( producer, mlt_producer_get_in( producer ) );
- mlt_producer_seek_frame( producer, position + entry->frame_out );
+ mlt_producer_seek( producer, entry->frame_out );
mlt_producer_set_speed( this_producer, 0 );
- mlt_producer_set_speed( producer, 0 );
}
else if ( !strcmp( eof, "loop" ) && total > 0 )
{
playlist_entry *entry = this->list[ 0 ];
mlt_producer this_producer = mlt_playlist_producer( this );
- mlt_producer_seek_frame( this_producer, 0 );
+ mlt_producer_seek( this_producer, 0 );
producer = entry->producer;
- position = entry->frame_in;
- position += mlt_producer_frame_position( producer, mlt_producer_get_in( producer ) );
- mlt_producer_seek_frame( producer, position );
+ mlt_producer_seek( producer, entry->frame_in );
}
else
{
- mlt_producer_seek( mlt_playlist_producer( this ), 0 );
producer = &this->blank;
}
return producer;
}
+/** Invoked when a producer indicates that it has prematurely reached its end.
+*/
+
static mlt_producer mlt_playlist_virtual_set_out( mlt_playlist this )
{
// Default producer to blank
mlt_producer producer = &this->blank;
// Map playlist position to real producer in virtual playlist
- mlt_timecode pos = mlt_producer_position( &this->parent );
- int64_t position = mlt_producer_frame_position( &this->parent, pos );
+ mlt_position position = mlt_producer_frame( &this->parent );
// Loop through the virtual playlist
int i = 0;
// Seek in real producer to relative position
if ( i < this->count )
{
- // Update the playtime for the changed clip (hmmm)
- this->list[ i ]->frame_count = position + 1;
- this->list[ i ]->frame_out = position - this->list[ i ]->frame_in;
+ // Update the frame_count for the changed clip (hmmm)
+ this->list[ i ]->frame_out = position;
+ this->list[ i ]->frame_count = this->list[ i ]->frame_out - this->list[ i ]->frame_in + 1;
// Refresh the playlist
mlt_playlist_virtual_refresh( this );
return producer;
}
+/** Obtain the current clips index.
+*/
+
int mlt_playlist_current_clip( mlt_playlist this )
{
// Map playlist position to real producer in virtual playlist
- mlt_timecode pos = mlt_producer_position( &this->parent );
- int64_t position = mlt_producer_frame_position( &this->parent, pos );
+ mlt_position position = mlt_producer_frame( &this->parent );
// Loop through the virtual playlist
int i = 0;
return i;
}
+/** Obtain the current clips producer.
+*/
+
mlt_producer mlt_playlist_current( mlt_playlist this )
{
int i = mlt_playlist_current_clip( this );
return &this->blank;
}
-/** Get the timecode which corresponds to the start of the next clip.
+/** Get the position which corresponds to the start of the next clip.
*/
-mlt_timecode mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index )
+mlt_position mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index )
{
int64_t position = 0;
int absolute_clip = index;
else if ( absolute_clip > this->count )
absolute_clip = this->count;
- // Now determine the timecode
+ // Now determine the position
for ( i = 0; i < absolute_clip; i ++ )
position += this->list[ i ]->frame_count;
- return mlt_producer_time( &this->parent, position );
+ return position;
}
int mlt_playlist_get_clip_info( mlt_playlist this, mlt_playlist_clip_info *info, int index )
info->start = mlt_playlist_clip( this, mlt_whence_relative_start, index );
info->resource = mlt_properties_get( properties, "resource" );
info->frame_in = this->list[ index ]->frame_in;
- info->in = mlt_producer_time( producer, info->frame_in );
info->frame_out = this->list[ index ]->frame_out;
- info->out = mlt_producer_time( producer, info->frame_out );
- info->playtime = this->list[ index ]->playtime;
+ info->frame_count = this->list[ index ]->frame_count;
info->length = mlt_producer_get_length( producer );
info->fps = mlt_producer_get_fps( producer );
}
int mlt_playlist_append( mlt_playlist this, mlt_producer producer )
{
// Append to virtual list
- int64_t in = mlt_producer_frame_position( producer, mlt_producer_get_in( producer ) );
- int64_t out = mlt_producer_frame_position( producer, mlt_producer_get_out( producer ) );
- return mlt_playlist_virtual_append( this, producer, 0, out - in );
+ return mlt_playlist_virtual_append( this, producer, 0, mlt_producer_get_playtime( producer ) - 1 );
}
/** Append a producer to the playlist with in/out points.
*/
-int mlt_playlist_append_io( mlt_playlist this, mlt_producer producer, double in, double out )
+int mlt_playlist_append_io( mlt_playlist this, mlt_producer producer, mlt_position in, mlt_position out )
{
// Append to virtual list
if ( in != -1 && out != -1 )
- {
- int64_t fin = mlt_producer_frame_position( producer, in );
- int64_t fout = mlt_producer_frame_position( producer, out );
- return mlt_playlist_virtual_append( this, producer, fin, fout );
- }
+ return mlt_playlist_virtual_append( this, producer, in, out );
else
- {
return mlt_playlist_append( this, producer );
- }
}
/** Append a blank to the playlist of a given length.
*/
-int mlt_playlist_blank( mlt_playlist this, mlt_timecode length )
+int mlt_playlist_blank( mlt_playlist this, mlt_position length )
{
// Append to the virtual list
- int64_t fout = mlt_producer_frame_position( &this->blank, length );
- return mlt_playlist_virtual_append( this, &this->blank, 0, fout );
+ return mlt_playlist_virtual_append( this, &this->blank, 0, length );
}
/** Insert a producer into the playlist.
*/
-int mlt_playlist_insert( mlt_playlist this, mlt_producer producer, int where, mlt_timecode in, mlt_timecode out )
+int mlt_playlist_insert( mlt_playlist this, mlt_producer producer, int where, mlt_position in, mlt_position out )
{
return 0;
}
return 0;
}
-int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_timecode in, mlt_timecode out )
+/** Resize the current clip.
+*/
+
+int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_position in, mlt_position out )
{
int error = clip < 0 || clip >= this->count;
if ( error == 0 )
if ( in <= -1 )
in = 0;
- if ( out <= -1 || out >= mlt_producer_get_out( producer ) )
- out = mlt_producer_get_out( producer );
+ if ( out <= -1 || out >= mlt_producer_get_playtime( producer ) )
+ out = mlt_producer_get_playtime( producer ) - 1;
if ( out < in )
{
- mlt_timecode t = in;
+ mlt_position t = in;
in = out;
out = t;
}
- int64_t fin = mlt_producer_frame_position( producer, in );
- int64_t fout = mlt_producer_frame_position( producer, out );
-
- entry->frame_in = fin;
- entry->frame_out = fout;
- entry->frame_count = fout - fin + 1;
- entry->playtime = out - in;
+ entry->frame_in = in;
+ entry->frame_out = out;
+ entry->frame_count = out - in + 1;
mlt_playlist_virtual_refresh( this );
}
return error;
notifier( argument );
}
- // Update timecode on the frame we're creating
- mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) );
+ // Update position on the frame we're creating
+ mlt_frame_set_position( *frame, mlt_producer_frame( producer ) );
// Position ourselves on the next frame
mlt_producer_prepare_next( producer );
typedef struct
{
mlt_producer producer;
- mlt_timecode start;
+ mlt_position start;
char *resource;
- mlt_timecode in;
- int64_t frame_in;
- mlt_timecode out;
- int64_t frame_out;
- mlt_timecode playtime;
- mlt_timecode length;
+ mlt_position frame_in;
+ mlt_position frame_out;
+ mlt_position frame_count;
+ mlt_position length;
float fps;
}
mlt_playlist_clip_info;
extern int mlt_playlist_count( mlt_playlist this );
extern int mlt_playlist_clear( mlt_playlist this );
extern int mlt_playlist_append( mlt_playlist this, mlt_producer producer );
-extern int mlt_playlist_append_io( mlt_playlist this, mlt_producer producer, double in, double out );
-extern int mlt_playlist_blank( mlt_playlist this, mlt_timecode length );
-extern mlt_timecode mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index );
+extern int mlt_playlist_append_io( mlt_playlist this, mlt_producer producer, mlt_position in, mlt_position out );
+extern int mlt_playlist_blank( mlt_playlist this, mlt_position length );
+extern mlt_position mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index );
extern int mlt_playlist_current_clip( mlt_playlist this );
extern mlt_producer mlt_playlist_current( mlt_playlist this );
extern int mlt_playlist_get_clip_info( mlt_playlist this, mlt_playlist_clip_info *info, int index );
-extern int mlt_playlist_insert( mlt_playlist this, mlt_producer producer, int where, mlt_timecode in, mlt_timecode out );
+extern int mlt_playlist_insert( mlt_playlist this, mlt_producer producer, int where, mlt_position in, mlt_position out );
extern int mlt_playlist_remove( mlt_playlist this, int where );
extern int mlt_playlist_move( mlt_playlist this, int from, int to );
-extern int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_timecode in, mlt_timecode out );
+extern int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_position in, mlt_position out );
extern void mlt_playlist_close( mlt_playlist this );
#endif
// Set the default properties
mlt_properties_set( properties, "mlt_type", "mlt_producer" );
- mlt_properties_set_timecode( properties, "position", 0.0 );
+ mlt_properties_set_position( properties, "position", 0.0 );
mlt_properties_set_double( properties, "frame", 0 );
mlt_properties_set_double( properties, "fps", 25.0 );
mlt_properties_set_double( properties, "speed", 1.0 );
- mlt_properties_set_timecode( properties, "in", 0.0 );
- mlt_properties_set_timecode( properties, "out", 36000.0 );
- mlt_properties_set_timecode( properties, "length", 36000.0 );
- mlt_properties_set_int( properties, "known_length", 1 );
+ mlt_properties_set_position( properties, "in", 0.0 );
+ mlt_properties_set_position( properties, "out", 179999 );
+ mlt_properties_set_position( properties, "length", 180000 );
mlt_properties_set_double( properties, "aspect_ratio", 4.0 / 3.0 );
mlt_properties_set( properties, "log_id", "multitrack" );
return mlt_service_properties( &this->parent );
}
-/** Convert frame position to timecode.
+/** Convert frame position to position.
*/
-mlt_timecode mlt_producer_time( mlt_producer this, int64_t frame )
+/*
+mlt_position mlt_producer_time( mlt_producer this, int64_t frame )
{
if ( frame < 0 )
return -1;
else
- return ( mlt_timecode )frame / mlt_producer_get_fps( this );
+ return ( mlt_position )frame / mlt_producer_get_fps( this );
}
+*/
-/** Convert timecode to frame position.
+/** Convert position to frame position.
*/
-int64_t mlt_producer_frame_position( mlt_producer this, mlt_timecode position )
+/*
+int64_t mlt_producer_frame_position( mlt_producer this, mlt_position position )
{
if ( position < 0 )
return -1;
else
return ( int64_t )( floor( position * mlt_producer_get_fps( this ) + 0.5 ) );
}
+*/
-/** Seek to a specified time code.
+/** Seek to a specified position.
*/
-int mlt_producer_seek( mlt_producer this, mlt_timecode timecode )
+int mlt_producer_seek( mlt_producer this, mlt_position position )
{
// Check bounds
- if ( timecode < 0 )
- timecode = 0;
- if ( timecode > mlt_producer_get_playtime( this ) )
- timecode = mlt_producer_get_playtime( this );
+ if ( position < 0 )
+ position = 0;
+ else if ( position > mlt_producer_get_playtime( this ) )
+ position = mlt_producer_get_playtime( this ) - 1;
// Set the position
- mlt_properties_set_timecode( mlt_producer_properties( this ), "position", timecode );
+ mlt_properties_set_position( mlt_producer_properties( this ), "position", position );
// Calculate the absolute frame
- double frame = ( mlt_producer_get_in( this ) + timecode ) * mlt_producer_get_fps( this );
- mlt_properties_set_double( mlt_producer_properties( this ), "frame", floor( frame + 0.5 ) );
-
- return 0;
-}
-
-/** Seek to a specified absolute frame.
-*/
-
-int mlt_producer_seek_frame( mlt_producer this, int64_t frame )
-{
- // Calculate the time code
- double timecode = ( frame / mlt_producer_get_fps( this ) ) - mlt_producer_get_in( this );
-
- // If timecode is invalid, then seek on time
- if ( frame < 0 || timecode < 0 )
- {
- // Seek to the in point
- mlt_producer_seek( this, 0 );
- }
- else if ( timecode > mlt_producer_get_playtime( this ) )
- {
- // Seek to the out point
- mlt_producer_seek( this, mlt_producer_get_playtime( this ) );
- }
- else
- {
- // Set the position
- mlt_properties_set_timecode( mlt_producer_properties( this ), "position", timecode );
-
- // Set the absolute frame
- mlt_properties_set_double( mlt_producer_properties( this ), "frame", frame );
- }
+ mlt_properties_set_position( mlt_producer_properties( this ), "frame", mlt_producer_get_in( this ) + position );
return 0;
}
-/** Get the current time code.
+/** Get the current position (relative to in point).
*/
-mlt_timecode mlt_producer_position( mlt_producer this )
+mlt_position mlt_producer_position( mlt_producer this )
{
- return mlt_properties_get_timecode( mlt_producer_properties( this ), "position" );
+ return mlt_properties_get_position( mlt_producer_properties( this ), "position" );
}
-/** Get the current frame.
+/** Get the current position (relative to start of producer).
*/
-uint64_t mlt_producer_frame( mlt_producer this )
+mlt_position mlt_producer_frame( mlt_producer this )
{
return mlt_properties_get_double( mlt_producer_properties( this ), "frame" );
}
/** Set the in and out points.
*/
-int mlt_producer_set_in_and_out( mlt_producer this, mlt_timecode in, mlt_timecode out )
+int mlt_producer_set_in_and_out( mlt_producer this, mlt_position in, mlt_position out )
{
// Correct ins and outs if necessary
if ( in < 0 )
in = 0;
- if ( in > mlt_producer_get_length( this ) )
+ else if ( in > mlt_producer_get_length( this ) )
in = mlt_producer_get_length( this );
+
if ( out < 0 )
out = 0;
- if ( out > mlt_producer_get_length( this ) )
+ else if ( out > mlt_producer_get_length( this ) )
out = mlt_producer_get_length( this );
// Swap ins and outs if wrong
if ( out < in )
{
- mlt_timecode t = in;
+ mlt_position t = in;
in = out;
out = t;
}
// Set the values
- mlt_properties_set_timecode( mlt_producer_properties( this ), "in", in );
- mlt_properties_set_timecode( mlt_producer_properties( this ), "out", out );
-
- // Seek to the in point
- mlt_producer_seek( this, 0 );
+ mlt_properties_set_position( mlt_producer_properties( this ), "in", in );
+ mlt_properties_set_position( mlt_producer_properties( this ), "out", out );
return 0;
}
/** Get the in point.
*/
-mlt_timecode mlt_producer_get_in( mlt_producer this )
+mlt_position mlt_producer_get_in( mlt_producer this )
{
- return mlt_properties_get_timecode( mlt_producer_properties( this ), "in" );
+ return mlt_properties_get_position( mlt_producer_properties( this ), "in" );
}
/** Get the out point.
*/
-mlt_timecode mlt_producer_get_out( mlt_producer this )
+mlt_position mlt_producer_get_out( mlt_producer this )
{
- return mlt_properties_get_timecode( mlt_producer_properties( this ), "out" );
+ return mlt_properties_get_position( mlt_producer_properties( this ), "out" );
}
/** Get the total play time.
*/
-mlt_timecode mlt_producer_get_playtime( mlt_producer this )
+mlt_position mlt_producer_get_playtime( mlt_producer this )
{
- return mlt_producer_get_out( this ) - mlt_producer_get_in( this );
+ return mlt_producer_get_out( this ) - mlt_producer_get_in( this ) + 1;
}
/** Get the total length of the producer.
*/
-mlt_timecode mlt_producer_get_length( mlt_producer this )
+mlt_position mlt_producer_get_length( mlt_producer this )
{
- return mlt_properties_get_timecode( mlt_producer_properties( this ), "length" );
+ return mlt_properties_get_position( mlt_producer_properties( this ), "length" );
}
/** Prepare for next frame.
void mlt_producer_prepare_next( mlt_producer this )
{
- mlt_producer_seek_frame( this, mlt_producer_frame( this ) + mlt_producer_get_speed( this ) );
+ mlt_producer_seek( this, mlt_producer_frame( this ) + mlt_producer_get_speed( this ) );
}
/** Get a frame.
{
// Get the frame from the implementation
result = this->get_frame( this, frame, index );
-
- mlt_properties frame_properties = mlt_frame_properties( *frame );
- double speed = mlt_producer_get_speed( this );
- mlt_properties_set_double( frame_properties, "speed", speed );
}
else
{
// Generate a test frame
*frame = mlt_frame_init( );
- // Set the timecode
- result = mlt_frame_set_timecode( *frame, mlt_producer_position( this ) );
+ // Set the position
+ result = mlt_frame_set_position( *frame, mlt_producer_position( this ) );
- // Calculate the next timecode
+ // Calculate the next position
mlt_producer_prepare_next( this );
}
- // Copy the fps of the producer onto the frame
+ // Copy the fps and speed of the producer onto the frame
mlt_properties properties = mlt_frame_properties( *frame );
mlt_properties_set_double( properties, "fps", mlt_producer_get_fps( this ) );
+ double speed = mlt_producer_get_speed( this );
+ mlt_properties_set_double( properties, "speed", speed );
return 0;
}
/** Public final methods
*/
+//extern double mlt_producer_convert_position_to_time( mlt_producer this, int64_t frame );
+//extern mlt_position mlt_producer_convert_time_to_position( mlt_producer this, double time );
+
extern int mlt_producer_init( mlt_producer this, void *child );
extern mlt_service mlt_producer_service( mlt_producer this );
extern mlt_properties mlt_producer_properties( mlt_producer this );
-extern mlt_timecode mlt_producer_time( mlt_producer this, int64_t frame );
-extern int64_t mlt_producer_frame_position( mlt_producer this, mlt_timecode position );
-extern int mlt_producer_seek( mlt_producer this, mlt_timecode timecode );
-extern int mlt_producer_seek_frame( mlt_producer this, int64_t frame );
-extern mlt_timecode mlt_producer_position( mlt_producer this );
-extern uint64_t mlt_producer_frame( mlt_producer this );
+extern int mlt_producer_seek( mlt_producer this, mlt_position position );
+extern mlt_position mlt_producer_position( mlt_producer this );
+extern mlt_position mlt_producer_frame( mlt_producer this );
extern int mlt_producer_set_speed( mlt_producer this, double speed );
extern double mlt_producer_get_speed( mlt_producer this );
extern double mlt_producer_get_fps( mlt_producer this );
-extern int mlt_producer_set_in_and_out( mlt_producer this, mlt_timecode in, mlt_timecode out );
-extern mlt_timecode mlt_producer_get_in( mlt_producer this );
-extern mlt_timecode mlt_producer_get_out( mlt_producer this );
-extern mlt_timecode mlt_producer_get_playtime( mlt_producer this );
-extern mlt_timecode mlt_producer_get_length( mlt_producer this );
+extern int mlt_producer_set_in_and_out( mlt_producer this, mlt_position in, mlt_position out );
+extern mlt_position mlt_producer_get_in( mlt_producer this );
+extern mlt_position mlt_producer_get_out( mlt_producer this );
+extern mlt_position mlt_producer_get_playtime( mlt_producer this );
+extern mlt_position mlt_producer_get_length( mlt_producer this );
extern void mlt_producer_prepare_next( mlt_producer this );
extern void mlt_producer_close( mlt_producer this );
/** Get a value associated to the name.
*/
-mlt_timecode mlt_properties_get_timecode( mlt_properties this, char *name )
+mlt_position mlt_properties_get_position( mlt_properties this, char *name )
{
mlt_property value = mlt_properties_find( this, name );
- return value == NULL ? 0 : mlt_property_get_timecode( value );
+ return value == NULL ? 0 : mlt_property_get_position( value );
}
/** Set a value associated to the name.
*/
-int mlt_properties_set_timecode( mlt_properties this, char *name, mlt_timecode value )
+int mlt_properties_set_position( mlt_properties this, char *name, mlt_position value )
{
int error = 1;
// Set it if not NULL
if ( property != NULL )
- error = mlt_property_set_timecode( property, value );
+ error = mlt_property_set_position( property, value );
return error;
}
extern int mlt_properties_set_int( mlt_properties this, char *name, int value );
extern double mlt_properties_get_double( mlt_properties this, char *name );
extern int mlt_properties_set_double( mlt_properties this, char *name, double value );
-extern mlt_timecode mlt_properties_get_timecode( mlt_properties this, char *name );
-extern int mlt_properties_set_timecode( mlt_properties this, char *name, mlt_timecode value );
+extern mlt_position mlt_properties_get_position( mlt_properties this, char *name );
+extern int mlt_properties_set_position( mlt_properties this, char *name, mlt_position value );
extern int mlt_properties_set_data( mlt_properties this, char *name, void *value, int length, mlt_destructor, mlt_serialiser );
extern void *mlt_properties_get_data( mlt_properties this, char *name, int *length );
extern int mlt_properties_count( mlt_properties this );
return 0;
}
-/** Set a timecode on this property.
+/** Set a position on this property.
*/
-int mlt_property_set_timecode( mlt_property this, mlt_timecode value )
+int mlt_property_set_position( mlt_property this, mlt_position value )
{
mlt_property_clear( this );
- this->types = mlt_prop_timecode;
- this->prop_timecode = value;
+ this->types = mlt_prop_position;
+ this->prop_position = value;
return 0;
}
return this->prop_int;
else if ( this->types & mlt_prop_double )
return ( int )this->prop_double;
- else if ( this->types & mlt_prop_timecode )
- return ( int )this->prop_timecode;
+ else if ( this->types & mlt_prop_position )
+ return ( int )this->prop_position;
else if ( this->types & mlt_prop_int64 )
return ( int )this->prop_int64;
else if ( this->types & mlt_prop_string )
return this->prop_double;
else if ( this->types & mlt_prop_int )
return ( double )this->prop_int;
- else if ( this->types & mlt_prop_timecode )
- return ( double )this->prop_timecode;
+ else if ( this->types & mlt_prop_position )
+ return ( double )this->prop_position;
else if ( this->types & mlt_prop_int64 )
return ( double )this->prop_int64;
else if ( this->types & mlt_prop_string )
return 0;
}
-/** Get a timecode from this property.
+/** Get a position from this property.
*/
-mlt_timecode mlt_property_get_timecode( mlt_property this )
+mlt_position mlt_property_get_position( mlt_property this )
{
- if ( this->types & mlt_prop_timecode )
- return this->prop_timecode;
+ if ( this->types & mlt_prop_position )
+ return this->prop_position;
else if ( this->types & mlt_prop_int )
- return ( mlt_timecode )this->prop_int;
+ return ( mlt_position )this->prop_int;
else if ( this->types & mlt_prop_double )
- return ( mlt_timecode )this->prop_double;
+ return ( mlt_position )this->prop_double;
else if ( this->types & mlt_prop_int64 )
- return ( mlt_timecode )this->prop_int64;
+ return ( mlt_position )this->prop_int64;
else if ( this->types & mlt_prop_string )
- return ( mlt_timecode )atof( this->prop_string );
+ return ( mlt_position )atol( this->prop_string );
return 0;
}
return ( int64_t )this->prop_int;
else if ( this->types & mlt_prop_double )
return ( int64_t )this->prop_double;
- else if ( this->types & mlt_prop_timecode )
- return ( int64_t )this->prop_timecode;
+ else if ( this->types & mlt_prop_position )
+ return ( int64_t )this->prop_position;
else if ( this->types & mlt_prop_string )
- return ( int64_t )atof( this->prop_string );
+ return ( int64_t )atol( this->prop_string );
return 0;
}
this->prop_string = malloc( 32 );
sprintf( this->prop_string, "%e", this->prop_double );
}
- else if ( this->types & mlt_prop_timecode )
+ else if ( this->types & mlt_prop_position )
{
this->types |= mlt_prop_string;
this->prop_string = malloc( 32 );
- sprintf( this->prop_string, "%e", this->prop_timecode );
+ sprintf( this->prop_string, "%lld", this->prop_position );
}
else if ( this->types & mlt_prop_int64 )
{
mlt_prop_none = 0,
mlt_prop_int = 1,
mlt_prop_string = 2,
- mlt_prop_timecode = 4,
+ mlt_prop_position = 4,
mlt_prop_double = 8,
mlt_prop_data = 16,
mlt_prop_int64 = 32
// Atomic type handling
int prop_int;
- mlt_timecode prop_timecode;
+ mlt_position prop_position;
double prop_double;
int64_t prop_int64;
extern void mlt_property_clear( mlt_property this );
extern int mlt_property_set_int( mlt_property this, int value );
extern int mlt_property_set_double( mlt_property this, double value );
-extern int mlt_property_set_timecode( mlt_property this, mlt_timecode value );
+extern int mlt_property_set_position( mlt_property this, mlt_position value );
extern int mlt_property_set_uint64( mlt_property this, uint64_t value );
extern int mlt_property_set_string( mlt_property this, char *value );
extern int mlt_property_set_data( mlt_property this, void *value, int length, mlt_destructor destructor, mlt_serialiser serialiser );
extern int mlt_property_get_int( mlt_property this );
extern double mlt_property_get_double( mlt_property this );
-extern mlt_timecode mlt_property_get_timecode( mlt_property this );
+extern mlt_position mlt_property_get_position( mlt_property this );
extern int64_t mlt_property_get_int64( mlt_property this );
extern char *mlt_property_get_string( mlt_property this );
extern void *mlt_property_get_data( mlt_property this, int *length );
#include "mlt_tractor.h"
#include "mlt_frame.h"
+#include "mlt_multitrack.h"
#include <stdio.h>
#include <stdlib.h>
struct mlt_tractor_s
{
- struct mlt_service_s parent;
+ struct mlt_producer_s parent;
mlt_service producer;
};
/** Forward references to static methods.
*/
-static int service_get_frame( mlt_service this, mlt_frame_ptr frame, int track );
+static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int track );
/** Constructor for the tractor.
mlt_tractor this = calloc( sizeof( struct mlt_tractor_s ), 1 );
if ( this != NULL )
{
- mlt_service service = &this->parent;
- if ( mlt_service_init( service, this ) == 0 )
+ mlt_producer producer = &this->parent;
+ if ( mlt_producer_init( producer, this ) == 0 )
{
- service->get_frame = service_get_frame;
+ producer->get_frame = producer_get_frame;
}
else
{
mlt_service mlt_tractor_service( mlt_tractor this )
{
+ return mlt_producer_service( &this->parent );
+}
+
+/** Get the producer object associated to the tractor.
+*/
+
+mlt_producer mlt_tractor_producer( mlt_tractor this )
+{
return &this->parent;
}
+/** Get the properties object associated to the tractor.
+*/
+
+mlt_properties mlt_tractor_properties( mlt_tractor this )
+{
+ return mlt_producer_properties( &this->parent );
+}
+
/** Connect the tractor.
*/
int mlt_tractor_connect( mlt_tractor this, mlt_service producer )
{
- int ret = mlt_service_connect_producer( &this->parent, producer, 0 );
+ int ret = mlt_service_connect_producer( mlt_tractor_service( this ), producer, 0 );
+ // This is the producer we're going to connect to
if ( ret == 0 )
- {
- // This is the producer we're going to connect to
this->producer = producer;
- }
return ret;
}
TODO: This should be reading a pump being populated by the thread...
*/
-static int service_get_frame( mlt_service parent, mlt_frame_ptr frame, int track )
+static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int track )
{
mlt_tractor this = parent->child;
int done = 0;
mlt_frame temp;
+ // Get the properties of the parent producer
+ mlt_properties properties = mlt_producer_properties( parent );
+
+ // Try to obtain the multitrack associated to the tractor
+ mlt_multitrack multitrack = mlt_properties_get_data( properties, "multitrack", NULL );
+
+ // If we don't have one, we're in trouble...
+ if ( multitrack != NULL )
+ {
+ mlt_producer target = mlt_multitrack_producer( multitrack );
+ mlt_producer_seek( target, mlt_producer_frame( parent ) );
+ mlt_producer_set_speed( target, mlt_producer_get_speed( parent ) );
+ mlt_producer_set_in_and_out( parent, mlt_producer_get_in( target ), mlt_producer_get_out( target ) );
+ }
+ else
+ {
+ fprintf( stderr, "tractor without a multitrack!!\n" );
+ }
+
// Loop through each of the tracks we're harvesting
for ( i = 0; !done; i ++ )
{
}
}
+ // Prepare the next frame
+ mlt_producer_prepare_next( parent );
+
// Indicate our found status
return 0;
}
void mlt_tractor_close( mlt_tractor this )
{
- mlt_service_close( &this->parent );
+ mlt_producer_close( &this->parent );
free( this );
}
extern mlt_tractor mlt_tractor_init( );
extern mlt_service mlt_tractor_service( mlt_tractor this );
+extern mlt_producer mlt_tractor_producer( mlt_tractor this );
+extern mlt_properties mlt_tractor_properties( mlt_tractor this );
extern int mlt_tractor_connect( mlt_tractor this, mlt_service service );
extern void mlt_tractor_close( mlt_tractor this );
service->get_frame = transition_get_frame;
- mlt_properties_set_timecode( properties, "in", 0 );
- mlt_properties_set_timecode( properties, "out", 0 );
+ mlt_properties_set_position( properties, "in", 0 );
+ mlt_properties_set_position( properties, "out", 0 );
mlt_properties_set_int( properties, "a_track", 0 );
mlt_properties_set_int( properties, "b_track", 1 );
/** Set the in and out points.
*/
-void mlt_transition_set_in_and_out( mlt_transition this, mlt_timecode in, mlt_timecode out )
+void mlt_transition_set_in_and_out( mlt_transition this, mlt_position in, mlt_position out )
{
mlt_properties properties = mlt_transition_properties( this );
- mlt_properties_set_timecode( properties, "in", in );
- mlt_properties_set_timecode( properties, "out", out );
+ mlt_properties_set_position( properties, "in", in );
+ mlt_properties_set_position( properties, "out", out );
}
/** Get the index of the a track.
/** Get the in point.
*/
-mlt_timecode mlt_transition_get_in( mlt_transition this )
+mlt_position mlt_transition_get_in( mlt_transition this )
{
mlt_properties properties = mlt_transition_properties( this );
- return mlt_properties_get_timecode( properties, "in" );
+ return mlt_properties_get_position( properties, "in" );
}
/** Get the out point.
*/
-mlt_timecode mlt_transition_get_out( mlt_transition this )
+mlt_position mlt_transition_get_out( mlt_transition this )
{
mlt_properties properties = mlt_transition_properties( this );
- return mlt_properties_get_timecode( properties, "out" );
+ return mlt_properties_get_position( properties, "out" );
}
/** Process the frame.
int a_track = mlt_properties_get_int( properties, "a_track" );
int b_track = mlt_properties_get_int( properties, "b_track" );
- mlt_timecode in = mlt_properties_get_timecode( properties, "in" );
- mlt_timecode out = mlt_properties_get_timecode( properties, "out" );
+ mlt_position in = mlt_properties_get_position( properties, "in" );
+ mlt_position out = mlt_properties_get_position( properties, "out" );
// Fetch a and b frames together...
if ( ( index == a_track || index == b_track ) &&
if ( index == a_track )
{
// Determine if we're in the right time zone
- mlt_timecode timecode = mlt_frame_get_timecode( this->a_frame );
- if ( timecode >= in && timecode < out )
+ mlt_position position = mlt_frame_get_position( this->a_frame );
+ if ( position >= in && position < out )
{
// Process the transition
*frame = transition_process( this, this->a_frame, this->b_frame );
}
else
{
- mlt_timecode timecode = mlt_frame_get_timecode( this->b_frame );
- if ( timecode >= in && timecode < out )
+ mlt_position position = mlt_frame_get_position( this->b_frame );
+ if ( position >= in && position < out )
{
// We're in the zone, but the 'a frame' has not been requested yet
*frame = mlt_frame_init( );
extern mlt_service mlt_transition_service( mlt_transition this );
extern mlt_properties mlt_transition_properties( mlt_transition this );
extern int mlt_transition_connect( mlt_transition this, mlt_service producer, int a_track, int b_track );
-extern void mlt_transition_set_in_and_out( mlt_transition this, mlt_timecode in, mlt_timecode out );
+extern void mlt_transition_set_in_and_out( mlt_transition this, mlt_position in, mlt_position out );
extern int mlt_transition_get_a_track( mlt_transition this );
extern int mlt_transition_get_b_track( mlt_transition this );
-extern mlt_timecode mlt_transition_get_in( mlt_transition this );
-extern mlt_timecode mlt_transition_get_out( mlt_transition this );
+extern mlt_position mlt_transition_get_in( mlt_transition this );
+extern mlt_position mlt_transition_get_out( mlt_transition this );
extern void mlt_transition_close( mlt_transition this );
#endif
}
mlt_whence;
-typedef double mlt_timecode;
+typedef int64_t mlt_position;
typedef struct mlt_frame_s *mlt_frame, **mlt_frame_ptr;
typedef struct mlt_properties_s *mlt_properties;
typedef struct mlt_service_s *mlt_service;
case '9':
mlt_producer_set_speed( producer, 10 );
break;
+ case 'd':
+ if ( multitrack != NULL )
+ {
+ int i = 0;
+ mlt_position last = -1;
+ for ( i = 0; 1; i ++ )
+ {
+ mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_start, i );
+ if ( time == last )
+ break;
+ last = time;
+ fprintf( stderr, "%d: %lld\n", i, time );
+ }
+ }
+ break;
+
case 'g':
if ( multitrack != NULL )
{
- mlt_timecode time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 0 );
+ mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 0 );
mlt_producer_seek( producer, time );
}
break;
case 'h':
if ( multitrack != NULL )
{
- mlt_producer producer = mlt_multitrack_producer( multitrack );
- int64_t position = mlt_producer_frame_position( producer, mlt_producer_position( producer ) );
+ mlt_position position = mlt_producer_position( producer );
mlt_producer_set_speed( producer, 0 );
- mlt_producer_seek_frame( producer, position - 1 >= 0 ? position - 1 : 0 );
+ mlt_producer_seek( producer, position - 1 >= 0 ? position - 1 : 0 );
}
break;
case 'j':
if ( multitrack != NULL )
{
- mlt_timecode time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 1 );
+ mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 1 );
mlt_producer_seek( producer, time );
}
break;
case 'k':
if ( multitrack != NULL )
{
- mlt_timecode time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, -1 );
+ mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, -1 );
mlt_producer_seek( producer, time );
}
break;
case 'l':
if ( multitrack != NULL )
{
- mlt_producer producer = mlt_multitrack_producer( multitrack );
- int64_t position = mlt_producer_frame_position( producer, mlt_producer_position( producer ) );
+ mlt_position position = mlt_producer_position( producer );
mlt_producer_set_speed( producer, 0 );
- mlt_producer_seek_frame( producer, position + 1 );
+ mlt_producer_seek( producer, position + 1 );
}
break;
}
mlt_properties properties = unit->properties;
int generation = mlt_properties_get_int( properties, "generation" );
mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
- mlt_producer producer = mlt_playlist_producer( playlist );
valerie_response_printf( response, 1024, "%d\n", generation );
i, info.resource,
info.frame_in,
info.frame_out,
- mlt_producer_frame_position( producer, info.playtime ),
- mlt_producer_frame_position( producer, info.length ),
+ info.frame_count,
+ info.length,
info.fps );
}
}
{
mlt_properties properties = unit->properties;
mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
- mlt_playlist_append_io( playlist, instance, mlt_producer_time( instance, in ), mlt_producer_time( instance, out ) );
+ mlt_playlist_append_io( playlist, instance, in, out );
miracle_log( LOG_DEBUG, "loaded clip %s", clip );
miracle_unit_status_communicate( unit );
return valerie_ok;
{
mlt_properties properties = unit->properties;
mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
- mlt_playlist_insert( playlist, instance, index, mlt_producer_time( instance, in ), mlt_producer_time( instance, out ) );
+ mlt_playlist_insert( playlist, instance, index, in, out );
miracle_log( LOG_DEBUG, "inserted clip %s at %d", clip, index );
update_generation( unit );
miracle_unit_status_communicate( unit );
{
mlt_properties properties = unit->properties;
mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
- mlt_playlist_append_io( playlist, instance, mlt_producer_time( instance, in ), mlt_producer_time( instance, out ) );
+ mlt_playlist_append_io( playlist, instance, in, out );
miracle_log( LOG_DEBUG, "appended clip %s", clip );
update_generation( unit );
miracle_unit_status_communicate( unit );
status->fps = mlt_producer_get_fps( producer );
status->in = info.frame_in;
status->out = info.frame_out;
- status->position = mlt_producer_frame_position( producer, mlt_producer_position( clip ) );
- status->length = mlt_producer_frame_position( producer, mlt_producer_get_length( clip ) );
+ status->position = mlt_producer_position( clip );
+ status->length = mlt_producer_get_length( clip );
strncpy( status->tail_clip, info.resource, sizeof( status->tail_clip ) );
status->tail_in = info.frame_in;
status->tail_out = info.frame_out;
- status->tail_position = mlt_producer_frame_position( producer, mlt_producer_position( clip ) );
- status->tail_length = mlt_producer_frame_position( producer, mlt_producer_get_length( clip ) );
+ status->tail_position = mlt_producer_position( clip );
+ status->tail_length = mlt_producer_get_length( clip );
status->clip_index = mlt_playlist_current_clip( playlist );
status->seek_flag = 1;
}
if ( mlt_playlist_get_clip_info( playlist, &info, clip ) == 0 )
{
- int64_t frame_start = mlt_producer_frame_position( info.producer, info.start );
+ int64_t frame_start = info.start;
int64_t frame_offset = position;
if ( frame_offset < 0 )
if ( frame_offset >= info.frame_out )
frame_offset = info.frame_out;
- mlt_producer_seek_frame( producer, frame_start + frame_offset - info.frame_in );
+ mlt_producer_seek( producer, frame_start + frame_offset - info.frame_in );
}
miracle_unit_status_communicate( unit );
if ( error == 0 )
{
- mlt_timecode in = mlt_producer_time( info.producer, position );
- error = mlt_playlist_resize_clip( playlist, index, in, info.out );
+ miracle_unit_play( unit, 0 );
+ error = mlt_playlist_resize_clip( playlist, index, position, info.frame_out );
update_generation( unit );
miracle_unit_change_position( unit, index, 0 );
}
if ( error == 0 )
{
- mlt_timecode out = mlt_producer_time( info.producer, position );
- error = mlt_playlist_resize_clip( playlist, index, info.in, out );
+ miracle_unit_play( unit, 0 );
+ error = mlt_playlist_resize_clip( playlist, index, info.frame_in, position );
update_generation( unit );
miracle_unit_status_communicate( unit );
miracle_unit_change_position( unit, index, -1 );
mlt_properties properties = unit->properties;
mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
mlt_producer producer = mlt_playlist_producer( playlist );
- mlt_timecode position = mlt_producer_position( producer );
- mlt_producer_seek_frame( producer, mlt_producer_frame_position( producer, position ) + offset );
+ mlt_position position = mlt_producer_frame( producer );
+ mlt_producer_seek( producer, position + offset );
}
/** Set the unit's clip mode regarding in and out points.
( *frame )->get_audio = producer_get_audio;
// Update timecode on the frame we're creating
- mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) );
+ mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
// Calculate the next timecode
mlt_producer_prepare_next( producer );
// Get the b frame from the stack
mlt_frame b_frame = mlt_frame_pop_frame( this );
- // Get the properties of the b frame
- mlt_properties b_props = mlt_frame_properties( b_frame );
-
- // Arbitrary composite defaults
- int x = 0;
- int y = 0;
- double mix = 1.0;
-
- // Override from b frame properties if provided
- if ( mlt_properties_get( b_props, "x" ) != NULL )
- x = mlt_properties_get_int( b_props, "x" );
- if ( mlt_properties_get( b_props, "y" ) != NULL )
- y = mlt_properties_get_int( b_props, "y" );
- if ( mlt_properties_get( b_props, "mix" ) != NULL )
- mix = mlt_properties_get_double( b_props, "mix" );
-
- // Composite the b_frame on the a_frame
- mlt_frame_composite_yuv( this, b_frame, x, y, mix );
-
- // Extract the a_frame image info
- *width = mlt_properties_get_int( a_props, "width" );
- *height = mlt_properties_get_int( a_props, "height" );
- *image = mlt_properties_get_data( a_props, "image", NULL );
-
- // Close the b_frame
- mlt_frame_close( b_frame );
+ if ( b_frame != NULL )
+ {
+ // Get the properties of the b frame
+ mlt_properties b_props = mlt_frame_properties( b_frame );
+
+ // Arbitrary composite defaults
+ int x = 0;
+ int y = 0;
+ double mix = 1.0;
+
+ // Override from b frame properties if provided
+ if ( mlt_properties_get( b_props, "x" ) != NULL )
+ x = mlt_properties_get_int( b_props, "x" );
+ if ( mlt_properties_get( b_props, "y" ) != NULL )
+ y = mlt_properties_get_int( b_props, "y" );
+ if ( mlt_properties_get( b_props, "mix" ) != NULL )
+ mix = mlt_properties_get_double( b_props, "mix" );
+
+ // Composite the b_frame on the a_frame
+ mlt_frame_composite_yuv( this, b_frame, x, y, mix );
+
+ // Extract the a_frame image info
+ *width = mlt_properties_get_int( a_props, "width" );
+ *height = mlt_properties_get_int( a_props, "height" );
+ *image = mlt_properties_get_data( a_props, "image", NULL );
+
+ // Close the b_frame
+ mlt_frame_close( b_frame );
+ }
+ else if ( a_props != NULL )
+ {
+ // Extract the a_frame image info
+ *width = mlt_properties_get_int( a_props, "width" );
+ *height = mlt_properties_get_int( a_props, "height" );
+ *image = mlt_properties_get_data( a_props, "image", NULL );
+ }
return 0;
}
}
// Determine the time position of this frame in the transition duration
- mlt_timecode in = mlt_transition_get_in( transition );
- mlt_timecode out = mlt_transition_get_out( transition );
- mlt_timecode time = mlt_frame_get_timecode( b_frame );
+ mlt_position in = mlt_transition_get_in( transition );
+ mlt_position out = mlt_transition_get_out( transition );
+ mlt_position time = mlt_frame_get_position( b_frame );
double pos = ( time - in ) / ( out - in );
// Set the b frame properties
TARGET = ../libmltdv.so
OBJS = factory.o \
- producer_libdv.o
+ producer_libdv.o \
+ consumer_libdv.o
CFLAGS = -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread
libdv libmltdv.so
EOF
+cat << EOF >> ../consumers.dat
+libdv libmltdv.so
+EOF
+
fi
--- /dev/null
+/*
+ * producer_libdv.c -- a DV encoder based on libdv
+ * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Author: Charles Yates <charles.yates@pandora.be>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+// Local header files
+#include "consumer_libdv.h"
+
+// mlt Header files
+#include <framework/mlt_frame.h>
+
+// System header files
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+
+// libdv header files
+#include <libdv/dv.h>
+
+// Forward references.
+static int consumer_encode_video( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame );
+static void consumer_encode_audio( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame );
+static void consumer_output( mlt_consumer this, uint8_t *dv_frame, int size, mlt_frame frame );
+static void *consumer_thread( void *arg );
+static void consumer_close( mlt_consumer this );
+
+/** Initialise the dv consumer.
+*/
+
+mlt_consumer consumer_libdv_init( char *arg )
+{
+ // Allocate the consumer
+ mlt_consumer this = calloc( 1, sizeof( struct mlt_consumer_s ) );
+
+ // If memory allocated and initialises without error
+ if ( this != NULL && mlt_consumer_init( this, NULL ) == 0 )
+ {
+ // Get properties from the consumer
+ mlt_properties properties = mlt_consumer_properties( this );
+
+ // Allocate a thread
+ pthread_t *thread = calloc( 1, sizeof( pthread_t ) );
+
+ // Assign close callback
+ this->close = consumer_close;
+
+ // Assign all properties
+ if ( arg == NULL || !strcmp( arg, "PAL" ) )
+ mlt_properties_set_double( properties, "fps", 25 );
+ else
+ mlt_properties_set_double( properties, "fps", 29.97 );
+
+ mlt_properties_set_data( properties, "thread", thread, sizeof( pthread_t ), free, NULL );
+ mlt_properties_set_data( properties, "video", consumer_encode_video, 0, NULL, NULL );
+ mlt_properties_set_data( properties, "audio", consumer_encode_audio, 0, NULL, NULL );
+ mlt_properties_set_data( properties, "output", consumer_output, 0, NULL, NULL );
+
+ // Create the thread (this should not happen immediately)
+ mlt_properties_set_int( properties, "running", 1 );
+ pthread_create( thread, NULL, consumer_thread, this );
+ }
+ else
+ {
+ // Clean up in case of init failure
+ free( this );
+ this = NULL;
+ }
+
+ // Return this
+ return this;
+}
+
+/** Get or create a new libdv encoder.
+*/
+
+static dv_encoder_t *libdv_get_encoder( mlt_consumer this, mlt_frame frame )
+{
+ // Get the properties of the consumer
+ mlt_properties this_properties = mlt_consumer_properties( this );
+
+ // Obtain the dv_encoder
+ dv_encoder_t *encoder = mlt_properties_get_data( this_properties, "dv_encoder", NULL );
+
+ // Construct one if we don't have one
+ if ( encoder == NULL )
+ {
+ // Get the fps of the consumer (for now - should be from frame)
+ double fps = mlt_properties_get_double( this_properties, "fps" );
+
+ // Create the encoder
+ encoder = dv_encoder_new( fps != 25, 0, 0 );
+
+ // Encoder settings
+ encoder->isPAL = fps = 25;
+ encoder->is16x9 = 0;
+ encoder->vlc_encode_passes = 1;
+ encoder->static_qno = 0;
+ encoder->force_dct = DV_DCT_AUTO;
+
+ // Store the encoder on the properties
+ mlt_properties_set_data( this_properties, "dv_encoder", encoder, 0, ( mlt_destructor )dv_encoder_free, NULL );
+
+ // Convenience for image dimensions
+ mlt_properties_set_int( this_properties, "width", 720 );
+ mlt_properties_set_int( this_properties, "height", fps == 25 ? 576 : 480 );
+ }
+
+ // Return the encoder
+ return encoder;
+}
+
+
+/** The libdv encode video method.
+*/
+
+static int consumer_encode_video( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame )
+{
+ // Obtain the dv_encoder
+ dv_encoder_t *encoder = libdv_get_encoder( this, frame );
+
+ // Get the properties of the consumer
+ mlt_properties this_properties = mlt_consumer_properties( this );
+
+ // This will hold the size of the dv frame
+ int size = 0;
+
+ // If we get an encoder, then encode the image
+ if ( encoder != NULL )
+ {
+ // Specify desired image properties
+ mlt_image_format fmt = mlt_image_yuv422;
+ int width = mlt_properties_get_int( this_properties, "width" );
+ int height = mlt_properties_get_int( this_properties, "height" );
+ uint8_t *image = NULL;
+
+ // Get the image
+ mlt_frame_get_image( frame, &image, &fmt, &width, &height, 0 );
+
+ // Check that we get what we expected
+ if ( fmt != mlt_image_yuv422 ||
+ width != mlt_properties_get_int( this_properties, "width" ) ||
+ height != mlt_properties_get_int( this_properties, "height" ) ||
+ image == NULL )
+ {
+ // We should try to recover here
+ fprintf( stderr, "We have a problem houston...\n" );
+ }
+ else
+ {
+ // Calculate the size of the dv frame
+ size = height == 576 ? frame_size_625_50 : frame_size_525_60;
+ }
+
+ // Process the frame
+ if ( size != 0 )
+ {
+ // Encode the image
+ dv_encode_full_frame( encoder, &image, e_dv_color_yuv, dv_frame );
+ }
+ }
+
+ return size;
+}
+
+/** The libdv encode audio method.
+*/
+
+static void consumer_encode_audio( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame )
+{
+ // Get the properties of the consumer
+ mlt_properties this_properties = mlt_consumer_properties( this );
+
+ // Obtain the dv_encoder
+ dv_encoder_t *encoder = libdv_get_encoder( this, frame );
+
+ // Only continue if we have an encoder
+ if ( encoder != NULL )
+ {
+ // Get the frame count
+ int count = mlt_properties_get_int( this_properties, "count" );
+
+ // Default audio args
+ mlt_audio_format fmt = mlt_audio_pcm;
+ int channels = 2;
+ int frequency = 48000;
+ int samples = mlt_sample_calculator( mlt_properties_get_double( this_properties, "fps" ), frequency, count );
+ int16_t *pcm = NULL;
+
+ // Get the frame number
+ time_t start = time( NULL );
+ int height = mlt_properties_get_int( this_properties, "height" );
+ int is_pal = height == 576;
+ int is_wide = 0;
+
+ // Temporary - audio buffer allocation
+ int16_t *audio_buffers[ 4 ];
+ int i = 0;
+ int j = 0;
+ for ( i = 0 ; i < 4; i ++ )
+ audio_buffers[ i ] = malloc( 2 * DV_AUDIO_MAX_SAMPLES );
+
+ // Get the audio
+ mlt_frame_get_audio( frame, &pcm, &fmt, &frequency, &channels, &samples );
+
+ // Inform the encoder of the number of audio samples
+ encoder->samples_this_frame = samples;
+
+ // Fill the audio buffers correctly
+ for ( i = 0; i < samples; i ++ )
+ for ( j = 0; j < channels; j++ )
+ audio_buffers[ j ][ i ] = *pcm ++;
+
+ // Encode audio on frame
+ dv_encode_full_audio( encoder, audio_buffers, channels, frequency, dv_frame );
+
+ // Specify meta data on the frame
+ dv_encode_metadata( dv_frame, is_pal, is_wide, &start, count );
+ dv_encode_timecode( dv_frame, is_pal, count );
+
+ // Update properties
+ mlt_properties_set_int( this_properties, "count", ++ count );
+
+ // Temporary - free audio buffers
+ for ( i = 0 ; i < 4; i ++ )
+ free( audio_buffers[ i ] );
+ }
+}
+
+/** The libdv output method.
+*/
+
+static void consumer_output( mlt_consumer this, uint8_t *dv_frame, int size, mlt_frame frame )
+{
+ fwrite( dv_frame, size, 1, stdout );
+ fflush( stdout );
+}
+
+/** The main thread - the argument is simply the consumer.
+*/
+
+static void *consumer_thread( void *arg )
+{
+ // Map the argument to the object
+ mlt_consumer this = arg;
+
+ // Get the properties
+ mlt_properties properties = mlt_consumer_properties( this );
+
+ // 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 );
+ int ( *output )( mlt_consumer, uint8_t *, int, mlt_frame ) = mlt_properties_get_data( properties, "output", NULL );
+
+ // Allocate a single PAL frame for encoding
+ uint8_t *dv_frame = malloc( frame_size_625_50 );
+
+ // Get the service associated to the consumer
+ mlt_service service = mlt_consumer_service( this );
+
+ // Define a frame pointer
+ mlt_frame frame;
+
+ // Loop while running
+ while( mlt_properties_get_int( properties, "running" ) )
+ {
+ // Get the frame
+ if ( mlt_service_get_frame( service, &frame, 0 ) == 0 )
+ {
+ // Encode the image
+ int size = video( this, dv_frame, frame );
+
+ // Encode the audio
+ if ( size > 0 )
+ audio( this, dv_frame, frame );
+
+ // Output the frame
+ output( this, dv_frame, size, frame );
+
+ // Close the frame
+ mlt_frame_close( frame );
+ }
+ }
+
+ // Tidy up
+ free( dv_frame );
+
+ return NULL;
+}
+
+/** Close the consumer.
+*/
+
+static void consumer_close( mlt_consumer this )
+{
+ // Get the properties
+ mlt_properties properties = mlt_consumer_properties( this );
+
+ // Get the thread
+ pthread_t *thread = mlt_properties_get_data( properties, "thread", NULL );
+
+ // Stop the thread
+ mlt_properties_set_int( properties, "running", 0 );
+
+ // Wait for termination
+ pthread_join( *thread, NULL );
+
+ // Close the parent
+ mlt_consumer_close( this );
+
+ // Free the memory
+ free( this );
+}
+
--- /dev/null
+/*
+ * producer_libdv.h -- a DV encoder based on libdv
+ * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Author: Charles Yates <charles.yates@pandora.be>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CONSUMER_LIBDV_H_
+#define _CONSUMER_LIBDV_H_
+
+#include <framework/mlt_consumer.h>
+
+extern mlt_consumer consumer_libdv_init( char *filename );
+
+#endif
#include <string.h>
#include "producer_libdv.h"
+#include "consumer_libdv.h"
void *mlt_create_producer( char *id, void *arg )
{
void *mlt_create_consumer( char *id, void *arg )
{
+ if ( !strcmp( id, "libdv" ) )
+ return consumer_libdv_init( arg );
return NULL;
}
// Calculate default in/out points
double fps = this->is_pal ? 25 : 30000.0 / 1001.0;
- mlt_timecode length = ( mlt_timecode )( this->frames_in_file ) / fps;
mlt_properties_set_double( properties, "fps", fps );
- mlt_properties_set_timecode( properties, "length", length );
- mlt_properties_set_timecode( properties, "in", 0.0 );
- mlt_properties_set_timecode( properties, "out", ( mlt_timecode )( this->frames_in_file - 1 ) / fps );
+ mlt_properties_set_position( properties, "length", this->frames_in_file );
+ mlt_properties_set_position( properties, "in", 0 );
+ mlt_properties_set_position( properties, "out", this->frames_in_file - 1 );
// Parse the header for meta info
dv_parse_header( this->dv_decoder, dv_data );
}
// Update timecode on the frame we're creating
- mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) );
+ mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
// Calculate the next timecode
mlt_producer_prepare_next( producer );
if ( !mlt_properties_get_int( producer_properties, "end_of_clip" ) )
{
// Get the position
- double position = mlt_properties_get_double( producer_properties, "dub_position" );
+ mlt_position position = mlt_properties_get_position( producer_properties, "dub_position" );
// We need a frame from the producer
mlt_frame producer_frame;
mlt_properties_set_double( producer_properties, "fps", mlt_properties_get_double( frame_properties, "fps" ) );
// Seek to the position
- mlt_producer_seek_frame( producer, ( int64_t )position );
+ mlt_producer_seek( producer, position );
// Get the next frame
producer->get_frame( producer, &producer_frame, 0 );
mlt_properties_set_data( frame_properties, "ffmpeg_dub_frame", producer_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
// Incrment the position
- mlt_properties_set_double( producer_properties, "dub_position", position + 1 );
+ mlt_properties_set_position( producer_properties, "dub_position", position + 1 );
}
}
mlt_properties_set_data( properties, "producer", producer, 0, ( mlt_destructor )mlt_producer_close, NULL );
// Initialise the audio frame position
- mlt_properties_set_double( properties, "dub_position", 0 );
+ mlt_properties_set_position( properties, "dub_position", 0 );
return this;
}
return 0;
}
-FILE *producer_ffmpeg_run_video( producer_ffmpeg this, mlt_timecode position )
+FILE *producer_ffmpeg_run_video( producer_ffmpeg this, mlt_position position )
{
if ( this->video == NULL )
{
return this->video;
}
-FILE *producer_ffmpeg_run_audio( producer_ffmpeg this, mlt_timecode position )
+FILE *producer_ffmpeg_run_audio( producer_ffmpeg this, mlt_position position )
{
// Get the producer
mlt_producer producer = &this->parent;
if ( this->end_of_video && this->end_of_audio )
{
mlt_properties_set_int( properties, "end_of_clip", 1 );
- mlt_properties_set_timecode( producer_properties, "length", mlt_producer_position( &this->parent ) );
+ mlt_properties_set_position( producer_properties, "length", mlt_producer_position( &this->parent ) );
mlt_producer_set_in_and_out( &this->parent, mlt_producer_get_in( &this->parent ), mlt_producer_position( &this->parent ) );
}
// Update timecode on the frame we're creating
- mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) );
+ mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
// Calculate the next timecode
mlt_producer_prepare_next( producer );
}
// Update timecode on the frame we're creating
- mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) );
+ mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
// Calculate the next timecode
mlt_producer_prepare_next( producer );
gap ++;
}
}
- mlt_properties_set_timecode( properties, "out", this->count );
+ mlt_properties_set_position( properties, "out", this->count * 25 );
}
else if ( strstr( filename, "/.all." ) != NULL )
{
free( de[ i ] );
}
- mlt_properties_set_timecode( properties, "out", this->count );
+ mlt_properties_set_position( properties, "out", this->count * 25 );
free( de );
free( dir_name );
}
{
this->filenames = realloc( this->filenames, sizeof( char * ) * ( this->count + 1 ) );
this->filenames[ this->count ++ ] = strdup( filename );
- mlt_properties_set_timecode( properties, "out", 1 );
+ mlt_properties_set_position( properties, "out", 25 );
}
// Initialise gobject types
int image_idx = ( int )floor( mlt_producer_position( producer ) / ttl ) % this->count;
// Update timecode on the frame we're creating
- mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) );
+ mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
// optimization for subsequent iterations on single picture
if ( this->image != NULL && image_idx == this->image_idx )
mlt_multitrack_connect( multitrack, mlt_playlist_producer( playlist ), track );
}
- mlt_properties props = mlt_multitrack_properties( multitrack );
+ mlt_tractor tractor = mlt_field_tractor( field );
+ mlt_producer prod = mlt_tractor_producer( tractor );
+ mlt_properties props = mlt_tractor_properties( tractor );
+ mlt_properties_set_data( props, "multitrack", multitrack, 0, NULL, NULL );
mlt_properties_set_data( props, "field", field, 0, NULL, NULL );
mlt_properties_set_data( props, "group", group, 0, NULL, NULL );
+ mlt_producer_set_in_and_out( prod, 0, mlt_producer_get_out( mlt_multitrack_producer( multitrack ) ) );
+ mlt_properties_set_double( props, "fps", mlt_producer_get_fps( mlt_multitrack_producer( multitrack ) ) );
- return mlt_multitrack_producer( multitrack );
+ return mlt_tractor_producer( tractor );
}
pthread_mutex_destroy( &this->audio_mutex );
pthread_cond_destroy( &this->audio_cond );
- // Now clean up the rest (the close = NULL is a bit nasty but needed for now)
- parent->close = NULL;
+ // Now clean up the rest
mlt_consumer_close( parent );
// Finally clean up this
void mlt_consumer_close( mlt_consumer this )
{
- if ( this->close != NULL )
- this->close( this );
+ // Get the childs close function
+ void ( *consumer_close )( ) = this->close;
+
+ // Make sure it only gets called once
+ this->close = NULL;
+
+ // Call the childs close if available
+ if ( consumer_close != NULL )
+ consumer_close( this );
else
mlt_service_close( &this->parent );
}
*/
#include "config.h"
-#include "mlt_factory.h"
+#include "mlt.h"
#include "mlt_repository.h"
-#include "mlt_properties.h"
#include <stdlib.h>
#include <string.h>
int mlt_factory_init( char *prefix )
{
- // If no directory is specified, default to install directory
- if ( prefix == NULL )
- prefix = PREFIX_DATA;
-
- // Store the prefix for later retrieval
- mlt_prefix = strdup( prefix );
-
- // Create the object list.
- object_list = calloc( sizeof( struct mlt_properties_s ), 1 );
- mlt_properties_init( object_list, NULL );
-
- // Create a repository for each service type
- producers = mlt_repository_init( object_list, prefix, "producers.dat", "mlt_create_producer" );
- filters = mlt_repository_init( object_list, prefix, "filters.dat", "mlt_create_filter" );
- transitions = mlt_repository_init( object_list, prefix, "transitions.dat", "mlt_create_transition" );
- consumers = mlt_repository_init( object_list, prefix, "consumers.dat", "mlt_create_consumer" );
+ // Only initialise once
+ if ( mlt_prefix == NULL )
+ {
+ // If no directory is specified, default to install directory
+ if ( prefix == NULL )
+ prefix = PREFIX_DATA;
+
+ // Store the prefix for later retrieval
+ mlt_prefix = strdup( prefix );
+
+ // Create the object list.
+ object_list = calloc( sizeof( struct mlt_properties_s ), 1 );
+ mlt_properties_init( object_list, NULL );
+
+ // Create a repository for each service type
+ producers = mlt_repository_init( object_list, prefix, "producers.dat", "mlt_create_producer" );
+ filters = mlt_repository_init( object_list, prefix, "filters.dat", "mlt_create_filter" );
+ transitions = mlt_repository_init( object_list, prefix, "transitions.dat", "mlt_create_transition" );
+ consumers = mlt_repository_init( object_list, prefix, "consumers.dat", "mlt_create_consumer" );
+ }
return 0;
}
mlt_producer mlt_factory_producer( char *service, void *input )
{
- return ( mlt_producer )mlt_repository_fetch( producers, service, input );
+ mlt_producer obj = mlt_repository_fetch( producers, service, input );
+ if ( obj != NULL )
+ {
+ mlt_properties properties = mlt_producer_properties( obj );
+ mlt_properties_set( properties, "mlt_type", "producer" );
+ mlt_properties_set( properties, "mlt_service", service );
+ }
+ return obj;
}
/** Fetch a filter from the repository.
mlt_filter mlt_factory_filter( char *service, void *input )
{
- return ( mlt_filter )mlt_repository_fetch( filters, service, input );
+ mlt_filter obj = mlt_repository_fetch( filters, service, input );
+ if ( obj != NULL )
+ {
+ mlt_properties properties = mlt_filter_properties( obj );
+ mlt_properties_set( properties, "mlt_type", "filter" );
+ mlt_properties_set( properties, "mlt_service", service );
+ }
+ return obj;
}
/** Fetch a transition from the repository.
mlt_transition mlt_factory_transition( char *service, void *input )
{
- return ( mlt_transition )mlt_repository_fetch( transitions, service, input );
+ mlt_transition obj = mlt_repository_fetch( transitions, service, input );
+ if ( obj != NULL )
+ {
+ mlt_properties properties = mlt_transition_properties( obj );
+ mlt_properties_set( properties, "mlt_type", "transition" );
+ mlt_properties_set( properties, "mlt_service", service );
+ }
+ return obj;
}
/** Fetch a consumer from the repository
mlt_consumer mlt_factory_consumer( char *service, void *input )
{
- return ( mlt_consumer )mlt_repository_fetch( consumers, service, input );
+ mlt_consumer obj = mlt_repository_fetch( consumers, service, input );
+ if ( obj != NULL )
+ {
+ mlt_properties properties = mlt_consumer_properties( obj );
+ mlt_properties_set( properties, "mlt_type", "consumer" );
+ mlt_properties_set( properties, "mlt_service", service );
+ }
+ return obj;
}
/** Close the factory.
void mlt_factory_close( )
{
- mlt_repository_close( producers );
- mlt_repository_close( filters );
- mlt_repository_close( transitions );
- mlt_repository_close( consumers );
- mlt_properties_close( object_list );
- free( mlt_prefix );
- free( object_list );
+ if ( mlt_prefix != NULL )
+ {
+ mlt_repository_close( producers );
+ mlt_repository_close( filters );
+ mlt_repository_close( transitions );
+ mlt_repository_close( consumers );
+ mlt_properties_close( object_list );
+ free( mlt_prefix );
+ free( object_list );
+ mlt_prefix = NULL;
+ }
}
return this->multitrack;
}
+/** Get the tractor.
+*/
+
+mlt_tractor mlt_field_tractor( mlt_field this )
+{
+ return this->tractor;
+}
+
/** Get the properties associated to this field.
*/
extern mlt_field mlt_field_init( );
extern mlt_service mlt_field_service( mlt_field this );
+extern mlt_tractor mlt_field_tractor( mlt_field this );
extern mlt_multitrack mlt_field_multitrack( mlt_field this );
extern mlt_properties mlt_field_properties( mlt_field this );
extern int mlt_field_plant_filter( mlt_field this, mlt_filter that, int track );
service->get_frame = filter_get_frame;
// Default in, out, track properties
- mlt_properties_set_timecode( properties, "in", 0 );
- mlt_properties_set_timecode( properties, "out", 0 );
+ mlt_properties_set_position( properties, "in", 0 );
+ mlt_properties_set_position( properties, "out", 0 );
mlt_properties_set_int( properties, "track", 0 );
return 0;
{
mlt_properties properties = mlt_service_properties( &this->parent );
this->producer = producer;
- mlt_properties_set_timecode( properties, "in", 0 );
- mlt_properties_set_timecode( properties, "out", 0 );
+ mlt_properties_set_position( properties, "in", 0 );
+ mlt_properties_set_position( properties, "out", 0 );
mlt_properties_set_int( properties, "track", index );
}
/** Tune the in/out points.
*/
-void mlt_filter_set_in_and_out( mlt_filter this, mlt_timecode in, mlt_timecode out )
+void mlt_filter_set_in_and_out( mlt_filter this, mlt_position in, mlt_position out )
{
mlt_properties properties = mlt_service_properties( &this->parent );
- mlt_properties_set_timecode( properties, "in", in );
- mlt_properties_set_timecode( properties, "out", out );
+ mlt_properties_set_position( properties, "in", in );
+ mlt_properties_set_position( properties, "out", out );
}
/** Return the track that this filter is operating on.
/** Get the in point.
*/
-mlt_timecode mlt_filter_get_in( mlt_filter this )
+mlt_position mlt_filter_get_in( mlt_filter this )
{
mlt_properties properties = mlt_service_properties( &this->parent );
- return mlt_properties_get_timecode( properties, "in" );
+ return mlt_properties_get_position( properties, "in" );
}
/** Get the out point.
*/
-mlt_timecode mlt_filter_get_out( mlt_filter this )
+mlt_position mlt_filter_get_out( mlt_filter this )
{
mlt_properties properties = mlt_service_properties( &this->parent );
- return mlt_properties_get_timecode( properties, "out" );
+ return mlt_properties_get_position( properties, "out" );
}
/** Process the frame.
{
if ( !mlt_frame_is_test_card( *frame ) )
{
- mlt_timecode timecode = mlt_frame_get_timecode( *frame );
- if ( timecode >= in && ( out == 0 || timecode < out ) )
+ mlt_position position = mlt_frame_get_position( *frame );
+ if ( position >= in && ( out == 0 || position < out ) )
*frame = filter_process( this, *frame );
}
return 0;
extern mlt_service mlt_filter_service( mlt_filter this );
extern mlt_properties mlt_filter_properties( mlt_filter this );
extern int mlt_filter_connect( mlt_filter this, mlt_service producer, int index );
-extern void mlt_filter_set_in_and_out( mlt_filter this, mlt_timecode in, mlt_timecode out );
+extern void mlt_filter_set_in_and_out( mlt_filter this, mlt_position in, mlt_position out );
extern int mlt_filter_get_track( mlt_filter this );
-extern mlt_timecode mlt_filter_get_in( mlt_filter this );
-extern mlt_timecode mlt_filter_get_out( mlt_filter this );
+extern mlt_position mlt_filter_get_in( mlt_filter this );
+extern mlt_position mlt_filter_get_out( mlt_filter this );
extern void mlt_filter_close( mlt_filter );
#endif
mlt_properties_init( properties, this );
// Set default properties on the frame
- mlt_properties_set_timecode( properties, "timecode", 0.0 );
+ mlt_properties_set_position( properties, "position", 0.0 );
mlt_properties_set_data( properties, "image", NULL, 0, NULL, NULL );
mlt_properties_set_int( properties, "width", 720 );
mlt_properties_set_int( properties, "height", 576 );
return mlt_properties_set_double( properties, "aspect_ratio", value );
}
-/** Get the timecode of this frame.
+/** Get the position of this frame.
*/
-mlt_timecode mlt_frame_get_timecode( mlt_frame this )
+mlt_position mlt_frame_get_position( mlt_frame this )
{
mlt_properties properties = mlt_frame_properties( this );
- return mlt_properties_get_timecode( properties, "timecode" );
+ return mlt_properties_get_position( properties, "position" );
}
-/** Set the timecode of this frame.
+/** Set the position of this frame.
*/
-int mlt_frame_set_timecode( mlt_frame this, mlt_timecode value )
+int mlt_frame_set_position( mlt_frame this, mlt_position value )
{
mlt_properties properties = mlt_frame_properties( this );
- return mlt_properties_set_timecode( properties, "timecode", value );
+ return mlt_properties_set_position( properties, "position", value );
}
/** Stack a get_image callback.
int i, j;
mlt_frame_get_audio( this, &p_dest, format, &frequency_dest, &channels_dest, &samples_dest );
- //fprintf( stderr, "frame dest samples %d channels %d timecode %f\n", samples_dest, channels_dest, mlt_properties_get_timecode( mlt_frame_properties( this ), "timecode" ) );
+ //fprintf( stderr, "frame dest samples %d channels %d position %f\n", samples_dest, channels_dest, mlt_properties_get_position( mlt_frame_properties( this ), "position" ) );
mlt_frame_get_audio( that, &p_src, format, &frequency_src, &channels_src, &samples_src );
//fprintf( stderr, "frame src samples %d channels %d\n", samples_src, channels_src );
if ( channels_src > 6 )
extern int mlt_frame_is_test_card( mlt_frame this );
extern double mlt_frame_get_aspect_ratio( mlt_frame this );
extern int mlt_frame_set_aspect_ratio( mlt_frame this, double value );
-extern mlt_timecode mlt_frame_get_timecode( mlt_frame this );
-extern int mlt_frame_set_timecode( mlt_frame this, mlt_timecode value );
+extern mlt_position mlt_frame_get_position( mlt_frame this );
+extern int mlt_frame_set_position( mlt_frame this, mlt_position value );
extern int mlt_frame_get_image( mlt_frame this, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable );
extern uint8_t *mlt_frame_get_alpha_mask( mlt_frame this );
return mlt_service_properties( mlt_multitrack_service( this ) );
}
-/** Initialise timecode related information.
+/** Initialise position related information.
*/
void mlt_multitrack_refresh( mlt_multitrack this )
mlt_properties properties = mlt_multitrack_properties( this );
// We need to ensure that the multitrack reports the longest track as its length
- mlt_timecode length = 0;
+ mlt_position length = 0;
// We need to ensure that fps are the same on all services
double fps = 0;
}
// Update multitrack properties now - we'll not destroy the in point here
- mlt_properties_set_timecode( properties, "length", length );
- mlt_properties_set_timecode( properties, "out", length );
+ mlt_properties_set_position( properties, "length", length );
+ mlt_properties_set_position( properties, "out", length );
mlt_properties_set_double( properties, "fps", fps );
}
0.0, 1.0, b0.0, 0.1, b1.1, 1.1, 0.1, 0.2, [out of playlist2], [out of playlist1]
*/
-mlt_timecode mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int index )
+mlt_position mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int index )
{
int first = 1;
- mlt_timecode position = 0;
+ mlt_position position = 0;
int i = 0;
// Loop through each of the tracks
// We only consider playlists
if ( playlist != NULL )
{
- // Locate the smallest timecode
+ // Locate the smallest position
if ( first )
{
// First position found
else
{
// Obtain the clip position in this playlist
- mlt_timecode position2 = mlt_playlist_clip( playlist, whence, index );
+ //mlt_position position2 = mlt_playlist_clip( playlist, whence, index );
// If this position is prior to the first, then use it
- if ( position2 < position )
- position = position2;
+ //if ( position2 < position )
+ //position = position2;
}
}
+ else
+ {
+ fprintf( stderr, "track %d isn't a playlist\n", index );
+ }
}
}
// Get the producer for this track
mlt_producer producer = this->list[ index ];
- // Obtain the current timecode
+ // Obtain the current position
uint64_t position = mlt_producer_frame( parent );
// Make sure we're at the same point
- mlt_producer_seek_frame( producer, position );
+ mlt_producer_seek( producer, position );
// Get the frame from the producer
mlt_service_get_frame( mlt_producer_service( producer ), frame, 0 );
// Generate a test frame
*frame = mlt_frame_init( );
- // Update timecode on the frame we're creating
- mlt_frame_set_timecode( *frame, mlt_producer_position( parent ) );
+ // Update position on the frame we're creating
+ mlt_frame_set_position( *frame, mlt_producer_position( parent ) );
// Move on to the next frame
if ( index >= this->count )
extern mlt_service mlt_multitrack_service( mlt_multitrack this );
extern mlt_properties mlt_multitrack_properties( mlt_multitrack this );
extern int mlt_multitrack_connect( mlt_multitrack this, mlt_producer producer, int track );
-extern mlt_timecode mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int index );
+extern mlt_position mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int index );
extern void mlt_multitrack_close( mlt_multitrack this );
#endif
typedef struct
{
mlt_producer producer;
- int64_t frame_in;
- int64_t frame_out;
- int64_t frame_count;
- mlt_timecode playtime;
+ mlt_position frame_in;
+ mlt_position frame_out;
+ mlt_position frame_count;
}
playlist_entry;
return mlt_producer_properties( &this->parent );
}
+/** Refresh the playlist after a clip has been changed.
+*/
+
static int mlt_playlist_virtual_refresh( mlt_playlist this )
{
int i = 0;
// Get the fps of the first producer
double fps = mlt_properties_get_double( mlt_playlist_properties( this ), "first_fps" );
- mlt_timecode playtime = 0;
+ mlt_position frame_count = 0;
for ( i = 0; i < this->count; i ++ )
{
mlt_properties_set_double( mlt_producer_properties( producer ), "fps", fps );
}
- // Update the playtime for this clip
- playtime += this->list[ i ]->playtime;
+ // Update the frame_count for this clip
+ frame_count += this->list[ i ]->frame_count;
}
// Refresh all properties
mlt_properties_set_double( mlt_playlist_properties( this ), "first_fps", fps );
mlt_properties_set_double( mlt_playlist_properties( this ), "fps", fps == 0 ? 25 : fps );
- mlt_properties_set_timecode( mlt_playlist_properties( this ), "length", playtime );
- mlt_properties_set_timecode( mlt_playlist_properties( this ), "out", playtime );
+ mlt_properties_set_position( mlt_playlist_properties( this ), "length", frame_count );
+ mlt_properties_set_position( mlt_playlist_properties( this ), "out", frame_count );
return 0;
}
/** Append to the virtual playlist.
*/
-static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer producer, int64_t in, int64_t out )
+static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer producer, mlt_position in, mlt_position out )
{
- double fps = mlt_properties_get_double( mlt_playlist_properties( this ), "fps" );
- double playtime = ( double )( out - in + 1 ) / fps;
-
// Check that we have room
if ( this->count >= this->size )
{
this->list[ this->count ]->frame_in = in;
this->list[ this->count ]->frame_out = out;
this->list[ this->count ]->frame_count = out - in + 1;
- this->list[ this->count ]->playtime = playtime;
mlt_producer_set_speed( producer, 0 );
mlt_producer producer = NULL;
// Map playlist position to real producer in virtual playlist
- mlt_timecode pos = mlt_producer_position( &this->parent );
- int64_t position = mlt_producer_frame_position( &this->parent, pos );
+ mlt_position position = mlt_producer_frame( &this->parent );
+
+ // 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" );
- // Loop through the virtual playlist
+ // Index for the main loop
int i = 0;
+ // Loop for each producer until found
for ( i = 0; i < this->count; i ++ )
{
// Increment the total
total += this->list[ i ]->frame_count;
+ // Check if the position indicates that we have found the clip
if ( position < this->list[ i ]->frame_count )
{
// Found it, now break
if ( producer != NULL )
{
position += this->list[ i ]->frame_in;
- position += mlt_producer_frame_position( producer, mlt_producer_get_in( producer ) );
- mlt_producer_seek_frame( producer, position );
+ mlt_producer_seek( producer, position );
}
else if ( !strcmp( eof, "pause" ) && total > 0 )
{
playlist_entry *entry = this->list[ this->count - 1 ];
mlt_producer this_producer = mlt_playlist_producer( this );
- mlt_producer_seek_frame( this_producer, total - 1 );
+ mlt_producer_seek( this_producer, total - 1 - mlt_producer_get_in( this_producer ) );
producer = entry->producer;
- position = mlt_producer_frame_position( producer, mlt_producer_get_in( producer ) );
- mlt_producer_seek_frame( producer, position + entry->frame_out );
+ mlt_producer_seek( producer, entry->frame_out );
mlt_producer_set_speed( this_producer, 0 );
- mlt_producer_set_speed( producer, 0 );
}
else if ( !strcmp( eof, "loop" ) && total > 0 )
{
playlist_entry *entry = this->list[ 0 ];
mlt_producer this_producer = mlt_playlist_producer( this );
- mlt_producer_seek_frame( this_producer, 0 );
+ mlt_producer_seek( this_producer, 0 );
producer = entry->producer;
- position = entry->frame_in;
- position += mlt_producer_frame_position( producer, mlt_producer_get_in( producer ) );
- mlt_producer_seek_frame( producer, position );
+ mlt_producer_seek( producer, entry->frame_in );
}
else
{
- mlt_producer_seek( mlt_playlist_producer( this ), 0 );
producer = &this->blank;
}
return producer;
}
+/** Invoked when a producer indicates that it has prematurely reached its end.
+*/
+
static mlt_producer mlt_playlist_virtual_set_out( mlt_playlist this )
{
// Default producer to blank
mlt_producer producer = &this->blank;
// Map playlist position to real producer in virtual playlist
- mlt_timecode pos = mlt_producer_position( &this->parent );
- int64_t position = mlt_producer_frame_position( &this->parent, pos );
+ mlt_position position = mlt_producer_frame( &this->parent );
// Loop through the virtual playlist
int i = 0;
// Seek in real producer to relative position
if ( i < this->count )
{
- // Update the playtime for the changed clip (hmmm)
- this->list[ i ]->frame_count = position + 1;
- this->list[ i ]->frame_out = position - this->list[ i ]->frame_in;
+ // Update the frame_count for the changed clip (hmmm)
+ this->list[ i ]->frame_out = position;
+ this->list[ i ]->frame_count = this->list[ i ]->frame_out - this->list[ i ]->frame_in + 1;
// Refresh the playlist
mlt_playlist_virtual_refresh( this );
return producer;
}
+/** Obtain the current clips index.
+*/
+
int mlt_playlist_current_clip( mlt_playlist this )
{
// Map playlist position to real producer in virtual playlist
- mlt_timecode pos = mlt_producer_position( &this->parent );
- int64_t position = mlt_producer_frame_position( &this->parent, pos );
+ mlt_position position = mlt_producer_frame( &this->parent );
// Loop through the virtual playlist
int i = 0;
return i;
}
+/** Obtain the current clips producer.
+*/
+
mlt_producer mlt_playlist_current( mlt_playlist this )
{
int i = mlt_playlist_current_clip( this );
return &this->blank;
}
-/** Get the timecode which corresponds to the start of the next clip.
+/** Get the position which corresponds to the start of the next clip.
*/
-mlt_timecode mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index )
+mlt_position mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index )
{
int64_t position = 0;
int absolute_clip = index;
else if ( absolute_clip > this->count )
absolute_clip = this->count;
- // Now determine the timecode
+ // Now determine the position
for ( i = 0; i < absolute_clip; i ++ )
position += this->list[ i ]->frame_count;
- return mlt_producer_time( &this->parent, position );
+ return position;
}
int mlt_playlist_get_clip_info( mlt_playlist this, mlt_playlist_clip_info *info, int index )
info->start = mlt_playlist_clip( this, mlt_whence_relative_start, index );
info->resource = mlt_properties_get( properties, "resource" );
info->frame_in = this->list[ index ]->frame_in;
- info->in = mlt_producer_time( producer, info->frame_in );
info->frame_out = this->list[ index ]->frame_out;
- info->out = mlt_producer_time( producer, info->frame_out );
- info->playtime = this->list[ index ]->playtime;
+ info->frame_count = this->list[ index ]->frame_count;
info->length = mlt_producer_get_length( producer );
info->fps = mlt_producer_get_fps( producer );
}
int mlt_playlist_append( mlt_playlist this, mlt_producer producer )
{
// Append to virtual list
- int64_t in = mlt_producer_frame_position( producer, mlt_producer_get_in( producer ) );
- int64_t out = mlt_producer_frame_position( producer, mlt_producer_get_out( producer ) );
- return mlt_playlist_virtual_append( this, producer, 0, out - in );
+ return mlt_playlist_virtual_append( this, producer, 0, mlt_producer_get_playtime( producer ) - 1 );
}
/** Append a producer to the playlist with in/out points.
*/
-int mlt_playlist_append_io( mlt_playlist this, mlt_producer producer, double in, double out )
+int mlt_playlist_append_io( mlt_playlist this, mlt_producer producer, mlt_position in, mlt_position out )
{
// Append to virtual list
if ( in != -1 && out != -1 )
- {
- int64_t fin = mlt_producer_frame_position( producer, in );
- int64_t fout = mlt_producer_frame_position( producer, out );
- return mlt_playlist_virtual_append( this, producer, fin, fout );
- }
+ return mlt_playlist_virtual_append( this, producer, in, out );
else
- {
return mlt_playlist_append( this, producer );
- }
}
/** Append a blank to the playlist of a given length.
*/
-int mlt_playlist_blank( mlt_playlist this, mlt_timecode length )
+int mlt_playlist_blank( mlt_playlist this, mlt_position length )
{
// Append to the virtual list
- int64_t fout = mlt_producer_frame_position( &this->blank, length );
- return mlt_playlist_virtual_append( this, &this->blank, 0, fout );
+ return mlt_playlist_virtual_append( this, &this->blank, 0, length );
}
/** Insert a producer into the playlist.
*/
-int mlt_playlist_insert( mlt_playlist this, mlt_producer producer, int where, mlt_timecode in, mlt_timecode out )
+int mlt_playlist_insert( mlt_playlist this, mlt_producer producer, int where, mlt_position in, mlt_position out )
{
return 0;
}
return 0;
}
-int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_timecode in, mlt_timecode out )
+/** Resize the current clip.
+*/
+
+int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_position in, mlt_position out )
{
int error = clip < 0 || clip >= this->count;
if ( error == 0 )
if ( in <= -1 )
in = 0;
- if ( out <= -1 || out >= mlt_producer_get_out( producer ) )
- out = mlt_producer_get_out( producer );
+ if ( out <= -1 || out >= mlt_producer_get_playtime( producer ) )
+ out = mlt_producer_get_playtime( producer ) - 1;
if ( out < in )
{
- mlt_timecode t = in;
+ mlt_position t = in;
in = out;
out = t;
}
- int64_t fin = mlt_producer_frame_position( producer, in );
- int64_t fout = mlt_producer_frame_position( producer, out );
-
- entry->frame_in = fin;
- entry->frame_out = fout;
- entry->frame_count = fout - fin + 1;
- entry->playtime = out - in;
+ entry->frame_in = in;
+ entry->frame_out = out;
+ entry->frame_count = out - in + 1;
mlt_playlist_virtual_refresh( this );
}
return error;
notifier( argument );
}
- // Update timecode on the frame we're creating
- mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) );
+ // Update position on the frame we're creating
+ mlt_frame_set_position( *frame, mlt_producer_frame( producer ) );
// Position ourselves on the next frame
mlt_producer_prepare_next( producer );
typedef struct
{
mlt_producer producer;
- mlt_timecode start;
+ mlt_position start;
char *resource;
- mlt_timecode in;
- int64_t frame_in;
- mlt_timecode out;
- int64_t frame_out;
- mlt_timecode playtime;
- mlt_timecode length;
+ mlt_position frame_in;
+ mlt_position frame_out;
+ mlt_position frame_count;
+ mlt_position length;
float fps;
}
mlt_playlist_clip_info;
extern int mlt_playlist_count( mlt_playlist this );
extern int mlt_playlist_clear( mlt_playlist this );
extern int mlt_playlist_append( mlt_playlist this, mlt_producer producer );
-extern int mlt_playlist_append_io( mlt_playlist this, mlt_producer producer, double in, double out );
-extern int mlt_playlist_blank( mlt_playlist this, mlt_timecode length );
-extern mlt_timecode mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index );
+extern int mlt_playlist_append_io( mlt_playlist this, mlt_producer producer, mlt_position in, mlt_position out );
+extern int mlt_playlist_blank( mlt_playlist this, mlt_position length );
+extern mlt_position mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index );
extern int mlt_playlist_current_clip( mlt_playlist this );
extern mlt_producer mlt_playlist_current( mlt_playlist this );
extern int mlt_playlist_get_clip_info( mlt_playlist this, mlt_playlist_clip_info *info, int index );
-extern int mlt_playlist_insert( mlt_playlist this, mlt_producer producer, int where, mlt_timecode in, mlt_timecode out );
+extern int mlt_playlist_insert( mlt_playlist this, mlt_producer producer, int where, mlt_position in, mlt_position out );
extern int mlt_playlist_remove( mlt_playlist this, int where );
extern int mlt_playlist_move( mlt_playlist this, int from, int to );
-extern int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_timecode in, mlt_timecode out );
+extern int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_position in, mlt_position out );
extern void mlt_playlist_close( mlt_playlist this );
#endif
// Set the default properties
mlt_properties_set( properties, "mlt_type", "mlt_producer" );
- mlt_properties_set_timecode( properties, "position", 0.0 );
+ mlt_properties_set_position( properties, "position", 0.0 );
mlt_properties_set_double( properties, "frame", 0 );
mlt_properties_set_double( properties, "fps", 25.0 );
mlt_properties_set_double( properties, "speed", 1.0 );
- mlt_properties_set_timecode( properties, "in", 0.0 );
- mlt_properties_set_timecode( properties, "out", 36000.0 );
- mlt_properties_set_timecode( properties, "length", 36000.0 );
- mlt_properties_set_int( properties, "known_length", 1 );
+ mlt_properties_set_position( properties, "in", 0.0 );
+ mlt_properties_set_position( properties, "out", 179999 );
+ mlt_properties_set_position( properties, "length", 180000 );
mlt_properties_set_double( properties, "aspect_ratio", 4.0 / 3.0 );
mlt_properties_set( properties, "log_id", "multitrack" );
return mlt_service_properties( &this->parent );
}
-/** Convert frame position to timecode.
+/** Convert frame position to position.
*/
-mlt_timecode mlt_producer_time( mlt_producer this, int64_t frame )
+/*
+mlt_position mlt_producer_time( mlt_producer this, int64_t frame )
{
if ( frame < 0 )
return -1;
else
- return ( mlt_timecode )frame / mlt_producer_get_fps( this );
+ return ( mlt_position )frame / mlt_producer_get_fps( this );
}
+*/
-/** Convert timecode to frame position.
+/** Convert position to frame position.
*/
-int64_t mlt_producer_frame_position( mlt_producer this, mlt_timecode position )
+/*
+int64_t mlt_producer_frame_position( mlt_producer this, mlt_position position )
{
if ( position < 0 )
return -1;
else
return ( int64_t )( floor( position * mlt_producer_get_fps( this ) + 0.5 ) );
}
+*/
-/** Seek to a specified time code.
+/** Seek to a specified position.
*/
-int mlt_producer_seek( mlt_producer this, mlt_timecode timecode )
+int mlt_producer_seek( mlt_producer this, mlt_position position )
{
// Check bounds
- if ( timecode < 0 )
- timecode = 0;
- if ( timecode > mlt_producer_get_playtime( this ) )
- timecode = mlt_producer_get_playtime( this );
+ if ( position < 0 )
+ position = 0;
+ else if ( position > mlt_producer_get_playtime( this ) )
+ position = mlt_producer_get_playtime( this ) - 1;
// Set the position
- mlt_properties_set_timecode( mlt_producer_properties( this ), "position", timecode );
+ mlt_properties_set_position( mlt_producer_properties( this ), "position", position );
// Calculate the absolute frame
- double frame = ( mlt_producer_get_in( this ) + timecode ) * mlt_producer_get_fps( this );
- mlt_properties_set_double( mlt_producer_properties( this ), "frame", floor( frame + 0.5 ) );
-
- return 0;
-}
-
-/** Seek to a specified absolute frame.
-*/
-
-int mlt_producer_seek_frame( mlt_producer this, int64_t frame )
-{
- // Calculate the time code
- double timecode = ( frame / mlt_producer_get_fps( this ) ) - mlt_producer_get_in( this );
-
- // If timecode is invalid, then seek on time
- if ( frame < 0 || timecode < 0 )
- {
- // Seek to the in point
- mlt_producer_seek( this, 0 );
- }
- else if ( timecode > mlt_producer_get_playtime( this ) )
- {
- // Seek to the out point
- mlt_producer_seek( this, mlt_producer_get_playtime( this ) );
- }
- else
- {
- // Set the position
- mlt_properties_set_timecode( mlt_producer_properties( this ), "position", timecode );
-
- // Set the absolute frame
- mlt_properties_set_double( mlt_producer_properties( this ), "frame", frame );
- }
+ mlt_properties_set_position( mlt_producer_properties( this ), "frame", mlt_producer_get_in( this ) + position );
return 0;
}
-/** Get the current time code.
+/** Get the current position (relative to in point).
*/
-mlt_timecode mlt_producer_position( mlt_producer this )
+mlt_position mlt_producer_position( mlt_producer this )
{
- return mlt_properties_get_timecode( mlt_producer_properties( this ), "position" );
+ return mlt_properties_get_position( mlt_producer_properties( this ), "position" );
}
-/** Get the current frame.
+/** Get the current position (relative to start of producer).
*/
-uint64_t mlt_producer_frame( mlt_producer this )
+mlt_position mlt_producer_frame( mlt_producer this )
{
return mlt_properties_get_double( mlt_producer_properties( this ), "frame" );
}
/** Set the in and out points.
*/
-int mlt_producer_set_in_and_out( mlt_producer this, mlt_timecode in, mlt_timecode out )
+int mlt_producer_set_in_and_out( mlt_producer this, mlt_position in, mlt_position out )
{
// Correct ins and outs if necessary
if ( in < 0 )
in = 0;
- if ( in > mlt_producer_get_length( this ) )
+ else if ( in > mlt_producer_get_length( this ) )
in = mlt_producer_get_length( this );
+
if ( out < 0 )
out = 0;
- if ( out > mlt_producer_get_length( this ) )
+ else if ( out > mlt_producer_get_length( this ) )
out = mlt_producer_get_length( this );
// Swap ins and outs if wrong
if ( out < in )
{
- mlt_timecode t = in;
+ mlt_position t = in;
in = out;
out = t;
}
// Set the values
- mlt_properties_set_timecode( mlt_producer_properties( this ), "in", in );
- mlt_properties_set_timecode( mlt_producer_properties( this ), "out", out );
-
- // Seek to the in point
- mlt_producer_seek( this, 0 );
+ mlt_properties_set_position( mlt_producer_properties( this ), "in", in );
+ mlt_properties_set_position( mlt_producer_properties( this ), "out", out );
return 0;
}
/** Get the in point.
*/
-mlt_timecode mlt_producer_get_in( mlt_producer this )
+mlt_position mlt_producer_get_in( mlt_producer this )
{
- return mlt_properties_get_timecode( mlt_producer_properties( this ), "in" );
+ return mlt_properties_get_position( mlt_producer_properties( this ), "in" );
}
/** Get the out point.
*/
-mlt_timecode mlt_producer_get_out( mlt_producer this )
+mlt_position mlt_producer_get_out( mlt_producer this )
{
- return mlt_properties_get_timecode( mlt_producer_properties( this ), "out" );
+ return mlt_properties_get_position( mlt_producer_properties( this ), "out" );
}
/** Get the total play time.
*/
-mlt_timecode mlt_producer_get_playtime( mlt_producer this )
+mlt_position mlt_producer_get_playtime( mlt_producer this )
{
- return mlt_producer_get_out( this ) - mlt_producer_get_in( this );
+ return mlt_producer_get_out( this ) - mlt_producer_get_in( this ) + 1;
}
/** Get the total length of the producer.
*/
-mlt_timecode mlt_producer_get_length( mlt_producer this )
+mlt_position mlt_producer_get_length( mlt_producer this )
{
- return mlt_properties_get_timecode( mlt_producer_properties( this ), "length" );
+ return mlt_properties_get_position( mlt_producer_properties( this ), "length" );
}
/** Prepare for next frame.
void mlt_producer_prepare_next( mlt_producer this )
{
- mlt_producer_seek_frame( this, mlt_producer_frame( this ) + mlt_producer_get_speed( this ) );
+ mlt_producer_seek( this, mlt_producer_frame( this ) + mlt_producer_get_speed( this ) );
}
/** Get a frame.
{
// Get the frame from the implementation
result = this->get_frame( this, frame, index );
-
- mlt_properties frame_properties = mlt_frame_properties( *frame );
- double speed = mlt_producer_get_speed( this );
- mlt_properties_set_double( frame_properties, "speed", speed );
}
else
{
// Generate a test frame
*frame = mlt_frame_init( );
- // Set the timecode
- result = mlt_frame_set_timecode( *frame, mlt_producer_position( this ) );
+ // Set the position
+ result = mlt_frame_set_position( *frame, mlt_producer_position( this ) );
- // Calculate the next timecode
+ // Calculate the next position
mlt_producer_prepare_next( this );
}
- // Copy the fps of the producer onto the frame
+ // Copy the fps and speed of the producer onto the frame
mlt_properties properties = mlt_frame_properties( *frame );
mlt_properties_set_double( properties, "fps", mlt_producer_get_fps( this ) );
+ double speed = mlt_producer_get_speed( this );
+ mlt_properties_set_double( properties, "speed", speed );
return 0;
}
/** Public final methods
*/
+//extern double mlt_producer_convert_position_to_time( mlt_producer this, int64_t frame );
+//extern mlt_position mlt_producer_convert_time_to_position( mlt_producer this, double time );
+
extern int mlt_producer_init( mlt_producer this, void *child );
extern mlt_service mlt_producer_service( mlt_producer this );
extern mlt_properties mlt_producer_properties( mlt_producer this );
-extern mlt_timecode mlt_producer_time( mlt_producer this, int64_t frame );
-extern int64_t mlt_producer_frame_position( mlt_producer this, mlt_timecode position );
-extern int mlt_producer_seek( mlt_producer this, mlt_timecode timecode );
-extern int mlt_producer_seek_frame( mlt_producer this, int64_t frame );
-extern mlt_timecode mlt_producer_position( mlt_producer this );
-extern uint64_t mlt_producer_frame( mlt_producer this );
+extern int mlt_producer_seek( mlt_producer this, mlt_position position );
+extern mlt_position mlt_producer_position( mlt_producer this );
+extern mlt_position mlt_producer_frame( mlt_producer this );
extern int mlt_producer_set_speed( mlt_producer this, double speed );
extern double mlt_producer_get_speed( mlt_producer this );
extern double mlt_producer_get_fps( mlt_producer this );
-extern int mlt_producer_set_in_and_out( mlt_producer this, mlt_timecode in, mlt_timecode out );
-extern mlt_timecode mlt_producer_get_in( mlt_producer this );
-extern mlt_timecode mlt_producer_get_out( mlt_producer this );
-extern mlt_timecode mlt_producer_get_playtime( mlt_producer this );
-extern mlt_timecode mlt_producer_get_length( mlt_producer this );
+extern int mlt_producer_set_in_and_out( mlt_producer this, mlt_position in, mlt_position out );
+extern mlt_position mlt_producer_get_in( mlt_producer this );
+extern mlt_position mlt_producer_get_out( mlt_producer this );
+extern mlt_position mlt_producer_get_playtime( mlt_producer this );
+extern mlt_position mlt_producer_get_length( mlt_producer this );
extern void mlt_producer_prepare_next( mlt_producer this );
extern void mlt_producer_close( mlt_producer this );
/** Get a value associated to the name.
*/
-mlt_timecode mlt_properties_get_timecode( mlt_properties this, char *name )
+mlt_position mlt_properties_get_position( mlt_properties this, char *name )
{
mlt_property value = mlt_properties_find( this, name );
- return value == NULL ? 0 : mlt_property_get_timecode( value );
+ return value == NULL ? 0 : mlt_property_get_position( value );
}
/** Set a value associated to the name.
*/
-int mlt_properties_set_timecode( mlt_properties this, char *name, mlt_timecode value )
+int mlt_properties_set_position( mlt_properties this, char *name, mlt_position value )
{
int error = 1;
// Set it if not NULL
if ( property != NULL )
- error = mlt_property_set_timecode( property, value );
+ error = mlt_property_set_position( property, value );
return error;
}
extern int mlt_properties_set_int( mlt_properties this, char *name, int value );
extern double mlt_properties_get_double( mlt_properties this, char *name );
extern int mlt_properties_set_double( mlt_properties this, char *name, double value );
-extern mlt_timecode mlt_properties_get_timecode( mlt_properties this, char *name );
-extern int mlt_properties_set_timecode( mlt_properties this, char *name, mlt_timecode value );
+extern mlt_position mlt_properties_get_position( mlt_properties this, char *name );
+extern int mlt_properties_set_position( mlt_properties this, char *name, mlt_position value );
extern int mlt_properties_set_data( mlt_properties this, char *name, void *value, int length, mlt_destructor, mlt_serialiser );
extern void *mlt_properties_get_data( mlt_properties this, char *name, int *length );
extern int mlt_properties_count( mlt_properties this );
return 0;
}
-/** Set a timecode on this property.
+/** Set a position on this property.
*/
-int mlt_property_set_timecode( mlt_property this, mlt_timecode value )
+int mlt_property_set_position( mlt_property this, mlt_position value )
{
mlt_property_clear( this );
- this->types = mlt_prop_timecode;
- this->prop_timecode = value;
+ this->types = mlt_prop_position;
+ this->prop_position = value;
return 0;
}
return this->prop_int;
else if ( this->types & mlt_prop_double )
return ( int )this->prop_double;
- else if ( this->types & mlt_prop_timecode )
- return ( int )this->prop_timecode;
+ else if ( this->types & mlt_prop_position )
+ return ( int )this->prop_position;
else if ( this->types & mlt_prop_int64 )
return ( int )this->prop_int64;
else if ( this->types & mlt_prop_string )
return this->prop_double;
else if ( this->types & mlt_prop_int )
return ( double )this->prop_int;
- else if ( this->types & mlt_prop_timecode )
- return ( double )this->prop_timecode;
+ else if ( this->types & mlt_prop_position )
+ return ( double )this->prop_position;
else if ( this->types & mlt_prop_int64 )
return ( double )this->prop_int64;
else if ( this->types & mlt_prop_string )
return 0;
}
-/** Get a timecode from this property.
+/** Get a position from this property.
*/
-mlt_timecode mlt_property_get_timecode( mlt_property this )
+mlt_position mlt_property_get_position( mlt_property this )
{
- if ( this->types & mlt_prop_timecode )
- return this->prop_timecode;
+ if ( this->types & mlt_prop_position )
+ return this->prop_position;
else if ( this->types & mlt_prop_int )
- return ( mlt_timecode )this->prop_int;
+ return ( mlt_position )this->prop_int;
else if ( this->types & mlt_prop_double )
- return ( mlt_timecode )this->prop_double;
+ return ( mlt_position )this->prop_double;
else if ( this->types & mlt_prop_int64 )
- return ( mlt_timecode )this->prop_int64;
+ return ( mlt_position )this->prop_int64;
else if ( this->types & mlt_prop_string )
- return ( mlt_timecode )atof( this->prop_string );
+ return ( mlt_position )atol( this->prop_string );
return 0;
}
return ( int64_t )this->prop_int;
else if ( this->types & mlt_prop_double )
return ( int64_t )this->prop_double;
- else if ( this->types & mlt_prop_timecode )
- return ( int64_t )this->prop_timecode;
+ else if ( this->types & mlt_prop_position )
+ return ( int64_t )this->prop_position;
else if ( this->types & mlt_prop_string )
- return ( int64_t )atof( this->prop_string );
+ return ( int64_t )atol( this->prop_string );
return 0;
}
this->prop_string = malloc( 32 );
sprintf( this->prop_string, "%e", this->prop_double );
}
- else if ( this->types & mlt_prop_timecode )
+ else if ( this->types & mlt_prop_position )
{
this->types |= mlt_prop_string;
this->prop_string = malloc( 32 );
- sprintf( this->prop_string, "%e", this->prop_timecode );
+ sprintf( this->prop_string, "%lld", this->prop_position );
}
else if ( this->types & mlt_prop_int64 )
{
mlt_prop_none = 0,
mlt_prop_int = 1,
mlt_prop_string = 2,
- mlt_prop_timecode = 4,
+ mlt_prop_position = 4,
mlt_prop_double = 8,
mlt_prop_data = 16,
mlt_prop_int64 = 32
// Atomic type handling
int prop_int;
- mlt_timecode prop_timecode;
+ mlt_position prop_position;
double prop_double;
int64_t prop_int64;
extern void mlt_property_clear( mlt_property this );
extern int mlt_property_set_int( mlt_property this, int value );
extern int mlt_property_set_double( mlt_property this, double value );
-extern int mlt_property_set_timecode( mlt_property this, mlt_timecode value );
+extern int mlt_property_set_position( mlt_property this, mlt_position value );
extern int mlt_property_set_uint64( mlt_property this, uint64_t value );
extern int mlt_property_set_string( mlt_property this, char *value );
extern int mlt_property_set_data( mlt_property this, void *value, int length, mlt_destructor destructor, mlt_serialiser serialiser );
extern int mlt_property_get_int( mlt_property this );
extern double mlt_property_get_double( mlt_property this );
-extern mlt_timecode mlt_property_get_timecode( mlt_property this );
+extern mlt_position mlt_property_get_position( mlt_property this );
extern int64_t mlt_property_get_int64( mlt_property this );
extern char *mlt_property_get_string( mlt_property this );
extern void *mlt_property_get_data( mlt_property this, int *length );
#include "mlt_tractor.h"
#include "mlt_frame.h"
+#include "mlt_multitrack.h"
#include <stdio.h>
#include <stdlib.h>
struct mlt_tractor_s
{
- struct mlt_service_s parent;
+ struct mlt_producer_s parent;
mlt_service producer;
};
/** Forward references to static methods.
*/
-static int service_get_frame( mlt_service this, mlt_frame_ptr frame, int track );
+static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int track );
/** Constructor for the tractor.
mlt_tractor this = calloc( sizeof( struct mlt_tractor_s ), 1 );
if ( this != NULL )
{
- mlt_service service = &this->parent;
- if ( mlt_service_init( service, this ) == 0 )
+ mlt_producer producer = &this->parent;
+ if ( mlt_producer_init( producer, this ) == 0 )
{
- service->get_frame = service_get_frame;
+ producer->get_frame = producer_get_frame;
}
else
{
mlt_service mlt_tractor_service( mlt_tractor this )
{
+ return mlt_producer_service( &this->parent );
+}
+
+/** Get the producer object associated to the tractor.
+*/
+
+mlt_producer mlt_tractor_producer( mlt_tractor this )
+{
return &this->parent;
}
+/** Get the properties object associated to the tractor.
+*/
+
+mlt_properties mlt_tractor_properties( mlt_tractor this )
+{
+ return mlt_producer_properties( &this->parent );
+}
+
/** Connect the tractor.
*/
int mlt_tractor_connect( mlt_tractor this, mlt_service producer )
{
- int ret = mlt_service_connect_producer( &this->parent, producer, 0 );
+ int ret = mlt_service_connect_producer( mlt_tractor_service( this ), producer, 0 );
+ // This is the producer we're going to connect to
if ( ret == 0 )
- {
- // This is the producer we're going to connect to
this->producer = producer;
- }
return ret;
}
TODO: This should be reading a pump being populated by the thread...
*/
-static int service_get_frame( mlt_service parent, mlt_frame_ptr frame, int track )
+static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int track )
{
mlt_tractor this = parent->child;
int done = 0;
mlt_frame temp;
+ // Get the properties of the parent producer
+ mlt_properties properties = mlt_producer_properties( parent );
+
+ // Try to obtain the multitrack associated to the tractor
+ mlt_multitrack multitrack = mlt_properties_get_data( properties, "multitrack", NULL );
+
+ // If we don't have one, we're in trouble...
+ if ( multitrack != NULL )
+ {
+ mlt_producer target = mlt_multitrack_producer( multitrack );
+ mlt_producer_seek( target, mlt_producer_frame( parent ) );
+ mlt_producer_set_speed( target, mlt_producer_get_speed( parent ) );
+ mlt_producer_set_in_and_out( parent, mlt_producer_get_in( target ), mlt_producer_get_out( target ) );
+ }
+ else
+ {
+ fprintf( stderr, "tractor without a multitrack!!\n" );
+ }
+
// Loop through each of the tracks we're harvesting
for ( i = 0; !done; i ++ )
{
}
}
+ // Prepare the next frame
+ mlt_producer_prepare_next( parent );
+
// Indicate our found status
return 0;
}
void mlt_tractor_close( mlt_tractor this )
{
- mlt_service_close( &this->parent );
+ mlt_producer_close( &this->parent );
free( this );
}
extern mlt_tractor mlt_tractor_init( );
extern mlt_service mlt_tractor_service( mlt_tractor this );
+extern mlt_producer mlt_tractor_producer( mlt_tractor this );
+extern mlt_properties mlt_tractor_properties( mlt_tractor this );
extern int mlt_tractor_connect( mlt_tractor this, mlt_service service );
extern void mlt_tractor_close( mlt_tractor this );
service->get_frame = transition_get_frame;
- mlt_properties_set_timecode( properties, "in", 0 );
- mlt_properties_set_timecode( properties, "out", 0 );
+ mlt_properties_set_position( properties, "in", 0 );
+ mlt_properties_set_position( properties, "out", 0 );
mlt_properties_set_int( properties, "a_track", 0 );
mlt_properties_set_int( properties, "b_track", 1 );
/** Set the in and out points.
*/
-void mlt_transition_set_in_and_out( mlt_transition this, mlt_timecode in, mlt_timecode out )
+void mlt_transition_set_in_and_out( mlt_transition this, mlt_position in, mlt_position out )
{
mlt_properties properties = mlt_transition_properties( this );
- mlt_properties_set_timecode( properties, "in", in );
- mlt_properties_set_timecode( properties, "out", out );
+ mlt_properties_set_position( properties, "in", in );
+ mlt_properties_set_position( properties, "out", out );
}
/** Get the index of the a track.
/** Get the in point.
*/
-mlt_timecode mlt_transition_get_in( mlt_transition this )
+mlt_position mlt_transition_get_in( mlt_transition this )
{
mlt_properties properties = mlt_transition_properties( this );
- return mlt_properties_get_timecode( properties, "in" );
+ return mlt_properties_get_position( properties, "in" );
}
/** Get the out point.
*/
-mlt_timecode mlt_transition_get_out( mlt_transition this )
+mlt_position mlt_transition_get_out( mlt_transition this )
{
mlt_properties properties = mlt_transition_properties( this );
- return mlt_properties_get_timecode( properties, "out" );
+ return mlt_properties_get_position( properties, "out" );
}
/** Process the frame.
int a_track = mlt_properties_get_int( properties, "a_track" );
int b_track = mlt_properties_get_int( properties, "b_track" );
- mlt_timecode in = mlt_properties_get_timecode( properties, "in" );
- mlt_timecode out = mlt_properties_get_timecode( properties, "out" );
+ mlt_position in = mlt_properties_get_position( properties, "in" );
+ mlt_position out = mlt_properties_get_position( properties, "out" );
// Fetch a and b frames together...
if ( ( index == a_track || index == b_track ) &&
if ( index == a_track )
{
// Determine if we're in the right time zone
- mlt_timecode timecode = mlt_frame_get_timecode( this->a_frame );
- if ( timecode >= in && timecode < out )
+ mlt_position position = mlt_frame_get_position( this->a_frame );
+ if ( position >= in && position < out )
{
// Process the transition
*frame = transition_process( this, this->a_frame, this->b_frame );
}
else
{
- mlt_timecode timecode = mlt_frame_get_timecode( this->b_frame );
- if ( timecode >= in && timecode < out )
+ mlt_position position = mlt_frame_get_position( this->b_frame );
+ if ( position >= in && position < out )
{
// We're in the zone, but the 'a frame' has not been requested yet
*frame = mlt_frame_init( );
extern mlt_service mlt_transition_service( mlt_transition this );
extern mlt_properties mlt_transition_properties( mlt_transition this );
extern int mlt_transition_connect( mlt_transition this, mlt_service producer, int a_track, int b_track );
-extern void mlt_transition_set_in_and_out( mlt_transition this, mlt_timecode in, mlt_timecode out );
+extern void mlt_transition_set_in_and_out( mlt_transition this, mlt_position in, mlt_position out );
extern int mlt_transition_get_a_track( mlt_transition this );
extern int mlt_transition_get_b_track( mlt_transition this );
-extern mlt_timecode mlt_transition_get_in( mlt_transition this );
-extern mlt_timecode mlt_transition_get_out( mlt_transition this );
+extern mlt_position mlt_transition_get_in( mlt_transition this );
+extern mlt_position mlt_transition_get_out( mlt_transition this );
extern void mlt_transition_close( mlt_transition this );
#endif
}
mlt_whence;
-typedef double mlt_timecode;
+typedef int64_t mlt_position;
typedef struct mlt_frame_s *mlt_frame, **mlt_frame_ptr;
typedef struct mlt_properties_s *mlt_properties;
typedef struct mlt_service_s *mlt_service;
case '9':
mlt_producer_set_speed( producer, 10 );
break;
+ case 'd':
+ if ( multitrack != NULL )
+ {
+ int i = 0;
+ mlt_position last = -1;
+ for ( i = 0; 1; i ++ )
+ {
+ mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_start, i );
+ if ( time == last )
+ break;
+ last = time;
+ fprintf( stderr, "%d: %lld\n", i, time );
+ }
+ }
+ break;
+
case 'g':
if ( multitrack != NULL )
{
- mlt_timecode time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 0 );
+ mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 0 );
mlt_producer_seek( producer, time );
}
break;
case 'h':
if ( multitrack != NULL )
{
- mlt_producer producer = mlt_multitrack_producer( multitrack );
- int64_t position = mlt_producer_frame_position( producer, mlt_producer_position( producer ) );
+ mlt_position position = mlt_producer_position( producer );
mlt_producer_set_speed( producer, 0 );
- mlt_producer_seek_frame( producer, position - 1 >= 0 ? position - 1 : 0 );
+ mlt_producer_seek( producer, position - 1 >= 0 ? position - 1 : 0 );
}
break;
case 'j':
if ( multitrack != NULL )
{
- mlt_timecode time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 1 );
+ mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 1 );
mlt_producer_seek( producer, time );
}
break;
case 'k':
if ( multitrack != NULL )
{
- mlt_timecode time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, -1 );
+ mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, -1 );
mlt_producer_seek( producer, time );
}
break;
case 'l':
if ( multitrack != NULL )
{
- mlt_producer producer = mlt_multitrack_producer( multitrack );
- int64_t position = mlt_producer_frame_position( producer, mlt_producer_position( producer ) );
+ mlt_position position = mlt_producer_position( producer );
mlt_producer_set_speed( producer, 0 );
- mlt_producer_seek_frame( producer, position + 1 );
+ mlt_producer_seek( producer, position + 1 );
}
break;
}
mlt_properties properties = unit->properties;
int generation = mlt_properties_get_int( properties, "generation" );
mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
- mlt_producer producer = mlt_playlist_producer( playlist );
valerie_response_printf( response, 1024, "%d\n", generation );
i, info.resource,
info.frame_in,
info.frame_out,
- mlt_producer_frame_position( producer, info.playtime ),
- mlt_producer_frame_position( producer, info.length ),
+ info.frame_count,
+ info.length,
info.fps );
}
}
{
mlt_properties properties = unit->properties;
mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
- mlt_playlist_append_io( playlist, instance, mlt_producer_time( instance, in ), mlt_producer_time( instance, out ) );
+ mlt_playlist_append_io( playlist, instance, in, out );
miracle_log( LOG_DEBUG, "loaded clip %s", clip );
miracle_unit_status_communicate( unit );
return valerie_ok;
{
mlt_properties properties = unit->properties;
mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
- mlt_playlist_insert( playlist, instance, index, mlt_producer_time( instance, in ), mlt_producer_time( instance, out ) );
+ mlt_playlist_insert( playlist, instance, index, in, out );
miracle_log( LOG_DEBUG, "inserted clip %s at %d", clip, index );
update_generation( unit );
miracle_unit_status_communicate( unit );
{
mlt_properties properties = unit->properties;
mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
- mlt_playlist_append_io( playlist, instance, mlt_producer_time( instance, in ), mlt_producer_time( instance, out ) );
+ mlt_playlist_append_io( playlist, instance, in, out );
miracle_log( LOG_DEBUG, "appended clip %s", clip );
update_generation( unit );
miracle_unit_status_communicate( unit );
status->fps = mlt_producer_get_fps( producer );
status->in = info.frame_in;
status->out = info.frame_out;
- status->position = mlt_producer_frame_position( producer, mlt_producer_position( clip ) );
- status->length = mlt_producer_frame_position( producer, mlt_producer_get_length( clip ) );
+ status->position = mlt_producer_position( clip );
+ status->length = mlt_producer_get_length( clip );
strncpy( status->tail_clip, info.resource, sizeof( status->tail_clip ) );
status->tail_in = info.frame_in;
status->tail_out = info.frame_out;
- status->tail_position = mlt_producer_frame_position( producer, mlt_producer_position( clip ) );
- status->tail_length = mlt_producer_frame_position( producer, mlt_producer_get_length( clip ) );
+ status->tail_position = mlt_producer_position( clip );
+ status->tail_length = mlt_producer_get_length( clip );
status->clip_index = mlt_playlist_current_clip( playlist );
status->seek_flag = 1;
}
if ( mlt_playlist_get_clip_info( playlist, &info, clip ) == 0 )
{
- int64_t frame_start = mlt_producer_frame_position( info.producer, info.start );
+ int64_t frame_start = info.start;
int64_t frame_offset = position;
if ( frame_offset < 0 )
if ( frame_offset >= info.frame_out )
frame_offset = info.frame_out;
- mlt_producer_seek_frame( producer, frame_start + frame_offset - info.frame_in );
+ mlt_producer_seek( producer, frame_start + frame_offset - info.frame_in );
}
miracle_unit_status_communicate( unit );
if ( error == 0 )
{
- mlt_timecode in = mlt_producer_time( info.producer, position );
- error = mlt_playlist_resize_clip( playlist, index, in, info.out );
+ miracle_unit_play( unit, 0 );
+ error = mlt_playlist_resize_clip( playlist, index, position, info.frame_out );
update_generation( unit );
miracle_unit_change_position( unit, index, 0 );
}
if ( error == 0 )
{
- mlt_timecode out = mlt_producer_time( info.producer, position );
- error = mlt_playlist_resize_clip( playlist, index, info.in, out );
+ miracle_unit_play( unit, 0 );
+ error = mlt_playlist_resize_clip( playlist, index, info.frame_in, position );
update_generation( unit );
miracle_unit_status_communicate( unit );
miracle_unit_change_position( unit, index, -1 );
mlt_properties properties = unit->properties;
mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
mlt_producer producer = mlt_playlist_producer( playlist );
- mlt_timecode position = mlt_producer_position( producer );
- mlt_producer_seek_frame( producer, mlt_producer_frame_position( producer, position ) + offset );
+ mlt_position position = mlt_producer_frame( producer );
+ mlt_producer_seek( producer, position + offset );
}
/** Set the unit's clip mode regarding in and out points.
( *frame )->get_audio = producer_get_audio;
// Update timecode on the frame we're creating
- mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) );
+ mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
// Calculate the next timecode
mlt_producer_prepare_next( producer );
// Get the b frame from the stack
mlt_frame b_frame = mlt_frame_pop_frame( this );
- // Get the properties of the b frame
- mlt_properties b_props = mlt_frame_properties( b_frame );
-
- // Arbitrary composite defaults
- int x = 0;
- int y = 0;
- double mix = 1.0;
-
- // Override from b frame properties if provided
- if ( mlt_properties_get( b_props, "x" ) != NULL )
- x = mlt_properties_get_int( b_props, "x" );
- if ( mlt_properties_get( b_props, "y" ) != NULL )
- y = mlt_properties_get_int( b_props, "y" );
- if ( mlt_properties_get( b_props, "mix" ) != NULL )
- mix = mlt_properties_get_double( b_props, "mix" );
-
- // Composite the b_frame on the a_frame
- mlt_frame_composite_yuv( this, b_frame, x, y, mix );
-
- // Extract the a_frame image info
- *width = mlt_properties_get_int( a_props, "width" );
- *height = mlt_properties_get_int( a_props, "height" );
- *image = mlt_properties_get_data( a_props, "image", NULL );
-
- // Close the b_frame
- mlt_frame_close( b_frame );
+ if ( b_frame != NULL )
+ {
+ // Get the properties of the b frame
+ mlt_properties b_props = mlt_frame_properties( b_frame );
+
+ // Arbitrary composite defaults
+ int x = 0;
+ int y = 0;
+ double mix = 1.0;
+
+ // Override from b frame properties if provided
+ if ( mlt_properties_get( b_props, "x" ) != NULL )
+ x = mlt_properties_get_int( b_props, "x" );
+ if ( mlt_properties_get( b_props, "y" ) != NULL )
+ y = mlt_properties_get_int( b_props, "y" );
+ if ( mlt_properties_get( b_props, "mix" ) != NULL )
+ mix = mlt_properties_get_double( b_props, "mix" );
+
+ // Composite the b_frame on the a_frame
+ mlt_frame_composite_yuv( this, b_frame, x, y, mix );
+
+ // Extract the a_frame image info
+ *width = mlt_properties_get_int( a_props, "width" );
+ *height = mlt_properties_get_int( a_props, "height" );
+ *image = mlt_properties_get_data( a_props, "image", NULL );
+
+ // Close the b_frame
+ mlt_frame_close( b_frame );
+ }
+ else if ( a_props != NULL )
+ {
+ // Extract the a_frame image info
+ *width = mlt_properties_get_int( a_props, "width" );
+ *height = mlt_properties_get_int( a_props, "height" );
+ *image = mlt_properties_get_data( a_props, "image", NULL );
+ }
return 0;
}
}
// Determine the time position of this frame in the transition duration
- mlt_timecode in = mlt_transition_get_in( transition );
- mlt_timecode out = mlt_transition_get_out( transition );
- mlt_timecode time = mlt_frame_get_timecode( b_frame );
+ mlt_position in = mlt_transition_get_in( transition );
+ mlt_position out = mlt_transition_get_out( transition );
+ mlt_position time = mlt_frame_get_position( b_frame );
double pos = ( time - in ) / ( out - in );
// Set the b frame properties
TARGET = ../libmltdv.so
OBJS = factory.o \
- producer_libdv.o
+ producer_libdv.o \
+ consumer_libdv.o
CFLAGS = -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread
libdv libmltdv.so
EOF
+cat << EOF >> ../consumers.dat
+libdv libmltdv.so
+EOF
+
fi
--- /dev/null
+/*
+ * producer_libdv.c -- a DV encoder based on libdv
+ * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Author: Charles Yates <charles.yates@pandora.be>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+// Local header files
+#include "consumer_libdv.h"
+
+// mlt Header files
+#include <framework/mlt_frame.h>
+
+// System header files
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+
+// libdv header files
+#include <libdv/dv.h>
+
+// Forward references.
+static int consumer_encode_video( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame );
+static void consumer_encode_audio( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame );
+static void consumer_output( mlt_consumer this, uint8_t *dv_frame, int size, mlt_frame frame );
+static void *consumer_thread( void *arg );
+static void consumer_close( mlt_consumer this );
+
+/** Initialise the dv consumer.
+*/
+
+mlt_consumer consumer_libdv_init( char *arg )
+{
+ // Allocate the consumer
+ mlt_consumer this = calloc( 1, sizeof( struct mlt_consumer_s ) );
+
+ // If memory allocated and initialises without error
+ if ( this != NULL && mlt_consumer_init( this, NULL ) == 0 )
+ {
+ // Get properties from the consumer
+ mlt_properties properties = mlt_consumer_properties( this );
+
+ // Allocate a thread
+ pthread_t *thread = calloc( 1, sizeof( pthread_t ) );
+
+ // Assign close callback
+ this->close = consumer_close;
+
+ // Assign all properties
+ if ( arg == NULL || !strcmp( arg, "PAL" ) )
+ mlt_properties_set_double( properties, "fps", 25 );
+ else
+ mlt_properties_set_double( properties, "fps", 29.97 );
+
+ mlt_properties_set_data( properties, "thread", thread, sizeof( pthread_t ), free, NULL );
+ mlt_properties_set_data( properties, "video", consumer_encode_video, 0, NULL, NULL );
+ mlt_properties_set_data( properties, "audio", consumer_encode_audio, 0, NULL, NULL );
+ mlt_properties_set_data( properties, "output", consumer_output, 0, NULL, NULL );
+
+ // Create the thread (this should not happen immediately)
+ mlt_properties_set_int( properties, "running", 1 );
+ pthread_create( thread, NULL, consumer_thread, this );
+ }
+ else
+ {
+ // Clean up in case of init failure
+ free( this );
+ this = NULL;
+ }
+
+ // Return this
+ return this;
+}
+
+/** Get or create a new libdv encoder.
+*/
+
+static dv_encoder_t *libdv_get_encoder( mlt_consumer this, mlt_frame frame )
+{
+ // Get the properties of the consumer
+ mlt_properties this_properties = mlt_consumer_properties( this );
+
+ // Obtain the dv_encoder
+ dv_encoder_t *encoder = mlt_properties_get_data( this_properties, "dv_encoder", NULL );
+
+ // Construct one if we don't have one
+ if ( encoder == NULL )
+ {
+ // Get the fps of the consumer (for now - should be from frame)
+ double fps = mlt_properties_get_double( this_properties, "fps" );
+
+ // Create the encoder
+ encoder = dv_encoder_new( fps != 25, 0, 0 );
+
+ // Encoder settings
+ encoder->isPAL = fps = 25;
+ encoder->is16x9 = 0;
+ encoder->vlc_encode_passes = 1;
+ encoder->static_qno = 0;
+ encoder->force_dct = DV_DCT_AUTO;
+
+ // Store the encoder on the properties
+ mlt_properties_set_data( this_properties, "dv_encoder", encoder, 0, ( mlt_destructor )dv_encoder_free, NULL );
+
+ // Convenience for image dimensions
+ mlt_properties_set_int( this_properties, "width", 720 );
+ mlt_properties_set_int( this_properties, "height", fps == 25 ? 576 : 480 );
+ }
+
+ // Return the encoder
+ return encoder;
+}
+
+
+/** The libdv encode video method.
+*/
+
+static int consumer_encode_video( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame )
+{
+ // Obtain the dv_encoder
+ dv_encoder_t *encoder = libdv_get_encoder( this, frame );
+
+ // Get the properties of the consumer
+ mlt_properties this_properties = mlt_consumer_properties( this );
+
+ // This will hold the size of the dv frame
+ int size = 0;
+
+ // If we get an encoder, then encode the image
+ if ( encoder != NULL )
+ {
+ // Specify desired image properties
+ mlt_image_format fmt = mlt_image_yuv422;
+ int width = mlt_properties_get_int( this_properties, "width" );
+ int height = mlt_properties_get_int( this_properties, "height" );
+ uint8_t *image = NULL;
+
+ // Get the image
+ mlt_frame_get_image( frame, &image, &fmt, &width, &height, 0 );
+
+ // Check that we get what we expected
+ if ( fmt != mlt_image_yuv422 ||
+ width != mlt_properties_get_int( this_properties, "width" ) ||
+ height != mlt_properties_get_int( this_properties, "height" ) ||
+ image == NULL )
+ {
+ // We should try to recover here
+ fprintf( stderr, "We have a problem houston...\n" );
+ }
+ else
+ {
+ // Calculate the size of the dv frame
+ size = height == 576 ? frame_size_625_50 : frame_size_525_60;
+ }
+
+ // Process the frame
+ if ( size != 0 )
+ {
+ // Encode the image
+ dv_encode_full_frame( encoder, &image, e_dv_color_yuv, dv_frame );
+ }
+ }
+
+ return size;
+}
+
+/** The libdv encode audio method.
+*/
+
+static void consumer_encode_audio( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame )
+{
+ // Get the properties of the consumer
+ mlt_properties this_properties = mlt_consumer_properties( this );
+
+ // Obtain the dv_encoder
+ dv_encoder_t *encoder = libdv_get_encoder( this, frame );
+
+ // Only continue if we have an encoder
+ if ( encoder != NULL )
+ {
+ // Get the frame count
+ int count = mlt_properties_get_int( this_properties, "count" );
+
+ // Default audio args
+ mlt_audio_format fmt = mlt_audio_pcm;
+ int channels = 2;
+ int frequency = 48000;
+ int samples = mlt_sample_calculator( mlt_properties_get_double( this_properties, "fps" ), frequency, count );
+ int16_t *pcm = NULL;
+
+ // Get the frame number
+ time_t start = time( NULL );
+ int height = mlt_properties_get_int( this_properties, "height" );
+ int is_pal = height == 576;
+ int is_wide = 0;
+
+ // Temporary - audio buffer allocation
+ int16_t *audio_buffers[ 4 ];
+ int i = 0;
+ int j = 0;
+ for ( i = 0 ; i < 4; i ++ )
+ audio_buffers[ i ] = malloc( 2 * DV_AUDIO_MAX_SAMPLES );
+
+ // Get the audio
+ mlt_frame_get_audio( frame, &pcm, &fmt, &frequency, &channels, &samples );
+
+ // Inform the encoder of the number of audio samples
+ encoder->samples_this_frame = samples;
+
+ // Fill the audio buffers correctly
+ for ( i = 0; i < samples; i ++ )
+ for ( j = 0; j < channels; j++ )
+ audio_buffers[ j ][ i ] = *pcm ++;
+
+ // Encode audio on frame
+ dv_encode_full_audio( encoder, audio_buffers, channels, frequency, dv_frame );
+
+ // Specify meta data on the frame
+ dv_encode_metadata( dv_frame, is_pal, is_wide, &start, count );
+ dv_encode_timecode( dv_frame, is_pal, count );
+
+ // Update properties
+ mlt_properties_set_int( this_properties, "count", ++ count );
+
+ // Temporary - free audio buffers
+ for ( i = 0 ; i < 4; i ++ )
+ free( audio_buffers[ i ] );
+ }
+}
+
+/** The libdv output method.
+*/
+
+static void consumer_output( mlt_consumer this, uint8_t *dv_frame, int size, mlt_frame frame )
+{
+ fwrite( dv_frame, size, 1, stdout );
+ fflush( stdout );
+}
+
+/** The main thread - the argument is simply the consumer.
+*/
+
+static void *consumer_thread( void *arg )
+{
+ // Map the argument to the object
+ mlt_consumer this = arg;
+
+ // Get the properties
+ mlt_properties properties = mlt_consumer_properties( this );
+
+ // 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 );
+ int ( *output )( mlt_consumer, uint8_t *, int, mlt_frame ) = mlt_properties_get_data( properties, "output", NULL );
+
+ // Allocate a single PAL frame for encoding
+ uint8_t *dv_frame = malloc( frame_size_625_50 );
+
+ // Get the service associated to the consumer
+ mlt_service service = mlt_consumer_service( this );
+
+ // Define a frame pointer
+ mlt_frame frame;
+
+ // Loop while running
+ while( mlt_properties_get_int( properties, "running" ) )
+ {
+ // Get the frame
+ if ( mlt_service_get_frame( service, &frame, 0 ) == 0 )
+ {
+ // Encode the image
+ int size = video( this, dv_frame, frame );
+
+ // Encode the audio
+ if ( size > 0 )
+ audio( this, dv_frame, frame );
+
+ // Output the frame
+ output( this, dv_frame, size, frame );
+
+ // Close the frame
+ mlt_frame_close( frame );
+ }
+ }
+
+ // Tidy up
+ free( dv_frame );
+
+ return NULL;
+}
+
+/** Close the consumer.
+*/
+
+static void consumer_close( mlt_consumer this )
+{
+ // Get the properties
+ mlt_properties properties = mlt_consumer_properties( this );
+
+ // Get the thread
+ pthread_t *thread = mlt_properties_get_data( properties, "thread", NULL );
+
+ // Stop the thread
+ mlt_properties_set_int( properties, "running", 0 );
+
+ // Wait for termination
+ pthread_join( *thread, NULL );
+
+ // Close the parent
+ mlt_consumer_close( this );
+
+ // Free the memory
+ free( this );
+}
+
--- /dev/null
+/*
+ * producer_libdv.h -- a DV encoder based on libdv
+ * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Author: Charles Yates <charles.yates@pandora.be>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CONSUMER_LIBDV_H_
+#define _CONSUMER_LIBDV_H_
+
+#include <framework/mlt_consumer.h>
+
+extern mlt_consumer consumer_libdv_init( char *filename );
+
+#endif
#include <string.h>
#include "producer_libdv.h"
+#include "consumer_libdv.h"
void *mlt_create_producer( char *id, void *arg )
{
void *mlt_create_consumer( char *id, void *arg )
{
+ if ( !strcmp( id, "libdv" ) )
+ return consumer_libdv_init( arg );
return NULL;
}
// Calculate default in/out points
double fps = this->is_pal ? 25 : 30000.0 / 1001.0;
- mlt_timecode length = ( mlt_timecode )( this->frames_in_file ) / fps;
mlt_properties_set_double( properties, "fps", fps );
- mlt_properties_set_timecode( properties, "length", length );
- mlt_properties_set_timecode( properties, "in", 0.0 );
- mlt_properties_set_timecode( properties, "out", ( mlt_timecode )( this->frames_in_file - 1 ) / fps );
+ mlt_properties_set_position( properties, "length", this->frames_in_file );
+ mlt_properties_set_position( properties, "in", 0 );
+ mlt_properties_set_position( properties, "out", this->frames_in_file - 1 );
// Parse the header for meta info
dv_parse_header( this->dv_decoder, dv_data );
}
// Update timecode on the frame we're creating
- mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) );
+ mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
// Calculate the next timecode
mlt_producer_prepare_next( producer );
if ( !mlt_properties_get_int( producer_properties, "end_of_clip" ) )
{
// Get the position
- double position = mlt_properties_get_double( producer_properties, "dub_position" );
+ mlt_position position = mlt_properties_get_position( producer_properties, "dub_position" );
// We need a frame from the producer
mlt_frame producer_frame;
mlt_properties_set_double( producer_properties, "fps", mlt_properties_get_double( frame_properties, "fps" ) );
// Seek to the position
- mlt_producer_seek_frame( producer, ( int64_t )position );
+ mlt_producer_seek( producer, position );
// Get the next frame
producer->get_frame( producer, &producer_frame, 0 );
mlt_properties_set_data( frame_properties, "ffmpeg_dub_frame", producer_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
// Incrment the position
- mlt_properties_set_double( producer_properties, "dub_position", position + 1 );
+ mlt_properties_set_position( producer_properties, "dub_position", position + 1 );
}
}
mlt_properties_set_data( properties, "producer", producer, 0, ( mlt_destructor )mlt_producer_close, NULL );
// Initialise the audio frame position
- mlt_properties_set_double( properties, "dub_position", 0 );
+ mlt_properties_set_position( properties, "dub_position", 0 );
return this;
}
return 0;
}
-FILE *producer_ffmpeg_run_video( producer_ffmpeg this, mlt_timecode position )
+FILE *producer_ffmpeg_run_video( producer_ffmpeg this, mlt_position position )
{
if ( this->video == NULL )
{
return this->video;
}
-FILE *producer_ffmpeg_run_audio( producer_ffmpeg this, mlt_timecode position )
+FILE *producer_ffmpeg_run_audio( producer_ffmpeg this, mlt_position position )
{
// Get the producer
mlt_producer producer = &this->parent;
if ( this->end_of_video && this->end_of_audio )
{
mlt_properties_set_int( properties, "end_of_clip", 1 );
- mlt_properties_set_timecode( producer_properties, "length", mlt_producer_position( &this->parent ) );
+ mlt_properties_set_position( producer_properties, "length", mlt_producer_position( &this->parent ) );
mlt_producer_set_in_and_out( &this->parent, mlt_producer_get_in( &this->parent ), mlt_producer_position( &this->parent ) );
}
// Update timecode on the frame we're creating
- mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) );
+ mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
// Calculate the next timecode
mlt_producer_prepare_next( producer );
}
// Update timecode on the frame we're creating
- mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) );
+ mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
// Calculate the next timecode
mlt_producer_prepare_next( producer );
gap ++;
}
}
- mlt_properties_set_timecode( properties, "out", this->count );
+ mlt_properties_set_position( properties, "out", this->count * 25 );
}
else if ( strstr( filename, "/.all." ) != NULL )
{
free( de[ i ] );
}
- mlt_properties_set_timecode( properties, "out", this->count );
+ mlt_properties_set_position( properties, "out", this->count * 25 );
free( de );
free( dir_name );
}
{
this->filenames = realloc( this->filenames, sizeof( char * ) * ( this->count + 1 ) );
this->filenames[ this->count ++ ] = strdup( filename );
- mlt_properties_set_timecode( properties, "out", 1 );
+ mlt_properties_set_position( properties, "out", 25 );
}
// Initialise gobject types
int image_idx = ( int )floor( mlt_producer_position( producer ) / ttl ) % this->count;
// Update timecode on the frame we're creating
- mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) );
+ mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
// optimization for subsequent iterations on single picture
if ( this->image != NULL && image_idx == this->image_idx )
mlt_multitrack_connect( multitrack, mlt_playlist_producer( playlist ), track );
}
- mlt_properties props = mlt_multitrack_properties( multitrack );
+ mlt_tractor tractor = mlt_field_tractor( field );
+ mlt_producer prod = mlt_tractor_producer( tractor );
+ mlt_properties props = mlt_tractor_properties( tractor );
+ mlt_properties_set_data( props, "multitrack", multitrack, 0, NULL, NULL );
mlt_properties_set_data( props, "field", field, 0, NULL, NULL );
mlt_properties_set_data( props, "group", group, 0, NULL, NULL );
+ mlt_producer_set_in_and_out( prod, 0, mlt_producer_get_out( mlt_multitrack_producer( multitrack ) ) );
+ mlt_properties_set_double( props, "fps", mlt_producer_get_fps( mlt_multitrack_producer( multitrack ) ) );
- return mlt_multitrack_producer( multitrack );
+ return mlt_tractor_producer( tractor );
}
pthread_mutex_destroy( &this->audio_mutex );
pthread_cond_destroy( &this->audio_cond );
- // Now clean up the rest (the close = NULL is a bit nasty but needed for now)
- parent->close = NULL;
+ // Now clean up the rest
mlt_consumer_close( parent );
// Finally clean up this