2252 字
11 分钟
音视频基础

音视频基础 #1#

1. 音频参数 (ZPCM)#

采样率 (Sample Rate)#

  • 采样率 sample_rate 44100 (CD)

    1s内 有44100的声音被采集下来,值越大,声音越真实

通道数 (Channels)#

一般是左右声道,5.1通道,双通道的话会是 两个通道同时采样。

样本大小/格式 (Sample Size)#

AV_SAMPLE_FMT_S16 (16位) AV_SAMPLE_FMT_FLTP (float存储、效率更高)

样本类型#

AV_SAMPLE_FMT_S16 在内存的格式就像
c1 c2 c1 c2 ...
AV_SAMPLE_FMT_S16P 的格式为
c1 c1 c1 ... c2 c2 c2 ...

2. H264 / AVC 视频编码标准#

概述#

AVC(Advanced Video Coding) 是一种广泛使用的视频压缩标准,通常称为H.264,能够以较低的比特率提供高质量的视频。

编码架构#

  • VCL:负责核心的视频编码工作,输出的是表示视频像素数据的切片(Slices)。这是编码器的”核心技术部门”。
  • NAL:负责将 VCL 产生的切片以及其他重要信息,封装成一种标准化、适用于网络传输的包,即 NAL 单元。这是公司的”包装和物流部门”

NAL 单元#

单纯来看,每个帧都可以视作一个NAL单元 (SPS,PPS)除外,一般来说编码器编出的首个帧中,往往帧前面都带有00 00 00 01 或者 00 00 00 01 分隔符, 再往后就是I帧了。

SPS 和 PPS#

SPS(Sequence Parameter Set,序列参数集)和 PPS(Picture Parameter Set,图像参数集)的区别:

SPS:

  • 作用于整个视频序列
  • 包含视频序列的全局参数,如档次(profile)、级别(level)、分辨率、帧率等

PPS:

  • 作用于单个图像(帧)或一组图像
  • 包含与图像编码相关的参数,如熵编码模式、量化参数、去块滤波强度等

image-20251030180447212

image-20251030180503844

GOP (Group of Picture)#

在视频编码序列中,GOPGroup of picture(图像组),指两个I帧之间的距离,Reference(参考周期)指两个P帧之间的距离。一个I帧所占用的字节数大于一个P帧,一个P帧所占用的字节数大于一个B帧。

所以在码率不变的前提下,GOP值越大,P、B帧的数量会越多,平均每个I、P、B帧所占用的字节数越多,也就更容易获取较好的图像质量Reference越大,B帧的数量越多,同理也更容易获得较好的图像质量。

GOP Size (N)#

指的是一个GOP内所包含的总帧数

  • 长GOP(N值大):压缩效率高,文件小/码率低。但拖动不灵敏,错误恢复慢。常用于点播、存储
  • 短GOP(N值小):压缩效率低,文件大/码率高。但拖动灵敏,容错性好。常用于直播、视频会议

GOP Structure (M)#

指的是两个参考帧(I帧或P帧) 之间的B帧数量

一个典型的GOP结构:IBBPBBPBBPBBPBB

开放GOP vs. 封闭GOP#

  • 封闭GOP

    • 每个GOP都是完全独立的。GOP内的B帧不会引用上一个GOP的帧。
    • 优点:无缝拼接、随机访问更精确、容错性好。
    • 应用广播电视、视频编辑、流媒体
  • 开放GOP

    • GOP内的B帧可以向前引用上一个GOP的帧。
    • 优点:压缩效率更高。
    • 应用本地文件存储,追求极限压缩率的场景。

GOP 特性对比#

特性短GOP / 多I帧长GOP / 少I帧
压缩效率
文件大小/码率
随机访问/拖动快且准慢且不准
容错性
编码延迟
典型应用直播、视频会议、视频编辑视频点播、文件存储

3. 视频流的完整构成#

第一部分:全局说明书(参数集)#

这是全书的前言和目录,告诉解码器如何解读后续所有内容。

  • SPS(序列参数集)

    • 相当于全书的出版规格:纸张大小(分辨率)、印刷色彩标准(色彩空间)、装订方式(编码档次)。
    • 定义了整个视频序列的全局参数。
  • PPS(图像参数集)

    • 相当于章节排版规范:字体大小、行间距、页边距。
    • 定义了单帧图像的编码细节。
  • VPS(视频参数集,H.265/HEVC特有)

    • 相当于多卷本的协调说明,用于复杂场景和多层编码。

重要性:没有这些说明书,后面的视频数据完全无法解码!

第二部分:内容组织单元(GOP序列)#

这是全书的核心内容,由多个章节(GOP) 连续组成。

[GOP 1] → [GOP 2] → [GOP 3] → ... → [GOP N]

每个GOP(章节)内部包含

  • I帧(章节开头):完整的独立页面,不依赖前后内容就能看懂。
  • P帧(承上启下的段落):基于前面内容的总结和发展,只写变化的部分。
  • B帧(细节补充):同时参考前后内容,做最精细的描述。

第三部分:辅助信息(元数据)#

这些是书中的脚注、批注和索引

  • SEI(补充增强信息):包含时间码、版权信息、编码设置等。
  • AUD(访问单元分隔符):相当于章节标记,明确指示每一帧的开始位置。

第四部分:实际的数据切片#

这是书中的具体文字和图片

  • 切片(Slices):一帧图像可能被分割成多个切片,每个切片封装在一个NAL单元中。

完整视频流的时序结构#

[全局说明书区]
SPS → PPS → VPS(可选) → SEI
[内容数据区 - 循环往复]
→ AUD → I帧切片 → I帧切片 ... ← GOP 1开始
→ AUD → B帧切片 → B帧切片 ...
→ AUD → P帧切片 → P帧切片 ...
→ AUD → B帧切片 → B帧切片 ...
→ AUD → I帧切片 → I帧切片 ... ← GOP 2开始(可能是场景切换)
...(继续循环)...

不同封装格式的影响#

视频流可以存储在不同的”书架”(容器)中:

  • 原始H.264/H.265流(.h264, .hevc):NAL单元的原始序列。
  • MP4/MKV文件:将NAL单元重新组织,添加索引。
  • 传输流(TS):将NAL单元分割成固定大小的包,添加时间戳和纠错信息。

4. FFmpeg SDK 软硬解码基础#

处理流程#

解封装 -> 软硬编码 -> 像素格式转换 -> 重采样 -> pts/dts -> 同步策略

解封装函数#

  • av_register_all() - 注册所有的封装格式,全局注册
  • avformat_network_init() - 通过网络打开文件
  • avformat_open_input(...)
  • avformat_find_stream_info() - 打开文件并解析
  • av_find_best_stream(...) - 查找最佳流

核心数据结构#

AVFormatContext - 格式上下文#

比喻:整个DVD光盘 + DVD播放机

// 它包含的信息就像DVD播放机的屏幕显示:
AVFormatContext {
- 文件格式: "MP4", "AVI", "MKV" // 就像知道是DVD、VCD还是蓝光
- 持续时间: 2小时15分钟 // 影片总长度
- 比特率: 1500 kbps // 数据读取速度
- 元数据: 标题、作者、版权信息 // 光盘封面信息
- 流列表: [视频流, 音频流1, 音频流2, ...] // 光盘包含的所有轨道
- 文件位置: 当前播放到01:23:45 // 当前播放进度
}

AVStream - 流信息#

比喻:光盘里的不同轨道

// 每个轨道的信息:
AVStream {
- 流类型: 视频 / 音频 / 字幕 // 这是什么轨道?
- 编解码器参数: H.264, AAC, SRT // 数据的编码格式
- 时间基: 1/1000 秒 // 时间计量单位
- 帧率: 25 fps // 视频帧率
- 分辨率: 1920x1080 // 视频尺寸
- 采样率: 44100 Hz // 音频采样率
- 时长: 2小时15分钟 // 该轨道的长度
- 索引: 0, 1, 2... // 轨道编号
}

AVPacket - 数据包#

比喻:从光盘里读取出来的一小段压缩数据

// 每个数据包就像一截电影胶片:
AVPacket {
- 数据指针: 指向压缩数据的内存地址 // 胶片上的图像
- 数据大小: 65536 字节 // 胶片的长度
- 流索引: 0 // 属于哪个轨道?
- 显示时间戳(PTS): 123456 // 什么时候显示?
- 解码时间戳(DTS): 123450 // 什么时候解码?
- 持续时间: 40ms // 播放多长时间?
- 关键帧标志: 是/否 // 是否是I帧?
}

操作函数比喻#

avformat_open_input() // 插入光盘到播放机
avformat_find_stream_info() // 读取光盘目录信息
av_read_frame() // 从光盘读取下一段数据
avformat_close_input() // 弹出光盘,关闭播放机

对于 H.264/H.265 视频流#

在大多数情况下:

  • 一个 AVPacket 包含一个完整的 NAL 单元
  • AVPacket 的 data 字段指向的就是 NAL 单元的起始位置
// 典型情况:一个AVPacket对应一个NAL单元
AVPacket {
.data = [NAL起始码] [NAL头] [NAL负载] // 整个NAL单元数据
.size = NAL单元的总长度
.stream_index = 视频流索引
}

总结关系#

FFmpeg结构比喻职责生命周期
AVFormatContextDVD播放机+光盘管理整个媒体文件从打开文件到关闭文件
AVStream光盘轨道描述单一媒体流的信息存在于FormatContext的生命周期内
AVPacket电影胶片段存储压缩的媒体数据短暂存在,解码后即可释放
音视频基础
https://rinzemoon.top/
作者
泠时月
发布于
2025-10-30
许可协议
CC

部分信息可能已经过时

封面
示例歌曲
示例艺术家
封面
示例歌曲
示例艺术家
0:00 / 0:00