尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

swr_alloc_set_opts2:FFmpeg 重采样里那个“一错全无声”的函数

swr_alloc_set_opts2:FFmpeg 重采样里那个“一错全无声”的函数 目录一、为什么不用 swr_alloc_set_opts()了二、函数原型三、参数逐个拆解四、FFmpeg → Qt6 QAudioSink 最常见正确模板对应 Qt6五、Planar vs PackedFFmpeg 解码出来通常是Qt / Windows / Pulse 想要六、swr_convert() 怎么写才不丢尾错误写法只写一次正确逻辑delay 必处理flush文件尾七、out_samples 到底怎么算八、Swresample Qt QAudioSink 完整最小闭环九、10 个 Swr 必踩坑速查表十、FFmpeg 4 / 5 / 6 兼容写法十一、一句话总结觉得有用就请您帮忙点赞转发收藏吧您的鼓励是我创作的动力多谢看官。由于能力水平有限文中的错误或不严谨的地方在所难免还请批评指正。结论先说​swr_alloc_set_opts2()是 FFmpeg ≥ 5.0 引入的“Swresample 2.0 API”它的出现只有一个目的把“你用错 layout 导致重采样炸了”这件事从运行时提前到编译期 返回错误。但现实是90% 的 FFmpeg 音频无声 / 爆音 / Qt QAudioSink 推出来像开水壶都是它填错参数。这篇文章我按原型 → 每个参数怎么坑你 → 正确姿势 → Qt 实战​ 拆干净。一、为什么不用swr_alloc_set_opts()了旧 APIFFmpeg 5SwrContext *swr swr_alloc_set_opts( nullptr, AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, 44100, AV_CH_LAYOUT_MONO, AV_SAMPLE_FMT_FLT, 48000, 0, nullptr );问题int64_t channel_layout→宏已废弃单声道/多平面 layout 语义模糊新 APIQt6 / FFmpeg ≥ 5 强烈推荐swr_alloc_set_opts2(swr, out_layout, out_fmt, out_rate, in_layout, in_fmt, in_rate, 0, nullptr);out 在前layout 用指针返回值可判错二、函数原型int swr_alloc_set_opts2( SwrContext **ps, const AVChannelLayout *out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, const AVChannelLayout *in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, int log_offset, void *log_ctx );三、参数逐个拆解参数真名新手误区psSwrContext 指针地址传 NULL / 野指针out_ch_layoutQt 播放端真实硬件布局​写错 → QAudioSink 爆out_sample_fmtQAudioSink 要的格式Int16 / Floatout_sample_rate声卡采样率44.1k / 48kin_ch_layoutFFmpeg 解码 layoutAAC 常是 monoin_sample_fmtAVFrame-formatFLTP 最常见in_sample_rateAVCodecContext-sample_rate顺序out → in先目标后源四、FFmpeg → Qt6 QAudioSink 最常见正确模板SwrContext *swr nullptr; AVChannelLayout in_layout AV_CHANNEL_LAYOUT_MONO; AVChannelLayout out_layout AV_CHANNEL_LAYOUT_STEREO; swr_alloc_set_opts2( swr, out_layout, AV_SAMPLE_FMT_S16, 44100, in_layout, AV_SAMPLE_FMT_FLTP, 48000, 0, nullptr ); if (!swr || swr_init(swr) 0) { qDebug(swr init failed); }对应 Qt6QAudioFormat fmt; fmt.setSampleRate(44100); fmt.setChannelConfig(QAudioFormat::ChannelConfigStereo); fmt.setSampleFormat(QAudioFormat::Int16);100% 对齐五、Planar vs PackedFFmpeg 解码出来通常是codecformatAACAV_SAMPLE_FMT_FLTPMP3AV_SAMPLE_FMT_S16POpusAV_SAMPLE_FMT_FLTQt / Windows / Pulse 想要Qt6 SampleFormatFFmpegInt16AV_SAMPLE_FMT_S16不是 S16PFloatAV_SAMPLE_FMT_FLT不是 FLTP错误示例in_sample_fmt AV_SAMPLE_FMT_S16; // 实际 frame 是 S16P → 爆音正确写法frame-format AV_SAMPLE_FMT_FLTP → swr 输入填 AV_SAMPLE_FMT_FLTP六、swr_convert() 怎么写才不丢尾错误写法只写一次swr_convert(swr, out_buf, out_samples, frame-data, frame-nb_samples);正确逻辑delay 必处理int out_samples swr_get_out_samples(swr, frame-nb_samples); uint8_t *out malloc(out_samples * 4); int ret swr_convert(swr, out, out_samples, (const uint8_t**)frame-data, frame-nb_samples);flush文件尾while (swr_convert(swr, out, out_samples, nullptr, 0) 0) { // 写 QAudioSink }不 flush → 最后 10~20ms 永远丢七、out_samples 到底怎么算int out_samples av_rescale_rnd( swr_get_delay(swr, in_rate) in_samples, out_rate, in_rate, AV_ROUND_UP );Qt 项目我偷懒版安全int out_samples frame-nb_samples * out_rate / in_rate 256;八、Swresample Qt QAudioSink 完整最小闭环// init swr_alloc_set_opts2(d-swr, (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, 44100, frame-ch_layout, (enum AVSampleFormat)frame-format, frame-sample_rate, 0, nullptr); swr_init(d-swr); // convert int os swr_get_out_samples(d-swr, frame-nb_samples); QByteArray pcm(os * 2 * 2, 0); uint8_t *out[] {(uint8_t*)pcm.data()}; swr_convert(d-swr, out, os, (const uint8_t**)frame-data, frame-nb_samples); // push d-audioSinkDev-write(pcm);九、10 个 Swr 必踩坑速查表坑现象out/in layout 写反声音像 8bit 游戏FLTP 当 FLT爆音忘了 swr_init直接返回 0swr_convert 不 flush尾音丢out_samples 太小underrun单声道 → stereo 不重采样QAudioSink StoppedAVChannelLayout 没 init段错误FFmpeg 4.x 用 opts2编译不过sample_rate 写错快进/慢放swr_free(swr) 没清下次 init 炸十、FFmpeg 4 / 5 / 6 兼容写法#if LIBSWRESAMPLE_VERSION_MAJOR 4 swr_alloc_set_opts2(swr, out_l, out_fmt, out_rate, in_l, in_fmt, in_rate, 0, nullptr); #else swr swr_alloc_set_opts(nullptr, AV_CH_LAYOUT_STEREO, out_fmt, out_rate, AV_CH_LAYOUT_MONO, in_fmt, in_rate, 0, nullptr); #endif十一、一句话总结swr_alloc_set_opts2 不是“重采样函数”是“音频世界观对齐函数”FFmpeg 的 Planar / Layout / Rate必须在这里一次性跪好跪对了 → QAudioSink 丝滑跪错 → 你怀疑人生三天。
返回列表