ffmpeg probe过程总结
来源:互联网 发布:mac散热差怎么办 编辑:程序博客网 时间:2024/05/17 07:40
fffmeg 通过avformat_open_input函数来打开媒体流.在这个函数中,首先做一些初始化工作,并设置一些option(比如ffplay 里面传入的一些参数),再调用init_input进行probe.
probe是个很关键的步骤,只有通过probe对一个未知的视频源进行分析,得知其具体的格式了,后面才能根据其协议进行解封装,解码,渲染.
我们在这里简单介绍一些probe的过程.
// Open input file and probe the format if necessary. */static int init_input(AVFormatContext *s, const char *filename, AVDictionary **options){ int ret; AVProbeData pd = { filename, NULL, 0 }; int score = AVPROBE_SCORE_RETRY; if (s->pb) { // AVProbeData为不为null的时候,会进来.这里通常不会进来.可能上层设置了pb后会进来 s->flags |= AVFMT_FLAG_CUSTOM_IO; if (!s->iformat) return av_probe_input_buffer2(s->pb, &s->iformat, filename, s, 0, s->format_probesize); else if (s->iformat->flags & AVFMT_NOFILE) av_log(s, AV_LOG_WARNING, "Custom AVIOContext makes no sense and " "will be ignored with AVFMT_NOFILE format.\n"); return 0; } // iformat为null或者为AVFMT_NOFILE表示还未prob成功 这时候尝试调用av_probe_input_format2来prob.这里仅根据输入文件的后缀名来猜测.并不接收码流数据.比如.mp4等有后缀的可以在这里确认 if ((s->iformat && s->iformat->flags & AVFMT_NOFILE) || (!s->iformat && (s->iformat = av_probe_input_format2(&pd, 0, &score)))) return score; // 根据后缀猜测失败了.比如这个流没有后缀. // 读取一段数据进行猜测. if ((ret = s->io_open(s, &s->pb, filename, AVIO_FLAG_READ | s->avio_flags, options)) < 0) return ret; if (s->iformat) return 0; return av_probe_input_buffer2(s->pb, &s->iformat, filename, s, 0, s->format_probesize);}
总结下:
1 先使用av_probe_input_format2,传个仅文件名有效的AVProbeData,如果成功了则返回;
2 否则读取一段码流,再调用一次av_probe_input_buffer2进行探测.这个函数内部实际上也调用了av_probe_input_format2.
3 av_probe_input_format2内部又调用了av_probe_input_format3,这个是关键实现.
如下是av_probe_input_format3的代码片段,其主要思路是,遍历所有支持的InputFormat,对每种format进行probe评分,然后取分数最高的.
这里所说的支持的InputFormat,就是在编译时指定的.
fmt = NULL; while ((fmt1 = av_iformat_next(fmt1))) { // 遍历支持的AVInputFormat if (!is_opened == !(fmt1->flags & AVFMT_NOFILE) && strcmp(fmt1->name, "image2")) continue; score = 0; if (fmt1->read_probe) { // 如果format支持read_probe,即该函数非空的话,调用该函数进行prob score = 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) { // 不支持read_probe,那根据后缀来判断 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) { av_log(NULL, AV_LOG_DEBUG, "Probing %s score:%d increased to %d due to MIME type\n", fmt1->name, score, AVPROBE_SCORE_MIME); score = AVPROBE_SCORE_MIME; } } if (score > score_max) { score_max = score; fmt = fmt1; } else if (score == score_max) fmt = NULL; } if (nodat == ID3_GREATER_PROBE) score_max = FFMIN(AVPROBE_SCORE_EXTENSION / 2 - 1, score_max); *score_ret = score_max; return fmt;
在每一种format来Probe时,先判断该format所指向的read_prob回调函数,如果回调函数不为空,那进行read_probe并打分.比如说rtmp格式,其read_probe就指向了flvdec.c里面的flv_probe;mp4格式,其read_prob指向了mov.c里面的mov_probe.
如果read_prob为空,会再判断extensions,根据文件后缀来,同样这里也会进行打分.
评分结束后,还会根据mime_type再进行一次评分,当然如果已经有更高分了,则忽略mime的评分.
最终,format遍历结束后,会得出最高分的AVInputFormat并返回.
- ffmpeg probe过程总结
- FFmpeg的解码过程总结
- FFmpeg的解码过程总结
- stmmac probe 过程
- usb设备probe过程
- stmmac probe 过程
- probe调用过程
- debian下ffmpeg编译过程总结
- probe
- ffmpeg 总结
- Linux Device和Driver注册过程,以及Probe的时机
- Linux Device和Driver注册过程,以及Probe的时机。
- Linux Device和Driver注册过程,以及Probe的时机
- Linux Device和Driver注册过程,以及Probe的时机
- Linux Device和Driver注册过程,以及Probe的时机
- Linux Device和Driver注册过程,以及Probe的时机
- HBA(pm8001)的probe过程 之内核路径
- Linux Device和Driver注册过程,以及Probe的时机
- Maven--servlet演示
- 在这种情况下居然strings不出结果, 呵呵哒!
- git 远程仓库创建和代码上传
- 电商项目简介
- 嵌入式每日学习心得2017.08.09
- ffmpeg probe过程总结
- UE编辑器重要快捷键总结
- 2017年8月份到年底的计划
- 关于用java生成验证码
- python之import机制详解
- java学习建议
- Codeforces 441E Valera and Number 概率DP
- Javascript图片库
- Maven--Eclipse集成Maven