媒體接收
媒體接收 是接收媒體資料的管線物件。 媒體接收是一或多個媒體資料流程的目的地。 媒體接收分為兩個一般類別:
轉 譯器 是一種媒體接收,可呈現用於播放的資料。 增強的視訊轉譯器 (EVR) 顯示視訊畫面,而音訊轉譯器會透過音效卡或其他音訊裝置播放音訊串流。
封存接收是一種媒體接收,會將資料寫入檔案或其他儲存體。
它們之間的主要差異在於封存接收不會以固定播放速率取用資料。 相反地,它會寫入儘快接收的資料。
媒體接收會公開 IMFMediaSink 介面。 每個媒體接收都包含一或多個 資料流程接收。 每個資料流程接收都會從一個資料流程接收資料。 資料流程接收會公開 IMFStreamSink 介面。 應用程式通常不會直接建立媒體接收。 相反地,應用程式會建立一或多個啟用物件,媒體會話會使用此物件來建立接收。 接收上的所有其他作業都是由媒體會話處理,而且應用程式不會在媒體接收或任何資料流程接收上呼叫任何方法。 如需啟用物件的詳細資訊,請參閱 啟用物件。
如果您要撰寫自訂媒體接收,或想要直接不使用媒體會話使用媒體接收,您應該閱讀本主題的其餘部分。
資料流程接收
媒體接收可以有固定數目的資料流程接收,也可以支援新增和移除資料流程接收。 如果有固定數目的資料流程接收, IMFMediaSink::GetCharacteristics 方法會傳回MEDIASINK_FIXED_STREAMS旗標。 否則,您可以新增和移除資料流程接收。 若要新增資料流程接收,請呼叫 IMFMediaSink::AddStreamSink。 若要移除資料流程接收,請呼叫 IMFMediaSink::RemoveStreamSink。 MEDIASINK_FIXED_STREAMS旗標表示媒體接收不支援這兩種方法。 (它可能支援設定資料流程數目的其他方式,例如在建立接收時設定初始化參數。) 已排序資料流程接收的清單。 若要依索引值列舉它們,請呼叫 IMFMediaSink::GetStreamSinkByIndex 方法。
資料流程接收也有識別碼。 資料流程識別碼在媒體接收內是唯一的,但不需要是連續的。 視媒體接收而定,串流識別碼可能有一些與內容相關的意義。 例如,封存接收可能會將資料流程識別碼寫入檔案標頭。 否則,它們是任意的。 若要依識別碼取得資料流程接收,請呼叫 IMFMediaSink::GetStreamSinkById。
簡報時鐘
媒體接收取用樣本的速率是由 Presentation Clock所控制。 媒體會話會選取簡報時鐘,並藉由呼叫媒體接收的 IMFMediaSink::SetPresentationClock 方法,在媒體接收上設定它。 必須先在媒體接收上設定簡報時鐘,才能開始串流。 每個媒體接收都需要執行簡報時鐘。 媒體接收會針對兩個用途使用簡報時鐘:
若要在串流啟動或停止時接收通知。 媒體接收會透過 IMFClockStateSink 介面接收這些通知,所有媒體接收都必須實作這些通知。
判斷其何時應該呈現樣本。 當媒體接收收到新的範例時,它會從範例取得時間戳記,並嘗試在該簡報時間轉譯樣本。
簡報時鐘會從另一個稱為 簡報時間來源的物件衍生其時鐘時間。 簡報時間來源會公開 IMFPresentationTimeSource 介面。 某些媒體接收可以存取精確的時鐘,因此它們會公開此介面。 這表示媒體接收可能會根據自己的時鐘所提供的時間排程樣本。 不過,媒體接收無法假設這是這種情況。 無論簡報時鐘是由媒體接收本身或其他時鐘所驅動,它都必須一律使用簡報時鐘的時間。
如果媒體接收無法比對頻率與其本身以外的時鐘, GetCharacteristics 方法會傳回MEDIASINK_CANNOT_MATCH_CLOCK旗標。 如果此旗標存在,而且簡報時鐘使用不同的簡報時間來源,媒體接收可能會效能不佳。 例如,在播放期間可能會發生問題。
無速率接收是一種媒體接收,會忽略樣本上的時間戳記,並在每個樣本送達時立即取用資料。 無速率媒體接收會從 GetCharacteristics 方法傳回MEDIASINK_RATELESS旗標。 此旗標通常適用于封存接收。 如果管線中的每個媒體接收都是無速率的,媒體會話會使用特殊的無速率簡報時鐘。 此時鐘會以接收取用樣本的速度執行。
資料流程格式
在媒體接收可以接收樣本之前,用戶端必須在資料流程接收上設定媒體類型。 若要設定媒體類型,請呼叫資料流程接收的 IMFStreamSink::GetMediaTypeHandler 方法。 這個方法會傳回 IMFMediaTypeHandler 介面的指標。 使用此介面來取得慣用媒體類型清單、取得目前的媒體類型,以及設定媒體類型。
若要取得慣用媒體類型的清單,請呼叫 IMFMediaTypeHandler::GetMediaTypeByIndex。 慣用的類型應視為用戶端的提示。 清單可能不完整或包含部分媒體類型。 部分媒體類型是沒有描述有效格式所需的所有屬性的媒體類型。 例如,部分視訊類型可能會指定色彩空間和位深度,但不會指定影像寬度或高度。 部分音訊類型可能會指定壓縮格式和取樣率,但不能指定音訊通道的數目。
若要取得資料流程接收的目前媒體類型,請呼叫 IMFMediaTypeHandler::GetCurrentMediaType。 第一次建立資料流程接收時,它可能會設定預設媒體類型,或者用戶端設定一個媒體類型之前可能沒有媒體類型。
若要設定媒體類型,請呼叫 IMFMediaTypeHandler::SetCurrentMediaType。 某些資料流程接收可能不支援在 設定 之後變更類型。 因此,在設定媒體類型之前測試媒體類型會很有用。 若要測試媒體接收是否接受媒體類型, (而不設定類型) ,請呼叫 IMFMediaTypeHandler::IsMediaTypeSupported。
資料流程
媒體接收會使用 提取模型,這表示資料流程接收會視需要要求資料。 用戶端應該及時回應,以避免發生任何問題。
某些媒體接收支援 預先註冊。 預先註冊是在簡報時鐘開始之前,將資料提供給媒體接收的程式。 如果媒體接收支援預先註冊,媒體接收會公開 IMFMediaSinkPreroll 介面,而 GetCharacteristics 方法會傳回 MEDIASINK_CAN_PREROLL 旗標。 預先註冊可確保媒體接收已準備好在簡報時鐘啟動時呈現第一個範例。 建議用戶端一律在媒體接收支援時預先註冊,因為它可以在播放期間防止發生問題或間距。
資料流程至媒體接收的運作方式如下:
- 用戶端會設定媒體類型和簡報時鐘。 媒體接收會向簡報時鐘註冊本身,以接收有關時鐘狀態變更的通知。
- 選擇性地,用戶端會查詢 IMFMediaSinkPreroll。 如果媒體接收公開此介面,用戶端會呼叫 IMFMediaSinkPreroll::NotifyPreroll。 否則,用戶端會跳到步驟 5。
- 每個資料流程接收都會傳送一或多個 MEStreamSinkRequestSample 事件。 為了回應上述每個事件,用戶端會取得該資料流程的下一個資料範例,並呼叫 IMFStreamSink::P rocessSample。
- 當每個資料流程接收接收足夠的預先註冊資料時,它會傳送 MEStreamSinkPrerolled 事件。
- 用戶端會呼叫 IMFPresentationClock::Start 來啟動簡報時鐘。
- 簡報時鐘會呼叫 IMFClockStateSink::OnClockStart,通知媒體接收正在啟動時鐘。
- 若要取得更多資料,每個資料流程接收都會傳送 MEStreamSinkRequestSample 事件。 為了回應上述每個事件,用戶端會取得下一個範例,並呼叫 ProcessSample。 此步驟會重複執行,直到簡報結束為止。
大部分媒體接收會以非同步方式處理樣本,因此資料流程接收可以一次傳送多個範例要求。
在串流期間,用戶端可以隨時呼叫 IMFStreamSink::P laceMarker 和 IMFStreamSink::Flush 。 下一節會說明標記。 排清會導致資料流程接收卸載已排入佇列但尚未轉譯的任何樣本。
標記
標記可讓用戶端指出資料流程中的特定點。 標記包含下列資訊:
- 標記類型,定義為 MFSTREAMSINK_MARKER_TYPE 列舉的成員。
- 與標記相關聯的資料。 資料的意義取決於標記類型。 某些標記類型沒有資料。
- 用戶端本身使用的選擇性資料。
若要放置標記,用戶端會呼叫 IMFStreamSink::P laceMarker。 資料流程接收會完成在 PlaceMarker 呼叫之前收到的任何樣本,然後傳送 MEStreamSinkMarker 事件。
大部分媒體接收都會保留暫止樣本佇列,它們會以非同步方式處理。 標記事件必須使用範例處理進行序列化,因此媒體接收應該將標記放在相同的佇列中。 例如,假設用戶端進行下列方法呼叫:
- ProcessSample (範例 #1)
- ProcessSample (範例 #2)
- PlaceMarker (Marker #1)
- ProcessSample (範例 #3)
- PlaceMarker (Marker #2)
在此範例中,資料流程接收必須在處理範例 #2 之後傳送 標記的 MEStreamSinkMarker 事件 #1,並在處理範例之後傳送標記 #2 的事件 #3。
如果用戶端排清資料流程接收,資料流程接收會立即處理佇列中的任何標記。 它會將狀態碼設定為在這些事件上E_ABORT。
某些標記包含與媒體接收相關的資訊:
- MFSTREAMSINK_MARKER_TICK:表示資料流程中有間距。 下一個範例將會是不連續的。
- MFSTREAMSINK_MARKER_ENDOFSEGMENT:表示區段的結尾或資料流程結尾。 下一個範例 (是否有任何) 可能不連續。
- MFSTREAMSINK_MARKER_EVENT:包含事件。 視事件種類和媒體接收的實作而定,媒體接收可能會處理事件或忽略它。
狀態變更
媒體接收會透過媒體接收的 IMFClockStateSink 介面,在簡報時鐘中收到狀態變更的通知。 當用戶端設定簡報時鐘時,媒體接收會呼叫 IMFPresentationClock::AddClockStateSink 來向時鐘註冊通知。 下表摘要說明媒體接收如何回應時鐘狀態變更。
時鐘狀態變更 | 來樣加工 | 標記處理 |
---|---|---|
OnClockStart | 處理時間戳記等於或晚于時鐘開始時間的範例。 | 處理標記之前收到的所有樣本時,傳送 MEStreamSinkMarker 事件。 |
OnClockPause | 暫停時,媒體接收可能會失敗 ProcessSample 。 如果媒體接收在暫停時接受樣本,則必須將它們排入佇列,直到時鐘重新開機為止。 暫停時請勿處理任何已排入佇列的樣本。 |
如果有已排入佇列的樣本,請將標記放在相同的佇列上。 當時鐘重新開機時,傳送標記事件。 否則,請立即傳送標記事件。 |
OnClockRestart | 處理暫停時已排入佇列的任何範例,然後處理與 OnClockStart相同的範例。 | 傳送佇列標記的 MEStreamSinkMarker 事件, (使用範例處理) 序列化,然後視為 OnClockStart。 |
OnClockStop | 卸載所有已排入佇列的範例。 進一步呼叫 ProcessSample 可能會失敗。 | 傳送佇列標記事件。 在後續呼叫 PlaceMarker時,立即傳送標記事件。 |
此外,串流接收必須在完成狀態轉換時傳送下列事件:
- OnClockStart、 OnClockRestart: MEStreamSinkStarted 事件
- OnClockPause: MEStreamSinkPaused 事件
- OnClockStop: MEStreamSinkStopped 事件
正在結束
在傳遞最後一個範例之後,某些媒體接收需要額外的處理步驟。 此需求通常適用于封存接收,這必須將標頭或索引寫入檔案中。 如果媒體接收需要任何最終處理,則會公開 IMFFinalizableMediaSink 介面。
用戶端傳遞最後一個範例之後,用戶端會查詢此介面。 如果媒體接收支援 介面,用戶端會呼叫 IMFFinalizableMediaSink::BeginFinalize 以非同步方式執行最終處理。 此方法遵循標準 Media Foundation 非同步模型,如 非同步回呼方法中所述。 媒體接收可以假設用戶端會呼叫 BeginFinalize。 呼叫 BeginFinalize 失敗可能會導致撰寫錯誤的檔案。
關閉
當用戶端使用媒體接收完成時,用戶端會呼叫 IMFMediaSink::Shutdown。 在此方法中,媒體接收應該中斷任何迴圈參考計數。 一般而言,媒體接收與資料流程接收之間會有迴圈參考。
如果您使用事件佇列協助程式物件來實作 IMFMediaEventGenerator,請在事件佇列上呼叫 IMFMediaEventQueue::Shutdown 。 這個方法會關閉事件佇列,併發出目前正在等候事件的任何呼叫端發出訊號。
關閉之後,媒體接收上的所有方法都會傳回MF_E_SHUTDOWN,但 IUnknown 方法除外。
媒體接收介面
下表列出媒體接收可以透過 QueryInterface公開的標準介面。 媒體接收也可以公開自訂介面。
介面 | 描述 |
---|---|
IMFMediaSink | 媒體接收的主要介面。 (必要項。) |
IMFClockStateSink | 用來在簡報時鐘變更狀態時通知媒體接收。 (必要項。) |
IMFFinalizableMediaSink | 如果媒體接收必須執行最終處理步驟,請實作 。 (選擇性。) |
IMFGetService | 如果媒體接收公開任何服務介面,則實作 。 (選擇性。) |
IMFMediaEventGenerator | 實作媒體接收是否傳送任何事件。 (選擇性。) |
IMFMediaSinkPreroll | 如果媒體接收支援預先註冊,請實作 。 (選擇性。) |
IMFPresentationTimeSource | 如果媒體接收可以提供簡報時鐘的時間來源,則實作 。 (選擇性。) |
IMFQualityAdvise | 如果媒體接收可以調整播放品質,請實作 。 (選擇性。) |
選擇性地,媒體接收可以實作下列介面即服務。
服務介面 | 描述 |
---|---|
IMFRateSupport | 報告支援播放速率的範圍。 |
如需有關服務介面和 IMFGetService的詳細資訊,請參閱 服務介面。
資料流程接收介面
資料流程接收必須透過 QueryInterface公開下列介面。
介面 | 描述 |
---|---|
IMFStreamSink | 資料流程接收的主要介面。 (必要項。) |
IMFMediaEventGenerator | 佇列事件。 IMFStreamSink介面繼承此介面。 (必要項。) |
目前沒有針對資料流程接收定義任何服務介面。
串流接收事件
下表列出針對泛型資料流程接收定義的事件。 串流接收也可以傳送此處未列出的自訂事件。
事件 | 描述 |
---|---|
MEStreamSinkFormatChanged | 資料流程接收的媒體類型已不再有效。 (選擇性。) |
MEStreamSinkMarker | 已處理標記。 (必要項。) |
MEStreamSinkPaused | 資料流程接收已暫停。 (必要項。) |
MEStreamSinkPrerolled | 預先註冊已完成。 (選擇性。) |
MEStreamSinkRateChanged | 資料流程接收已變更播放速率。 (選擇性。) |
MEStreamSinkRequestSample | 要求新的範例。 (必要項。) |
MEStreamSinkScrubSampleComplete | 清除要求已完成。 (選擇性。) |
MEStreamSinkStarted | 資料流程接收已啟動。 (必要項。) |
MEStreamSinkStopped | 資料流程接收已停止。 (必要項。) |
目前沒有針對媒體接收定義一般用途的事件。 某些媒體接收可能會傳送自訂事件。
相關主題