SwrContext重取樣結構體
SwrContext重取樣結構體使用說明
在瞭解FFMPEG音訊解碼過程中,看到SwrContext重取樣這個結構體,於是便詳細瞭解下這個結構體相關的一些概念,記錄下筆記。。。。
一、重取樣
1)什麼是重取樣
所謂的重取樣,就是改變音訊的取樣率、sample format、聲道數等引數,使之按照我們期望的引數輸出。
2)為什麼要重取樣
為什麼要重取樣?當然是原有的音訊引數不滿足我們的需求,比如在FFMPEG解碼音訊的時候,不同的音源有不同的格式,取樣率等,在解碼後的資料中的這些引數也會不一致(最新FFMPEG 16 解碼音訊後,音訊格式為AV_SAMPLE_FMT_FLTP,這個引數應該是一致的),如果我們接下來需要使用解碼後的音訊資料做其他操作,而這些引數的不一致導致會有很多額外工作,此時直接對其進行重取樣,獲取我們制定的音訊引數,這樣就會方便很多。
再比如在將音訊進行SDL播放時候,因為當前的SDL2.0不支援planar格式,也不支援浮點型的,而最新的FFMPEG 16年會將音訊解碼為AV_SAMPLE_FMT_FLTP格式,因此此時就需要我們對其重取樣,使之可以在SDL2.0上進行播放。
3)可調節的引數
通過重取樣,我們可以對 sample rate(取樣率)、sample format(取樣格式)、channel layout(通道佈局,可以通過此引數獲取聲道數)。
二、SwrContext常用函式
1)swr_alloc
函式原型:struct SwrContext *swr_alloc(void);
此函式用於申請一個SwrContext結構體
2)swr_init
函式原型:int swr_init(struct SwrContext *s);
當設定好相關的引數後,使用此函式來初始化SwrContext結構體
3)swr_alloc_set_opts
函式原型: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);
此函式是比較重要的函式,分配SwrContext並設定/重置常用的引數。
相關引數解釋如下:
* @param s Swr context, can be NULL
* @param out_ch_layout output channel layout (AV_CH_LAYOUT_*)
* @param out_sample_fmt output sample format (AV_SAMPLE_FMT_*).
* @param out_sample_rate output sample rate (frequency in Hz)
* @param in_ch_layout input channel layout (AV_CH_LAYOUT_*)
* @param in_sample_fmt input sample format (AV_SAMPLE_FMT_*).
* @param in_sample_rate input sample rate (frequency in Hz)
* @param log_offset logging level offset
* @param log_ctx parent logging context, can be NULL
上面的引數即包含了輸入輸出引數中sample rate(取樣率)、sample format(取樣格式)、channel layout等引數。
4)swr_convert
函式原型:int swr_convert(struct SwrContext *s, uint8_t **out, int out_count,
const uint8_t **in , int in_count);
此函式便是將輸入的音訊按照定義的引數進行轉換,並輸出
5)swr_free
函式原型:void swr_free(struct SwrContext **s);
釋放掉SwrContext結構體並將此結構體置為NULL;
三、基本用法
此結構體比較簡單,參考FFMPEG中標頭檔案 swresample.h中說明,基本用法如下:
申請結構體—>設定相關引數—>初始化—>轉換—->釋放結構體
申請結構體和設定相關引數有兩種方法:
方法1:
SwrContext *swr = swr_alloc();
av_opt_set_channel_layout(swr, "in_channel_layout", AV_CH_LAYOUT_5POINT1, 0);
av_opt_set_channel_layout(swr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
av_opt_set_int(swr, "in_sample_rate", 48000, 0);
av_opt_set_int(swr, "out_sample_rate", 44100, 0);
av_opt_set_sample_fmt(swr, "in_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
方法2:
SwrContext *swr = swr_alloc_set_opts(NULL, // we're allocating a new context
AV_CH_LAYOUT_STEREO, // out_ch_layout
AV_SAMPLE_FMT_S16, // out_sample_fmt
44100, // out_sample_rate
AV_CH_LAYOUT_5POINT1, // in_ch_layout
AV_SAMPLE_FMT_FLTP, // in_sample_fmt
48000, // in_sample_rate
0, // log_offset
NULL); // log_ctx
上面的兩種方法是將輸入音源引數為: 5.1聲道 48K取樣率 AV_SAMPLE_FMT_FLTP格式轉換為 雙聲道 44.1k取樣率 AV_SAMPLE_FMT_S16格式