• 沒有找到結果。

子系統之建構流程

二、 Java 多媒體系統

2.3 子系統之建構流程

圖 2-6 處理媒體之子系統建構流程

2.3.1 影音來源

藉由UI 所傳遞的資訊(圖 2-6 的虛線 1):影音資料格式和影音來源位置,建 立管理影音資料的DataSource 物件,如圖 2-6,必須執行下面函式(請參考 2.4.1):

JMFUtils.createCaptureDataSource(audioDeviceName, getAudioFormat( ), videoDeviceName, getVideoFormat( )),其函式利用已知的裝置名稱和影音媒體 格式,建立DataSource 物件,如表格 2-2。

表格 2-2 DataSource 物件 DataSource

streams:PushBufferStream[2]

Connect()

DataSource 物件內的 PushBufferStream 陣列,會有存有管理影像資料和音 訊資料的物件,分別是VFWSourceStream 和 DirectSoundStream 物件。

connect( )函式與 thread 的建立有關,請參考 3.2 節。

2.3.2 影音分流

有了影音資料的來源,我們必須利用DataSource 物件作為引數,建立圖 2-6 中的Processor,接著必須執行 Manager.createProcessor(DataSource)函式。媒 體資料將會輸入Processor,經過各個處理媒體資料的元件,執行相關資料處理 的程序。當媒體資料傳遞至Processor,則必須將影音資料執行影音分流的處理,

因此必須執行以下程序,(1)找出適當的 parser(解多工器),執行影音分流的處理 (2)建立 BasicSourceModule 物件,此物件作為媒體資料壓縮處理的來源。

(1)找出適當的 parser。DataSource 物件包含媒體的內容型別,由於影音來 源自擷取裝置,因此內容型別為raw,藉由此內容型別找出相對應的 parser。首 先建立ContentDescriptor 物件,其包函媒體的內容型別 (raw),接著執行 PlugInManager.getPlugInList(ContentDescriptor, ,1)函式,此函式會找尋所有 JMF 有支援的 parsers(圖 2-7),最後將內容型別 (raw)和所有 parsers 的輸入的 格式都轉為數值,接著開始互相比對,互相符合者就是我們所要使用的parser,

在此為RawBufferParser,接著建構 RawBufferParser 物件,此 parser 是負責 處理未經過處理的媒體資料。

圖 2-7 JMF 支援的 parsers

(2)建立 BasicSourceModule 物件。利用上述的 parser 和 DataSource 物件 以引數的形式,呼叫BasicSourceModule(DataSource, parser),建立

BasicSourceModule 物件,此物件負責將音訊或影像資料送至處理壓縮媒體資料 的子系統,請參考 3.4 節。

當Processor 已得到關於媒體資料的資訊,確定資料的格式與位置,

Processor 的狀態應該轉變為 Configured 的狀態(請參考 2.4.1 節)。因此必須呼 叫configureProcessor ( )函式,主要執行下面程序:執行 parser 的 getTracks( ) 函式,會依track 的數量建立相同數量的 RawBufferParser$FrameTrack 物件:

BufferTransferHandler,此物件將會分別抽出音訊和影像的媒體資料,負責將 媒體資料送入parser。

最後必須要對DataSource 物件設置負責資料傳遞的 BufferTransferHandler,分別下面函式:

VFWSourceStream.setTransferHandler(RawBufferParser$FrameTrack)、

DirectSoundStream.setTransferHandler(RawBufferParser$FrameTrack),

BufferTransferHandler 是負責將媒體資料自 DataSource 物件抓入 Parser 內的 暫存器,實際資料的搬運細節請參考 3.4。

2.3.3 影音壓縮

欲將媒體資料以串流的傳輸方式傳送至用戶端前,必須將未處理的媒體資料 壓縮,轉換為能進行即時串流傳輸的媒體格式。由 2.2.3 節,自UI 取得影音編 碼格式的資訊,由此資訊選擇所要使用的Codec,Codec 以引數的形式建立 BasicFilterModule 物件,此物件是負責將未經處理的媒體資料交由 encoder 處 理,編碼完成後的媒體資料會送入多工器,由多工器將媒體資料送至

RTPSession。

因此必須將Processor 狀態由 Configured 更新為 Realized(請參考 2.4.1),

更新Processor 狀態必須執行 realizeProcessor( )函式,此函式會建立 RealizeWorkThread 物件,此 thread 進入待命狀態,當開始執行時會呼叫 doRealize( )函式,來執行以下兩個程序:1.建立 BasicFilterModule 物件,2.建立 多工器。

1.Codec 以引數的形式建立 BasicFilterModule 物件,如表格 2-3。

表格 2-3 BasicFilterModule 物件 BasicFilterModule

codec:Codec

ic:BasicInputConnector oc:BasicOutputConnector

表格 2-3 中ic 為媒體資料輸入 BasicFilterModule 的路徑,oc 為自

BasicFilterModule 輸出的路徑,ic 和 oc 是輸入/出 BasicFilterModul 的連結器,

它的內部會定義 buffer 和媒體輸入/出的格式。接著呼叫 BasicFilterModule.

doRealize( )函式,此函式會執行 codec.open( )函式,對 encoder 作初始。

表格 2-4 Picture Formats Supported FRAME

FORMAT

Width height nativeformat

SQCIF 128 96 0

QCIF (PAL) 176 144 1

CIF (PAL) 352 288 2

在此以H.263 為例,表格 2-4 中,提供 3 種影像格式,藉由影像資料欲壓縮 的影像格式(大小)決定 nativeformat 參數值,初始 h.263 的 encoder。由 2.2.2 節,自UI 取得擷取的影像大小的資訊,接著對影像大小的資訊作一簡單的檢驗 程序,如下:

if videosizewidth>=352 { w=352;

初始 h263 的 encoder 所需的參數有:nativeformat、MTUPacketSize 與 IFramePeriod。MTUPacketSize = 1024-RTPsize(12)-UDPsize(8)-IPsize(20) = 984(byte),由於編碼完成的資料將來都必須封裝程 RTP 封包,而在 Internet 所 傳遞的封包大小不可以超過 1500byte,因此每一編碼完成的資料都會存入暫存 器中,暫存器所存的資料就是payload。每一 Picture layer 內總共有 15 個 frame,

第一個frame 為 Iframe,因此 IframePeriod 設為 15。

2.執行 connectMux( )函式,此函式建立 BasicMuxModule 物件,此物件會 包含RTPSyncBufferMux(多工器)物件,接著初始多工器的輸入端,因此建立兩 個RawBufferSourceStream 物件,此物件是媒體(A/V)輸入多工器,資料存放的 地方。當建立RawBufferSourceStream 物件的同時,會建立兩個

RawBufferStreamThread,此兩個 thread 負責傳遞實際的音訊和影像的資料,

請參考第三章。

2.3.4 RTP Session

此節,將會探討如何建立RTPSession以及其流程,如圖2-8。

RTPSession

RTPSessionMgr.initialize( local Addr&Port)

DatagramSocket(Port, local Addr)

RTPSessionMgr.createSendStream(DataSource, i )

generateSSRC() RTPSinkStream

StartDataTransmission(dataPort, destAddr)

RTPRawSender(dataPort, destAddr,sender) UDPPacketSender(datagramsocket)

Processor

RTPSessionMgr.initialize( local Addr&Port)

DatagramSocket(Port, local Addr)

RTPSessionMgr.createSendStream(DataSource, i )

generateSSRC() RTPSinkStream

StartDataTransmission(dataPort, destAddr)

RTPRawSender(dataPort, destAddr,sender) UDPPacketSender(datagramsocket)

Processor

DataSource

Socket

SendStream

RTPTransmitter

圖2-8 RTPSession

即時的影音資料經Processor(圖2-1)處理後,以串流的傳輸方式將媒體資料 傳送至遠方的用戶端,為達到此目的我們必須建立RTPSession,來管理傳送RTP 封包的session(請參考2.4.2節)。

利用源自UI所取得遠方用戶端的資訊:IP位址和port來建立RTPSession,必 須執行JMFUtils.createSessionManager (IP位址, Port, Ttl, null )函式,此函式會 負責建立RTPSessionMgr物件,由此物件管理RTPSession,如圖2-7。當欲自本 地端傳送封包至網際網路時,必須先建立Socket,由2.5.1節可知,負責傳送封 包的為DatagramSocket,因此必須給予專屬此DatagramSocket的port和IP位 址,必須執行RTPSessionMgr.initialize( 本地端IP位址,port),此函式會建立 DatagramSocket,DatagramSocket會被繫結至本地通訊埠,發送封包時,該通 訊埠也會被填入datagram的標頭。

由圖 2-7 可知,自Processor 輸出的媒體資料是包含在 DataSource 物件,

其中i 引數是代表要對音訊或是影像建立資料串流。接著要對同一音訊或影像串 流設定一SSRC 的數值,執行 generateSSRC( )函式。由圖 2-1 我們已知 Processor 的輸出也就是多工器的輸出,當媒體資料自多工器輸出時必須要有一暫存器存放 輸出的資料,RTPSinkStream 物件就是扮演上述的角色,因此建立

RTPSinkStream 物件。並且執行 RTPSinkStream.setFormat(format),format 物件為RTPPayload 的影音格式,接著呼叫 format.getSampleRate( )函式取得 此資料型態的取樣率。

Clock Rate(Hz)

0 ULAW/RTP A 8000

3 GSM/RTP A 8000

4 G723/RTP A 8000

5 DVI/RTP A 8000

14 MPEGAUDIO/RTP A 32000

15 G728/RTP A 8000

26 JPEG/RTP V 90000

31 H261/RTP V 90000

32 MPEG/RTP V 90000

34 H263/RTP V 90000

當RTPSinkStream 物件取得媒體資料後,必須將媒體資料封裝為 RTP 封 包,設置RTP 標頭所有參數(請參考 2.5.2),RTPTransmitter 物件會執行上述 功能。RTP 封包建立完成後,將資料填入 DatagramPacket,接著 DatagramPacket 會由DatagramSocket 送出,如圖 2-7 中,RTPRawSender(dataPort,

destAddr,sender)所建立的物件會執行上述流程,其中 dataPort:通訊埠,

destAddr:用戶端 IP 位址,sender 為 UDPPacketSender(datagramsocket),

UDPPacketSender 物件負責將 DatagramePacket 送至 DatagramSocket。

最後執行 SendStream.start( )函式,當呼叫 start( )函式時則會執行

RTPSinkStream.start()此時表示已準備好可以將影音資料自 Processor 送入。實 際媒體資料傳遞細節,請參考 3.4 節。

相關文件