#include <stdlib.h>
#include <sys/time.h>
+/** Define this if you want an automatic deinterlace (if necessary) when the
+ * consumer's producer is not running at normal speed.
+ */
#undef DEINTERLACE_ON_NOT_NORMAL_SPEED
static void mlt_consumer_frame_render( mlt_listener listener, mlt_properties owner, mlt_service this, void **args );
static void mlt_consumer_property_changed( mlt_service owner, mlt_consumer this, char *name );
static void apply_profile_properties( mlt_consumer this, mlt_profile profile, mlt_properties properties );
+/** Initialize a consumer service.
+ *
+ * \public \memberof mlt_consumer_s
+ * \param this the consumer to initialize
+ * \param child a pointer to the object for the subclass
+ * \param profile the \p mlt_profile_s to use (optional but recommended,
+ * uses the environment variable MLT if this is NULL)
+ * \return true if there was an error
+ */
+
int mlt_consumer_init( mlt_consumer this, void *child, mlt_profile profile )
{
int error = 0;
return error;
}
+/** Convert the profile into properties on the consumer.
+ *
+ * \private \memberof mlt_consumer_s
+ * \param this a consumer
+ * \param profile a profile
+ * \param properties a properties list (typically, the consumer's)
+ */
+
static void apply_profile_properties( mlt_consumer this, mlt_profile profile, mlt_properties properties )
{
mlt_event_block( this->event_listener );
mlt_event_unblock( this->event_listener );
}
+/** The property-changed event listener
+ *
+ * \private \memberof mlt_consumer_s
+ * \param owner the service a service (ignored)
+ * \param this the consumer
+ * \param name the name of the property that changed
+ */
+
static void mlt_consumer_property_changed( mlt_service owner, mlt_consumer this, char *name )
{
if ( !strcmp( name, "profile" ) )
}
}
+/** The transmitter for the consumer-frame-show event
+ *
+ * Invokes the listener.
+ *
+ * \private \memberof mlt_consumer_s
+ * \param listener a function pointer that will be invoked
+ * \param owner a properties list that will be passed to \p listener
+ * \param this a service that will be passed to \p listener
+ * \param args an array of pointers - the first entry is passed as a string to \p listener
+ */
+
static void mlt_consumer_frame_show( mlt_listener listener, mlt_properties owner, mlt_service this, void **args )
{
if ( listener != NULL )
listener( owner, this, ( mlt_frame )args[ 0 ] );
}
+/** The transmitter for the consumer-frame-render event
+ *
+ * Invokes the listener.
+ *
+ * \private \memberof mlt_consumer_s
+ * \param listener a function pointer that will be invoked
+ * \param owner a properties list that will be passed to \p listener
+ * \param this a service that will be passed to \p listener
+ * \param args an array of pointers - the first entry is passed as a string to \p listener
+ */
+
static void mlt_consumer_frame_render( mlt_listener listener, mlt_properties owner, mlt_service this, void **args )
{
if ( listener != NULL )
}
/** Create a new consumer.
-*/
+ *
+ * \public \memberof mlt_consumer_s
+ * \param profile a profile (optional, but recommended)
+ * \return a new consumer
+ */
mlt_consumer mlt_consumer_new( mlt_profile profile )
{
}
/** Get the parent service object.
-*/
+ *
+ * \public \memberof mlt_consumer_s
+ * \param this a consumer
+ * \return the parent service class
+ * \see MLT_CONSUMER_SERVICE
+ */
mlt_service mlt_consumer_service( mlt_consumer this )
{
}
/** Get the consumer properties.
-*/
+ *
+ * \public \memberof mlt_consumer_s
+ * \param this a consumer
+ * \return the consumer's properties list
+ * \see MLT_CONSUMER_PROPERTIES
+ */
mlt_properties mlt_consumer_properties( mlt_consumer this )
{
}
/** Connect the consumer to the producer.
-*/
+ *
+ * \public \memberof mlt_consumer_s
+ * \param this a consumer
+ * \param producer a producer
+ * \return > 0 warning, == 0 success, < 0 serious error,
+ * 1 = this service does not accept input,
+ * 2 = the producer is invalid,
+ * 3 = the producer is already registered with this consumer
+ */
int mlt_consumer_connect( mlt_consumer this, mlt_service producer )
{
}
/** Start the consumer.
-*/
+ *
+ * \public \memberof mlt_consumer_s
+ * \param this a consumer
+ * \return true if there was an error
+ */
int mlt_consumer_start( mlt_consumer this )
{
return 0;
}
-/** An alternative method to feed frames into the consumer - only valid if
- the consumer itself is not connected.
-*/
+/** An alternative method to feed frames into the consumer.
+ *
+ * Only valid if the consumer itself is not connected.
+ *
+ * \public \memberof mlt_consumer_s
+ * \param this a consumer
+ * \param frame a frame
+ * \return true (ignore this for now)
+ */
int mlt_consumer_put_frame( mlt_consumer this, mlt_frame frame )
{
}
/** Protected method for consumer to get frames from connected service
-*/
+ *
+ * \public \memberof mlt_consumer_s
+ * \param this a consumer
+ * \return a frame
+ */
mlt_frame mlt_consumer_get_frame( mlt_consumer this )
{
return frame;
}
+/** Compute the time difference between now and a time value.
+ *
+ * \private \memberof mlt_consumer_s
+ * \param time1 a time value to be compared against now
+ * \return the difference in microseconds
+ */
+
static inline long time_difference( struct timeval *time1 )
{
struct timeval time2;
return time1->tv_sec * 1000000 + time1->tv_usec - time2.tv_sec * 1000000 - time2.tv_usec;
}
+/** The thread procedure for asynchronously pulling frames through the service
+ * network connected to a consumer.
+ *
+ * \private \memberof mlt_consumer_s
+ * \param arg a consumer
+ */
+
static void *consumer_read_ahead_thread( void *arg )
{
// The argument is the consumer
return NULL;
}
+/** Start the read/render thread.
+ *
+ * \private \memberof mlt_consumer_s
+ * \param this a consumer
+ */
+
static void consumer_read_ahead_start( mlt_consumer this )
{
// We're running now
}
}
+/** Stop the read/render thread.
+ *
+ * \private \memberof mlt_consumer_s
+ * \param this a consumer
+ */
+
static void consumer_read_ahead_stop( mlt_consumer this )
{
// Make sure we're running
}
}
+/** Flush the read/render thread's buffer.
+ *
+ * \public \memberof mlt_consumer_s
+ * \param this a consumer
+ */
+
void mlt_consumer_purge( mlt_consumer this )
{
if ( this->ahead )
}
}
+/** Get the next frame from the producer connected to a consumer.
+ *
+ * Typically, one uses this instead of \p mlt_consumer_get_frame to make
+ * the asynchronous/real-time behavior configurable at runtime.
+ * You should close the frame returned from this when you are done with it.
+ *
+ * \public \memberof mlt_consumer_s
+ * \param this a consumer
+ * \return a frame
+ */
+
mlt_frame mlt_consumer_rt_frame( mlt_consumer this )
{
// Frame to return
}
/** Callback for the implementation to indicate a stopped condition.
-*/
+ *
+ * \public \memberof mlt_consumer_s
+ * \param this a consumer
+ */
void mlt_consumer_stopped( mlt_consumer this )
{
}
/** Stop the consumer.
-*/
+ *
+ * \public \memberof mlt_consumer_s
+ * \param this a consumer
+ * \return true if there was an error
+ */
int mlt_consumer_stop( mlt_consumer this )
{
}
/** Determine if the consumer is stopped.
-*/
+ *
+ * \public \memberof mlt_consumer_s
+ * \param this a consumer
+ * \return true if the consumer is stopped
+ */
int mlt_consumer_is_stopped( mlt_consumer this )
{
return 0;
}
-/** Close the consumer.
-*/
+/** Close and destroy the consumer.
+ *
+ * \public \memberof mlt_consumer_s
+ * \param this a consumer
+ */
void mlt_consumer_close( mlt_consumer this )
{
#include <pthread.h>
/** \brief Consumer abstract service class
+ *
+ * A consumer is a service that pulls audio and video from the connected
+ * producers, filters, and transitions. Typically a consumer is used to
+ * output audio and/or video to a device, file, or socket.
*
* \extends mlt_service_s
+ * \properties \em rescale the scaling algorithm to pass on to all scaling
+ * filters, defaults to "bilinear"
+ * \properties \em buffer the number of frames to use in the asynchronous
+ * render thread, defaults to 25
+ * \properties \em frequency the audio sample rate to use in Hertz, defaults to 48000
+ * \properties \em channels the number of audio channels to use, defaults to 2
+ * \properties \em real_time the asynchronous behavior: 1 (default) for asynchronous
+ * with frame dropping, -1 for asynchronous without frame dropping, 0 to disable (synchronous)
+ * \properties \em test_card the name of a resource to use as the test card, defaults to
+ * environment variable MLT_TEST_CARD. If undefined, the hard-coded default test card is
+ * white silence. A test card is what appears when nothing is produced.
+ * \event \em consumer-frame-show Subclass implementations should fire this.
+ * \event \em consumer-frame-render The abstract class fires this.
+ * \event \em consumer-stopped
+ * \properties \em fps video frames per second as floating point (read only)
+ * \properties \em frame_rate_num the numerator of the video frame rate, overrides \p mlt_profile_s
+ * \properties \em frame_rate_den the denominator of the video frame rate, overrides \p mlt_profile_s
+ * \properties \em width the horizontal video resolution, overrides \p mlt_profile_s
+ * \properties \em height the vertical video resolution, overrides \p mlt_profile_s
+ * \properties \em progressive a flag that indicates if the video is interlaced
+ * or progressive, overrides \p mlt_profile_s
+ * \properties \em aspect_ratio the video sample (pixel) aspect ratio as floating point (read only)
+ * \properties \em sample_aspect_num the numerator of the sample aspect ratio, overrides \p mlt_profile_s
+ * \properties \em sample_aspect_den the denominator of the sample aspect ratio, overrides \p mlt_profile_s
+ * \properties \em display_ratio the video frame aspect ratio as floating point (read only)
+ * \properties \em display_aspect_num the numerator of the video frame aspect ratio, overrides \p mlt_profile_s
+ * \properties \em display_aspect_den the denominator of the video frame aspect ratio, overrides \p mlt_profile_s
+ *
*/
struct mlt_consumer_s
{
- /* We're implementing service here */
+ /** A consumer is a service. */
struct mlt_service_s parent;
- /* public virtual */
+ /** Start the consumer to pull frames (virtual function).
+ *
+ * \param mlt_consumer a consumer
+ * \return true if there was an error
+ */
int ( *start )( mlt_consumer );
+
+ /** Stop the consumer (virtual function).
+ *
+ * \param mlt_consumer a consumer
+ * \return true if there was an error
+ */
int ( *stop )( mlt_consumer );
+
+ /** Get whether the consumer is running or stopped (virtual function).
+ *
+ * \param mlt_consumer a consumer
+ * \return true if the consumer is stopped
+ */
int ( *is_stopped )( mlt_consumer );
+
+ /** The destructor virtual function
+ *
+ * \param mlt_consumer a consumer
+ */
void ( *close )( mlt_consumer );
- /* Private data */
- void *local;
- void *child;
+ void *local; /**< \private instance object */
+ void *child; /**< \private the object of a subclass */
int real_time;
int ahead;
static int filter_get_frame( mlt_service this, mlt_frame_ptr frame, int index );
-/** Constructor method.
-*/
+/** Initialize a new filter.
+ *
+ * \public \memberof mlt_filter_s
+ * \param this a filter
+ * \param child the object of a subclass
+ * \return true if there was an error
+ */
int mlt_filter_init( mlt_filter this, void *child )
{
return 1;
}
-/** Create a new filter.
-*/
+/** Create a new filter and initialize it.
+ *
+ * \public \memberof mlt_filter_s
+ * \return a new filter
+ */
mlt_filter mlt_filter_new( )
{
return this;
}
-/** Get the service associated to this filter
-*/
+/** Get the service class interface.
+ *
+ * \public \memberof mlt_filter_s
+ * \param this a filter
+ * \return the service parent class
+ * \see MLT_FILTER_SERVICE
+ */
mlt_service mlt_filter_service( mlt_filter this )
{
return this != NULL ? &this->parent : NULL;
}
-/** Get the properties associated to this filter.
-*/
+/** Get the filter properties.
+ *
+ * \public \memberof mlt_filter_s
+ * \param this a filter
+ * \return the properties list for the filter
+ * \see MLT_FILTER_PROPERTIES
+ */
mlt_properties mlt_filter_properties( mlt_filter this )
{
}
/** Connect this filter to a producers track. Note that a filter only operates
- on a single track, and by default it operates on the entirety of that track.
-*/
+ * on a single track, and by default it operates on the entirety of that track.
+ *
+ * \public \memberof mlt_filter_s
+ * \param this a filter
+ * \param producer the producer to which to connect this filter
+ * \param index which of potentially multiple producers to this service (0 based)
+ */
int mlt_filter_connect( mlt_filter this, mlt_service producer, int index )
{
int ret = mlt_service_connect_producer( &this->parent, producer, index );
-
+
// If the connection was successful, grab the producer, track and reset in/out
if ( ret == 0 )
{
mlt_properties_set_position( properties, "out", 0 );
mlt_properties_set_int( properties, "track", index );
}
-
+
return ret;
}
-/** Tune the in/out points.
-*/
+/** Set the starting and ending time.
+ *
+ * \public \memberof mlt_filter_s
+ * \param this a filter
+ * \param in the time relative to the producer at which start applying the filter
+ * \param out the time relative to the producer at which to stop applying the filter
+ */
+
void mlt_filter_set_in_and_out( mlt_filter this, mlt_position in, mlt_position out )
{
}
/** Return the track that this filter is operating on.
-*/
+ *
+ * \public \memberof mlt_filter_s
+ * \param this a filter
+ * \return true on error
+ */
+
int mlt_filter_get_track( mlt_filter this )
{
}
/** Get the in point.
-*/
+ *
+ * \public \memberof mlt_filter_s
+ * \param this a filter
+ * \return the start time for the filter relative to the producer
+ */
+
mlt_position mlt_filter_get_in( mlt_filter this )
{
}
/** Get the out point.
-*/
+ *
+ * \public \memberof mlt_filter_s
+ * \param this a filter
+ * \return the ending time for the filter relative to the producer
+ */
+
mlt_position mlt_filter_get_out( mlt_filter this )
{
}
/** Process the frame.
-*/
+ *
+ * \public \memberof mlt_filter_s
+ * \param this a filter
+ * \param frame a frame
+ * \return a frame
+ */
+
mlt_frame mlt_filter_process( mlt_filter this, mlt_frame frame )
{
}
/** Get a frame from this filter.
-*/
+ *
+ * \private \memberof mlt_filter_s
+ * \param service a service
+ * \param[out] frame a frame by reference
+ * \param index as determined by the producer
+ * \return true on error
+ */
+
static int filter_get_frame( mlt_service service, mlt_frame_ptr frame, int index )
{
int track = mlt_filter_get_track( this );
int in = mlt_filter_get_in( this );
int out = mlt_filter_get_out( this );
-
+
// Get the producer this is connected to
mlt_service producer = mlt_service_producer( &this->parent );
}
}
-/** Close the filter.
-*/
+/** Close and destroy the filter.
+ *
+ * \public \memberof mlt_filter_s
+ * \param this a filter
+ */
+
void mlt_filter_close( mlt_filter this )
{
#include "mlt_service.h"
/** \brief Filter abstract service class
+ *
+ * A filter is a service that may modify the output of a single producer.
*
* \extends mlt_service_s
+ * \properties \em track the index of the track of a multitrack on which the filter is applied
*/
struct mlt_filter_s
{
- /* We're implementing service here */
+ /** We're implementing service here */
struct mlt_service_s parent;
- /* public virtual */
+ /** public virtual */
void ( *close )( mlt_filter );
- /* protected filter method */
+ /** protected filter method */
mlt_frame ( *process )( mlt_filter, mlt_frame );
- /* Protected */
+ /** Protected */
void *child;
};
-/** Public final methods
-*/
-
#define MLT_FILTER_SERVICE( filter ) ( &( filter )->parent )
#define MLT_FILTER_PROPERTIES( filter ) MLT_SERVICE_PROPERTIES( MLT_FILTER_SERVICE( filter ) )
* \properties \em _producer holds a reference to the frame's end producer
* \properties \em _speed
* \properties \em meta.* holds metadata
+ * \properties \em hide set to 1 to hide the video, 2 to mute the audio
+ * \properties \em last_track a flag to indicate an end-of-tracks frame
*/
struct mlt_frame_s
#include <stdio.h>
#include <stdlib.h>
-/** Forward reference.
-*/
+/* Forward reference. */
static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int index );
-/** Constructor.
+/** Construct and initialize a new multitrack.
*/
mlt_multitrack mlt_multitrack_init( )
typedef struct mlt_track_s *mlt_track;
/** \brief Multitrack class
+ *
+ * A multitrack is a parallel container of producers that acts a single producer.
*
* \extends mlt_producer_s
*/
* \param this the producer structure to initialize
* \param child a pointer to the child object for the subclass
* \return true if there was an error
- * \todo Document the special properties and events.
*/
int mlt_producer_init( mlt_producer this, void *child )
return error;
}
-/** The listener for property changes.
+/** The transmitter for property changes.
+ *
+ * Invokes the listener.
*
* \private \memberof mlt_service_s
* \param listener a function pointer that will be invoked
mlt_service_base *base = this->local;
mlt_position position = mlt_frame_get_position( frame );
mlt_position this_in = mlt_properties_get_position( service_properties, "in" );
- /** \properties \em out where to stop playing */
mlt_position this_out = mlt_properties_get_position( service_properties, "out" );
if ( index == 0 || mlt_properties_get_int( service_properties, "_filter_private" ) == 0 )
* \event \em property-changed
* \properties \em mlt_type identifies the subclass
* \properties \em resource is either the stream identifier or grandchild-class
- * \properties \em in where to start playing
+ * \properties \em in when to start, what is started is service-specific
+ * \properties \em out when to stop
* \properties \em _filter_private Set this on a service to ensure that attached filters are handled privately.
* See modules/core/filter_region.c and modules/core/filter_watermark.c for examples.
* \properties \em disable Set this on a filter to disable it while keeping it in the object model.
#include <stdlib.h>
#include <string.h>
-/** Forward references.
-*/
+/* Forward references */
static int transition_get_frame( mlt_service this, mlt_frame_ptr frame, int index );
-/** Constructor.
-*/
+/** Initialize a new transition.
+ *
+ * \public \memberof mlt_transition_s
+ * \param this a transition
+ * \param child the object of a subclass
+ * \return true on error
+ */
int mlt_transition_init( mlt_transition this, void *child )
{
return 1;
}
-/** Create a new transition.
-*/
+/** Create and initialize a new transition.
+ *
+ * \public \memberof mlt_transition_s
+ * \return a new transition
+ */
mlt_transition mlt_transition_new( )
{
return this;
}
-/** Get the service associated to the transition.
-*/
+/** Get the service class interface.
+ *
+ * \public \memberof mlt_transition_s
+ * \param this a transition
+ * \return the service class
+ * \see MLT_TRANSITION_SERVICE
+ */
mlt_service mlt_transition_service( mlt_transition this )
{
}
/** Get the properties interface.
-*/
+ *
+ * \public \memberof mlt_transition_s
+ * \param this a transition
+ * \return the transition's properties
+ * \see MLT_TRANSITION_PROPERTIES
+ */
mlt_properties mlt_transition_properties( mlt_transition this )
{
}
/** Connect this transition with a producers a and b tracks.
-*/
+ *
+ * \public \memberof mlt_transition_s
+ * \param this a transition
+ * \param producer a producer
+ * \param a_track the track index of the first input
+ * \param b_track the track index of the second index
+ * \return true on error
+ */
int mlt_transition_connect( mlt_transition this, mlt_service producer, int a_track, int b_track )
{
return ret;
}
-/** Set the in and out points.
-*/
+/** Set the starting and ending time for when the transition is active.
+ *
+ * \public \memberof mlt_transition_s
+ * \param this a transition
+ * \param in the starting time
+ * \param out the ending time
+ */
void mlt_transition_set_in_and_out( mlt_transition this, mlt_position in, mlt_position out )
{
}
/** Get the index of the a track.
-*/
+ *
+ * \public \memberof mlt_transition_s
+ * \param this a transition
+ * \return the 0-based index of the track of the first producer
+ */
int mlt_transition_get_a_track( mlt_transition this )
{
}
/** Get the index of the b track.
-*/
+ *
+ * \public \memberof mlt_transition_s
+ * \param this a transition
+ * \return the 0-based index of the track of the second producer
+ */
int mlt_transition_get_b_track( mlt_transition this )
{
}
/** Get the in point.
-*/
+ *
+ * \public \memberof mlt_transition_s
+ * \param this a transition
+ * \return the starting time
+ */
mlt_position mlt_transition_get_in( mlt_transition this )
{
}
/** Get the out point.
-*/
+ *
+ * \public \memberof mlt_transition_s
+ * \param this a transition
+ * \return the ending time
+ */
mlt_position mlt_transition_get_out( mlt_transition this )
{
}
/** Process the frame.
-
- If we have no process method (unlikely), we simply return the a_frame unmolested.
-*/
+ *
+ * If we have no process method (unlikely), we simply return the a_frame unmolested.
+ *
+ * \public \memberof mlt_transition_s
+ * \param this a transition
+ * \param a_frame a frame from the first producer
+ * \param b_frame a frame from the second producer
+ * \return a frame
+ */
mlt_frame mlt_transition_process( mlt_transition this, mlt_frame a_frame, mlt_frame b_frame )
{
for the transition type (this is either audio or image).
However, the fixed a_track may not always contain data of the correct type, eg:
-
+<pre>
+---------+ +-------+
|c1 | |c5 | <-- A(0,1) <-- B(0,2) <-- get frame
+---------+ +---------+-+-----+ | |
+----------+-----------+-+---------+ |
|c2 |c3 | <-----------------+
+----------+-------------+
-
+</pre>
During the overlap of c1 and c2, there is nothing for the A transition to do, so this
results in a no operation, but B is triggered. During the overlap of c2 and c3, again,
the A transition is inactive and because the B transition is pointing at track 0,
This method is invoked for each track and we return the cached frames as needed.
We clear the cache only when the requested frame is flagged as a 'last_track' frame.
-*/
+
+ * \private \memberof mlt_transition_s
+ * \param service a service
+ * \param[out] frame a frame by reference
+ * \param index 0-based track index
+ * \return true on error
+ */
static int transition_get_frame( mlt_service service, mlt_frame_ptr frame, int index )
{
return error;
}
-/** Close the transition.
-*/
+/** Close and destroy the transition.
+ *
+ * \public \memberof mlt_transition_s
+ * \param this a transition
+ */
void mlt_transition_close( mlt_transition this )
{
#include "mlt_service.h"
/** \brief Transition abstract service class
+ *
+ * A transition may modify the output of a producer based on the output of a second producer.
*
* \extends mlt_service_s
+ * \properties \em a_track the track index (0-based) of a multitrack of the first producer
+ * \properties \em b_track the track index (0-based) of a multitrack of the second producer
+ * \properties \em accepts_blanks a flag to indicate if the transition should accept blank frames
+ * \properties \em always_active a flag to indicate that the in and out points do not apply
+ * \properties \em _transition_type 1 for video, 2 for audio
*/
struct mlt_transition_s
{
- /* We're implementing service here */
+ /** We're implementing service here */
struct mlt_service_s parent;
- /* public virtual */
+ /** public virtual */
void ( *close )( mlt_transition );
- /* protected transition method */
+ /** protected transition method */
mlt_frame ( *process )( mlt_transition, mlt_frame, mlt_frame );
- /* Protected */
+ /** Protected */
void *child;
- /* track and in/out points */
+ /** track and in/out points */
mlt_service producer;
- /* Private */
+ /** Private */
mlt_frame *frames;
int held;
};
-/** Public final methods
-*/
-
#define MLT_TRANSITION_SERVICE( transition ) ( &( transition )->parent )
#define MLT_TRANSITION_PROPERTIES( transition ) MLT_SERVICE_PROPERTIES( MLT_TRANSITION_SERVICE( transition ) )