=專題=
Multicast
& RTP 即時影音傳輸
目錄:
-前言
-Framework
-Microsoft Direct
Show
-Filter與Filter Graph
-使用DirectShow
-DS整體架構
-DS的彈性
-COM (Component
Object Model)
-Multicast
-RTP/RTCP
-多媒體檔案格式
-系統初步架構
-系統最後架構
-系統架構圖-- DirectShow Filter
-傳送端Screen Shot
-接收端Screen Shot
-後記
-參考資料
-投影片和程式碼下載
◆ 前言
此專題的目的是將遠端CCD與MIC取得的影像與聲音,壓縮成MPEG4
(Divx)格式,以RTP透過Multicast的方式,即時傳給多台電腦,實作平台都是WIN32 PC,最終目標是讓接收端不限於WIN32 PC,比如是WinCE
PDA、Linux PDA等等,目前的平台著重於WIN32 PC。
整個專題的成員總共有五人,工作分成三大部分,分別是RTP小組、多媒體檔案格式小組、Microsoft
DirectShow小組,而我們小組主要負責的部分是Microsoft DirectShow部分,雖說工作是如此分的,在許多方面仍須去研究並了解,否則實作出的程式模組是無法結合的。
◆ Framework
◆ Microsoft Direct Show
撥放端與傳送端影音擷取技術主要是採Microsoft Direct Show達成,
Microsoft Direct Show包含在Microsoft DirectX之中,要開發程式之前首先要去微軟官方網站下載DirectX SDK (目前是採8.0a),整個SDK中包含許多說明文件與程式範例,大部分的技術支援都是從此取得的。
Direct Show(後簡稱DS)整個是以Microsoft
COM原件完成,DS可以說是數個COM原件組成,使用DS就是於程式中產生所需的COM原件,並對元件呼叫所需的開放介面,以下開始介紹DS的細節部分。
◆ Filter與Filter Graph
Preview
在DS中最基礎的單位稱為Filter,每一個Filter代表對多媒體資料進行一個處理步驟,在DS中有三種型態的Filter,分別為Source
Filter、Transform Filter、Render Filter。
Filters
Source Filter主要的工作是讀取Raw
Data ; Transform Filter主要工作是取得Source Filter的Raw Data並加工處理(通常扮演Decoder角色),Render
Filter主要工作是取得Transform Filter處理的Raw Data並輸出到適當的裝置(比如寫入檔案、輸出影音設備等等),其關係圖如下圖所示:
![]()


Filter Graph & Filter Graph
Manager
由此三種Filter間組成的圖稱為Filter Graph,就如上流程圖一樣,而在DS中主要掌管控制Filter Graph的COM
Component為Filter Graph Manager。
Filter component
各個Filter在DS中是以COM實作,因此我們使用DS就相當於在程式產生符合需要的Filter Component,其後將Filter組成一個Filter
Graph,最後控制Media Stream的流向就算大公告成,比方如下的範例(撥放AVI的Filter Graph):

Summary
透過Filter Graph我們可以清楚了解到多媒體資料是如何被處理的。Filter的架構讓應用程式對多媒體處理能力很有彈性,程式設計師像是在拼裝Graph,拼出一個符合我們多媒體需求的Filter
Graph。
◆ 使用DirectShow
使用DS的步驟在此更詳細的說明一遍:
STEP1
由於我們會使用到COM,因此一開始我們必須先呼叫Windows初始化COM
Library的API,然後產生一個Filter Graph Manager Component。
STEP2
再來我們就要產生完整Filter
Graph,而產生的方法分為兩種,一種是自動產生符合多媒體的Filter Graph(由Filter Graph Manager來做這項工作),另一種是我們手動產生個個需要的Filter
Component並將圖給建立起來給Filter Graph Manager管理。
STEP3
最後的步驟就是控制Media
Stream的動作,此時需要一個Media Control Component來作管理,其中控制了Media Stream的Stop、Pause、Start動作。還有Media
Stream可能會產生些事件(如撥放完畢),這時我們可以產生一個Media Event Component來作管理事件的動作。
◆ DS整體架構
下圖是來自DS SDK Document,在此我們可以更了解DS的內部架構。虛線方塊部分就是我們程式所能控制的部分,也是上上幾篇介紹的部分。

◆ DS的彈性
DS本身附上許多Filter,但也有可能會發生找不到合適的Filter來完成我們的專案,要是發生這種情況我們就得去寫出一個Filter出來,而寫出一個Filter所涉及的背景知識蠻多的,在此次專題就碰到這個頭痛的問題。基本上DS本身已經附上一些Base
Class,繼承這些Base Class並Over Ride一些方法就會使的這個開發過程容易些。
◆ COM(Component
Object Model)
使用DS只需知如何使用COM(Filter全為COM原件),但如果需要開發Filter就必須去了解COM,並知道如何實作COM原件,否則就不能繼續下去,在此簡略說明一下Microsoft
COM。
COM
COM並不是一種程式語言,也不是特定的函式庫,COM是一種規格定義,COM規定了製作具有動態替換能力元件的方法,也定義了用戶端程式與元件之間共同合作的標準。使用COM讓程式變成是像由原件組成,程式設計師設計可以重複的使用原件,日後要是軟體更新只要將須汰換的原件更新,不用大幅修改程式,讓日後軟體維護的工作更容易,減少軟體成本。
就如下圖所示:
Application

![]()
原本單一獨立的程式變成由許多原件組成,而原件也能在執行階段動態更換,或許有些人會想這不就是把程式分成幾個模組,但是在COM中A、B、C、D、E是一個可執行二進碼(完整的程式,通常是DLL),而不是structure
paradigm的程式寫作風格,而各元件都是透過介面來溝通,程式可以在執行階段更換原件。
COM Component
COM Component是Win32動態連結程式庫或可執行檔存在的可執行程式碼,以COM規格標準所寫出來的元件,我們就稱為COM
Component。
Summary
在DS中所有的Filter都是以COM存在,在此我們已經可以看到COM的一些好處,就是庸有高度的彈性。微軟的許多技術都是以COM完成,如OLE、ActiveX都是建構在COM上面,COM的目的是達成軟體IC理想。
◆ Multicast
Preview
在網路中的傳送模式可以分為三種,Unicast、Broadcast、Multicast
,Unicast屬於一對一的傳送方式 ,Broadcast是對整體網路做傳送,Multicast是對整體網路的特定幾台(Multicast Group)做傳送,Multicast的實作也可以靠Unicast或Broadcast實作出來,但是這種模擬方式會非常浪費網路資源。
Multicast常應用於多媒體方面(如VOD),而此次的多媒體傳送是以Multicast來傳送,讓加入同Multicast
Group的電腦可以接收遠端多媒體。
Mbone(Multicast Backbone)
若要各網域能收送全球性的multicast封包,就需要其router或其它硬體也要能支援multicast封包的轉送動作,但若其網域只支援unicast方式的傳送,這時候若使用多址傳輸骨幹網路(Multicast
Backbone, MBone),則我們可以藉此達到網路多址傳輸的目的。現在世界上已經許許多多的MBone網路。因此Mbone引入了通道(Tunnel)的概念。事實上,Mbone是一個虛擬的網路骨幹,Mbone藉由通道將一個個的多址傳輸的網路(Multicast
Island)連起來
Multicast Group Address
Multicast Group Address定在Class D IP,如下圖:

Ipv6的格式,如下圖:
◆ RTP/RTCP
Preview
RTP針對需要傳送即時資料的application,像是影像,聲音,模擬資料…等,提供了在multicast或unicast上,點對點的傳輸功能。
RTP沒有保留資源的能力,亦不保證即時服務的OoS。但RTP可與另一控制協定(即RTCP)結合,來監測資料傳輸的狀況,以及增加一些控制與識別的功能。
Application一般都在UDP之上跑RTP,這兩者都提供了部分的傳輸功能﹔然而,RTP也可以與其他適合的下層protocol一起運作。
在傳統的protocol中,若要增加新的功能,只有將protocol改得更一般化,或是加入一個需要分析的選項機制。不同於此的是,RTP只要修改或者增加header就可以達到目的。
現今的Internet環境,並無法完全滿足即時服務的要求。使用RTP的寬頻服務,像是影像,可能會影響其它網路服務的QoS。因此,程式設計者必須採取一些措施,限制次要的服務利用頻寬。
一家公司的成員們想藉由multicast傳達聲音的方式,進行一場線上會議。會議的主席透過某種配置的機制,獲得了一個multicast address,以及一對port,其中一個port是為了RTP(傳送聲音),另一個則是為了RTCP(傳送控制packet)。這些位置與port的資訊會分布給所有想加入會議的公司成員。
使用聲音會議程式的公司成員,可送出一小塊的聲音資料,每一小塊資料前會被加上RTP的header。RTP header會指出每一個packet所包含的資料是用什麼壓縮方式,像是PCM, ADPCM, LPC…等。在會議的過程之中,傳送聲音資料的公司成員,可以改變聲音的壓縮方式,以配合經由窄頻連接到Internet的的新加入者,或是對網路壅塞做出反應。
如同其它packet網路一般,Internet偶而也會遺失packet,或是將packet的順序用亂。為了處理這些損害,RTP header會包含時間的資訊,以及一個sequence number。如此一來,所有加入會議的成員就可以依此來重組收到的packet,甚至估計有多少packet遺失。
因為在會議的過程之中,公司成員們可能會加入或離開會議,所以知道某人在何時加入,還有他接收資料的狀況,會是很有用的。為了達到這個目的,每一個會議上的application,都會在RTCP的port上,定期群播包含使用者名稱的reception report。Reception report會指出傳送聲音資料的成員,被接收的程度如何,也可以用來控制適合的聲音壓縮方式。當然,除了使用者名稱,其它辨識資訊可視控制頻寬的限制,被加入reception report。當某人想離開此一會議,application將送出RTP BYE packet。
如果聲音與影像都被使用在會議中,application將使用兩個UDP port pair,以及(或著)兩個multicast address,分別來傳送聲音與影像的RTP和RTCP。然而RTP並沒有方法直接將聲音與影像的session做結合,除非participant在聲音與影像的RTCP packet中,都使用相同的CNAME。
將聲音與影像以不同的session來傳送,其中一個原因是,允許加入會議的人,只選擇接收其中一種媒體。
雖然聲音與影像的session是分開的,但是同步化仍然可以藉著RTCP packet中的時間資訊來達到。
在之前的兩個情況中,我們假設所有的participant都能接收相同format的媒體資料。然而,這卻不是完全正確的。
想像某一區域的人是透過低速線路連接到Internet,而其它區域的人則是透過高速線路連接到Internet。與其強迫所有人都使用較少的頻寬,RTP寧可在靠近第速網路之處,放置一個名為mixer的機制。
Mixer會先將收到的packet作同步化以重組packet,然後將這些重組過的packet混和到單一的資料流,最後再將壓縮方式改為適合低速網路的format,並透過低速線路將新format的packet傳送給低速網路中的participant。
在RTP的header中,會有一種方法可以讓mixer辨識每一個混和過的packet的傳送者,如此一來,receiver就可以知道packet是由誰發出來的。
如果有些participant是透過高速線路連接到Internet,可是不支援IP Multicast,像是被Firewall與Internet隔絕,因為Firewall外的packet都無法進入Firewall內部。在這種情況下,RTP將使用一個名為Translator的機制。
Translator的機制是安置兩個Translator,一個在Firewall外部,一個在Firewall內部。外部的Translator傳送multicast packet,內部的Translator則透過安全的管道收到這些multicast,之後內部的Translator再將這些multicast packet轉送給Firewall內的participant。
在一個影像會議中,mixer可以把每個人的影像分成若干等份,然後將它們合成放到單一個資料流,來模擬群體的景象。
如果在一個遠距會議中,有兩群人分別使用不同的底層protocol,例如一群人使用IP/UDP,另一群人使用ST-II。或是影像的壓縮方式是一個packet接著一個packet,而不需重組或混和。此時,Translator也可派上用場。
RTP packet: 一個開頭有RTP header的packet,即為RTP packet。通常在底層protocol中,一個packet只包含一個RTP packet,但透過一些特別的encapsulation方法,底層packet也可以包含一個以上的RTP packet。
RTP payload: 在RTP packet中,真正要傳送的資料,即為RTP payload。例如在影像會議中,影像資料就是RTP payload。
RTCP packet: 一個開頭是RTCP header,後面接著控制資料的packet,即為RTCP packet。通常許多RTCP packet會被結合,再加上底層的header,而結合後的RTCP packet長度會被紀錄在RTCP header中的length欄位。
Port: 當RTP想傳送RTP packet與RTCP packet到同一個IP Address時,port就可以用來區分目的地的不同。
Transport address: 一般都是IP Address加上UDP port。packet都是從一個source transport address傳到一個destination transport address。
RTP session: 對於每一個RTP使用者而言,RTP session是由一對destination transport address定義而成(一個為了RTP,另一個為了RTCP)。要注意的是,一個多媒體會議中,不同的媒體資料最好在不同的RTP session中傳送。
Synchronization source
(SSRC): SSRC是一個隨機選取的識別值,用意是使一個RTP session中的participant都有獨一無二的識別資訊。但是同一個使用者在不同的RTP session中,並不一定要用同一個SSRC。
Contributing source
(CSRC): 之前提過mixer可以將不同來源的RTP packet混和放到同一個RTP packet中。此時,RTP也會在RTP header中紀錄與這個packet有關的SSRC,而這些SSRC合起來就叫做CSRC。
End system: 如果一個application可以產生內容被包在RTP packet中被傳送,或是可以讀取RTP packet中的內容,就可以被稱為End system。
Monitor: 如果一個application可以接收在一個RTP session中所有participant送來的RTCP packet,就可以被稱為Monitor。Monitor可以被內建在End system中﹔也可以不直接參與RTP session,這種Monitor被稱為Third Party Monitor。
|
0 |
1 |
2 |
3 |
||||||||||||||||||||||||||||
|
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
0 |
1 |
|
V=2 |
P |
X |
CC |
M |
PT |
Sequence number |
|
Timestamp |
||||||
|
Synchronization
source (SSRC) identifier |
||||||
|
Contributing
source (CSRC) identifier …… |
||||||
Version (V): 說明RTP的版本。
Padding (P): 如果這個欄位被設定,RTP packet尾端將會包含一個以上的padding octets,但它們並不是RTP payload的一部份,而在padding的最後一個octet會記錄在這個RTP packet中有多少個octet。在某些壓縮演算法,或是底層的通訊協定,padding有可能會被用到。
Extension (X): 如果這個欄位被設定,在固定的RTP header後還要加上一個 header extension。
CSRC count (CC): 紀錄CSRC的個數。
Marker (M): 用作重要事件,像是影像中frame的界限識別值。這個值的解釋是留給application去處理。
Payload type (PT): 用來定義RTP payload的format,而format的解釋則是留給application去處理。
Sequence number: 每送出一個RTP packet之後,sequence number就會增加一。Sequence number也可以被receiver用來偵測packet loss,以及恢復packet的順序。
Timestamp: 用來記錄RTP packet第一個octet被讀取的取樣時間。
SSRC: 如同前面的定義。要注意的是,如果一個source改變它的source transport address,它必須選擇一個新的SSRC。
CSRC list: 如同前面的定義。要注意的是,如果一個RTP packet包含15個以上的CSRC,只有15個CSRC可以被識別。
前十二個octet一定會出現在每個RTP packet﹔但CSRC list只有packet經過mixer才會被填入。
要先說明的是,如果一個protocol想有效率的運作,multiplexing的點應該盡量減少。
在RTP中,multiplexing是藉由destination transport address來完成。例如一個包含影像與聲音的遠距會議,聲音與影像將在不同的RTP session中被傳送。基本上,RTP並不希望影像與聲音等不同的資料在同一個RTP session中被傳送,然後再根據payload type或SSRC來demultiplex。
在同一個RTP session中使用同一個SSRC會造成以下五個問題﹔至於在同一個RTP session中使用不同的SSRC,將可避免前三個問題,但仍會遇到後兩個問題:
如果在session運作的過程中,有payload type的改變,將沒有方法知道是哪一個舊的payload type被取代。
可能需要不同的計時方式,以及sequence number空間。
不論是RTCP sender report或是RTCP receive report,當針對同一個SSRC,都只能描述一個計時方式,以及一個sequence number空間。而且,沒有payload type欄位。
RTP mixer沒有辦法結合不相容的media。
如果receiver只想接收RTP session其中一種media,將是不可能的。此外,receiver application想用不同的process去接收不同的media,也是難以達成的。
|
0 |
1 |
2 |
3 |
||||||||||||||||||||||||||||
|
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
0 |
1 |
|
Defined by profile |
length |
|
header extension …… |
|
defined by profile: 用來接收一些identifier或parameter。以允許要交互作用的implementation可以用不同的header extension去試驗﹔或允許一個特殊的implementation可以用一種以上的header extension去試驗。
Length: 用來記錄在extension中32-bit word的個數。
Extension機制是為了試驗新的payload-format-independent功能,讓那些功能可以在RTP header中加入需要的資訊﹔但是,若只是某些payload format所需要的而外資訊,則不宜使用header extension,而是應該包含在RTP packet中的payload section。
RTCP的原理就是,使用與RTP傳送packet一樣的傳送機制,每隔一段時間就傳送control packet。
n
RTCP主要的功能是了解資料distribution的quality。再配合distribution機制,像是IP Multicast,就可以讓network service provider這類實際上沒有加入RTP session的單位,去診斷網路上的問題。
n
RTCP包含一個不變的RTP source的transport-level identifier,叫做canonical name或是CNAME。Receiver依靠CNAME來追蹤每一個participant。RTP也使用CNAME在一組相關的RTP sessions中,將來自同一個participant的多的data stream作聯繫。
n
前面兩個功能都需要所有的participant傳送RTCP packet,所以為適應大量的participant,傳送的速率就要控制。透過每一個participant傳送RTCP packet給其他participant,所有的participant可以觀察現在participant總數目,而這個數目就用來計算傳送RTCP packet的速率。
RTCP packet可以包含以下五種資訊﹔
n
SR: 紀錄sender的reception statistics。
n
RR: 紀錄receiver的reception statistics。
n
SDES: 有關source的資訊,像是CNAME。
n
BYE: 指出某一participant的離開。
n APP: 指出某一application特有的functions。
n
每一個RTCP packet最前面都會有固定的部分,然後根據packet種類的不同,接著長度不同的資料,但總bit數都是32的倍數。
n
多個RTCP packet可以結合,而不需要任何的separator。
每一個RTCP packet一定要包含SR/RR與有CNAME的SDES,而且SR/RR一定是在最前面。
◆ 多媒體檔案格式
一般利用RTP來做視訊應用通常會分兩個Session來做,一個Session負責聲音傳送,另一個則為影像,這樣的狀況之下必須考慮影音同步的問題。而這次是傳送一個已經內含有聲音影像的Raw
Data過去(AVI file),這樣就不需要去考慮到影音同步的問題,讓Raw Data中的同步協定自己去做,我們聲音壓縮的格式主要是採MPEG Layer
III,影像壓縮主要是採MPEG4,最後合成一個RIFF-AVI傳送過去。
Mpeg Audio
Mpeg Audio是採Frame by Frame的儲存方式,一個Frame就是一個最基本的撥放單位,Mpeg
Audio的檔案結構如下:
FRAME1
FRAME2

31 0(bits)
Header的概述如下(詳細欄位資訊可於最後列出的參考資料尋找,因為整個篇幅太大了,不方便列出)
|
Sign |
Length(bit) |
Position(bit) |
Description |
A |
11 |
(31-21) |
Frame sync (all
bits must be set) |
|
B |
2 |
(20-19) |
MPEG Audio
version ID |
|
C |
2 |
(18-17) |
Layer
description |
|
D |
1 |
(16) |
Protection
bit |
|
E |
4 |
(15-12) |
Bitrate index |
|
F |
2 |
(11-10) |
Sampling rate
frequency index |
|
G |
1 |
(9) |
Padding bit |
|
H |
1 |
(8) |
Private bit.
This one is only informative |
|
I |
2 |
(7-6) |
Channel Mode |
|
J |
2 |
(5-4) |
Mode
extension |
|
K |
1 |
(3) |
Copyright |
|
L |
1 |
(2) |
Original |
|
M |
2 |
(1-0) |
Emphasis |
Mpeg Audio Frame Length
標頭的資訊我們已經詳細知道了,至於Raw
Data的長度可以由以下公式計算出來。
Read
the BitRate, SampleRate , Padding bit and protection bit(CRC) from header.
For
Layer I files us this formula:
FrameLengthInBytes
= (12 * BitRate / SampleRate + Padding) * 4 + CRC
For
Layer II & III files use this formula:
FrameLengthInBytes
= 144 * BitRate / SampleRate + Padding + CRC
Mpeg4
Mpeg4內的壓縮法並不是很清楚,可以參考其SPEC,我們是採DivX
MPEG4 Video Codec(filter)來達成我們的目的。
RIFF(defined by Microsoft)
因為AVI算是RIFF格式的檔案,因此先簡介RIFF。RIFF(Resource
Interchange File Format)是一個二進位的巢狀結構檔案,它並不代表任何多媒體檔案,而它是把多媒體檔案包裝在其定義的結構之中,包裝在RIFF中的多媒體資料主要是以檔案的副檔名來判別,如下所列:
·
Audio/visual
interleaved data (.AVI)
·
Waveform
data (.WAV)
·
Bitmapped
data (.RDI)
·
·
Color
palette (.PAL)
·
Multimedia
movie (.RMN)
·
Animated cursor (.ANI)
· A bundle of other RIFF files (.BND)
如上都是RIFF格式的檔案,只是其內含的多媒體資料不一樣。再來要說明的是RIFF結構,在RIFF中的基本單位就是Chunk,如下所列:
typedef struct _Chunk{DWORD ChunkId; /* Chunk ID marker */
DWORD ChunkSize; /* Size of the chunk data in bytes */
BYTE ChunkData[ChunkSize]; /* The chunk data */
} CHUNK;
ChunkData中又可包含別的Chunck(Sub
Chunk),這樣的關係一直下去就如上所稱的巢狀結構。
AVI
AVI屬於如上述的RIFF格式,AVI內擺的檔案資料包括了聲音與影像,它的Chunk分布如下:
struct _RIFF /* "RIFF" */
{
RIFF CHUNKstruct _AVICHUNK /* "AVI " */
{
struct _LISTHEADERCHUNK /* "hdrl" */
{
AVI CHUNK
AVIHEADER AviHeader; /* "avih" */
struct _LISTHEADERCHUNK /* "strl" */{
LIST-HDR CHUNK
AVISTREAMHEADER StreamHeader; /* "strh" */
AVISTREAMFORMAT StreamFormat; /* "strf" */ AVISTREAMDATA StreamData; /* "strd" */ }
}
struct _LISTMOVIECHUNK /* "movi" */
{struct _LISTRECORDCHUNK /* "rec " */
LIST-MOVI CHUNK
{
/* Subchunk 1 */ /* Subchunk 2 */ /* Subchunk N */ }
}
struct _AVIINDEXCHUNK /* "idx1" */
{
INDEX CHUNK
/* Index data */
}
}
}
如上所列,這是一個AVI的結構檔案,主要RIFF
chunk包裝一個AVI chunk,AVI chunk之中又包含了,LIST-HDR、LIST-MOVI、INDEX三個chunk,LIST-HDR
chunk之中主要是紀錄影音資料的資訊,LIST-MOVI chunk是擺影音資料,INDEX chunk是擺影音長度的索引,主要是提供快轉或迴轉影音的資訊,裡面更細部的內容可以參考後面列出的參考資料,因為篇幅長度實在太大了。
Summary
並不是所有的格式都是適合在網路上做傳送,許多做多媒體傳送的公司都有另外自訂的檔案格式,如Real
Player RA或是Microsoft ASF,此次採AVI格式將影像傳送出去也不是很清楚是否真的合適,這需要更仔細的研究才對。
◆ 系統初步架構
![]()
![]()

如上圖是我們初步實作出的架構,首先撥放端從DISK取出要撥放AVI
File做切割並套上RTP做Multicast傳送給撥放端。撥放端包含Receiver與Player兩部分,但其實是在同一程式於兩個不同的Thread執行。
撥放端接收到資料後就將AVI片段寫入DISK,最後Player將寫入的AVI片段給撥放出來。
這邊就出現了一些蠻有趣的現象,就是我們傳送端與撥放端的速度要如何協調,還有之間的頻寬問題呢?!基本上傳送端是根據AVI片段長度來調整速度的。或許可能又會問為什麼撥放端要透過DISK存取這道手續,接收到的AVI片段的RTP
Packet一開始不就是在記憶體中,為什麼不直接撥放出來?!主要的原因是因為Player是用DS來實作,而DS此時提供的Source Filter只能從URL或FILE讀取Raw
Data,因而我們採FILE的方式,所以要透過DISK而不是從Memory過去,但一透過DISK的方式,我們發覺在撥放AVI片段之間會有些許Delay。
關於剛剛提到的主要缺失我們也討論初一些解決方案,但是最好的就是直接透過Memory給DS處理,不用這樣拐個彎縮減效能,這就表示說我們需要去開發一個能從自訂記憶體Buffer讀取Raw
Data的Source Filter,至於這個部分由於時間不允許,因此尚未實作。
◆ 系統最後架構
![]()
![]()

最後的系統架構如上圖所示,撥放端全部沒有變,而在傳送端改為先由Capture
(CCD & MIC Device)取得多媒體,將取得的多媒體先寫入DISK,最後Sender再將寫入DISK的影像傳送出去,而Send與Capture實際上是同一程式,但Run在不同的Thread。
基本上傳送端也是有剛剛所提的毛病,其實是不必透過DISK的,這樣又浪費掉一些系統效能,而且效果又不是很好。
◆ 系統架構圖--
DirectShow Filter
Audio Capture Filter

![]()
![]()


![]()

![]()
![]()
![]()
![]()
如上圖將Capture與Sender部分展成內部DS
Filter連結狀況。Optional部分是指可以選擇壓縮方式或不壓縮,影像支援DivX MPEG4 Video Compressor、Microsoft
AVI Compressor,聲音方面有MPEG Layer3 Compressor,其實這方面可以根據系統擁有的Compressor來選擇。
◆ 傳送端Screen
Shot
如圖左下,主要的所有功能都在那下拉的Menu之中,包括是否要擷取影像或聲音、是否支援即時壓縮。選擇Start
Writing就會開始作傳送捕捉的影音,Stop會暫時停止傳送動作,空白部分是Preview視窗(如下圖畫面)。

圖一:開啟Video Capture時,自動出現Capture
property視窗

圖二:操作選單,可以選擇影像、聲音擷取,以及壓縮格式
◆ 接收端Screen
Shot

圖三:節目選單視窗

圖四:撥放CCD和MIC即時擷取的影像、聲音
◆ 後記
這個專題有些地方是值得繼續研究、改善的,例如RTP/RTCP的控制使用、DS部分改寫Filter來控制Raw
data的data flow或試著使用 DS內附的RTP Filter。
總而言之,這次的專題讓我們接觸到許多以往沒接觸的領域, 括實驗室的一些學長姐們也是,因此許多東西都要花費蠻多的時間去研究和搜尋資料,其中完成的測試程式也很多,包括了Multicast檔案傳輸、MPEG
Audio檔案切割器、DirectShow撥放影像、聲音的測試範例、RTP傳送、接收測試程式,領略到Microsoft Direct Show的架構和技術、也學會COM原件設計等等,有了這些概念與實作的基礎,想再深入下去也不會如此艱深。
◆ 參考資料
l
Online MSDN (http://msdn.microsoft.com/library/)
l
Microsoft DirectShow 8.0a SDK Document (see DX
SDK)
l
JRTP Library Document (http://lumumba.luc.ac.be/jori/jrtplib/jrtplib.html)
l
RTP Official Site (http://www.cs.columbia.edu/~hgs/rtp/)
l
RFC 1889 RTP
l
完全剖析COM Dale
Rogerson Microsoft Press
l
AVI RIFF FORMAT
(http://www.oreilly.com/centers/gff/formats/micriff/index.htm)
l
DirectX, RDX, RSX, and MMX technology : Rohan
Coelho and Maher Hawash Addison-Wesley Development Press
l
李英瑞,“IP Multicast 群播網路簡介”,1998.3
◆ 投影片和程式碼下載
=======================