NLS
USET points=ignore
USET eof=terminate
-XFER
Incorrect Behaviour
#include "config.h"
#include "mlt_consumer.h"
+#include "mlt_factory.h"
+#include "mlt_producer.h"
+#include "mlt_frame.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int mlt_consumer_init( mlt_consumer this, void *child )
{
+ int error = 0;
memset( this, 0, sizeof( struct mlt_consumer_s ) );
this->child = child;
- return mlt_service_init( &this->parent, this );
+ error = mlt_service_init( &this->parent, this );
+ if ( error == 0 )
+ {
+ // Get the properties from the service
+ mlt_properties properties = mlt_service_properties( &this->parent );
+
+ // Get the normalisation preference
+ char *normalisation = getenv( "MLT_NORMALISATION" );
+
+ // Deal with normalisation
+ if ( normalisation == NULL || strcmp( normalisation, "NTSC" ) )
+ {
+ mlt_properties_set( properties, "normalisation", "PAL" );
+ mlt_properties_set_double( properties, "fps", 25.0 );
+ mlt_properties_set_int( properties, "width", 720 );
+ mlt_properties_set_int( properties, "height", 576 );
+ }
+ else
+ {
+ mlt_properties_set( properties, "normalisation", "NTSC" );
+ mlt_properties_set_double( properties, "fps", 30000.0 / 1001.0 );
+ mlt_properties_set_int( properties, "width", 720 );
+ mlt_properties_set_int( properties, "height", 480 );
+ }
+
+ // Default rescaler for all consumers
+ mlt_properties_set( properties, "rescale", "bilinear" );
+ }
+ return error;
}
/** Get the parent service object.
int mlt_consumer_start( mlt_consumer this )
{
+ // Get the properies
+ mlt_properties properties = mlt_consumer_properties( this );
+
+ // Determine if there's a test card producer
+ char *test_card = mlt_properties_get( properties, "test_card" );
+
+ // Deal with it now.
+ if ( test_card != NULL )
+ {
+ // Create a test card producer
+ mlt_producer producer = mlt_factory_producer( "fezzik", test_card );
+
+ // Do we have a producer
+ if ( producer != NULL )
+ {
+ // Set the test card on the consumer
+ mlt_properties_set_data( properties, "test_card_producer", producer, 0, ( mlt_destructor )mlt_producer_close, NULL );
+ }
+ }
+
+ // Start the service
if ( this->start != NULL )
return this->start( this );
+
return 0;
}
+/** Protected method :-/ for consumer to get frames from connected service
+*/
+
+mlt_frame mlt_consumer_get_frame( mlt_consumer this )
+{
+ // Frame to return
+ mlt_frame frame = NULL;
+
+ // Get the service assoicated to the consumer
+ mlt_service service = mlt_consumer_service( this );
+
+ // Get the frame
+ if ( mlt_service_get_frame( service, &frame, 0 ) == 0 )
+ {
+ // Get the consumer properties
+ mlt_properties properties = mlt_consumer_properties( this );
+
+ // Get the frame properties
+ mlt_properties frame_properties = mlt_frame_properties( frame );
+
+ // Attach the test frame producer to it.
+ mlt_producer test_card = mlt_properties_get_data( properties, "test_card_producer", NULL );
+ mlt_properties_set_data( frame_properties, "test_card_producer", test_card, 0, NULL, NULL );
+
+ // Attach the rescale property
+ if ( mlt_properties_get( properties, "rescale" ) != NULL )
+ mlt_properties_set( frame_properties, "rescale.interp", mlt_properties_get( properties, "rescale" ) );
+
+ // TODO: Aspect ratio and other jiggery pokery
+ }
+
+ // Return the frame
+ return frame;
+}
+
/** Stop the consumer.
*/
int mlt_consumer_is_stopped( mlt_consumer this )
{
+ // Get the properies
+ mlt_properties properties = mlt_consumer_properties( this );
+
+ // Stop the consumer
if ( this->is_stopped != NULL )
return this->is_stopped( this );
+
+ // Kill the test card
+ mlt_properties_set_data( properties, "test_card_producer", NULL, 0, NULL, NULL );
+
return 0;
}
extern mlt_properties mlt_consumer_properties( mlt_consumer this );
extern int mlt_consumer_connect( mlt_consumer this, mlt_service producer );
extern int mlt_consumer_start( mlt_consumer this );
+extern mlt_frame mlt_consumer_get_frame( mlt_consumer this );
extern int mlt_consumer_stop( mlt_consumer this );
extern int mlt_consumer_is_stopped( mlt_consumer this );
extern void mlt_consumer_close( mlt_consumer );
#include "config.h"
#include "mlt_frame.h"
+#include "mlt_producer.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
{
mlt_properties properties = mlt_frame_properties( this );
mlt_get_image get_image = mlt_frame_pop_get_image( this );
+ mlt_producer producer = mlt_properties_get_data( properties, "test_card_producer", NULL );
if ( get_image != NULL )
{
*width = mlt_properties_get_int( properties, "width" );
*height = mlt_properties_get_int( properties, "height" );
}
+ else if ( producer != NULL )
+ {
+ mlt_frame test_frame = NULL;
+ mlt_service_get_frame( mlt_producer_service( producer ), &test_frame, 0 );
+ if ( test_frame != NULL )
+ {
+ mlt_frame_get_image( test_frame, buffer, format, width, height, writable );
+ mlt_properties_inherit( mlt_frame_properties( this ), mlt_frame_properties( test_frame ) );
+ mlt_properties_set_data( properties, "test_card_frame", test_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
+
+ mlt_properties_set_data( properties, "image", *buffer, *width * *height * 2, NULL, NULL );
+ mlt_properties_set_int( properties, "width", *width );
+ mlt_properties_set_int( properties, "height", *height );
+ }
+ else
+ {
+ mlt_properties_set_data( properties, "test_card_producer", NULL, 0, NULL, NULL );
+ mlt_frame_get_image( this, buffer, format, width, height, writable );
+ }
+ }
else
{
uint8_t *p;
case mlt_image_yuv420p:
size = size * 3 / 2;
*buffer = malloc( size );
- if ( *buffer )
+ if ( *buffer )
memset( *buffer, 255, size );
break;
}
// Initialise the service
if ( mlt_service_init( &this->parent, this ) == 0 )
{
+ // Get the normalisation preference
+ char *normalisation = getenv( "MLT_NORMALISATION" );
+
// The parent is the service
mlt_service parent = &this->parent;
mlt_properties_set( properties, "mlt_type", "mlt_producer" );
mlt_properties_set_position( properties, "_position", 0.0 );
mlt_properties_set_double( properties, "_frame", 0 );
- mlt_properties_set_double( properties, "fps", 25.0 );
+ if ( normalisation == NULL || strcmp( normalisation, "NTSC" ) )
+ mlt_properties_set_double( properties, "fps", 25.0 );
+ else
+ mlt_properties_set_double( properties, "fps", 30000.0 / 1001.0 );
mlt_properties_set_double( properties, "_speed", 1.0 );
mlt_properties_set_position( properties, "in", 0 );
mlt_properties_set_position( properties, "out", 1799999 );
// Get the video_index
int index = mlt_properties_get_int( properties, "video_index" );
+ // Get the frame properties
+ mlt_properties frame_properties = mlt_frame_properties( frame );
+
// Lock the mutex now
pthread_mutex_lock( &avformat_mutex );
if ( context != NULL && index != -1 )
{
- // Get the frame properties
- mlt_properties frame_properties = mlt_frame_properties( frame );
-
// Get the video stream
AVStream *stream = context->streams[ index ];
mlt_frame_push_get_image( frame, producer_get_image );
mlt_properties_set_data( frame_properties, "avformat_producer", this, 0, NULL, NULL );
}
+ else
+ {
+ mlt_properties_set_int( frame_properties, "test_image", 1 );
+ }
+ }
+ else
+ {
+ mlt_properties_set_int( frame_properties, "test_image", 1 );
}
// Unlock the mutex now
// Assign close callback
this->close = consumer_close;
- // Interpret the constructor argument
- if ( arg == NULL || !strcmp( arg, "PAL" ) )
- mlt_properties_set_double( properties, "fps", 25 );
- else
- mlt_properties_set_double( properties, "fps", 29.97 );
+ // Interpret the argument
+ if ( arg != NULL )
+ mlt_properties_set( properties, "target", arg );
// Set the encode and output handling method
mlt_properties_set_data( properties, "video", consumer_encode_video, 0, NULL, NULL );
// Wait for termination
pthread_join( *thread, NULL );
+
+ // Close the output file :-) - this is obtuse - doesn't matter if output file
+ // exists or not - the destructor will kick in if it does
+ mlt_properties_set_data( properties, "output_file", NULL, 0, NULL, NULL );
}
return 0;
// 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
uint8_t *image = NULL;
int is_test = 0;
- if ( mlt_properties_get( this_properties, "rescale" ) != NULL )
- mlt_properties_set( mlt_frame_properties( frame ), "rescale.interp", mlt_properties_get( this_properties, "rescale" ) );
-
// Get the image
mlt_frame_get_image( frame, &image, &fmt, &width, &height, 0 );
// 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 )
+ mlt_frame frame = mlt_consumer_get_frame( this );
+
+ // Check that we have a frame to work with
+ if ( frame != NULL )
{
// Obtain the dv_encoder
if ( libdv_get_encoder( this, frame ) != NULL )
// Open the file if specified
this->fd = open( filename, O_RDONLY );
- producer_collect_info( this );
- // Set the resource property (required for all producers)
- mlt_properties_set( properties, "resource", filename );
+ // Collect info
+ if ( this->fd != -1 && producer_collect_info( this ) )
+ {
+ // Set the resource property (required for all producers)
+ mlt_properties_set( properties, "resource", filename );
+ }
+ else
+ {
+ // Reject this file
+ mlt_producer_close( producer );
+ producer = NULL;
+ }
// Return the producer
return producer;
// Calculate default in/out points
double fps = this->is_pal ? 25 : 30000.0 / 1001.0;
- mlt_properties_set_double( properties, "fps", 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 );
+ if ( mlt_properties_get_double( properties, "fps" ) == 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 );
+ }
+ else
+ {
+ valid = 0;
+ }
// Parse the header for meta info
dv_parse_header( this->dv_decoder, dv_data );
//dv_decoder_free( this->dv_decoder );
// Close the file
- if ( this->fd != 0 )
+ if ( this->fd > 0 )
close( this->fd );
// Close the parent
mlt_properties properties = mlt_producer_properties( &this->parent );
// Set the default properties
- mlt_properties_set_int( properties, "video_standard", mlt_video_standard_pal );
mlt_properties_set( properties, "fgcolour", "0xffffffff" );
mlt_properties_set( properties, "bgcolour", "0x00000000" );
mlt_properties_set_int( properties, "align", pango_align_left );
mlt_properties_set( properties, "resource", "pango" );
mlt_properties_set( properties, "markup", "" );
}
- else if ( filename[ 0 ] == '+' )
+ else if ( filename[ 0 ] == '+' || strstr( filename, "/+" ) )
{
- char *markup = strdup( filename + 1 );
+ char *copy = strdup( filename + 1 );
+ char *markup = copy;
+ if ( strstr( markup, "/+" ) )
+ markup = strstr( markup, "/+" ) + 2;
( *strrchr( markup, '.' ) ) = '\0';
while ( strchr( markup, '~' ) )
( *strchr( markup, '~' ) ) = '\n';
mlt_properties_set( properties, "resource", ( char * )filename );
mlt_properties_set( properties, "markup", markup );
- free( markup );
+ free( copy );
}
else
{
// Set the default properties
mlt_properties_set( properties, "resource", filename );
- mlt_properties_set_int( properties, "video_standard", mlt_video_standard_pal );
mlt_properties_set_int( properties, "ttl", 25 );
// Obtain filenames
pthread_mutex_init( &this->audio_mutex, NULL );
pthread_cond_init( &this->audio_cond, NULL);
- // Default fps
- mlt_properties_set_double( this->properties, "fps", 25 );
-
// Default scaler (for now we'll use nearest)
mlt_properties_set( this->properties, "rescale", "nearest" );
// process actual param
- if ( arg == NULL || !strcmp( arg, "PAL" ) )
- {
- this->width = 720;
- this->height = 576;
- }
- else if ( !strcmp( arg, "NTSC" ) )
- {
- this->width = 720;
- this->height = 480;
- mlt_properties_set_double( this->properties, "fps", 29.97 );
- }
- else if ( sscanf( arg, "%dx%d", &this->width, &this->height ) != 2 )
+ if ( arg == NULL || sscanf( arg, "%dx%d", &this->width, &this->height ) != 2 )
{
- this->width = 720;
- this->height = 576;
+ this->width = mlt_properties_get_int( this->properties, "width" );
+ this->height = mlt_properties_get_int( this->properties, "height" );
}
// Default window size and aspect ratio
}
this->queue[ this->count ++ ] = frame;
- if ( mlt_properties_get( properties, "rescale" ) != NULL )
- mlt_properties_set( mlt_frame_properties( frame ), "rescale.interp", mlt_properties_get( properties, "rescale" ) );
-
if ( this->playing )
{
// We're working on the oldest frame now
// Get the consumer
mlt_consumer consumer = &this->parent;
- // Get the service assoicated to the consumer
- mlt_service service = mlt_consumer_service( consumer );
-
- // Define a frame pointer
- mlt_frame frame;
-
// internal intialization
int init_audio = 1;
// Loop until told not to
while( this->running )
{
- // Get a frame from the service (should never return anything other than 0)
- if ( mlt_service_get_frame( service, &frame, 0 ) == 0 )
+ // Get a frame from the attached producer
+ mlt_frame frame = mlt_consumer_get_frame( consumer );
+
+ // Ensure that we have a frame
+ if ( frame != NULL )
{
init_audio = consumer_play_audio( this, frame, init_audio );
consumer_play_video( this, frame );
// If no malloc'd and consumer init ok
if ( this != NULL && mlt_consumer_init( this, NULL ) == 0 )
{
- // We have stuff to clean up, so override the close method
- //parent->close = consumer_close;
-
// Allow thread to be started/stopped
this->start = consumer_start;
this->is_stopped = consumer_is_stopped;