DirectShow編程(3.6) - 關於DirectShow - DirectShow中的時間和時鐘

http://blog.csdn.net/believefym/article/details/1779745

3.6. DirectShow中的時間和時鐘
    這一節主要概述DirectShow體系中時間和時鐘。
3.6.1. 參考時鐘
    Filter Graph Manager的一個功能,能夠以同一個時鐘來同步所有在graph中的filter,稱作參考時鐘(reference clock)
    任何暴露了IReferenceClock接口的對象都能夠作爲一個參考時鐘來使用。參考時鐘可以由一個DirectShow filter來提供,例如可以直接使用硬件時鐘的audio renderer。另外,Filter Graph Manager也能使用系統時間來作參考時鐘。
    名義上,一個參考時鐘以千萬分之一秒的精度來度量時間,但是實際上的精度不會這麼高。要取得參考時鐘的當前時間,調用IReferenceClock:: GetTime方法。由於時鐘的基準時間,即時鐘開始時的時間計數,是依賴於具體的實現的,因此GetTime的返回值不反映絕對時間,只反映相對於 graph開始時的相對時間。
    雖然參考時鐘的精度是變化的,但是GetTime的返回值卻保證是單調遞增的,換句話說,也就是參考時鐘的時間是不會回退的。如果參考時鐘的時間是由硬件 源產生的,而硬件時鐘回退了(比如,有一個調節器調節了時鐘),GetTime依然返回最晚的那個時間只到硬件時鐘追上它。要知道更多的內容可以參考 CBaseReferenceClock類(http://msdn.microsoft.com/library/en-us/directshow/htm/cbasereferenceclockclass.asp)。
    
    默認參考時鐘
    當Graph運行時,Filter Graph Manager會自動選擇參考時鐘,選擇參考時鐘的規則如下:
    *如果應用程序指定了一個時鐘,則使用這個時鐘;
    *如果Graph包含了一個支持IReferenceClock的活動源filter(即推模式源filter),則使用這個filter;
    *如果Graph未包含任何支持IReferenceClock的推模式源filter,使用任何一個支持IReferenceClock接口的 filter,選擇的次序是從Renderer filter開始依次向上。已連接的filter優先於未連接的filter被選。(如果這個graph會render一個音頻流,則這個規則通常就會選 擇audio renderer filter來作爲參考時鐘)
    *如果沒有filter支持合適的時鐘,則使用系統參考時鐘。
    
    設置參考時鐘
    應用程序可以在Filter Graph Manager上調用IMediaFilter::SetSyncSource方法來選擇時鐘,只有在由於你有一個特殊原因想要選擇自己的時鐘時才需要這麼做。
    想要讓Filter Graph Manager不使用任何參考時鐘,可以調用SetSyncSource,參數爲NULL。比如,你需要儘可能快地來處理sample時,就可以這麼做。 要恢復黑認的參考時鐘,在Filter Graph Manager上調用IFilterGraph::SetDefaultSyncSource方法。
    當參考時鐘發生變化時,Filter Graph Manager會通知每一個filter調用它的IMediaFilter::SetSyncSource方法,應用程序無需調用filter的這個方法。
    
3.6.2. 時鐘時間
    DirectShow定義了兩種相關時間:參考時間(reference time)流時間(stream time)
    *參考時間是一個絕對時間,由參考時鐘返回
    *流時間是一個相對於graph最後開始時的相對時間
     ·當graph處於運行態時,流時間等於參考時間減去起始時間
     ·當graph處於暫停態時,流時間停留在暫停的那一刻
     ·在重新定位後,流時間被重設爲0
     ·當graph處於停止態時,流時間無意義
    如果一個媒體樣本有一個時間戳t,表示這個在流時間爲t時被render,正因爲這個原因,因此流時間也被叫做呈現時間(presentation time)
    當應用程序調用IMediaControl::Run運行graph時,Filter Graph Manager調用每個filter的IMediaFilter::Run。爲了補償消耗在運行每個filter的時間總和,Filter Graph Manager會略微晚一點來定義起始時間。
    
3.6.3. 時間戳
    時間戳定義了媒體樣本的起始和結束時間。時間戳有時被稱作呈現時間(presentation time)。在閱讀餘下的文章時,一個必須記住的要點是並非所有的媒體格式都以相同的方式來使用時間戳。舉個例子,並不是所有MPEG樣本都被打上了時間 戳,在MPEG Filter Graph中,時間戳在被解碼前並非應用在每個幀上。
    當一個renderer filter接收到一個樣本時,它以時間戳爲基準來確定render時間。如果樣本來晚了,或者這個樣本沒有時間戳,那個filter就立刻render 它,否則,filter就等在那直到合適的時機。(通過IReferenceClock::AdviseTime方法來等待樣本的render時間)
    源filter和語法解析filte使用下列原則,在它們處理的樣本上設置合適的時間戳:
    *文件回放:第一個樣本被打上起始時間戳,爲0,後面的時間戳由樣本長度和回放速率來決定,這些都由文件格式來決定。分析文件的filter負責計算出合適的時間戳。例子見(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directshow/htm/avisplitterfilter.asp
    *音視頻採集:每個樣本都被打上一個起始時間戳,這個時間戳與當它被捕獲時的Stream time相同。應注意以下幾點:
     ·從預覽pin(Preview Pin)出來的樣本沒有時間戳。因爲圖像處理的延時,一個打上採集時間的視頻幀總是會遲一點到達視頻renderer。這會導致在進行質量控制時,renderer會丟棄部分視頻幀。關於質量控制,參見(http://msdn.microsoft.com/library/en-us/directshow/htm/qualitycontrolmanagement.asp
     ·音頻採集:音頻採集filter使用它自己的緩衝集,而並非使用音頻驅動程序的。音頻驅動以固定的時間間隔來填充採集filter的緩衝。這個時間間 隔由驅動決定,通常不超過10毫秒。在音頻樣本上的時間戳反映的是驅動填充採集filter時的時間,因此會有偏差,尤其是當應用程序使用一個很小的緩衝 區時。不過,媒體時間可以精確地反映緩衝區中音頻樣本的數量。
    *混合filter(Mux filter):依賴於輸出格式,一個mux filter可能需要由它來產生時間戳,也可能不需要。舉個例子,AVI文件格式使用固定的幀率而沒有時間戳,因此AVI Mux filter假設那些樣本在近似正確的時間內到達。如果樣本沒有在合適的時間間隔內到達,AVI Mux filter會插入一個長度爲0的空樣本,來表示一個丟失的幀。在文件回放時,新的時間戳在運行時如前面所述地那樣產生。
    要在一個樣本上設置一個時間戳,調用IMediaSample::SetTime方法。
    此外,filter還可以爲樣本指定一個媒體時間(media time)。 在視頻流中,media time表示視頻幀的數量。在音頻流中,media time表示包中的樣本數量,比如,如果每個包包含以44.1KHz的採樣率採集的一秒鐘的音頻,那麼第一個包具有一個爲0的媒體起始時間以及爲 44100的媒體終止時間。在一個可以定位的流中,媒體時間總是相對於流的起始時間,比如,假設你在一個15幀/秒的視頻流上定位到2秒這個位置,那麼定 位後的每一個媒體樣本的時間媒爲0,但是它的媒體時間爲30.
    Renderer和Mux filter能使用媒體時間通過檢查是否有缺口來確定幀或樣本是否被丟棄了。但是,filter不是一定要設定媒體時間。要設置媒體時間,調用IMediaSample::SetMediaTime方法。
    
3.6.4 實時源(Live Source)
    實時源,也被叫做推模式源(push source),實時地接收數據,比如視頻採集和網絡廣播。通常情況下,一個實時源不能控制數據到達的速率。
    一個filter被認爲是實時源需要具有以下幾點:
    * 調用IAMFilterMiscFlags::GetMiscFlags方法時返回AM_FILTER_MISC_FLAGS_IS_SOURCE標記,並且至少有一個輸出pin暴露IAMPushSource接口。
    * filter暴露IKsPropertySet接口,並具有一個capture pin(PIN_CATEGORY_CAPTURE)。
    
    延時(latency)
    一個filter的延時是這個filter處理一個樣本所需的時間總和。在實時源中,延時取決於保存樣本的緩衝區大小。舉個例子,假設graph有一個具 有33ms延時的視頻源和一個具有500ms延時的音頻源,那麼每個到達視頻renderer的視頻幀要比與之匹配的音頻樣本到達音頻renderer早 470ms,除非graph對這個差別進行補償,否則音視頻將會不同步。
    實時源可以通過IAMPushSource接口來進行同步。Filter Graph Manager並做同步工作除非應用程序通過調用IAMGraphStreams::SyncUsingStreamOffset方法來激活它。如果同步 被激活,Filter Graph Manager通過IAMPushSource來查詢每一個source filter,如果filter支持IAMPushSource,那麼Filter Graph Manager調用IAMLatency::GetLatency來得到filter預期的延時(IAMPushSource繼承自 IAMLatency)。通過組合的延時值,filter graph manager決定graph中最大的預期延時,然後調用IAMPushSource::SetStreamOffset來給每一個source filter一個流偏移,以後filter會在產生時間戳時加上這個偏移。
    這個方法主要是爲了實現實時預覽,但是,注意實時採集設備(比如攝像頭)的preview pin上是沒有時間戳的,因此,要在一個實時採集設備上使用這種方法,你必須在capture pin上進行視頻預覽。
    通常,IAMPushSource接口被VFW Capture filter和音頻採集filter(Audio capture filter)支持。
    
    速率匹配(Rate Matching)
    如果renderer filter和source filter使用不同的參考時鐘,那麼就會有問題,renderer可能比source要快,這就導致了數據的缺口,或則renderer比source 慢,就會導致數據擁堵而樣本丟棄。通常一個實時源無法控制速率,因此要求renderer來與source進行速率匹配。
    通常,只有audio renderer實現速率匹配,因爲聲音回放的頻率比視頻更重要。要實現速率匹配,audio renderer必須排除以下幾點:
    *如果graph沒有使用一個參考時鐘,那麼audio renderer不會去進行速率匹配(如果graph沒有參考時鐘,那麼樣本總是在到達時就被立刻render)。
    *另外,如果graph中有一個參考時鐘,audio renderer檢測是否有一個實時源在上游,如果沒有,audio renderer不進行速率匹配。
    *如果有一個實時源在上游,並且這個實時源在它的輸出Pin上暴露IAMPushSource接口,audio renderer調用IAMPushSource::GetPushSourceFlags,並尋找以下標記:
     ·AM_PUSHSOURCECAPS_INTERNAL_RM,這個標記表示這個實時源擁有自己的速率匹配機制,因此audio renderer不進行速率匹配。
     ·AM_PUSHSOURCECAPS_NOT_LIVE,這個標記表示source filter並不是一個真正的實時源,即使它暴露了IAMPushSource接口,因此,audio renderer不進行速率匹配。
     ·AM_PUSHSOURCECAPS_PRIVATE_CLOCK,這個標記表示source filter使用一個私有的時鐘來產生時間戳。在這種情況下,audio renderer速率匹配與時間戳會有衝突。(如果樣本沒有時間戳,那麼renderer忽略這個標記。
    *如果GetPushSourceFlags返回沒有標記(0),audio renderer的行爲依賴於graph時鐘和樣本是否擁有時間戳:
     ·如果audio renderer不是graph參考時鐘,並且樣本擁有時間戳,那麼audio renderer速率匹配與時間戳會有衝突
     ·如果樣本沒有時間戳,audio renderer嘗試與輸入的音頻數據的速率進行匹配。
     ·如果audio renderer是graph參考時鐘,它與輸入的數據速率進行匹配。
    最後一種情況的原因如下:如果audio renderer是參考時鐘,並且source filter使用同樣的時鐘來產生時間戳,那麼audio renderer不會與這個時間戳進行速率匹配,因爲如果它這樣做了,導致的結果是,它等於在嘗試與自己進行速率匹配,這將導致時鐘偏差。因此,在這種情 況下,renderer與輸入的音頻數據速率進行匹配。 

發佈了2 篇原創文章 · 獲贊 1 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章