1. 程式人生 > 實用技巧 >4.影象處理庫libswscale的sws_getContext(),sws_scale(),avdevice_register_all(),gdigrab簡記

4.影象處理庫libswscale的sws_getContext(),sws_scale(),avdevice_register_all(),gdigrab簡記

原文連結:https://blog.csdn.net/leixiaohua1020/article/details/44305697

  FFmpeg中的影象處理(縮放,YUV/RGB格式轉換)類庫libswsscale的原始碼。libswscale是一個主要用於處理圖片畫素資料的類庫。可以完成圖片畫素格式的轉換,圖片的拉伸等工作。有關libswscale的使用可以參考文章:https://blog.csdn.net/leixiaohua1020/article/details/42134965

  它的初始化函式為sws_getContext(),它的資料處理函式為sws_scale()。

  SwsContext是使用libswscale時候一個貫穿始終的結構體。但是我們在使用FFmpeg的類庫進行開發的時候,是無法看到它的內部結構的。在libswscale\swscale.h中只能看到一行定義:struct SwsContext;

  它的定義位於libswscale\swscale_internal.h中,(幾百行的定義)

  sws_getContext()是初始化SwsContext的函式。

struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,
                                  int dstW, int dstH, enum AVPixelFormat dstFormat,
                                  int flags, SwsFilter *srcFilter,
                                  SwsFilter 
*dstFilter, const double *param);

該函式包含以下引數:

srcW:源影象的寬
srcH:源影象的高
srcFormat:源影象的畫素格式
dstW:目標影象的寬
dstH:目標影象的高
dstFormat:目標影象的畫素格式
flags:設定影象拉伸使用的演算法

成功執行的話返回生成的SwsContext,否則返回NULL。

  成功執行的話返回生成的SwsContext,否則返回NULL。sws_getContext()的定義位於libswscale\utils.c  

  從sws_getContext()的定義中可以看出,它首先呼叫了一個函式sws_alloc_context()用於給SwsContext分配記憶體。然後將傳入的源影象,目標影象的寬高,畫素格式,以及標誌位分別賦值給該SwsContext相應的欄位。最後呼叫一個函式sws_init_context()完成初始化工作。下面我們分別看一下sws_alloc_context()和sws_init_context()這兩個函式。

  

  sws_init_context()除了對SwsContext中的各種變數進行賦值之外,主要按照順序完成了以下一些工作:
1. 通過sws_rgb2rgb_init()初始化RGB轉RGB(或者YUV轉YUV)的函式(注意不包含RGB與YUV相互轉換的函式)。
2. 通過判斷輸入輸出影象的寬高來判斷影象是否需要拉伸。如果影象需要拉伸,那麼unscaled變數會被標記為1。
3. 通過sws_setColorspaceDetails()初始化顏色空間。
4. 一些輸入引數的檢測。例如:如果沒有設定影象拉伸方法的話,預設設定為SWS_BICUBIC;如果輸入和輸出影象的寬高小於等於0的話,也會返回錯誤資訊。
5. 初始化Filter。這一步根據拉伸方法的不同,初始化不同的Filter。
6. 如果flags中設定了“列印資訊”選項SWS_PRINT_INFO,則輸出資訊。
7. 如果不需要拉伸的話,呼叫ff_get_unscaled_swscale()將特定的畫素轉換函式的指標賦值給SwsContext中的swscale指標。
8. 如果需要拉伸的話,呼叫ff_getSwsFunc()將通用的swscale()賦值給SwsContext中的swscale指標(這個地方有點繞,但是確實是這樣的)。
  

1.初始化RGB轉RGB(或者YUV轉YUV)的函式。注意這部分函式不包含RGB與YUV相互轉換的函式。

sws_rgb2rgb_init()

sws_rgb2rgb_init()的定義位於libswscale\rgb2rgb.c,

從sws_rgb2rgb_init()程式碼中可以看出,有兩個初始化函式:rgb2rgb_init_c()是初始化C語言版本的RGB互轉(或者YUV互轉)的函式,rgb2rgb_init_x86()則是初始化X86彙編版本的RGB互轉的函式。
PS:在libswscale中有一點需要注意:很多的函式名稱中包含類似“_c”這樣的字串,代表了該函式是C語言寫的。與之對應的還有其它標記,比如“_mmx”,“sse2”等。
  C語言版本的RGB互轉函式的初始化函式rgb2rgb_init_c(),定義位於libswscale\rgb2rgb_template.c,

可以看出rgb2rgb_init_c()執行後,會把C語言版本的影象格式轉換函式賦值給系統的函式指標。

  rgb24tobgr24_c()完成了RGB24向BGR24格式的轉換。函式的定義如下所示。從程式碼中可以看出,該函式實現了“R”與“B”之間位置的對調,從而完成了這兩種格式之間的轉換。

  rgb24to16_c()完成了RGB24向RGB16畫素格式的轉換。

  yuyvtoyuv422_c()完成了YUYV向YUV422畫素格式的轉換。

  該函式將YUYV畫素資料分離成為Y,U,V三個分量的畫素資料。其中extract_even_c()用於獲取一行畫素中序數為偶數的畫素,對應提取了YUYV畫素格式中的“Y”。extract_odd2_c()用於獲取一行畫素中序數為奇數的畫素,並且把這些畫素值再次按照奇偶的不同,儲存於兩個陣列中。對應提取了YUYV畫素格式中的“U”和“V”。
  rgb2rgb_init_x86()用於初始化基於X86組合語言的RGB互轉的程式碼。由於對彙編不是很熟,不再作詳細分析。

  

  可以看出,rgb2rgb_init_x86()首先呼叫了av_get_cpu_flags()獲取CPU支援的特性,根據特性呼叫rgb2rgb_init_mmx(),rgb2rgb_init_3dnow(),rgb2rgb_init_mmxext(),rgb2rgb_init_sse2(),rgb2rgb_init_avx()等函式。

  

2.判斷影象是否需要拉伸。

這一步主要通過比較輸入影象和輸出影象的寬高實現。系統使用一個unscaled變數記錄影象是否需要拉伸,如下所示。

unscaled = (srcW == dstW && srcH == dstH);

3.初始化顏色空間。

初始化顏色空間通過函式sws_setColorspaceDetails()完成。sws_setColorspaceDetails()是FFmpeg的一個API函式,它的宣告如下所示:

int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4],
                             int srcRange, const int table[4], int dstRange,
                             int brightness, int contrast, int saturation);

簡單解釋一下幾個引數的含義:
c:需要設定的SwsContext。
inv_table:描述輸出YUV顏色空間的引數表。
srcRange:輸入影象的取值範圍(“1”代表JPEG標準,取值範圍是0-255;“0”代表MPEG標準,取值範圍是16-235)。
table:描述輸入YUV顏色空間的引數表。
dstRange:輸出影象的取值範圍。
brightness:未研究。
contrast:未研究。
saturation:未研究。
  

  其他雷神部落格也還有,可去看。。。。。