7. DirectShow-內(nèi)部時鐘與音畫同步

內(nèi)部時鐘ReferenceTime

Filter Graph 管理器的一個功能是將圖形中的所有filter同步到同一時鐘(稱為 ReferenceTime)。

任何公開 IReferenceClock 接口的對象都可以充當(dāng)ReferenceTime。 ReferenceTime可能由 DirectShow filter提供,通常是音頻呈現(xiàn)器,它有權(quán)訪問硬件計時器。 作為回退,F(xiàn)ilter Graph 管理器可以使用系統(tǒng)時間。

從名義上說,ReferenceTime以 100 納秒的間隔測量時間,盡管時鐘的實際準(zhǔn)確度可能較低。 若要檢索時鐘的當(dāng)前時間,請調(diào)用 IReferenceClock::GetTime 方法。 時鐘的基線(開始計數(shù)的時間)取決于實現(xiàn),因此 GetTime 返回的值本質(zhì)上沒有意義。 重要的是圖形開始運行時的增量。

盡管ReferenceTime的準(zhǔn)確性可能會有所不同,但 GetTime 方法返回的時間保證單調(diào)增加。 換句話說,時鐘時間永遠(yuǎn)不會倒退。 如果ReferenceTime正在從硬件源生成時鐘時間,并且硬件時鐘向后跳 (例如,如果對時鐘) 進(jìn)行調(diào)整, 則 GetTime 方法應(yīng)繼續(xù)返回上次報告的時間,直到硬件時鐘趕上為止。 有關(guān)詳細(xì)信息,請參閱 CBaseReferenceClock 類。

默認(rèn)的ReferenceTime來源(不重要)

filter圖形管理器在圖形運行時自動選擇ReferenceTime。 它使用以下算法來選擇時鐘:

  • 如果應(yīng)用程序選擇了一個時鐘 (請參閱下面) ,請使用該時鐘。
  • 如果圖形包含支持 IReferenceClock 的實時源filter,請使用該filter。 有關(guān)實時源的定義,請參閱 實時源。
  • 如果圖形不包含任何實時源filter,請在圖形中使用支持 IReferenceClock 的任何filter,從呈現(xiàn)器開始,上游工作。 首選連接的filter,而不是未連接的filter
  • 如果圖形呈現(xiàn)音頻流,則算法中的此步驟通常會選擇音頻呈現(xiàn)器filter
  • 如果沒有filter提供合適的時鐘,請使用基于系統(tǒng)時間的系統(tǒng) ReferenceTime

設(shè)置ReferenceTime(不重要)

應(yīng)用程序可以通過在 Filter Graph Manager 上調(diào)用 IMediaFilter::SetSyncSource 方法來選擇時鐘。 僅當(dāng)有特定原因首選另一個時鐘時,才應(yīng)執(zhí)行此操作。

可以通過調(diào)用值為 NULL 的 SetSyncSource 來指示 Filter Graph 管理器不要使用ReferenceTime。 例如,可以執(zhí)行此操作以盡快處理MediaSample。 若要還原默認(rèn)ReferenceTime,請在 Filter Graph 管理器上調(diào)用 IFilterGraph::SetDefaultSyncSource 方法。

每當(dāng)ReferenceTime更改時,F(xiàn)ilter Graph 管理器都會通過調(diào)用其 IMediaFilter::SetSyncSource 方法通知每個filter。 應(yīng)用程序絕不應(yīng)在filter上調(diào)用此方法。

引用時間和流時間

DirectShow 定義了兩個相關(guān)的時鐘時間:引用時間和流時間。引用時間 是ReferenceTime返回的絕對時間。 (請參閱 ReferenceTime.)。流時間 相對于圖形上次開始運行的時間進(jìn)行定義。

  • 當(dāng)圖形運行時,流時間等于引用時間減去開始時間。
  • 當(dāng)圖形暫停時,流時間將停留在暫停的流時間。
  • 執(zhí)行查找操作后,流時間將重置為零。
  • 當(dāng)圖形停止時,流時間未定義。
  • 當(dāng)MediaSample具有時間戳 t 時,這意味著應(yīng)在流時間 t 呈現(xiàn)該MediaSample。 因此,流時間也稱為 演示時間。

當(dāng)應(yīng)用程序調(diào)用 IMediaControl::Run 來運行filter圖時,F(xiàn)ilter Graph 管理器在每個filter上調(diào)用 IMediaFilter::Run 。 為了補(bǔ)償filter開始運行所花費的輕微時間,F(xiàn)ilter Graph 管理器在將來會稍微指定一個啟動時間。

時間戳

時間戳采用流時間

時間戳定義MediaSample的開始和完成時間,以流時間度量。 時間戳有時稱為 呈現(xiàn)時間。 閱讀本文的其余部分時,請務(wù)必記住,并非所有格式都以相同的方式使用時間戳。 例如,并非所有 MPEG 樣本都帶有時間戳。 在 MPEG filter圖中,時間戳不會應(yīng)用于每個幀,直到它們從解碼器輸出。

當(dāng)呈現(xiàn)器filter收到MediaSample時,它會根據(jù)時間戳計劃呈現(xiàn)。 如果樣本遲到或沒有時間戳,filter將立即呈現(xiàn)樣本。 否則,filter將等到MediaSample的開始時間,然后才呈現(xiàn)MediaSample。 (它通過調(diào)用 IReferenceClock::AdviseTime 方法等待開始時間。)

filter和分析程序filter負(fù)責(zé)為其處理的樣本設(shè)置正確的時間戳。 請遵循以下準(zhǔn)則。

  • 文件播放:第一個MediaSample帶有時間戳,開始時間為零。 后續(xù)時間戳由樣本長度和播放速率決定,后者本身由文件格式?jīng)Q定。 分析文件的filter負(fù)責(zé)計算正確的時間戳, (例如 AVI 拆分器) 。
  • 視頻和音頻捕獲:每個樣本都標(biāo)有時間戳,其開始時間等于捕獲時的流時間,但需要注意預(yù)覽引腳中的視頻幀 (而不是捕獲引腳) 沒有時間戳。 由于圖形延遲,帶有捕獲時間標(biāo)記的視頻幀將始終晚于視頻呈現(xiàn)器到達(dá)。 這可能會導(dǎo)致呈現(xiàn)器在試圖進(jìn)行質(zhì)量控制時刪除幀。 有關(guān)質(zhì)量控制的信息,請參閱 質(zhì)量控制管理。
  • 音頻捕獲:音頻捕獲filter使用自己的一組緩沖區(qū),這些緩沖區(qū)與音頻驅(qū)動程序使用的緩沖區(qū)是分開的。 音頻驅(qū)動程序按固定間隔填充捕獲filter的緩沖區(qū)。 間隔取決于驅(qū)動程序,但通常不超過 10 毫秒。 音頻樣本上的時間戳反映了驅(qū)動程序填充音頻捕獲filter緩沖區(qū)的時間。 這些時間可能略有不準(zhǔn)確,尤其是在應(yīng)用程序使用非常小的緩沖區(qū)時。 但是,媒體時間將準(zhǔn)確反映緩沖區(qū)中的音頻樣本數(shù)。
  • 復(fù)用filter:根據(jù)輸出格式,多路復(fù)用filter可能需要生成時間戳,也可能不需要生成時間戳。 例如,AVI 文件格式使用沒有時間戳的固定幀速率,因此 AVI Mux filter假定樣本在大約正確的時間到達(dá)。 但是,如果傳入時間戳顯示大于一幀的間隙,AVI 復(fù)用器會寫入一個索引條目,其大小為零,以指示丟棄的幀。 在文件播放時,會在運行時生成新的時間戳,如前所述。
    若要在MediaSample上設(shè)置時間戳,請調(diào)用 IMediaSample::SetTime 方法。

MediaTime

(可選)filter還可以指定樣本的 媒體時間 。 在視頻流中,媒體時間表示幀數(shù)。 在音頻流中,媒體時間表示數(shù)據(jù)包中的樣本數(shù)。 例如,如果每個數(shù)據(jù)包包含 44.1 千赫 (kHz) 音頻的 1 秒,則第一個數(shù)據(jù)包的媒體開始時間為 0,媒體停止時間為 44100。 在可查找流中,媒體時間始終相對于流的開始時間。 例如,假設(shè)你從 15-fps 視頻流的開始時間開始 2 秒。 搜尋后的第一個MediaSample的時間戳為零,但媒體時間為 30。

呈現(xiàn)器和復(fù)用器filter可以使用媒體時間,通過檢查間隙來確定幀或樣本是否已丟棄。 但是,不需要filter來設(shè)置媒體時間。 若要在MediaSample上設(shè)置媒體時間,請調(diào)用 IMediaSample::SetMediaTime 方法。

實時源(也稱為 推送源)實時接收數(shù)據(jù)。

MediaSample包括視頻捕獲和網(wǎng)絡(luò)廣播。 通常,實時源無法控制數(shù)據(jù)的到達(dá)速率。如果存在以下任一情況,則filter被視為實時源:

  • filter從 IAMFilterMiscFlags::GetMiscFlags 方法返回AM_FILTER_MISC_FLAGS_IS_SOURCE標(biāo)志,并且至少一個其輸出引腳公開 IAMPushSource 接口。
  • filter公開 IKsPropertySet 接口,并具有捕獲引腳 (PIN_CATEGORY_CAPTURE) 。 有關(guān)詳細(xì)信息 ,請參閱固定屬性集 。
    如果實時源filter提供時鐘,filter關(guān)系圖管理器在選擇圖形ReferenceTime時會首選該時鐘。 有關(guān)詳細(xì)信息 ,請參閱ReferenceTime 。

延遲

filter的延遲是filter處理樣本所需的時間。 對于實時源,延遲取決于用于保存樣本的緩沖區(qū)的大小。 例如,假設(shè)filter圖的延遲為 33 毫秒 (毫秒的視頻源) ,音頻源的延遲為 500 毫秒。 在匹配的音頻樣本到達(dá)音頻呈現(xiàn)器之前,每個視頻幀到達(dá)視頻呈現(xiàn)器大約 470 毫秒。 除非圖形補(bǔ)償差異,否則音頻和視頻不會同步。

可以通過 IAMPushSource 接口同步實時源。 Filter Graph 管理器不會同步實時源,除非應(yīng)用程序通過調(diào)用 IAMGraphStreams::SyncUsingStreamOffset 方法啟用同步。 如果啟用了同步,filter關(guān)系圖管理器將查詢 IAMPushSource 的每個源filter。 如果filter支持 IAMPushSource,filter關(guān)系圖管理器會調(diào)用 IAMLatency::GetLatency 來檢索filter的預(yù)期延遲。 (IAMPushSource 接口從組合的延遲值繼承 IAMLatency.) ,filter關(guān)系圖管理器確定圖中的最大預(yù)期延遲。 然后,它調(diào)用 IAMPushSource::SetStreamOffset 為每個源filter提供流偏移量,該filter會將該偏移量添加到它生成的時間戳中。

此方法主要用于實時預(yù)覽版。 但請注意,實時捕獲設(shè)備上的預(yù)覽固定 ((如相機(jī)) )不會在它提供的MediaSample上設(shè)置時間戳。 因此,若要將此方法用于實時捕獲設(shè)備,必須從捕獲引腳預(yù)覽。 有關(guān)詳細(xì)信息,請參閱 DirectShow 視頻捕獲filter。

目前,VFW 捕獲filter和音頻捕獲filter支持 IAMPushSource 接口。

速率匹配

如果呈現(xiàn)器filter使用一個ReferenceTime計劃樣本,但源filter使用不同的時鐘生成樣本,則播放時可能會出現(xiàn)故障。 呈現(xiàn)器運行速度可能比源快,從而導(dǎo)致數(shù)據(jù)間隙。 或者,它的運行速度可能比源慢,導(dǎo)致樣本“堆起來”,直到圖在某個時候會丟棄樣本。 通常,實時源無法控制其生產(chǎn)速率,因此呈現(xiàn)器應(yīng)將速率與源匹配。

目前,只有音頻呈現(xiàn)器執(zhí)行速率匹配,因為音頻播放中的故障比視頻中的故障更明顯。 若要執(zhí)行速率匹配,音頻呈現(xiàn)器必須選擇與速率匹配的內(nèi)容。 它使用以下算法:

  • 如果圖形未使用ReferenceTime,則音頻呈現(xiàn)器不會嘗試匹配速率。 (每當(dāng)圖形沒有ReferenceTime時,樣本始終在到達(dá)時立即呈現(xiàn)。) 否則,如果有圖形的ReferenceTime,音頻呈現(xiàn)器將使用前面所述的條件檢查是否存在實時源上游。 否則,音頻呈現(xiàn)器與速率不匹配。
  • 如果存在實時源上游,并且該源在其輸出引腳上公開 IAMPushSource 接口,則音頻呈現(xiàn)器將調(diào)用 IAMPushSource::GetPushSourceFlags。 它會查找以下標(biāo)志之一:
    • AM_PUSHSOURCECAPS_INTERNAL_RM。 此標(biāo)志表示源filter具有自己的速率匹配機(jī)制,因此音頻呈現(xiàn)器不匹配速率。
    • AM_PUSHSOURCECAPS_NOT_LIVE。 此標(biāo)志意味著源filter不是真正的實時源,即使它公開了 IAMPushSource 接口。 因此,音頻呈現(xiàn)器與速率不匹配。
    • AM_PUSHSOURCECAPS_PRIVATE_CLOCK。 此標(biāo)志表示源filter使用專用時鐘生成時間戳。 在這種情況下,音頻呈現(xiàn)器將速率與時間戳匹配。 (如果MediaSample沒有時間戳,呈現(xiàn)器將忽略此標(biāo)志。)
  • 如果 GetPushSourceFlags 未返回任何標(biāo)志 (零) ,則音頻呈現(xiàn)器的行為取決于圖形時鐘以及樣本是否具有時間戳:
    • 如果音頻呈現(xiàn)器不是圖形時鐘,并且樣本具有時間戳,則音頻呈現(xiàn)器會將速率與時間戳匹配。
    • 如果樣本沒有時間戳,音頻呈現(xiàn)器會嘗試匹配傳入音頻數(shù)據(jù)的速率。
    • 如果音頻呈現(xiàn)器是圖形時鐘,它將嘗試匹配傳入的數(shù)據(jù)速率。
      最后一種情況的原因如下:如果音頻呈現(xiàn)器是ReferenceTime,并且源filter使用相同的時鐘來生成時間戳,則音頻呈現(xiàn)器無法將速率與時間戳匹配。 如果確實如此,實際上它會嘗試將速率與自身匹配,這可能導(dǎo)致時鐘偏移。 因此,在這種情況下,呈現(xiàn)器與傳入音頻數(shù)據(jù)的速率匹配。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容