Demuxer解复用架构—FFmpeg源码分析

FFmpeg 的 Demuxer 解复用架构可以分为 3 个部分,以 MP4 为例,其他的格式也是类似的,如下:

1-1

1,avformat_open_input,确定输入格式,再调 read_header 读取头部信息

当没有在命令行使用 -f 指定输入格式的时候,init_input() 里会遍历所有的 Demuxer,调用他们的 read_probe 函数来探测输入文件是什么格式的。

也就是说,他会调 mp4mov_porbe 函数,flvkux_probe 函数,等等,来探测输入格式

当确定了 输入格式(iformat)的时候,就会把确定的 Demuxer 赋值给 s->iformat,然后调这个 iformatread_header 函数来读取头部信息。

mp4iformatff_mov_demuxer,如下:

AVInputFormat ff_mov_demuxer = {
    .name           = "mov,mp4,m4a,3gp,3g2,mj2",
    .long_name      = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
    .priv_class     = &mov_class,
    .priv_data_size = sizeof(MOVContext),
    .extensions     = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v",
    .read_probe     = mov_probe,
    .read_header    = mov_read_header,
    .read_packet    = mov_read_packet,
    .read_close     = mov_read_close,
    .read_seek      = mov_read_seek,
    .flags          = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS,
};

提醒:avformat_open_input() 读取的是头部信息,并不会去读取文件里面的编码数据。

优化技巧:由于 avformat_open_input() 会遍历所有的 Demuxer 来进行 probe 操作,所以可以通过 -f 指定格式,来提高性能。


2,avformat_find_streaminfo,对数据进行解码

avformat_find_streaminfo() 里面会调 read_frame_internal() 来读取 AVPacket,然后进行解码,但是为什么要解码,我也不太清楚,后面补充。

注意,这里的 AVPacket 是编码的数据,也就是一个 GOP 的 IDR 帧,所以如果读出来之后丢弃,可能会导致后面花屏,所以默认情况下会调 avpriv_packet_list_put() 函数把 AVPacket 放进去 internal->packet_buffer 缓存里面。

后面的 av_read_frame() 会优先从 packet_buffer 缓存里面里面拿 AVPacket

提示:可以在命令行用 -nobuffer 来禁止缓存,可以降低延迟,但是可能会导致解码器刚开始输出的数据花屏。


3,av_read_frame,读取 AVPacket 编码数据

av_read_frame()read_frame_internal() 的区别在于,av_read_frame 会优选从 packet_buffer 缓存里面读数据,缓存里没数据再调 read_frame_internal() 从输入文件读数据。


后面就让我们学习,解复用(Demuxer)三部曲的具体细节。

版权所属 xianwanzhiyin.net 罗上文 2023 all right reserved,powered by Gitbook该文件修订时间: 2023-05-17 14:50:31

results matching ""

    No results matching ""