static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int index ) { // Get the mutiltrack object mlt_multitrack self = parent->child; // Check if we have a track for this index if ( index >= 0 && index < self->count && self->list[ index ] != NULL ) { // Get the producer for this track mlt_producer producer = self->list[ index ]->producer; // Get the track hide property int hide = mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( mlt_producer_cut_parent( producer ) ), "hide" ); // Obtain the current position mlt_position position = mlt_producer_frame( parent ); // Get the parent properties mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( parent ); // Get the speed double speed = mlt_properties_get_double( producer_properties, "_speed" ); // Make sure we're at the same point mlt_producer_seek( producer, position ); // Get the frame from the producer mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), frame, 0 ); // Indicate speed of this producer mlt_properties properties = MLT_FRAME_PROPERTIES( *frame ); mlt_properties_set_double( properties, "_speed", speed ); mlt_frame_set_position( *frame, position ); mlt_properties_set_int( properties, "hide", hide ); } else { // Generate a test frame *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( parent ) ); // Update position on the frame we're creating mlt_frame_set_position( *frame, mlt_producer_position( parent ) ); // Move on to the next frame if ( index >= self->count ) { // Let tractor know if we've reached the end mlt_properties_set_int( MLT_FRAME_PROPERTIES( *frame ), "last_track", 1 ); // Move to the next frame mlt_producer_prepare_next( parent ); } } return 0; }
static void *consumer_thread( void *arg ) { mlt_consumer consumer = arg; mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer ); mlt_frame frame = NULL; // Determine whether to stop at end-of-media int terminate_on_pause = mlt_properties_get_int( properties, "terminate_on_pause" ); int terminated = 0; // Loop while running while ( !terminated && !is_stopped( consumer ) ) { // Get the next frame frame = mlt_consumer_rt_frame( consumer ); // Check for termination if ( terminate_on_pause && frame ) terminated = mlt_properties_get_double( MLT_FRAME_PROPERTIES( frame ), "_speed" ) == 0.0; // Check that we have a frame to work with if ( frame && !terminated && !is_stopped( consumer ) ) { if ( mlt_properties_get_int( MLT_FRAME_PROPERTIES(frame), "rendered" ) ) { if ( mlt_properties_get_int( MLT_FRAME_PROPERTIES(frame), "_speed" ) == 0 ) foreach_consumer_refresh( consumer ); foreach_consumer_put( consumer, frame ); } else { int dropped = mlt_properties_get_int( properties, "_dropped" ); mlt_log_info( MLT_CONSUMER_SERVICE(consumer), "dropped frame %d\n", ++dropped ); mlt_properties_set_int( properties, "_dropped", dropped ); } mlt_frame_close( frame ); } else { if ( frame && terminated ) { // Send this termination frame to nested consumers for their cancellation foreach_consumer_put( consumer, frame ); } if ( frame ) mlt_frame_close( frame ); terminated = 1; } } // Indicate that the consumer is stopped mlt_consumer_stopped( consumer ); return NULL; }
void mlt_frame_replace_image( mlt_frame self, uint8_t *image, mlt_image_format format, int width, int height ) { // Remove all items from the stack while( mlt_deque_pop_back( self->stack_image ) ) ; // Update the information mlt_properties_set_data( MLT_FRAME_PROPERTIES( self ), "image", image, 0, NULL, NULL ); mlt_properties_set_int( MLT_FRAME_PROPERTIES( self ), "width", width ); mlt_properties_set_int( MLT_FRAME_PROPERTIES( self ), "height", height ); mlt_properties_set_int( MLT_FRAME_PROPERTIES( self ), "format", format ); self->get_alpha_mask = NULL; }
static int producer_get_audio( mlt_frame self, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ) { mlt_properties properties = MLT_FRAME_PROPERTIES( self ); mlt_frame frame = mlt_frame_pop_audio( self ); mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame ); mlt_properties_set( frame_properties, "producer_consumer_fps", mlt_properties_get( properties, "producer_consumer_fps" ) ); mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples ); mlt_frame_set_audio( self, *buffer, *format, mlt_audio_format_size( *format, *samples, *channels ), NULL ); mlt_properties_set_int( properties, "audio_frequency", *frequency ); mlt_properties_set_int( properties, "audio_channels", *channels ); mlt_properties_set_int( properties, "audio_samples", *samples ); return 0; }
static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index ) { if ( frame ) { // Construct a new frame *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) ); // Stack the producer and producer's get image mlt_frame_push_service_int( *frame, 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; }
/** 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 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; }
static int get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ) { context cx = mlt_frame_pop_audio( frame ); mlt_frame nested_frame = mlt_frame_pop_audio( frame ); int result = 0; // if not repeating last frame if ( mlt_frame_get_position( nested_frame ) != cx->audio_position ) { double fps = mlt_profile_fps( cx->profile ); if ( mlt_producer_get_fps( cx->self ) < fps ) { fps = mlt_producer_get_fps( cx->self ); mlt_properties_set_double( MLT_FRAME_PROPERTIES(nested_frame), "producer_consumer_fps", fps ); } *samples = mlt_sample_calculator( fps, *frequency, cx->audio_counter++ ); result = mlt_frame_get_audio( nested_frame, buffer, format, frequency, channels, samples ); int size = mlt_audio_format_size( *format, *samples, *channels ); int16_t *new_buffer = mlt_pool_alloc( size ); mlt_frame_set_audio( frame, new_buffer, *format, size, mlt_pool_release ); memcpy( new_buffer, *buffer, size ); *buffer = new_buffer; cx->audio_position = mlt_frame_get_position( nested_frame ); } else { // otherwise return no samples *samples = 0; *buffer = NULL; } return result; }
void mlt_service_apply_filters( mlt_service self, mlt_frame frame, int index ) { int i; mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame ); mlt_properties service_properties = MLT_SERVICE_PROPERTIES( self ); mlt_service_base *base = self->local; mlt_position position = mlt_frame_get_position( frame ); mlt_position self_in = mlt_properties_get_position( service_properties, "in" ); mlt_position self_out = mlt_properties_get_position( service_properties, "out" ); if ( index == 0 || mlt_properties_get_int( service_properties, "_filter_private" ) == 0 ) { // Process the frame with the attached filters for ( i = 0; i < base->filter_count; i ++ ) { if ( base->filters[ i ] != NULL ) { mlt_position in = mlt_filter_get_in( base->filters[ i ] ); mlt_position out = mlt_filter_get_out( base->filters[ i ] ); int disable = mlt_properties_get_int( MLT_FILTER_PROPERTIES( base->filters[ i ] ), "disable" ); if ( !disable && ( ( in == 0 && out == 0 ) || ( position >= in && ( position <= out || out == 0 ) ) ) ) { mlt_properties_set_position( frame_properties, "in", in == 0 ? self_in : in ); mlt_properties_set_position( frame_properties, "out", out == 0 ? self_out : out ); mlt_filter_process( base->filters[ i ], frame ); mlt_service_apply_filters( MLT_FILTER_SERVICE( base->filters[ i ] ), frame, index + 1 ); } } } } }
static void get_transform_config( VSTransformConfig* conf, mlt_filter filter, mlt_frame frame ) { mlt_properties properties = MLT_FILTER_PROPERTIES( filter ); const char* filterName = mlt_properties_get( properties, "mlt_service" ); *conf = vsTransformGetDefaultConfig( filterName ); conf->smoothing = mlt_properties_get_int( properties, "smoothing" ); conf->maxShift = mlt_properties_get_int( properties, "maxshift" ); conf->maxAngle = mlt_properties_get_double( properties, "maxangle" ); conf->crop = (VSBorderType)mlt_properties_get_int( properties, "crop" ); conf->zoom = mlt_properties_get_int( properties, "zoom" ); conf->optZoom = mlt_properties_get_int( properties, "optzoom" ); conf->zoomSpeed = mlt_properties_get_double( properties, "zoomspeed" ); conf->relative = mlt_properties_get_int( properties, "relative" ); conf->invert = mlt_properties_get_int( properties, "invert" ); if ( mlt_properties_get_int( properties, "tripod" ) != 0 ) { // Virtual tripod mode: relative=False, smoothing=0 conf->relative = 0; conf->smoothing = 0; } // by default a bicubic interpolation is selected const char *interps = mlt_properties_get( MLT_FRAME_PROPERTIES( frame ), "rescale.interp" ); conf->interpolType = VS_BiCubic; if ( strcmp( interps, "nearest" ) == 0 || strcmp( interps, "neighbor" ) == 0 ) conf->interpolType = VS_Zero; else if ( strcmp( interps, "tiles" ) == 0 || strcmp( interps, "fast_bilinear" ) == 0 ) conf->interpolType = VS_Linear; else if ( strcmp( interps, "bilinear" ) == 0 ) conf->interpolType = VS_BiLinear; }
static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { int error = 0; mlt_profile profile = (mlt_profile) mlt_frame_pop_get_image( frame ); mlt_properties properties = MLT_FRAME_PROPERTIES(frame); mlt_image_format format_from = *format; mlt_image_format format_to = mlt_image_rgb24; error = mlt_frame_get_image( frame, image, format, width, height, writable ); int frame_colorspace = mlt_properties_get_int( properties, "colorspace" ); if ( !error && *format == mlt_image_yuv422 && profile->colorspace > 0 && frame_colorspace > 0 && frame_colorspace != profile->colorspace ) { mlt_log_debug( NULL, "[filter avcolor_space] colorspace %d -> %d\n", frame_colorspace, profile->colorspace ); // Convert to RGB using frame's colorspace error = convert_image( frame, image, &format_from, format_to ); // Convert to YUV using profile's colorspace if ( !error ) { *image = mlt_properties_get_data( properties, "image", NULL ); format_from = mlt_image_rgb24; format_to = *format; mlt_properties_set_int( properties, "colorspace", profile->colorspace ); error = convert_image( frame, image, &format_from, format_to ); *image = mlt_properties_get_data( properties, "image", NULL ); } } return error; }
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 int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index ) { // Generate a frame *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) ); mlt_profile profile = mlt_service_profile( MLT_PRODUCER_SERVICE( producer ) ); if ( *frame != NULL ) { // Obtain properties of frame mlt_properties frame_properties = MLT_FRAME_PROPERTIES( *frame ); // Update time code on the frame mlt_frame_set_position( *frame, mlt_producer_frame( producer ) ); mlt_properties_set_int( frame_properties, "progressive", 1 ); mlt_properties_set_double( frame_properties, "aspect_ratio", mlt_profile_sar( profile ) ); mlt_properties_set_int( frame_properties, "meta.media.width", profile->width ); mlt_properties_set_int( frame_properties, "meta.media.height", profile->height ); // Configure callbacks mlt_frame_push_service( *frame, producer ); mlt_frame_push_get_image( *frame, producer_get_image ); mlt_frame_push_audio( *frame, producer ); mlt_frame_push_audio( *frame, producer_get_audio ); } // Calculate the next time code mlt_producer_prepare_next( producer ); return 0; }
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 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 getFrame(mlt_producer producer, mlt_frame_ptr frame, int /*index*/) { // Generate a frame *frame = mlt_frame_init(MLT_PRODUCER_SERVICE(producer)); if (*frame) { // Obtain properties of frame and producer mlt_properties properties = MLT_FRAME_PROPERTIES(*frame); // Set the producer on the frame properties mlt_properties_set_data(properties, kWebVfxProducerPropertyName, producer, 0, NULL, NULL); // Update timecode on the frame we're creating mlt_position position = mlt_producer_position(producer); mlt_frame_set_position(*frame, position); mlt_properties_set_position(properties, kWebVfxPositionPropertyName, position); // Set producer-specific frame properties mlt_properties_set_int(properties, "progressive", 1); // Push the get_image method mlt_frame_push_get_image(*frame, producerGetImage); } // Calculate the next timecode mlt_producer_prepare_next(producer); 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_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 get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ) { mlt_frame nested_frame = mlt_frame_pop_audio( frame ); int result = mlt_frame_get_audio( nested_frame, buffer, format, frequency, channels, samples ); int size = *channels * *samples; switch ( *format ) { case mlt_audio_s16: size *= sizeof( int16_t ); break; case mlt_audio_s32: size *= sizeof( int32_t ); case mlt_audio_float: size *= sizeof( float ); default: mlt_log_error( NULL, "[producer consumer] Invalid audio format\n" ); } int16_t *new_buffer = mlt_pool_alloc( size ); mlt_properties_set_data( MLT_FRAME_PROPERTIES( frame ), "audio", new_buffer, size, mlt_pool_release, NULL ); memcpy( new_buffer, *buffer, size ); *buffer = new_buffer; return result; }
void consumer_frame_show_cb( mlt_consumer sdl, mlt_consumer parent, mlt_frame frame ) { consumer_sdl self = parent->child; self->last_speed = mlt_properties_get_double( MLT_FRAME_PROPERTIES( frame ), "_speed" ); self->last_position = mlt_frame_get_position( frame ); mlt_events_fire( MLT_CONSUMER_PROPERTIES( parent ), "consumer-frame-show", frame, NULL ); }
int GlslManager::render_frame_texture(mlt_service service, mlt_frame frame, int width, int height, uint8_t **image) { EffectChain* chain = get_chain( service ); if (!chain) return 1; glsl_fbo fbo = get_fbo( width, height ); if (!fbo) return 1; glsl_texture texture = get_texture( width, height, GL_RGBA ); if (!texture) { release_fbo( fbo ); return 1; } glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo ); check_error(); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 ); check_error(); glBindFramebuffer( GL_FRAMEBUFFER, 0 ); check_error(); render_fbo( service, chain, fbo->fbo, width, height ); glFinish(); check_error(); glBindFramebuffer( GL_FRAMEBUFFER, 0 ); check_error(); release_fbo( fbo ); *image = (uint8_t*) &texture->texture; mlt_frame_set_image( frame, *image, 0, NULL ); mlt_properties_set_data( MLT_FRAME_PROPERTIES(frame), "movit.convert.texture", texture, 0, (mlt_destructor) GlslManager::release_texture, NULL ); return 0; }
int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index ) { // Generate a frame *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) ); if ( *frame != NULL ) { // Obtain properties of frame and producer mlt_properties properties = MLT_FRAME_PROPERTIES( *frame ); // Obtain properties of producer mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer ); // Set the producer on the frame properties mlt_properties_set_data( properties, "producer_frei0r", producer, 0, NULL, NULL ); // Update timecode on the frame we're creating mlt_frame_set_position( *frame, mlt_producer_position( producer ) ); // Set producer-specific frame properties mlt_properties_set_int( properties, "progressive", 1 ); mlt_profile profile = mlt_service_profile( MLT_PRODUCER_SERVICE( producer ) ); mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( profile ) ); // Push the get_image method mlt_frame_push_get_image( *frame, producer_get_image ); } // Calculate the next timecode mlt_producer_prepare_next( producer ); return 0; }
static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index ) { // Generate a frame *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) ); // Check that we created a frame and initialize it if ( *frame != NULL ) { // Obtain properties of frame mlt_properties frame_properties = MLT_FRAME_PROPERTIES( *frame ); // Update timecode on the frame we're creating mlt_frame_set_position( *frame, mlt_producer_position( producer ) ); // Save the producer to be used in get_audio mlt_properties_set_data( frame_properties, "_producer_ladspa", producer, 0, NULL, NULL ); // Push the get_audio method mlt_frame_push_audio( *frame, producer_get_audio ); } // Calculate the next time code mlt_producer_prepare_next( producer ); return 0; }
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; }
mlt_frame transition_process( mlt_transition transition, mlt_frame a_frame, mlt_frame b_frame ) { char *name = mlt_properties_get( MLT_TRANSITION_PROPERTIES( transition ), "_unique_id" ); mlt_properties_set_position( MLT_FRAME_PROPERTIES( a_frame ), name, mlt_frame_get_position( a_frame ) ); mlt_frame_push_service( a_frame, transition ); mlt_frame_push_frame( a_frame, b_frame ); mlt_frame_push_get_image( a_frame, transition_get_image ); return a_frame; }
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; }
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; }
void mlt_profile_from_producer( mlt_profile profile, mlt_producer producer ) { mlt_frame fr = NULL; uint8_t *buffer = NULL; mlt_image_format fmt = mlt_image_none; mlt_properties p; int w = profile->width; int h = profile->height; if ( ! mlt_service_get_frame( MLT_PRODUCER_SERVICE(producer), &fr, 0 ) && fr ) { if ( ! mlt_frame_get_image( fr, &buffer, &fmt, &w, &h, 0 ) ) { // Some source properties are not exposed until after the first get_image call. mlt_frame_close( fr ); mlt_service_get_frame( MLT_PRODUCER_SERVICE(producer), &fr, 0 ); p = MLT_FRAME_PROPERTIES( fr ); // mlt_properties_dump(p, stderr); if ( mlt_properties_get_int( p, "meta.media.frame_rate_den" ) && mlt_properties_get_int( p, "meta.media.sample_aspect_den" ) ) { profile->width = mlt_properties_get_int( p, "meta.media.width" ); profile->height = mlt_properties_get_int( p, "meta.media.height" ); profile->progressive = mlt_properties_get_int( p, "meta.media.progressive" ); if ( 1000 > mlt_properties_get_double( p, "meta.media.frame_rate_num" ) / mlt_properties_get_double( p, "meta.media.frame_rate_den" ) ) { profile->frame_rate_num = mlt_properties_get_int( p, "meta.media.frame_rate_num" ); profile->frame_rate_den = mlt_properties_get_int( p, "meta.media.frame_rate_den" ); } else { profile->frame_rate_num = 60; profile->frame_rate_den = 1; } // AVCHD is mis-reported as double frame rate. if ( profile->progressive == 0 && ( profile->frame_rate_num / profile->frame_rate_den == 50 || profile->frame_rate_num / profile->frame_rate_den == 59 ) ) profile->frame_rate_num /= 2; profile->sample_aspect_num = mlt_properties_get_int( p, "meta.media.sample_aspect_num" ); profile->sample_aspect_den = mlt_properties_get_int( p, "meta.media.sample_aspect_den" ); profile->colorspace = mlt_properties_get_int( p, "meta.media.colorspace" ); profile->display_aspect_num = lrint( (double) profile->sample_aspect_num * profile->width / profile->sample_aspect_den ); profile->display_aspect_den = profile->height; free( profile->description ); profile->description = strdup( "automatic" ); profile->is_explicit = 0; } } } mlt_frame_close( fr ); mlt_producer_seek( producer, 0 ); }
static int filter_get_audio( mlt_frame frame, void** buffer, mlt_audio_format* format, int* frequency, int* channels, int* samples ) { mlt_filter filter = (mlt_filter)mlt_frame_pop_audio( frame ); mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter ); private_data* pdata = (private_data*)filter->child; // Create the FFT filter the first time. if( !pdata->fft ) { mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE(filter) ); pdata->fft = mlt_factory_filter( profile, "fft", NULL ); mlt_properties_set_int( MLT_FILTER_PROPERTIES( pdata->fft ), "window_size", mlt_properties_get_int( filter_properties, "window_size" ) ); if( !pdata->fft ) { mlt_log_warning( MLT_FILTER_SERVICE(filter), "Unable to create FFT.\n" ); return 1; } } mlt_properties fft_properties = MLT_FILTER_PROPERTIES( pdata->fft ); // The service must stay locked while using the private data mlt_service_lock( MLT_FILTER_SERVICE( filter ) ); // Perform FFT processing on the frame mlt_filter_process( pdata->fft, frame ); mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples ); float* bins = (float*)mlt_properties_get_data( fft_properties, "bins", NULL ); if( bins ) { double window_level = mlt_properties_get_double( fft_properties, "window_level" ); int bin_count = mlt_properties_get_int( fft_properties, "bin_count" ); size_t bins_size = bin_count * sizeof(float); float* save_bins = (float*)mlt_pool_alloc( bins_size ); if( window_level == 1.0 ) { memcpy( save_bins, bins, bins_size ); } else { memset( save_bins, 0, bins_size ); } // Save the bin data as a property on the frame to be used in get_image() mlt_properties_set_data( MLT_FRAME_PROPERTIES(frame), pdata->fft_prop_name, save_bins, bins_size, mlt_pool_release, NULL ); } mlt_service_unlock( MLT_FILTER_SERVICE( filter ) ); return 0; }