Compartilhar via


Selecionando um decodificador nos Serviços de Edição do DirectShow

[O recurso associado a esta página, DirectShow, é um recurso herdado. Foi substituído por MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda fortemente que o novo código use MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation em vez de DirectShow, quando possível. A Microsoft sugere que o código existente que usa as APIs herdadas seja reescrito para usar as novas APIs, se possível.]

[Não há suporte para essa API e pode ser alterada ou indisponível no futuro.]

Quando o DirectShow Editing Services (DES) renderiza um projeto de edição de vídeo, o Mecanismo de Renderização seleciona automaticamente os decodificadores necessários. Isso pode acontecer dentro do método IRenderEngine::ConnectFrontEnd ou dinamicamente durante a renderização.

Um usuário pode instalar vários decodificadores capazes de decodificar um arquivo específico. Quando vários decodificadores estão disponíveis, o DES usa o algoritmo Intelligent Connect para selecionar o decodificador.

Não há como o aplicativo especificar diretamente qual decodificador usar. No entanto, você pode escolher o decodificador indiretamente por meio da interface de retorno de chamada IAMGraphBuilderCallback . Ao implementar essa interface em seu aplicativo, você pode receber notificações durante o processo de criação de grafo e rejeitar determinados filtros do grafo.

Comece implementando uma classe que expõe a interface IAMGraphBuilderCallback :

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

Em seguida, crie uma instância do Gerenciador de Grafo de Filtro e registre sua classe para receber notificações de retorno de chamada:

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

Em seguida, crie o Mecanismo de Renderização e chame o método IRenderEngine::SetFilterGraph com um ponteiro para o Gerenciador de Gráficos de Filtro. Isso garante que o Mecanismo de Renderização não crie seu próprio Gerenciador de Grafo de Filtro, mas usa a instância que você configurou para retornos de chamada.

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

hr = pRender->SetFilterGraph(pGraph);

Quando o projeto é renderizado, o método IAMGraphBuilderCallback::SelectedFilter do aplicativo é chamado imediatamente antes que o Gerenciador de Grafo de Filtro crie um novo filtro. O método SelectedFilter recebe um ponteiro para uma interface IMoniker que representa um moniker para o filtro. Examine o moniker e, se você decidir rejeitar o filtro, retorne um código de falha do método SelectedFilter .

A parte difícil é identificar quais monikers representam decodificadores — e, em particular, quais monikers representam decodificadores que você deseja rejeitar. Uma solução é a seguinte:

  • Antes de renderizar o projeto, use o método IFilterMapper2::EnumMatchingFilters para criar uma lista de filtros registrados como aceitando o tipo de entrada desejado. Para tipos de compactação de áudio ou vídeo, essa lista deve ser mapeada para um conjunto de decodificadores.

  • O método EnumMatchingFilters retorna uma coleção de monikers. Para cada moniker na coleção, obtenha a propriedade DisplayName , conforme descrito em Usando o Mapeador de Filtro.

  • Armazene uma lista dos nomes de exibição, mas omita o nome de exibição que corresponde ao filtro que você deseja usar para decodificação. Os nomes de exibição para filtros de software têm o seguinte formato:

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

    onde

    CategoryGUID
    

    é o GUID da categoria de filtro e

    FilterCLSID
    

    é o CLSID do filtro. Para DMOs, o formato é o mesmo, mas é alterado sw para dmo.

    A lista agora contém nomes de exibição para cada filtro que gera o tipo de mídia desejado, mas não é o filtro preferencial.

  • No método SelectedFilter, obtenha a propriedade DisplayName no moniker proposto e marcar-a na lista armazenada. Se o nome de exibição corresponder a uma entrada na lista, rejeite esse filtro. Caso contrário, aceite-o retornando S_OK.

Renderizando um projeto