FFmpeg av_find_input_format函数剖析

本文深入解析AVInputFormat结构体,该结构体用于保存不同码流输入格式(如h264、FLV等)的解码参数。通过具体示例h264,介绍其成员变量的功能,并详细阐述了这些码流格式如何在av_register_all调用时被加载的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

AVInputFormat结构体
AVInputFormat 每种码流输入格式(例如h264,FLV, MKV, MP4, AVI)对应一个结构体,用来保存视音频的解码参数,目前以h264码流格式为例,描述结构体成员:
name:封装格式名称简写(short_name)[h264]
long_name:码流输入格式的长名称[raw H.264 video]
extensions:码流输入格式的扩展名[h26l,h264,264,avc]
raw_codec_id:码流输入格式ID[28]
read_packet:avformat-57.dll!0x000007fee101ca90 (加载符号以获取其他信息)
read_header:avformat-57.dll!0x000007fee101cb70 (加载符号以获取其他信息)

关键函数:int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);
read_packet函数读取一个AVPacket,然后放在pkt,这个函数在进行分帧
av_read_frame函数的里面会被调用到,调用相应的解码器获取一帧的完整数据


问题:各种码流输入格式是什么时候被加载的?
回答:当第一次调用av_register_all的时候就会注册复用器,其中就包含了各种码流的输入格式的处理函数

查看调用关系
av_register_all
    register_all
        REGISTER_MUXDEMUX(H264,             h264);
            #define REGISTER_MUXDEMUX(X, x) REGISTER_MUXER(X, x); REGISTER_DEMUXER(X, x)

#define REGISTER_MUXER(X, x)                                            \
    {                                                                   \
        extern AVOutputFormat ff_##x##_muxer;                           \
        if (CONFIG_##X##_MUXER)                                         \
            av_register_output_format(&ff_##x##_muxer);                 \
    }

#define REGISTER_DEMUXER(X, x)                                          \
    {                                                                   \
        extern AVInputFormat ff_##x##_demuxer;                          \
        if (CONFIG_##X##_DEMUXER)                                       \
            av_register_input_format(&ff_##x##_demuxer);                \
    }

看看注册码流输入格式的函数
void av_register_input_format(AVInputFormat *format)
{
    AVInputFormat **p = last_iformat;

    // Note, format could be added after the first 2 checks but that implies that *p is no longer NULL
    while(p != &format->next && !format->next && avpriv_atomic_ptr_cas((void * volatile *)p, NULL, format))
        p = &(*p)->next;

    if (!format->next)
        last_iformat = &format->next;
}
其中关键的全局变量是
static AVInputFormat *first_iformat = NULL;
static AVInputFormat **last_iformat = &first_iformat;
保存了所有码流格式

AVInputFormat *av_iformat_next(const AVInputFormat *f)
{
    if (f)
        return f->next;
    else
        return first_iformat;
}

AVInputFormat *av_find_input_format(const char *short_name)
{
    AVInputFormat *fmt = NULL;
    while ((fmt = av_iformat_next(fmt)))//获取解码器的链表指针,
        if (av_match_name(short_name, fmt->name))//根据输入的码流格式简写,轮询链表查找解码器
            return fmt;
    return NULL;
}

在avformat_open_input函数优化篇就直接指定码流的输入格式,从而减少了探测码流格式的时间

参考
http://blog.youkuaiyun.com/leixiaohua1020/article/details/12677129

http://blog.youkuaiyun.com/neustar1/article/details/38231937


     本文转自fengyuzaitu 51CTO博客,原文链接:http://blog.51cto.com/fengyuzaitu/1983060,如需转载请自行联系原作者




<think>嗯,用户遇到了一个C++编译错误,具体是在使用FFmpeg库的时候,类型转换的问题。错误信息显示在decode_file.cpp的第14行,从const AVInputFormat*转换为AVInputFormat*时不合法。这应该是因为新版本的FFmpeg中,av_find_input_format返回的是指向const的指针,而用户试图将其赋值给非const的指针。 首先,我需要确认FFmpeg版本的变化。在早期的FFmpeg版本中,av_find_input_format可能返回的是非const的指针,但在较新的版本中,可能改为返回const指针,以增强类型安全和防止意外修改。用户代码中的AVInputFormat *iformat是非const的,而函数返回的是const指针,导致类型不匹配。 解决方法应该是将变量声明为const AVInputFormat*,以匹配函数的返回类型。用户需要修改代码中的变量类型,比如将AVInputFormat *iformat改为const AVInputFormat *iformat。这样类型就一致了,编译错误就会消失。 另外,可能用户参考的示例代码是基于旧版本的FFmpeg,而他们现在使用的是新版本,导致兼容性问题。需要提醒用户检查FFmpeg的版本,并确认文档或API参考是否对应。例如,在较新的FFmpeg中,许多函数参数和返回类型可能增加了const修饰符,以符合更严格的C++规范。 同时,用户可能在其他地方也使用了类似的非const指针,需要检查整个代码中是否有其他类似的问题。例如,如果其他地方将iformat传递给期望非const指针的函数,可能需要进一步调整,或者确认那些函数是否在新版本中接受const指针。 另外,用户可能需要了解为什么FFmpeg做出这样的改变。通常,添加const修饰符是为了表明函数返回的指针指向的内容不应被修改,这有助于编译器优化和防止程序错误。因此,遵循这种约定可以提高代码的安全性和可维护性。 总结来说,解决方案是修改变量声明,添加const修饰符。如果用户还有其他类似的错误,同样的方法也适用。此外,建议用户查阅对应版本的FFmpeg文档,确保其他API调用也符合当前的类型要求。</think>### **问题分析** 这个编译错误是由于 FFmpeg API 的**类型不匹配**导致的。在较新版本的 FFmpeg 中,`av_find_input_format()` 函数返回的是一个 `const AVInputFormat*`(常量指针),而你的代码试图将其赋值给一个非 `const` 的 `AVInputFormat*` 指针,违反了 C++ 的类型安全规则。 --- ### **直接解决方案** 修改指针类型声明,添加 `const` 限定符: ```cpp // 原代码(错误) AVInputFormat *iformat = av_find_input_format("cavs"); // 修改后(正确) const AVInputFormat *iformat = av_find_input_format("cavs"); ``` --- ### **深入解释** #### 1. **FFmpeg API 的常量性变化** - **历史版本**:旧版 FFmpeg 的 `av_find_input_format()` 返回 `AVInputFormat*`(非 `const`)。 - **新版 FFmpeg**:出于安全性考虑,该函数返回 `const AVInputFormat*`,明确表示返回的指针指向的内容不可修改。 #### 2. **C/C++ 类型系统规则** - `const` 指针不能隐式转换为非 `const` 指针,这是为了防止意外修改只读数据。 - 如果强行转换,需要通过 `const_cast`(不推荐,除非明确知道数据可修改)。 --- ### **扩展建议** #### 1. **检查其他类似问题** 如果代码中有以下调用,同样需要添加 `const`: ```cpp // 例如 avformat_open_input 的第三个参数 const AVInputFormat *iformat = av_find_input_format("cavs"); avformat_open_input(&pFormatCtx, filename, iformat, NULL); ``` #### 2. **验证 FFmpeg 版本** 通过以下命令查看 FFmpeg 版本: ```bash ffmpeg -version ``` 如果是较新版本(如 4.0+),需确保代码遵循新版 API 规范。 #### 3. **查阅官方文档** 参考 FFmpeg 官方 API 文档确认函数签名: - [FFmpeg 官方文档](https://ffmpeg.org/doxygen/trunk/group__lavf__decoding.html#ga10a404346c646e4a58c0e05b3e92c0c0) --- ### **错误示例修正对比** | **错误代码** | **修正后代码** | |--------------|----------------| | `AVInputFormat *iformat = av_find_input_format("cavs");` | `const AVInputFormat *iformat = av_find_input_format("cavs");` | --- ### **附加说明** 如果代码中需要**强制绕过 `const`**(不推荐,除非明确必要),可使用 `const_cast`: ```cpp AVInputFormat *iformat = const_cast<AVInputFormat*>(av_find_input_format("cavs")); ``` 但这样做会破坏类型安全,可能导致未定义行为。 --- ### **总结** 1. **直接修复**:添加 `const` 修饰符。 2. **兼容性检查**:确保代码其他 FFmpeg API 调用适配新版常量性规则。 3. **文档验证**:通过官方文档确认函数签名变化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值