android生成预处理文件,FFmpeg:Android利用Filter进行音频数据预处理
前言
這篇文件簡單介紹下移動端Android系統下利用FFmpeg的Filter進行音頻數據預處理的方法。
按照慣例先上一份源碼 AndroidFFmpegFilter。
項目實現了:
FFmepg編譯須知
由于需要用到Filter模塊,
所以在FFmpeg編譯腳本中需要開啟相關編譯選項。
否則會出現 avfilter_get_by_name(filter_name) 找不到對應的處理器。
--enable-filters
#or
--enable-filter=name #name 指定需要使用到的filter name
如果不想自己編譯,可以使用項目編譯好的 動態庫。
使用FFmpeg相關動態庫
接下來要將ffmpeg的動態庫鏈接到我們的工程上面。
Filter相關只需要使用到libavfilter.so、libavformat.so、libavutil.so這三個動態庫。
參考代碼如下(提供CMake實現,Android.mk請自己轉換):
set(LIB_DIR ${PROJECT_SOURCE_DIR}/libs)
#設置ffmpeg的頭文件目錄位置
include_directories(${LIB_DIR}/include/ffmpeg)
#導入avfilter動態庫
add_library( avfilter
SHARED
IMPORTED )
set_target_properties( avfilter
PROPERTIES
IMPORTED_LOCATION
${LIB_DIR}/${ANDROID_ABI}/libavfilter-6.so )
#導入avformat動態庫
add_library( avformat
SHARED
IMPORTED )
set_target_properties( avformat
PROPERTIES
IMPORTED_LOCATION
${LIB_DIR}/${ANDROID_ABI}/libavformat-57.so )
#導入avutil動態庫
add_library( avutil
SHARED
IMPORTED )
set_target_properties( avutil
PROPERTIES
IMPORTED_LOCATION
${LIB_DIR}/${ANDROID_ABI}/libavutil-55.so )
#連接動態庫
target_link_libraries(
your-lib
avfilter
avutil
avformat
)
FFmpeg Filter初始化流程
導入頭文件
extern "C" {
#include
#include
#include
};
注冊相關filter
avfilter_register_all();
獲取一個AVFilterGraph
利用這個Graph可以對后續的AVFilter進行管理。
AVFilterGraph *graph = avfilter_graph_alloc();
對于AVFilter的處理
一般步驟都是:
1、通過filter_name獲取到需要使用的AVFilter。
AVFilter filter = avfilter_get_by_name(filter_name);
2、利用AVFilter從AVFilterGraph獲取到相應的上下文環境。
AVFilterContext filter_ctx = avfilter_graph_alloc_filter(graph, filter, NULL);
3、構造初始化參數配置(多種方式)
方式一
char options_str[1024];
snprintf(options_str, sizeof(options_str),
"sample_fmt=%s:sample_rate=%d:channel_layout=0x%" PRIx64 ,
av_get_sample_fmt_name(sample_format),
sample_rate,
sample_channel);
avfilter_init_str(filter_ctx, options_str);
方式二
char ch_layout[64];
av_get_channel_layout_string(ch_layout, sizeof(ch_layout), 0, sample_channel);
av_opt_set(filter_ctx, "channel_layout", ch_layout, AV_OPT_SEARCH_CHILDREN);
av_opt_set(filter_ctx, "sample_fmt", av_get_sample_fmt_name(sample_format), AV_OPT_SEARCH_CHILDREN);
av_opt_set_int(filter_ctx, "sample_rate", sample_rate, AV_OPT_SEARCH_CHILDREN);
avfilter_init_str(filter_ctx, NULL);
方式三
AVDictionary *options_dict = NULL;
char ch_layout[64];
av_get_channel_layout_string(ch_layout, sizeof(ch_layout), 0, sample_channel);
av_dict_set(&options_dict, "channel_layout", ch_layout, AV_OPT_SEARCH_CHILDREN);
av_dict_set(&options_dict, "sample_fmt", av_get_sample_fmt_name(sample_format), AV_OPT_SEARCH_CHILDREN);
av_dict_set(&options_dict, "sample_rate", sample_rate, AV_OPT_SEARCH_CHILDREN);
avfilter_init_dict(volume_ctx, &options_dict);
PS:以上三種方式的實現效果是一致的。
對各個Filter進行鏈接
連接情況一(例如音量調節):
//abuffersrc_ctx -> volume_ctx -> abuffersink_ctx
avfilter_link(abuffersrc_ctx, 0, volume_ctx, 0);
avfilter_link(volume_ctx, 0, abuffersink_ctx, 0);
連接情況二 (例如混音):
//abuffersrc1_ctx
// -> amix_ctx -> abuffersink_ctx
//abuffersrc2_ctx
avfilter_link(abuffersrc1_ctx, 0, amix_ctx, 0);
avfilter_link(abuffersrc2_ctx, 0, amix_ctx, 1);
avfilter_link(amix_ctx, 0, abuffersink_ctx, 0);
初始化整個filters鏈
avfilter_graph_config(graph, NULL);
以上的流程就是整個FFmpeg Filter的初始化過程。
FFmpeg Filter使用流程
源音頻數據輸入
1、構造一個AVFrame:
//獲取一個AVFrame實例
AVFrame *avframe = av_frame_alloc();
//配置輸入音頻的格式、采樣率、聲道和采樣數
avframe->sample_rate = sample_rate;
avframe->format = sample_format;
avframe->channel_layout = sample_channel;
avframe->nb_samples = nb_sample;
//根據上面設置的情況,申請音頻數據緩沖區
av_frame_get_buffer(avframe, 1);
2、將源音頻輸入送入Filter鏈中:
av_buffersrc_add_frame(abuffersrc_ctx, avframe);
3、銷毀AVFrame相關資源
av_frame_free(&avframe);
處理后音頻數據輸出
1、申請一個AVFrame實例,值得提醒的是我們不需要對這個AVFrame做任何配置
AVFrame *avframe = av_frame_alloc();
2、從Filters鏈中獲取處理后的數據包
av_buffersink_get_frame(abuffersink_ctx, avframe);
3、提取完畢AVFrame的數據后,我們需要將其銷毀
av_frame_free(&avframe);
最后說幾句
對于FFmpeg Filter的使用,基本都是遵循上述流程。
注冊Filters
獲取一個AVFilterGraph
獲取多個AVFilter和AVFilterContext并進行參數配置
連接各個AVFilterContext
初始化整個Filters鏈
將源數據AVFrame輸入Filters鏈接收端
從Filters鏈輸出端獲取處理后數據AVFrame
對于音量調節,我們需要獲取如下幾個filter:
abuffer:提供了音頻數據的輸入端。
volume:提供了音頻數據音量調節的模塊。
aformat:提供了轉換成我們期望輸出格式的模塊,是因為Graph會在abuffer和volume之間自動做了格式轉換。
abuffersink:提供了音頻數據的輸出端。
對于混音,我們需要獲取如下幾個filter:
abuffer:提供了音頻數據的輸入端,我們需要獲取兩個,因為有兩路輸入。
amix:提供了多路音頻數據混合的模塊。
aformat:提供了轉換成我們期望輸出格式的模塊,是因為Graph會在abuffer和amix之間自動做了格式轉換。
abuffersink:提供了音頻數據的輸出端。
播放PCM文件可以利用Audacity這個工具可以導入pcm原始文件,并且提供了波形圖查看和播放功能。
本文同步發布于簡書、CSDN。
End!
總結
以上是生活随笔為你收集整理的android生成预处理文件,FFmpeg:Android利用Filter进行音频数据预处理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华为鸿蒙测试结果,华为鸿蒙OS系统测试结
- 下一篇: 汽车之家android平板,【精】中控面