1. YUV數據在使用avfilter scale時在特定的分辨率下UV分量不對
由於是小視頻,那么分辨率不需要太高,但是有的視頻源是1080p,甚至有的是4K的,所以對視頻源進行scale非常有必要。scale操作可以使用avfilter或者sws_scale完成,具體參考:
在對視頻數據進行decode后,得到了包含YUV數據的AVFrame,AVFrame中的data[0], data[1], data[2]分別表示YUV三個分量,YUV三個分量的數據量之比是4:1:1,每行的字節數分別是linesize[0], linesize[1], linesize[2]。
假定圖像長寬分別為w和h,那么Y分量字節數為w*h,linesize[0]等於w,U/V分量字節數均為0.5w*0.5h,linesize[1]等於linesize[2]等於0.5w。但是實際使用時發現,特定分辨率下scale后的UV分量顯示不正常,進一步發現UV的linesize有時不等於0.5w,對此FFMpeg(avframe.h)是這么解釋的:
* @note The linesize may be larger than the size of usable data -- there * may be extra padding present for performance reasons. */
int linesize[AV_NUM_DATA_POINTERS];
實際上確實發現UV分量的linesize不等於0.5w,這樣的話,在拷貝UV分量的時候,就需要一行一行拷貝,每行拷貝0.5w,這個問題也就解決了。
Tips:Mac下使用GLYUVPlay.app軟件,導入原始的YUV數據,輸入分辨率,YUV格式等信息,可以查看原始YUV數據的分量信息,對於解決問題非常有幫助。
2. PCM在使用FFMpeg的aac編碼器編碼時提示編碼失敗
在特定的手機上,aac會編碼失敗,提示的是"Input contains (near) NaN/+-Inf\n"。但是很奇怪,只在特定的手機出現該問題,查了半天沒有結果,看到有人說libfdk-aac庫可能會解決這個問題,將fdk-aac添加進FFMpeg后,編碼沒有問題,但是編碼出來后的數據有爆音,使用Audacity軟件查看dump下的數據,確實有爆音,也就是說程序還是有問題。仔細審代碼最后發現,aac編碼輸入的PCM數據只有一個聲道的,而編碼參數里寫的輸入為兩個聲道,而第二個聲道的數據沒有賦值,將第二個聲道拷貝了輸入數據后,問題就解決了。。
總結一下,不是所有的手機都沒問題,那就證明程序還是有問題。
Tips:Mac下使用Audacity軟件,輸入原始PCM數據的采樣率、音頻數據格式后,可以查看原始PCM數據波形,有無爆音等問題。
3. 視頻尺寸裁切不生效
視頻尺寸裁切時,用libavfilter的crop參數,我之前的理解,av_buffersink_get_frame出來的frame數據就變成了裁切后的尺寸,后來發現不是這樣。av_buffersink_get_frame后的frame只是width, height變成了裁切尺寸的長寬,data[]指針和linesize大小都沒有變。debug發現,frame的crop相關參數變了,在重新編碼時,就會根據crop參數和width, height參數編碼成裁切后的尺寸。
4. 錄制GIF時花屏
按照錄制視頻的代碼去錄制GIF時發現錄制后的GIF花屏,查閱資料可以,GIF的out format必須是AV_PIX_FMT_RGB8,把pixel_format改成RGB8后就OK了。
5. 對帶有HE-AAC的視頻編碼失敗
之前一直以為服務器的視頻都是LC-AAC格式的,這種格式的采樣樣本數nb_samples是1024個,而HE-AAC視頻的nb_samples是2048個,並且FFmpeg自帶的aac編碼器只支持LC-AAC編碼。於是不得已,只能換為fdk-aac編碼器,根據文檔,fdk-aac編碼器兩種格式的aac都支持。但是fdk-aac編碼器只支持S16格式的PCM,因此對解碼后得到的PCM又加了一層resample,將原來FLTP格式的PCM resample成S16格式,之后編碼成功。附FFmpeg支持的音頻編碼器信息:
Dolby Digital: ac3 Dolby Digital Plus: eac3 MP2: libtwolame, mp2 Windows Media Audio 1: wmav1 Windows Media Audio 2: wmav2 AAC LC: libfdk_aac, aac HE-AAC: libfdk_aac Vorbis: libvorbis, vorbis MP3: libmp3lame, libshine Opus: libopus
6. 編碼后視頻前幾幀黑屏
原因是開啟了多線程編碼,但是單線程編碼效率很低,這個問題還需要細研究一下。
參考資料:
2. FFMpeg學習(六) 用libavfilter對視頻尺寸進行裁切
3. https://trac.ffmpeg.org/wiki/Encode/HighQualityAudio