天天看點

ffmpeg 進行視訊轉換圖像翻轉的問題的修正

我在用FFMPEG 開發在DirectShow 環境下生成FLV的篩選器(Filter)的時候,碰到了一個比較古怪的問題。因為該篩選器的輸入格式需要支援常見的RGB,和YUV格式。但是在輸入是RGB格式的時候,最終生成的視訊圖像是翻轉的。而用YUV格式确實沒有問題的。

分析了一下程式,因為ffmpeg支援的最終存入FLV的格式是YUV420P,需要調用sws_scale進行圖像的格式轉換,應該是調用sws_scale進行圖像格式轉換的時候發生的圖像反轉。雖然問題很顯然,但是卻一直找不到好的辦法,這個問題困擾了好久,也檢視了ffmpeg的源代碼。本想也一段代碼,先把RGB格式的圖像先手工做一次反轉,再通過sws_scale進行處理,那樣負負得正正好解決問題,當然實作這樣的反轉代碼也比較簡單,稍微花點時間就可以搞定。但是進行編解碼處理的程式關鍵是性能,這樣處理,因為圖像反轉操作,白白損失了大量的CPU。後來發現其實,有一個非常巧妙的方法可以解決這個問題。或許ffmpeg在開發的時候,他們早已考慮到了這個問題,已經預留了這個後門了。

辦法是這樣的:

先看看sws_scale的函數定義

int sws_scale(struct SwsContext *ctx, uint8_t* src[], int srcStride[],

              int srcSliceY, int srcSliceH, uint8_t* dst[], int dstStride[])

其中src和srcStride定義了輸入圖像的四個平面的資料起始指針和四個平面中每一行包含的像素的個數。

dst和dstStride是輸出變量,定義的是輸出圖像的四個平面的資料起始指針和四個平面包含的資料的大小。

為什麼一個圖像有四個平面,可以找一下YUV格式的一些詳細介紹就可以明白。

當然,RGB格式是按照緊湊格式進行編碼的,是以隻有一個平面,也就是說隻要設定src[0]就可以,src[1],src[2],src[3]都為NULL。

我們就在設定src[0]和srcStride[0]的地方做文章。

按照一般處理src[0]和srcStride[0]分别設定為起始圖像資料的開始和圖像每一行的像素個數。

那如果把src[0] 設定為 width * ( height - 1)    srcStride[0] = -height 結果會如何呢?是不是就會把圖像倒過來呢?

實際确實如此。進行圖像倒置的操作盡然如此簡單。這樣避免了人為再添加一次圖像的反轉操作,提高了編碼的性能。

繼續閱讀