SwrContext
一、SwrContext 的重要字段
SwrContext
是音频重采样的核心配置对象,其关键字段决定了重采样的行为和性能。以下是常用字段及其作用:
字段名称 | 类型 | 作用 | 典型值示例 |
---|---|---|---|
in_sample_rate |
int | 输入音频的采样率(Hz)。 | 44100 |
out_sample_rate |
int | 输出音频的采样率(Hz)。 | 48000 |
in_ch_layout |
AVChannelLayout | 输入音频的声道布局(如立体声、单声道)。 | AV_CH_LAYOUT_STEREO |
out_ch_layout |
AVChannelLayout | 输出音频的声道布局。 | AV_CH_LAYOUT_MONO |
in_sample_fmt |
AVSampleFormat | 输入音频的样本格式(如 PCM、浮点)。 | AV_SAMPLE_FMT_S16 |
out_sample_fmt |
AVSampleFormat | 输出音频的样本格式。 | AV_SAMPLE_FMT_FLTP |
filter |
const char * | 重采样滤波器名称(如 Lanczos、Sinc)。 | SWR_FILTER_LANCZOS |
speed |
double | 重采样速度倍数(1.0 = 实时,>1.0 加速)。 | 1.0 |
channel_map |
const int * | 声道映射表(高级用法:自定义声道顺序)。 | NULL(默认布局) |
error_occurred |
int | 错误标志(非零表示重采样过程中发生错误)。 | 0(成功)/-1(失败) |
buffer |
uint8_t ** | 内部缓冲区指针(用于存储中间音频数据)。 | 由 libswresample 自动管理 |
buffer_len |
int | 内部缓冲区长度(字节)。 | 自动调整 |
二、SwrContext 的重要函数
以下是使用 SwrContext
时最常用的函数及其作用:
1. swr_alloc()
c
SwrContext *swr_alloc(void);
- 作用 :分配一个空的
SwrContext
结构体(不初始化参数)。 - 返回值 :指向新分配的
SwrContext
,需检查是否为NULL
(内存不足)。
• 典型用法:
2. swr_alloc_set_opts()
c
SwrContext *swr_alloc_set_opts(
SwrContext **ctx,
const AVChannelLayout *in_ch_layout,
AVSampleFormat in_sample_fmt,
int in_sample_rate,
const AVChannelLayout *out_ch_layout,
AVSampleFormat out_sample_fmt,
int out_sample_rate,
double speed,
const char *filter,
const char *filter_name
);
- 作用 :一步到位 分配并初始化
SwrContext
,设置所有核心参数。 - 参数说明 :
- 输入参数(前 3 个):输入音频的布局、格式、采样率。
- 输出参数(后 3 个):输出音频的布局、格式、采样率。
- speed:重采样速度(1.0 表示实时处理)。
- filter :滤波器类型(如
SWR_FILTER_LANCZOS
)。 - 返回值 :成功返回配置后的
SwrContext
,失败返回NULL
。
- 关键点 :
- **替代
swr_alloc **:此函数内部已调用
swr_alloc` 无需手动初始化。 - 参数顺序:必须严格区分输入和输出参数,否则可能导致逻辑错误。
- **替代
- 示例:
3. swr_free()
c
void swr_free(SwrContext *ctx);
• 作用 :释放 SwrContext
占用的内存及内部缓冲区。
• 注意 :无论初始化是否成功,最终必须调用此函数避免内存泄漏。
• 示例:
4. swr_convert()
c
int swr_convert(
SwrContext *ctx,
uint8_t **out_buf,
int out_samples,
const uint8_t *in_buf,
int in_samples
);
• 作用 :执行实际的重采样操作。
• 参数 :
• in_buf :输入音频数据指针(需符合 in_sample_fmt
的格式)。
• in_samples :输入样本数量(以 in_sample_rate
为单位)。
• out_buf :输出缓冲区指针(需预分配,格式由 out_sample_fmt
决定)。
• out_samples :请求的输出样本数量(可能被调整)。
• 返回值 :实际输出的样本数量,或负数表示错误。
• 关键点 :
• 输入/输出缓冲区格式 :必须与 SwrContext
中的 in_sample_fmt
/out_sample_fmt
匹配。
• 缓冲区大小 :需提前分配足够空间(参考 swr_get_out_samples()
)。
5. swr_get_sample_rate()
c
int swr_get_sample_rate(SwrContext *ctx);
• 作用 :获取当前上下文的采样率(输入或输出,取决于调用时机)。
• 注意:在初始化后,输出采样率是固定的,输入采样率可能动态变化(如流式处理)。
6. swr_init()
swr_init
是 FFmpeg 中用于初始化音频重采样器(SwrContext
)的函数。它的作用是根据 swr_alloc_set_opts
或 swr_alloc_set_opts2
设置的参数,完成重采样器的内部配置和准备工作。以下是关于 swr_init
的详细说明:
##### 1. 函数原型
c
#include <libswresample/swresample.h>
int swr_init(SwrContext *s);
参数 | 类型 | 说明 |
---|---|---|
s |
SwrContext * |
音频重采样器上下文 |
返回值 | int |
成功返回 0 ,失败返回负的错误码 |
2. 功能说明
swr_init
的主要功能包括:
-
验证参数:
- 检查输入和输出的声道布局、采样格式、采样率等参数是否合法。
- 如果参数不合法,返回错误码(如
AVERROR(EINVAL)
)。
-
初始化内部状态:
- 根据输入和输出的参数,计算重采样器的内部状态(如滤波器系数、缓冲区大小等)。
- 如果输入和输出的采样率不同,初始化重采样滤波器。
-
分配内部资源:
- 分配重采样器所需的内存(如缓冲区、滤波器等)。
-
准备重采样:
- 完成所有准备工作,使重采样器可以开始处理音频数据。
3. 使用场景
swr_init
通常在以下步骤之后调用:
- 使用
swr_alloc()
或swr_alloc_set_opts()
/swr_alloc_set_opts2()
创建并配置SwrContext
。 - 调用
swr_init()
初始化重采样器。 - 使用
swr_convert()
进行音频重采样。
4. 返回值处理
swr_init
的返回值需要检查,如果返回值 < 0
,说明初始化失败。
常见错误码
错误码 | 说明 |
---|---|
AVERROR(EINVAL) |
参数不合法(如声道布局不支持) |
AVERROR(ENOMEM) |
内存分配失败 |
AVERROR(EOPNOTSUPP) |
不支持的采样格式或布局 |
四、完整使用示例
cpp
#include <libswresample/swresample.h>
#include <libavutil/channel_layout.h>
void setup_resampler(AVCodecContext *ac) {
// 创建 SwrContext
SwrContext *actx = swr_alloc();
if (!actx) {
fprintf(stderr, "Failed to allocate SwrContext\n");
return;
}
// 设置输入和输出的声道布局
AVChannelLayout out_ch_layout;
AVChannelLayout in_ch_layout;
// 输出声道布局:立体声(2声道)
av_channel_layout_default(&out_ch_layout, 2);
// 输入声道布局:从 AVCodecContext 中获取
av_channel_layout_copy(&in_ch_layout, &ac->ch_layout);
// 配置 SwrContext
int ret = swr_alloc_set_opts2(
&actx,
&out_ch_layout, // 输出声道布局
AV_SAMPLE_FMT_S16, // 输出采样格式
ac->sample_rate, // 输出采样率
&in_ch_layout, // 输入声道布局
ac->sample_fmt, // 输入采样格式
ac->sample_rate, // 输入采样率
0, // 日志偏移
NULL // 日志上下文
);
if (ret < 0) {
char errbuf[AV_ERROR_MAX_STRING_SIZE];
av_strerror(ret, errbuf, sizeof(errbuf));
LOGW("swr_alloc_set_opts2 failed: %s", errbuf);
return;
}
// 初始化重采样器
ret = swr_init(actx);
if (ret < 0) {
char errbuf[AV_ERROR_MAX_STRING_SIZE];
av_strerror(ret, errbuf, sizeof(errbuf));
LOGW("swr_init failed: %s", errbuf);
return;
}
LOGW("SwrContext initialized successfully");
// 使用 actx 进行重采样...
// 释放资源
swr_free(&actx);
}