ffmpeg源码分析(九)解协议

本文将聚焦于FFmpeg协议处理模块,以avformat_open_input函数为核心,详细剖析其在最新FFmpeg源码中的实现。

音视频处理流程简介

在这里插入图片描述

avformat_open_input概述

avformat_open_input是FFmpeg用于打开输入多媒体数据的关键函数。它通过统一的接口处理多种协议,使用户无需关心底层实现。该函数的声明如下,位于libavformat/avformat.h

int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);
  • ps:指向AVFormatContext结构体的指针,用于存储打开的多媒体数据上下文。

  • url:要打开的资源URL。

  • fmt:指定输入格式,如果为NULL,FFmpeg会自动探测。

  • options:用于传递其他选项(字典形式)。

这个函数主要完成的功能就是探测输入的格式,然后配置格式的上下文,

比如输入一个mp4文件的地址,它会判断出这是mp4文件,然后AVFormatContext 就知道该怎么处理这个文件了。

avformat_open_input 打开数据流

/**
 * @brief 打开一个输入媒体文件。
 * 
 * @param ps 用户提供的 AVFormatContext 的指针,可能是一个指向 NULL 的指针来分配一个新的上下文。
 * @param filename 要打开的文件名。
 * @param fmt 如果非 NULL,此参数强制使用特定的输入格式。
 * @param options 填充 AVFormatContext 和解复用器私有选项的字典。返回时,该参数将被销毁并替换为包含未找到选项的字典。
 * 
 * @return 成功返回0,失败返回负的 AVERROR。
 */
int avformat_open_input(AVFormatContext **ps, const char *filename,
                        const AVInputFormat *fmt, AVDictionary **options)
{
   
   
    AVFormatContext *s = *ps;  // 获取提供的格式上下文
    FFFormatContext *si;       // 内部格式上下文
    AVDictionary *tmp = NULL;  // 用于选项的临时字典
    int ret = 0;               // 返回值

    // 如果没有提供格式上下文,则分配一个新的,也就是说这个格式上下文是可以由外部分配创建的
    if (!s && !(s = avformat_alloc_context()))
        return AVERROR(ENOMEM); 
  
    // 获取内部格式上下文,这相当于给AVFormatContext补充额外的上下文,这在ffmepg中是比较常见的。注意补充字段的内存是在avformat_alloc_context中分配的,所以不要自己直接malloc AVFormatContext
    si = ffformatcontext(s);   
    if (!s->av_class) {
   
   
        av_log(NULL, AV_LOG_ERROR, "输入上下文未通过 avformat_alloc_context() 正确分配\n");
        return AVERROR(EINVAL); 
    }
    if (fmt)
        s->iformat = fmt; // 设置输入格式

    if (options)
        av_dict_copy(&tmp, *options, 0); 

    // 如果设置了IO上下文,则设定定制的解复用标志
    if (s->pb)
        s->flags |= AVFMT_FLAG_CUSTOM_IO;

    if ((ret = av_opt_set_dict(s, &tmp)) < 0)
        goto fail; // 设置格式上下文选项失败

    // 拷贝文件名
    if (!(s->url = av_strdup(filename ? filename : ""))) {
   
   
        ret = AVERROR(ENOMEM);
        goto fail;
    }

    // 【重要】探测输入格式
    if ((ret = init_input(s, filename, &tmp)) < 0)
        goto fail;

    s->probe_score = ret; // 设置探测得分

    // 复制协议白名单
    if (!s->protocol_whitelist && s->pb && s->pb->protocol_whitelist) {
   
   
        s->protocol_whitelist = av_strdup(s->pb->protocol_whitelist);
        if (!s->protocol_whitelist) {
   
   
            ret = AVERROR(ENOMEM); 
            goto fail;
        }
    }

    // 复制协议黑名单
    if (!s->protocol_blacklist && s->pb && s->pb->protocol_blacklist) {
   
   
        s->protocol_blacklist = av_strdup(s->pb->protocol_blacklist);
        if (!s->protocol_blacklist) {
   
   
            ret = AVERROR(ENOMEM); 
            goto fail;
        }
    }

    // 检查格式白名单
    if (s->format_whitelist && av_match_
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值