JMF實現對USB視頻數據捕捉和應用
一、JMF簡介
Java Media Framework (JMF) API是Sun免費提供的基於Java的多媒體框架,利用這個框架能夠編寫出功能強大的多媒體程序,卻不用關心底層複雜的實現細節。
二、使用必備軟件
1、安裝Java JDK 1.6 版本,配置好Java開發環境;
2、安裝好jmf-2_1_1e-windows-i586.exe,該軟件會自動配置好相關的windows開發環境(當然如果你是在Linux或者Uinux的環境下開發,你可以去下載相應環境下的jmf驅動包)。
三、流媒體數據的處理方式
1、數據源(DataSource)
數據源(DataSource)就像錄像帶一樣,其中包含了媒體流。JMF數據源根據數據傳輸怎樣被啓動分爲兩類,即Pull Data-Source和Push Data-Source。Pull Data-Source可以是文件或Web頁。爲這種類型的數據制定的協議包括超文本傳輸協議(HTTP)和文件(FILE)。使用Pull Data-Source由客戶端啓動並控制數據的傳輸。
Push Data-Source是由服務器啓動並控制數據傳輸。Push Data-Source包括廣播媒體 (broadcast media),在線組播媒體(Multicast media)和視頻點播 (VoD) 。對broadcast media要用到實時傳輸協議 (Real-time Transport Protocol,RTP)。Push Data-Source可以是麥克風或網絡攝像頭(Webcam)。
2、播放器(Player)
播放器(Player)是一個對時基媒體進行Render 和 Control的媒體處理者。播放器處理媒體數據的輸入流並及時輸出它。DataSource被用於傳遞輸入媒體流給Player,至於Player輸出媒體流的目的地要依賴媒體被輸出的類型,如:聲音被輸出到揚聲器,視頻被輸出到計算機屏幕。播放器可有6種狀態。在整個事件發展過程中,播放器有2個主要狀態:Stopped and Started。而Stopped狀態又能被分解成5個待命狀態:Unrealized, Realizing, Realized, Prefetching, and Prefetched。在正常情況下,Player需要經歷上述的每個狀態直到它達到開始狀態。
3、 處理器(Processor)
處理器(Processor)只是播放器的一個特殊類型,除了繼承Player的所有功能外,還可以控制對於輸入的媒體流進行何種處理。Processor能發送輸出數據到一個輸出設備或到一個DataSource。如果數據被髮送到一個DataSource,則這DataSource可以被用於另外的Player或Processor的輸入,或作爲DataSink的輸入。Processor還可解析媒體流,執行特殊功效的編碼或解碼,並可將多個輸入軌道的數據融合到一起。如可將分開的視頻和音頻軌道中的數據流合併成單一的MPEG-1數據流。可以指定輸出流的數據類型。
除了在播放器中提到了6種狀態外,Processor 對象還有另外的兩種新的狀 態,這兩種狀態是在Unrealized狀態之後,但是在Realizing狀態之前。
(1) Configuring:當調用configure()方法後,Processor對象進入該狀態。 在該狀態下,Processor對象連接到數據源並獲取輸入數據的格式信息。 (2)Configured:當完成數據源連接,獲得輸入數據格式的信息後,Processor 對象就處於此狀態。
當一個Processor在Configured狀態時,可對某個單一的軌道調用getTrackControls()方法獲得對該軌道對象的控制。
4、捕捉設備(Capture devices)
捕捉設備(Capture devices)是指可以捕獲到視頻或音頻數據的硬件。如麥克風可以捕獲音頻數據、網絡攝像頭可捕獲視頻數據,因此它們兩個都是數據源(Push DataSource)。捕獲到的數據可以被送入到Player或Processor對象進行處理。
5、媒體數據存儲和傳輸(DataSink)
DataSink經常被用於從DataSource讀取媒體數據並傳送媒體數據到一些輸出目的地。JMF提供一默認的DataSink,可以被用於寫數據到文件。其它類型的DataSink類能寫數據到網絡或另外的目的地。注意,Plaryers、Processors和DataSinks都屬於MediaHandlers,它們都是從DataSource讀取數據。如果想保存捕獲的媒體數據到文件,必須用Processor替代Player,然後用DataSink從Processor對象輸出的DataSource中讀取數據並輸出數據到文件。
四、捕捉視頻及聲音並保存到磁盤實例
1、捕獲視頻及聲音
爲了使用視頻和音頻設備捕獲媒體數據,需要以下幾個步驟:
(1)通過調用方法CaptureDeviceManage()定位想用的捕獲設備。
(2)對定位的設備獲得相應的CaptureDeviceInfo對象。
(3)通過CaptureDeviceInfo對象獲得MediaLocator並用之創建DataSource。
(4)用DataSource創建Player 或Processor。
(5)Start這個Player或Processor,開始捕獲媒體數據。
相應的代碼示例如下[1,2]。注意,若單獨考慮捕獲音視頻數據到屏幕,直接用SUN提供的示例代碼即可。但爲使錄製電影文件與屏幕顯示不衝突,這裏用到了數據克隆。
//定位捕獲設備
MediaLocator[] locatorVA = new MediaLocator[2];
locatorVA[0] = new MediaLocator("javasound://0");
locatorVA[1] = new MediaLocator("vfw://0");
//獲得MediaLocator並用之創建DataSource
DataSource[] dsc = new DataSource[2];
dsc[0] = Manager.createDataSource(locatorVA[0]);
dsc[1] = Manager.createDataSource(locatorVA[1]);
//將視頻與音頻合併
DataSource mainSource=Manager.createMergingDataSource(dsc);
//爲了能讓幾個Processor訪問同一數據源,需將之轉換成可克//隆的數據源
mainSource=Manager.createCloneableDataSource(mainSource);
//用克隆的數據源創建Processor
DataSource camSource = (SourceCloneable)mainSource.
createClone();
Processor processor = Manager.createProcessor(camSource);
// 用類camStateHelper可幫助控制Processor的媒體事件
camStateHelper playhelper = new camStateHelper(processor);
//Configure, Realize然後開始我們的Processor
playhelper.configure(10000);
// Processor的內容描述符必須設置成空,爲防止Processor的數//據源來自輸出的原始數據
processor.setContentDescriptor(null);
playhelper.realize(10000);
processor.start();
//用Processor的可視組件將電影顯示到屏幕上
processor.getVisualComponent().setBackground(Color.white);
centerPanel.add(processor.getVisualComponent(),
2、保存到磁盤
可用 DataSink從Processor對象的輸出數據源中讀取數據並將之輸出到文件中。具體步驟如下:
(1)創建一個MediaLocator對象用於指定想保存的文件位置。
URL movieUrl = file.toURL();
MediaLocator dest = new MediaLocator(movieUrl);
(2)再克隆一份數據源並用之又創建一個Processor。
DataSource recordCamSource = dataSource.cloneCamSource();
Processor recordProcessor = Manager.createProcessor
(recordCamSource);
camStateHelper playhelper = new camStateHelper
(recordProcessor);
(3)對該Processor調用configure
Playhelper.configure(10000);
(4)對每個軌道調用方法getTrackControls和setFormat。音視頻的軌道序號應與捕獲代碼中的音視頻順序一致。
VideoFormat vfmt = new VideoFormat(VideoFormat.JPEG);
AudioFormat afmt = new AudioFormat(AudioFormat.LINEAR);
(recordProcessor.getTrackControls())[0].setFormat(afmt);
(recordProcessor.getTrackControls())[0].setEnabled(true);
(recordProcessor.getTrackControls())[1].setFormat(vfmt);
(recordProcessor.getTrackControls())[1].setEnabled(true);
(5)用Processor的輸出數據源創建DataSink,並將數據寫到指定格式的文件中。
recordProcessor.setContentDescriptor(new FileTypeDescriptor(FileTypeDescriptor.QUICKTIME));
Control control = recordProcessor.getControl ("javax.media.control.FrameRateControl");
playhelper.realize(10000);
DataSink dataSink = Manager.createDataSink(recordProcessor.
getDataOutput(), dest);
recordProcessor.start();
dataSink.open(); //打開文件
dataSink.start();
(6)調用stop()和close()方法,結束數據的捕獲。
recordProcessor.stop();
recordProcessor.close();
dataSink.stop();
dataSink.close();
附:相關的源代碼以及相關的安裝軟件已經附帶到文件夾!源代碼實現了:1、捕捉任意禎的圖像,並以.GIF的格式保存圖片至硬盤;
2、錄製實時視頻(包括實時聲音),並以.QUICKTIME的格 式保存至硬盤;
3、對於硬件的要求:帶USB接口的攝像頭(攝像頭能正常使 用),能正常使用的麥克風。
對於圖片和視頻的格式可以進行修改,此處暫略!