Version:3.4.6
ffmpeg对于格式的探测其实是两步:
- read_probe
- extensions
参考分析路径
./libavformat
|---- utils.c
|---- avformat_open_input
|---- init_input
|---- format.c
|---- av_probe_input_buffer2
|---- av_probe_input_format3
|---- avformat.h - wtvdec/paf/mgsts/jvdec.c
|---- read_probe
详情
static int init_input(AVFormatContext *s, const char *filename,
AVDictionary **options)
{
//...
return av_probe_input_buffer2(s->pb, &s->iformat, filename,
s, 0, s->format_probesize);
}
int av_probe_input_buffer2(AVIOContext *pb, AVInputFormat **fmt,
const char *filename, void *logctx,
unsigned int offset, unsigned int max_probe_size)
{
//...
//把AVFormatContext和具体的AVInputFormat联系起来了
*fmt = av_probe_input_format2(&pd, 1, &score);
//...
}
FFmpeg中实现探测的函数是av_probe_input_buffer2
和av_probe_input_format3
* format.c - av_probe_input_format3
/**
* 遍历所有的Demuxer
* 是优先使用demuxer的read_probe函数,然后参考文件名的后缀名来关联某个AVInputFormat
*/
fmt = NULL;
while ((fmt1 = av_iformat_next(fmt1))) {
if (!is_opened == !(fmt1->flags & AVFMT_NOFILE) && strcmp(fmt1->name, "image2"))
continue;
score = 0;
if (fmt1->read_probe) {
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) {
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;
网友评论