MLT媒体程序框架02:源码剖析

2024-04-11 16:52

本文主要是介绍MLT媒体程序框架02:源码剖析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

以MLT自带的Melt命令行工具源码为例
去掉一些不重要的代码

melt.c

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;int is_abort = 0;int is_getc = 0;int error = 0;mlt_profile backup_profile;mlt_repository repo = NULL;const char *repo_path = NULL;int is_consumer_explicit = 0;int is_setlocale = 0;// Handle abnormal exit situations.signal(SIGSEGV, abnormal_exit_handler);signal(SIGILL, abnormal_exit_handler);signal(SIGABRT, abnormal_exit_handler);// 设置地区,不设置默认是中国// 在程序中,区域是影响程序语言处理方式的环境变量,比如日期,时间,货币,数字和字符串的格式等。for (i = 1; i < argc; i++) {if (!strcmp(argv[i], "-setlocale")) {is_setlocale = 1;break;}}for (i = 1; i < argc; i++) {// Check for serialisation switchif (!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 optionelse if (!strcmp(argv[i], "-profile")) {// Construct the factoryif (!repo)repo = setup_factory(repo_path, is_setlocale);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;}// 查找,会打印对应的service种类和信息// Look for the query optionelse if (!strcmp(argv[i], "-query")) {// Construct the factoryif (!repo)repo = setup_factory(repo_path, is_setlocale);const char *pname = argv[++i];if (pname && pname[0] != '-') {if (!strcmp(pname, "consumers") || !strcmp(pname, "consumer"))query_services(repo, mlt_service_consumer_type);else if (!strcmp(pname, "filters") || !strcmp(pname, "filter"))query_services(repo, mlt_service_filter_type);else if (!strcmp(pname, "links") || !strcmp(pname, "link"))query_services(repo, mlt_service_link_type);else if (!strcmp(pname, "producers") || !strcmp(pname, "producer"))query_services(repo, mlt_service_producer_type);else if (!strcmp(pname, "transitions") || !strcmp(pname, "transition"))query_services(repo, mlt_service_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,mlt_service_consumer_type,"consumer",strchr(pname, '=') + 1);else if (!strncmp(pname, "filter=", 7))query_metadata(repo, mlt_service_filter_type, "filter", strchr(pname, '=') + 1);else if (!strncmp(pname, "link=", 5))query_metadata(repo, mlt_service_link_type, "link", strchr(pname, '=') + 1);else if (!strncmp(pname, "producer=", 9))query_metadata(repo,mlt_service_producer_type,"producer",strchr(pname, '=') + 1);else if (!strncmp(pname, "transition=", 11))query_metadata(repo,mlt_service_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);elsegoto query_all;} else {query_all:query_services(repo, mlt_service_consumer_type);query_services(repo, mlt_service_filter_type);query_services(repo, mlt_service_link_type);query_services(repo, mlt_service_producer_type);query_services(repo, mlt_service_transition_type);fprintf(stdout,"# You can query the metadata for a specific service using:\n""# -query <type>=<identifier>\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], "-quiet")) {is_silent = 1;mlt_log_set_level(MLT_LOG_QUIET);} else if (!strcmp(argv[i], "-verbose")) {mlt_log_set_level(MLT_LOG_VERBOSE);} else if (!strcmp(argv[i], "-timings")) {mlt_log_set_level(MLT_LOG_TIMINGS);} else if (!strcmp(argv[i], "-version") || !strcmp(argv[i], "--version")) {fprintf(stdout,"%s " VERSION "\n""Copyright (C) 2002-2023 Meltytech, LLC\n""<https://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);} else if (!strcmp(argv[i], "-abort")) {is_abort = 1;} else if (!strcmp(argv[i], "-getc")) {is_getc = 1;} else if (!repo && !strcmp(argv[i], "-repository")) {if (i + 1 < argc && argv[i + 1][0] != '-')repo_path = argv[++i];} else if (!strcmp(argv[i], "-consumer")) {is_consumer_explicit = 1;}}if (!is_silent && !isatty(STDIN_FILENO) && !is_progress)is_progress = 1;// Construct the factoryif (!repo)repo = setup_factory(repo_path, is_setlocale);// Create profile if not set explicitlyif (getenv("MLT_PROFILE"))// 根据环境变量去找到对应的profileprofile = mlt_profile_init(NULL);if (profile == NULL)profile = mlt_profile_init(NULL);elseprofile->is_explicit = 1;// 备份profile,然后加载consumer,如果profile在加载consumer的时候发生了改变,则表明这时候的profile信息是精确的// Look for the consumer option to load profile settings from consumer propertiesbackup_profile = mlt_profile_clone(profile);if (load_consumer(&consumer, profile, argc, argv) != EXIT_SUCCESS)goto exit_factory;// 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);backup_profile = NULL;// 除了第一个参数,把后面的参数都传递到factory中,用于生产producer// Get melt producerif (argc > 1)melt = mlt_factory_producer(profile, "melt", &argv[1]);if (melt) {// Generate an automatic profile if needed.if (!profile->is_explicit) {mlt_producer first_producer = mlt_properties_get_data(MLT_PRODUCER_PROPERTIES(melt),"first_producer",NULL);mlt_profile_from_producer(profile, first_producer);mlt_consumer melt_consumer = MLT_CONSUMER(mlt_service_consumer(MLT_PRODUCER_SERVICE(melt)));if (melt_consumer)mlt_consumer_connect(melt_consumer, NULL);mlt_producer_close(melt);melt = mlt_factory_producer(profile, "melt", &argv[1]);}double scale = mlt_properties_get_double(MLT_CONSUMER_PROPERTIES(consumer), "scale");if (scale > 0.0) {// 设置缩放set_preview_scale(&profile, &backup_profile, scale);}// 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 attachedif (!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 sdlif (store == NULL && consumer == NULL)consumer = create_consumer(profile, NULL);}// Set transport properties on consumer and produderif (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 (is_getc)mlt_properties_set_int(MLT_CONSUMER_PROPERTIES(consumer), "melt_getc", is_getc);}if (argc > 1 && melt != NULL && mlt_producer_get_length(melt) > 0) {// Parse the argumentsfor (i = 1; i < argc; i++) {if (!strcmp(argv[i], "-jack") && consumer) {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 propertiesmlt_properties melt_props = MLT_PRODUCER_PROPERTIES(melt);mlt_properties properties = MLT_CONSUMER_PROPERTIES(consumer);if (is_consumer_explicit) {// Apply group settingsmlt_properties group = mlt_properties_get_data(melt_props, "group", 0);// properties继承mlt_properties_inherit(properties, group);}int in = mlt_properties_get_int(properties, "in");int out = mlt_properties_get_int(properties, "out");if (in > 0 || out > 0) {if (out == 0) {out = mlt_producer_get_length(melt) - 1;}mlt_producer_set_in_and_out(melt, in, out);mlt_producer_seek(melt, 0);}// Connect consumer to meltmlt_consumer_connect(consumer, MLT_PRODUCER_SERVICE(melt));// Start the consumermlt_events_listen(properties,consumer,"consumer-fatal-error",(mlt_listener) on_fatal_error);if (mlt_consumer_start(consumer) == 0) {// Try to exit gracefully upon these signalssignal(SIGINT, stop_handler);signal(SIGTERM, stop_handler);
#ifndef _WIN32signal(SIGHUP, stop_handler);signal(SIGPIPE, stop_handler);
#endif// Transport functionalitytransport(melt, consumer);// Stop the consumermlt_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 servicesif (consumer) {error = mlt_properties_get_int(MLT_CONSUMER_PROPERTIES(consumer), "melt_error");mlt_consumer_connect(consumer, NULL);if (!is_abort)mlt_events_fire(MLT_CONSUMER_PROPERTIES(consumer),"consumer-cleanup",mlt_event_data_none());}if (is_abort)return error;// Close the producerif (melt != NULL)mlt_producer_close(melt);// Close the consumerif (consumer != NULL)mlt_consumer_close(consumer);// Close the factorymlt_profile_close(profile);mlt_profile_close(backup_profile);exit_factory:// Workaround qmelt on OS X from crashing at exit.
#if !defined(__MACH__) || !defined(QT_GUI_LIB)mlt_factory_close();
#endifreturn error;
}

这篇关于MLT媒体程序框架02:源码剖析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/894651

相关文章

python获取指定名字的程序的文件路径的两种方法

《python获取指定名字的程序的文件路径的两种方法》本文主要介绍了python获取指定名字的程序的文件路径的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 最近在做项目,需要用到给定一个程序名字就可以自动获取到这个程序在Windows系统下的绝对路径,以下

GSON框架下将百度天气JSON数据转JavaBean

《GSON框架下将百度天气JSON数据转JavaBean》这篇文章主要为大家详细介绍了如何在GSON框架下实现将百度天气JSON数据转JavaBean,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录前言一、百度天气jsON1、请求参数2、返回参数3、属性映射二、GSON属性映射实战1、类对象映

深度剖析SpringBoot日志性能提升的原因与解决

《深度剖析SpringBoot日志性能提升的原因与解决》日志记录本该是辅助工具,却为何成了性能瓶颈,SpringBoot如何用代码彻底破解日志导致的高延迟问题,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言第一章:日志性能陷阱的底层原理1.1 日志级别的“双刃剑”效应1.2 同步日志的“吞吐量杀手”

基于Python编写自动化邮件发送程序(进阶版)

《基于Python编写自动化邮件发送程序(进阶版)》在数字化时代,自动化邮件发送功能已成为企业和个人提升工作效率的重要工具,本文将使用Python编写一个简单的自动化邮件发送程序,希望对大家有所帮助... 目录理解SMTP协议基础配置开发环境构建邮件发送函数核心逻辑实现完整发送流程添加附件支持功能实现htm

C#控制台程序同步调用WebApi实现方式

《C#控制台程序同步调用WebApi实现方式》控制台程序作为Job时,需同步调用WebApi以确保获取返回结果后执行后续操作,否则会引发TaskCanceledException异常,同步处理可避免异... 目录同步调用WebApi方法Cls001类里面的写法总结控制台程序一般当作Job使用,有时候需要控制

解决若依微服务框架启动报错的问题

《解决若依微服务框架启动报错的问题》Invalidboundstatement错误通常由MyBatis映射文件未正确加载或Nacos配置未读取导致,需检查XML的namespace与方法ID是否匹配,... 目录ruoyi-system模块报错报错详情nacos文件目录总结ruoyi-systnGLNYpe

Python Web框架Flask、Streamlit、FastAPI示例详解

《PythonWeb框架Flask、Streamlit、FastAPI示例详解》本文对比分析了Flask、Streamlit和FastAPI三大PythonWeb框架:Flask轻量灵活适合传统应用... 目录概述Flask详解Flask简介安装和基础配置核心概念路由和视图模板系统数据库集成实际示例Stre

Olingo分析和实践之OData框架核心组件初始化(关键步骤)

《Olingo分析和实践之OData框架核心组件初始化(关键步骤)》ODataSpringBootService通过初始化OData实例和服务元数据,构建框架核心能力与数据模型结构,实现序列化、URI... 目录概述第一步:OData实例创建1.1 OData.newInstance() 详细分析1.1.1

golang程序打包成脚本部署到Linux系统方式

《golang程序打包成脚本部署到Linux系统方式》Golang程序通过本地编译(设置GOOS为linux生成无后缀二进制文件),上传至Linux服务器后赋权执行,使用nohup命令实现后台运行,完... 目录本地编译golang程序上传Golang二进制文件到linux服务器总结本地编译Golang程序

使用Docker构建Python Flask程序的详细教程

《使用Docker构建PythonFlask程序的详细教程》在当今的软件开发领域,容器化技术正变得越来越流行,而Docker无疑是其中的佼佼者,本文我们就来聊聊如何使用Docker构建一个简单的Py... 目录引言一、准备工作二、创建 Flask 应用程序三、创建 dockerfile四、构建 Docker