7.SwrContext音頻重采樣使用


頭文件位於 #include <libswresample/swresample.h>
 
SwrContext常用函數如下所示
SwrContext *swr_alloc(void); //創建一個SwrContext,並設置為默認參數
 
struct SwrContext *swr_alloc_set_opts(struct SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,nt64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, int log_offset, void *log_ctx);
//如果第一個參數指向為NULL,則創建一個新的SwrContext,否則對其進行參數配置。
//@param s 要創建的SwrContext ,如果指向NULL,則分配一個新的SwrContext
//@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(日志相關,為NULL即可)
//@param log_ctx parent logging context(日志相關,為NULL即可) int64_t av_get_default_channel_layout(int nb_channels); //通過當前通道數返回對應AV_CH_LAYOUT_*枚舉值,比如參數為2(2通道),那么返回AV_CH_LAYOUT_STEREO(立體聲) int av_get_channel_layout_nb_channels(uint64_t channel_layout); //通過AV_CH_LAYOUT_*獲取當前有多少通道 int swr_init(struct SwrContext *s); // 初始化上下文,初始化之前需要配置好SwrContext //如果初始化好后,還需要修改轉換的參數,則調用swr_alloc_set_opts(),然后swr_init()重新初始化

void swr_free(struct SwrContext **s); // 釋放上下文空間,並且設置*s為NULL int swr_convert(struct SwrContext *s, uint8_t **out, int out_count, const uint8_t **in , int in_count); //音頻重采樣轉換 // s : 初始化好的SwrContext //out : 輸出緩沖區,對於packet,都存在out[0]中,對於planar,比如AV_CH_LAYOUT_STEREO,那么out[0]存L,out[1]存R //out_count : 輸出緩沖區每通道樣本數據數量(對於音頻,每個通道數據長度都相同),注意這里不是以字節為單位. //in :輸入緩沖區,這里填入frame->data即可 //in_count :輸入緩沖區每通道數據數量,這里填入frame->nb_samples即可 //返回值:轉換成功后每個通道的輸出樣本數,出錯則為負值

 音頻解碼並重采樣示例

void debugErr(QString prefix, int err)  //根據錯誤編號獲取錯誤信息並打印
{
    char errbuf[512]={0};

    av_strerror(err,errbuf,sizeof(errbuf));

    cout<<prefix<<":"<<errbuf<<endl;
}

void runAudioPlay()
{
    int ret;     
    avformat_network_init(); //初始化網絡庫 (可以打開rtsp rtmp http 協議的流媒體視頻)
    AVFormatContext *pFmtCtx=NULL;
ret
= avformat_open_input(&pFmtCtx,filePath,NULL, NULL) ; //打開音視頻文件並創建AVFormatContext結構體以及初始化. if (ret!= 0) { debugErr("avformat_open_input",ret); return ; } ret = avformat_find_stream_info(pFmtCtx, NULL); //初始化流信息 if (ret!= 0) { debugErr("avformat_find_stream_info",ret); return ; } int audioindex=-1; audioindex = av_find_best_stream(pFmtCtx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0); qDebug()<<"audioindex:"<<audioindex; AVCodec *acodec = avcodec_find_decoder(pFmtCtx->streams[audioindex]->codecpar->codec_id);//獲取codec AVCodecContext *acodecCtx = avcodec_alloc_context3(acodec); //構造AVCodecContext ,並將vcodec填入AVCodecContext中 avcodec_parameters_to_context(acodecCtx, pFmtCtx->streams[audioindex]->codecpar); //初始化AVCodecContext ret = avcodec_open2(acodecCtx, NULL,NULL);
//打開解碼器,由於之前調用avcodec_alloc_context3(acodec)初始化了解碼器,那么codec(第2個參數)可以填NULL if (ret!= 0) { debugErr("avcodec_open2",ret); return ; } SwrContext *swrctx =NULL; swrctx=swr_alloc_set_opts(swrctx, av_get_default_channel_layout(2),AV_SAMPLE_FMT_S16,44100, acodecCtx->channel_layout, acodecCtx->sample_fmt,acodecCtx->sample_rate, NULL,NULL);
       swr_init(swrctx);
while(1) { ret = av_read_frame(pFmtCtx, packet); if (ret!= 0) { debugErr("av_read_frame",ret); break ; } //解碼一幀數據 ret = avcodec_send_packet(acodecCtx, packet); av_packet_unref(packet); if (ret != 0) { debugErr("avcodec_send_packet",ret); continue ; } if(packet->stream_index==audioindex) //判斷是音頻流 { while( avcodec_receive_frame(acodecCtx, frame) == 0) { uint8_t *data[2] = { 0 }; int byteCnt=frame->nb_samples * 2 * 2; unsigned char *pcm = new uint8_t[byteCnt]; //frame->nb_samples*2*2表示分配樣本數據量*兩通道*每通道2字節大小 data[0] = pcm; //輸出格式為AV_SAMPLE_FMT_S16(packet類型),所以轉換后的LR兩通道都存在data[0]中 ret = swr_convert(swrctx, data, frame->nb_samples, //輸出 (const uint8_t**)frame->data,frame->nb_samples ); //輸入 //將重采樣后的data數據發送到輸出設備,進行播放 ... ... delete[] pcm; //最后delete pcm } } } //釋放 av_frame_free(&frame); av_packet_free(&packet); swr_free(&swrctx); avcodec_free_context(&acodecCtx); avformat_close_input(&pFmtCtx); }

 

  未完待續,下章學習: 11.QT-ffmpeg+QAudioOutput實現音頻播放器


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM