簡報時鐘
簡報時鐘 是一個物件,可產生簡報的時鐘時間。 簡報時鐘所報告的時間稱為 簡報時間。 簡報中的所有數據流都會同步處理至簡報時間。 簡報時鐘會公開下列介面。
介面 | 描述 |
---|---|
IMFPresentationClock | 使用簡報時鐘的主要介面。 |
IMFRateControl | 控制時鐘速率。 |
IMFTimer | 提供定時器回呼。 |
IMFShutdown | 關閉簡報時鐘。 |
媒體接收會使用簡報時間排程何時轉譯樣本。 每當媒體接收收到新的範例時,它會從範例取得時間戳,並在指定的時間轉譯樣本,或盡可能接近該時間。 由於拓撲中的所有媒體接收都會共用相同的簡報時鐘,因此會同步處理多個串流(例如音訊和視訊)。 媒體來源和轉換不會使用簡報時鐘,因為它們不會排程何時傳遞範例。 相反地,每當管線要求新的範例時,它們就會產生範例。
如果您使用媒體會話播放,媒體會話會處理建立簡報時鐘、選取時間來源,以及通知媒體接收的所有詳細數據。 您的應用程式可能會使用簡報時鐘在播放期間取得目前的簡報時間,否則不會在簡報時鐘上呼叫任何方法。
時鐘時間和時鐘狀態
若要從簡報時鐘取得最新的時鐘時間,請呼叫 IMFPresentationClock::GetTime。 時鐘時間一律以 100 奈秒為單位,因此一秒是 10,000,000 (10^7) 刻度。 這會對應至 10 MHz 的頻率。
簡報時鐘有三種狀態:執行、暫停和停止。
- 若要執行時鐘,請呼叫 IMFPresentationClock::Start。 Start 方法會指定時鐘的開始時間。 當時鐘執行時,時鐘時間會以目前的時鐘速率從開始時間遞增。
- 若要暫停時鐘,請呼叫 IMFPresentationClock::P ause。 當時鐘暫停時,時鐘時間不會前進,GetTime 會傳回時鐘暫停的時間。
- 若要停止時鐘,請呼叫 IMFPresentationClock::Stop。 當時鐘停止時,時鐘時間不會前進,而且 GetTime 會傳回零。
根據預設,時鐘會以 1.0 的速度前進,這表示每 100 奈秒 1 個刻度。 若要變更時鐘的進階速率,請查詢IMFRateControl介面簡報時鐘,並呼叫 IMFRateControl::SetRate。
物件可以從簡報時鐘接收狀態變更的通知(包括速率變更)。 若要接收通知,請在簡報時鐘上實作 IMFClockStateSink 介面,並呼叫 IMFPresentationClock::AddClockStateSink。 關閉之前,請先呼叫 IMFPresentationClock::RemoveClockStateSink 以取消註冊物件。 媒體接收會使用此機制從時鐘接收通知。
簡報時間
媒體接收會嘗試排程每個範例,讓樣本在正確的時間轉譯,或盡可能接近正確的時間。 下列定義適用:
- 簡報時間。 應該轉譯樣本的時間。 時間是以 100 奈秒為單位來指定。
- 媒體時間。 相對於內容開始的時間。 例如,如果視訊檔案長 10 秒,則透過檔案的半點有 5 秒的媒體時間。
- 時間戳。 在媒體範例上標示的時間。 若要取得時間戳,請呼叫 IMFSample::GetSampleTime。 當媒體來源產生範例時,它會將時間戳設定為等於媒體時間。 媒體會話會將時間戳轉譯成簡報時間。
根據預設,媒體時間和簡報時間相同,例如,如果視訊畫面出現在來源檔案中 5 秒,則媒體時間和簡報時間都是 5 秒。 如果您使用 Sequencer Source,則計時模型會比較複雜,以啟用區段之間的順暢轉換。 如需排序器來源計時模型的詳細資訊,請參閱 時序呈現時間。
媒體來源一律會將時間戳設定為等於媒體時間。 如果簡報時間與媒體時間不一致,媒體會話會轉換媒體範例上的時間戳。 在接收接收樣本時,範例的時間戳已轉換為簡報時間。 接收會根據簡報時鐘的目前時間排程範例。 (無速率接收是例外狀況,因為它們會忽略簡報時鐘。
如果應用程式尋求新位置,媒體會話會在指定的搜尋時間重新啟動簡報時鐘。 例如,如果應用程式搜尋檔案中的5秒位置,媒體會話就會以5秒的速度啟動時鐘。 如果搜尋時間不落在主要畫面格界限上,媒體來源可能會提供稍早時間戳的樣本。 這是必要的,讓譯碼器可以譯碼所有畫面格。 媒體會話會先卸除或修剪樣本,再到達媒體接收,以符合要求的搜尋時間。 例如,如果搜尋時間是5秒,則第一個音訊範例可能會從4.5秒開始。 媒體會話會從第一個譯碼的音訊範例修剪前0.5秒。
建立簡報時鐘
若要建立簡報時鐘,請呼叫 MFCreatePresentationClock。 若要關閉時鐘,請查詢 IMFShutdown 介面,並呼叫 IMFShutdown::Shutdown。 MFCreatePresentationClock 的呼叫端負責呼叫 Shutdown;在大部分情況下,這是媒體會話,而不是應用程式。
簡報時間來源
儘管其名稱,但簡報時鐘實際上不會實作時鐘。 相反地,它會從另一個物件取得時鐘時間,稱為 表示時間來源。 時間來源可以是任何產生精確時鐘刻度的物件,並公開IMFPresentationTimeSource介面。 下圖顯示此程式。
顯示簡報時鐘與簡報時間來源之間關聯
第一次建立簡報時鐘時,它沒有時間來源。 若要設定時間來源,請呼叫 IMFPresentationClock::SetTimeSource,並使用時間來源 IMFPresentationTimeSource 介面的指標。 時間來源支援與簡報時鐘相同的狀態(執行、暫停和停止),而且必須實作IMFClockStateSink介面。 簡報時鐘會使用此介面來通知時間來源何時變更狀態。 如此一來,時間來源會提供時鐘刻度,但簡報時鐘會在時鐘中起始狀態變更。
某些媒體接收可以存取精確的時鐘,因此會公開IMFPresentationTimeSource介面。 特別是,音訊轉譯器可以使用聲卡的頻率作為時鐘。 在音訊播放中,音訊轉譯器可做為時間來源,以便將視訊同步處理至音訊播放速率。 這通常會產生比嘗試將音訊比對外部時鐘更好的結果。
媒體基礎也會根據系統時鐘提供簡報時間來源。 若要建立此物件,請呼叫 MFCreateSystemTimeSource。 沒有媒體接收提供時間來源時,可以使用系統時間來源。
一般而言,媒體接收必須使用提供給它的簡報時鐘,不論簡報時鐘所使用的時間來源為何。 即使媒體接收實作 IMFPresentationTimeSource,仍適用此規則。 如果簡報時鐘使用其他時間來源,媒體接收必須遵循該時間來源,而不是它自己的內部時鐘。
媒體接收不會遵循簡報時鐘時,有兩種情況:
某些媒體接收器 無速率。 如果媒體接收是無速率的,它會盡可能快速地取用樣本,而不會根據簡報時鐘排程樣本。 一般而言,無速率接收會將數據寫入檔案,因此最好儘快完成作業。 無速率接收會傳回其 IMFMediaSink::GetCharacteristics 方法中的MEDIASINK_RATELESS旗標。 當拓撲中的所有接收都是無速率時,媒體會話會儘快透過管線推送數據。
某些媒體接收器無法比對本身以外的時間來源的速率。 如果是,接收會傳回其 GetCharacteristics 方法中的MEDIASINK_CANNOT_MATCH_CLOCK旗標。 管線仍然可以使用另一個時間來源,但結果會小於最佳。 接收可能會落後,並在播放期間造成問題。
相關主題