这个篇文档主要对ffmpeg  命令分析:主要分析ffmpeg 程序主要流程:

1. 分析命令行函数,解析出输入文件及输出文件

ffmpeg_parse_option

int ffmpeg_parse_options(int argc, char **argv)
{OptionParseContext octx;uint8_t error[128];int ret;memset(&octx, 0, sizeof(octx));/* split the commandline into an internal representation */ret = split_commandline(&octx, argc, argv, options, groups,FF_ARRAY_ELEMS(groups));if (ret < 0) {av_log(NULL, AV_LOG_FATAL, "Error splitting the argument list: ");goto fail;}/* apply global options */ret = parse_optgroup(NULL, &octx.global_opts);if (ret < 0) {av_log(NULL, AV_LOG_FATAL, "Error parsing global options: ");goto fail;}/* configure terminal and setup signal handlers */term_init();/* open input files */ret = open_files(&octx.groups[GROUP_INFILE], "input", open_input_file);if (ret < 0) {av_log(NULL, AV_LOG_FATAL, "Error opening input files: ");goto fail;}/* create the complex filtergraphs */ret = init_complex_filters();if (ret < 0) {av_log(NULL, AV_LOG_FATAL, "Error initializing complex filters.\n");goto fail;}/* open output files */ret = open_files(&octx.groups[GROUP_OUTFILE], "output", open_output_file);if (ret < 0) {av_log(NULL, AV_LOG_FATAL, "Error opening output files: ");goto fail;}check_filter_outputs();fail:uninit_parse_context(&octx);if (ret < 0) {av_strerror(ret, error, sizeof(error));av_log(NULL, AV_LOG_FATAL, "%s\n", error);}return ret;
}

2. transcode 转码处理

static int transcode(void)
{int ret, i;AVFormatContext *os;OutputStream *ost;InputStream *ist;int64_t timer_start;int64_t total_packets_written = 0;ret = transcode_init();     // 转码初始化if (ret < 0)goto fail;if (stdin_interaction) {av_log(NULL, AV_LOG_INFO, "Press [q] to stop, [?] for help\n");}timer_start = av_gettime_relative();#if HAVE_THREADSif ((ret = init_input_threads()) < 0)goto fail;
#endifwhile (!received_sigterm) {int64_t cur_time= av_gettime_relative();/* if 'q' pressed, exits */if (stdin_interaction)if (check_keyboard_interaction(cur_time) < 0)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 < 0 && ret != AVERROR_EOF) {av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret));break;}/* dump report by using the output first video and audio streams */print_report(0, timer_start, cur_time);}
#if HAVE_THREADSfree_input_threads();
#endif/* at the end of stream, we must flush the decoder buffers */for (i = 0; i < nb_input_streams; i++) {ist = input_streams[i];if (!input_files[ist->file_index]->eof_reached) {process_input_packet(ist, NULL, 0);}}flush_encoders();term_exit();/* write the trailer if needed and close file */for (i = 0; i < nb_output_files; i++) {os = output_files[i]->ctx;if (!output_files[i]->header_written) {av_log(NULL, AV_LOG_ERROR,"Nothing was written into output file %d (%s), because ""at least one of its streams received no packets.\n",i, os->url);continue;}if ((ret = av_write_trailer(os)) < 0) {av_log(NULL, AV_LOG_ERROR, "Error writing trailer of %s: %s\n", os->url, av_err2str(ret));if (exit_on_error)exit_program(1);}}/* dump report by using the first video and audio streams */print_report(1, timer_start, av_gettime_relative());/* close each encoder */for (i = 0; i < nb_output_streams; i++) {ost = output_streams[i];if (ost->encoding_needed) {av_freep(&ost->enc_ctx->stats_in);}total_packets_written += ost->packets_written;if (!ost->packets_written && (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT_STREAM)) {av_log(NULL, AV_LOG_FATAL, "Empty output on stream %d.\n", i);exit_program(1);}}if (!total_packets_written && (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT)) {av_log(NULL, AV_LOG_FATAL, "Empty output\n");exit_program(1);}/* close each decoder */for (i = 0; i < nb_input_streams; i++) {ist = input_streams[i];if (ist->decoding_needed) {avcodec_close(ist->dec_ctx);if (ist->hwaccel_uninit)ist->hwaccel_uninit(ist->dec_ctx);}}hw_device_free_all();/* finished ! */ret = 0;fail:
#if HAVE_THREADSfree_input_threads();
#endifif (output_streams) {for (i = 0; i < nb_output_streams; i++) {ost = output_streams[i];if (ost) {if (ost->logfile) {if (fclose(ost->logfile))av_log(NULL, AV_LOG_ERROR,"Error closing logfile, loss of information possible: %s\n",av_err2str(AVERROR(errno)));ost->logfile = NULL;}av_freep(&ost->forced_kf_pts);av_freep(&ost->apad);av_freep(&ost->disposition);av_dict_free(&ost->encoder_opts);av_dict_free(&ost->sws_dict);av_dict_free(&ost->swr_opts);av_dict_free(&ost->resample_opts);}}}return ret;
}

2.1  transcode_step     // 转换流程。
               process_input
                      process_input_packet

/* pkt = NULL means EOF (needed to flush decoder buffers) */
static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eof)
{int ret = 0, i;int repeating = 0;int eof_reached = 0;AVPacket avpkt;if (!ist->saw_first_ts) {ist->dts = ist->st->avg_frame_rate.num ? - ist->dec_ctx->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0;ist->pts = 0;if (pkt && pkt->pts != AV_NOPTS_VALUE && !ist->decoding_needed) {ist->dts += av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q);ist->pts = ist->dts; //unused but better to set it to a value thats not totally wrong}ist->saw_first_ts = 1;}if (ist->next_dts == AV_NOPTS_VALUE)ist->next_dts = ist->dts;if (ist->next_pts == AV_NOPTS_VALUE)ist->next_pts = ist->pts;if (!pkt) {/* EOF handling */av_init_packet(&avpkt);avpkt.data = NULL;avpkt.size = 0;} else {avpkt = *pkt;}if (pkt && pkt->dts != AV_NOPTS_VALUE) {ist->next_dts = ist->dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);if (ist->dec_ctx->codec_type != AVMEDIA_TYPE_VIDEO || !ist->decoding_needed)ist->next_pts = ist->pts = ist->dts;}// while we have more to decode or while the decoder did output something on EOFwhile (ist->decoding_needed) {int64_t duration_dts = 0;int64_t duration_pts = 0;int got_output = 0;int decode_failed = 0;ist->pts = ist->next_pts;ist->dts = ist->next_dts;switch (ist->dec_ctx->codec_type) {case AVMEDIA_TYPE_AUDIO:ret = decode_audio    (ist, repeating ? NULL : &avpkt, &got_output,&decode_failed);break;case AVMEDIA_TYPE_VIDEO:ret = decode_video    (ist, repeating ? NULL : &avpkt, &got_output, &duration_pts, !pkt,&decode_failed);if (!repeating || !pkt || got_output) {if (pkt && pkt->duration) {duration_dts = av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q);} else if(ist->dec_ctx->framerate.num != 0 && ist->dec_ctx->framerate.den != 0) {int ticks= av_stream_get_parser(ist->st) ? av_stream_get_parser(ist->st)->repeat_pict+1 : ist->dec_ctx->ticks_per_frame;duration_dts = ((int64_t)AV_TIME_BASE *ist->dec_ctx->framerate.den * ticks) /ist->dec_ctx->framerate.num / ist->dec_ctx->ticks_per_frame;}if(ist->dts != AV_NOPTS_VALUE && duration_dts) {ist->next_dts += duration_dts;}elseist->next_dts = AV_NOPTS_VALUE;}if (got_output) {if (duration_pts > 0) {ist->next_pts += av_rescale_q(duration_pts, ist->st->time_base, AV_TIME_BASE_Q);} else {ist->next_pts += duration_dts;}}break;case AVMEDIA_TYPE_SUBTITLE:if (repeating)break;ret = transcode_subtitles(ist, &avpkt, &got_output, &decode_failed);if (!pkt && ret >= 0)ret = AVERROR_EOF;break;default:return -1;}if (ret == AVERROR_EOF) {eof_reached = 1;break;}if (ret < 0) {if (decode_failed) {av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d: %s\n",ist->file_index, ist->st->index, av_err2str(ret));} else {av_log(NULL, AV_LOG_FATAL, "Error while processing the decoded ""data for stream #%d:%d\n", ist->file_index, ist->st->index);}if (!decode_failed || exit_on_error)exit_program(1);break;}if (got_output)ist->got_output = 1;if (!got_output)break;// During draining, we might get multiple output frames in this loop.// ffmpeg.c does not drain the filter chain on configuration changes,// which means if we send multiple frames at once to the filters, and// one of those frames changes configuration, the buffered frames will// be lost. This can upset certain FATE tests.// Decode only 1 frame per call on EOF to appease these FATE tests.// The ideal solution would be to rewrite decoding to use the new// decoding API in a better way.if (!pkt)break;repeating = 1;}/* after flushing, send an EOF on all the filter inputs attached to the stream *//* except when looping we need to flush but not to send an EOF */if (!pkt && ist->decoding_needed && eof_reached && !no_eof) {int ret = send_filter_eof(ist);if (ret < 0) {av_log(NULL, AV_LOG_FATAL, "Error marking filters as finished\n");exit_program(1);}}/* handle stream copy */if (!ist->decoding_needed && pkt) {ist->dts = ist->next_dts;switch (ist->dec_ctx->codec_type) {case AVMEDIA_TYPE_AUDIO:av_assert1(pkt->duration >= 0);if (ist->dec_ctx->sample_rate) {ist->next_dts += ((int64_t)AV_TIME_BASE * ist->dec_ctx->frame_size) /ist->dec_ctx->sample_rate;} else {ist->next_dts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q);}break;case AVMEDIA_TYPE_VIDEO:if (ist->framerate.num) {// TODO: Remove work-around for c99-to-c89 issue 7AVRational time_base_q = AV_TIME_BASE_Q;int64_t next_dts = av_rescale_q(ist->next_dts, time_base_q, av_inv_q(ist->framerate));ist->next_dts = av_rescale_q(next_dts + 1, av_inv_q(ist->framerate), time_base_q);} else if (pkt->duration) {ist->next_dts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q);} else if(ist->dec_ctx->framerate.num != 0) {int ticks= av_stream_get_parser(ist->st) ? av_stream_get_parser(ist->st)->repeat_pict + 1 : ist->dec_ctx->ticks_per_frame;ist->next_dts += ((int64_t)AV_TIME_BASE *ist->dec_ctx->framerate.den * ticks) /ist->dec_ctx->framerate.num / ist->dec_ctx->ticks_per_frame;}break;}ist->pts = ist->dts;ist->next_pts = ist->next_dts;}for (i = 0; i < nb_output_streams; i++) {OutputStream *ost = output_streams[i];if (!check_output_constraints(ist, ost) || ost->encoding_needed)continue;do_streamcopy(ist, ost, pkt);  // packet 拷贝到输出文件}return !eof_reached;
}

3. do_streamcopy

do_streamcopy
    output_packet
        write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue)
            av_interleaved_write_frame
                write_packets_common
                    write_packet(AVFormatContext *s, AVPacket *pkt)
                        s->oformat->write_packet
                             AVOutputFormat *oformat; mux  中函数:

ffmpeg 之ffmpeg 整理流程分析相关推荐

  1. ffmpeg.c学习-1-框架分析及命令行解析

    ffmpeg.c学习-1-框架分析及命令行解析 目录 掌握ffmpeg.c的意义 ffmpeg框架分析 ffmpeg对应的⽂件 ffmpeg程序框架流程 命令行解析 1. 掌握ffmpeg.c的意义 ...

  2. FFmpeg简述,源码分析,录制/压缩/水印/剪切/旋转/滤镜/美颜/上传视频等(CPU软编码和解码)

    > ffmpeg源码分析 ffmpeg源码简析(一)结构总览- https://blog.csdn.net/Louis_815/article/details/79621056 FFmpeg的库 ...

  3. FFMpeg中apiexample.c例子分析——编码分析

    FFMpeg中apiexample.c例子分析--编码分析apiexample.c例子教我们如何去利用ffmpeg库中的api函数来自己编写编解码程序. (1)首先,main函数中一开始会去调用avc ...

  4. FFMpeg中apiexample.c例子分析——解码分析

    FFMpeg中apiexample.c例子分析--解码分析 收藏 我们直接从 video_decode_example() 函数开始讲,该函数实现了如何去解码一个视频文件,以 .mpeg 文 件为例. ...

  5. 利用ffmpeg对视频文件进行分析几例

    1.将视频文件转换为jpg图片文件序列: ffmpeg -i /home/czl/WorkSpace/ffmpeg/H264_REC.raw -r 1 -q:v 2 -f image2 pic-%03 ...

  6. FFmpeg播放视频文件流程

    一.FFmpeg解码播放主要流程,如图1-1所示: 使用播放一个媒体文件时,通常需要经过以下几个步骤: 图1-1    FFmpeg 播放视频文件流程 1.解封装(Demuxing):就是将输入的封装 ...

  7. FFmpeg 使用命令整理 – 提取音频或视频、提取图片、格式转换等

    提取声音的软件网上搜索有不少,不过最有名最专业的似乎是一个命令行工具:ffmpeg.这个工具功能十分丰富且强大,我所需要的从视频中提取 mp3 的功能只是其中包含的一个.感觉使用起来很复杂因为是命令行 ...

  8. WebRTC视频数据流程分析

    本文来自<WebRTC Native开发实战>书籍作者许建林在LiveVideoStack线上分享中的内容,详细分析总结 WebRTC 的视频数据流程,并对大型项目如何快速上手:分析方法, ...

  9. Android流媒体处理流程分析

    文章目录 1. WiFiDisplay简介 2.RTSP协议流程分析 3. 流媒体协议简介 4. RTP.RTCP协议简介 4.1 RTP协议 4.1 RTP载荷H264码流 4.2 RTP载荷PS码 ...

最新文章

  1. 讲一讲什么是 MMAP
  2. 你真的了解实时计算吗?
  3. java环境教程_window下Java环境配置图文教程
  4. Ubuntu 16.04 安装mysql5.7
  5. 5月7日MySQL 学习
  6. CentOS 7运维管理笔记(5)----源代码安装Apache 2.4,搭建LAMP服务器
  7. phpstudy mysql升级5.7
  8. 维基解密:科技公司获得安全漏洞信息须答应几个条件
  9. 1、mysql创建用户和授权总结
  10. 精益创业实战 - 第3章 制作自己的精益画布
  11. 教你快速制作多张图片、多段视频的画中画特效
  12. 电脑变wifi 用电脑建立无线网
  13. triplets 、triplet Loss和 hard triplets
  14. OC基础--对象做参数在方法间传递
  15. 更改分辨率时banner图片变形解决方案
  16. commons-poll、jedis-2.7.0、jedis.properties资源分享
  17. 使用NAT打造FTP服务新法
  18. html如何制作正方体手工图,怎么用卡纸做正方体(做长方体的步骤图纸)
  19. iReport制作报表
  20. 【原创】开源OpenIM:轻量、高效、实时、可靠、低成本的消息模型

热门文章

  1. web前端HTML_1(简单页面的实现)
  2. 使用Guardium大数据智能解决方案释放Guardium数据的价值
  3. excel高级筛选怎么用_Excel表格中高级筛选的优点以及常用方法介绍
  4. deepin标题栏边框美化
  5. 京东价格api,京东商品详情接口,京东api,京东优惠券接口,京东到手价api接口,京东app详情接口,接口代码对接实现价格监控接口,品牌维权接口,行业分析api接口代码分享
  6. C#中Trim的功能介绍
  7. 渐进式复杂度分析-学习笔记
  8. 最新最全移动端界面设计UI尺寸规范-2018年初版
  9. friends第九季看完了,经典对白记录--gt;对婚姻有阴影的男人
  10. 初识IndexedDB本地存储