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

FFmpeg libswresample 模块的关键函数swr_convert 到底在干嘛?
目录一、先给一句话定性二、swr_convert 函数原型三、参数逐个拆重点在“样本不是字节”① SwrContext *s② out[]/ in[]—— 不是 void*packedS16 / S32 / U8planarFLTP / S16P③ in_count/ out_count单位是什么四、返回值到底什么意思五、最经典的坑残留 FIFO90%人踩现象原因正确 flush 姿势六、AVFrame 流派的“标准模板”解码 → swr → SDL / D3D七、S16 packed → SDL 最小完整例子八、常见翻车表血泪九、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*packedS16 / S32 / U8uint8_t* out[1] { (uint8_t*)pcm16 }; swr_convert(s, out, ...);planarFLTP / S16Puint8_t* out[2]; out[0] left; out[1] right;规则planar data[i] 每声道一块packed data[0] 全挤一起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输出样本数0FIFO 里攒着呢0出错常见误解“我给了 1024为啥返回 882”因为48000 → 44100 ratio 44100/48000 ≈ 0.91875五、最经典的坑残留 FIFO90%人踩现象最后几秒声音没了每次 flush 都有一小截原因swr 内部有 FIFO不够一帧不吐正确 flush 姿势while ((ret swr_convert(swr, out, out_max, nullptr, 0)) 0) { write_pcm(out, ret); }口诀innullptr, in_count0 冲 FIFO六、AVFrame 流派的“标准模板”解码 → swr → SDL / D3DAVFrame* 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 flushplanar 用 data[]永远别碰字节数。

最新新闻

日新闻

周新闻

月新闻