ffmpeg在看media文件信息的时候特别方便,通过-i参数指定input文件,就可以得到下面这样的输出,当然通过ffprobe也是一样的,只是ffmpeg用的太习惯了而已。

$ ffmpeg -i ~/h264.mp4Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/hui/h264.mp4':Metadata:major_brand     : isomminor_version   : 512compatible_brands: isomiso2avc1mp41encoder         : Lavf55.37.102Duration: 00:00:18.04, start: 0.000000, bitrate: 390 kb/sStream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1280x720, 389 kb/s, 25 fps, 25 tbr, 1200k tbn, 50 tbc (default)Metadata:handler_name    : VideoHandler

下面是对这个处理过程的一个简单的分析,首先是调用栈:

av_demuxer_iterate
av_probe_input_format3 format.c     165  0x7ffff70bf3dc
av_probe_input_format2 format.c     208  0x7ffff70bf5ca
av_probe_input_buffer2 format.c     280  0x7ffff70bf8b5
init_input             utils.c      446  0x7ffff722ed5d
avformat_open_input    utils.c      576  0x7ffff722f26a
open_input_file        ffmpeg_opt.c 1105 0x555555563c13
open_files             ffmpeg_opt.c 3280 0x55555556dba3
ffmpeg_parse_options   ffmpeg_opt.c 3320 0x55555556dd57
main                   ffmpeg.c     4874 0x55555558d9d8

从ffmpeg的main函数开始,最后进入av_probe_input_format3中调用av_demuxer_iterate,av_demuxer_iterate遍历所有的demuxer,进行打分,最后返回打分最高的fmt,完成了container format的识别。

const AVInputFormat *av_demuxer_iterate(void **opaque)
{static const uintptr_t size = sizeof(demuxer_list)/sizeof(demuxer_list[0]) - 1;uintptr_t i = (uintptr_t)*opaque;const AVInputFormat *f = NULL;if (i < size) {f = demuxer_list[i];} else if (outdev_list) {f = indev_list[i - size];}if (f)*opaque = (void*)(i + 1);return f;
}

这部分是demuxer_list的列表定义,为了方便阅读,省略掉很多:

static const AVInputFormat * const demuxer_list[] = {&ff_aa_demuxer,&ff_aac_demuxer,&ff_ac3_demuxer,&ff_acm_demuxer,&ff_act_demuxer,&ff_adf_demuxer,&ff_adp_demuxer,&ff_ads_demuxer,&ff_adx_demuxer,&ff_aea_demuxer,&ff_afc_demuxer,&ff_aiff_demuxer,&ff_aix_demuxer,&ff_amr_demuxer,&ff_amrnb_demuxer,&ff_amrwb_demuxer,&ff_anm_demuxer,&ff_apc_demuxer,&ff_ape_demuxer,&ff_m4v_demuxer,&ff_matroska_demuxer,&ff_mgsts_demuxer,&ff_microdvd_demuxer,&ff_mjpeg_demuxer,&ff_mjpeg_2000_demuxer,&ff_mlp_demuxer,&ff_mlv_demuxer,&ff_mm_demuxer,&ff_mmf_demuxer,&ff_mov_demuxer,&ff_mp3_demuxer,&ff_mpc_demuxer,&ff_mpc8_demuxer,&ff_mpegps_demuxer,&ff_mpegts_demuxer,&ff_mpegtsraw_demuxer,&ff_mpegvideo_demuxer,&ff_mpjpeg_demuxer,&ff_image_tiff_pipe_demuxer,&ff_image_webp_pipe_demuxer,&ff_image_xpm_pipe_demuxer,&ff_image_xwd_pipe_demuxer,NULL };

av_probe_input_format3的代码分析:


ff_const59 AVInputFormat *av_probe_input_format3(ff_const59 AVProbeData *pd, int is_opened,int *score_ret)
{AVProbeData lpd = *pd;const AVInputFormat *fmt1 = NULL;ff_const59 AVInputFormat *fmt = NULL;int score, score_max = 0;void *i = 0;const static uint8_t zerobuffer[AVPROBE_PADDING_SIZE];enum nodat {NO_ID3,ID3_ALMOST_GREATER_PROBE,ID3_GREATER_PROBE,ID3_GREATER_MAX_PROBE,} nodat = NO_ID3;if (!lpd.buf)lpd.buf = (unsigned char *) zerobuffer;if (lpd.buf_size > 10 && ff_id3v2_match(lpd.buf, ID3v2_DEFAULT_MAGIC)) {int id3len = ff_id3v2_tag_len(lpd.buf);if (lpd.buf_size > id3len + 16) {if (lpd.buf_size < 2LL*id3len + 16)nodat = ID3_ALMOST_GREATER_PROBE;lpd.buf      += id3len;lpd.buf_size -= id3len;} else if (id3len >= PROBE_BUF_MAX) {nodat = ID3_GREATER_MAX_PROBE;} elsenodat = ID3_GREATER_PROBE;}// 遍历所有的demuxerwhile ((fmt1 = av_demuxer_iterate(&i))) {if (!is_opened == !(fmt1->flags & AVFMT_NOFILE) && strcmp(fmt1->name, "image2"))continue;score = 0;if (fmt1->read_probe) {// 调用demuxer的read_probe函数计算scorescore = fmt1->read_probe(&lpd);if (score)av_log(NULL, AV_LOG_TRACE, "Probing %s score:%d size:%d\n", fmt1->name, score, lpd.buf_size);if (fmt1->extensions && av_match_ext(lpd.filename, fmt1->extensions)) {switch (nodat) {case NO_ID3:score = FFMAX(score, 1);break;case ID3_GREATER_PROBE:case ID3_ALMOST_GREATER_PROBE:score = FFMAX(score, AVPROBE_SCORE_EXTENSION / 2 - 1);break;case ID3_GREATER_MAX_PROBE:score = FFMAX(score, AVPROBE_SCORE_EXTENSION);break;}}} else if (fmt1->extensions) {if (av_match_ext(lpd.filename, fmt1->extensions))score = AVPROBE_SCORE_EXTENSION;}if (av_match_name(lpd.mime_type, fmt1->mime_type)) {if (AVPROBE_SCORE_MIME > score) {score = AVPROBE_SCORE_MIME;}}// 记录分值最高的formatif (score > score_max) {score_max = score;fmt       = (AVInputFormat*)fmt1;} else if (score == score_max)fmt = NULL;}// 返回score_max对应的fmtif (nodat == ID3_GREATER_PROBE)score_max = FFMIN(AVPROBE_SCORE_EXTENSION / 2 - 1, score_max);*score_ret = score_max;return fmt;
}

在前面probe到具体的format之后,就调用真正的demuxer来处理,这里是iso base的文件类型,进入mov对应的处理逻辑,下面是调用栈:

mov_read_ftyp        mov.c        1120 0x7ffff71261bd
mov_read_default     mov.c        6929 0x7ffff713864d
mov_read_header      mov.c        7468 0x7ffff713a38b
avformat_open_input  utils.c      634  0x7ffff722f56b
open_input_file      ffmpeg_opt.c 1105 0x555555563c13
open_files           ffmpeg_opt.c 3280 0x55555556dba3
ffmpeg_parse_options ffmpeg_opt.c 3320 0x55555556dd57
main                 ffmpeg.c     4874 0x55555558d9d8

ffmpeg probe一个文件的过程相关推荐

  1. 使用ffmpeg播放视频文件的过程

    本文中,红色字体部分是涉及到的ffmpeg部分,其他函数是视频显示部分或者内部封装函数(文中没有给出实现). 本文的主要目的,在于记录播放视频文件时用到的ffmpeg函数,及其用法. typedef ...

  2. 工作记录--使用FFmpeg将一个视频文件中音频合成到另一个视频中

    由于工作需要,临时被老大吩咐去研究一个FFmpeg工具,通过linux命令行去将一个视频中的音频提取出来并合成到另一个视频中,最终的效果是要保证2个视频中的音频都在一个视频中播放. 但是本人对FFmp ...

  3. 如何用FFmpeg编写一个简单播放器详细步骤介绍

    如何用FFmpeg编写一个简单播放器详细步骤介绍(转载) FFMPEG是一个很好的库,可以用来创建视频应用或者生成特定的工具.FFMPEG几乎为你把所有的繁重工作都做了,比如解码.编码.复用和解复用. ...

  4. Java使用FFmpeg处理视频文件指南

    https://www.cnblogs.com/Dreamer-1/p/10394011.html Java使用FFmpeg处理视频文件指南 本文主要讲述如何使用Java + FFmpeg实现对视频文 ...

  5. Java使用FFmpeg处理视频文件的方法教程

    这篇文章主要给大家介绍了关于Java使用FFmpeg处理视频文件的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧 前言 本文主要 ...

  6. FFMPEG 合并视频文件(无损)

    FFMPEG 合并视频文件(无损) 前言 最近在做视频转码相关业务,但是片源商给了一些DVD的零散视频片段,需要自己去合并片段并进行业务转码,本篇文章主要记录视频合并的过程及常见的合并方式. 环境 F ...

  7. Linux 如何通过命令查看一个文件的某几行(中间几行或最后几行)

    linux 如何显示一个文件的某几行(中间几行) [一]从第3000行开始,显示1000行.即显示3000~3999行 cat filename | tail -n +3000 | head -n 1 ...

  8. 安卓 linux init.rc,[原创]Android init.rc文件解析过程详解(二)

    Android init.rc文件解析过程详解(二) 3.parse_new_section代码如下: void parse_new_section(struct parse_state *state ...

  9. go 一个文件引进另一个文件_一个浏览 GitHub 文件的神操作!

    阅读本文大概需要 5 分钟. 嗨,大家好,我是年轻的小编--&herongwei,今天是我在这个公众号上发的第一篇文章.请大家指教! 序 我们都知道,GitHub 上可以查看某个文件的历史修改 ...

最新文章

  1. python中类的用法_Python中的类和方法使用举例
  2. AtCoder AGC031F Walk on Graph (图论、数论)
  3. C++面向对象设计原则详解
  4. CentOS6.5系统重启后宕机
  5. dp递推 hdu1978
  6. python数据存储用什么_Python的小数据存储,用什么格式更有逼格?
  7. RegExp类型exec()方法的返回值说明
  8. chmod命令的用法
  9. NHibernet能带来什么呢?
  10. 微服务架构:spring cloud之服务注册和服务发现
  11. 阿里春招Android面经
  12. 每天几道面试题SSM面试题
  13. 计算机关闭窗口可以使用alt,电脑关闭窗口快捷键
  14. DNS基础之使用dig查询DNS解析过程
  15. 2017年大数据会是广告市场最后一根救命草吗?
  16. 怎样让公司全员贡献结构化内容?
  17. Sublime Text 3--->中文乱码的解决方法
  18. 为什么PDF转成Word后是图片,怎么才能修改?
  19. iOS 教你如何修改微信运动步数
  20. Linux集群的安装和配置

热门文章

  1. MODBUS-RTU协议主机和从机代码STM32 包含2个程序代码,主机和从机
  2. 【android】项目案例(一)之超级课程表
  3. C# 串口接收含有asic2=0x3f时发生的故障
  4. 读数据优化 绝对值函数优化 加速 示范程序 洛谷P2345奶牛集会
  5. mysql 插入缓冲_innodb insert buffer 插入缓冲区的理解
  6. 怎样才算是好程序员?关于好程序员与好代码的杂谈
  7. 计算机毕业设计基于Android平台的公交线路查询系统app
  8. 为了不被晒黑,这届年轻人有多拼?| 小红书防晒趋势洞察
  9. Android 实现自动点击屏幕的方法
  10. linux pptpd无法访问内网,Linux系统中Starting pptpd无法运行的解决办法