第一部分:核心概念与基础理论
在开始编码之前,必须理解音视频编解码的基本原理。

音视频数字化的基础
- 模拟信号 vs. 数字信号:自然界的声音和图像是连续的模拟信号,计算机只能处理离散的数字信号,需要通过 采样 和 量化 将模拟信号转换为数字信号。
- 采样:在时间轴上对信号进行“拍照”,单位是赫兹,CD 音质的采样率是 44.1kHz,意味着每秒采样 44,100 次。
- 量化:在幅度轴上将采样值划分为有限个等级,单位是比特,16-bit 量化意味着每个采样值用 16 个二进制位表示。
- 原始数据量巨大:一秒钟的 1080p (1920x1080) 24fps 的 YUV420 格式视频,原始数据量约为
1920 * 1080 * 1.5 * 24 ≈ 74.66 Mbps,一段 3 分钟的歌曲(44.1kHz/16-bit/立体声)原始数据量约为44100 * 2 * 16 * 180 / 8 / 1024 / 1024 ≈ 30.3 MB,如此大的数据量不经过压缩是无法存储和传输的。
编解码的核心:压缩
压缩分为两种:
- 无损压缩:可以完全、无失真地恢复原始数据,压缩率有限,常用于音频编码(如 FLAC, ALAC)。
- 有损压缩:通过去除人眼/人耳不敏感的数据来大幅减小文件体积,无法完全恢复原始数据,这是音视频领域的主流技术。
- 视频压缩:利用 空间冗余(一帧图像内相邻像素相似)和 时间冗余(相邻帧之间内容相似),关键技术包括 变换编码(如 DCT)、量化、熵编码(如 Huffman, CAVLC/CABAC)和 运动估计/补偿(处理时间冗余)。
- 音频压缩:利用 心理声学模型,去除人耳听不到的声音(低于听阈)和被强音掩盖的弱音(掩蔽效应),关键技术包括 离散余弦变换、量化 和 熵编码。
主流编解码标准
- 视频:
- H.264/AVC:目前应用最广泛的视频编码标准,在压缩率和计算复杂度之间取得了很好的平衡,广泛应用于蓝光、网络视频(如 YouTube)、视频会议等。
- H.265/HEVC:H.264 的继任者,压缩率比 H.264 提升约 50%,但编码和解码的复杂度也显著增加,用于 4K/8K 超高清视频流。
- AV1:由谷歌、Netflix 等公司主导的开源、免版税的视频编码格式,压缩效率媲美 H.265,是未来的重要方向。
- 音频:
- AAC (Advanced Audio Coding):MP3 的继任者,在相同比特率下音质更好,是目前最主流的音频编码格式(如 iTunes, YouTube, iOS)。
- Opus:一个极其灵活和高效的音频编解码器,支持从窄带到超宽带的各种比特率和采样率,专为网络实时传输(如 WebRTC, Discord)设计。
- FLAC:无损音频压缩的代表。
第二部分:Visual C++ 技术栈与关键组件
使用 C++ 进行音视频开发,离不开一些关键的库和框架。
核心解码库
直接编写一个完整的编解码器(如 H.264 解码器)是极其复杂的,通常依赖于现成的底层库。
- FFmpeg:业界事实上的标准,一个集录制、转换、流化音视频文件的开源项目,它包含了几乎所有的音视频编解码器、格式封装器、协议处理器和滤镜。
- 核心组件:
libavcodec:提供编解码功能。libavformat:负责音视频文件的封装和解封装。libavutil:提供公共的工具函数,如数据结构、数学运算、哈希等。libswscale:用于图像色彩空间和尺寸的转换。libswresample:用于音频采样率转换和格式重采样。
- 集成方式:通常使用预编译好的库文件(如
gpl或lgpl版本)和头文件,通过 Visual Studio 的项目配置进行链接。
- 核心组件:
图形渲染库
解码后的原始数据(如 YUV 视频、PCM 音频)需要显示出来。

- DirectShow:Windows 平台下的传统多媒体框架,基于 COM 组件,比较复杂,但功能强大且稳定,很多旧的音视频应用仍在使用。
- Media Foundation (MF):微软推荐的现代多媒体框架,从 Windows Vista 开始引入,是 DirectShow 的替代品,它更易于使用(基于 COM,但有更现代的 C++ 封装),支持硬件加速,并且是 Windows 8/10/11 上处理多媒体的首选。
- Direct2D / Direct3D:更底层的图形 API,通常用于高性能的游戏和视频播放器渲染,可以实现复杂的视觉效果和硬件加速的图像处理,FFmpeg 解码后的 YUV 帧可以通过
libswscale转换为 RGB,然后使用 Direct2D 绘制到窗口上。
开发环境
- Visual Studio:首选的 IDE,建议安装 “使用 C++ 的桌面开发” 工作负载,它包含了 C++ 编译器、Windows SDK 和必要的工具。
- CMake:一个跨平台的构建工具,对于像 FFmpeg 这样结构复杂的项目,使用 CMake 来管理编译和链接过程是最佳实践。
第三部分:实践步骤 - 以 FFmpeg + DirectShow/MF 为例
下面我们以开发一个简单的视频播放器为例,梳理整个流程。
步骤 1:环境搭建
- 安装 Visual Studio:确保安装了 C++ 桌面开发工作负载。
- 获取 FFmpeg 库:
- 访问 FFmpeg 官网 下载 Windows 预编译版本。
- 解压文件,你会得到
bin,include,lib三个文件夹。 - 将
bin目录下的.dll文件(如avcodec-59.dll,avformat-59.dll等)复制到你的 Visual Studio 项目的输出目录(如x64/Debug)。
- 配置 Visual Studio 项目:
- 创建一个新的 Windows 桌面应用程序 项目。
- 项目属性 -> C/C++ -> 常规 -> 附加包含目录:添加 FFmpeg 的
include目录。 - 项目属性 -> 链接器 -> 常规 -> 附加库目录:添加 FFmpeg 的
lib目录。 - 项目属性 -> 链接器 -> 输入 -> 附加依赖项:添加需要链接的库文件,如
avcodec.lib; avformat.lib; avutil.lib; swscale.lib; swresample.lib。
步骤 2:使用 FFmpeg 解码视频
- 注册所有组件:
av_register_all()(旧版) 或avformat_network_init()(新版)。 - 打开媒体文件:使用
avformat_open_input()打开视频文件,并使用avformat_find_stream_info()获取流信息。 - 查找视频流:遍历所有流,找到类型为
AVMEDIA_TYPE_VIDEO的流。 - 查找解码器:使用
avcodec_find_decoder_by_name()或avcodec_find_decoder()找到对应的解码器。 - 打开解码器:使用
avcodec_open2()打开解码器,并获取其上下文。 - 读取和解码数据包:
- 循环调用
av_read_frame()从文件中读取一个数据包。 - 如果数据包的类型是我们找到的视频流,则将其送入解码器。
- 调用
avcodec_send_packet()发送数据包。 - 循环调用
avcodec_receive_frame()接收解码后的原始帧(AVFrame结构体,通常包含 YUV 数据)。
- 循环调用
- 释放资源:

