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 get_image_b( mlt_frame b_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { mlt_transition self = mlt_frame_pop_service( b_frame ); mlt_frame a_frame = mlt_frame_pop_frame( b_frame ); mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame ); mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame ); // Set scaling from A frame if not already provided. if ( !mlt_properties_get( b_props, "rescale.interp" ) ) { const char *rescale = mlt_properties_get( a_props, "rescale.interp" ); if ( !rescale || !strcmp( rescale, "none" ) ) rescale = "nearest"; mlt_properties_set( b_props, "rescale.interp", rescale ); } // Ensure sane aspect ratio if ( mlt_frame_get_aspect_ratio( b_frame ) == 0.0 ) mlt_frame_set_aspect_ratio( b_frame, mlt_profile_sar( mlt_service_profile( MLT_TRANSITION_SERVICE(self) ) ) ); mlt_properties_pass_list( b_props, a_props, "consumer_deinterlace, deinterlace_method, consumer_tff" ); return mlt_frame_get_image( b_frame, image, format, width, height, writable ); }
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 attach_boundry_to_frame( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { // Get the filter object mlt_filter filter = mlt_frame_pop_service( frame ); // Get the filter's property object mlt_properties filter_properties = MLT_FILTER_PROPERTIES(filter); // Get the frame properties mlt_properties frame_properties = MLT_FRAME_PROPERTIES(frame); // Get the frame position mlt_position position = mlt_filter_get_position( filter, frame ); mlt_service_lock( MLT_FILTER_SERVICE( filter ) ); // Get the geometry object mlt_geometry geometry = mlt_properties_get_data(filter_properties, "filter_geometry", NULL); if (geometry == NULL) { mlt_geometry geom = mlt_geometry_init(); char *arg = mlt_properties_get(filter_properties, "geometry"); // Initialize with the supplied geometry struct mlt_geometry_item_s item; mlt_geometry_parse_item( geom, &item, arg ); item.frame = 0; item.key = 1; item.mix = 100; mlt_geometry_insert( geom, &item ); mlt_geometry_interpolate( geom ); mlt_properties_set_data( filter_properties, "filter_geometry", geom, 0, (mlt_destructor)mlt_geometry_close, (mlt_serialiser)mlt_geometry_serialise ); geometry = mlt_properties_get_data(filter_properties, "filter_geometry", NULL); } mlt_service_unlock( MLT_FILTER_SERVICE( filter ) ); // Get the current geometry item mlt_geometry_item geometry_item = mlt_pool_alloc( sizeof( struct mlt_geometry_item_s ) ); mlt_geometry_fetch(geometry, geometry_item, position); // Cleanse the geometry item geometry_item->w = geometry_item->x < 0 ? geometry_item->w + geometry_item->x : geometry_item->w; geometry_item->h = geometry_item->y < 0 ? geometry_item->h + geometry_item->y : geometry_item->h; geometry_item->x = geometry_item->x < 0 ? 0 : geometry_item->x; geometry_item->y = geometry_item->y < 0 ? 0 : geometry_item->y; geometry_item->w = geometry_item->w < 0 ? 0 : geometry_item->w; geometry_item->h = geometry_item->h < 0 ? 0 : geometry_item->h; mlt_properties_set_data( frame_properties, "bounds", geometry_item, sizeof( struct mlt_geometry_item_s ), mlt_pool_release, NULL ); // Get the new image int error = mlt_frame_get_image( frame, image, format, width, height, 1 ); if( error != 0 ) mlt_properties_debug( frame_properties, "error after mlt_frame_get_image() in autotrack_rectangle attach_boundry_to_frame", stderr ); 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_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_data( properties, "movit.convert.fence", mlt_properties_get_data( frame_properties, "movit.convert.fence", NULL ), 0, NULL, NULL ); data = mlt_frame_get_alpha_mask( frame ); 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; }
static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { mlt_filter filter = (mlt_filter) mlt_frame_pop_service( frame ); int error = 0; // Regenerate the LUT if necessary mlt_service_lock( MLT_FILTER_SERVICE( filter ) ); refresh_lut( filter, frame ); mlt_service_unlock( MLT_FILTER_SERVICE( filter ) ); // Make sure the format is acceptable if( *format != mlt_image_rgb24 && *format != mlt_image_rgb24a ) { *format = mlt_image_rgb24; } // Get the image writable = 1; error = mlt_frame_get_image( frame, image, format, width, height, writable ); // Apply the LUT if( !error ) { apply_lut( filter, *image, *format, *width, *height ); } return error; }
/** 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; }
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 filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { mlt_filter filter = (mlt_filter) mlt_frame_pop_service( frame ); mlt_properties properties = MLT_FILTER_PROPERTIES( filter ); mlt_position position = mlt_filter_get_position( filter, frame ); mlt_position length = mlt_filter_get_length2( filter, frame ); // Get the image *format = mlt_image_yuv422; int error = mlt_frame_get_image( frame, image, format, width, height, 1 ); // Only process if we have no error and a valid colour space if ( error == 0 ) { double level = 1.0; // Use animated "level" property only if it has been set since init char* level_property = mlt_properties_get( MLT_FILTER_PROPERTIES( filter ), "level" ); if ( level_property != NULL ) { level = mlt_properties_anim_get_double( properties, "level", position, length ); } else { // Get level using old "start,"end" mechanics // Get the starting brightness level level = fabs( mlt_properties_get_double( MLT_FILTER_PROPERTIES( filter ), "start" ) ); // If there is an end adjust gain to the range if ( mlt_properties_get( MLT_FILTER_PROPERTIES( filter ), "end" ) != NULL ) { // Determine the time position of this frame in the transition duration double end = fabs( mlt_properties_get_double( MLT_FILTER_PROPERTIES( filter ), "end" ) ); level += ( end - level ) * mlt_filter_get_progress( filter, frame ); } } // Only process if level is something other than 1 if ( level != 1.0 ) { int i = *width * *height + 1; uint8_t *p = *image; int32_t m = level * ( 1 << 16 ); int32_t n = 128 * ( ( 1 << 16 ) - m ); while ( --i ) { p[0] = CLAMP( (p[0] * m) >> 16, 16, 235 ); p[1] = CLAMP( (p[1] * m + n) >> 16, 16, 240 ); p += 2; } }
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 = *width * *height * ( *format == mlt_image_yuv422 ? 2 : *format == mlt_image_rgb24 ? 3 : ( *format == mlt_image_rgb24a || *format == mlt_image_opengl ) ? 4 : ( 3 / 2 ) ); uint8_t *new_image = mlt_pool_alloc( size ); // Update the frame mlt_properties properties = mlt_frame_properties( frame ); mlt_properties_set_data( properties, "image", new_image, size, mlt_pool_release, NULL ); memcpy( new_image, *image, size ); mlt_properties_set( properties, "progressive", mlt_properties_get( MLT_FRAME_PROPERTIES(nested_frame), "progressive" ) ); *image = new_image; return result; }
static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ){ if (*format!=mlt_image_yuv422 ){ return -1; } 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" ); if ( mlt_properties_get( a_props, "rescale.interp" ) == NULL || !strcmp( mlt_properties_get( a_props, "rescale.interp" ), "none" ) ) mlt_properties_set( a_props, "rescale.interp", "nearest" ); // set consumer_aspect_ratio for a and b frame if ( mlt_properties_get_double( a_props, "aspect_ratio" ) == 0.0 ) mlt_properties_set_double( a_props, "aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) ); if ( mlt_properties_get_double( b_props, "aspect_ratio" ) == 0.0 ) mlt_properties_set_double( b_props, "aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) ); mlt_properties_set_double( b_props, "consumer_aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) ); if ( mlt_properties_get( b_props, "rescale.interp" ) == NULL || !strcmp( mlt_properties_get( b_props, "rescale.interp" ), "none" ) ) mlt_properties_set( b_props, "rescale.interp", "nearest" ); uint8_t *images[]={NULL,NULL,NULL}; mlt_frame_get_image( a_frame, &images[0], format, width, height, 1 ); mlt_frame_get_image( b_frame, &images[1], format, width, height, 1 ); mlt_position in = mlt_transition_get_in( transition ); mlt_position out = mlt_transition_get_out( transition ); // Get the position of the frame char *name = mlt_properties_get( MLT_TRANSITION_PROPERTIES( transition ), "_unique_id" ); mlt_position position = mlt_properties_get_position( MLT_FRAME_PROPERTIES( a_frame ), name ); float pos=( float )( position - in ) / ( float )( out - in + 1 ); process_frei0r_item( transition_type , pos , properties, !invert ? a_frame : b_frame , images , format, width,height, writable ); *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; }
/** 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_frame_pop_service( frame ); mlt_properties properties = MLT_FILTER_PROPERTIES( filter ); mlt_producer producer = mlt_properties_get_data( properties, "_producer", NULL ); mlt_transition transition = mlt_properties_get_data( properties, "_transition", NULL ); mlt_frame text_frame = NULL; mlt_position position = 0; // Configure this filter mlt_service_lock( MLT_FILTER_SERVICE( filter ) ); setup_producer( filter, producer, frame ); setup_transition( filter, transition ); mlt_service_unlock( MLT_FILTER_SERVICE( filter ) ); // Make sure the producer is in the correct position position = mlt_filter_get_position( filter, frame ); mlt_producer_seek( producer, position ); // Get the b frame and process with transition if successful if ( mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &text_frame, 0 ) == 0 ) { // Get the a and b frame properties mlt_properties a_props = MLT_FRAME_PROPERTIES( frame ); mlt_properties b_props = MLT_FRAME_PROPERTIES( text_frame ); // Set the frame and text_frame to be in the same position and have same consumer requirements mlt_frame_set_position( text_frame, position ); mlt_frame_set_position( frame, position ); mlt_properties_set_int( b_props, "consumer_deinterlace", mlt_properties_get_int( a_props, "consumer_deinterlace" ) ); // Apply all filters that are attached to this filter to the b frame mlt_service_apply_filters( MLT_FILTER_SERVICE( filter ), text_frame, 0 ); // Process the frame mlt_transition_process( transition, frame, text_frame ); // Get the image *format = mlt_image_yuv422; error = mlt_frame_get_image( frame, image, format, width, height, 1 ); // Close the b frame mlt_frame_close( text_frame ); } return error; }
static int get_image_a( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { mlt_transition self = mlt_frame_pop_service( a_frame ); mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame ); // All transitions get scaling const char *rescale = mlt_properties_get( a_props, "rescale.interp" ); if ( !rescale || !strcmp( rescale, "none" ) ) mlt_properties_set( a_props, "rescale.interp", "nearest" ); // Ensure sane aspect ratio if ( mlt_frame_get_aspect_ratio( a_frame ) == 0.0 ) mlt_frame_set_aspect_ratio( a_frame, mlt_profile_sar( mlt_service_profile( MLT_TRANSITION_SERVICE(self) ) ) ); return mlt_frame_get_image( a_frame, image, format, width, height, writable ); }
static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { mlt_filter filter = (mlt_filter) mlt_frame_pop_service( frame ); mlt_properties properties = MLT_FILTER_PROPERTIES( filter ); mlt_position position = mlt_frame_get_position( frame ); // Get the image *format = mlt_image_yuv422; int error = mlt_frame_get_image( frame, image, format, width, height, 0 ); // Only process if we have no error and a valid colour space if ( error == 0 ) { double factor = mlt_properties_get_double( properties, "start" ); mlt_position f_pos = mlt_filter_get_position( filter, frame ); mlt_position f_len = mlt_filter_get_length2( filter, frame ); int speed = mlt_properties_anim_get_int( properties, "speed", f_pos, f_len ); int deformX = mlt_properties_anim_get_int( properties, "deformX", f_pos, f_len ); int deformY = mlt_properties_anim_get_int( properties, "deformY", f_pos, f_len ); if ( mlt_properties_get( properties, "end" ) ) { // Determine the time position of this frame in the transition duration double end = fabs( mlt_properties_get_double( MLT_FILTER_PROPERTIES( filter ), "end" ) ); factor += ( end - factor ) * mlt_filter_get_progress( filter, frame ); } // If animated property "wave" is set, use its value. char* wave_property = mlt_properties_get( properties, "wave" ); if ( wave_property ) { factor = mlt_properties_anim_get_double( properties, "wave", f_pos, f_len ); } if (factor != 0) { int image_size = *width * (*height) * 2; uint8_t *dst = mlt_pool_alloc (image_size); DoWave(*image, *width, (*height), dst, position, speed, factor, deformX, deformY); *image = dst; mlt_frame_set_image( frame, *image, image_size, mlt_pool_release ); } } return error; }
static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { mlt_filter filter = (mlt_filter)mlt_frame_pop_service( frame ); mlt_properties properties = MLT_FILTER_PROPERTIES( filter ); uint8_t* vs_image = NULL; VSPixelFormat vs_format = PF_NONE; // VS only works on progressive frames mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "consumer_deinterlace", 1 ); *format = validate_format( *format ); int error = mlt_frame_get_image( frame, image, format, width, height, 1 ); // Convert the received image to a format vid.stab can handle if ( !error ) { vs_format = mltimage_to_vsimage( *format, *width, *height, *image, &vs_image ); } if( vs_image ) { mlt_service_lock( MLT_FILTER_SERVICE(filter) ); char* results = mlt_properties_get( properties, "results" ); if( results && strcmp( results, "" ) ) { apply_results( filter, frame, vs_image, vs_format, *width, *height ); vsimage_to_mltimage( vs_image, *image, *format, *width, *height ); } else { analyze_image( filter, frame, vs_image, vs_format, *width, *height ); if( mlt_properties_get_int( properties, "show" ) == 1 ) { vsimage_to_mltimage( vs_image, *image, *format, *width, *height ); } } mlt_service_unlock( MLT_FILTER_SERVICE(filter) ); free_vsimage( vs_image, vs_format ); } return error; }
static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { mlt_filter filter = mlt_frame_pop_service( frame ); *format = mlt_image_rgb24a; mlt_log_debug( MLT_FILTER_SERVICE( filter ), "frei0r %dx%d\n", *width, *height ); int error = mlt_frame_get_image( frame, image, format, width, height, 0 ); if ( error == 0 && *image ) { double position = mlt_filter_get_position( filter, frame ); mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) ); double time = position / mlt_profile_fps( profile ); int length = mlt_filter_get_length2( filter, frame ); process_frei0r_item( MLT_FILTER_SERVICE(filter), position, time, length, frame, image, width, height ); } return error; }
static int producer_get_image( mlt_frame frame, uint8_t** image, mlt_image_format* format, int* width, int* height, int writable ) { mlt_producer producer = mlt_frame_pop_service( frame ); mlt_frame bg_frame = NULL; mlt_frame text_frame = NULL; int error = 1; int size = 0; char* background = mlt_properties_get( MLT_PRODUCER_PROPERTIES( producer ), "background" ); time_info info; mlt_service_lock( MLT_PRODUCER_SERVICE( producer ) ); get_time_info( producer, frame, &info ); bg_frame = get_background_frame( producer ); if( !strcmp( background, "clock" ) ) { add_clock_to_frame( producer, bg_frame, &info ); } text_frame = get_text_frame( producer, &info ); add_text_to_bg( producer, bg_frame, text_frame ); if( bg_frame ) { // Get the image from the background frame. error = mlt_frame_get_image( bg_frame, image, format, width, height, writable ); size = mlt_image_format_size( *format, *width, *height, NULL ); // Detach the image from the bg_frame so it is not released. mlt_frame_set_image( bg_frame, *image, size, NULL ); // Attach the image to the input frame. mlt_frame_set_image( frame, *image, size, mlt_pool_release ); mlt_frame_close( bg_frame ); } if( text_frame ) { mlt_frame_close( text_frame ); } mlt_service_unlock( MLT_PRODUCER_SERVICE( producer ) ); return error; }
static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { mlt_filter filter = (mlt_filter) mlt_frame_pop_service( frame ); mlt_properties properties = MLT_FILTER_PROPERTIES( filter ); mlt_position pos = mlt_filter_get_position( filter, frame ); mlt_position len = mlt_filter_get_length2( filter, frame ); *format = mlt_image_yuv422; int error = mlt_frame_get_image( frame, image, format, width, height, 1 ); if ( error == 0 && *image ) { int h = *height; int w = *width; double position = mlt_filter_get_progress( filter, frame ); srand(position*10000); int noise = mlt_properties_anim_get_int( properties, "noise", pos, len ); double contrast = mlt_properties_anim_get_double( properties, "contrast", pos, len ) / 100.0; double brightness = 127.0 * (mlt_properties_anim_get_double( properties, "brightness", pos, len ) -100.0 ) / 100.0; int x = 0,y = 0,pix = 0; for ( x = 0; x < w; x++ ) { for( y = 0; y < h; y++ ) { uint8_t* pixel = (*image + (y) * w * 2 + (x) * 2 ); if (*pixel > 20) { pix = MIN ( MAX ( ( (double)*pixel -127.0 ) * contrast + 127.0 + brightness , 0 ) , 255 ) ; if ( noise > 0 ) pix -= ( rand() % noise - noise ); *pixel = MIN ( MAX ( pix , 0 ) , 255 ); } } } } return error; }
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 ); }
static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { // Pop the top of stack now mlt_filter filter = mlt_frame_pop_service( frame ); // Get the image from the frame *format = mlt_image_yuv422; int error = mlt_frame_get_image( frame, image, format, width, height, 1 ); // Get the image from the frame if ( error == 0 ) { if ( filter != NULL ) { // Get the filter properties mlt_properties properties = MLT_FILTER_PROPERTIES( filter ); mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) ); // Structures for geometry struct geometry_s result; struct geometry_s start; struct geometry_s end; // Retrieve the position float position = mlt_filter_get_progress( filter, frame ); // Now parse the geometries geometry_parse( &start, NULL, mlt_properties_get( properties, "start" ), profile->width, profile->height ); geometry_parse( &end, &start, mlt_properties_get( properties, "end" ), profile->width, profile->height ); // Do the calculation geometry_calculate( &result, &start, &end, position, *width, *height ); // Now actually render it obscure_render( *image, *width, *height, result ); } } return error; }
static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { // Get the filter mlt_filter filter = mlt_frame_pop_service( frame ); // Get the properties of the filter mlt_properties properties = MLT_FILTER_PROPERTIES( filter ); mlt_service_lock( MLT_FILTER_SERVICE( filter ) ); // Get the region transition mlt_transition transition = mlt_properties_get_data( properties, "_transition", NULL ); // Create the transition if not available if ( transition == NULL ) { // Create the transition mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) ); transition = mlt_factory_transition( profile, "region", NULL ); // Register with the filter mlt_properties_set_data( properties, "_transition", transition, 0, ( mlt_destructor )mlt_transition_close, NULL ); // Pass a reference to this filter down mlt_properties_set_data( MLT_TRANSITION_PROPERTIES( transition ), "_region_filter", filter, 0, NULL, NULL ); } mlt_service_unlock( MLT_FILTER_SERVICE( filter ) ); // Pass all properties down mlt_properties_inherit( MLT_TRANSITION_PROPERTIES( transition ), properties ); // Make the frame's position relative to this filter's in point mlt_frame_set_position( frame, mlt_filter_get_position( filter, frame ) ); // Process the frame mlt_transition_process( transition, frame, NULL ); return mlt_frame_get_image( frame, image, format, width, height, writable ); }
static int get_image(mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable) { mlt_transition transition = mlt_frame_pop_service(frame); *format = mlt_frame_pop_service_int(frame); int error = mlt_frame_get_image(frame, image, format, width, height, writable); if (!error) { mlt_properties properties = MLT_FRAME_PROPERTIES(frame); mlt_frame clone = mlt_properties_get_data(properties, "mask frame", NULL); if (clone) { mlt_frame_push_get_image(frame, dummy_get_image); mlt_service_lock(MLT_TRANSITION_SERVICE(transition)); mlt_transition_process(transition, clone, frame); mlt_service_unlock(MLT_TRANSITION_SERVICE(transition)); error = mlt_frame_get_image(clone, image, format, width, height, writable); if (!error) { int size = mlt_image_format_size(*format, *width, *height, NULL); mlt_frame_set_image(frame, *image, size, NULL); } } } return error; }
static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { mlt_filter filter = (mlt_filter) mlt_frame_pop_service( frame ); mlt_properties properties = MLT_FILTER_PROPERTIES( filter ); mlt_position position = mlt_filter_get_position( filter, frame ); mlt_position length = mlt_filter_get_length2( filter, frame ); *format = mlt_image_yuv422; int error = mlt_frame_get_image( frame, image, format, width, height, 1 ); if ( error == 0 ) { // Get the gamma value double gamma = mlt_properties_anim_get_double( properties, "gamma", position, length ); if ( gamma != 1.0 ) { uint8_t *p = *image; uint8_t *q = *image + *width * *height * 2; // Calculate the look up table double exp = 1 / gamma; uint8_t lookup[ 256 ]; int i; for( i = 0; i < 256; i ++ ) lookup[ i ] = ( uint8_t )( pow( ( double )i / 255.0, exp ) * 255 ); while ( p != q ) { *p = lookup[ *p ]; p += 2; } } } return 0; }
int get_image_and_detect(mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable) { mlt_filter filter = (mlt_filter) mlt_frame_pop_service(frame); mlt_properties properties = MLT_FILTER_PROPERTIES(filter); *format = mlt_image_yuv420p; writable = writable || mlt_properties_get_int(properties, "show") ? 1 : 0; int error = mlt_frame_get_image(frame, image, format, width, height, writable); if (!error) { // Service locks are for concurrency control mlt_service_lock(MLT_FILTER_SERVICE(filter)); StabData *data = static_cast<StabData*>(mlt_properties_get_data(properties, "_stab_data", NULL)); if (!data) { data = init_detect(properties, format, width, height); mlt_properties_set_data(properties, "_stab_data", data, 0, (mlt_destructor) destroy_detect, NULL); } VSMotionDetect* md = &data->md; LocalMotions localmotions; VSFrame vsFrame; vsFrameFillFromBuffer(&vsFrame, *image, &md->fi); // detect and save motions vsMotionDetection(md, &localmotions, &vsFrame); mlt_position pos = mlt_filter_get_position( filter, frame ); serialize_localmotions(data, localmotions, pos); mlt_service_unlock(MLT_FILTER_SERVICE(filter)); } return error; }
static int transitionGetImage(mlt_frame aFrame, uint8_t **image, mlt_image_format *format, int *width, int *height, int /*writable*/) { int error = 0; mlt_frame bFrame = mlt_frame_pop_frame(aFrame); mlt_transition transition = (mlt_transition)mlt_frame_pop_service(aFrame); mlt_position position = mlt_transition_get_position(transition, aFrame); mlt_position length = mlt_transition_get_length(transition); // Get the aFrame image, we will write our output to it *format = mlt_image_rgb24; if ((error = mlt_frame_get_image(aFrame, image, format, width, height, 1)) != 0) return error; // Get the bFrame image, we won't write to it uint8_t *bImage = NULL; int bWidth = 0, bHeight = 0; if ((error = mlt_frame_get_image(bFrame, &bImage, format, &bWidth, &bHeight, 0)) != 0) return error; { // Scope the lock MLTWebVfx::ServiceLocker locker(MLT_TRANSITION_SERVICE(transition)); if (!locker.initialize(*width, *height)) return 1; MLTWebVfx::ServiceManager* manager = locker.getManager(); WebVfx::Image renderedImage(*image, *width, *height, *width * *height * WebVfx::Image::BytesPerPixel); manager->setImageForName(manager->getSourceImageName(), &renderedImage); WebVfx::Image targetImage(bImage, bWidth, bHeight, bWidth * bHeight * WebVfx::Image::BytesPerPixel); manager->setImageForName(manager->getTargetImageName(), &targetImage); manager->render(&renderedImage, position, length); } return error; }
// FIXME: may exceed boundies *(r-1) = ( 1.0 - scale ) * ( (double)(*(f-1) + (double)f[3]) / 2.0 ) + scale * (double) s[1]; } // } } } } } } // Image stack(able) method static int slowmotion_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { // Get the filter object and properties mlt_producer producer = mlt_frame_pop_service( this ); mlt_frame second_frame = mlt_frame_pop_service( this ); mlt_frame first_frame = mlt_frame_pop_service( this ); mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer ); // Frame properties objects mlt_properties frame_properties = MLT_FRAME_PROPERTIES( this ); mlt_properties first_frame_properties = MLT_FRAME_PROPERTIES( first_frame ); mlt_properties second_frame_properties = MLT_FRAME_PROPERTIES( second_frame ); // image stride int size, xstride, ystride; switch( *format ){ case mlt_image_yuv422: size = *width * *height * 2;
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <framework/mlt.h> #include "frei0r_helper.h" #include <string.h> static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { mlt_filter filter = mlt_frame_pop_service( this ); int error = mlt_frame_get_image( this, image, format, width, height, 1 ); if ( error == 0 && *image && *format == mlt_image_yuv422 ) { mlt_position in = mlt_filter_get_in( filter ); mlt_position out = mlt_filter_get_out( filter ); mlt_position time = mlt_frame_get_position( this ); double position = ( double )( time - in ) / ( double )( out - in + 1 ); process_frei0r_item( filter_type , position, MLT_FILTER_PROPERTIES ( filter ), this , image, format , width , height , writable ); } return error; }
static int 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_properties properties = MLT_FRAME_PROPERTIES( a_frame ); mlt_transition transition = MLT_TRANSITION( mlt_frame_pop_service( a_frame ) ); uint8_t *b_image; int window_size = mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( transition ), "window_size" ); double psnr[3], ssim[3]; *format = mlt_image_yuv422; mlt_frame_get_image( b_frame, &b_image, format, width, height, writable ); mlt_frame_get_image( a_frame, image, format, width, height, writable ); psnr[0] = calc_psnr( *image, b_image, *width * *height, 2 ); psnr[1] = calc_psnr( *image + 1, b_image + 1, *width * *height / 2, 4 ); psnr[2] = calc_psnr( *image + 3, b_image + 3, *width * *height / 2, 4 ); ssim[0] = calc_ssim( *image, b_image, *width, *height, window_size, 2 ); ssim[1] = calc_ssim( *image + 1, b_image + 1, *width / 2, *height, window_size, 4 ); ssim[2] = calc_ssim( *image + 3, b_image + 3, *width / 2, *height, window_size, 4 ); mlt_properties_set_double( properties, "meta.vqm.psnr.y", psnr[0] ); mlt_properties_set_double( properties, "meta.vqm.psnr.cb", psnr[1] ); mlt_properties_set_double( properties, "meta.vqm.psnr.cr", psnr[2] ); mlt_properties_set_double( properties, "meta.vqm.ssim.y", ssim[0] ); mlt_properties_set_double( properties, "meta.vqm.ssim.cb", ssim[1] ); mlt_properties_set_double( properties, "meta.vqm.ssim.cr", ssim[2] ); printf( "%05d %05.2f %05.2f %05.2f %5.3f %5.3f %5.3f\n", mlt_frame_get_position( a_frame ), psnr[0], psnr[1], psnr[2], ssim[0], ssim[1], ssim[2] ); // copy the B frame to the bottom of the A frame for comparison window_size = mlt_image_format_size( *format, *width, *height, NULL ) / 2; memcpy( *image + window_size, b_image + window_size, window_size ); if ( !mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( transition ), "render" ) ) return 0; // get RGBA image for Qt drawing *format = mlt_image_rgb24a; mlt_frame_get_image( a_frame, image, format, width, height, 1 ); // convert mlt image to qimage QImage img( *width, *height, QImage::Format_ARGB32 ); int y = *height + 1; uint8_t *src = *image; while ( --y ) { QRgb *dst = (QRgb*) img.scanLine( *height - y ); int x = *width + 1; while ( --x ) { *dst++ = qRgba( src[0], src[1], src[2], 255 ); src += 4; } } // setup Qt drawing QPainter painter; painter.begin( &img ); painter.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing ); // draw some stuff with Qt QPalette palette; QFont font; QString s; font.setBold( true ); font.setPointSize( 30 * *height / 1080 ); painter.setPen( QColor("black") ); painter.drawLine( 0, *height/2 + 1, *width, *height/2 ); painter.setPen( QColor("white") ); painter.drawLine( 0, *height/2 - 1, *width, *height/2 ); painter.setFont( font ); s.sprintf( "Frame: %05d\nPSNR: %05.2f (Y) %05.2f (Cb) %05.2f (Cr)\nSSIM: %5.3f (Y) %5.3f (Cb) %5.3f (Cr)", mlt_frame_get_position( a_frame ), psnr[0], psnr[1], psnr[2], ssim[0], ssim[1], ssim[2] ); painter.setPen( QColor("black") ); painter.drawText( 52, *height * 8 / 10 + 2, *width, *height, 0, s ); painter.setPen( QColor("white") ); painter.drawText( 50, *height * 8 / 10, *width, *height, 0, s ); // finish Qt drawing painter.end(); window_size = mlt_image_format_size( *format, *width, *height, NULL ); uint8_t *dst = (uint8_t *) mlt_pool_alloc( window_size ); mlt_properties_set_data( MLT_FRAME_PROPERTIES(a_frame), "image", dst, window_size, mlt_pool_release, NULL ); *image = dst; // convert qimage to mlt y = *height + 1; while ( --y ) { QRgb *src = (QRgb*) img.scanLine( *height - y ); int x = *width + 1; while ( --x ) { *dst++ = qRed( *src ); *dst++ = qGreen( *src ); *dst++ = qBlue( *src ); *dst++ = qAlpha( *src ); src++; } } return 0; }
static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { mlt_filter filter = mlt_frame_pop_service( frame ); *format = mlt_image_rgb24; mlt_properties_set_int( MLT_FRAME_PROPERTIES(frame), "consumer_deinterlace", 1 ); int error = mlt_frame_get_image( frame, image, format, width, height, 1 ); if ( !error && *image ) { videostab self = filter->child; mlt_position length = mlt_filter_get_length2( filter, frame ); int h = *height; int w = *width; // Service locks are for concurrency control mlt_service_lock( MLT_FILTER_SERVICE( filter ) ); if ( !self->initialized ) { // Initialize our context self->initialized = 1; self->es = es_init( w, h ); self->pos_i = (vc*) malloc( length * sizeof(vc) ); self->pos_h = (vc*) malloc( length * sizeof(vc) ); self->pos_y = (vc*) malloc( h * sizeof(vc) ); self->rs = rs_init( w, h ); } char *vectors = mlt_properties_get( MLT_FILTER_PROPERTIES(filter), "vectors" ); if ( !vectors ) { // Analyse int pos = (int) mlt_filter_get_position( filter, frame ); self->pos_i[pos] = vc_add( pos == 0 ? vc_zero() : self->pos_i[pos - 1], es_estimate( self->es, *image ) ); // On last frame if ( pos == length - 1 ) { mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE(filter) ); double fps = mlt_profile_fps( profile ); // Filter and store the results hipass( self->pos_i, self->pos_h, length, fps ); serialize_vectors( self, length ); } } else { // Apply if ( self->initialized != 2 ) { // Load analysis results from property self->initialized = 2; deserialize_vectors( self, vectors, length ); } if ( self->initialized == 2 ) { // Stabilize float shutter_angle = mlt_properties_get_double( MLT_FRAME_PROPERTIES(frame) , "shutterangle" ); float pos = mlt_filter_get_position( filter, frame ); int i; for (i = 0; i < h; i ++) self->pos_y[i] = interp( self->lanc_kernels,self->pos_h, length, pos + (i - h / 2.0) * shutter_angle / (h * 360.0) ); rs_resample( self->lanc_kernels,self->rs, *image, self->pos_y ); } } mlt_service_unlock( MLT_FILTER_SERVICE( filter ) ); } return error; }
static int framebuffer_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { // Get the filter object and properties mlt_producer producer = mlt_frame_pop_service( frame ); int index = ( int )mlt_frame_pop_service( frame ); mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer ); mlt_service_lock( MLT_PRODUCER_SERVICE( producer ) ); // Frame properties objects mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame ); mlt_frame first_frame = mlt_properties_get_data( properties, "first_frame", NULL ); // Get producer parameters int strobe = mlt_properties_get_int( properties, "strobe" ); int freeze = mlt_properties_get_int( properties, "freeze" ); int freeze_after = mlt_properties_get_int( properties, "freeze_after" ); int freeze_before = mlt_properties_get_int( properties, "freeze_before" ); int in = mlt_properties_get_position( properties, "in" ); // Determine the position mlt_position first_position = (first_frame != NULL) ? mlt_frame_get_position( first_frame ) : -1; mlt_position need_first = freeze; if ( !freeze || freeze_after || freeze_before ) { double prod_speed = mlt_properties_get_double( properties, "_speed" ); double actual_position = in + prod_speed * (double) mlt_producer_position( producer ); if ( mlt_properties_get_int( properties, "reverse" ) ) actual_position = mlt_producer_get_playtime( producer ) - actual_position; if ( strobe < 2 ) { need_first = floor( actual_position ); } else { // Strobe effect wanted, calculate frame position need_first = floor( actual_position ); need_first -= need_first % strobe; } if ( freeze ) { if ( freeze_after && need_first > freeze ) need_first = freeze; else if ( freeze_before && need_first < freeze ) need_first = freeze; } } // Determine output buffer size *width = mlt_properties_get_int( frame_properties, "width" ); *height = mlt_properties_get_int( frame_properties, "height" ); int size = mlt_image_format_size( *format, *width, *height, NULL ); // Get output buffer int buffersize = 0; int alphasize = *width * *height; uint8_t *output = mlt_properties_get_data( properties, "output_buffer", &buffersize ); uint8_t *output_alpha = mlt_properties_get_data( properties, "output_alpha", NULL ); if( buffersize == 0 || buffersize != size ) { // invalidate cached frame first_position = -1; } if ( need_first != first_position ) { // invalidate cached frame first_position = -1; // Bust the cached frame mlt_properties_set_data( properties, "first_frame", NULL, 0, NULL, NULL ); first_frame = NULL; } if ( output && first_position != -1 ) { // Using the cached frame uint8_t *image_copy = mlt_pool_alloc( size ); memcpy( image_copy, output, size ); uint8_t *alpha_copy = mlt_pool_alloc( alphasize ); memcpy( alpha_copy, output_alpha, alphasize ); // Set the output image *image = image_copy; mlt_frame_set_image( frame, image_copy, size, mlt_pool_release ); mlt_frame_set_alpha( frame, alpha_copy, alphasize, mlt_pool_release ); *width = mlt_properties_get_int( properties, "_output_width" ); *height = mlt_properties_get_int( properties, "_output_height" ); *format = mlt_properties_get_int( properties, "_output_format" ); mlt_service_unlock( MLT_PRODUCER_SERVICE( producer ) ); return 0; } // Get the cached frame 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, need_first ); // 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 first_frame_properties = MLT_FRAME_PROPERTIES( first_frame ); // Which frames are buffered? uint8_t *first_image = mlt_properties_get_data( first_frame_properties, "image", NULL ); uint8_t *first_alpha = mlt_properties_get_data( first_frame_properties, "alpha", NULL ); if ( !first_image ) { mlt_properties_set( first_frame_properties, "rescale.interp", mlt_properties_get( frame_properties, "rescale.interp" ) ); int error = mlt_frame_get_image( first_frame, &first_image, format, width, height, writable ); if ( error != 0 ) { mlt_log_error( MLT_PRODUCER_SERVICE( producer ), "first_image == NULL get image died\n" ); mlt_service_unlock( MLT_PRODUCER_SERVICE( producer ) ); return error; } output = mlt_pool_alloc( size ); memcpy( output, first_image, size ); // Let someone else clean up mlt_properties_set_data( properties, "output_buffer", output, size, mlt_pool_release, NULL ); mlt_properties_set_int( properties, "_output_width", *width ); mlt_properties_set_int( properties, "_output_height", *height ); mlt_properties_set_int( properties, "_output_format", *format ); } if ( !first_alpha ) { alphasize = *width * *height; first_alpha = mlt_frame_get_alpha_mask( first_frame ); output_alpha = mlt_pool_alloc( alphasize ); memcpy( output_alpha, first_alpha, alphasize ); mlt_properties_set_data( properties, "output_alpha", output_alpha, alphasize, mlt_pool_release, NULL ); } mlt_service_unlock( MLT_PRODUCER_SERVICE( producer ) ); // Create a copy uint8_t *image_copy = mlt_pool_alloc( size ); memcpy( image_copy, first_image, size ); uint8_t *alpha_copy = mlt_pool_alloc( alphasize ); memcpy( alpha_copy, first_alpha, alphasize ); // Set the output image *image = image_copy; mlt_frame_set_image( frame, *image, size, mlt_pool_release ); mlt_frame_set_alpha( frame, alpha_copy, alphasize, mlt_pool_release ); return 0; }