在 DirectShow 編輯服務中選取譯碼器
[與此頁面相關聯的功能,DirectShow是舊版功能。 它已被 MediaPlayer、IMFMediaEngine和媒體基金會中的音訊/視訊擷取 取代。 這些功能已針對 Windows 10 和 Windows 11 進行優化。 Microsoft強烈建議新程式代碼盡可能在媒體 基礎中使用 MediaPlayer、IMFMediaEngine 和 音訊/視訊擷取,而不是 DirectShow。 Microsoft建議使用舊版 API 的現有程式代碼,盡可能改寫成使用新的 API。]
[此 API 不受支持,未來可能會改變或無法使用。]
DirectShow 編輯服務 (DES) 轉譯視訊編輯專案時,轉譯引擎會自動選取必要的譯碼器。 這可能會在 IRenderEngine::ConnectFrontEnd 方法內發生,或在轉譯期間動態發生。
使用者可能會安裝數個能夠譯碼特定檔案的譯碼器。 當有多個譯碼器可用時,DES 會使用 Intelligent Connect 演演算法來選取譯碼器。
應用程式無法直接指定要使用的譯碼器。 不過,您可以透過 IAMGraphBuilderCallback 回呼介面間接選擇譯碼器。 藉由在應用程式中實作此介面,您可以在圖形建置程式期間收到通知,並拒絕來自圖形的特定篩選。
首先,實作公開 IAMGraphBuilderCallback 介面的類別:
class GraphBuilderCB : public IAMGraphBuilderCallback
{
public:
// Method declarations (not shown).
};
然後建立 Filter Graph 管理員的實例,並註冊類別以接收回呼通知:
// Declare an instance of the callback object.
GraphBuilderCB GraphCB;
// Create the Filter Graph Manager.
CComPtr<IGraphBuilder> pGraph;
hr = pGraph.CoCreateInstance(CLSID_FilterGraph);
if (FAILED(hr))
{
// Handle error (not shown).
}
// Register to receive the callbacks.
CComQIPtr<IObjectWithSite> pSite(pGraph);
if (pSite)
{
hr = pSite->SetSite((IUnknown*)&GraphCB);
}
接下來,建立轉譯引擎,並使用篩選圖形管理員的指標呼叫 IRenderEngine::SetFilterGraph 方法。 這可確保 Render 引擎不會建立自己的 Filter Graph 管理器,而是改用您已配置用於回呼的實例。
CComPtr<IRenderEngine> pRender;
hr = pRender.CoCreateInstance(CLSID_RenderEngine);
if (FAILED(hr))
{
// Handle error (not shown).
}
hr = pRender->SetFilterGraph(pGraph);
轉譯專案時,應用程式 IAMGraphBuilderCallback::SelectedFilter 方法會在 Filter Graph Manager 建立新的篩選之前立即呼叫。 SelectedFilter 方法會接收 IMoniker 介面的指標,該介面代表篩選的 Moniker。 檢查代號,如果您決定拒絕篩選,請從 SelectedFilter 方法傳回失敗碼。
困難的部分在於識別哪些代號代表譯碼器,特別是哪些代號代表那些您希望拒絕的譯碼器。 其中一個解決方案如下:
在轉譯專案之前,請使用 IFilterMapper2::EnumMatchingFilters 方法來建立註冊為接受所需輸入類型的篩選清單。 針對視訊或音訊壓縮類型,此列表應該對應至一組譯碼器。
EnumMatchingFilters 方法會傳回一個標識集合。 針對集合中的每個Moniker,取得 DisplayName 屬性,如使用篩選對應程式 中所述。
儲存顯示名稱的清單,但省略符合您要用於譯碼之篩選的顯示名稱。 軟體篩選的顯示名稱的格式如下:
OLESTR("@device:sw:{CategoryGUID}\{FilterCLSID}");
哪裡
CategoryGUID
是篩選類別的 GUID,而
FilterCLSID
是篩選器的 CLSID。 對於 DMO,格式相同,但將
sw
變更為dmo
。現在,此清單包含了輸出所需媒體類型但並非您偏好的篩選器中的每一個篩選器的顯示名稱。
在 SelectedFilter 方法中,取得在建議 moniker 上的 DisplayName 屬性,然後針對預存清單檢查它。 如果顯示名稱符合清單中的專案,請拒絕該篩選。 否則,返回 S_OK 以接受。
相關主題