ffmpeg源码分析二:main函数和transcode函数 (转2)
原帖地址:http://blog.csdn.net/austinblog/article/details/24804455
首先从main函数看起,关键解释部分已加注释,该函数在ffmpeg.c文件中。代码如下:
int main(int argc, char **argv)
{
int ret;
int64_t ti;
// 注册清理回调函数
register_exit(ffmpeg_cleanup); setvbuf(stderr,NULL,_IONBF,); /* win32 runtime needs this */ av_log_set_flags(AV_LOG_SKIP_REPEATED);
parse_loglevel(argc, argv, options); if(argc> && !strcmp(argv[], "-d")){
run_as_daemon=;
av_log_set_callback(log_callback_null);
argc--;
argv++;
} // 注册组件们
avcodec_register_all();
#if CONFIG_AVDEVICE
avdevice_register_all();
#endif
avfilter_register_all();
av_register_all();
avformat_network_init(); show_banner(argc, argv, options); term_init(); /* parse options and open all input/output files */
// 解析参数,并且打开输入输出文件
ret = ffmpeg_parse_options(argc, argv);
if (ret < )
exit_program(); if (nb_output_files <= && nb_input_files == ) {
show_usage();
av_log(NULL, AV_LOG_WARNING, "Use -h to get full help or, even better, run 'man %s'\n", program_name);
exit_program();
} /* file converter / grab */
if (nb_output_files <= ) {
av_log(NULL, AV_LOG_FATAL, "At least one output file must be specified\n");
exit_program();
} // if (nb_input_files == 0) {
// av_log(NULL, AV_LOG_FATAL, "At least one input file must be specified\n");
// exit_program(1);
// } current_time = ti = getutime();
// 音视频转换函数
if (transcode() < )
exit_program();
ti = getutime() - ti;
if (do_benchmark) {
printf("bench: utime=%0.3fs\n", ti / 1000000.0);
}
av_log(NULL, AV_LOG_DEBUG, "%"PRIu64" frames successfully decoded, %"PRIu64" decoding errors\n",
decode_error_stat[], decode_error_stat[]);
if ((decode_error_stat[] + decode_error_stat[]) * max_error_rate < decode_error_stat[])
exit_program(); exit_program(received_nb_signals ? : main_return_code);
return main_return_code;
}
下面阅读transcode函数:
static int transcode(void)
{
int ret, i;
AVFormatContext *os;
OutputStream *ost;
InputStream *ist;
int64_t timer_start; // 初始化,打开所有输出流的编码器,打开所有输入流的解码器,写入所有输出文件的文件头。后面详细介绍。
ret = transcode_init();
if (ret < )
goto fail; if (stdin_interaction) {
av_log(NULL, AV_LOG_INFO, "Press [q] to stop, [?] for help\n");
} timer_start = av_gettime(); #if HAVE_PTHREADS
if ((ret = init_input_threads()) < )
goto fail;
#endif // 循环,直到收到系统信号才退出 。
while (!received_sigterm) {
int64_t cur_time= av_gettime(); /* if 'q' pressed, exits */
if (stdin_interaction)
if (check_keyboard_interaction(cur_time) < )
break; /* check if there's any stream where output is still needed */
if (!need_output()) {
av_log(NULL, AV_LOG_VERBOSE, "No more output streams to write to, finishing.\n");
break;
} // 具体的转换工作,后面将详细介绍。
ret = transcode_step();
if (ret < ) {
if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
continue; av_log(NULL, AV_LOG_ERROR, "Error while filtering.\n");
break;
} /* dump report by using the output first video and audio streams */
print_report(, timer_start, cur_time);
}
#if HAVE_PTHREADS
free_input_threads();
#endif // 文件处理完了,把缓冲中剩余的数据写到输出文件中。
/* at the end of stream, we must flush the decoder buffers */
for (i = ; i < nb_input_streams; i++) {
ist = input_streams[i];
if (!input_files[ist->file_index]->eof_reached && ist->decoding_needed) {
output_packet(ist, NULL);
}
}
flush_encoders(); term_exit(); /* write the trailer if needed and close file */
// 为输出文件写文件尾(有的不需要)。
for (i = ; i < nb_output_files; i++) {
os = output_files[i]->ctx;
av_write_trailer(os);
} /* dump report by using the first video and audio streams */
print_report(, timer_start, av_gettime()); // 关闭所有编码器。
/* close each encoder */
for (i = ; i < nb_output_streams; i++) {
ost = output_streams[i];
if (ost->encoding_needed) {
av_freep(&ost->st->codec->stats_in);
avcodec_close(ost->st->codec);
}
} // 关闭所有解码器。
/* close each decoder */
for (i = ; i < nb_input_streams; i++) {
ist = input_streams[i];
if (ist->decoding_needed) {
avcodec_close(ist->st->codec);
if (ist->hwaccel_uninit)
ist->hwaccel_uninit(ist->st->codec);
}
} /* finished ! */
ret = ; fail:
#if HAVE_PTHREADS
free_input_threads();
#endif if (output_streams) {
for (i = ; i < nb_output_streams; i++) {
ost = output_streams[i];
if (ost) {
if (ost->stream_copy)
av_freep(&ost->st->codec->extradata);
if (ost->logfile) {
fclose(ost->logfile);
ost->logfile = NULL;
}
av_freep(&ost->st->codec->subtitle_header);
av_freep(&ost->forced_kf_pts);
av_freep(&ost->apad);
av_dict_free(&ost->opts);
av_dict_free(&ost->swr_opts);
av_dict_free(&ost->resample_opts);
}
}
}
return ret;
}
ffmpeg源码分析二:main函数和transcode函数 (转2)的更多相关文章
- 最新版ffmpeg源码分析
最新版ffmpeg源码分析一:框架 (ffmpeg v0.9) 框架 最新版的ffmpeg中发现了一个新的东西:avconv,而且ffmpeg.c与avconv.c一个模样,一研究才发现是libav下 ...
- Vue源码分析(二) : Vue实例挂载
Vue源码分析(二) : Vue实例挂载 author: @TiffanysBear 实例挂载主要是 $mount 方法的实现,在 src/platforms/web/entry-runtime-wi ...
- 多线程之美8一 AbstractQueuedSynchronizer源码分析<二>
目录 AQS的源码分析 该篇主要分析AQS的ConditionObject,是AQS的内部类,实现等待通知机制. 1.条件队列 条件队列与AQS中的同步队列有所不同,结构图如下: 两者区别: 1.链表 ...
- Fresco 源码分析(二) Fresco客户端与服务端交互(1) 解决遗留的Q1问题
4.2 Fresco客户端与服务端的交互(一) 解决Q1问题 从这篇博客开始,我们开始讨论客户端与服务端是如何交互的,这个交互的入口,我们从Q1问题入手(博客按照这样的问题入手,是因为当时我也是从这里 ...
- 框架-springmvc源码分析(二)
框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ...
- Tomcat源码分析二:先看看Tomcat的整体架构
Tomcat源码分析二:先看看Tomcat的整体架构 Tomcat架构图 我们先来看一张比较经典的Tomcat架构图: 从这张图中,我们可以看出Tomcat中含有Server.Service.Conn ...
- 十、Spring之BeanFactory源码分析(二)
Spring之BeanFactory源码分析(二) 前言 在前面我们简单的分析了BeanFactory的结构,ListableBeanFactory,HierarchicalBeanFactory,A ...
- external-attacher源码分析(1)-main方法与启动参数分析
更多 ceph-csi 其他源码分析,请查看下面这篇博文:kubernetes ceph-csi分析目录导航 摘要 ceph-csi分析-external-attacher源码分析.external- ...
- SequoiaDB 系列之五 :源码分析之main函数
好久好久没有写博客了,因为一直要做各种事,工作上的,生活上的,这一下就是半年. 时光如梭. 这两天回头看了看写的博客,感觉都是贻笑大方. 但是还是想坚持把SequoiaDB系列写完. 初步的打算已经确 ...
随机推荐
- discuz数据库迁移,改密码后,相关配置文件修改
网上看到这篇文章,觉得有用就收藏下 网站系统需要修改的位置有两处 Discuz 和 UC-center ①路径:/wwwroot/config/config_global.php 这个根据你网站安装的 ...
- 命令“"xxx.exe" xxx”已退出,代码为 n。这些错误是什么意思?(3 / 123 / 9009)
命令“”xxx.exe” xxx”已退出,代码为 n. 我们在 cmd 中输入常见命令的时候,如果命令输入错误或使用错误,cmd 中会提示错误原因,帮助我们定位并解决问题.然而如果相同的命令放到了 V ...
- 重温CLR(九) 接口
对于多继承(multiple inheritance)的概念,许多程序员并不陌生,他是指一个类从两个或多个基类派生的能力.例如,假定TransmitData类的作用是发送数据,ReceiveData类 ...
- HTML CSS 表格换行禁止 超出指定长度自动截断
word-break:keep-all; white-space:nowrap; overflow:hidden; min-width:30px; max-width:100px;
- maven创建多模块项目
在eclipse下构建maven项目,该项目由多个子模块组成. 1.创建一个父项目 NEW -->project-->maven-->maven Project,点击下一步,进入ne ...
- html页面设置一个跟随鼠标移动的DIV(jQuery实现)
说明业务:鼠标放到某个标签上,显示一个div,并跟随鼠标移动 html页面(直接放body里面): <a href="#" id="'+data[i].refund ...
- Liquibase 了解
Liquibase 是一个用于跟踪.管理和应用数据库变化的开源的数据库重构工具.它将所有数据库的变化(包括结构和数据)都保存在 XML 文件中,便于版本控制. Liquibase 具备如下特性: 不依 ...
- docker windows 2016 安装测试
1. 安装方式 powershell Install-Module-NameDockerMsftProvider-RepositoryPSGallery-Force Install-Pack ...
- 数据库视图View的使用
一.视图的概念: 概念: 视图是指计算机数据库中的视图,是一个虚拟表,其内容由查询定义.同真实的表一样,视图包含一系列带有名称的列和行数据.但是,视图并不在数据库中以存储的数据值集形式存在.行和列数据 ...
- 搭建基于hyperledger fabric的联盟社区(二) --环境配置
接下来讲一下在本地测试区块链网络的过程.我要部署的是2peer+1orderer架构,所以需要准备三台虚拟机,为了方便起见可以先把一台配置好,然后复制出剩余两台即可.搭建虚拟机我用的是virtualb ...