x264改變輸出分辨率的算法
在某些應用場景下,x264的輸入視頻分辨率與接收端輸出的視頻分辨率不同。例如編碼端攝像頭採集到的YUV數據爲1280x720,而接收端視頻顯示窗口爲640x480。
對於這種場景,一般的處理方式是:
源端:採集,編碼,傳輸 720p的碼流
收端:接收,解碼720p的碼流,縮放到480p去顯示。
這種方式的劣勢在於編碼,傳輸了接收端用不到的大分辨率碼流。
一種改進的方式是在源端縮放720p的視頻輸入數據:
源端:採集720p,縮放到480p,輸入480p給x264編碼器編碼,傳輸 480p的碼流
收端:接收,解碼,顯示480p的碼流。
這種方式處理掉了傳輸大分辨率碼流的問題,但不是最有效率的方式。因爲縮放本身也有計算量,同時增加了一次一幀數據讀寫的操作。
研究x264的代碼發現,x264通過以下函數實現輸入源圖像到準備編碼幀的格式轉換:
int x264_frame_copy_picture( x264_t *h, x264_frame_t *dst, x264_picture_t *src );
其中有從src->img.planet調撿數據拷貝到dst->plane的過程,目的是實現src和dst之間顏色空間轉換(x264內部用的原始數據幀,參考幀都是NV12/NV16格式, src如果是YV12需要轉成NV12)。x264在這裏假設src和dst的分辨率是相同的,只做顏色空間轉換。既然這裏有一次因爲色彩空間轉換而引起的數據搬移,那麼可以把圖像縮放操作加入其中一併完成,這樣就可以達到改變輸出分辨率的需求。
ffmpeg的sws_scale函數可以一次性的實現輸入圖像和輸出圖像之間分辨率以及顏色空間的轉換。在這裏如果發現輸入輸出分辨率不同,就用sws_scale函數替換掉原來plane_copy,plane_copy_interleave函數。在計算量幾乎不變的情況下(縮放計算稍微增加一些計算量,但一幀數據讀寫操作沒有增加),完美實現改變輸出分辨率的功能。