mlt_producer producer_consumer_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ) { mlt_producer self = mlt_producer_new( profile ); // Encapsulate the real producer mlt_profile temp_profile = mlt_profile_clone( profile ); temp_profile->is_explicit = 0; mlt_producer real_producer = mlt_factory_producer( temp_profile, NULL, arg ); if ( self && real_producer ) { // Override some producer methods self->close = ( mlt_destructor )producer_close; self->get_frame = get_frame; // Get the properties of this producer mlt_properties properties = MLT_PRODUCER_PROPERTIES( self ); mlt_properties_set( properties, "resource", arg ); mlt_properties_pass_list( properties, MLT_PRODUCER_PROPERTIES( real_producer ), "out, length" ); // Done with the producer - will re-open later when we have the profile property mlt_producer_close( real_producer ); } else { if ( self ) mlt_producer_close( self ); if ( real_producer ) mlt_producer_close( real_producer ); self = NULL; } mlt_profile_close( temp_profile ); return self; }
void MltRuntime::run() throw (Exception) { init(); Lock lk(&run_lock); if (consumer)mlt_consumer_close(consumer); mlt_profile profile = mlt_profile_clone(MltLoader::global_profile); #ifndef __ANDROID__ consumer = mlt_factory_consumer(profile, "sdl", NULL); //todo #else assert(0); #endif mlt_consumer_connect(consumer, mlt_producer_service(producer)); mlt_consumer_start(consumer); status = StatusRunning; }
static mlt_consumer generate_consumer( mlt_consumer consumer, mlt_properties props, int index ) { mlt_profile profile = NULL; if ( mlt_properties_get( props, "mlt_profile" ) ) profile = mlt_profile_init( mlt_properties_get( props, "mlt_profile" ) ); if ( !profile ) profile = mlt_profile_clone( mlt_service_profile( MLT_CONSUMER_SERVICE(consumer) ) ); mlt_consumer nested = create_consumer( profile, mlt_properties_get( props, "mlt_service" ), mlt_properties_get( props, "target" ) ); if ( nested ) { mlt_properties properties = MLT_CONSUMER_PROPERTIES(consumer); mlt_properties nested_props = MLT_CONSUMER_PROPERTIES(nested); char key[30]; snprintf( key, sizeof(key), "%d.consumer", index ); mlt_properties_set_data( properties, key, nested, 0, (mlt_destructor) mlt_consumer_close, NULL ); snprintf( key, sizeof(key), "%d.profile", index ); mlt_properties_set_data( properties, key, profile, 0, (mlt_destructor) mlt_profile_close, NULL ); mlt_properties_set_int( nested_props, "put_mode", 1 ); mlt_properties_pass_list( nested_props, properties, "terminate_on_pause" ); mlt_properties_set( props, "consumer", NULL ); // set mlt_profile before other properties to facilitate presets mlt_properties_pass_list( nested_props, props, "mlt_profile" ); mlt_properties_inherit( nested_props, props ); attach_normalisers( profile, MLT_CONSUMER_SERVICE(nested) ); // Relay the first available consumer-frame-show event mlt_event event = mlt_properties_get_data( properties, "frame-show-event", NULL ); if ( !event ) { event = mlt_events_listen( nested_props, properties, "consumer-frame-show", (mlt_listener) on_frame_show ); mlt_properties_set_data( properties, "frame-show-event", event, 0, /*mlt_event_close*/ NULL, NULL ); } } else { mlt_profile_close( profile ); } return nested; }
void MltRuntime::run(const string& outpath) throw(Exception) { init(); Lock lk(&run_lock); if ( consumer) mlt_consumer_close(consumer); mlt_profile profile = mlt_profile_clone(MltLoader::global_profile); consumer = mlt_factory_consumer(profile, "avformat", outpath.c_str()); if ( consumer == NULL) { mlt_profile_close(profile); throw_error_v(ErrorRuntimeLoadFailed, "consumer init failed"); } mlt_consumer_connect(consumer, mlt_producer_service(producer)); mlt_consumer_start(consumer); status = StatusRunning; }
void MltRuntime::run(ANativeWindow* nw) throw(Exception) { init(); Lock lk(&run_lock); if ( consumer) mlt_consumer_close(consumer); mlt_profile profile = mlt_profile_clone(MltLoader::global_profile); consumer = mlt_factory_consumer(profile, "android_surface_preview", NULL); if ( consumer == NULL) { mlt_profile_close(profile); throw_error_v(ErrorRuntimeLoadFailed, "consumer init failed"); } mlt_properties props = mlt_consumer_properties(consumer); ANativeWindow_acquire(nw); mlt_properties_set_data(props, "native_window", nw , sizeof(void*),release_native_window , NULL); mlt_consumer_connect(consumer, mlt_producer_service(producer)); mlt_consumer_start(consumer); status = StatusRunning; }
int main( int argc, char **argv ) { int i; mlt_consumer consumer = NULL; FILE *store = NULL; char *name = NULL; mlt_profile profile = NULL; int is_progress = 0; int is_silent = 0; mlt_profile backup_profile; // Handle abnormal exit situations. signal( SIGSEGV, abnormal_exit_handler ); signal( SIGILL, abnormal_exit_handler ); signal( SIGABRT, abnormal_exit_handler ); // Construct the factory mlt_repository repo = mlt_factory_init( NULL ); #if defined(WIN32) && !defined(MELT_NOSDL) is_silent = 1; #endif for ( i = 1; i < argc; i ++ ) { // Check for serialisation switch if ( !strcmp( argv[ i ], "-serialise" ) ) { name = argv[ ++ i ]; if ( name != NULL && strstr( name, ".melt" ) ) store = fopen( name, "w" ); else { if ( name == NULL || name[0] == '-' ) store = stdout; name = NULL; } } // Look for the profile option else if ( !strcmp( argv[ i ], "-profile" ) ) { const char *pname = argv[ ++ i ]; if ( pname && pname[0] != '-' ) profile = mlt_profile_init( pname ); } else if ( !strcmp( argv[ i ], "-progress" ) ) { is_progress = 1; } else if ( !strcmp( argv[ i ], "-progress2" ) ) { is_progress = 2; } // Look for the query option else if ( !strcmp( argv[ i ], "-query" ) ) { const char *pname = argv[ ++ i ]; if ( pname && pname[0] != '-' ) { if ( !strcmp( pname, "consumers" ) || !strcmp( pname, "consumer" ) ) query_services( repo, consumer_type ); else if ( !strcmp( pname, "filters" ) || !strcmp( pname, "filter" ) ) query_services( repo, filter_type ); else if ( !strcmp( pname, "producers" ) || !strcmp( pname, "producer" ) ) query_services( repo, producer_type ); else if ( !strcmp( pname, "transitions" ) || !strcmp( pname, "transition" ) ) query_services( repo, transition_type ); else if ( !strcmp( pname, "profiles" ) || !strcmp( pname, "profile" ) ) query_profiles(); else if ( !strcmp( pname, "presets" ) || !strcmp( pname, "preset" ) ) query_presets(); else if ( !strncmp( pname, "format", 6 ) ) query_formats(); else if ( !strncmp( pname, "acodec", 6 ) || !strcmp( pname, "audio_codecs" ) ) query_acodecs(); else if ( !strncmp( pname, "vcodec", 6 ) || !strcmp( pname, "video_codecs" ) ) query_vcodecs(); else if ( !strncmp( pname, "consumer=", 9 ) ) query_metadata( repo, consumer_type, "consumer", strchr( pname, '=' ) + 1 ); else if ( !strncmp( pname, "filter=", 7 ) ) query_metadata( repo, filter_type, "filter", strchr( pname, '=' ) + 1 ); else if ( !strncmp( pname, "producer=", 9 ) ) query_metadata( repo, producer_type, "producer", strchr( pname, '=' ) + 1 ); else if ( !strncmp( pname, "transition=", 11 ) ) query_metadata( repo, transition_type, "transition", strchr( pname, '=' ) + 1 ); else if ( !strncmp( pname, "profile=", 8 ) ) query_profile( strchr( pname, '=' ) + 1 ); else if ( !strncmp( pname, "preset=", 7 ) ) query_preset( strchr( pname, '=' ) + 1 ); else goto query_all; } else { query_all: query_services( repo, consumer_type ); query_services( repo, filter_type ); query_services( repo, producer_type ); query_services( repo, transition_type ); fprintf( stdout, "# You can query the metadata for a specific service using:\n" "# -query <type>=<identifer>\n" "# where <type> is one of: consumer, filter, producer, or transition.\n" ); } goto exit_factory; } else if ( !strcmp( argv[ i ], "-silent" ) ) { is_silent = 1; } else if ( !strcmp( argv[ i ], "-verbose" ) ) { mlt_log_set_level( MLT_LOG_VERBOSE ); } else if ( !strcmp( argv[ i ], "-version" ) || !strcmp( argv[ i ], "--version" ) ) { fprintf( stdout, "%s " VERSION "\n" "Copyright (C) 2002-2013 Ushodaya Enterprises Limited\n" "<http://www.mltframework.org/>\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n", basename( argv[0] ) ); goto exit_factory; } else if ( !strcmp( argv[ i ], "-debug" ) ) { mlt_log_set_level( MLT_LOG_DEBUG ); } } if ( !is_silent && !isatty( STDIN_FILENO ) && !is_progress ) is_progress = 1; // Create profile if not set explicitly if ( getenv( "MLT_PROFILE" ) ) profile = mlt_profile_init( NULL ); if ( profile == NULL ) profile = mlt_profile_init( NULL ); else profile->is_explicit = 1; // Look for the consumer option to load profile settings from consumer properties backup_profile = mlt_profile_clone( profile ); load_consumer( &consumer, profile, argc, argv ); // If the consumer changed the profile, then it is explicit. if ( backup_profile && !profile->is_explicit && ( profile->width != backup_profile->width || profile->height != backup_profile->height || profile->sample_aspect_num != backup_profile->sample_aspect_num || profile->sample_aspect_den != backup_profile->sample_aspect_den || profile->frame_rate_den != backup_profile->frame_rate_den || profile->frame_rate_num != backup_profile->frame_rate_num || profile->colorspace != backup_profile->colorspace ) ) profile->is_explicit = 1; mlt_profile_close( backup_profile ); // Get melt producer if ( argc > 1 ) melt = mlt_factory_producer( profile, "melt", &argv[ 1 ] ); if ( melt ) { // Generate an automatic profile if needed. if ( ! profile->is_explicit ) { mlt_profile_from_producer( profile, melt ); mlt_producer_close( melt ); melt = mlt_factory_producer( profile, "melt", &argv[ 1 ] ); } // Reload the consumer with the fully qualified profile. // The producer or auto-profile could have changed the profile. load_consumer( &consumer, profile, argc, argv ); // See if producer has consumer already attached if ( !store && !consumer ) { consumer = MLT_CONSUMER( mlt_service_consumer( MLT_PRODUCER_SERVICE( melt ) ) ); if ( consumer ) { mlt_properties_inc_ref( MLT_CONSUMER_PROPERTIES(consumer) ); // because we explicitly close it mlt_properties_set_data( MLT_CONSUMER_PROPERTIES(consumer), "transport_callback", transport_action, 0, NULL, NULL ); } } // If we have no consumer, default to sdl if ( store == NULL && consumer == NULL ) consumer = create_consumer( profile, NULL ); } // Set transport properties on consumer and produder if ( consumer != NULL && melt != NULL ) { mlt_properties_set_data( MLT_CONSUMER_PROPERTIES( consumer ), "transport_producer", melt, 0, NULL, NULL ); mlt_properties_set_data( MLT_PRODUCER_PROPERTIES( melt ), "transport_consumer", consumer, 0, NULL, NULL ); if ( is_progress ) mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "progress", is_progress ); if ( is_silent ) mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "silent", is_silent ); } if ( argc > 1 && melt != NULL && mlt_producer_get_length( melt ) > 0 ) { // Parse the arguments for ( i = 1; i < argc; i ++ ) { if ( !strcmp( argv[ i ], "-jack" ) ) { setup_jack_transport( consumer, profile ); } else if ( !strcmp( argv[ i ], "-serialise" ) ) { if ( store != stdout ) i ++; } else { if ( store != NULL ) fprintf( store, "%s\n", argv[ i ] ); i ++; while ( argv[ i ] != NULL && argv[ i ][ 0 ] != '-' ) { if ( store != NULL ) fprintf( store, "%s\n", argv[ i ] ); i += 1; } i --; } } if ( consumer != NULL && store == NULL ) { // Get melt's properties mlt_properties melt_props = MLT_PRODUCER_PROPERTIES( melt ); // Get the last group mlt_properties group = mlt_properties_get_data( melt_props, "group", 0 ); // Apply group settings mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer ); mlt_properties_inherit( properties, group ); // Connect consumer to melt mlt_consumer_connect( consumer, MLT_PRODUCER_SERVICE( melt ) ); // Start the consumer mlt_events_listen( properties, consumer, "consumer-fatal-error", ( mlt_listener )on_fatal_error ); if ( mlt_consumer_start( consumer ) == 0 ) { // Try to exit gracefully upon these signals signal( SIGINT, stop_handler ); signal( SIGTERM, stop_handler ); #ifndef WIN32 signal( SIGHUP, stop_handler ); signal( SIGPIPE, stop_handler ); #endif // Transport functionality transport( melt, consumer ); // Stop the consumer mlt_consumer_stop( consumer ); } } else if ( store != NULL && store != stdout && name != NULL ) { fprintf( stderr, "Project saved as %s.\n", name ); fclose( store ); } } else { show_usage( argv[0] ); } // Disconnect producer from consumer to prevent ref cycles from closing services if ( consumer ) { mlt_consumer_connect( consumer, NULL ); mlt_events_fire( MLT_CONSUMER_PROPERTIES(consumer), "consumer-cleanup", NULL); } // Close the producer if ( melt != NULL ) mlt_producer_close( melt ); // Close the consumer if ( consumer != NULL ) mlt_consumer_close( consumer ); // Close the factory mlt_profile_close( profile ); exit_factory: // Workaround qmelt on OS X from crashing at exit. #if !defined(__MACH__) || !defined(QT_GUI_LIB) mlt_factory_close( ); #endif return 0; }
void VideoScript::pre_judge() throw (Exception) { const ScriptParam* inparam = get_param_info("in"); const ScriptParam* outparam = get_param_info("out"); const ScriptParam* resparam = get_param_info("resource"); if ( !inparam || inparam->param_style != ScriptParams::PosParam || !outparam || outparam->param_style != ScriptParams::PosParam) { throw_error_v(ErrorScriptArgInvalid, "in/out position param is required for %s script", Vm::proc_type_names[VIDEO_RESOURCE_SCRIPT]); } if ( !resparam || resparam->param_style != ScriptParams::ScalarParam ) { throw_error_v(ErrorScriptArgInvalid, "resource scalar param is required for %s script", Vm::proc_type_names[VIDEO_RESOURCE_SCRIPT]); } json_t* res_arg = get_arg_value("resource"); json_t* in = get_arg_value("in"); json_t* out = get_arg_value("out"); if (!res_arg || !json_is_string(res_arg) || !strlen(json_string_value(res_arg))) { throw_error_v(ErrorScriptArgInvalid, "resource arg is required for %s script", Vm::proc_type_names[VIDEO_RESOURCE_SCRIPT]); } if ( !in || !json_is_integer(in) ) { throw_error_v(ErrorScriptArgInvalid, "in arg is required for %s script", Vm::proc_type_names[VIDEO_RESOURCE_SCRIPT]); } if ( !out || !json_is_integer(out) ) { throw_error_v(ErrorScriptArgInvalid, "out arg is required for %s script", Vm::proc_type_names[VIDEO_RESOURCE_SCRIPT]); } string path(json_string_value(res_arg)); mlt_profile profile = mlt_profile_clone(MltLoader::global_profile); mlt_producer prod = mlt_factory_producer(profile, "loader", path.c_str()); if ( prod == NULL ) { throw_error_v(ErrorScriptArgInvalid, "out arg is required for %s script", Vm::proc_type_names[VIDEO_RESOURCE_SCRIPT]); } uuid = Vm::uuid(); MltLoader::push_mlt_registry(mlt_producer_service(prod), uuid.c_str()); //mlt_producer prod = Vm::get_stream_resource(path); int length = mlt_producer_get_length(prod); int inframe = json_integer_value(in), outframe = json_integer_value(out); json_decref(in); json_decref(out); switch (inparam->pos_type) { case ScriptParams::FramePos: if ( inframe == -1 || inframe >= length) { inframe = length - 1; } else if ( inframe < 0 ) { inframe = length + inframe; if (inframe < 0)inframe = 0; } break; case ScriptParams::TimePos: { int total_time = length * 40; if ( inframe == -1 ) { inframe = length - 1; } else if ( inframe >= 0 ) { if ( inframe > total_time) { inframe = length -1; } else { inframe = (double)inframe / 40 ; } } else { inframe = total_time + inframe; if ( inframe < 0 ) { inframe = length - 1; } else { inframe = (double)inframe/40; } } } break; } switch (outparam->pos_type) { case ScriptParams::FramePos: if ( outframe == -1 || outframe >= length) { outframe = length - 1; } else if ( outframe < 0 ) { outframe = length + outframe; if (outframe < 0)outframe = 0; } break; case ScriptParams::TimePos: { int total_time = length * 40; if ( outframe == -1 ) { outframe = length - 1; } else if ( outframe >= 0 ) { if ( outframe > total_time) { outframe = length -1; } else { outframe = (double)outframe / 40 ; } } else { outframe = total_time + outframe; if ( outframe < 0 ) { outframe = length - 1; } else { outframe = (double)outframe/40; } } } break; } if ( inframe > outframe ) { inframe ^= outframe ^= inframe ^= outframe; } set_frame_range(inframe,outframe); if ( !type_spec_props.get() ) { type_spec_props.reset(new ScriptProps(*this, NULL)); } type_spec_props->add_property("resource", res_arg); json_decref(res_arg); type_spec_props->add_property("uuid", JsonWrap(json_string(uuid.c_str()),1).h); if ( !mlt_props.get()) { mlt_props.reset(new ScriptProps(*this, NULL)); } json_t* jv = json_integer(inframe); mlt_props->add_property("in", jv); json_decref(jv); jv = json_integer(outframe); mlt_props->add_property("out", jv); json_decref(jv); //mlt_producer_set_in_and_out(prod, inframe, outframe); #ifdef DEBUG std::cout << mlt_producer_properties(prod); #endif this->path = path; //todo: check format info return; }
void AsisScript::pre_judge() throw (Exception) { ScriptProps::Property& service_prop = type_spec_props->get_property("service"); if (!service_prop.Evaluable::finished()) throw_error_v(ErrorScriptFmtError,"asis producer script service should be determinated"); ScriptProps::Property& resource_prop = type_spec_props->get_property("resource"); if (!resource_prop.Evaluable::finished()) throw_error_v(ErrorScriptFmtError,"asis producer script resource should be determinated"); json_t* svc_value = service_prop.compile(); json_t* res_value = resource_prop.compile(); JsonWrap svc_wrap(svc_value,1); JsonWrap res_wrap(res_value,1); if ( !svc_value || !json_is_string(svc_value) || !strlen(json_string_value(svc_value))) throw_error_v(ErrorScriptFmtError,"asis producer script service should be string value"); if ( !res_value || !json_is_string(res_value) || !strlen(json_string_value(res_value))) throw_error_v(ErrorScriptFmtError,"asis producer script resource should be string value"); mlt_profile prof = mlt_profile_clone(MltLoader::global_profile); mlt_producer tmp_prod = mlt_factory_producer(prof, json_string_value(svc_value), json_string_value(res_value)); MltSvcWrap prod_wrap(mlt_producer_service(tmp_prod), 1); if (tmp_prod == NULL) { throw_error_v(ErrorRuntimeLoadFailed, "producer %s load failed", json_string_value(svc_value)); } if ( mlt_props ) { ScriptProps::PropIter it = mlt_props->begin(); for ( ; it!=mlt_props->end(); it++) { if ( it->second->Evaluable::finished() ) { json_t* prop_v = it->second->compile(); JsonWrap prop_wrap(prop_v, 1); switch(prop_v->type) { case JSON_INTEGER: mlt_properties_set_int64(mlt_producer_properties(tmp_prod), it->first.c_str(), json_integer_value(prop_v)); break; case JSON_REAL: mlt_properties_set_double(mlt_producer_properties(tmp_prod), it->first.c_str(), json_real_value(prop_v)); break; case JSON_STRING: mlt_properties_set(mlt_producer_properties(tmp_prod), it->first.c_str(), json_string_value(prop_v)); break; case JSON_TRUE: mlt_properties_set_int(mlt_producer_properties(tmp_prod), it->first.c_str(), 1); break; case JSON_FALSE: mlt_properties_set_int(mlt_producer_properties(tmp_prod), it->first.c_str(), 0); break; default: throw_error_v(ErrorRuntimeLoadFailed, "producer %s load failed. %s prop invalid", json_string_value(svc_value), it->first.c_str()); } } } } int in = mlt_producer_get_in(tmp_prod); int out = mlt_producer_get_out(tmp_prod); set_frame_range(in, out); if ( !mlt_props.get()) { mlt_props.reset(new ScriptProps(*this, NULL)); } json_t* jv = json_integer(in); mlt_props->add_property("in", jv); json_decref(jv); jv = json_integer(out); mlt_props->add_property("out", jv); json_decref(jv); string uuid = Vm::uuid(); type_spec_props->add_property("uuid", JsonWrap(json_string(uuid.c_str()),1).h); prod_wrap.obj = NULL; MltLoader::push_mlt_registry(mlt_producer_service(tmp_prod), uuid.c_str()); }
mlt_service SingleResourceLoader::get_asis_producer(JsonWrap js) throw (Exception) { json_t* defines = js.h; defines_tmp=js; json_t* je = json_object_get(defines, "resource"); json_t* uuid_je = json_object_get(defines, "uuid"); json_t* svc_je = json_object_get(defines, "service"); assert( je && json_is_string(je) && strlen(json_string_value(je))); assert( svc_je && json_is_string(svc_je) && strlen(json_string_value(svc_je))); assert( uuid_je && json_is_string(uuid_je) && strlen(json_string_value(uuid_je))); mlt_producer obj = MLT_PRODUCER(MltLoader::pop_mlt_registry(json_string_value(uuid_je))); if (obj == NULL) { mlt_profile profile = mlt_profile_clone(global_profile); obj = mlt_factory_producer(profile, json_string_value(svc_je), json_string_value(je)); #ifdef DEBUG std::cout << mlt_producer_properties(obj); #endif } if ( !obj ) { throw_error_v(ErrorRuntimeLoadFailed, "video producer load failed:%s", json_string_value(je)); } mlt_properties props = mlt_producer_properties(obj); je = json_object_get(defines, "props"); if (je && json_is_object(je) && json_object_size(je)) { json_t* inj = json_object_get(je,"in"), *outj = json_object_get(je,"out"); assert(inj && outj && json_is_integer(inj) && json_is_integer(outj)); mlt_producer_set_in_and_out(obj,json_integer_value(inj), json_integer_value(outj)); void* it = json_object_iter(je); while(it) { const char* k = json_object_iter_key(it); json_t* prop_je = json_object_iter_value(it); it = json_object_iter_next(je, it); if ( json_is_object(prop_je) || json_is_array(prop_je)) continue; if ( !strcmp(k,"in") || !strcmp(k,"out")) continue; switch(prop_je->type) { case JSON_INTEGER: mlt_properties_set_int64(props, k, json_integer_value(prop_je)); break; case JSON_REAL: mlt_properties_set_double(props, k, json_real_value(prop_je)); break; case JSON_STRING: mlt_properties_set(props, k, json_string_value(prop_je)); break; case JSON_TRUE: mlt_properties_set_int(props,k, 1); break; case JSON_FALSE: mlt_properties_set_int(props,k, 0); break; default: break; } } } MltSvcWrap wrap(mlt_producer_service(obj), 1); producer_tmp = obj; parse_filters(); wrap.obj = NULL; return mlt_producer_service(obj); }
static int get_frame( mlt_producer self, mlt_frame_ptr frame, int index ) { mlt_properties properties = MLT_PRODUCER_PROPERTIES(self); context cx = mlt_properties_get_data( properties, "context", NULL ); if ( !cx ) { // Allocate and initialize our context cx = mlt_pool_alloc( sizeof( struct context_s ) ); memset( cx, 0, sizeof( *cx ) ); mlt_properties_set_data( properties, "context", cx, 0, mlt_pool_release, NULL ); cx->self = self; char *profile_name = mlt_properties_get( properties, "profile" ); if ( !profile_name ) profile_name = mlt_properties_get( properties, "mlt_profile" ); mlt_profile profile = mlt_service_profile( MLT_PRODUCER_SERVICE( self ) ); if ( profile_name ) { cx->profile = mlt_profile_init( profile_name ); cx->profile->is_explicit = 1; } else { cx->profile = mlt_profile_clone( profile ); cx->profile->is_explicit = 0; } // Encapsulate a real producer for the resource cx->producer = mlt_factory_producer( cx->profile, NULL, mlt_properties_get( properties, "resource" ) ); if ( ( profile_name && !strcmp( profile_name, "auto" ) ) || mlt_properties_get_int( properties, "autoprofile" ) ) { mlt_profile_from_producer( cx->profile, cx->producer ); mlt_producer_close( cx->producer ); cx->producer = mlt_factory_producer( cx->profile, NULL, mlt_properties_get( properties, "resource" ) ); } // Since we control the seeking, prevent it from seeking on its own mlt_producer_set_speed( cx->producer, 0 ); cx->audio_position = -1; // We will encapsulate a consumer cx->consumer = mlt_consumer_new( cx->profile ); // Do not use _pass_list on real_time so that it defaults to 0 in the absence of // an explicit real_time property. mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( cx->consumer ), "real_time", mlt_properties_get_int( properties, "real_time" ) ); mlt_properties_pass_list( MLT_CONSUMER_PROPERTIES( cx->consumer ), properties, "buffer, prefill, deinterlace_method, rescale" ); // Connect it all together mlt_consumer_connect( cx->consumer, MLT_PRODUCER_SERVICE( cx->producer ) ); mlt_consumer_start( cx->consumer ); } // Generate a frame *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( self ) ); if ( *frame ) { // Seek the producer to the correct place // Calculate our positions double actual_position = (double) mlt_producer_frame( self ); if ( mlt_producer_get_speed( self ) != 0 ) actual_position *= mlt_producer_get_speed( self ); mlt_position need_first = floor( actual_position ); mlt_producer_seek( cx->producer, lrint( need_first * mlt_profile_fps( cx->profile ) / mlt_producer_get_fps( self ) ) ); // Get the nested frame mlt_frame nested_frame = mlt_consumer_rt_frame( cx->consumer ); // Stack the producer and our methods on the nested frame mlt_frame_push_service( *frame, nested_frame ); mlt_frame_push_service( *frame, cx ); mlt_frame_push_get_image( *frame, get_image ); mlt_frame_push_audio( *frame, nested_frame ); mlt_frame_push_audio( *frame, cx ); mlt_frame_push_audio( *frame, get_audio ); // Give the returned frame temporal identity mlt_frame_set_position( *frame, mlt_producer_position( self ) ); // Store the nested frame on the produced frame for destruction mlt_properties frame_props = MLT_FRAME_PROPERTIES( *frame ); mlt_properties_set_data( frame_props, "_producer_consumer.frame", nested_frame, 0, (mlt_destructor) mlt_frame_close, NULL ); // Inform the normalizers about our video properties mlt_properties_set_double( frame_props, "aspect_ratio", mlt_profile_sar( cx->profile ) ); mlt_properties_set_int( frame_props, "width", cx->profile->width ); mlt_properties_set_int( frame_props, "height", cx->profile->height ); mlt_properties_set_int( frame_props, "meta.media.width", cx->profile->width ); mlt_properties_set_int( frame_props, "meta.media.height", cx->profile->height ); mlt_properties_set_int( frame_props, "progressive", cx->profile->progressive ); } // Calculate the next timecode mlt_producer_prepare_next( self ); return 0; }
static mlt_producer create_producer( mlt_profile profile, char *file ) { mlt_producer result = NULL; // 1st Line - check for service:resource handling if ( strchr( file, ':' ) ) { char *temp = strdup( file ); char *service = temp; char *resource = strchr( temp, ':' ); *resource ++ = '\0'; result = mlt_factory_producer( profile, service, resource ); free( temp ); } // 2nd Line preferences if ( result == NULL ) { int i = 0; char *lookup = strdup( file ); char *p = lookup; // Make backup of profile for determining if we need to use 'consumer' producer. mlt_profile backup_profile = mlt_profile_clone( profile ); // We only need to load the dictionary once if ( dictionary == NULL ) { char temp[ 1024 ]; sprintf( temp, "%s/core/loader.dict", mlt_environment( "MLT_DATA" ) ); dictionary = mlt_properties_load( temp ); mlt_factory_register_for_clean_up( dictionary, ( mlt_destructor )mlt_properties_close ); } // Convert the lookup string to lower case while ( *p ) { *p = tolower( *p ); p ++; } // Iterate through the dictionary for ( i = 0; result == NULL && i < mlt_properties_count( dictionary ); i ++ ) { char *name = mlt_properties_get_name( dictionary, i ); if ( fnmatch( name, lookup, 0 ) == 0 ) result = create_from( profile, file, mlt_properties_get_value( dictionary, i ) ); } // Check if the producer changed the profile - xml does this. // The consumer producer does not handle frame rate differences. if ( result && backup_profile->is_explicit && ( profile->width != backup_profile->width || profile->height != backup_profile->height || profile->sample_aspect_num != backup_profile->sample_aspect_num || profile->sample_aspect_den != backup_profile->sample_aspect_den || profile->colorspace != backup_profile->colorspace ) ) { // Restore the original profile attributes. profile->display_aspect_den = backup_profile->display_aspect_den; profile->display_aspect_num = backup_profile->display_aspect_num; profile->frame_rate_den = backup_profile->frame_rate_den; profile->frame_rate_num = backup_profile->frame_rate_num; profile->height = backup_profile->height; profile->progressive = backup_profile->progressive; profile->sample_aspect_den = backup_profile->sample_aspect_den; profile->sample_aspect_num = backup_profile->sample_aspect_num; profile->width = backup_profile->width; // Use the 'consumer' producer. mlt_producer_close( result ); result = mlt_factory_producer( profile, "consumer", file ); } mlt_profile_close( backup_profile ); free( lookup ); } // Finally, try just loading as service if ( result == NULL ) result = mlt_factory_producer( profile, file, NULL ); return result; }