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系列写完. 初步的打算已经确 ...
随机推荐
- 神器如 dnSpy,无需源码也能修改 .NET 程序
dnSpy 是 0xd4d 开发的 .NET 程序调试神器. 说它是神器真的毫不为过!它能在完全没有源码的情况下即时调试程序,甚至还能修改程序!本文讲向大家介绍如何使用 dnSpy 修改 .NET 程 ...
- Web API的发布问题
配置“ISAPI 和 CGI 限制”的4.0版本设置为允许,要不然出现“由于 Web 服务器上的“ISAPI 和 CGI 限制”列表设置,无法提供您请求的页面.”的错误. “An error has ...
- [LOJ6261]一个人的高三楼
loj description 给你一个长度为\(n\)的数列\(a_i\),求它的\(k\)次前缀和模\(998244353\).(就是做\(k\)次前缀和后的数列) \(n\le10^5,k\le ...
- 解决js代码中加入alert()就成功执行,不加就不对的问题!
问题: jquery中的$(document).ready(function(){})中调用两个方法(1)利用ajax请求去后台查图书类别的方法(2)当页面上利用图书类别去查询图书返回页面,让图书类别 ...
- 基于spring的异常一站式解决方案
https://segmentfault.com/a/1190000006749441#articleHeader4 https://lrwinx.github.io/2016/04/28/%E5%A ...
- js的delegate回调例子
暂时没发现有具体的实际用处,先记录下 <!DOCTYPE html> <html> <head lang="en"> <meta char ...
- Oracle拆分字符串函数与执行调用
本函数可以将“目标字符串”以“指定字符串”进行拆分,并通过表结构返回结果.代码如下: ); CREATE OR REPLACE FUNCTION splitstr(p_string IN VARCHA ...
- linux tcp server demo
#include <sys/types.h> #include <sys/socket.h> #include <string.h> #include <ne ...
- Java报错 -- The public type c must be defined in its own file
出现The public type c must be defined in its own file这个问题,是由于定义的JAVA类同文件名不一致 你的文件里很可能有两个 public 的类,而Ja ...
- mysql 下字符集知识汇总
Do not issue the query set names with Connector/J, as the driver will not detect that the character ...