(長江大學 湖北 荊州 434023)
Ffmpeg是一套可以用來記錄、轉(zhuǎn)換數(shù)字音頻、視頻,并能將其轉(zhuǎn)化為流的開源計算機程序。它提供了一套完整的音視頻解決方案,可以實現(xiàn)音視頻的轉(zhuǎn)碼、裁剪、拼接、縮放、旋轉(zhuǎn)、圖層的疊加等功能,唯一的缺點是其libavcodec編解碼庫在移植到Android平臺后,只支持軟編碼,兼容性很好,但不支持Android的MediaCodec硬編碼,所以編碼效率比較低。
交叉編譯是在一個平臺(windows)生成另一個平臺(Android)的可執(zhí)行代碼。由于ffmpeg是用c語言開發(fā)的,不能直接運行在Android系統(tǒng)中,所以需要編譯成Android可以執(zhí)行的代碼庫。通常是在windows下安裝Linux虛擬機,編寫shell腳本,修改ffmpeg配置文件,最后編譯生成so庫。編譯成功后會生成幾個so文件。libavcodec.so提供了一系列編碼器的實現(xiàn)。
libavformat.so實現(xiàn)了流協(xié)議,容器格式及其IO訪問。
libavutil.so包含了各種工具函數(shù),命令入口也從這里開始。
libavfilter.so提供了各種音視頻過濾器。
libavdevice.so提供了訪問捕獲設(shè)備和回放設(shè)備的接口。
libswresample.so實現(xiàn)了混音和重采樣。
libswscale.so實現(xiàn)了色彩轉(zhuǎn)換和縮放功能。
OpenGL ES(OpenGL for Embedded Systems)是OpenGL(Open Graphics Library)三維圖形API的一個子集。OpenGL ES是為移動設(shè)備而設(shè)計出來的,通過它可以直接調(diào)用GPU來進行繪圖,效率很高性能很好。并且Android系統(tǒng)中是自帶OpenGL的,不需要像ffmpeg那樣必須要通過交叉編譯引入進來,我們可以直接通過Android提供的api來調(diào)用OpenGL。
MediaCodec是Android自帶一個庫,可用于對視頻進行編解碼。MediaCodec可以通過createInputSurface創(chuàng)建一個Surface,然后OpenGL將數(shù)據(jù)渲染到這個Surface上,這樣MediaCodec就可以對得到的視頻數(shù)據(jù)進行編碼了,編碼后在通過MediaMuxer對其封裝成Mp4。在Android音視頻開發(fā)中,通常使用OpenGL ES來繪制視頻,然后配合MediaCodec來對OpenGL進行硬編碼生成視頻。
何為Canny邊緣檢測?
Canny邊緣檢測算法是一個多級邊緣檢測算法。Canny算法經(jīng)過多年的發(fā)展,已經(jīng)成為邊緣檢測的一種標準算法,性能和效果都比較優(yōu)化,在實際中被廣泛應(yīng)用。
Canny邊緣檢測主要的思想如下:1.應(yīng)用高斯濾波來平滑圖像,目的是去除噪聲;2.找尋圖像的強度梯度(intensity gradients);3.利于非最大抑制技術(shù)來消除邊緣誤檢;4.通過兩個閾值low和high來確定出邊緣;5.利用滯后技術(shù)來跟蹤邊界。
FFmpeg中已經(jīng)封裝好了Canny邊緣檢測算法,所以通過ffmpeg來調(diào)用邊緣檢測就方便很多了。
例如:ffmpeg-i input.png-vf edgedetect=low=0.1:high=0.4:mode=wires-frames:v 1-y edge.png
其中有幾個參數(shù)”-i input.png”代表輸入文件,”-vf edgedetect=low=0.1:high=0.4:mode=wires”代表使用邊緣檢測濾鏡,”-frames:v 1”代表從視頻中提取一幀,可以適用于一些動態(tài)圖的情況,”-y edge.png代表”生成文件并強制覆蓋。其中關(guān)于edgedetect的參數(shù)有3個分別是low、high、mode。其中l(wèi)ow和high代表設(shè)置Canny閾值算法中的低閾值和高閾值。必須在[0,1]范圍內(nèi)選擇低閾值和高閾值,低閾值應(yīng)小于或等于高閾值。高閾值代表強邊緣像素,低閾值代表弱邊緣像素,然后通過八連通性將這些點相連。四連通區(qū)域是11011其中0代表中心點,4個1代表上下左右四個方向。八連通區(qū)域是111101111也就是除了上下左右四個方向外,還有左上、右上、左下、右下。關(guān)于mode繪圖模式,例如wires代表生成黑白圖,colormix代表生成油畫卡通效果圖。
關(guān)于深度優(yōu)先遍歷算法的思想如下:
1.訪問頂點v;
2.依次從v的未被訪問的鄰接點出發(fā),對圖進行深度優(yōu)先遍歷;直至圖中和v有路徑相通的頂點都被訪問;
3.若此時圖中尚有頂點未被訪問,則從一個未被訪問的頂點出發(fā),重新進行深度優(yōu)先遍歷,直到圖中所有頂點均被訪問過為止。
通過Canny邊緣檢測可以得到一個二值化的圖像,背景是黑色,輪廓是白色的圖片。這時需要使用深度優(yōu)先遍歷得到這個圖片上所有白色的點。
定義圖片的左上角為(1,1)右下角為(width,height)。首先對這個圖片進行從左到右,從上到下遍歷,直到找到一個白色點,然后從這個白色的點開始,采用八連通規(guī)則依次判斷周圍的點,同一個點只需要添加一次即可。最終得到深度優(yōu)先遍歷的點陣序列。
在Android中棧的最大內(nèi)存大小為1024KB,這里需要存儲大量的點陣數(shù)據(jù),如果棧空間不足會報錯StackOverflowError,所以這里存儲坐標的點陣時使用short類型即可。另外還需要控制點陣存儲的最大數(shù)量限制以防止棧溢出。
方案一:使用FFmpeg軟編碼,速度慢但是兼容性好。實現(xiàn)思路是,在得到點陣序列后,依次將每一幀的序列生成Bitmap并保存成實際圖片在磁盤上。接下來調(diào)用FFmpeg命令對這每一幀圖片進行處理生成視頻。例如:ffmpeg-framerate 30-i image-%03d.png-c:v libx264-y out.mp4 即可將一個圖片序列生成視頻。其中,-framerate 30控制輸入幀率為每秒30幀,-i image-%03d.png輸入一個圖片序列可以匹配image-001到image-999之間的所有圖片,-c:v libx264指定使用libx264庫進行編碼。
方案二:直接將幀序列繪制到OpenGL的GlSurfaceView上,同時使用MediaCodec對GlSurfaceView進行錄制,這種方案既滿足的實時預(yù)覽的需要,又可以快速的合成視頻。