樣本和分配器
[與此頁面相關聯的功能,DirectShow是舊版功能。 它已被 MediaPlayer、IMFMediaEngine,以及在媒體基金會中的音訊/視訊擷取取代。 這些功能已針對 Windows 10 和 Windows 11 進行優化。 Microsoft強烈建議新程式代碼盡可能在媒體 基礎中使用 MediaPlayer、IMFMediaEngine 和 音訊/視訊擷取,而不是 DirectShow。 Microsoft建議使用舊版 API 的現有程式代碼,盡可能改寫成使用新的 API。]
當針腳將媒體數據傳送到另一個針腳時,它不會將直接的指標傳遞到記憶體緩衝區。 相反地,它會將指標傳遞給管理記憶體的 COM 物件。 這個對象稱為 媒體範例,會公開 IMediaSample 介面。 接收針腳會呼叫 IMediaSample 方法來存取記憶體緩衝區,例如 IMediaSample::GetPointer、IMediaSample::GetSize和 IMediaSample::GetActualDataLength。
樣本總是從輸出針腳流向輸入針腳。 在推送模型中,輸出接點透過在輸入接點上調用 IMemInputPin::Receive 來傳遞範例。 輸入引腳會同步處理數據(亦即,完全在 Receive 方法內),或於工作線程上以異步方式處理數據。 如果輸入引腳需要等候資源,則允許在 Receive 方法內阻塞。
另一個稱作 配置器的 COM 物件負責創建和管理媒體樣本。 配置器會公開 IMemAllocator 介面。 每當篩選需要具有空白緩衝區的媒體範例時,它會呼叫 IMemAllocator::GetBuffer 方法,此方法會傳回範例的指標。 每個接腳連線都會共用一個配置器。 當兩個接腳連接時,他們會決定哪個過濾器提供配置器。 接腳也會在指派器上設定屬性,例如緩衝區的數量和每個緩衝區的大小。 (如需詳細資訊,請參閱 篩選如何連接 和 交涉配置器。
下圖顯示配置器、媒體範例和篩選之間的關聯性。
媒體樣本參考計數
分配器會建立有限的樣本池。 您可以隨時使用某些範例,而其他範例則可用於 GetBuffer 呼叫。 配置器會使用參考計數來追蹤樣本。 GetBuffer 方法會傳回參考計數為 1 的範例。 如果參考計數歸零,樣本會回到配置器的資源池中,並能在下一個 GetBuffer 呼叫中被使用。 只要參考計數維持在零以上,樣本就無法使用 GetBuffer。 如果屬於配置器的每個樣本都正在使用中,GetBuffer 方法會封鎖,直到樣本變成可用為止。
例如,假設輸入引腳會收到樣本。 如果它同步處理範例,則在 Receive 方法內,不會遞增參考計數。 Receive 傳回之後,輸出針腳會釋放範例、參考計數會移至零,而範例會傳回配置器的集區。 另一方面,如果輸入 pin 在背景工作執行緒上處理範例,它會在離開 Receive 方法之前先遞增參考計數。 參考計數現在是 2。 當輸出接腳釋放範例時,計數會移至 1,範例尚未返回集區。 工作線程使用範例完成後,它會呼叫 Release 來釋放該範例。 現在樣本會返回池中。
當接腳收到樣本時,可以將數據複製到另一個樣本,或者可以修改原始樣本,並將該樣本傳遞給下一個過濾器。 樣本可能會遍歷整個圖表的長度,每個篩選器依次呼叫 AddRef 和 Release。 因此,輸出針腳絕對不能在呼叫 Receive後再次使用樣本,因為下游過濾器可能會使用該樣本。 輸出針腳必須一律呼叫 GetBuffer,才能取得新的樣本。
此機制可減少記憶體配置量,因為篩選條件會重複使用相同的緩衝區。 它也可防止篩選意外寫入尚未處理的數據,因為配置器會維護可用範例的清單。
過濾器可以對輸入和輸出使用不同的配置器。 如果它展開輸入數據,它可能會執行此動作(例如,藉由解壓縮它)。 如果輸出不大於輸入,過濾器可能會就地處理數據,而不需將其複製到新的樣本。 在此情況下,兩個以上的針腳連線可以共用一個分配器。
認可和取消認可配置器
當篩選第一次建立配置器時,配置器並未保留任何記憶體緩衝區。 此時,任何對 GetBuffer方法的 呼叫都會失敗。 串流啟動時,輸出腳位會呼叫 IMemAllocator::Commit,這會啟用記憶體分配器,導致它分配記憶體。 針腳現在可以呼叫 GetBuffer。
當串流停止時,引腳會呼叫 IMemAllocator::Decommit,這會取消配置此分配器。 所有後續呼叫 GetBuffer 都會失敗,直到配置器再次認可為止。 此外,如果目前任何對 GetBuffer 的呼叫因等待樣本而被封鎖,它們就會立即傳回失敗碼。 視實作而定,Decommit 方法可能或可能不會釋放記憶體。 例如,CMemAllocator 類別會等到其解構函式方法釋放記憶體為止。
相關主題
-
篩選圖表中的 數據流