FFmpeg5.0源码阅读——avformat_open_input

这篇具有很好参考价值的文章主要介绍了FFmpeg5.0源码阅读——avformat_open_input。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  摘要:本文主要描述了FFmpeg中用于打开文件接口avformat_open_input的具体调用流程,详细描述了该接口被调用时所作的具体工作。
  关键字ffmpegavformat_open_input
  注意:读者需要了解FFmpeg的基本使用流程,以及一些FFmpeg的基本常识,了解FFmpegIO相关的内容,以及大致的解码流程。

1 avformat_open_input大致流程

  在了解avformat_open_input的具体实现之前,我们先简单看下具体的函数声明和使用方式。avformat_open_input函数调用时会检测一部分当前格式的信息,更多的信息需要调用avformat_find_stream_info获取更加准确的信息。在函数调用时可以强制指定对应格式的格式,即参数AVInputFormat,否则FFmpeg内部会根据扩展名,数据格式等进行检测。另外也可以设置options,该option控制了探测码流的一些标志位,一般情况下不会设置,但是有些情况下需要根据具体的场景设置,比如有些素材普通的方式检测不到就需要设置probesize才能准确的检测到码流的属性等。

/**
 * Open an input stream and read the header. The codecs are not opened.
 * The stream must be closed with avformat_close_input().
 *
 * @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context).
 *           May be a pointer to NULL, in which case an AVFormatContext is allocated by this
 *           function and written into ps.
 *           Note that a user-supplied AVFormatContext will be freed on failure.
 * @param url URL of the stream to open.
 * @param fmt If non-NULL, this parameter forces a specific input format.
 *            Otherwise the format is autodetected.
 * @param options  A dictionary filled with AVFormatContext and demuxer-private options.
 *                 On return this parameter will be destroyed and replaced with a dict containing
 *                 options that were not found. May be NULL.
 *
 * @return 0 on success, a negative AVERROR on failure.
 *
 * @note If you want to use custom IO, preallocate the format context and set its pb field.
 */
int avformat_open_input(AVFormatContext **ps, const char *url, const AVInputFormat *fmt, AVDictionary **options);

FFmpeg5.0源码阅读——avformat_open_input

  从上面的流程图(图中省略了ID3V2 metadata获取的相关内容)中我们能够看出avformat_open_input的主要工作就是打开文件流然后探测文件的码流检测出当前文件的格式。

2 调用流程详情

  avformat_alloc_context,如果用户指定的AVFormatContext指针为空内部就会创建一个。而该函数主要的工作就是利用av_malloc申请一个AVFormatContext然后设置默认值。av_opt_set_dict就是设置基本的参数到当前的Context中。
  init_input主要工作就是打开输入流,并探测对应的流内容,对流进行打分,分支越高对应格式的可能性越高否则越低。打开流的工作就是利用avio的打开流,根据不同的流类型会调用不同的打开API,文件就是调用open。在进行流探测是分别调用av_probe_input_buffer2av_probe_input_format2对码流进行打分,前者最终也是调用后者实现的。

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) {
        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;
    }
    //文件流已经被打开过了就直接调用av_probe_input_format2进行格式检测
    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);
}

  av_probe_input_format3内通过遍历一个全局的demuxer_list表格,利用每种封装格式的探测指针对流进行打分,选择分值最高的作为最终的流格式。demuxer_list是一个自动生成的全局数组,如果没有编译FFmpeg是不会看到该数组的。

static const AVInputFormat *demuxer_list[] = {
    &ff_aa_demuxer,
    &ff_aac_demuxer,
    &ff_aax_demuxer
    ...
    &ff_libmodplug_demuxer,
    NULL 
};

  av_probe_input_format3的核心代码如下,遍历已知的格式列表,如果探测不到就会常使用mime_type和扩展名作为依据。

while ((fmt1 = av_demuxer_iterate(&i))) {
    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;
}

  随后就是调用read_header取读取一些基本的参数,比如流的数量,时长等。其他代码就是一些检查类以及参数更新类代码了。文章来源地址https://www.toymoban.com/news/detail-500049.html

3 参考文献

  • ID3
  • FFmpeg源代码简单分析:avformat_open_input()

到了这里,关于FFmpeg5.0源码阅读——avformat_open_input的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • FFmpeg5.0源码阅读—— av_read_frame

       摘要 :本文主要描述了FFmpeg中用于打开编解码器接口 av_read_frame 的具体调用流程,详细描述了该接口被调用时所作的具体工作。    : ffmpeg 、 av_read_frame    读者须知 :读者需要了解FFmpeg的基本使用流程,以及一些FFmpeg的基本常识,了解FFmpegIO相关的内容,

    2024年02月16日
    浏览(29)
  • FFmpeg5.0源码阅读——av_interleaved_write_frame

       摘要 :本文主要详细描述FFmpeg中封装时写packet到媒体文件的函数 av_interleaved_write_frame 的实现。    : av_interleaved_write_frame    读者须知 :读者需要熟悉ffmpeg的基本使用。    av_interleaved_write_frame 的基本调用流程图如下。   首先就是根据输入数据是否为空

    2024年02月14日
    浏览(47)
  • FFmpeg5.0源码阅读—— avcodec_send_frame && avcodec_receive_packet

       摘要 :本文主要描述了FFmpeg中用于编码的接口的具体调用流程,详细描述了该接口被调用时所作的具体工作。    : ffmpeg 、 avcodec_send_frame 、 avcodec_receive_packet    读者须知 :读者需要了解FFmpeg的基本使用流程,以及一些FFmpeg的基本常识,了解FFmpegIO相关的内

    2024年02月16日
    浏览(37)
  • FFmpeg之AVFormat

       团队博客: 汽车电子社区   avformat中实现了目前多媒体领域中的几乎所有封装格式,可以封装,可以解封装(也叫解复用),根据需求不同,所支持的也有所不同,ffmpeg能否支持一种封装格式的视频的封装与解封装,完全取决于这个库,例如mp4、flv、mkv等容器的封装与

    2024年01月16日
    浏览(40)
  • avformat_open_input 调用失败的原因

    avformat_open_input 是 FFmpeg 库中的一个函数,用于打开音视频文件或网络流并进行解封装操作,返回值为一个表示打开的文件或流的 AVFormatContext 结构体指针。如果 avformat_open_input 失败,可能是如下的原因: 文件路径或 URL 错误: avformat_open_input 的第一个参数是文件路径或 URL,如

    2024年02月09日
    浏览(55)
  • ffmpeg之avformat_alloc_output_context2

    函数原型: 功能:         查找根据format_name或者filename或者oformat输出类型,并且初始化ctx结构。 参数:         ctx:AVFormatContext结构体,ffmpeg核心结构体,会在函数内部给ctx分配AVFormatContext空间并初始化。         oformat:指定输出格式的 AVOutputFormat 结构体指针

    2024年02月21日
    浏览(28)
  • 【Android音视频】MacOS上FFmpeg5.0.1编译

    1. FFmpeg官网下载链接(推荐下载release的版本): Download FFmpeg http://ffmpeg.org/download.html#releases  尽情去下载并开始编译吧 2. 下载压缩包,解压至自己想要的文件路径下即可。个人习惯用全英文路径,避免出现奇怪的问题。 3. Android Studio请预先下载好。点击AS右上角“SDK Manager”

    2024年02月02日
    浏览(40)
  • FFmpeg5.1.3编译动态库踩坑之旅(基于Linux虚拟机)

    环境准备 1.Windows安装Oracle VM VirtualBox 7.0.10,安装ubuntu-22.04.3。 坑一 :无法往虚拟机里拖放复制文件,解决办法:登录Ubuntu虚拟机时切换到xorg方式登录,参考地址:Ubuntu Desktop 22.04 无法实现拖放复制操作解决办法-CSDN博客 下载文件 下载ndk25 官网下载:ndk官网 网盘下载:andr

    2024年02月07日
    浏览(38)
  • 【开放集检测】OpenGAN: Open-Set Recognition via Open Data Generation 论文阅读

    Machine learning systems that operate in the real openworld invariably encounter test-time data that is unlike training examples, such as anomalies or rare objects that were insufficiently or even never observed during training. invariably:一贯的 … can be crisply formulated as … 可以被很清晰的定义/表述为 an elegant idea is to… 一个绝佳

    2024年02月02日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包