SwrContext初始化失败主因是参数不匹配,如声道布局与通道数不一致;输入输出格式须经swr_is_supported_format验证;采样率须为正整数;重采样需调用swr_init()。

SwrContext 初始化失败的常见原因
多数人卡在 swr_init() 返回负值,根本原因是输入/输出参数不满足 FFmpeg 的约束条件。比如用 AV_SAMPLE_FMT_S16 作为输出格式,却把 out_channel_layout 设为 AV_CH_LAYOUT_STEREO、out_channels 却填了 1 —— 两者必须匹配,否则 swr_init() 直接失败并返回 AVERROR(EINVAL)。
初始化前务必检查:
-
in_sample_fmt和out_sample_fmt都得是swr_is_supported_format()返回非零的格式(如AV_SAMPLE_FMT_FLTP、AV_SAMPLE_FMT_S16) -
in_channel_layout和out_channel_layout要用av_get_channel_layout_nb_channels()验证与in_channels/out_channels一致 -
in_sample_rate和out_sample_rate必须是正整数,且不能为 0 - 若需重采样,
out_sample_rate != in_sample_rate;若只需声道变换,可设为相等,但依然要调用swr_init()
如何正确分配和填充 SwrContext 输入缓冲区
swr_convert() 不接受裸指针数组,它要求输入是 uint8_t**,即指向每个平面(plane)起始地址的指针数组。对于 planar 格式(如 AV_SAMPLE_FMT_FLTP),每个声道一个 plane;对于 packed 格式(如 AV_SAMPLE_FMT_S16),所有声道数据交错存放,此时只需一个 plane,但 src_data[0] 指向整个 buffer,src_linesize[0] 是整块 buffer 字节数。
实操要点:
- 用
av_samples_alloc_array_and_samples()分配内存,它会自动按格式和布局计算 plane 数、每 plane 字节数、linesize - 手动填充时,对 planar 数据:每个
dst_data[i]对应第 i 个声道的起始地址;对 packed 数据:只用dst_data[0],其余为NULL - 传给
swr_convert()的src_nb_samples是「输入帧的采样点数」,不是字节数,也不是样本总数(例如 stereo 1024 点,这里填 1024,不是 2048)
swr_convert() 返回值为 0 或负值时怎么处理
swr_convert() 返回实际转换出的样本数(per-channel),不是字节数。返回 0 表示当前输入不足以产出一帧输出(常见于重采样时输入太短),不是错误;返回负值才是真错误,比如 AVERROR_INPUT_CHANGED 表示上下文参数被外部修改过,必须重新 swr_init()。
典型应对逻辑:
- 若返回 > 0:说明成功产出
ret个样本/声道,可用av_samples_get_buffer_size()计算实际占用字节数 - 若返回 == 0:缓存当前输入,等下次有更多数据再喂给
swr_convert()(尤其在实时流中很常见) - 若返回 av_err2str(ret) 查错,90% 是初始化参数没对齐,比如 layout 和 channels 不匹配,或 sample format 不支持
重采样 + 声道变换混合使用时的性能与精度取舍
FFmpeg 的 SwrContext 把重采样和声道映射合并在一次调用里完成,但底层策略受 swr_set_opts() 中 SWR_FLAG_RESAMPLE 和 SWR_FLAG_CHESSBOARD 影响。默认开启重采样,但声道变换是否启用“chessboard”布局(如 5.1→stereo 的智能混音)取决于 out_channel_layout 是否为标准布局且 swr_init() 接受。
要注意:
- 启用
SWR_FLAG_RESAMPLE(默认)会引入少量延迟(内部缓冲最多 1024 样本),对低延迟场景需调小out_sample_rate或用swr_set_compensation() - 若仅做声道复制(如 mono→stereo),用
av_opt_set_int(swr_ctx, "ich", 1, 0)和av_opt_set_int(swr_ctx, "och", 2, 0)显式设置,比靠 layout 推导更稳 -
AV_SAMPLE_FMT_FLTP到AV_SAMPLE_FMT_S16的转换默认用线性插值,精度够用;若需更高保真,可在swr_init()前调用swr_set_matrix()自定义声道混音系数
真正容易被忽略的是:每次调用 swr_convert() 后,swr_get_delay() 的返回值会变,这意味着你不能假设输出样本数 = 输入样本数 × (out_sr/in_sr),尤其在首帧和尾帧——缓冲区残留数据必须用 swr_convert(NULL, NULL, 0) 清空,否则最后一段音频会丢。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











