前言
從2016年6月開始寫《javacv開發(fā)詳解》系列,到而今的《javacv入門指南》,雖然僅隔了兩年多時間,卻也改變了很多東西。
比如我們的流媒體技術(shù)群從剛開始的兩三個人發(fā)展到現(xiàn)在的三個500人群。又比如博主剛開始也想放棄,期間自行腦洞內(nèi)心掙扎的場面也就不詳說了,結(jié)果是現(xiàn)在還在堅持更新博客。當然這期間離不開群里小伙伴們一直以來的陪伴和支持,感謝大家一起默默為java流媒體技術(shù)踩坑,踩的多了也就真的成了路(也可能踩成深坑 )。另外感謝雷霄驊博士的ffmpeg博客,給予博主很大幫助,2016年剛開始接觸ffmpeg就忽聞博士去世,甚為感慨,大家且行且珍惜吧。
以前從來不覺得java可以做流媒體、音視頻編解碼這些,直到現(xiàn)在,頂多說java做流媒體是非主流。業(yè)界廣泛應(yīng)用的librtmp、live555、ffmpeg也都是c/c++的庫,剛開始也確實嘗試過使用jni方式調(diào)ffmpeg,發(fā)現(xiàn)做起來吃力不討好,后來在github發(fā)現(xiàn)了新大陸:javaCV。
有,總比沒有強。雖然連個API文檔都沒有,通過github項目描述的那可憐的幾個字勉勉強強知道它對ffmpeg、opencv等等等十幾個庫做了封裝,用javacpp方式為fmpeg、opencv等庫編譯了各個系統(tǒng)環(huán)境的包方便跨平臺調(diào)用。
JavaCV入門指南系列:
JavaCV入門指南:調(diào)用FFmpeg原生API和JavaCV是如何封裝了FFmpeg的音視頻操作
JavaCV入門指南:調(diào)用opencv原生API和JavaCV是如何封裝了opencv的圖像處理操作
JavaCV入門指南:幀抓取器(FrameGrabber)的原理與應(yīng)用
JavaCV入門指南:幀錄制器/推流器(FrameRecorder)的原理與應(yīng)用
JavaCV入門指南:幀過濾器(FrameFilter)的原理與應(yīng)用
JavaCV入門指南:FrameConverter轉(zhuǎn)換工具類及CanvasFrame圖像預(yù)覽工具類
一些題外話
踩坑到今天,可能還會有許多人躊躇疑惑javacv除了可以在音視頻和圖像處理這塊稍微可以施展手腳外,還可以做什么?除了這些,在應(yīng)對各種紛繁復雜的流媒體協(xié)議(rtp/rtsp/rtmp/flv/hls等等)也不在話下,當然一些小眾和國產(chǎn)協(xié)議(比如sip/gb28181/jtt178等)可能需要依賴netty/mina等網(wǎng)絡(luò)庫來實現(xiàn),編解碼上結(jié)合javaCV,性能上也已經(jīng)沒有什么顧慮。另外在深度學習領(lǐng)域,deeplearning4j借助javaCV的東風令java在深度學習領(lǐng)域也同樣引領(lǐng)風騷。
本系列將結(jié)合《javacv開發(fā)詳解》系列作為實戰(zhàn)教程,結(jié)合實例,力求簡單易懂,快速上手。
一、老生常談
javaCV能做什么,既然是"CV"大法,那自然是計算機視覺領(lǐng)域的庫,諸如音視頻、流媒體、圖像處理、深度學習、機器學習、人工智能等等等(現(xiàn)在流行后面這三個,寫上去應(yīng)該能唬住不少人,deeplearning曉得不,里面一堆的javaCV庫沒發(fā)現(xiàn)嗎)。
二、入門基礎(chǔ)
以上全是些空話,我們無非就是要用javaCV采集視頻和音頻,給這些音視頻編解碼,然后是用什么封裝格式封裝這些音視頻數(shù)據(jù),以及用什么協(xié)議傳輸,可能還要對視頻里的圖像進一步進行處理(這個屬于圖像處理范疇),流程大致如此(音頻方面了解不多,大家見諒):
拉流(采集)--->圖像像素數(shù)據(jù)/音頻數(shù)據(jù)<---->編/解碼 <---->音/視頻幀<---->解封裝/封裝---->推流
舉例:編解碼過程(以hevc編碼的rtsp轉(zhuǎn)rtmp/flv為例,無音頻數(shù)據(jù)):
rtsp流---拉流解復用--->h265(hevc)---解碼--->yuv像素數(shù)據(jù)---編碼--->h264---封裝推流--->rtmp/flv
1、圖像像素格式與圖片封裝格式
圖像像素格式(簡稱像素格式),一般指的是沒有經(jīng)過編碼的按照原始像素排列的數(shù)據(jù)。
舉個栗子,一個完整圖像的像素排列一般是這樣的(以4*4像素的rgb像素格式為例):
rgbrgbrgbrgb
rgbrgbrgbrgb
rgbrgbrgbrgb
rgbrgbrgbrgb
當然我們存儲的時候一般使用一維數(shù)組來存這些數(shù)據(jù),所以排列順序就變成這樣:rgbrgbrgbrgb.......以此類推。
圖片封裝格式指的我們?nèi)粘R姷降膒ng,jpg,bmp,gif等等圖片格式,其中bmp是無損格式,里面的數(shù)據(jù)格式就是圖片頭信息加上rgb排列的像素數(shù)據(jù),png/jpg這些都是有損壓縮格式,但是壓縮比還是很高的,為什么要壓縮下面會講到。
2、圖像?視頻幀?傻傻分不清楚
圖像像素數(shù)據(jù)指的是yuv、rgb,rbga,bgr,gbra等圖像像素格式,經(jīng)過編碼后才是視頻幀。比如我們常見的h264編碼,編碼其實就是對圖像像素數(shù)據(jù)的壓縮,(以rgb為例,假如當前圖像像素尺寸為1920*1080,,每種顏色用一個字節(jié)表示,也就是說每個像素點有紅綠藍三色共3字節(jié),圖像有1920*1080個像素點,也就是說這張圖像大小為1920*1080*3字節(jié),顯然數(shù)據(jù)太大了),可以這樣理解,h264編碼本質(zhì)上就是一種圖像數(shù)據(jù)壓縮算法。
補充:視頻幀中常常提到的I幀,B幀和P幀指的是什么?i幀也叫關(guān)鍵幀,實際上就是一張完整的靜態(tài)圖像,而B幀和P幀只是用來記錄畫面的運動矢量等非圖像數(shù)據(jù),B/P幀都需要依賴i幀才能夠正確解碼出完整圖像(有損的圖像畫面)。在實際應(yīng)用中各種視頻源中很少使用B幀,原因是雖然使用大量B幀可以提高壓縮率,但也會消耗更多的硬件性能,所以大多數(shù)情況下的視頻源都以i幀(關(guān)鍵幀)和大量P幀為主。
另外在直播應(yīng)用中i幀間隔會很低,這樣能夠更快的顯示首幀畫面(B/P幀需要i幀才能夠解碼),但是這樣也增加了傳輸?shù)臄?shù)據(jù)量,因為一個i幀通常會很大。
3、編碼?封裝?傻傻分不清楚
編碼上面已經(jīng)講了,是一種壓縮算法;那么封裝格式又是什么呢,封裝格式就是我們?nèi)粘R姷降囊曨l文件了,比如mp4,avi,mkv,flv等等等,按照每種封裝格式的規(guī)范把視頻幀和音頻按照一定順序存起來就成我們?nèi)粘?吹降囊曨l文件了,這些封裝格式一般都會包含一些頭/尾標識和一些視頻描述信息,這樣播放器讀取視頻文件的時候就知道該怎么播放這些視頻文件了(可以把封裝格式理解成收納箱,上面貼著小紙條說明里面放了哪些東西)。
壓縮圖片格式也可以參考視頻編碼格式,原理都一樣,都是對圖像數(shù)據(jù)做有損/無損壓縮。
什么是轉(zhuǎn)封裝?為什么轉(zhuǎn)封裝比轉(zhuǎn)碼消耗更少?為什么轉(zhuǎn)封裝無法改動視頻尺寸?
先舉個栗子:假設(shè)視頻格式(mp4,flv,avi等)是盒子,里面的視頻編碼數(shù)據(jù)(h264,hevc)是蘋果,我們把這個蘋果從盒子里取出來放到另一個盒子里,盒子是變了,蘋果是沒有變動的,因此視頻相關(guān)的尺寸數(shù)據(jù)是沒有改動的,這個就是轉(zhuǎn)封裝的概念。
有了上面這個例子,我們可以把“轉(zhuǎn)碼”理解為:把這個盒子里的蘋果(hevc)拿出來削皮切塊后再加工成櫻桃(h264)后再裝到另一個盒子里,多了一步對蘋果(hevc)轉(zhuǎn)換為櫻桃(h264)的操作,自然比直接把蘋果拿到另一個盒子(轉(zhuǎn)封裝)要消耗更多機器性能。
4、音/視頻源
音/視頻源可以是視頻文件、音頻文件,流媒體源,設(shè)備等等。
比如我們要看電腦或手機攝像頭視頻,就得采集設(shè)備的圖像數(shù)據(jù)(從源設(shè)備采集到的是像素數(shù)據(jù),一般是bgr或者rgb像素數(shù)據(jù))如果是某些廠商的商用攝像機,可能會支持rtsp/rtmp協(xié)議,要采集聲音呢,就得采集錄音/話筒設(shè)備里面的數(shù)據(jù)(一般是pcm采樣數(shù)據(jù))。
5、流媒體協(xié)議
rtsp協(xié)議棧,rtmp協(xié)議棧,hls,http-flv(理論上講這個flv不能算是流媒體協(xié)議,它只是個無限大的flv文件)等等。
例如rtmp,對編碼后的音視頻幀,要對其進行封裝成flv進行傳輸。
補充:說到底這些協(xié)議原理上依然是建立在tcp/udp基礎(chǔ)上的應(yīng)用層傳輸協(xié)議。
6、流媒體服務(wù)
支持音視頻存儲分發(fā)的服務(wù)都可以叫流媒體服務(wù)。
比如常見的srs(開源的rtmp流媒體服務(wù),當然它支持rtmp/hls/http-flv的分發(fā))和nginx(通過安裝模塊可以支持rtmp,hls,http-flv分發(fā)),除此之外的收費的和一些不太友好的開源流媒體服務(wù)就不一一介紹了。
下一章:javaCV入門指南:調(diào)用FFmpeg原生API和JavaCV是如何封裝了FFmpeg的音視頻操作?
支持eguid原創(chuàng)
?
JavaCV入門指南系列:
JavaCV入門指南:調(diào)用FFmpeg原生API和JavaCV是如何封裝了FFmpeg的音視頻操作
JavaCV入門指南:調(diào)用opencv原生API和JavaCV是如何封裝了opencv的圖像處理操作
JavaCV入門指南:幀抓取器(FrameGrabber)的原理與應(yīng)用
JavaCV入門指南:幀錄制器/推流器(FrameRecorder)的原理與應(yīng)用
JavaCV入門指南:幀過濾器(FrameFilter)的原理與應(yīng)用
JavaCV入門指南:FrameConverter轉(zhuǎn)換工具類及CanvasFrame圖像預(yù)覽工具類