• 沒有找到結果。

多執行緒在多媒體串流的應用

N/A
N/A
Protected

Academic year: 2021

Share "多執行緒在多媒體串流的應用"

Copied!
98
0
0

加載中.... (立即查看全文)

全文

(1)

電機學院通訊與網路科技產業研發碩士班

多執行緒在多媒體串流的應用

Construction of Multi-media Streaming

with Multithread Programing

研 究 生:韓孟潔

指導教授:張文鐘 教授

(2)

多執行緒在多媒體串流的應用

Construction of Multi-media Streaming

with Multithread Programing

研 究 生:韓孟潔 Student:Meng-Jie Han

指導教授:張文鐘 Advisor:Wen-Thong Chang

國 立 交 通 大 學

電機學院通訊與網路科技產業研發碩士班

碩 士 論 文

A Thesis

Submitted to College of Electrical and Computer Engineering National Chiao Tung University

in partial Fulfillment of the Requirements for the Degree of

Master in

Industrial Technology R & D Master Program on Communication Engineering

August 2007

Hsinchu, Taiwan, Republic of China

(3)

多執行緒在多媒體串流的應用

研究生:韓孟潔

指導教授:張文鐘 博士

國立交通大學

電機學院通訊與網路科技產業研發碩士班

多媒體串流傳輸的技術,可以使得消費者不需花費大量的等待時間至檔案完全下載完畢即 可播放影音檔案,此技術亦可使用在傳輸live 的影音資料。

本論文探討利用Java Media Framework 建置一個可以處理即時影音資料並傳送至遠方

接收端的串流系統,系統建置流程如下:設置擷取裝置的路徑、設定影音來源的格式、影音分

流、影音資料壓縮與RTP 封包建立與發送。

此系統整體的運作是藉由多個thread 各自執行專屬的任務,如截取影音資料、資料壓縮…

等,以及多個thread 彼此間相互溝通與合作而達成,在本論文中會探討 Java thread 同步機

制的基本原理,以及實際系統程式所使用的thread 排程機制,以達到 thread 之間的制衡。並

實際觀測multithread 的執行順序與時間,分析系統真實的狀態,並且說明 thread 之間確實

是以Java thread 同步機制和系統程式所使用的 thread 排程機制來運作,證明彼此之間互相

(4)

Construction of Multi-media Streaming

with Multithread Programing

Student:Meng-Jie Han Advisor:Wen-Thong Chang

National Chiao Tung University Industrial Technology R & D Master Program on

Communication Engineering

ABSTRACT

With the multi-media streaming technology, consumers do not have to speed a lot of waiting time while downloading the multi-media data. This technology can also be used to transmit live audio/video.

This work discusses the construction of multi-media streaming system with Java Media Framework (JMF). System is constructed in the following sequence: set the path of capture device , set the file format of the audio/video, parse the multi-media data , compress multi-media data, create RTP Packets and transmit RTP Packets.

The Java based streaming system is operated with threads which may work alone or co-operate. Synchronization of Java threads and multithread scheduling are also discussed in this work. Finally, we observe the timing sequence of multithread.

(5)

誌 謝

能順利完成這篇論文,首先要誌謝的人是我的指導教授 張文鐘 博士。在這二 年多的時間,老師在學術研究和研究態度、方法以及專業知識上,給予我許多的啟 發,使我獲益良多,對於往後的發展幫助很大。同時也謝謝教授們於口試時的指導, 有了您的指導才使得這篇論文更趨完備。 再來要感謝無線多媒體通訊實驗室的所有同學們,在這段期間內,大家一起討 論、共同成長,謝謝你們的協助使我釐清許多盲點。跟你們在這兩年一起修課、聊 聊生活瑣事、打球使得苦悶的研究生生活多了幾分亮麗、愉悅的色彩。 最後要感謝的是我的家人,你們不但感受我在這段時間內的壓力,更不時給予 我最大的關懷與支持,有了你們的支持以及鼓勵我才能順利地完成碩士學業,在此 向你們致上最高的感謝之意。 誌於2007.8 風城 交大 Meng Jie

(6)

目錄

中文摘要 ……… i 英文摘要 ……… ii 誌謝 ……… iii 目錄 ……… iv 圖目錄 ……… vii 表目錄 ……… x 一、 緒論……… 1 1.1 背景介紹……… 1 1.2 研究動機……… 2 二、 Java 多媒體系統 ……… 3 2.1 系統架構……… 3 2.2 使用者介面(UI)之建構流程 ……… 4 2.2.1 硬體支援之影音格式 ……… 4 2.2.2 系統支援之影音格式 ……… 5 2.2.3 影音編碼格式選項……… 5 2.2.4 取得用戶端資訊 ……… 8 2.3 子系統之建構流程 ……… 8 2.3.1 影音來源……… 8 2.3.2 影音分流……… 9 2.3.3 影音壓縮 ……… 11 2.3.4 RTP Session... 13

2.4 Java Media FrameWork ……… 15

(7)

2.4.2 JMF RTP Architecture……… 20

2.5 Java Socket & Real-Time Transport Protocol………… 22

2.5.1 Java Socket ……… 22

2.5.2 Real-Time Transport Protocol ……… 25

2.5.2.1 RTP 檔頭架構……… 26 三、 Java 多媒體系統動態分析 ……… 28 3.1 各個Thread 的功能介紹 ……… 28 3.2 Thread建立的流程 ... 29 3.3 Thread之間的資料分享與溝通 ……… 32 3.3.1 子系統介紹和Thread 所屬之類別物件……… 33 3.3.2 Thread的設計原理與制衡 ……… 35 3.3.2.1 處理影像資料 ……… 35 3.3.2.2 處理音訊資料 ……… 42 3.4 系統程式執行的細部運作 ……… 44 3.4.1 Video 資料的處理流程 ……… 44 3.4.2 Audio 資料的處理流程 ……… 49 3.4.3 資料壓縮與傳遞 ……… 51 3.5 RTP封包建立與發送 ……… 53 3.6 Java Thread ……… 54 3.6.1 Thread狀態 ……… 56 3.6.2 Thread 建立的方式 ……… 57 3.6.3 Thread 同步機制 ……… 58 3.6.4 Thread 之間的溝通 ……… 60 3.6.5 自訂排程 ……… 61 3.6.6 Multithread 之應用 ……… 62

(8)

3.6.7 Java虛擬機的簡介 ……… 63 四、 Thread試驗 ……… 65 4.1 Thread封鎖與時間之試驗 ……… 65 4.2 Thread執行次序和時間之量測 ……… 68 4.2.1 暫存器之儲存列 ……… 69 4.2.2 次序和時間量測 ……… 69 4.3 結論與相關探討 ……… 74 五、 結論 ……… 78 參考文獻 ……… 79 附錄一 Thread 順序和時間量測的數據 ……… 80 附錄二 暫存器空間不足的特例……… 81 附錄三 SourceThread(V)封鎖試驗 ……… 83

(9)

圖目錄

圖 2-1 媒體資料處理系統 ……… 3 圖 2-2 UI 建構流程 ……… 4 圖 2-3 裝置支援格式 ……… 5 圖 2-4 JMF 所支援的多工器 ……… 6 圖 2-5 顯示Video 編碼格式 ……… 8 圖 2-6 處理媒體之子系統建構流程 ……… 8 圖 2-7 JMF 支援的 parsers ……… 10 圖 2-8 RTPSession ……… 13 圖 2-9 JMF Architecture ……… 16 圖 2-10 JMF Media Formats ……… 17 圖 2-11 Process stages ……… 18 圖 2-12 Processor states ……… 19 圖 2-13 RTP transmission ……… 21 圖 2-14 RTP reception ……… 21 圖 2-15 JMF RTP architecture ……… 21 圖 2-16 伺服端與用戶端之架構 ……… 24

圖 2-17 Java Datagram Socket ……… 24

圖 2-18 RTP architecture ……… 25

圖 2-19 RTP data-packet header format ……… 27

圖 3-1 Thread 建立流程 ……… 28

圖 3-2 (a)音訊擷取裝置管理、音訊資料來源 ……… 33

圖 3-2 (b)影像擷取裝置管理、影像資料來源 ……… 33

圖 3-2 (c)影音來源之分流 ……… 33

(10)

圖 3-2 (e)影音來源整合 ……… 33 圖 3-2 (f) RTP 封包建立和傳送……… 33 圖 3-3 (a)音訊來源 ……… 34 圖 3-3 (b)影像來源 ……… 34 圖 3-3 (c)影音分流 ……… 34 圖 3-3 (d)多工器輸入來源 ……… 34 圖 3-4 Thread Path(V) ……… 36 圖 3-5 PushThread(V) ……… 37 圖 3-6 VFWTransferDataThread(V) ……… 38 圖 3-7 SourceThread(V)……… 39 圖 3-8 RawBufferStreamThread(V) ……… 40 圖 3-9 buffer manage(V) ……… 41 圖 3-10 Thread Path(A) ……… 42 圖 3-11 DirectSoundPushThread(A)……… 43 圖 3-12 buffer manage(A) ……… 44 圖 3-13 系統運作(V)……… 44 圖 3-14 擷取影像資料 ……… 45 圖 3-15 抽取影像資料 ……… 47 圖 3-16 資料壓縮流程 ……… 48 圖 3-17 RTP 封包建立與發送之前置處理 ……… 49 圖 3-18 系統運作(A)……… 50 圖 3-19 擷取&抽取音訊資料……… 51 圖 3-20 資料壓縮與傳遞之流程 ……… 52

圖 3-21 Video Packet Structure ……… 53

(11)

圖 3-23 Multithread……… 55 圖 3-24 Thread 物件的狀態圖……… 56 圖 3-25 thread 的集合 ……… 59 圖 3-26 thread 間之溝通……… 62 圖 4-1 sleep(0),CPU 之使用率 ……… 66 圖 4-2 sleep(10),CPU 之使用率 ……… 67 圖 4-3 暫存器內容 ……… 69 圖 4-4 順序和時間量測(a)(b)……… 70 圖 4-5 無檢查EOM 時的執行順序 ……… 75

(12)

表目錄

表格 2-1 擷取裝置資訊 ……… 4

表格 2-2 DataSource 物件 ……… 9

表格 2-3 BasicFilterModule 物件……… 12

表格 2-4 Picture Formats Supported……… 12

表格 2-5 影音格式取樣率 ……… 14

表格 2-6 Java Stream Socket API ... 23

表格 2-7 Java Datagram Socket API ……… 24

表格 4-1 thread Sleep 試驗 ……… 65

表格 4-2 暫存器內容 ……… 72

(13)

第一章序論

1.1 背景介紹

由於近年來,網路科技和硬體的技術不斷的改進,網路服務變的更多元化, 人們可以透過如PC、PDA、Smart Phone…等各式各樣的裝置,恣意地存取網路 上任何地方的資源。透過網路已不只可作文字與音樂欣賞或是影像資訊的瀏覽, 現而轉變成結合聲音、影像的互動式多媒體網路,這些多媒體資訊藉由多媒體串 流技術的新傳輸科技在網際網路上迅速擴張。 過去,用戶端要下載一部短片,通常都需要等待一段時間,直到完全下載完畢 後才能觀看。這會使用戶端花冗長的時間等待媒體資料的下載,是相當不方便 的。多媒體串流技術則提供了解決此問題的方案。多媒體串流技術是具有即時性 的傳輸技術,當用戶端要求下載媒體檔案時,會自伺服器端下載一小部分的媒體 資料,即可立即播放,除了可避免用戶端等待冗長的下載時間、節省硬碟空間, 同時可以提供傳輸live的影音資料和VOD(Video-on-Demand)的服務,也達到保 護影音檔案的版權。 串流技術大概可分成三類,第一類以HTTP/TCP為基礎,利用HTTP協定可 以讓串流媒體通過防火牆的阻礙,但因傳輸層所使用的為TCP通訊協定,因此, 當傳輸的資料遺失時會要求重傳時,容易造成延遲(delay)。第二類是利用一獨立 的串流伺服器,以RTP/UDP為傳輸的基礎,將多媒體資料送到使用者的播放器 上播放。RTP提供即時性的端對端傳輸服務,包括payload type identification、 sequence numbering…等,利用sequence number來進行封包重建,如此即可增 進即時傳輸的品質。第三類串流技術叫Clientless Streaming,其是在串流過程中 才將播放器送至用戶端,主要應用在行動裝置上,尤其是支援Java技術的平台。

目前多媒體的平台主流有Apple 主推的 Quick Time Server、Microsoft 的

Media Services 以及 RealNetworks.com 的 RealSystem。在上述的三大陣營中, Apple 推出 QuickTime for Java 的 API,使得 Apple iPod 逐漸開啟了移動視頻

(14)

的市場。 近幾年來Java 的版本不斷升級,並且釋出在各方面應用的套件,使得 Java 應用面很廣,如桌上型PC 的應用程式、PDA 應用軟體的開發…等。Java 語言 最大的好處就是在於可跨平臺、動態連結,及安全性的優勢,使其在網路電腦、 家用電腦和嵌入式的控制器等領域中,成為最受歡迎的程式語言。 雖然Java 的執行效能比 C/C++還要低了些,但近幾年 Java 加速器已逐漸 改善Java 的執行效能,以達到可以接受的水準。隨著網路的蓬勃發展,Java 作 業系統和各種Java 應用軟體所組成的 Java 網路資訊系統,在未來無線多媒體通 訊的網路世界中將佔重要的地位。

1.2 研究動機

近幾年來,Java蓬勃發展,其跨平台的特性以及優異的物件導向語法,Java 是非常適合用來發展系統、開發應用程式的語言。Java在多媒體串流上,有提供 相關的套件,如Java Media Framework(JMF)為Sun與IBM合力制定的一個開 放性與具可擴充性的多媒體處理API,其提供上層應用程式或Applet,是一種處

理多媒體串流的一致性介面。JMF提供大部份標準的媒體編碼影音格式,但未包

含MPEG4和H.264,但Apple推出QuickTime for Java的API 彌補JMF的不足, 使得Java在多媒體方面的支援更加強大。

由於以上種種因素,我們對於Java 在多媒體上的支援倍感興趣,Java 在多

媒體方面釋出以下幾種套件:Java Media Framework、Java 3D、Java 2D…等。

其中Java Media Framework(JMF)套件可以做得到的功能相當的多,如擷取影

音檔案、http 檔案下載和播放,也可以做到傳輸串流媒體,JMF 算是相當完整

的多媒體套件。藉此本論文將會探討JMF 對處理多媒體資料和即時傳輸所提供

(15)

第二章

Java 多媒體系統

2.1 系統架構

本論文利用JMF 所提供的 API 套件(請參考 2.4.1 節),探討一個 Java 多媒 體資料處理系統,此系統主要目的為傳送擷取的即時性影音媒體資料至遠方用戶 端,並且利用JMF 所提供的 RTP/RTCP 的套件(請參考 2.4.2 節),以串流的傳 輸形式將資料送至用戶端。 整體系統的運作是藉由 9 個 thread 在處理,其中包括擷取裝置管理、媒體 資料來源、影音來源之分流、影音壓縮處理、影音整合與 RTP 封包建立和傳送, 都會有專門的 thread 處理,在第三章會詳細說明。 以下為傳輸端的系統架構:

UI

transmit

DataSource(A/V) BasicSourceModule RawBufferParser BasicFilterModule Codec.open( ) BasicMuxModule RTPSyncBufferMux RTPSession RTPSinkStream

A

B

C

D

A: Get multimedia format of hardware support. B: Tell User &User choice media format.

C: Tell User what media format they can use to transmit streaming data & User choice media format.

D: User tell Program what information of client . information building System

System Architecture

1

2

3

4

Processor 圖 2-1 媒體資料處理系統 圖 2-1 中,藍色方塊是描述使用者介面(UI)的建構流程,其表示傳送端的系 統程式與本地端使用者之間的互動;建構子系統的同時必須向使用者取得建構子 系統所需的訊息。綠色的子系統方塊主要為處理媒體資料和傳送串流媒體至遠方

(16)

用戶端。圖 2-1 中,information:代表建立子系統時,所必須自 UI 取得的相關 資訊;同時建立UI 時,所需自子系統取得的相關資訊。building: UI 和子系統 方塊建立的流程。

2.2 使用者介面(UI)之建構流程

UI A B C D UI A B C D 圖 2-2 UI 建構流程

2.2.1 硬體支援之影音格式

圖 2-2,A 之方塊中,其主要為取得關於擷取裝置的資訊,相關資訊包括擷 取裝置的位置、支援哪些影音格式。JMF 套件有提供 query mechanism(請參考 2.4.1),以得知擷取裝置的資訊,因此必須執行 CaptureDeviceManager. getDeviceList( )函式,取得包含擷取裝置的相關資訊之物件:CaptureDeviceInfo (包含 VFWDeviceQuery)物件,CaptureDeviceInfo 物件內容主要為:裝置名稱、 裝置位置、此裝置所支援的格式、音訊的取樣率與影像的大小。 表格 2-1 舉出 CaptureDeviceInfo 的部分內容: 表格 2-1 擷取裝置資訊 音訊之相關資訊(CaptureDeviceInfo) 裝置名稱 (MediaLocator) DirectSoundCapture : dsound:// 音訊格式/ 取樣率

LINEAR, 48000.0 Hz, 16-bit, Stereo, LittleEndian, Signed

影像之相關資訊(VFWDeviceQuery) 裝置名稱

(MediaLocator)

(17)

影像格式 /影像大小

YUV Video Format: Size =java.awt.Dimension[width=160,heig ht=120], MaxDataLength = 28800

RGB, 160x120, Length=57600, 24-bit

當此階段無法取得CaptureDeviceInfo物件時,判定無可以使用的擷取裝置時,會 顯示"No capture devices found in JMF registry!"的對話視窗。

2.2.2 系統支援之影音格式

圖 2-2,B 之方塊中,其主要為建立一對話視窗,將系統有支援的影音格式 告知使用者(本地端),使用者可依其需求選擇影音格式、音訊取樣率與影像大 小。對話視窗顯示兩資訊:音訊和影像資訊。在音訊方面,必須呼叫 CaptureDeviceInfo.getFormat( )函式,取得一存有音訊格式型態的陣列,此陣 列包含擷取裝置所支援的輸出音訊格式目錄。將此目錄裡的資訊一一抽出,做為 建立音訊的訊息對話視窗,告知使用者可選用的音訊格式。 在影像方面,必須呼叫VFWDeviceQuery.getFormat( )函式,取得一存有影 像格式型態的陣列,此陣列包含擷取裝置所支援的輸出影像格式目錄。同樣將此 目錄裡的資訊一一抽出,做為建立影像的訊息對話視窗,告知使用者可選用的影 像格式。如下圖 2-3: 圖 2-3 裝置支援格式 當使用者完成選定影音格式的動作後,其相關資訊(圖 2-1 的虛線 1)會用來做 DataSource 物件的初始與建立(2.3.1 節會說明此物件的功能)。

2.2.3 影音編碼格式選項

由圖 2-1 中,經由使用者選定擷取裝置輸出的媒體格式,建立DataSource

(18)

物件,接著會選用適當的parser,同時建立 processor(以上流程在 2.3.2 節說 明)。當 parser 選定後,會依 parser 輸出的內容格式(content type)找出相對應

的多工器,此多工器的輸入影音格式會成為建立C 之方塊時所需的資訊(圖 2-1 的虛線 2)。圖 2-2,C 之方塊中,主要為告知使用者,影音編碼的傳輸格式(也 就是多工器的輸入影音格式)有哪一些,由使用者選定後,影音資料將來會壓縮 為使用者所選定的影音編碼格式(圖 2-1 的虛線 3)。 以下為取得影音編碼格式選項的程序: (1)找出 JMF 支援的多工器 執行pluginManager.getPlugInList (,,5)函式(請參考 2.4.1),取得所有確定 存在的多工器,總共有 10 個。如下圖 2-4: 圖 2-4 JMF 所支援的多工器 (2)建立 ContentDescriptor 物件

(19)

執行processor.getSupportedContentDescriptors( )函式(請參考 2.4.1 節),此函式會取得媒體資料格式。前面有提到,在此主要處理擷取裝置的影音 資料,因此此函式所取得的影音資料的內容型別(content type)為 raw,此時意 味著所取得的影音資料為未經過壓縮處理的媒體資料。利用前面所取的內容型別 加上".rtp",接著建立 ContentDescriptor 物件,其包含內容型別為"raw.rtp", 意謂著經處理後的媒體資訊是要送至網際網路。

(3)找尋適當的多工器

1.執行 processor.setContentDescriptor(contentDescriptor)函式,設定此時 processor 的輸出內容型別為"raw.rtp",此函式會詢問 PlugInManager,因此會

呼叫PlugInManager.getPlugInList(,contentDescriptor, 5)函式,詢問在所有多 工器中是否有內容型別為"raw.rtp"的多工器。以下為找尋適當多工器的過程: 將"raw.rtp"轉為某一整數。而所有的多工器會將它的輸出格式(含有各自的 內容型別)轉為整數,接著依序與"raw.rtp"所對應的整數做比對,直到找到多工 器的內容型別與此整數互相符合,在此所找到的多工器是 com.sun.media.Multiplexer.RTPSyncBufferMux,此多工器是負責處理要送至 網際網路上的媒體資料。 2.執行 RTPSyncBufferMux.setInputFormat(input[],TrackID)函式,input[ ]

為一陣列,其存放processor 的輸出媒體格式:codec 的列表;TrackID 為音訊或

影像的TrackID。此函式會將 RTPSyncBufferMux 所能提供的媒體輸入格式與 RTP Payload Type 作比對,互相符合的格式資訊會存入陣列中,接著利用所得 到的資訊建立影音編碼格式選項的對話視窗,如圖 2-5。 影音編碼格式選項的對話視窗,其告知傳輸端使用者下面資訊: 影像編碼格式選項:h263/rtp 和 jpeg/rtp。 音訊編碼格式選項: dvi/rtp、mpegaudio/rtp、ulaw/rtp、gsm/rtp、g723/rtp。

(20)

圖 2-5 顯示 Video 編碼格式

2.2.4 取得用戶端資訊

圖 2-2,D 之方塊中,其主要為建立一取得用戶端資訊的對話視窗。對話視 窗要求傳送端的使用者,輸入使用者所要傳送的目的地之IP 位址、port,當使 用者輸入資訊後,會執行使用者所輸入接收端的IP Address、Port 是否正確的 檢查程序,若有錯誤則會顯示通知使用者”有錯誤的”的對話視窗,並且對話視窗 不會再往下一頁跳,仍是在原先的視窗等待使用者重新輸入資訊。圖 2-1 中,我 們可知,使用者所輸入的資訊是將來要建立RTPSession 所需的資訊((圖 2-1 的 虛線 4))。

transmit

DataSource(A/V) BasicSourceModule RawBufferParser BasicFilterModule Codec.open( ) BasicMuxModule RTPSyncBufferMux RTPSession RTPSinkStream System Processor

1

2

3

4

2.3 子系統之建構流程

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

2.3.1 影音來源

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

(21)

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 的輸入的

(22)

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

圖 2-7 JMF 支援的 parsers

(2)建立 BasicSourceModule 物件。利用上述的 parser 和 DataSource 物件

以引數的形式,呼叫BasicSourceModule(DataSource, parser),建立

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

(23)

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.建立 多工器。

(24)

表格 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; h=288; } else if videosizewidth>=160 { w=174; h=144; }else { w=128; h=96; }

(25)

初始 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 DataSource Socket SendStream RTPTransmitter 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 DataSource Socket SendStream RTPTransmitter 圖2-8 RTPSession

(26)

即時的影音資料經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( )函式取得 此資料型態的取樣率。 舉例來說若format 為 H.263 的格式則得到的取樣率就為 90000HZ,表格 2-5 列舉在JMF 有支援的影音格式相對於取樣率的列表: 表格 2-5 影音格式取樣率 Payload type JMF 有支援的編碼 標準 支援 Audio 或 Video Clock Rate(Hz) 0 ULAW/RTP A 8000 3 GSM/RTP A 8000 4 G723/RTP A 8000 5 DVI/RTP A 8000

(27)

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 節。

2.4 Java Media FrameWork

Java Media FrameWork (JMF)提供一組能夠處理 time-base media data 的

多媒體套件,它提供了擷取、處理與傳送的統一建構方式。而time-base 提供的

資訊只有目前的時間,以system clock 為主。JMF 能提供大部份標準的媒體內

容型別(content type),例如:AIFF、AU、AVI、MPEG、WAV、QuickTime 和 WAV 等。

JMF 主要為兩大部份,第一部份為處理多媒體資料的相關套件,第二部份

(28)

2.4.1 JMF Architecture

JMF 提供兩種型態的 API(圖 2-9),一為高階 API: 提供擷取、處理與呈現 媒體資料的功能。另一種為低階API:提供設計者擴充元件的功能。 圖 2-9 JMF Architecture JMF 處理媒體的介面大致分為以下幾種: ¾ 時間模型(Time Model):串流媒體的媒體時間,其可表示為媒體播放的位置。 ¾ 管理者(Managers),主要有以下 4 種類別,其都置於 javax.media 套件內, 主要功能如下: z Manager:負責建立 Processor、DataSource。 z PackageManager:管理已註冊的套件,這些套件包含 JMF class,如 Players、Processors…等,這些元件也可為自行設計。存放 package-prefix 列表,將來 manager 會依照列表找出 time-based media 的協議處理者和內 容處理者.

z CaptureDeviceManager:使用一 registry 和 query 機制,找出擷取裝置

的位置,以及對於可使用的裝置回傳CaptureDeviceInfo 物件。

CaptureDeviceManager(位置於 javax.media 套件中)通常被使用來註冊 新的擷取裝置.。

(29)

Multiplexers、Demultiplexers、 Codecs、Effects、Renderers。 ¾ 資料模型(Data Model ) JMF 通常是使用 DataSource 來管理媒體內容的轉換、連結, DataSource 內會包含媒體的來源位置、媒體資料的格式與傳輸協定等。JMF 將DataSource 主要分為二種類型: z Push 和 Pull 資料來源: 此類型的DataSource 可根據資料傳送方式分為二類:

9 PullDataSource:接收端開始傳遞資料,並控制 pull data-sources

的資料流,使用的protocols 型態為 HTTP、FILE。JMF 定義二種

pull data sources 型態:PullDataSource、PullBufferDataSouce。

9 PushDataSource:傳送端開始傳遞資料,並控制 push data-sources

的資料流。使用的protocols 型態包括 RTP、multicast media、

VOD。JMF 定義二種 push data sources 型態:PushDataSource、 PushBufferDataSouce

一個標準的data source 是使用 byte 為傳送單位;一個 buffer data

source 是使用 buffer 為傳送單位。

z Data Format: JMF 描述音訊和影像格式的屬性,音訊格式如取樣

率,channel 的數量。影像格式如下圖 2-10。

(30)

JMF 提供許多處理媒體資料的套件,以下依 JMF 所提供的功能,分別加以 說明。

¾ Capturing

擷取裝置可以扮演媒體資料的來源,例如麥克風和攝影機。這些擷取裝置可

作為抽象的DataSource,如擷取裝置可傳遞具有時間性的媒體資料,此

DataSource 為 PushDataSource。擷取裝置可傳遞複合性資料串流(multiple data streams),其 DataSource 是複合性 SourceStreams,它會對應到裝置所提供的資料 串流。 要取得擷取裝置的相關資訊,必須透過CaptureDeviceManager,存取關於擷 取裝置的資訊,執行CaptureDeviceManager.getDeviceList( )函式可以得到所有 可利用的擷取裝置列表。CaptureDeviceInfo 物件描述每一個裝置,取得 CaptureDeviceInfo 物件,如下例: 要從裝置上擷取多媒體資料,必須由它的CaptureDeviceInfo 物件取得裝置的 MediaLocator 物件。 ¾ Processing Processors 可以用來播放媒體資料,除此之外,Processor 也可以使得自 DataSource 所輸出的媒體資料,由其它的 Player 和 Processor 來呈現,或是將 媒體資料傳送到其他的目的地,如網際網路。媒體資料處理分為幾個階段,如下 圖 2-11。

(31)

由圖 2-11,processing 元件都為 JMF plug-ins,JMF plug-ins 分別為以下 五種:

z Demultiplexing:分析輸入的媒體串流,如 WAV、MPEG 或

QuickTime,將其媒體資料流中個別的 track 抽取出來。

z Effect:對輸入或輸出的媒體資料流中,個別 track 做特效(effect)的演

算處理。 z Codec:解壓縮媒體資料,或者將未處理的媒體資料做壓縮處理。 z Multiplexer: 將多個 tracks 合併為單一個輸出資料流,並且做為輸出 的DataSource。 z Renderer:將媒體資料傳送至螢幕或喇叭。 以下三個函式執行結果為建立Processor,可以依程式設計者的需求分別執 行以下函式: Manager.createProcessor(DataSource source) Manager.createProcessor(MediaLocator sourceLocator) Manager.createProcessor (java.net.URL sourceURL)

媒體資料自輸入Processor,經過各個 processing 元件執行相關資料處理的程

序,在這之前必須先了解Processor 的狀態,如圖 2-12。

(32)

z Unrealized 狀態:剛建立 Processor,意謂著 Processor 與媒體來源並無關 聯。

z Configuring 狀態:此時正嘗試連接到 DataSource、 demultiplexes,並且

取得輸入的媒體資料格式。 z Configured 狀態:已經連結 DataSource,並且已經計算輸入的媒體資料格 式。 z Realizing 狀態:Processor 已計算處理資源(包括網路可下載的資源)的需 求,包括 rendering resource。 z Realized 狀態:此時 Processor 已完全建立。 Processor 的輸出可以作為 Player 的輸入,或是直接呈現媒體資料,在此並 不討論Player 與呈現媒體資料(圖 2-11),因此 Prefetching 狀態之後並不說明。

當Processor 在 Configured 狀態下,執行 getTrackControl( )函式,進而從

媒體串流中的track 得到 TrackControl 物件。這些 TrackControl 物件可以使我

們對media 做一些特別的處理,如選擇那一個(或那些)plug-ins,用來處理音訊

或影像track。可以使用 Processor 的 setContentDescriptor 函式,具體指定

Processor 媒體資料輸出的格式;呼叫 getSupportedContentDescriptors,而得 到媒體資料格式的列表。

2.4.2 JMF RTP Architecture

JMF可以傳送和接收RTP streams,主要是定義以下三種套件:

javax.media.rtp, javax.media.rtp.event, and javax.media.rtp.rtcp packages.影 音來源可為一般檔案或擷取裝置,將影音來源以串流的方式傳送至網際網路或者 儲存成一般檔案,如下圖2-13。

(33)

圖 2-13 RTP transmission 當接收一串流媒體時,同樣也可以將媒體直接播放或是儲存為一般檔案,如 下圖 2-14。 圖 2-14 RTP reception JMF 可以藉由標準 JMF plug-in 機制,延伸支援外加的 RTPformats 和 payloads,如下圖 2-15。 圖 2-15 JMF RTP architecture JMF的SessionManager物件用以協調RTP session,SessionManager借由觀 察本地端的成員,維護管理session的狀態,而SessionManager本身也是整個本 地端的RTP session代表,也操控RTCP control channel,並且對於sender和

(34)

receiver 都有支援RTCP。

在RTPsession,對於 RTP 資料封包所屬的每個 stream,RTPSession

Manager 必須管理一個 RTPStream 的物件。RTPStream 物件為描述在一個 RTP

sessions 內的 stream,有兩種形式的 RTPStream:ReceiveStream 和

SendStream,每個 RTPStream 都有一資料來源緩衝器與 RTPStream 相關。以

下主要有二種RTPstreams:

z ReceiveStream: 表示一個已接收的stream是從遠方的接收端傳送過來的。

z SendStream: 表示一串流資料是由 Processor所輸出(DataSource),而此串

流資料將經由網際網路傳送至遠方接收端。根據[5]。

2.5 Java Socket & Real-Time Transport Protocol

2.5.1 Java Socket

Java 語言初期便將支援網路視為必備的要素之一,其擷取 Berkeley Socket

的優點,並加入Java 跨平臺、物件導向、支援網際網路等考量之下,Java 一推

出關於支援網路的套件,則就包括有關於Socket API 套件:java.net。

Java 發展至今,其支援網路的 API 共有: ¾ java.net: networking applications。

¾ java.nio.channels.ServerSocketChannel:new I/O Server Socket Channel。

¾ java.nio.channels.SocketChannel: new I/O Client Socket Channel。

¾ javax.net.ssl: networking with Secure Socket Layer(SSL)。

¾ java.rmi: remote method invocation

¾ javax.rmi:remote method invocation for IIOP。

接著探討java.net 套件,其它套件請參考[2]。對 java.net 而言,其套件分

(35)

訊協定;(4)UDP 通訊協定;(5)網路認證(Authentication);(6)內容處理器 (Content Handler)。

(1)主機名稱和IP 位址:java 使用 java.net.InetAddress 類別來封裝「IP 位

址」(其中包括 IPv4 和 IPv6)的概念。當欲查詢某一主機的 IP 位址時,執行 InetAddress.getByName(主機名稱)函式,此函式會以 DNS 來查詢該主機的 IP 位址。

(2)Uniform Resource Locator:處理 URL 時,java 提供 java.net.URL 類別, 請參考[2]。

(3)TCP 通訊協定:在 java.net 套件中,其關於支援 Stream Socket 伺服端與

用戶端網路應用程式的相關API 和函式如表格 2-6。

表格 2-6 Java Stream Socket API

Java API 函式說明 java.net.ServerSocket 建立伺服端Socket 以及設定所使用 的IP 位址和通訊埠。 accept() 等候與接受自用戶端的連結請求,並 且建立與用戶端之連線。 read() 接收來自用戶端所傳送的資料。 write() 傳送資料至用戶端。 伺服端 close() 關閉Socket 及與用戶端之通訊連結。 java.net.Socket 建立用戶端Socket,並且嘗試建立與 伺服端之連結。 read() 接收來自伺服端所傳送的資料。 write() 傳送資料至伺服端。 用戶端 close() 關閉Socket 及與伺服端之通訊連結。

(36)

以下為伺服端與用戶端之架構圖(圖 2-16)

圖 2-16 伺服端與用戶端之架構

(4)UDP 通訊協定: 在 java.net 套件中,其關於支援 Datagram Socket 的相

關API 和函式如表格 2-7:

表格 2-7 Java Datagram Socket API

Java API 說明

DatagramSocket 建立Datagram Socket。

DatagramePacket 建立Datagrame Packet。

(DatagramSocket)receive() 接收Datagrame Packet。

(DatagramSocket)send() 傳送Datagrame Packet。

Close() 關閉Datagram Socket。

以下為Java Datagram Socket 的架構圖(圖 2-17)

(37)

TCP 協定是提供可靠的資料傳輸,但由於 TCP 協定的重傳機制使得它並不 適合用在即時影音應用。UDP 協定傳輸速度比 TCP 快,雖然 UDP 為不可靠的 傳輸協定,但封包丟失或次序錯亂對即時影音而言只會出現雜訊,因此對於即時

影音的傳送UDP 更適合 TCP。

Java 的 UDP 實作分別為兩各類別: DatagramePacket 和

DatagramSocket。DatagramePacket 類別為程式設計者將資料位元組填入 datagram 的 UDP 封包,並且也可自收到的 datagram 取出資料。DatagramSocket

兼具發送與接收UDP DatagramPacket 的能力。發送資料時,將資料填入

DatagramePacket,接著由 DatagramSocket 送出,反之亦然。

在UDP 中,與 datagram 有關的資訊都包在封包裡,而 socket 只需知道它

應該監聽當地主機的哪一各通訊埠,或是由哪一各通訊埠送出資料,根據[3]。 (5)網路認證(Authentication)、(6)內容處理器(Content Handler) 請參考 [2]。

2.5.2 Real-Time Transport Protocol

RTP 提供點對點的網路傳輸服務,適用於即時傳輸的資料,例如各種多媒 體資料的傳輸,這些多媒體資料將被包裝成特定格式的RTP 封包。RTP 架構在 UDP 的上層(如圖 2-18),將以包裝成特定格式的 RTP 封包傳遞給 UDP,然後 藉由UDP 等網路協定傳送到網際網路上。由於 RTP 對於網路的品質並沒有保 證,對此增加控制協定(RTCP),以達到監控網路的品質。 圖 2-18 RTP architecture

(38)

2.5.2.1 RTP 檔頭架構

RTP 封包包含一個檔頭以及在檔頭後面的負載資料,RTP 封包的檔頭格式

在RFC3550,根據[4],中有明確定義,而負載資料格式的切割方式,則根據負

載資料不同而有不同的定義,以下為介紹RTP 封包的檔頭資訊。

The RTP version number (V): 2bits,指出RTP的版本為何,在此RFC3550把此 值設定為2。

Padding (P): 1bits,指出封包的結尾有無padding data,padding data可以被用 於各種加密演算法。

Extension (X): 1 bit,指出延伸標頭是否存在,若存在則表除了 RTP 固定的檔 頭,還放了額外的檔頭資訊。

CSRC Count (CC): 4 bits,RTP packet 是由幾個來源所組成的。

Marker (M): 1 bit.指出此資料流的邊界,當設定為1時表此資料流已達邊界。 Payload Type (PT): 7 bits,是表示為一個索引,此索引指向多媒體設定檔的表, 指出payload data的格式。

Sequence Number: 16 bits,此數值指出此封包的位置,數值起始值是隨機產生, 隨著封包增加逐次加一。藉由這個數字,接收端可以偵測出遺失封包,以及將順 序錯誤的封包進行重新排列。 Timestamp: 32 bits,伺服端會根據取樣時間在每個封包上加上一個時間戳記, 使得接收端能得知何時必須處理此封包,當接收端接收的封包已逾時,則此封包 將被丟棄。 SSRC: 32 bits,辨別同步來源(Synchronization source),當此數值為零,表示此 payload就為其資料來源,若不為零則表其資料來源為mixer。 CSRC: 最多16項,每項32 bits,指出payload的來源。

(39)
(40)

第三章 Java多媒體系統動態分析

多媒體資料處理系統,必須由建立數個子系統方塊而組成。其所包括的子系 統如下,擷取裝置管理、媒體資料來源、影音來源之分流、影音壓縮處理、影音 整合與RTP封包建立和傳送(系統建立之細節請參考第二章)。 本論文依子系統的程式功能建立數個thread,如圖3-1。每個thread彼此間 會透過同步機制,互相溝通與合作,傳遞每個子系統所處理完成的媒體資料,並 將媒體資料包裝為RTP封包傳遞至接收端。 以下,會依序說明,各個thread的功能、thread的建構流程、thread之間是 以何種機制達成溝通與資料分享以及整個系統程式執行的細部運作。 圖3-1 Thread建立流程

3.1各個Thread的功能介紹

(1)Audio方面 RequestThread(A):執行開啟mike的程序,或是其它對mike的要求,如關

(41)

閉mike。 DirectSound PushThread(A):將mike所擷取的音訊資料放入子系統:「媒體資料 來源」的暫存器,接著將暫存器的音訊資料放入parser內的 暫存器。 SourceThread(A):將parser內的音訊資料取出,交由BasicFilterModule做資料壓 縮的處理,並且將完成壓縮的資料放入多工器內的暫存器。 RawBufferStreamThread(A):將多工器存的音訊資料交給RTPSession,建立RTP 封包,將封包交由接著由下層的UDP送出。 (2)Video方面 VFWRequestThread(V):執行開啟camera的程序,或是其它對camera的要求, 如關閉camera。 PushThread(V):將camera所擷取的影像資料放入子系統:「媒體資料來源」的暫 存器。 VFWTransferDataThread(V):將媒體資料來源的暫存器內所存的影像資料寫入 parser的暫存器。 SourceThread(V):將parser內的影像資料取出,交由BasicFilterModule做資料壓 縮的處理,並且將完成壓縮的資料放入多工器內的暫存器。 RawBufferStream Thread(V): 將多工器所存的影像資料交給RTPSession,建立

RTP封包,將封包交由接著由下層的UDP送出。

3.2 Threads建立的流程

由圖3-1Thread建立的流程,以下依序說明其建立流程以及thread所處理的 暫存器。

(42)

(1)1、2和3 thread的建立 程式Main thread開始執行,建立媒體資料來源,DataSource物件,此物件 會包函擷取裝置的路徑和管理影音來源的物件。接著呼叫DataSource物件的 connect( )函式,此時會分別建立RequestThread(A)、VFWRequestThread(V) 和DirectSoundPushThread (A)。 在建立RequestThread(A)之前,最主要必須為設置存放擷取資料的暫存器 大小,暫存器大小的設置與音訊來源有關,程序如下: 1.計算frameSize=取樣位元 X 通道數 / 8 2. 暫存器的大小=取樣率 X frameSize X 預設轉衝器長度(50) / 1000 以表格2-1音訊格式為例: 暫存器的大小=48000 X 4 X 50/1000=9600 (byte) 上例表示每一次擷取的資料量為9600 (byte)。 當建立RequestThread(A)時,RequestThread(A)會進入待命狀態,但由於 此thread設立了request旗標,其預設為0,唯有當request旗標大於0時,run( ) 函式裡,判斷式條件成立才能對mike改變狀態。但由於request旗標此時為0,因 此,此thread雖為待命狀態,只有當收到旗標狀態變更的通知,並且判斷式條件 成立,此thread才能對mike改變狀態。在此會先建立DirectSound PushThread(A),由於未呼叫start( )函式,此時為初始狀態。 VFW RequestThread(V)設立vfwRequest旗標,其預設為-1,唯有當 vfwRequest旗標大於或等於0時,此thread才會進入到執行狀態,但由於 vfwRequest旗標此時為-1,因此此thread會放出執行權,並且進入封鎖狀態,但 由於它呼叫為sleep( )函式,因此當設立的時間到時,它會再次醒來,但若還有 其它thread也在競爭執行權時,就可能超過預定的等待時間才醒來。醒來後同樣 會再次檢查vfwRequest旗標。在此設置此暫存器的大小是依影像大小而決定, 以表格2-1影像格式為例:每次擷取的資料量為28800(byte)。

(43)

(2)4和5thread的建立

Main thread呼叫realizeProcessor( )函式,會建立RealizeWorkThread物 件,此thread會進入執行狀態,執行以下程序:呼叫doRealize( )函式,當呼叫此 函式時,會建立BasicFilterModule物件(處理媒體資料壓縮)和呼叫connectMux( ) 函式,建立RTPSyncBufferMux物件(多工器),初始多工器的輸入端時,會建立 兩個RawBufferSourceStream物件,此物件是媒體(A/V)輸入資料存放的地方。 當 建 立 RawBufferSourceStream 物 件 的 同 時 , 會 依 序 建 立 RawBufferStreamThread(A)和RawBufferStreamThread(V),此兩個thread都會 進入初始狀態,直到Main thread建立了RTPSessionMgr物件和SendStream物件 (所存放的媒體資料將會封成RTP封包),執行SendStream.start( )函式時(請參考 2.3.4節),此兩個thread才會呼叫start()函式才會進入待命狀態,。 由於RealizeWorkThread的run( )函式並非迴圈,當上面程序都執行完成 後,此thread會進入結束狀態,此thread會佔用記憶體位置,Java提供自動回收 廢棄不用的記憶體(automatic garbage collection),也提供記憶體回收執行緒 (garbage-collector thread),會自動回收程式不再使用的記憶體。 (3)6、7、8和9 thread的建立 最後必須要求實際的媒體資料輸入,因此會建立PrefetchWorkThread,此 thread會進入執行狀態,接著呼叫doPrefetch( )函式,接著執行以下程 序:BasicSourceModule.doStart( ),其會呼叫RawBufferParser.start( )函式,接 著會呼叫PushBufferStream陣列內的VFWSourceStream.start( )函式與 DirectSoundStream.start( )函式。 當呼叫VFWSourceStream.start( )函式時,則會建立PushThread(V),此 thread會進入待命狀態,當thread取得執行權,進入執行狀態,開始執行時會先 睡0.01秒,醒來後會呼叫yield( )函式,此函式目的是要達到公平的排程。緊接 著會建立VFWTransferDataThread(V),此thread會進入執行狀態,會先檢查

(44)

bufferQ(在此bufferQ泛指儲存資料的暫存器)是否存有資料,若無資料,則會進 入鎖定狀態,等待0.25秒,醒來後一樣會再檢查bufferQ。建立上面兩個thread 的同時,會送出vfwRequest=1,改變VFW RequestThread(V)旗標的狀態,此 thread會開啟camera。 當呼叫DirectSoundStream.start( )函式,會先送出request旗標為3至 RequestThread(A),此thread則會開啟mike。接著會呼叫DirectSound PushThread(A).start(),此thread會進入待命狀態。 接著會依據有多少影音tracks而建立相同數目的SourceThread,在此會有 SourceThread(A)和SourceThread(V),並且都會進入等待狀態,當thread取得 執行權進入執行狀態,當檢查bufferQ為不可讀時,則此thread會進入封鎖狀態, 直到此thread收到解開封鎖的通告,此thread才會再進入執行狀態。 由於PrefetchWorkThread的run函式並非迴圈,當上面程序都執行完成後, 此thread會進入結束狀態。

3.3 Thread之間的資料分享與溝通

本論文所使用的排程機制為3.6.5節所提:自定排程,對各個thread用wait( ) 函式保留執行權。處理媒體資料的各個子系統,當各自要處理媒體資料時,都會 將媒體資料存在各自的暫存器,因此thread就必須做為每個暫存器之間的橋樑, 負責將媒體資料自暫存器讀出,或是將媒體資料放入暫存器。 子系統內的暫存器,其所扮演的角色就是thread能否執行的條件式,若 thread無法執行任務時,子系統內的暫存器就會扮演管理thread的角色,直到收 到此thread可執行條件成立的通告,就會解開對此thread的管理,而此thread就 會鎖住此暫存器,而執行資料讀出或放入的任務。 由上可知,本論文是利用子系統內的暫存器,做為每個thread互相制衡的機 制,同時每個子系統也必須各自完成,處理媒體的任務。以上Java thread的相

(45)

關知識請參考3.6節。

3.3.1 子系統介紹和Thread所屬之類別物件

(1) 子系統介紹

DirectSoundStream

擷取裝置(mike)管理

音訊資料來源

DirectSoundStream

擷取裝置(mike)管理

音訊資料來源

DirectSoundStream

擷取裝置(mike)管理

音訊資料來源

VFWSourceStream

擷取裝置(camera)管理

影像資料來源

VFWSourceStream

擷取裝置(camera)管理

影像資料來源

VFWSourceStream

擷取裝置(camera)管理

影像資料來源

(a) (b)

BasicSourceModule

RawBufferParser

影音來源之分流

BasicSourceModule

RawBufferParser

影音來源之分流

BasicFilterModule

影音壓縮處理

BasicFilterModule

影音壓縮處理

(c) (d)

RTPSinkStream

RTP封包建立和傳送

RTPSinkStream

RTP封包建立和傳送

BasicMuxModule

影音來源整合

BasicMuxModule

影音來源整合

(e) (f) 圖3-2(a)音訊擷取裝置管理、音訊資料來源;(b)影像擷取裝置管理、影像資料來 源;(c)影音來源之分流;(d)影音壓縮處理; (e)影音來源整合;(f) RTP封包建立和 傳送。 以上為各個子系統的實際物件,黑色實線之下方表示其物件的功能。 (2) Thread所屬之類別物件 在"3.6 Java thread"會提到,同一個類別可產生多個thread,圖3-3為介紹 每個thread是包含在哪些類別,並且說明子系統所擁有的暫存器內容。

(46)

(a) (b) (c) (d) 圖3-3 (a)音訊來源(b)影像來源(c)影音分流(d)多工器輸入來源 在3.2節,有說明每一次mike所抓取的資料大小,在DirectSoundStream物 件內會有一bufferQ物件的暫存器,且為FIFO的特性

此暫存器擁有一個queue, queue儲存大小與3.2節所計算的資料量大小相同。VFWSourceStream物件內會 有一bufferQ物件的暫存器,且為FIFO的特性

此暫存器擁有八個queue,每個 queue儲存大小與擷取的影像資料量有關,如表格2-1其大小為28800(byte)。 在RawBufferParser物件內的bufferQ物件的暫存器所擁有的queue的數量: 音訊方面為1,影像為1,兩者大小設置都與前者相同。BasicMuxModule物件內 的bufferQ物件的暫存器同樣具有FIFO的特性

,其

所擁有的queue的數量,影音 皆為5,每個queue儲存大小皆為1456(byte)。 媒 體 資 料 來 源 DataSource 物 件 會 包 含 DirectSoundStream 物 件 和 VFWSourceStream物件。VFWSourceStream物件會將擷取到的影像資料放入暫 存 器 中 , 其 過 程 為 VFWRequestThread(V) 負 責 管 理 camera , 當

(47)

VFWRequestThread (V)開啟camera,PushThread(V)將擷取的影像資料存入暫 存器中。VFWTransferDataThread(V)會將暫存器中的影像資料取出,接著放入 RawBufferParser物件的暫存器,在以上過程中,我們會發現暫存器是由後兩個 thread所共用的,因此當thread要放入或讀出資料時,都必須注意資料同步的問 題。

由上圖3-3,除了VFWSourceStream物件內包含數個thread,要注意資料 同步的問題之外,每個物件之間,資料的傳遞則是靠著thread之間的溝通,主要 是每個物件都有提供一個機制能讓thread成為等待區,此機制能夠幫助thread間 的通訊。

3.3.2

Thread的設計原理與制衡 依thread所處理的媒體資料特性,分別以處理音訊和影像資料的thread來加 以探討。Java虛擬機對作業系統來說,也是一支程式,Java虛擬機會自作業系統 取得執行權,接著將執行權分給各個thread使用。在此系統中,所有的thread的 run( )函式都是無窮迴圈,除非main thread完全結束,否則各個thread都會依排 程機制繼續執行。 在此,我們必須先了解一件事,在此的9個thread(包含處理影像和音訊)都 為無窮迴圈,每一個thread都是相同的優先度,在任何時間每個thread都是有權 利競爭執行權,除了處在封鎖狀態的thread是無法競爭。Thread會進入封鎖狀 態,是因未滿足某一條件,在此的條件只有兩種,可否放入資料:「判斷記錄暫 存器剩餘空間的參數值若為0,表示暫存器不允許放入資料」和可否讀出資料: 「判斷紀錄暫存器資料量的參數值若為0,表示暫存器不允許讀出資料」。

3.3.2.1 處理影像資料

此小節說明處理影像Thread 的設計原理與制衡機制。在圖 3-4 中,處理影

(48)

像資料的 threads 會執行各自的任務,所有箭頭的起始點和終點表示為各個 thread 所必須要處理的物件,以及物件內的暫存器,其中 bufferQ1 有 8 個 queue,bufferQ2 有 1 個 queue,前兩者的 queue 都為儲存一張照片的大小。 bufferQ3 有 5 個 queue,每個 queue 都為儲存一預設 RTP 封包的大小。

Thread0:VFW RequestThread(V) Thread1:PushThread (V)

Thread2:VFW TransferDataThread (V) Thread3:SourceThread(V)

Thread4:RawBufferStream Thread(V) Object Thread Path

buffer RTPSinkStream buffer2 BasicMuxModule bufferQ3 BasicSourceModule RawBufferParser buffer1 bufferQ2 VFWSourceStream bufferQ1 Manage camera

0

1

2

3 4 圖 3-4 Thread Path(V) (1) Thread 的設計原理 以下會針對每一個thread 的設計概念做說明,當有對 bufferQ1、bufferQ2 或bufferQ3 作處理時,都會啟動同步機制,此 3 個物件會宣告為 synchronized(請 參考 3.6.3~3.6.6 節)。

Thread0:負責管理 camera,如開啟 camera。除非有其它 thread 要求它改變狀

態,否則當它取得執行權時,並不會做任何程序就會再度回到待命狀態。

Thread1:負責從 camera 取得影像資料,並存入 bufferQ1。

由於擷取影像資料的時間點不能太近,並且希望盡量達到公平的排程,因此

使用sleep(time)函式,使得 Thread1 休眠數豪秒後再起來執行,並且使用 yield()

函式,若Thread1 此次已執行過,下一次的執行機會能讓給其它的 thread,以

(49)

接著必須檢查bufferQ1可否放入資料,當無法放入資料時,表示已有8張照 片未處理,因此會清除在bufferQ1內最早放入的照片。接著將擷取的影像資料放 入一暫存器buffer,再將buffer內的資料放入bufferQ1,此時會執行bufferQ1. notifyAll()函式,此函式主要為通知Thread2隨時可取走資料,接著將記錄buffer 資料量的參數設為0(接下說明相同的程序時都稱之為「清空暫存器」),為下一 次的影像資料做準備。以上流程如圖3-5。 圖3-5 PushThread(V) Thread2:負責將bufferQ1內的資料搬運至bufferQ2。 首先必須要確定兩件事:1.Thread2可以取得影像資料,因此會檢查bufferQ1 可否讀出資料,若無法取得影像資料Thread2就會在此等待影像資料。當確定可 以取得影像資料時,必須確定另一件事:2.Thread2可否將資料放入bufferQ2,因 此會檢查bufferQ2可否放入資料,當判定無法放入資料時,Thread2會在此等待 Thread3將bufferQ2內的資料取走。 當上述兩件事都成立時,才會開始執行真正資料搬運的動作。首先,會先宣 告一暫存器buffer,將bufferQ1內的資料放入buffer,並且清空bufferQ1所存放

(50)

此資料的queue。接著再將buffer內的資料放入bufferQ2,並執行bufferQ2. notifyAll()函式,通知Thread3隨時可取走資料。以上流程如圖3-6。 圖3-6 VFWTransferDataThread(V) Thread3:負責自bufferQ2讀出資料後,對取出的資料做壓縮的處理,同時切割 為數個封包,並且依序放入bufferQ3。 首先必須確定Thread3能否取得影像資料,因此檢查bufferQ2可否讀出資 料,當無法自bufferQ2讀出資料時,Thread3會等待Thread2將影像資料放入 bufferQ2。 當Thread3可以自bufferQ2讀取資料時,宣告一暫存器buffer1,將bufferQ2 的資料放入buffer1,接著清空bufferQ2並通知Thread2隨時可放入新的影像資 料。將資料暫時存入buffer1是為了要對資料壓縮的處理做準備,當buffer1的資 料壓縮好並切割為封包大小後放入buffer1`,接著buffer1`所存的封包必須要逐 一放入bufferQ3。 因此必須檢查bufferQ3可否放入資料,當無法放入資料時,Thread3會等待 Thread4取出bufferQ3內的封包。當Thread3可以將封包放入bufferQ3時,會宣 告一暫存器buffer,接著將buffer1`內的封包放入buffer,再將buffer內的封包逐

(51)

一放入bufferQ3,並且告知Thread4隨時可將封包取出。 最後Thread3會檢查自buffer送出的封包是不是為最後一個封包,若是最後 一個封包,則Thread3會等待一段時間,此做法是希望再壓縮下一張照片前, Thread4已將此次照片相關的封包都發送自網際網路,當Thread4發送出最後一 個封包時就會通知Thread3可以壓縮下一張照片。以上流程如圖3-7。 圖3-7 SourceThread(V) Thread4:負責將bufferQ3內的封包一一讀出,建構為RTP封包,並交給Socket 發送。 首先Thread4必須確定是否有封包要發送,因此必須檢查bufferQ3可否讀出 資料,若判定無法讀出資料,Thread4則會等待Thread3將封包放入bufferQ3。 當Thread4可以自bufferQ3讀出封包時,宣告一暫存器buffer,接將bufferQ3內 的封包放入buffer,接著檢查buffer內所存的是不是為最後一個封包,若是最後 一個封包,Thread4會通知Thread3可以壓縮下一張照片。最後清空bufferQ3內 存放此次封包的queue。以上流程如圖3-8。

(52)

圖3-8 RawBufferStreamThread(V) (2) Thread制衡機制

由上述各個thread 的執行概念,下圖 3-9 為暫存器可能管理的 thread 之整

理。bufferQ1 可能管理 VFWTransferDataThread(V),藉由封鎖時間的結束, VFWTransferDataThread(V) 可 自 動 解 開 bufferQ1 的 封 鎖 , 或 是 由 PushThread(V) 將 資 料 放 入 bufferQ1 時 , 通 知 bufferQ1 解 除 VFWTransferDataThread(V) 的 封 鎖 , VFWTransferDataThread(V) 隨 時 可 自 bufferQ1 讀取資料。

bufferQ2 可能管理 VFWTransferDataThread(V)或 SourceThead(V),也意

味著此兩個thread 同時是藉由 bufferQ2 來溝通。當 VFWTransferDataThread(V)

無法將資料放入bufferQ2 時,此 thread 會被 bufferQ2 封鎖,直到 SourceThead(V)

通 知 bufferQ2 解 除 對 VFWTransferDataThread(V) 的 封 鎖 時 ,

VFWTransferDataThread(V)就會得知可以將資料放入 bufferQ2 的通知。反之 亦然。

bufferQ3 可能管理 SourceThead(V)或 RawBufferStreamThread(V) ,也意

味著此兩個 thread 同時是藉由 bufferQ3 來溝通。當 SourceThead(V)無法將資

(53)

RawBufferStreamThread(V)通知 bufferQ3 解除對 SourceThead(V)的封鎖時, SourceThead(V)就會得知可以將資料放入 bufferQ2 的通知。

當RawBufferStreamThread(V)無法自 bufferQ3 取得封包時,會被 bufferQ3

鎖住,此thread 可藉由封鎖時間結束而自動結束封鎖,或是 SourceThead(V)

將封包放入bufferQ3 時,會通知 bufferQ3 解除對 RawBufferStreamThread(V)

的封鎖。

圖 3-9 buffer manage(V)

由Thread 的設計原理可知 SourceThead(V)和 RawBufferStreamThread(V)

之間還外加有一控制機制。當SourceThead(V)壓縮並送出最後一個封包時,必 須進入封鎖狀態,等待RawBufferStreamThread(V)將 bufferQ3 內的最後一個 封包發送出去時,SourceThead(V)就會解開封鎖繼續壓縮下一張照片。如圖 3-9 的右下方。 (3)暫存器狀態判斷機制 由前,對於Thread間的制衡機制的介紹,可知必須要有相關機制加以判斷 暫存器是否可以被放入或是讀取資料。當要判斷可否自暫存器讀出資料時,呼叫 canRead( )函式,此函式會檢查記錄暫存器資料量的參數是否大於零,當大於零 時,會回傳一true的布林值,表示此暫存器內存有資料。當要判斷可否放入資料

(54)

時,呼叫canWrite( )函式,此函式會檢查記錄暫存器剩餘空間的參數值是否為 零,當大於零時,會回傳一true的布林值,表暫存器還可放入新資料。

3.3.2.2 處理音訊資料

RTPSinkStream buffer2 BasicMuxModule bufferQ3 BasicSourceModule RawBufferParser buffer1 bufferQ2 DirectSoundStream bufferQ1 Manage mike Thread1:RequestThread(A) Thread2:DirectSound PushThread (A) Thread3:SourceThread(A) Thread4:RawBufferStream Thread(A) Object buffer Thread Path 1 2 3 此小節說明處理音訊Thread 的設計原理與制衡機制。在圖 3-9 中,處理音 訊資料的 threads 會執行各自的任務,所有箭頭的起始點和終點表示為各個 thread 所必須要處理的物件,以及物件內的暫存器,其中 bufferQ1 有 1queue, bufferQ2 有 1queue。bufferQ3 有 5 個 queue,每個 queue 都為儲存一預設 RTP 封包的大小。 4 圖3-10 Thread Path(A) (1) Thread 的設計原理 以下會針對每一個thread 的設計概念做說明,當有對 bufferQ1、bufferQ2 或bufferQ3 作處理時,都會啟動同步機制,此 3 個物件會宣告為 synchronized(請 參考 3.6.3~3.6.6 節)。由於在影像處理時有說明 Thread3 和 Thread4,因此不 再說明此兩個 thread。

Thread1:為負責開啟 mike,除非有其它 thread 要求它改變狀態,否則當它取

得執行權時,並不會做任何程序就會再度回到待命狀態。

(55)

資料放入bufferQ2。

由圖 3-10 中,Thread2 要將擷取的音訊資料放入 bufferQ1 時,會宣告 bufferQ1 為 synchronized 接著取得 bufferQ1 的 token,並且檢查 bufferQ1 可

否放入資料,當無法放入資料時會將記錄bufferQ1 資料量的參數設為 0(接下說

明相同的程序時都稱之為「清空暫存器」)。接著會將音訊資料放入bufferQ1。

接著必須先確定bufferQ2 允許放入資料,Thread2 才會執行搬運資料的動

作。因此必須檢查bufferQ2 可否放入資料,當無法放入資料時必須等待 Thread3

取出bufferQ2 內的資料,所以必須執行 bufferQ2.wait()函式,Thread2 會進入

封鎖狀態直到Thread3 通知 Thread2 可放入資料時,所執行的 bufferQ2.

notifyAll()函式來解除 Thread2 的封鎖狀態。

當確定可以將資料放入bufferQ2 時,會宣告一 buffer 的暫存器,做為自

bufferQ1 傳遞資料至 bufferQ2 的仲介。當 bufferQ1 的資料放入 buffer 內時,

接著會執行清空bufferQ1,最後將 buffer 內的資料放入 bufferQ2。以上流程如

圖 3-11。

圖 3-11 DirectSoundPushThread(A) (2) Thread制衡機制

數據

圖 2-5    顯示 Video 編碼格式  2.2.4 取得用戶端資訊  圖 2-2,D 之方塊中,其主要為建立一取得用戶端資訊的對話視窗。對話視 窗要求傳送端的使用者,輸入使用者所要傳送的目的地之 IP 位址、port,當使 用者輸入資訊後,會執行使用者所輸入接收端的 IP Address、Port 是否正確的 檢查程序,若有錯誤則會顯示通知使用者”有錯誤的”的對話視窗,並且對話視窗 不會再往下一頁跳,仍是在原先的視窗等待使用者重新輸入資訊。圖 2-1 中,我 們可知,使用者所輸入的資訊是將來要建立
圖 2-7 JMF 支援的 parsers
圖 2-11 Process stages
圖 2-12 Processor states
+7

參考文獻

相關文件

„ 移動滑鼠游標到縮圖上, 移動滑鼠游標到縮圖上, ACDSee會自動顯示放大 ACDSee 會自動顯示放大 的縮圖

首先,在套裝程式軟體 Matlab 中執行 k-means 分群法,將前置樣本中的 學測成績分成三群或四群。特別注意的是,在執行 k-means

• 人所看見的顏色 ,

Multimedia Technology Applications 授課老師: 羅崇銘.. 時間: Thursday

„ „ 利用電腦來安排與整合多種媒體,可產生 利用電腦來 更多樣化的作品。如某一段背景配樂在影 片中的哪個時間點開始播放、新聞播報中 子母畫面的相對位置、文字字幕出現在畫

 電腦鍵盤已經代替了筆,能夠快速打出一長串文字 ,大 多數人不會再選擇去「握筆寫字」,甚至有人都要 漸漸忘記文字

Whatsapp、Youtube、虛擬實境等)。社交媒體(social media)是可

 將建議行車路線、車輛狀態等 資訊投影於擋風玻璃 ,創造猶如科 幻電影一般的虛擬檔風玻璃系統所整合。在以液晶螢幕彌補視覺死角