[ffmpeg]音频格式转换

本文主要梳理 ffmpeg 中的音频格式转换。由于采集的音频数据和编码器支持的音频格式可能不一样,所以经常需要进行格式转换。

API 调用

常用 API

c 复制代码
struct SwrContext *swr_alloc(void);
int swr_init(struct SwrContext *s);
struct SwrContext *swr_alloc_set_opts(struct SwrContext *s,
                                      int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
                                      int64_t  in_ch_layout, enum AVSampleFormat  in_sample_fmt, int  in_sample_rate,
                                      int log_offset, void *log_ctx);
void swr_free(struct SwrContext **s);
int swr_convert(struct SwrContext *s, uint8_t **out, int out_count,
                                const uint8_t **in , int in_count);
int swr_convert_frame(SwrContext *swr,
                      AVFrame *output, const AVFrame *input);

初始化和销毁相关

swr_alloc 创建 context 上下文结构体

swr_init 初始化 context 结构体

swr_free 销毁结构体


SwsContext class 定义 libswresample\options.c

c 复制代码
static const AVClass av_class = {
    .class_name                = "SWResampler",
    .item_name                 = context_to_name,
    .option                    = options,
    .version                   = LIBAVUTIL_VERSION_INT,
    .log_level_offset_offset   = OFFSET(log_level_offset),
    .parent_log_context_offset = OFFSET(log_ctx),
    .category                  = AV_CLASS_CATEGORY_SWRESAMPLER,
};

swr_init 之前需要配置 context 一些参数,才能正确初始化。

c 复制代码
if (av_opt_set_int(s, "ocl", out_ch_layout,   0) < 0)
     goto fail;
 if (av_opt_set_int(s, "osf", out_sample_fmt,  0) < 0)
     goto fail;
 if (av_opt_set_int(s, "osr", out_sample_rate, 0) < 0)
     goto fail;
 if (av_opt_set_int(s, "icl", in_ch_layout,    0) < 0)
     goto fail;
 if (av_opt_set_int(s, "isf", in_sample_fmt,   0) < 0)
     goto fail;
 if (av_opt_set_int(s, "isr", in_sample_rate,  0) < 0)
     goto fail;
 if (av_opt_set_int(s, "ich", av_get_channel_layout_nb_channels(s-> user_in_ch_layout), 0) < 0)
     goto fail;
 if (av_opt_set_int(s, "och", av_get_channel_layout_nb_channels(s->user_out_ch_layout), 0) < 0)
     goto fail;

为了简化调用所以有了 swr_alloc_set_opts接口,其主要就是做了 1. swr_alloc调用;2.参数设置。

由于其不像视频转换的 sws_getContext 接口,内部不会调用 swr_init,所以还需要调用一下初始化接口。

类型转换

swr_convert

swr_convert_frame

输出结果是直接写在输入的内存上的,所以 data 需要提前分配好内存

demo 调用

c 复制代码
m_asc = swr_alloc_set_opts(m_asc,
			m_ac->channel_layout, m_ac->sample_fmt, m_ac->sample_rate,
			av_get_default_channel_layout(m_inChannels), (AVSampleFormat)m_inSampleFmt, m_inSampleRate,
			0, 0);
ret = swr_init(m_asc);
const uint8_t* data[1];
data[0] = (uint8_t*)pcm;
int len = swr_convert(m_asc, m_pcm->data, m_pcm->nb_samples,
	data, m_pcm->nb_samples);
if (m_asc)
{
	swr_free(&m_asc);
}

其他

所有接口

c 复制代码
const AVClass *swr_get_class(void);
struct SwrContext *swr_alloc(void);
int swr_init(struct SwrContext *s);
int swr_is_initialized(struct SwrContext *s);
struct SwrContext *swr_alloc_set_opts(struct SwrContext *s,
                                      int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
                                      int64_t  in_ch_layout, enum AVSampleFormat  in_sample_fmt, int  in_sample_rate,
                                      int log_offset, void *log_ctx);
void swr_free(struct SwrContext **s);
void swr_close(struct SwrContext *s);
int swr_convert(struct SwrContext *s, uint8_t **out, int out_count,
                                const uint8_t **in , int in_count);
int64_t swr_next_pts(struct SwrContext *s, int64_t pts);
int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance);
int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map);
int swr_build_matrix(uint64_t in_layout, uint64_t out_layout,
                     double center_mix_level, double surround_mix_level,
                     double lfe_mix_level, double rematrix_maxval,
                     double rematrix_volume, double *matrix,
                     int stride, enum AVMatrixEncoding matrix_encoding,
                     void *log_ctx);
int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride);
int swr_drop_output(struct SwrContext *s, int count);
int swr_inject_silence(struct SwrContext *s, int count);
int64_t swr_get_delay(struct SwrContext *s, int64_t base);
int swr_get_out_samples(struct SwrContext *s, int in_samples);
unsigned swresample_version(void);
const char *swresample_configuration(void);
const char *swresample_license(void);
int swr_convert_frame(SwrContext *swr,
                      AVFrame *output, const AVFrame *input);
int swr_config_frame(SwrContext *swr, const AVFrame *out, const AVFrame *in);
相关推荐
昵称画3 小时前
交接班记录电子化:三班之间的信息不漏
开发语言·数据库·人工智能·低代码·php
“AI国潮设计-小江”3 小时前
【AIGC实战】Python+SDXL批量生成“潮汕英歌舞不倒翁”IP | 角色一致性与多场景融合方案,附完整代码
开发语言·人工智能·python·prompt·aigc
传奇开心果编程3 小时前
【Rust入门练中学】第6课:结构体与方法
开发语言·rust·结构体·编程语言理论·结构体方法·编程通用语言
code tsunami4 小时前
【无标题】
开发语言·python
CodeGL4 小时前
10、Python基础之进程和线程
开发语言·python
hetao17338375 小时前
2026-10-22~23 hetao1733837 的刷题记录
c++·算法
TechWayfarer5 小时前
PHP漏洞被利用,怎么揪出攻击IP?
开发语言·python·tcp/ip·网络安全·php
王老师青少年编程6 小时前
2025年6月GESP真题及题解(C++三级): 选择题和判断题(题解)
c++·真题·gesp·答案·csp·三级·信奥赛
卡卡~~7 小时前
“101计划”核心课程实践教材《数据实验结构指导-C++语言版》题目集
开发语言·c++·学习·算法
qq_406981037 小时前
大白话rust系列09 函数调用两次有什么错?
开发语言·python·rust