流媒体过滤器 - AVFilter
函数说明 :
avfilter_init_str参数选项:
key | value type | value 选项 | 默认值 | 解释 |
---|---|---|---|---|
NULL | NULL | NULL | NULL | NULL |
key | value type | value 选项 | 默认值 | 解释 |
---|---|---|---|---|
sample_fmts | STRING | 0 | 格式化后的采样格式 | |
sample_rates | STRING | 0 | 格式化后的采样率 | |
channel_layouts | STRING | 0 | 格式化后的声道布局 |
key | value type | value 选项 | 默认值 | 解释 |
---|---|---|---|---|
inputs | INT | INT16_T_MAX | 2 | 输入音频数 |
duration | INT | 0 ~ 2 | 0 | 0 ~ longest (以最长输入为准) 1 ~ shortest (以最短输入为准) 2 ~ first (以首个输入为准) |
dropout_transition | FLOAT | INT32_T_MAX | 2.0 | 当输入流结束时,用于音量重新正规化的转换时间(以秒为单位) |
weights | STRING | 0 | “1 1” | 为每个输入设置权重 |
normalize | BOOL | ture or false | true | 规模的输入 |
key | value type | value 选项 | 默认值 | 解释 |
---|---|---|---|---|
time_base | AV_OPT_TYPE_RATIONAL | INT32_T_MAX | 0 | 时间基 |
sample_rate | INT | INT32_T_MAX | 0 | 输入采样率 |
sample_fmt | AV_OPT_TYPE_SAMPLE_FMT | -1 ~ INT32_T_MAX | -1 | 输入采样格式 |
channel_layout | STRING | 输入声道布局 | ||
channels | INT | INT32_T_MXA | 0 | 声道数 |
key | value type | value 选项 | 默认值 | 解释 |
---|---|---|---|---|
volume | STRING | 1.0 | 设置音量调节表达式 1.0 = 100% | |
precision | INT | 0 ~ 2 | 1 | 选择数学精度 0 ~ fixed (select 8-bit fixed-point) 1 ~ float (select 32-bit fixed-point) 2 ~ double (select 64-bit fixed-point) |
eval | INT | 0 ~ 1 | 0 | specify when to evaluate expressions 0 ~ once (eval volume expression once) 1 ~ frame (eval volume expression per-frame) |
replaygain | INT | 0 ~ 3 | 0 | Apply replaygain side data when present 0 ~ drop (replaygain side data is dropped) 1 ~ ignore (replaygain side data is ignored) 2 ~ track (track gain is preferred) 3 ~ album (album gain is preferred) |
replaygain_preamp | DOUBLE | -15.0 ~ 15.0 | 0.0 | Apply replaygain pre-amplification |
replaygain_noclip | BOOL | true or false | true | Apply replaygain clipping prevention |
音频功能流程 :
//本实例不做任何异常判断
//核心 使用过滤器必备
AVFilterGraph * pFilterGraph = avfilter_graph_alloc();
/***************** 查找获取相应的过滤器 *****************/
//abuffersink - 音频出口
const AVFilter* pFilterABuffsink = avfilter_get_by_name("abuffersink");
//aformat - 对音频进行重新格式化
const AVFilter* pFilterAFormat = avfilter_get_by_name("aformat");
//amix - 将音频数据混音汇总
const AVFilter* pFilterAMix = avfilter_get_by_name("amix");
//abuffer - 音频入口
const AVFilter* pFilterABuffer = avfilter_get_by_name("abuffer");
//volume - 音频音量调整
const AVFilter* pFilterVolume = avfilter_get_by_name("volume");
/************ 根据相应过滤器创建过滤器实例 ************/
//abuffersink实例
AVFilterContext* pFilterCtxABuffSink = avfilter_graph_alloc_filter(pFilterGraph, pFilterABuffsink, "sink");
//aformat实例
AVFilterContext* pFilterCtxAFormat = avfilter_graph_alloc_filter(pFilterGraph, pFilterAFormat, "format");
//amix实例
AVFilterContext* pFilterCtxAMix = avfilter_graph_alloc_filter(pFilterGraph, pFilterAMix, "mix");
//abuffer - 入口0 实例
AVFilterContext* pFilterCtxABuffer_0 = avfilter_graph_alloc_filter(pFilterGraph, pFilterABuffer, "buffer0");
//abuffer - 入口1 实例
AVFilterContext* pFilterCtxABuffer_1 = avfilter_graph_alloc_filter(pFilterGraph, pFilterABuffer, "buffer1");
//volume - 控制入口0的音量 实例
AVFilterContext* pFilterCtxVolume_0 = avfilter_graph_alloc_filter(pFilterGraph, pFilterVolume, "volume0");
/****************** 参数选项设置 ********************/
//abuffersink - 参数设置
avfilter_init_str(pFilterCtxABuffSink, nullptr);
//aformat - 参数设置 - 采样率:44100 | 采样格式:f32 | 声道布局:双声道
avfilter_init_str(pFilterCtxAFormat, "sample_rates=44100:sample_fmts=flt:channel_layouts=0x3");
//amix - 参数设置 - 输入音频流数:2 | 持续时长:最长的音频为准 | dropout_transition:输入流结束时,容量重整时间
avfilter_init_str(pFilterCtxAMix, "inputs=2:duration=longest:dropout_transition=0");
//abuffer入口0 - 参数设置 - 采样率:44100 | 采样格式:s16 | 声道布局:双声道
avfilter_init_str(pFilterCtxABuffer_0, "sample_rate=44100:sample_fmt=s16:channel_layout=0x3");
//abuffer入口1 - 参数设置 - 采样率:48000 | 采样格式:flt | 声道布局:双声道
avfilter_init_str(pFilterCtxABuffer_1, "sample_rate=48000:sample_fmt=flt:channel_layout=0x3");
//volume 0 - 参数设置 - 音量 10%
avfilter_init_str(pFilterCtxVolume_0, "volume=0.1");
/************ 对目前个不相关的过滤器做连接 *************/
//abuffer入口0 -> volume0
avfilter_link(pFilterCtxABuffer_0, 0, pFilterCtxVolume_0, 0);
//volume0 -> amix 混音
avfilter_link(pFilterCtxVolume_0, 0, pFilterCtxAMix, 0);
//abuffer入口1 -> amix
avfilter_link(pFilterCtxABuffer_1, 0, pFilterCtxAMix, 1);
//amix -> aformat
avfilter_link(pFilterCtxAMix, 0, pFilterCtxAFormat, 0);
//aformat -> abuffersink
avfilter_link(pFilterCtxAFormat, 0, pFilterCtxABuffSink, 0);
//graph整合
avfilter_graph_config(pFilterGraph, nullptr);
bool bReadFileEnd_0 = false;
bool bReadFileEnd_1 = false;
AVFrame* pFrame_0 = av_frame_alloc();
AVFrame* pFrame_1 = av_frame_alloc();
AVFrame* pFrameOut = av_frame_alloc();
/******
*
* 打开文件、初始化avframe操作
*
******/
while(!bReadFileEnd_0 || !bReadFileEnd_1 )
{
/******* 输入其一 *******/
if(!bReadFileEnd_0)
{
/***
* 读取 pcm 一帧数据
***/
if(/* Read File End */) bReadFileEnd_0 = ture;
}
/******* 输入其二 *******/
if(!bReadFileEnd_1)
{
/***
* 读取 pcm 一帧数据
***/
if(/* Read File End */) bReadFileEnd_1 = ture;
}
/******* 只要其中一路还有数据就必须得传入数据 *******/
//传入的数据流其一 - 通过abuffer0传入
av_buffersrc_add_frame(pFilterCtxABuffer_0, bReadFileEnd_0 ? nullptr : pFrame_0);
//传入的数据流其二 - 通过abuffer1传入
av_buffersrc_add_frame(pFilterCtxABuffer_1, bReadFileEnd_1 ? nullptr : pFrame_1;
/****** 读取混音后的数据 ******/
while(true)
{
//从abuffersink中获取一帧数据
if(av_buffersink_get_frame(pFilterCtxABuffSink, pFrameOut) < 0)
{
//读取失败则表示过滤器中已经不存在数据了,需要重新往里添加帧
break;
}
/***
* 将数据写入输出文件
***/
}
}