【音视频开发入门】FFmpeg小白必读:封装、编码、裸流与播放器底层原理图解

【音视频开发入门】FFmpeg小白必读:封装、编码、裸流与播放器底层原理图解 前言 最近开始系统学习 FFmpeg 音视频开发面对繁杂的音视频概念MP4、H.264、AAC、YUV、PCM...初学者很容易一头雾水。今天通过拜读国内音视频启蒙导师雷霄骅雷神的经典博客并结合实际的数据计算终于把音视频播放的底层逻辑理顺了。特此记录希望也能帮到正在入门的你一、 核心概念封装格式 vs 编码格式在音视频领域初学者最容易混淆的就是这两个词。我们可以用**“快递包裹”**来生动地理解它们编码格式Codec / 压缩算法—— “包裹里的物品”未压缩的原始音视频数据体积极其庞大。编码格式就是一套压缩算法负责将这些庞大的原始数据压缩成较小的体积。常见视频编码H.264 (AVC)、H.265 (HEVC)、VP9、AV1。常见音频编码AAC、MP3、AC-3。封装格式Container / 容器—— “快递包装盒”把压缩好的视频轨道、音频轨道、字幕和元数据如时长、分辨率、时间戳 PTS/DTS按照一定的规则“打包”放到一个文件里。它的作用是整合和同步。常见封装格式MP4、MOV、MKV、FLV、AVI、TS。总结以.mp4文件为例MP4 只是个包装盒封装格式里面装的视频通常是 H.264 编码音频通常是 AAC 编码。二、 破除迷信MP4 就是 MPEG-4 吗很多人以为“MP4 就是 MPEG-4”或者“MPEG-4 是一种视频格式”这其实是严重误解MPEG-4 是一个极其庞大的国际标准“全家桶”ISO/IEC 14496它包含了很多个“部分Parts”。我们常说的音视频概念其实分别对应着它不同的子集MPEG-4 Part 2 (Visual)早期的视频压缩标准以前网上的 AVI 电影DivX/Xvid就是基于它。MPEG-4 Part 3 (Audio)大名鼎鼎的 AAC 音频它的初衷是为了取代 MP3目前是绝对的主流。MPEG-4 Part 10 (Advanced Video Coding)这就是 H.264由 ITU-T 和 ISO/MPEG 联合制定H.264 和 MPEG-4 AVC 是同一个东西的两个名字。MPEG-4 Part 14 (MP4 File Format)这才是 MP4 封装格式定义了如何将音视频打包的“容器”标准。三、 致敬雷神音视频播放底层流水线当我们在播放器里打开一个网络视频比如 RTMP 直播流或本地 MP4 文件时底层到底发生了什么根据雷霄骅前辈的总结整个流程可以抽象为以下几个步骤解协议(本地文件播放不需要该步骤)-解封装-解码获取裸流-将音视频裸流进行同步解协议 (Deprotocol)针对网络流剥离 HTTP/RTMP 等协议的控制信令保留纯粹的封装媒体数据如 FLV/TS。(播放本地文件无此步)解封装 (Demuxing)像拆快递一样把 MP4/FLV 盒子拆开分离出独立的视频压缩流如 H.264和音频压缩流如 AAC。解码 (Decoding)最耗性能的一步将压缩算法还原为庞大的原始像素数据视频和音频采样数据。获取裸流 (Raw Data)音频解码后得到PCM 数据视频解码后得到YUV 或 RGB 数据视音频同步 (A/V Sync)因为音视频解码速度不同必须依据解封装时提取的PTS显示时间戳将画面和声音对齐防止“光打雷不下雨”。播放输出将同步好的 PCM 送给声卡YUV/RGB 送给显卡渲染。四、 灵魂拷问为什么要花这么大代价去“编码”既然解码那么耗费性能我们为什么不直接传输和播放原始的“裸流”数据呢我们来算一笔账就知道了1. 视频裸流计算 (以 YUV420P 为例)视频本质上是连续的图片帧。假设我们要看一部1080P、60帧的视频。 在音视频开发中最常用的原始视频格式是YUV420P利用人眼对亮度敏感、色度不敏感的特性去除了部分色彩数据平均每个像素占1.5 个字节。一帧画面的大小1920 * 1080 * 1.5 Bytes ≈ 2.96 MB一秒钟的视频大小2.96 MB * 60 FPS ≈ 178 MB/s一部 2 小时的电影仅画面178 MB/s * 7200 秒 ≈ 1.2 TB2. 音频裸流计算 (PCM)声音是模拟信号需经过采样、量化变为 PCM 数字信号。假设是常见的CD 音质44100Hz 采样率16bit 位深双声道。一秒钟的声音大小44100 * (16/8) * 2 176,400 Bytes ≈ 172 KB/s结论如果不压缩1080P 60帧的视频一秒钟就要耗费178 MB的带宽和存储这在当前的互联网环境下是完全无法承受的。 而H.264 等编码标准利用帧内预测和帧间预测技术能将这 178 MB 的数据压缩到仅仅 1~5 MB 左右压缩比高达上百倍这才是流媒体时代得以存在的基石。总结今天理清了 FFmpeg 开发的宏观地图解封装 - 解码 - 处理裸流(重采样/加滤镜) - 编码 - 封装。所有的代码实现其实都是在围绕这条流水线做文章。