【FFmpeg】解封装 ① ( 封装与解封装流程 | 解封装函数简介 | 查找码流标号和码流参数信息 | 使用 MediaInfo 分析视频文件 )

文章目录

  • 一、解封装
  • 二、解封装函数简介
    • [1、avformat_alloc_context 函数](#1、avformat_alloc_context 函数)
    • [2、avformat_free_context 函数](#2、avformat_free_context 函数)
    • [3、avformat_open_input 函数](#3、avformat_open_input 函数)
    • [4、avformat_close_input 函数](#4、avformat_close_input 函数)
    • [5、avformat_find_stream_info 函数](#5、avformat_find_stream_info 函数)
    • [6、av_read_frame 函数](#6、av_read_frame 函数)
    • [7、avformat_seek_file 函数](#7、avformat_seek_file 函数)
    • [8、av_seek_frame 函数](#8、av_seek_frame 函数)
  • 三、查找码流标号和参数信息
    • 1、码流标号
    • [2、查找码流标号 - av_find_best_stream 函数](#2、查找码流标号 - av_find_best_stream 函数)
    • [3、查找码流参数信息 - avformat_find_stream_info 函数](#3、查找码流参数信息 - avformat_find_stream_info 函数)
    • 4、查找码流参数信息延迟分析
  • 四、视频文件解封装示例
    • [1、使用 MediaInfo 分析视频文件](#1、使用 MediaInfo 分析视频文件)
    • [2、使用 MediaInfo 分析视频文件的每个字节的信息](#2、使用 MediaInfo 分析视频文件的每个字节的信息)

FFmpeg 4.0 版本源码地址 :

一、解封装


1、封装与解封装流程

" 封装 " 是 将 音频流 / 视频流 / 字幕流 等多媒体流 , 按照一定的规则 组合成 特定格式的 视频文件 ;

  • 封装 主要是由 " 复用器 " 完成的 ;
  • 封装示例 : 将 AAC 格式的 音频流 和 H.264 格式的 视频流 封装成一个 .mp4 文件 ;

" 解封装 " 是 将 特定格式的 视频文件 , 按照一定的规则 拆分成 音频流 / 视频流 / 字幕流 等多媒体流 ;

  • 解封装 主要是由 " 解复用器 " 完成的 ;
  • 解封装示例 : 将 .mp4 文件 拆分成 AAC 格式的 音频流 和 H.264 格式的 视频流 ;

2、解封装 常用函数

解封装 常用函数 简介 :

  • avformat_alloc_context 函数 : 用于 申请 AVFormatContext 结构体内存 , 并 对 结构体的字段 进行简单初始化操作 ;
  • avformat_free_context 函数 : 释放 AVFormatContext 结构体 及其 关联的资源 ;
  • avformat_open_input 函数 : 使用 解复用器 打开 视频文件 / 媒体流 ;
  • avformat_close_input 函数 : 关闭 解复用器 ;
  • avformat_find_stream_info 函数 : 获取 媒体流信息 ;
  • av_read_frame 函数 : 读取 媒体流 中的 AVPacket 数据包 ;
  • avformat_seek_file 函数 : 根据 时间戳 跨多个流 定位文件 中的位置 ;
  • av_seek_frame 函数 : 根据 时间戳 跳转到指定流的指定位置 ;

二、解封装函数简介


下面的 解封装 函数 可 参考 【FFmpeg】FFmpeg 函数简介 ② ( 封装格式相关函数解析 | 封装格式与解复用器 | avformat_alloc_context 函数 | avformat_open_input函数 ) 博客 ;

解封装流程如下 :

1、avformat_alloc_context 函数

avformat_alloc_context 函数原型 :

cpp 复制代码
AVFormatContext *avformat_alloc_context(void);
  • 函数作用 : 该函数用于 分配并初始化一个 AVFormatContext 结构体 ;
  • 函数参数 : 函数参数为空 ;
  • 函数返回值 : 函数 返回一个 AVFormatContext 指针 , 指向分配的结构体 ; 如果分配失败 , 则返回 NULL ;

AVFormatContext 结构体 用于 存储 文件格式相关信息 , 其中包括文件中 各个媒体流 的参数信息 ;

2、avformat_free_context 函数

avformat_free_context 函数 用于 释放 AVFormatContext 结构体 以及相关的资源 , 包括 流信息 / IO 资源 / 解码器 / 格式上下文 等数据 ,

avformat_free_context 函数原型如下 :

cpp 复制代码
void avformat_free_context(AVFormatContext *s);

avformat_free_context 函数 与 avformat_alloc_context 函数 一般都要成对使用 , 防止内存泄漏 ;

如果 之前调用过 avformat_alloc_context 函数 , 则必须调用 avformat_free_context 函数 释放内存 ;

如果 之前没有调用过 avformat_alloc_context 函数 , 则不必调用 avformat_free_context 函数 ;

3、avformat_open_input 函数

avformat_open_input 函数 使用 " 解复用器 " 打开 视频文件 , 该函数 在内部会调用 avformat_alloc_context 函数 用于为 AVFormatContext 结构体分配内存 ;

avformat_open_input 函数原型如下 :

cpp 复制代码
int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);
  • 函数参数 :
    • AVFormatContext **ps : 指向 AVFormatContext 指针的指针 ;
    • const char *url : 输入流的地址或文件名 , 文件路径 或 网络流的 URL ;
    • AVInputFormat *fmt : 设置输入格式 , 一般都是 NULL , FFmpeg 自动选择输入格式 ;
    • AVDictionary **options : 附加参数 , 设置解码器 , 网络连接 等参数 ;
  • 函数返回值 : 关闭成功 返回 0 , 关闭失败 返回 负值错误码 ;

注意 : avformat_open_input 函数 要与 avformat_close_input 函数 成对使用 ;

4、avformat_close_input 函数

avformat_close_input 函数 用于 关闭 " 解复用器 " , 该函数 在内部会调用 avformat_free_context 函数 ;

avformat_close_input 函数原型如下 :

cpp 复制代码
int avformat_close_input(AVFormatContext **ps);
  • 函数参数 : 其中的参数 ps 是 指向 AVFormatContext 指针的指针 ;
  • 函数返回值 : 关闭成功 返回 0 , 关闭失败 返回 负值错误码 ;

注意 : avformat_open_input 函数 要与 avformat_close_input 函数 成对使用 ;

5、avformat_find_stream_info 函数

avformat_find_stream_info 函数 用于获取 媒体流 信息 ;

一般情况下 , 调用 avformat_open_input 函数 就可以获取到 视频文件的 媒体流信息 ;

如果调用 avformat_open_input 函数 无法获取 媒体流信息 , 此时 需要 开发者 手动调用 avformat_find_stream_info 函数 用于获取媒体流信息 ;

函数原型如下 :

cpp 复制代码
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
  • 函数参数 :
    • AVFormatContext *ic : 指向 AVFormatContext 的指针 ;
    • AVDictionary **options : 可选附加参数 , 设置解码器 , 网络连接 等参数 ;
  • 函数返回值 : 关闭成功 返回 0 , 关闭失败 返回 负值错误码 ;

6、av_read_frame 函数

av_read_frame 函数 用于 读取 音视频流 中的 数据包 , 这是压缩后的数据 , 不能直接播放 , 需要经过解码后才能播放 ;

AAC 格式的 音频流 数据包 , 需要转为 PCM 格式 才能播放 ;

H.264 格式的 视频流 数据包 , 需要转为 YUV 或 RGB 格式 才能播放 ;

av_read_frame 函数 原型 :

cpp 复制代码
int av_read_frame(AVFormatContext *s, AVPacket *pkt);
  • 函数参数 :
    • AVFormatContext *s : 指向 AVFormatContext 的指针 , 这是已经打开的 多媒体流 的格式上下文 ;
    • AVPacket *pkt : 指向 AVPacket 的指针 , 用于存储读取的 一帧 音视频数据 ;
  • 函数返回值 : 关闭成功 返回 0 , 关闭失败 返回 负值错误码 ;

7、avformat_seek_file 函数

avformat_seek_file 函数 参考 【FFmpeg】FFmpeg 函数简介 ② ( 封装格式相关函数解析 | 封装格式与解复用器 | avformat_alloc_context 函数 | avformat_open_input函数 ) 一、FFmpeg 音视频文件 封装格式相关函数 8、avformat_seek_file 函数 博客章节 ;

8、av_seek_frame 函数

av_seek_frame 函数 参考 【FFmpeg】FFmpeg 函数简介 ② ( 封装格式相关函数解析 | 封装格式与解复用器 | avformat_alloc_context 函数 | avformat_open_input函数 ) 一、FFmpeg 音视频文件 封装格式相关函数 9、av_seek_frame 函数 博客章节 ;

avformat_seek_file 函数 与 av_seek_frame 函数 对比 :

  • 跳转粒度 :
    • avformat_seek_file : 支持 视频文件 跨多个媒体流 定位跳转 到 指定时间戳 , 并且 可以控制最小、最大时间戳范围 ;
    • av_seek_frame : 跳转到 特定流 的 指定时间戳 ;
  • 跳转控制 :
    • avformat_seek_file : 可以 精细控制时间戳范围 , 设置最小时间戳和最大时间戳 ;
    • av_seek_frame : 跳转到关键帧 , 灵活性较低 ;
  • 常用场景 :
    • avformat_seek_file : 适用于 跨多个媒体流 的文件 的 精准跳转 ;
    • av_seek_frame : 适用于 单个媒体流操作 , 通常用于快速定位到 视频流、音频流 或 字幕流 的 关键帧 ;

三、查找码流标号和参数信息


1、码流标号

在 FFmpeg 中 , 每个 多媒体文件 可能 包含 多个多媒体流 , 如 : 视频流、音频流、字幕流 等 ;

这些 媒体流都 会 被分配 一个 唯一的索引号 来标识 , 称为 " Stream index " , 用于区分文件中的不同流 ;

上述 流索引号 可以称为 " 码流标号 " , 从 0 开始进行递增编号 , 其中 标号为 0 的码流 可能是 视频流 / 音频流 / 字幕流 ;

2、查找码流标号 - av_find_best_stream 函数

av_find_best_stream 函数 用于查找 媒体文件 中的 最佳流 ;

cpp 复制代码
int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type, int wanted_stream, int related_stream, AVCodec **decoder_ret, int flags);
  • 函数参数 :
    • AVFormatContext *ic : 指向已打开媒体文件的 AVFormatContext 结构体的指针 , 其中封装了 媒体信息 包括 流的数量 以及 每个流的详细信息 ;
    • enum AVMediaType type : 要查找的 媒体流的类型 , 可选的媒体流类型如下 :
      • AVMEDIA_TYPE_VIDEO : 视频流类型 ;
      • AVMEDIA_TYPE_AUDIO : 音频流类型 ;
      • AVMEDIA_TYPE_DATA : 数据流类型 ;
      • AVMEDIA_TYPE_SUBTITLE : 字幕流类型 ;
      • AVMEDIA_TYPE_UNKNOWN : 未知类型 ;
      • AVMEDIA_TYPE_ATTACHMENT : 附件类型 ;
    • int wanted_stream : 用户期望的流索引 , 默认设置 -1 ;
    • int related_stream : 与之相关的最佳流的索引 , 默认设置 -1 ;
    • AVCodec **decoder_ret : 指向找到的流的对应解码器 , 默认设置 NULL ;
    • int flags : 指定额外的查找选项 , 默认设置 0 ;
  • 函数返回值 : 查找成功返回流索引 , 查找失败返回 AVERROR_STREAM_NOT_FOUND 或 错误码 ;

查找视频流示例 :

cpp 复制代码
int video_index = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0)

查找音频流示例 :

cpp 复制代码
int audio_index = av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0)

3、查找码流参数信息 - avformat_find_stream_info 函数

视频文件 在 播放前 , 必须要进行解码 , 解码的前提就是要知道 文件中的如下信息 :

  • 媒体流数量
  • 媒体流类型 : 视频流、音频流、字幕流 等 ;
  • 每个流的详细信息 : 编码格式、比特率、分辨率 等 ;

获取到这些信息后 , 都设置到 AVFormatContext 结构体中 ;

avformat_open_input 函数 在 打开 输入媒体文件 后 , 会读取 文件的头部信息 , 函数执行过程中会 初始化 AVFormatContext 结构体 , 并将读取到的文件流信息填充到该结构体中 ;

有些类型的文件 , 如 : FLV 文件 / H.264 文件 / 网络直播流 , 文件的 头部信息 中并没有完整的流信息 , 甚至就没有头部信息 ;

此时就需要 调用 avformat_find_stream_info 函数 , 获取每个媒体流的完整流信息 , 包括流的 编码参数、比特率、分辨率 等信息 ;

avformat_find_stream_info 函数 可以 在 信息缺失的情况下 , 通过分析 数据包 格式 , 探测并分析 流 的 缺失参数信息 ;

4、查找码流参数信息延迟分析

avformat_find_stream_info 函数会尝试读取足够的数据 , 来确定每个流的参数 , 如 : 编解码器、比特率、采样率 等 ;

读取数据 , 分析数据 , 然后获取流的参数信息 , 这个过程 需要花费一定的时间 , 这就会造成延迟 , 设置的 读取数据越多 , 造成的延迟越大 ;

开发者 通过 AVFormatContext 相关结构设置的一些参数 , 设置 avformat_find_stream_info 函数 读取数据的多少 ;

四、视频文件解封装示例


视频文件 封装在 文件容器中 , 将容器中的数据提取出来 , 就是解封装过程 ;

在本章节中 使用 MediaInfo 分析视频文件 提取视频文件的信息 , 之后在下一篇博客中自己编写代码提取视频文件中的数据 , 并在 输出日志 中展示出来 ;

1、使用 MediaInfo 分析视频文件

MediaInfo 软件 可 用于 提取 视频文件 的 技术信息和元数据 , 支持多种格式和编码 , 可以快速显示文件的详细信息 ;

下面我们使用 MediaInfo 软件 分析 mp4 格式的 视频文件 ;

MediaInfo 软件 默认显示的 文件内容细节是 Details - 0 级别 , 在 " 菜单栏 / 调试 " 选项中可以查看当前的 调试级别 ;

在 Details - 0 调试级别下 , 只能看到 文件的 容器格式 一般信息 , 有几个文件流 , 每个文件流都是什么格式的 , 具体的文件流的内容是无法看到的 ;

下图就是 mp4 文件的 Details - 0 调试级别 显示的文件的容器信息 , 很简略 ;

2、使用 MediaInfo 分析视频文件的每个字节的信息

在 " 菜单栏 / 调试 " 选项中 , 设置 调试级别为 Details - 10 级别 , 这样就可以分析文件中每个字节的信息 ;

此时再打开上个章节中的 mp4 文件 , 就会显示如下信息 , MediaInfo 会将文件的每个字节的数据都解析出来 , 同时将每个字节的含义也展出出来 ;

相关推荐
流氓也是种气质 _Cookie1 小时前
uniapp blob格式转换为video .mp4文件使用ffmpeg工具
ffmpeg·uni-app
野蛮的大西瓜3 小时前
BigBlueButton视频会议 vs 华为云会议的详细对比
人工智能·自动化·音视频·实时音视频·信息与通信·视频编解码
网络安全queen4 小时前
网络安全-企业环境渗透2-wordpress任意文件读&&FFmpeg任意文件读
安全·web安全·ffmpeg
野蛮的大西瓜4 小时前
文心一言对接FreeSWITCH实现大模型呼叫中心
人工智能·机器人·自动化·音视频·实时音视频·文心一言·信息与通信
野蛮的大西瓜5 小时前
BigBlueButton视频会议 vs 钉钉视频会议系统的详细对比
人工智能·自然语言处理·自动化·音视频·实时音视频·信息与通信·视频编解码
一只特立独行的程序猿6 小时前
Android音频中常用的BT Format和Profile介绍
android·音视频·bt profile·bt format
yerennuo7 小时前
FFmpeg库之ffmpeg
qt·ffmpeg
yerennuo7 小时前
FFmpeg 框架简介和文件解复用
ffmpeg
每月一号准时摆烂8 小时前
数字逻辑(五)——用二进制来表示音频和视频
嵌入式硬件·音视频