天天看點

FFmpeg入門詳解之62:過濾器:理論與實戰

過濾器(Filter)

在多媒體進行中,filter的意思是被編碼到輸出檔案之前用來修改輸入檔案内容的一個軟體工具。如:視訊翻轉,旋轉,縮放等。

文法:[input_link_label1]… filter_name=parameters [output_link_label1]…

1、視訊過濾器 -vf

如input.mp4視訊按順時針方向旋轉90度

ffplay -i input.mp4 -vf transpose=1

如input.mp4視訊水準翻轉(左右翻轉)

ffplay -i input.mp4 -vf hflip

2、音頻過濾器 -af

實作慢速播放,聲音速度是原始速度的50%

offplay input.mp3 -af atempo=0.5

過濾器鍊(Filterchain)

Filterchain = 逗号分隔的一組filter

文法:“filter1,filter2,filter3,…filterN-2,filterN-1,filterN”

順時針旋轉90度并水準翻轉

ffplay -i input.mp4 -vf transpose=1,hflip

過濾器圖(Filtergraph)

第一步: 源視訊寬度擴大兩倍。

ffmpeg -i jidu.mp4 -t 10 -vf pad=2*iw output.mp4

第二步:源視訊水準翻轉

ffmpeg -i jidu.mp4 -t 10 -vf hflip output2.mp4

第三步:水準翻轉視訊覆寫output.mp4

ffmpeg -i output.mp4 -i output2.mp4 -filter_complex overlay=w compare.mp4

是不是很複雜?

用帶有連結标記的過濾器圖(Filtergraph)隻需一條指令

基本文法

Filtergraph = 分号分隔的一組filterchain

“filterchain1;filterchain2;…filterchainN-1;filterchainN”

Filtergraph的分類

1、簡單(simple) 一對一

2、複雜(complex)多對一, 多對多

複雜過濾器圖比簡單過濾器圖少2個步驟,效率比簡單高,ffmpeg建議盡量使用複雜過濾器圖。

對于剛才用三步處理的方式,用過濾器圖可以這樣做:

ffplay -f lavfi -i testsrc -vf split[a][b];[a]pad=2*iw[1];[b]hflip[2];[1][2]overlay=w

F1: split過濾器建立兩個輸入檔案的拷貝并标記為[a],[b]

F2: [a]作為pad過濾器的輸入,pad過濾器産生2倍寬度并輸出到[1].

F3: [b]作為hflip過濾器的輸入,vflip過濾器水準翻轉視訊并輸出到[2].

F4: 用overlay過濾器把 [2]覆寫到[1]的旁邊.

Filter的結構體關系圖與定義

4.1 結構體間的關系圖

filter涉及的結構體,主要包括:

> FilterGraph, AVFilterGraph

> InputFilter, InputStream, OutputFilter, OutputStream

> AVFilter, AVFilterContext

> AVFilterLink

> AVFilterPad;

FFmpeg的濾鏡相關的結構體三層組成:

1) filtergraph層

由結構體 FilterGraph, AVFilterGraph組成;

其中,

FilterGraph, 包含一個InputFilter, 它訓示了整個Graph的第一個濾鏡,并訓示了InputStream, 進而作為整個Graph的輸入;

包含一個OutputFilter, 它訓示了整個Graph的最後一個濾鏡,并訓示了OutputStream,進而作為整個Graph的輸出;

包含一個AVFilterGraph的執行個體,它訓示的是組成本graph的filter;

2) filterchain層

它由AVFilter, AVFilterContext, AVFilterLink, AVFilterPad組成;

其中,AVFilterContext是AVFilter的執行個體;

而filter之間是用 AVFilterLink進行連接配接,意思是,濾鏡之間并不是直接相連的,是通過AVFilterLink進行連接配接;

AVFilterContext 通過AVFilterLink進行連接配接後,就組成了Filterchain。

而AVFilterContext與AVFilterLink之間的AVFilterPad是直接相連的,對應的關系是

AVFilterContext的output_pad 連接配接它下遊AVFilterLink的 srcpad;

AVFilterContext的input_pad 連接配接它上遊AVFilterLink的 dstpad;

3) filter層

由AVFilterContext, AVFilterPad組成;

其中AVFilterContext是真正進行資料處理的濾鏡實體;

AVFilterPad用于AVFilterContext之間的callback(回調):

第一個AVFilterContext的outputs[0]指針,指向第一個AVFilterLink,這個AVFilterLink的dst指針,指向第二個AVFilterContext。

如果在前一個AVFilterContext調用 outputs[0]->dstpad->filter_frame(Frame* input_frame1),

那其實就意味着,第一個過濾器,可以把處理好的一個frame(名字為input_frame1),可以通過這個調用,傳遞給第二個過濾器的input_pads的filter_frame函數。

而第二個過濾器,裡面就是使用者自己實作的filter_frame(),以對資料進行處理;

DirectShow

DirectShow(簡稱 DShow) 是一個 Windows 平台上的流媒體架構,提供了高品質的多媒體流采集和回放功能。它支援多種多樣的媒體檔案格式,包括 ASF、MPEG、AVI、MP3和WAV 檔案,同時支援使 動或早期的 VFW 驅動來進行多媒體流的采集。

DirectShow 大大簡化了媒體回放、格式轉換和采集工作。但與此同時,它也為使用者自定義的解決方案提供了底層流控制架構,進而使使用者可以自行建立支援新的檔案格式或其他使用者的 DirectShow 元件。

DirectShow 專為 C ++ 而設計。 Microsoft 不提供用于 DirectShow 的托管 API。

DirectShow 是基于元件對象模型(COM)的,是以當你編寫 DirectShow 應用程式時,你必須具備 COM 用戶端程式編寫的知識。對于大部分的應用程式,你不需要實作自己的 COM 對象,DirectShow 提供了大部分你需要的 DirectShow 元件,但是假如你需要編寫自己的 DirectShow 元件來進行擴充,那麼你必須編寫實作 COM 對象。

使用 DirectShow 編寫的典型應用程式包括:DVD 播放器、視訊編輯程式、AVI 到 ASF 轉換器、 MP3 播放器和數字視訊采集應用。

DirectShow 架構

DirectShow 位于應用層中。它使用一種叫 Filter Graph 的模型來管理整個資料流的處理過程;參與資料處理的各個功能子產品叫 Filter;各個 Filter 在 Filter Graph 中按一定的順序連接配接成一條 "流水線" 協同工作。( 可以看出 FilterGraph 是 Filter 的容器 )

按照功能來分,Filter 大緻分為三類:

Source Filters、Transform Filters 和 Rendering(sink) Filters。

Source Filters 主要負責取得資料,資料源可以是檔案、網際網路、或者計算機裡的采集卡、數字錄影機等,然後将資料往下傳輸;

Transform Fitlers 主要負責資料的格式轉換、傳輸;

Rendering Filtes 主要負責資料的最終去向,我們可以将資料送給聲霸卡、顯示卡進行多媒體的示範,也可以輸出到檔案進行存儲。

在 DirectShow 系統上,我們看到的,即是我們的應用程式(Application)。應用程式要按照一定的意圖建立起相應的 Filter Graph,然後通過 Filter Graph Manager 來控制整個的資料處理過程。DirectShow 能在 Filter Graph 運作的時候接收到各種事件,并通過消息的方式發送到我們的應用程式。這樣,就實作了應用程式與 DirectShow 系統之間的互動。

DirectShow使用一種交Filter Graph的模型來管理整個資料流的處理過程;參與資料處理的各個功能子產品叫做Filter;各個Filter在Filter Graph中按一定的順序連接配接成一條"流水線"協同工作。Filter,它是最基本的軟體構件,過濾器通常在多媒體流中執行一個操作。各個Filter在Filter Graph中按一定的順序連接配接成一條"流水線"協同工作。如果用圖論的術語描述,過濾器圖是一個有向、無環、非連通圖。有向是因為資料在過濾器之間以預定的方向流動;無環是指沒有路徑可以從一個過濾器出發又傳回到它自身;而非連通是指不是所有的過濾器都可以達到所有其他過濾器。

案例實戰

Filtering_video.c

繼續閱讀