原帖地址: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)的更多相关文章

  1. 最新版ffmpeg源码分析

    最新版ffmpeg源码分析一:框架 (ffmpeg v0.9) 框架 最新版的ffmpeg中发现了一个新的东西:avconv,而且ffmpeg.c与avconv.c一个模样,一研究才发现是libav下 ...

  2. Vue源码分析(二) : Vue实例挂载

    Vue源码分析(二) : Vue实例挂载 author: @TiffanysBear 实例挂载主要是 $mount 方法的实现,在 src/platforms/web/entry-runtime-wi ...

  3. 多线程之美8一 AbstractQueuedSynchronizer源码分析<二>

    目录 AQS的源码分析 该篇主要分析AQS的ConditionObject,是AQS的内部类,实现等待通知机制. 1.条件队列 条件队列与AQS中的同步队列有所不同,结构图如下: 两者区别: 1.链表 ...

  4. Fresco 源码分析(二) Fresco客户端与服务端交互(1) 解决遗留的Q1问题

    4.2 Fresco客户端与服务端的交互(一) 解决Q1问题 从这篇博客开始,我们开始讨论客户端与服务端是如何交互的,这个交互的入口,我们从Q1问题入手(博客按照这样的问题入手,是因为当时我也是从这里 ...

  5. 框架-springmvc源码分析(二)

    框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ...

  6. Tomcat源码分析二:先看看Tomcat的整体架构

    Tomcat源码分析二:先看看Tomcat的整体架构 Tomcat架构图 我们先来看一张比较经典的Tomcat架构图: 从这张图中,我们可以看出Tomcat中含有Server.Service.Conn ...

  7. 十、Spring之BeanFactory源码分析(二)

    Spring之BeanFactory源码分析(二) 前言 在前面我们简单的分析了BeanFactory的结构,ListableBeanFactory,HierarchicalBeanFactory,A ...

  8. external-attacher源码分析(1)-main方法与启动参数分析

    更多 ceph-csi 其他源码分析,请查看下面这篇博文:kubernetes ceph-csi分析目录导航 摘要 ceph-csi分析-external-attacher源码分析.external- ...

  9. SequoiaDB 系列之五 :源码分析之main函数

    好久好久没有写博客了,因为一直要做各种事,工作上的,生活上的,这一下就是半年. 时光如梭. 这两天回头看了看写的博客,感觉都是贻笑大方. 但是还是想坚持把SequoiaDB系列写完. 初步的打算已经确 ...

随机推荐

  1. System.Net.FtpClient改进

    项目用到Ftp,搜了下现有的类库System.Net.FtpClient 貌似比较不错. 一开始用着还行,但是有个FtpServer下有8k多内容,列表需要很久(7.8s)才能刷新出来. 翻源码吧,有 ...

  2. LOJ2362. 「NOIP2016」蚯蚓【单调队列】

    LINK 思路 良心来说这题还挺思维的 我没看题解也不知道要这样维护 把每次斩断的点分别放进两个队列里面 因为要维护增长,所以可以让新进队的节点来一个负增长? 是不是就好了? 然后很容易发现因为在原始 ...

  3. POJ1733 Parity game 【带权并查集】*

    POJ1733 Parity game Description Now and then you play the following game with your friend. Your frie ...

  4. lua不支持的泛型方法

    1.没有泛型约束 2.缺少带约束的泛型参数 3.泛型约束必须为class /// <summary> /// 不支持生成lua的泛型方法(没有泛型约束) /// </summary& ...

  5. nomad 安装(单机)试用

    备注:     nomad  可以实现基础设施的调度管理,类似kubernetes ,但是在多云以及多平台支持上比较好,     还是hashicrop 工具出品的,很不错,同时本地测试因为使用默认的 ...

  6. java I/O进程控制,重定向 演示样例代码

    java I/O进程控制,重定向 演示样例代码 package org.rui.io.util; import java.io.*; /** * 标准I/O重定向 */ public class Re ...

  7. 如何点焊过的镍片再次焊接到 PCBA 上?

    如何将点焊过的镍片再次焊接到 PCBA 上? 在 PCBA 上贴了镍片再点焊,这样的制造工艺可以大大减少人工处理,提高生产通过率. 由于种种原因,有些机器可能有故障需要维修,而且电池又需要拆下来,才能 ...

  8. [LeetCode系列]最大容器问题

    给定n个数: a1, a2, ... , an. 代表着(i, ai)个点, 连接这些点与对应的(i, 0), 我们可以得到n条线. 请在这n条线中找出2条, 使得这两条线和x轴构成的容器能够容纳最多 ...

  9. oracle 之 控制oracle RAC 进行并行运算

    RAC的一大优点就是可以跨节点进行并行计算,那么如何控制并行运算?这就是这篇文章要讨论的内容. 10 g 中: 合理设置跨节点并行,需要先设置一些参数:instance_groups:这个参数主要是设 ...

  10. 数组去重(初识ES6)

    较常见的一问题:数组去重. 方法一:利用hash数组的原理 var arr=[1,3,3,4,5,5,6,6,7,8,69,8,99,9,0,]; function unique(arry){ var ...