1.1.3 EMIPLIB簡介
EMIPLIB全稱爲“EDM Media over IP Library”,是比利時哈瑟爾大學下屬研究機構Expertise Centre for Digital Media (EDM)研發的開源代碼,此庫用於串聯流媒體系統所必須的各個功能模塊:音視頻數據採集(Input)與播放(Output)、編碼(Encode)與解碼(Decode)、網絡傳輸(Transmission),使流媒體系統的開發變得更加容易與高效。
此庫的框架設計合理,功能強大,尤其便於二次開發。下面將分別從它的主要功能部件、運行機制及原理實現進行簡要介紹和分析。
1.1.3.1 EMIPLIB 的功能
目前EMIPLIB支持的具體功能如下:
l 聲卡輸入:支持OSS,WinMM,Jack和PortAudio;
l 聲卡輸出:支持OSS,ALSA,ESD,WinMM,Jack,SDL和PortAudio;
l 支持OpenAL輸出組件;
l 支持WAV格式文件輸入,但需要預裝libsndfile、libaudiofile或者一個WAV reader作爲支持庫;
l 支持WAV格式輸出,但需要預裝libsndfile或者一個WAV writer作爲支持庫;
l 支持攝像頭、並口或者USB輸入:需要預裝Vide04Linux和DirectShow組件;
l 支持Speex壓縮方式;
l 支持U-law音頻編碼標準;
l 支持A-law音頻編碼標準;
l 支持LPC壓縮方式;
l 支持GSM 06.10壓縮方式;
l 支持H.263+壓縮方式;
l 支持針對音頻流的混音處理;
l 能夠根據RTCP報文信息同步RTP碼流;
l 支持通過HRIR/HRTF信息實現3D特效;
l 能便捷的輔助實現VOIP(Voice Over IP)和網絡視頻會話。
EMIPLIB已經在下列平臺上通過了測試:
l GNU/Linux
l Mac OS X
l Win32
l WinCE
l Android
1.1.3.2 EMIPLIB 實現機制
一個通用的流媒體系統必須至少包含如下組件:
通用流媒體系統結構圖
(1) 輸入模塊(Input Module)
獲取原始視頻流,可以是從文件中讀取,也可以通過設備採集獲得。
(2) 編碼模塊(Encode Module)
按照各種編解碼協議,將原始視頻流進行壓縮,使傳輸速率和質量得到提高,適用於網絡傳輸。
(3) 網絡傳輸模塊(Transmission Module)
根據所使用的網絡傳輸協議,將壓縮後的視頻碼流打包爲相應報文形式,便於實現對應協議中的流量控制、差錯控制等控制行爲。
(4) 解碼模塊(Decode Module)
將被壓縮的視頻流還原爲原始視頻流。
(5) 輸出模塊(Output Module)
將原始視頻流進行播放或者存儲。
上述每一個模塊都可以根據實際需求,採用不同的實現手段。比如編碼模塊,既可以使用高性能的H.264編碼方式壓縮數據流,也可以在某些低碼流應用場景中選擇H.263作爲實現手段。
因此,EMIPLIB根據上述特點,將自己設計爲一個可供拆卸的邏輯“貨架”,功能模塊中每一種特定的需求實現就是可在“貨架”中安置的“貨物”。我們將所需要的“貨物”按照一定的實現順序依次安放在貨架上,當視頻流從“貨架”頭流動到“貨架”尾時,就能獲取到我們需要的數據。
舉個例子,當我們需要在一個已安裝V4L的Linux系統上把攝像頭中捕獲到原始數據流(假設格式爲YUV420P)壓縮爲H.264編碼後,打包爲RTP包格式傳送給客戶端,那麼我們應該依次把“V4L調用組件”、“H264壓縮組件”、“RTP打包組件”這些“貨物”放入貨架上。當我們啓動貨架開關後,在貨架尾部就可以得到所期望的RTP碼流。
EMIPLIB將把貨物依次串起來的“貨架”叫做Component Chain(組件鏈),把“貨物”叫做Component(組件)。EMIPLIB使用一個虛擬類MIPComponent定義作爲“貨物”所必須具備的功能,供外部調用,而每一個真正負責實現該功能模塊的類對象必須繼承該標準接口,通過不同的底層手段,來實現相同的接口定義功能。
因此,根據EMIPLIB開發出的流媒體系統,模塊間鬆耦合,各模塊開發過程比較獨立,後期可擴展性和可伸縮性都很好。流媒體系統的搭建只需要爲每個功能模塊選擇合適自身系統特點的實現組件,使用一條Component Chain(組件鏈)將每個組件串起來,視頻流就將源源不斷的從第一個功能模塊流向最後一個功能模塊,並按照我們期望的方式輸出數據。
至於EMIPLIB的跨平臺支持性,在一定程度上是依靠CMake自動化建構系統的輔助實現的。CMake使用與Make相似的build process方式,只是 CMake 的build文檔取名爲 CmakeLists.txt。Cmake 並不直接建構出最終的軟件,而是產生標準的建構檔(如 Linux系統下產生Makefile或 Windows Visual C++ 環境下產生projects/workspaces),然後再依靠一般的建構方式使用。同時,CMake可以獲取當前操作系統環境的具體配置,整理出可供EMIPLIB調用的庫資源,並按照EMIPLIB預寫入的軟件配置方案(.ini文件),將系統已安裝的庫資源以宏定義的形式寫入到配置文件。當EMIPLIB運行時,則可通過讀取該配置文件中的宏定義,獲取當前系統配置信息,從而針對不同系統環境進行區別處理。
1.1.3.3 EMIPLIB 體系結構
1. EMIPLIB的功能模塊劃分
爲了實現我們在3.2.4.1節提到的功能,EMIPLIB將自身已經實現的所有組件分爲八個功能模塊,具體如下:
三‑2功能模塊結構圖
l 輸入(Input):
從音頻文件輸入:mipaudiofileinput
Android平臺的音頻調用:mipaudiorecorderinput
Windows平臺下一般採用DirectShow進行視頻採集:mipdirectshowcapture
自實現的特定頻率的音頻產生器,實現簡單,通過輸入的左/右聲道的振幅和頻率、採樣速率、採樣週期,帶入音頻運算式中即可獲得所需音頻數據:mipfrequencygenerator
Linux下的Jack聲音框架(Jack audio connection kit):mipjackinput
從文件中讀取音頻碼流,基於libsndfile庫:mipsndfileinput
V4L(video for linux)是Linux下視頻採集設備驅動程序的編寫提供統一的接口而提出的一套規範(API):mipv4linput
V4L2(video for linux Two),對V4L做出極大改進,因此與V4L並不兼容:mipv4l2input
WAV音頻文件輸入:mipwavinput
Windows下音頻採集方案WINMM:mipwinmminput
以原始碼流格式YUV420P存儲的文件讀入:mipyuv420fileinput
l 編解碼(Codec):
A律編解碼組件:mipalawdecoder,mipalawencoder
需FFMPEG中libavcodec庫支持,EMIPLIB針對視頻部分僅實現H.263+編解碼工作,因此視頻部分的RTP打包也僅實現荷載爲H.263+編碼格式報文:mipavcodecdecoder,mipavcodecencoder
GSM 06.10編解碼組件:mipgsmdecoder,mipgsmencoder
LPC編解碼組件:miplpcdecoder,miplpcencoder
SILK編解碼組件:mipsilkdecoder,mipsilkencoder
Speex編解碼組件:mipspeexdecoder,mipspeexencoder
基於Tiny JPEG Decoder 庫,支持將JPEG壓縮格式逐幀轉換爲YUV420P原始數據流:miptinyjpegdecoder
u律編解碼組件:mipulawdecoder,mipulawencoder
l 網絡傳輸(Transmission):實現RTP協議針對不同編碼格式的打包和解包工作
(1) EMIPLIB對音頻壓縮格式的RTP打包、解包支持:
A律、u律、GSM、L16(處理16bit按照大端存儲方式數據流,默認採樣率爲44100Hz,作爲RFC3551中預定義的負載類型實現)、LPC、Dummy解包機制(當收到不支持的打包格式時,使用此機制拋棄報文。而不會作爲異常拋出)、SILK、Speex
(2) EMIPLIB對視頻壓縮格式的RTP打包、解包支持:
按照RFC實現了H.263+格式的打包、解包。
內部實現(非RFC實現)H.263+與YUV420P的RTP打包,但外部設備無法識別。
l 格式轉換(Transform):
mipaudiofilter
mipaudiosplitter
mipavcodecframeconverter
miphrirbase
miphrirlisten
mipsampleencoder
mipsamplingrateconverter
mipspeexechocanceller
mipyuv420framecutter
l 計時器(Timer):作爲Component Chain的第一個組件,按照碼流速率將視頻流按幀分時處理
組件鏈中每隔設定時間,發送MIPSYSTEMMESSAGE_ISTIME系統報文觸發下一組件:mipaveragetimer
多線程組件鏈時,設定組件間時序關係:mipinterchaintimer
等待特定事件完成後纔開啓計時器(比如一個被動等待聲音輸入的聲卡設備在組件鏈頂端,則可以將此定時器放在其後,當有音頻數據輸入後系統纔開始運行):mippusheventtimer
l 輸出(Output):
Linux系統環境下調用Advanced Linux Sound Architecture (ALSA) 來實現聲卡輸出:mipalsaoutput
Android平臺上音頻回放機制:mipaudiotrackoutput
Enlightened Sound Daemon (ESD)聲卡輸出:mipesdoutput
Jack音頻輸出套件:mipjackoutput
OpenAL音頻輸出組件:mipopenaloutput
QT播放器(調用其API可直接播放音視頻數據流):mipqtoutput
SDL音頻輸出組件,接受16 bit本地原始音頻流的播放:mipsdlaudiooutput
將收到的音頻數據流寫入本地文件:mipsndfileoutput
支持將格式爲YUV420P的視頻流進行本地存儲:mipvideoframestorage
僅支持將8 bit無符號音頻流寫入本地文件:mipwavoutput
Win32/WinCE平臺下的音頻播放組件:mipwinmmoutput
l 混音(Mixer):
mipaudiomixer
mipmediabuffer
mipvideomixer
l 輸入輸出(IO,InputOutput):既可以在組件中作爲Input組件使用,也可以作爲Output組件使用
調用OSS(Open Sound System開放聲音系統):mipossinputoutput
調用PortAudio聲卡:mippainputoutput