FFmpeg libswresample 模块的关键函数swr_convert 到底在干嘛?

目录

一、先给一句话定性

[二、swr_convert 函数原型](#二、swr_convert 函数原型)

三、参数逐个拆(重点在"样本不是字节")

[① SwrContext *s](#① SwrContext *s)

[② out\[\]/ in\[\]------ 不是 void*](#② out[]/ in[]—— 不是 void*)

[packed(S16 / S32 / U8)](#packed(S16 / S32 / U8))

[planar(FLTP / S16P)](#planar(FLTP / S16P))

[③ in_count/ out_count单位是什么?](#③ in_count/ out_count单位是什么?)

四、返回值到底什么意思?

[五、最经典的坑:残留 FIFO(90%人踩)](#五、最经典的坑:残留 FIFO(90%人踩))

现象

原因

[正确 flush 姿势](#正确 flush 姿势)

[六、AVFrame 流派的"标准模板"](#六、AVFrame 流派的“标准模板”)

[解码 → swr → SDL / D3D](#解码 → swr → SDL / D3D)

[七、S16 packed → SDL 最小完整例子](#七、S16 packed → SDL 最小完整例子)

八、常见翻车表(血泪)

[九、swr_convert 内部在干嘛](#九、swr_convert 内部在干嘛)

十、一句话总结


觉得有用,就请您帮忙点赞转发收藏吧,您的鼓励是我创作的动力,多谢看官。

由于能力水平有限,文中的错误或不严谨的地方在所难免,还请批评指正。

swr_convert 是 FFmpeg 中 libswresample 库的核心函数,用于执行音频重采样操作。它能够将音频流的‌采样率 ‌、‌采样格式 ‌(如从浮点转为整型)或‌声道布局‌(如从单声道转为立体声)进行转换,且不会改变音频的播放时长。

做音频播放 / 录音 / 转码的人,迟早都会撞上这一句:

复制代码
swr_convert(swr_ctx,
            out_buf, out_samples,
            in_buf,  in_samples);

抄能跑,但一问:**为什么返回值是输出帧数?in_samples 怎么给?planar 怎么摆?残留数据在哪?**​

今天把 swr_convert拆干净,不绕术语。


一、先给一句话定性

swr_convert 不是"格式转换器",是音频流水线工人:

负责 采样率 / 声道布局 / 样本格式 / 位深 全部打包干完。

核心任务只有三个:

复制代码
重采样(SRC)
声道重排(channel layout)
packed ↔ planar

二、swr_convert 函数原型

复制代码
int swr_convert(struct SwrContext *s,
                uint8_t *const out[], int out_count,
                const uint8_t *const in[], int in_count);

看着简单,其实 4 组语义:

复制代码
上下文
输出地址 / 想要多少样本
输入数据 / 实际多少样本

三、参数逐个拆(重点在"样本不是字节")


① SwrContext *s

一次初始化,反复用:

复制代码
swr_alloc_set_opts(nullptr,
     AV_CH_LAYOUT_STEREO,       // out layout
     AV_SAMPLE_FMT_S16,         // out fmt
     48000,                     // out rate

     AV_CH_LAYOUT_5POINT1_BACK, // in layout
     AV_SAMPLE_FMT_FLTP,        // in fmt
     44100,

     0, nullptr);

layout + rate + fmt 缺一不可


② out[]/ in[]------ 不是 void*

packed(S16 / S32 / U8)
复制代码
uint8_t* out[1] = { (uint8_t*)pcm16 };
swr_convert(s, out, ...);
planar(FLTP / S16P)
复制代码
uint8_t* out[2];
out[0] = left;
out[1] = right;

规则:

  • planar = datai 每声道一块

  • packed = data0 全挤一起

AVFrame::data 原样传就行


③ in_count/ out_count单位是什么?

单声道样本数(per channel sample count)

参数 意思
in_count 输入每个声道多少帧
out_count 我最多能吃多少帧

不是字节

不是 packet size

例:1024 帧立体声:

复制代码
in_count = 1024;
// FLTP: data[0][1024], data[1][1024]

四、返回值到底什么意思?

复制代码
int ret = swr_convert(...);

ret = 本次输出的 per-channel sample 数

ret 含义
>0 输出样本数
0 FIFO 里攒着呢
<0 出错

常见误解:

"我给了 1024,为啥返回 882?"

因为:

复制代码
48000 → 44100
ratio = 44100/48000 ≈ 0.91875

五、最经典的坑:残留 FIFO(90%人踩)

现象

  • 最后几秒声音没了

  • 每次 flush 都有一小截

原因

swr 内部有 FIFO,不够一帧不吐

正确 flush 姿势

复制代码
while ((ret = swr_convert(swr, out, out_max, nullptr, 0)) > 0) {
    write_pcm(out, ret);
}

口诀:

in=nullptr, in_count=0 = 冲 FIFO


六、AVFrame 流派的"标准模板"

解码 → swr → SDL / D3D

复制代码
AVFrame* dec = got_frame;
uint8_t* out[1] = { audio_buf };
int out_nb = swr_get_out_samples(swr, dec->nb_samples);

int ret = swr_convert(swr,
                      out, out_nb,
                      (const uint8_t**)dec->data,
                      dec->nb_samples);

// ret = 实际可播放样本数

swr_get_out_samples()先问大小,避免 alloc 太小


七、S16 packed → SDL 最小完整例子

复制代码
int dst_nb = swr_get_out_samples(swr_ctx, frame->nb_samples);
uint8_t* dst = (uint8_t*)malloc(dst_nb * 2 * 2);

uint8_t* out[1] = { dst };
swr_convert(swr_ctx, out, dst_nb,
             (const uint8_t**)frame->data, frame->nb_samples);

SDL_QueueAudio(dev, dst, dst_nb * 4);
free(dst);

八、常见翻车表(血泪)

症状 真凶
声音加速 in/out rate 反了
爆音 planar 当 packed
声道左右反 layout 没设
最后没声 没 flush
返回负 out_count 太小

九、swr_convert 内部在干嘛

复制代码
[in frame]
   ↓
delay / compensation
   ↓
重采样(polyphase filter)
   ↓
声道混合(downmix / upmix)
   ↓
planar ↔ packed
   ↓
[FIFO] → out

不是一帧进一帧出


十、一句话总结

swr_convert = 给样本数,吃样本数,返回输出样本数;

结束必须 nullptr/0 flush;planar 用 data\[\],永远别碰字节数。

相关推荐
2601_965448876 小时前
AI视频制作:做系列节气民俗视频音色不统一,AI 音色克隆省事的方法
人工智能·机器学习·音视频
美狐美颜SDK开放平台6 小时前
视频美颜SDK试用DEMO阶段应该测试什么?直播APP接入实操指南
开发语言·人工智能·深度学习·音视频·美颜sdk·直播美颜sdk·第三方美颜sdk
EasyDSS8 小时前
讲座视频资源散存易丢失?视频直播点播EasyDSS校园/视频融媒体平台高效管理视频
音视频·媒体·easydss
2601_9656196910 小时前
AI视频制作:做历史战争视频,兵力部署的老地图难找,AI怎么自动配战争地图?
人工智能·音视频
2601_9654490813 小时前
AI视频制作:做系列考古视频音色不统一,AI 音色克隆的完整流程
人工智能·机器学习·音视频
2601_9654490814 小时前
AI视频制作:做系列历史地图视频想固定音色,AI 音色克隆的流程实测
人工智能·音视频
智塑未来15 小时前
AI视频翻译配音工具怎么选?5款工具的链路覆盖对比
人工智能·音视频
做萤石二次开发的哈哈17 小时前
商场分区广播怎么开发?商用音频主机四大技能与音频文件管理实践
音视频·蓝海aiot一站式工作台·公共广播·智慧广播·萤石云开放平台·商用音频主机·矩阵路由
音视频牛哥19 小时前
大牛直播SDK(SmartMediaKit)iOS平台Unity3D RTSP/RTMP播放器集成实践
音视频·unity3d·ios rtmp播放器·ios rtsp播放器·ios unity3d播放器·ios unity rtsp·ios unity rtmp
美狐美颜SDK开放平台19 小时前
视频美颜SDK如何应对快速转头与大幅度面部动作?
android·人工智能·ios·音视频·直播美颜sdk·视频美颜sdk