static void foreach_consumer_stop( mlt_consumer consumer ) { mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer ); mlt_consumer nested = NULL; char key[30]; int index = 0; struct timespec tm = { 0, 1000 * 1000 }; do { snprintf( key, sizeof(key), "%d.consumer", index++ ); nested = mlt_properties_get_data( properties, key, NULL ); if ( nested ) { // Let consumer with terminate_on_pause stop on their own if ( mlt_properties_get_int( MLT_CONSUMER_PROPERTIES(nested), "terminate_on_pause" ) ) { // Send additional dummy frame to unlatch nested consumer's threads mlt_consumer_put_frame( nested, mlt_frame_init( MLT_CONSUMER_SERVICE(consumer) ) ); // wait for stop while ( !mlt_consumer_is_stopped( nested ) ) nanosleep( &tm, NULL ); } else { mlt_consumer_stop( nested ); } } } while ( nested ); }
/** Get the image. */ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { int error = 0; mlt_filter filter = (mlt_filter)mlt_frame_pop_service( frame ); private_data* pdata = (private_data*)filter->child; mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame ); if( mlt_properties_get_data( frame_properties, pdata->fft_prop_name, NULL ) ) { // Get the current image *format = mlt_image_rgb24a; error = mlt_frame_get_image( frame, image, format, width, height, 1 ); // Draw the spectrum if( !error ) { QImage qimg( *width, *height, QImage::Format_ARGB32 ); copy_mlt_to_qimage_rgba( *image, &qimg ); draw_spectrum( filter, frame, &qimg ); copy_qimage_to_mlt_rgba( &qimg, *image ); } } else { if ( pdata->preprocess_warned++ == 2 ) { // This filter depends on the consumer processing the audio before // the video. mlt_log_warning( MLT_FILTER_SERVICE(filter), "Audio not preprocessed.\n" ); } mlt_frame_get_image( frame, image, format, width, height, writable ); } return error; }
mlt_cache_item mlt_cache_get( mlt_cache cache, void *object ) { mlt_cache_item result = NULL; pthread_mutex_lock( &cache->mutex ); void **hit = shuffle_get_hit( cache, object ); void **alt = cache->current == cache->A ? cache->B : cache->A; if ( hit ) { // copy the hit to the MRU end alt[ cache->count - 1 ] = *hit; hit = &alt[ cache->count - 1 ]; char key[19]; sprintf( key, "%p", *hit ); result = mlt_properties_get_data( cache->active, key, NULL ); if ( result && result->data ) result->refcount++; mlt_log( NULL, MLT_LOG_DEBUG, "%s: get %d = %p, %p\n", __FUNCTION__, cache->count - 1, *hit, result->data ); // swap the current array cache->current = alt; } pthread_mutex_unlock( &cache->mutex ); return result; }
static int start( mlt_consumer consumer ) { // Check that we're not already running if ( is_stopped( consumer ) ) { mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer ); pthread_t *thread = calloc( 1, sizeof( pthread_t ) ); // Assign the thread to properties with automatic dealloc mlt_properties_set_data( properties, "thread", thread, sizeof( pthread_t ), free, NULL ); // Set the running state mlt_properties_set_int( properties, "running", 1 ); mlt_properties_set_int( properties, "joined", 0 ); // Construct and start nested consumers if ( !mlt_properties_get_data( properties, "0.consumer", NULL ) ) foreach_consumer_init( consumer ); foreach_consumer_start( consumer ); // Create the thread pthread_create( thread, NULL, consumer_thread, consumer ); } return 0; }
static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ){ mlt_frame b_frame = mlt_frame_pop_frame( a_frame ); mlt_transition transition = mlt_frame_pop_service( a_frame ); mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition ); mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame ); mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame ); int invert = mlt_properties_get_int( properties, "invert" ); uint8_t *images[]={NULL,NULL,NULL}; *format = mlt_image_rgb24a; mlt_frame_get_image( a_frame, &images[0], format, width, height, 0 ); mlt_frame_get_image( b_frame, &images[1], format, width, height, 0 ); double position = mlt_transition_get_position( transition, a_frame ); mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( transition ) ); double time = position / mlt_profile_fps( profile ); process_frei0r_item( MLT_TRANSITION_SERVICE(transition), position, time, properties, !invert ? a_frame : b_frame, images, width, height ); *width = mlt_properties_get_int( !invert ? a_props : b_props, "width" ); *height = mlt_properties_get_int( !invert ? a_props : b_props, "height" ); *image = mlt_properties_get_data( !invert ? a_props : b_props , "image", NULL ); return 0; }
static int stop( mlt_consumer consumer ) { // Check that we're running if ( !mlt_properties_get_int( MLT_CONSUMER_PROPERTIES(consumer), "joined" ) ) { mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer ); pthread_t *thread = mlt_properties_get_data( properties, "thread", NULL ); // Stop the thread mlt_properties_set_int( properties, "running", 0 ); // Wait for termination if ( thread ) { foreach_consumer_refresh( consumer ); pthread_join( *thread, NULL ); } mlt_properties_set_int( properties, "joined", 1 ); // Stop nested consumers foreach_consumer_stop( consumer ); } return 0; }
static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable ) { // Obtain properties of frame mlt_properties properties = MLT_FRAME_PROPERTIES( frame ); // Obtain the producer for this frame mlt_producer producer = mlt_properties_get_data( properties, "producer_frei0r", NULL ); // Obtain properties of producer mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer ); // Allocate the image int size = *width * ( *height + 1 ) * 2; // Allocate the image *buffer = mlt_pool_alloc( size ); // Update the frame mlt_properties_set_data( properties, "image", *buffer, size, mlt_pool_release, NULL ); mlt_properties_set_int( properties, "width", *width ); mlt_properties_set_int( properties, "height", *height ); *format = mlt_image_yuv422; if ( *buffer != NULL ) { mlt_position in = mlt_producer_get_in( producer ); mlt_position out = mlt_producer_get_out( producer ); mlt_position time = mlt_frame_get_position( frame ); double position = ( double )( time - in ) / ( double )( out - in + 1 ); process_frei0r_item( producer_type , position, producer_props, frame , buffer, format , width , height , writable ); } return 0; }
static void add_text_to_bg( mlt_producer producer, mlt_frame bg_frame, mlt_frame text_frame ) { mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer ); mlt_transition transition = mlt_properties_get_data( producer_properties, "_transition", NULL ); if( !transition ) { mlt_profile profile = mlt_service_profile( MLT_PRODUCER_SERVICE( producer ) ); transition = mlt_factory_transition( profile, "composite", NULL ); // Save the transition for future use. mlt_properties_set_data( producer_properties, "_transition", transition, 0, ( mlt_destructor )mlt_transition_close, NULL ); // Configure the transition. mlt_properties transition_properties = MLT_TRANSITION_PROPERTIES( transition ); mlt_properties_set( transition_properties, "geometry", "0%/0%:100%x100%:100" ); mlt_properties_set( transition_properties, "halign", "center" ); mlt_properties_set( transition_properties, "valign", "middle" ); } if( transition && bg_frame && text_frame ) { // Apply the transition. mlt_transition_process( transition, bg_frame, text_frame ); } }
int mlt_frame_is_test_card( mlt_frame self ) { mlt_properties properties = MLT_FRAME_PROPERTIES( self ); return ( mlt_deque_count( self->stack_image ) == 0 && !mlt_properties_get_data( properties, "image", NULL ) ) || mlt_properties_get_int( properties, "test_image" ); }
int mlt_frame_is_test_audio( mlt_frame self ) { mlt_properties properties = MLT_FRAME_PROPERTIES( self ); return ( mlt_deque_count( self->stack_audio ) == 0 && !mlt_properties_get_data( properties, "audio", NULL ) ) || mlt_properties_get_int( properties, "test_audio" ); }
static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { context cx = mlt_frame_pop_service( frame ); mlt_frame nested_frame = mlt_frame_pop_service( frame ); *width = cx->profile->width; *height = cx->profile->height; int result = mlt_frame_get_image( nested_frame, image, format, width, height, writable ); // Allocate the image int size = mlt_image_format_size( *format, *width, *height, NULL ); uint8_t *new_image = mlt_pool_alloc( size ); // Update the frame mlt_properties properties = mlt_frame_properties( frame ); mlt_frame_set_image( frame, new_image, size, mlt_pool_release ); memcpy( new_image, *image, size ); mlt_properties_set( properties, "progressive", mlt_properties_get( MLT_FRAME_PROPERTIES(nested_frame), "progressive" ) ); *image = new_image; // Copy the alpha channel uint8_t *alpha = mlt_properties_get_data( MLT_FRAME_PROPERTIES( nested_frame ), "alpha", &size ); if ( alpha && size > 0 ) { new_image = mlt_pool_alloc( size ); memcpy( new_image, alpha, size ); mlt_frame_set_alpha( frame, new_image, size, mlt_pool_release ); } return result; }
static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index ) { // Construct a new frame *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) ); if( frame != NULL ) { // Stack the producer and producer's get image mlt_frame_push_service( *frame, (void*) index ); mlt_frame_push_service( *frame, producer ); mlt_frame_push_service( *frame, framebuffer_get_image ); mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer ); mlt_properties frame_properties = MLT_FRAME_PROPERTIES(*frame); // Get frame from the real producer mlt_frame first_frame = mlt_properties_get_data( properties, "first_frame", NULL ); if ( first_frame == NULL ) { // Get the frame to cache from the real producer mlt_producer real_producer = mlt_properties_get_data( properties, "producer", NULL ); // Seek the producer to the correct place mlt_producer_seek( real_producer, mlt_producer_position( producer ) ); // Get the frame mlt_service_get_frame( MLT_PRODUCER_SERVICE( real_producer ), &first_frame, index ); // Cache the frame mlt_properties_set_data( properties, "first_frame", first_frame, 0, ( mlt_destructor )mlt_frame_close, NULL ); } mlt_properties_inherit( frame_properties, MLT_FRAME_PROPERTIES(first_frame) ); double force_aspect_ratio = mlt_properties_get_double( properties, "force_aspect_ratio" ); if ( force_aspect_ratio <= 0.0 ) force_aspect_ratio = mlt_properties_get_double( properties, "aspect_ratio" ); mlt_properties_set_double( frame_properties, "aspect_ratio", force_aspect_ratio ); // Give the returned frame temporal identity mlt_frame_set_position( *frame, mlt_producer_position( producer ) ); mlt_properties_set_int( frame_properties, "meta.media.width", mlt_properties_get_int( properties, "width" ) ); mlt_properties_set_int( frame_properties, "meta.media.height", mlt_properties_get_int( properties, "height" ) ); mlt_properties_pass_list( frame_properties, properties, "width, height" ); } return 0; }
static uint8_t *filter_get_alpha_mask( mlt_frame frame ) { uint8_t *alpha = NULL; // Obtain properties of frame mlt_properties properties = MLT_FRAME_PROPERTIES( frame ); // Get the shape frame mlt_frame shape_frame = mlt_properties_get_data( properties, "shape_frame", NULL ); // Get the width and height of the image int region_width = mlt_properties_get_int( properties, "width" ); int region_height = mlt_properties_get_int( properties, "height" ); uint8_t *image = NULL; mlt_image_format format = mlt_image_yuv422; // Get the shape image to trigger alpha creation mlt_properties_set_int( MLT_FRAME_PROPERTIES( shape_frame ), "distort", 1 ); mlt_frame_get_image( shape_frame, &image, &format, ®ion_width, ®ion_height, 0 ); alpha = mlt_frame_get_alpha_mask( shape_frame ); int size = region_width * region_height; uint8_t *alpha_duplicate = mlt_pool_alloc( size ); int holewhite = mlt_properties_get_int(properties,"holecolor"); if (holewhite) { alpha = alpha_duplicate; while (size--) { uint8_t test = ( int )( ( ( *image ++ - 16 ) * 299 ) / 255 ); if (test <= 10) { *alpha = holewhite==1?0:255; } else if (test >= 250 ) { *alpha = holewhite==2?0:255; } alpha++; image++; } } // Generate from the Y component of the image if no alpha available else if ( alpha == NULL ) { alpha = alpha_duplicate; while ( size -- ) { *alpha ++ = ( int )( ( ( *image ++ - 16 ) * 299 ) / 255 ); image ++; } } else { memcpy( alpha_duplicate, alpha, size ); } mlt_frame_set_alpha( frame, alpha_duplicate, region_width * region_height, mlt_pool_release ); return alpha_duplicate; }
static mlt_filter obtain_filter( mlt_filter filter, char *type ) { // Result to return mlt_filter result = NULL; // Miscelaneous variable int i = 0; int type_len = strlen( type ); // Get the properties of the data show filter mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter ); // Get the profile properties mlt_properties profile_properties = mlt_properties_get_data( filter_properties, "profile_properties", NULL ); // Obtain the profile_properties if we haven't already if ( profile_properties == NULL ) { char temp[ 512 ]; // Get the profile requested char *profile = mlt_properties_get( filter_properties, "resource" ); // If none is specified, pick up the default for this normalisation if ( profile == NULL ) sprintf( temp, "%s/feeds/%s/data_fx.properties", mlt_environment( "MLT_DATA" ), mlt_environment( "MLT_NORMALISATION" ) ); else if ( strchr( profile, '%' ) ) sprintf( temp, "%s/feeds/%s/%s", mlt_environment( "MLT_DATA" ), mlt_environment( "MLT_NORMALISATION" ), strchr( profile, '%' ) + 1 ); else { strncpy( temp, profile, sizeof( temp ) ); temp[ sizeof( temp ) - 1 ] = '\0'; } // Load the specified profile or use the default profile_properties = mlt_properties_load( temp ); // Store for later retrieval mlt_properties_set_data( filter_properties, "profile_properties", profile_properties, 0, ( mlt_destructor )mlt_properties_close, NULL ); } if ( profile_properties != NULL ) { for ( i = 0; i < mlt_properties_count( profile_properties ); i ++ ) { char *name = mlt_properties_get_name( profile_properties, i ); char *value = mlt_properties_get_value( profile_properties, i ); if ( result == NULL && !strcmp( name, type ) && result == NULL ) result = mlt_factory_filter( mlt_service_profile( MLT_FILTER_SERVICE( filter ) ), value, NULL ); else if ( result != NULL && !strncmp( name, type, type_len ) && name[ type_len ] == '.' ) mlt_properties_set( MLT_FILTER_PROPERTIES( result ), name + type_len + 1, value ); else if ( result != NULL ) break; } } return result; }
mlt_producer mlt_producer_cut_parent( mlt_producer self ) { mlt_properties properties = MLT_PRODUCER_PROPERTIES( self ); if ( mlt_producer_is_cut( self ) ) return mlt_properties_get_data( properties, "_cut_parent", NULL ); else return self; }
static void *consumer_thread( void *arg ) { // Map the argument to the object mlt_consumer consumer = arg; // Get the properties mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer ); // Convenience functionality int terminate_on_pause = mlt_properties_get_int( properties, "terminate_on_pause" ); int terminated = 0; // Frame and size mlt_frame frame = NULL; // Loop while running while( !terminated && mlt_properties_get_int( properties, "_running" ) ) { // Get the frame frame = mlt_consumer_rt_frame( consumer ); // Check for termination if ( terminate_on_pause && frame != NULL ) terminated = mlt_properties_get_double( MLT_FRAME_PROPERTIES( frame ), "_speed" ) == 0.0; // Check that we have a frame to work with if ( frame ) { avsync_stats* stats = mlt_properties_get_data( properties, "_stats", NULL ); double fps = mlt_properties_get_double( properties, "fps" ); mlt_position pos = mlt_frame_get_position( frame ); if( !strcmp( mlt_properties_get( properties, "report" ), "frame" ) ) { stats->report_frames = 1; } else { stats->report_frames = 0; } detect_flash( frame, pos, fps, stats ); detect_blip( frame, pos, fps, stats ); calculate_sync( stats ); report_results( stats, pos ); // Close the frame mlt_events_fire( properties, "consumer-frame-show", frame, NULL ); mlt_frame_close( frame ); } } // Indicate that the consumer is stopped mlt_properties_set_int( properties, "_running", 0 ); mlt_consumer_stopped( consumer ); return NULL; }
static int dummy_get_image(mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable) { mlt_properties properties = MLT_FRAME_PROPERTIES(frame); *image = mlt_properties_get_data(properties, "image", NULL); *format = mlt_properties_get_int(properties, "format"); *width = mlt_properties_get_int(properties, "width"); *height = mlt_properties_get_int(properties, "height"); return 0; }
static void cache_object_close( mlt_cache cache, void *object, void* data ) { char key[19]; // Fetch the cache item from the active list by its owner's address sprintf( key, "%p", object ); pthread_mutex_lock( &cache->mutex ); mlt_cache_item item = mlt_properties_get_data( cache->active, key, NULL ); if ( item ) { mlt_log( NULL, MLT_LOG_DEBUG, "%s: item %p object %p data %p refcount %d\n", __FUNCTION__, item, item->object, item->data, item->refcount ); if ( item->destructor && --item->refcount <= 0 ) { // Destroy the data object item->destructor( item->data ); item->data = NULL; item->destructor = NULL; // Do not dispose of the cache item because it could likely be used // again. } } // Fetch the cache item from the garbage collection by its data address if ( data ) { sprintf( key, "%p", data ); item = mlt_properties_get_data( cache->garbage, key, NULL ); if ( item ) { mlt_log( NULL, MLT_LOG_DEBUG, "collecting garbage item %p object %p data %p refcount %d\n", item, item->object, item->data, item->refcount ); if ( item->destructor && --item->refcount <= 0 ) { item->destructor( item->data ); item->data = NULL; item->destructor = NULL; // We do not need the garbage-collected cache item mlt_properties_set_data( cache->garbage, key, NULL, 0, NULL, NULL ); } } } pthread_mutex_unlock( &cache->mutex ); }
static void on_jack_started( mlt_properties owner, mlt_consumer consumer, mlt_position *position ) { mlt_producer producer = mlt_properties_get_data( MLT_CONSUMER_PROPERTIES(consumer), "transport_producer", NULL ); if ( producer ) { if ( mlt_producer_get_speed( producer ) != 0 ) { mlt_properties jack = mlt_properties_get_data( MLT_CONSUMER_PROPERTIES( consumer ), "jack_filter", NULL ); mlt_events_fire( jack, "jack-stop", NULL ); } else { mlt_producer_set_speed( producer, 1 ); mlt_consumer_purge( consumer ); mlt_producer_seek( producer, *position ); mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "refresh", 1 ); } } }
int mlt_frame_get_image( mlt_frame self, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable ) { mlt_properties properties = MLT_FRAME_PROPERTIES( self ); mlt_get_image get_image = mlt_frame_pop_get_image( self ); mlt_image_format requested_format = *format; int error = 0; if ( get_image ) { mlt_properties_set_int( properties, "image_count", mlt_properties_get_int( properties, "image_count" ) - 1 ); error = get_image( self, buffer, format, width, height, writable ); if ( !error && buffer && *buffer ) { mlt_properties_set_int( properties, "width", *width ); mlt_properties_set_int( properties, "height", *height ); if ( self->convert_image && requested_format != mlt_image_none ) self->convert_image( self, buffer, format, requested_format ); mlt_properties_set_int( properties, "format", *format ); } else { error = generate_test_image( properties, buffer, format, width, height, writable ); } } else if ( mlt_properties_get_data( properties, "image", NULL ) && buffer ) { *format = mlt_properties_get_int( properties, "format" ); *buffer = mlt_properties_get_data( properties, "image", NULL ); *width = mlt_properties_get_int( properties, "width" ); *height = mlt_properties_get_int( properties, "height" ); if ( self->convert_image && *buffer && requested_format != mlt_image_none ) { self->convert_image( self, buffer, format, requested_format ); mlt_properties_set_int( properties, "format", *format ); } } else { error = generate_test_image( properties, buffer, format, width, height, writable ); } return error; }
static int producer_get_image( mlt_frame self, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable ) { uint8_t *data = NULL; int size = 0; mlt_properties properties = MLT_FRAME_PROPERTIES( self ); mlt_frame frame = mlt_frame_pop_service( self ); mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame ); mlt_properties_set( frame_properties, "rescale.interp", mlt_properties_get( properties, "rescale.interp" ) ); mlt_properties_set_int( frame_properties, "resize_alpha", mlt_properties_get_int( properties, "resize_alpha" ) ); mlt_properties_set_int( frame_properties, "distort", mlt_properties_get_int( properties, "distort" ) ); mlt_properties_set_int( frame_properties, "consumer_deinterlace", mlt_properties_get_int( properties, "consumer_deinterlace" ) ); mlt_properties_set( frame_properties, "deinterlace_method", mlt_properties_get( properties, "deinterlace_method" ) ); mlt_properties_set_int( frame_properties, "consumer_tff", mlt_properties_get_int( properties, "consumer_tff" ) ); mlt_properties_set( frame_properties, "consumer_color_trc", mlt_properties_get( properties, "consumer_color_trc" ) ); // WebVfx uses this to setup a consumer-stopping event handler. mlt_properties_set_data( frame_properties, "consumer", mlt_properties_get_data( properties, "consumer", NULL ), 0, NULL, NULL ); mlt_frame_get_image( frame, buffer, format, width, height, writable ); mlt_frame_set_image( self, *buffer, 0, NULL ); mlt_properties_set_int( properties, "width", *width ); mlt_properties_set_int( properties, "height", *height ); mlt_properties_set_int( properties, "format", *format ); mlt_properties_set_double( properties, "aspect_ratio", mlt_frame_get_aspect_ratio( frame ) ); mlt_properties_set_int( properties, "progressive", mlt_properties_get_int( frame_properties, "progressive" ) ); mlt_properties_set_int( properties, "distort", mlt_properties_get_int( frame_properties, "distort" ) ); mlt_properties_set_int( properties, "colorspace", mlt_properties_get_int( frame_properties, "colorspace" ) ); mlt_properties_set_int( properties, "force_full_luma", mlt_properties_get_int( frame_properties, "force_full_luma" ) ); mlt_properties_set_int( properties, "top_field_first", mlt_properties_get_int( frame_properties, "top_field_first" ) ); mlt_properties_set( properties, "color_trc", mlt_properties_get( frame_properties, "color_trc" ) ); mlt_properties_set_data( properties, "movit.convert.fence", mlt_properties_get_data( frame_properties, "movit.convert.fence", NULL ), 0, NULL, NULL ); data = mlt_frame_get_alpha( frame ); if ( data ) { mlt_properties_get_data( frame_properties, "alpha", &size ); mlt_frame_set_alpha( self, data, size, NULL ); }; self->convert_image = frame->convert_image; self->convert_audio = frame->convert_audio; return 0; }
void mlt_cache_purge( mlt_cache cache, void *object ) { pthread_mutex_lock( &cache->mutex ); if ( cache && object ) { int i, j; void **alt = cache->current == cache->A ? cache->B : cache->A; for ( i = 0, j = 0; i < cache->count; i++ ) { void *o = cache->current[ i ]; if ( o == object ) { pthread_mutex_unlock( &cache->mutex ); cache_object_close( cache, o, NULL ); pthread_mutex_lock( &cache->mutex ); } else { alt[ j++ ] = o; } } cache->count = j; cache->current = alt; // Remove the object's data from the active list regardless of refcount char key[19]; sprintf( key, "%p", object ); mlt_cache_item item = mlt_properties_get_data( cache->active, key, NULL ); if ( item && item->destructor ) { item->destructor( item->data ); item->data = NULL; item->destructor = NULL; mlt_properties_set_data( cache->active, key, NULL, 0, NULL, NULL ); } // Remove the object's items from the garbage collection regardless of refcount i = mlt_properties_count( cache->garbage ); while ( i-- ) { item = mlt_properties_get_data_at( cache->garbage, i, NULL ); if ( object == item->object && item->destructor ) { sprintf( key, "%p", item->data ); item->destructor( item->data ); item->data = NULL; item->destructor = NULL; mlt_properties_set_data( cache->garbage, key, NULL, 0, NULL, NULL ); } } } pthread_mutex_unlock( &cache->mutex ); }
static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *image_format, int *width, int *height, int writable ) { int error = 0; mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame ); mlt_filter filter = (mlt_filter)mlt_frame_pop_service( frame ); int samples = 0; int channels = 0; int frequency = 0; mlt_audio_format audio_format = mlt_audio_s16; int16_t* audio = (int16_t*)mlt_properties_get_data( frame_properties, "audio", NULL ); if ( !audio && !preprocess_warned ) { // This filter depends on the consumer processing the audio before the // video. If the audio is not preprocessed, this filter will process it. // If this filter processes the audio, it could cause confusion for the // consumer if it needs different audio properties. mlt_log_warning( MLT_FILTER_SERVICE(filter), "Audio not preprocessed. Potential audio distortion.\n" ); preprocess_warned = true; } *image_format = mlt_image_rgb24a; // Get the current image error = mlt_frame_get_image( frame, image, image_format, width, height, writable ); // Get the audio if( !error ) { frequency = mlt_properties_get_int( frame_properties, "audio_frequency" ); if (!frequency) { frequency = 48000; } channels = mlt_properties_get_int( frame_properties, "audio_channels" ); if (!channels) { channels = 2; } samples = mlt_properties_get_int( frame_properties, "audio_samples" ); if (!samples) { mlt_producer producer = mlt_frame_get_original_producer( frame ); double fps = mlt_producer_get_fps( mlt_producer_cut_parent( producer ) ); samples = mlt_sample_calculator( fps, frequency, mlt_frame_get_position( frame ) ); } error = mlt_frame_get_audio( frame, (void**)&audio, &audio_format, &frequency, &channels, &samples ); } // Draw the waveforms if( !error ) { QImage qimg( *width, *height, QImage::Format_ARGB32 ); convert_mlt_to_qimage_rgba( *image, &qimg, *width, *height ); draw_waveforms( filter, frame, &qimg, audio, channels, samples ); convert_qimage_to_mlt_rgba( &qimg, *image, *width, *height ); } return error; }
static int producer_get_image( mlt_frame frame, uint8_t** buffer, mlt_image_format* format, int* width, int* height, int writable ) { mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame ); mlt_producer producer = static_cast<mlt_producer>( mlt_properties_get_data( frame_properties, "_producer_qtext", NULL ) ); mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer ); int img_size = 0; int alpha_size = 0; uint8_t* alpha = NULL; QImage* qImg = static_cast<QImage*>( mlt_properties_get_data( producer_properties, "_qimg", NULL ) ); mlt_service_lock( MLT_PRODUCER_SERVICE( producer ) ); // Regenerate the qimage if necessary if( check_qimage( frame_properties ) == true ) { generate_qimage( frame_properties ); } *format = mlt_image_rgb24a; *width = qImg->width(); *height = qImg->height(); // Allocate and fill the image buffer img_size = mlt_image_format_size( *format, *width, *height, NULL ); *buffer = static_cast<uint8_t*>( mlt_pool_alloc( img_size ) ); copy_qimage_to_mlt_image( qImg, *buffer ); mlt_service_unlock( MLT_PRODUCER_SERVICE( producer ) ); // Allocate and fill the alpha buffer alpha_size = *width * *height; alpha = static_cast<uint8_t*>( mlt_pool_alloc( alpha_size ) ); copy_image_to_alpha( *buffer, alpha, *width, *height ); // Update the frame mlt_frame_set_image( frame, *buffer, img_size, mlt_pool_release ); mlt_frame_set_alpha( frame, alpha, alpha_size, mlt_pool_release ); mlt_properties_set_int( frame_properties, "width", *width ); mlt_properties_set_int( frame_properties, "height", *height ); return 0; }
static uint8_t *frame_resize_image( mlt_frame frame, int owidth, int oheight, int bpp ) { // Get properties mlt_properties properties = MLT_FRAME_PROPERTIES( frame ); // Get the input image, width and height uint8_t *input = mlt_properties_get_data( properties, "image", NULL ); uint8_t *alpha = mlt_frame_get_alpha( frame ); int alpha_size = 0; mlt_properties_get_data( properties, "alpha", &alpha_size ); int iwidth = mlt_properties_get_int( properties, "width" ); int iheight = mlt_properties_get_int( properties, "height" ); // If width and height are correct, don't do anything if ( iwidth < owidth || iheight < oheight ) { uint8_t alpha_value = mlt_properties_get_int( properties, "resize_alpha" ); // Create the output image uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * bpp ); // Call the generic resize resize_image( output, owidth, oheight, input, iwidth, iheight, bpp ); // Now update the frame mlt_frame_set_image( frame, output, owidth * ( oheight + 1 ) * bpp, mlt_pool_release ); // We should resize the alpha too if ( alpha && alpha_size >= iwidth * iheight ) { alpha = resize_alpha( alpha, owidth, oheight, iwidth, iheight, alpha_value ); if ( alpha ) mlt_frame_set_alpha( frame, alpha, owidth * oheight, mlt_pool_release ); } // Return the output return output; } // No change, return input return input; }
static void on_jack_stopped( mlt_properties owner, mlt_consumer consumer, mlt_position *position ) { mlt_producer producer = mlt_properties_get_data( MLT_CONSUMER_PROPERTIES(consumer), "transport_producer", NULL ); if ( producer ) { mlt_producer_set_speed( producer, 0 ); mlt_consumer_purge( consumer ); mlt_producer_seek( producer, *position ); mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "refresh", 1 ); } }
dv_decoder_t *dv_decoder_alloc( ) { // We'll return a dv_decoder dv_decoder_t *this = NULL; // Lock the mutex pthread_mutex_lock( &decoder_lock ); // Create the properties if necessary if ( dv_decoders == NULL ) { // Create the properties dv_decoders = mlt_properties_new( ); // Create the stack mlt_properties_set_data( dv_decoders, "stack", mlt_deque_init( ), 0, ( mlt_destructor )mlt_deque_close, NULL ); // Register the properties for clean up mlt_factory_register_for_clean_up( dv_decoders, ( mlt_destructor )mlt_properties_close ); } // Now try to obtain a decoder if ( dv_decoders != NULL ) { // Obtain the stack mlt_deque stack = mlt_properties_get_data( dv_decoders, "stack", NULL ); // Pop the top of the stack this = mlt_deque_pop_back( stack ); // Create a new decoder if none available if ( this == NULL ) { // We'll need a unique property ID for this char label[ 256 ]; // Configure the decoder this = dv_decoder_new( FALSE, FALSE, FALSE ); this->quality = DV_QUALITY_COLOR | DV_QUALITY_AC_2; this->audio->arg_audio_emphasis = 2; dv_set_audio_correction( this, DV_AUDIO_CORRECT_AVERAGE ); dv_set_error_log( this, NULL ); // Register it with the properties to ensure clean up sprintf( label, "%p", this ); mlt_properties_set_data( dv_decoders, label, this, 0, ( mlt_destructor )dv_decoder_free, NULL ); } } // Unlock the mutex pthread_mutex_unlock( &decoder_lock ); return this; }
static void on_jack_seek( mlt_properties owner, mlt_filter filter, mlt_position *position ) { mlt_properties properties = MLT_FILTER_PROPERTIES( filter ); mlt_log_verbose( MLT_FILTER_SERVICE(filter), "%s: %d\n", __FUNCTION__, *position ); mlt_properties_set_int( properties, "_sync_guard", 1 ); mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) ); jack_client_t *jack_client = mlt_properties_get_data( properties, "jack_client", NULL ); jack_nframes_t jack_frame = jack_get_sample_rate( jack_client ); jack_frame *= *position / mlt_profile_fps( profile ); jack_transport_locate( jack_client, jack_frame ); }
static int push( mlt_parser self, int multitrack, int track, int position ) { mlt_properties properties = mlt_parser_properties( self ); mlt_deque stack = mlt_properties_get_data( properties, "stack", NULL ); track_info *info = malloc( sizeof( track_info ) ); info->multitrack = multitrack; info->track = track; info->position = position; info->length = 0; info->offset = 0; return mlt_deque_push_back( stack, info ); }
static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { // Pop the service mlt_filter filter = mlt_frame_pop_service( frame ); // Get the frame properties mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame ); mlt_service_lock( MLT_FILTER_SERVICE( filter ) ); // Track specific process_queue( mlt_properties_get_data( frame_properties, "data_queue", NULL ), frame, filter ); // Global process_queue( mlt_properties_get_data( frame_properties, "global_queue", NULL ), frame, filter ); mlt_service_unlock( MLT_FILTER_SERVICE( filter ) ); // Need to get the image return mlt_frame_get_image( frame, image, format, width, height, 1 ); }