天天看點

【FFMpeg視訊開發與應用基礎】七、 調用FFMpeg SDK實作視訊水印

視訊的水印通常指附加在原始視訊上的可見或者不可見的,與原始視訊無直接關聯的辨別。通常在有線電視畫面上電視台的台标以及視訊網站上的logo就是典型的視訊水印的應用場景。通常實作視訊水印可以通過FFMpeg提供的libavfilter庫實作。libavfilter庫實際上實作的是視訊的濾鏡功能,除了水印之外,還可以實作視訊幀的灰階化、平滑、翻轉、直方圖均衡、裁剪等操作。

我們這裡實作的視訊水印等操作,完全在視訊像素域實作,即從一個yuv檔案中讀取資料到AVFrame結構,對AVFrame結構進行處理後再輸出到另一個yuv檔案。中間不涉及封裝或編碼解碼等操作。

我們通過與之前類似的方式,在指令行中擷取輸入、輸出檔案名,圖像寬高。首先定義如下的結構體用于儲存配置資訊:

在這個結構體中,filterIdx用于表示目前工程選擇哪一種filter,即希望實作哪一種功能。

在進入main函數之後,調用hello函數來解析指令行參數:

該函數實作了輸入輸出檔案的檔案名擷取并打開,并讀取filter索引。

在進行初始化之前,必須調用filter的init函數,之後才能針對Video Filter進行各種操作。其聲明如下:

為了實作視訊水印的功能,所需要的相關結構主要有:

其中AVFilterContext用于表示一個filter的執行個體上下文,AVFilterGraph表示一個video filtering的工作流。Video Filter的初始化實作如以下函數:

我們首先聲明AVFrame類型的對象和指向像素緩存的指針:

然後配置設定AVFrame對象,并配置設定其中的緩存區:

這一部分主要包括三大部分:

讀取原始的YUV資料到輸入的frame;

使用預先定義好的filter_graph處理輸入frame,生成輸出frame;

将輸出frame中的像素值寫入輸出yuv檔案;

第一部分,讀取原始yuv的實作由自定義函數Read_yuv_data_to_buf實作:

第二部分實際上分為兩部分,即将輸入frame送入filter graph,以及從filter graph中取出輸出frame。實作方法分别為:

第三部分,寫出輸出frame到輸出yuv檔案:

該部分的綜合實作如下:

整體實作完成後,需要進行善後的收尾工作有釋放輸入和輸出frame、關閉輸入輸出檔案,以及釋放filter graph:

處理前的原始圖像如下:

【FFMpeg視訊開發與應用基礎】七、 調用FFMpeg SDK實作視訊水印

添加水印之後的圖像如下:

【FFMpeg視訊開發與應用基礎】七、 調用FFMpeg SDK實作視訊水印