Udostępnij przez


Wybieranie dekodera w usługach edycji DirectShow

[Funkcja skojarzona z tą stroną, DirectShow, jest starszą funkcją. Został zastąpiony przez MediaPlayer, IMFMediaEnginei Audio/Video Capture w Media Foundation. Te funkcje zostały zoptymalizowane pod kątem systemów Windows 10 i Windows 11. Firma Microsoft zdecydowanie zaleca, aby nowy kod używał MediaPlayer, IMFMediaEngine i Audio/Video Capture w programie Media Foundation zamiast DirectShow, jeśli to możliwe. Firma Microsoft sugeruje, że istniejący kod, który używa starszych interfejsów API, należy przepisać go do korzystania z nowych interfejsów API, jeśli to możliwe.]

[Ten interfejs API nie jest obsługiwany i może zostać zmieniony lub niedostępny w przyszłości.]

Gdy Usługi edycji DirectShow (DES) renderują projekt edycji wideo, silnik renderujący automatycznie wybiera niezbędne dekodery. Może się to zdarzyć wewnątrz metody IRenderEngine::ConnectFrontEnd lub w inny sposób dynamicznie podczas renderowania.

Użytkownik może zainstalować kilka dekodatorów, które mogą dekodować określony plik. Gdy dostępnych jest wiele dekodatorów, des używa algorytmu Intelligent Connect do wybrania dekodera.

Nie ma możliwości, aby aplikacja określała bezpośrednio, który dekoder ma być używany. Można jednak wybrać dekoder pośrednio za pomocą interfejsu wywołania zwrotnego IAMGraphBuilderCallback. Implementując ten interfejs w aplikacji, można otrzymywać powiadomienia podczas procesu tworzenia grafu i odrzucać niektóre filtry z grafu.

Zacznij od zaimplementowania klasy, która uwidacznia interfejs IAMGraphBuilderCallback:

class GraphBuilderCB : public IAMGraphBuilderCallback
{
public:
     // Method declarations (not shown).
};

Następnie utwórz instancję menedżera grafu filtrów i zarejestruj swoją klasę, aby otrzymywać powiadomienia zwrotne:

// 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);
}

Następnie utwórz silnik renderujący i wywołaj metodę IRenderEngine::SetFilterGraph, przekazując wskaźnik do Menedżera Grafu Filtrów. Gwarantuje to, że Silnik Renderowania nie tworzy własnego Menedżera Filtrów Graficznych, lecz zamiast tego używa instancji skonfigurowanej dla wywołań zwrotnych.

CComPtr<IRenderEngine> pRender;
hr = pRender.CoCreateInstance(CLSID_RenderEngine);
if (FAILED(hr))
{
    // Handle error (not shown).
}

hr = pRender->SetFilterGraph(pGraph);

Gdy projekt jest renderowany, metoda IAMGraphBuilderCallback::SelectedFilteraplikacjijest wywoływana bezpośrednio przed utworzeniem nowego filtru przez Menedżera grafu filtrów. Metoda SelectedFilter odbiera wskaźnik do interfejsu IMoniker, który reprezentuje moniker filtru. Sprawdź moniker, a jeśli zdecydujesz się odrzucić filtr, zwróć kod błędu z metody SelectedFilter.

Trudną częścią jest zidentyfikowanie, które monikery reprezentują dekodery — a w szczególności, które monikery reprezentują dekodery, które chcesz odrzucić. Jedno rozwiązanie jest następujące:

  • Przed renderowaniem projektu użyj metody IFilterMapper2::EnumMatchingFilters, aby utworzyć listę filtrów zarejestrowanych jako akceptowanie żądanego typu danych wejściowych. W przypadku typów kompresji wideo lub audio ta lista powinna być mapowana na zestaw dekodatorów.

  • Metoda EnumMatchingFilters zwraca kolekcję monikerów. Dla każdego monikera w kolekcji pobierz właściwość DisplayName zgodnie z opisem w Using the Filter Mapper.

  • Zapisz listę nazw wyświetlanych, ale pomiń nazwę wyświetlaną zgodną z filtrem, którego chcesz użyć do dekodowania. Nazwy wyświetlane filtrów oprogramowania mają następującą postać:

    OLESTR("@device:sw:{CategoryGUID}\{FilterCLSID}");
    

    gdzie

    CategoryGUID
    

    jest identyfikatorem GUID kategorii filtru i

    FilterCLSID
    

    to identyfikator CLSID filtru. W przypadku DMO format jest taki sam, ale zmień sw na dmo.

    Lista zawiera teraz nazwy wyświetlane dla każdego filtra, który generuje żądany typ mediów, ale nie jest Twoim preferowanym filtrem.

  • W metodzie SelectedFilter pobierz właściwość DisplayName i sprawdź ją względem przechowywanej listy. Jeśli nazwa wyświetlana jest zgodna z wpisem na liście, odrzuć ten filtr. W przeciwnym razie zaakceptuj go, zwracając S_OK.

renderowanie projektu