FFMpeg雜音問題解決小結

   最近在調試網上下載的android ffmpeg播放器的源代碼。因爲編譯ffmpeg過程中,覺得很麻煩,因此就沒有繼續編譯SDL庫了。打算在Java層使用Bitmap顯示視頻幀,在C層使用OpenSLES播放音頻幀。


     將網上的相關源代碼整合到一塊後,發現音視頻解碼,都沒有錯誤。並且視頻可以播放出來,但是聲音聲調不對,主要還有雜音。試了網上的一些方法也不行。最後自己嘗試性地改了一個變量。雜音就消失了,但是聲調還不對。

   網上的解碼音頻數據包,然後將解碼後的原始數據push到音頻緩衝區的源代碼中有以下幾行代碼

   //音頻數據解碼

   len = avcodec_decode_audio4(aCodecCtx, frame, &got_frame, &packet); 

   //得到解碼音頻數據的大小

   data_size = av_samples_get_buffer_size(   NULL, aCodecCtx->channels, 
                                                                        frame->nb_samples,aCodecCtx->sample_fmt, 1);  

  //將解碼的音頻數據push到音頻緩衝區
   memcpy(stream, (uint8_t*)(frame->data[0]), data_size]); 

 

  我將  memcpy(stream, (uint8_t*)(frame->data[0]), data_size]); 

  改爲  memcpy(stream, (uint8_t*)(frame->data[0]), frame->linesize[0]);  後雜音就消失了。但是聲音明顯比正常的要快。


  這個時候,感覺再去網上找方法也沒什麼用了。必須老老實實地理解AVFrame結構體中,各個字段的具體意思和PCM的相關知識點。


      後來知道了雜音和聲調不對的原因了。


      雜音是因爲avcodec_decode_audio4(aCodecCtx, frame, &got_frame, &packet)解碼後的兩個聲道的音頻數據分別存放在frame->data[0]和frame->data[1]中,而 frame->linesize[0]和 frame->linesize[1] 分別是前兩者的大小。(我用來調試的視頻文件,音頻部分是雙聲道的)。而data_size表示的是兩個聲道的音頻數據的總和。  因此memcpy(stream, (uint8_t*)(frame->data[0]), data_size])將一大段錯誤的數據push到緩衝區了。


     聲音明顯比正常的要快的原因是,memcpy(stream, (uint8_t*)(frame->data[0]), frame->linesize[0])只是push了一個聲道的音頻數據,而創建OpenSLES的播放器是卻設置成了雙 聲道。format_pcm.numChannels = aCodecCtx->channels(實際上爲2)。兩個通道播放一個通道的數據,自然變快了。爲儘快播放出正常的聲音,將播放器聲道數設爲1,此時聽到了正常的音樂。


    當然最正確的方法是正確地將編碼後的音頻數據,轉換爲正確的PCM格式。這樣就可以雙聲道播放了。


    小結一下:遇到不是程序本身存在的問題時。還需要從原理入手,學習相關的知識,這樣才能夠真正理解一段代碼的工作流程和原理。




  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章