Como os decodificadores usam o IAMVideoAccelerator
[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.]
A interface IAMVideoAccelerator permite operações genéricas de aceleração de vídeo, incluindo a ACELERAção de Vídeo (VA) do DirectX. Para aceleração de VA não DirectX, o decodificador e o driver de vídeo devem aderir a um protocolo comum.
Esta seção descreve a ordem geral das operações que qualquer decodificador deve seguir ao usar essa interface. Mais informações específicas para decodificadores baseados em VA do DirectX podem ser encontradas em Mapeamento de Aceleração de Vídeo DirectX para IAMVideoAccelerator.
Observação
Essa interface está disponível no Windows 2000 e posterior.
A interface IAMVideoAccelerator é exposta no pino de entrada do Mixer de Sobreposição ou do VMR (Renderizador de Combinação de Vídeo). A interface IAMVideoAcceleratorNotify é exposta no pin de saída do decodificador. A sequência de eventos para conectar os pinos de filtro é a seguinte:
O Gerenciador de Grafo de Filtro chama IPin::Connect no pino de saída do filtro de decodificador. Um AM_MEDIA_TYPE é um parâmetro opcional.
- AM_MEDIA_TYPE é uma estrutura de dados que descreve um tipo de mídia. Ele contém um GUID de tipo principal (que, em nosso caso, deve ser MEDIATYPE_Video), um GUID de subtipo (que, em nosso caso, deve ser um GUID de acelerador de vídeo) e uma variedade de outras coisas. Uma dessas coisas é um GUID de tipo de formato que contém informações sobre a mídia, incluindo, em nosso caso, a largura e a altura de uma imagem de vídeo descompactada, provavelmente em uma estrutura MPEG1VIDEOINFO, VIDEOINFOHEADER, MPEG2VIDEOINFO ou VIDEOINFOHEADER2 .
- A estrutura AM_MEDIA_TYPE , se presente, instrui o decodificador a operar usando o tipo de mídia especificado, que pode ser "totalmente especificado" ou "parcialmente especificado". Se "totalmente especificado", o decodificador normalmente simplesmente tentaria operar com esse tipo de mídia. Se for "parcialmente especificado", ele tentará encontrar um modo de operação compatível "totalmente especificado" que possa ser usado para se conectar de maneira consistente com o tipo de mídia "parcialmente especificado".
- A maneira comum de tentar localizar um tipo de mídia "totalmente especificado" a ser usado para uma conexão é simplesmente executar uma lista de cada tipo de mídia "totalmente especificado" que o pino de saída dá suporte, que é compatível com o tipo de mídia "parcialmente especificado" e tentar se conectar com cada um deles até ser bem-sucedido. O processo normalmente seria semelhante se nenhuma AM_MEDIA_TYPE estivesse contida na chamada IPin::Connect, mas com o pino de saída precisando marcar todos os seus tipos de mídia.
Se o decodificador quiser marcar se um AM_MEDIA_TYPE específico (incluindo um GUID do acelerador de vídeo) tem suporte pelo pino de entrada downstream, ele pode chamar iPin::QueryAccept desse pino (com o GUID do acelerador de vídeo como o subtipo do AM_MEDIA_TYPE) ou simplesmente tentar se conectar a esse pino, conforme descrito no item 5 abaixo.
Se o decodificador não souber quais GUIDs de acelerador de vídeo o pino de entrada downstream dá suporte e não deseja propor apenas algum GUID de acelerador de vídeo candidato específico chamando IPin::QueryAccept do pino de entrada downstream, o decodificador pode chamar IAMVideoAccelerator::GetVideoAcceleratorGUIDs para obter uma lista dos GUIDs do acelerador de vídeo compatíveis com o pino.
Para alguns GUIDs específicos do acelerador de vídeo, o decodificador pode chamar o IAMVideoAccelerator::GetUncompFormatsSupported do pino de entrada downstream para obter uma lista dos formatos de pixel DDPIXELFORMAT que podem ser usados para renderizar um GUID específico do acelerador de vídeo. A lista retornada deve ser considerada em ordem de preferência decrescente (ou seja, com o formato mais preferencial listado primeiro).
O decodificador chama o IPin::ReceiveConnection do pino de entrada downstream, passando-lhe um AM_MEDIA_TYPE com o GUID do acelerador de vídeo adequado como o subtipo do tipo de mídia. Isso configura a conexão para a operação, incluindo a criação das superfícies de saída descompactadas (que são alocadas usando a largura e a altura encontradas em AM_MEDIA_TYPE e o número de superfícies a serem alocadas encontradas por uma chamada descrita abaixo e quaisquer outras informações que o acelerador de vídeo tenha disponível e deseje usar para essa finalidade, como o próprio GUID do acelerador de vídeo). Se o pino de entrada downstream rejeitar o GUID do acelerador de vídeo ou algum outro aspecto da conexão, isso poderá causar falha no IPin::ReceiveConnection . Se IPin::ReceiveConnection falhar, isso será indicado em um HRESULT retornado e o decodificador poderá tentar fazer a chamada novamente, por exemplo, com um novo GUID de acelerador de vídeo na estrutura AM_MEDIA_TYPE .
[!Observação]
Essa é outra maneira (e a maneira mais definitiva) para o decodificador determinar o que é compatível com o pin de entrada downstream— simplesmente chamando IPin::ReceiveConnection e tentando se conectar e verificando se a tentativa de conexão foi bem-sucedida.
Durante o IPin::ReceiveConnection, o renderizador chama o IAMVideoAcceleratorNotify::GetUncompSurfacesInfo do decodificador, passando-lhe o GUID do acelerador de vídeo e uma estrutura AMVAUncompBufferInfo , a fim de descobrir quantas superfícies não compactadas alocar. O decodificador preenche e retorna a estrutura , que contém o número mínimo e máximo de superfícies a serem alocadas do tipo específico e uma estrutura DDPIXELFORMAT que descreve o formato de pixel das superfícies a serem alocadas.
[!Observação]
Na verdade, nada é passado para o decodificador na chamada para IAMVideoAcceleratorNotify::GetUncompSurfacesInfo diferente do GUID do acelerador de vídeo.
O renderizador chama o IAMVideoAcceleratorNotify::SetUncompSurfacesInfo do decodificador, passando para o decodificador o número real de superfícies descompactadas alocadas.
O renderizador chama IAMVideoAcceleratorNotify::GetCreateVideoAcceleratorData do decodificador para obter os dados necessários para inicializar o acelerador de vídeo.
O decodificador chama IAMVideoAccelerator::GetCompBufferInfo, passando-lhe um GUID de acelerador de vídeo, uma estrutura AMVAUncompDataInfo e o número de tipos de buffer compactados, para obter em troca um conjunto de estruturas de dados AMVACompBufferInfo , uma correspondente a cada tipo de buffer de dados compactado usado pelo GUID do acelerador de vídeo.
- A estrutura AMVAUncompDataInfo contém a largura e a altura dos dados descompactados decodificados (em pixels) e o DDPIXELFORMAT da imagem descompactada.
- As estruturas de dados AMVACompBufferInfo retornadas contêm:
O número de buffers compactados necessários para o tipo específico.
A largura e a altura da superfície a ser criada (campos que podem ou não ter qualquer significado real).
Observação
A operação de alocação de superfície do DirectDraw para os buffers compactados não fornece atualmente que a largura ou altura dessas superfícies seja maior ou igual a 2^15, embora a chamada de alocação de superfície não falhe de forma excessiva se esse limite for violado. Portanto, o driver pode estruturar suas solicitações de memória de buffer compactada para evitar tamanhos extremos. Por exemplo, em vez de solicitar um buffer com width="1" e height="65536", o driver deve solicitar um buffer de width="1024" e height="64".
O número total de bytes a serem usados pela superfície.
Uma estrutura do tipo DDSCAPS2 que define um objeto DirectDrawSurface, descrevendo os recursos para criar superfícies para armazenar dados compactados.
Um DDPIXELFORMAT, descrevendo o formato de pixel usado para criar superfícies para armazenar dados compactados (um campo que pode ou não ter qualquer significado real).
Observação
As chamadas do renderizador para alguns dos métodos de interface IAMVideoAcceleratorNotify do decodificador podem (e normalmente ocorreriam) dentro da chamada do decodificador para iPin::ReceiveConnection do renderizador. Especificamente, isso se aplica ao seguinte:
Observação
Para dar suporte a alterações de formato dinâmico, o decodificador também pode chamar IPin::ReceiveConnection e outros métodos por acima enquanto os filtros estão conectados e em execução. Essa funcionalidade é fornecida para dar suporte a alterações de formato dinâmico (embora não no H.263, Anexo P, sensor – como todos os conjuntos de dados são iniciados novamente do zero e qualquer informação de imagem de referência é, portanto, perdida).
Veja a seguir uma descrição do uso de IAMVideoAccelerator durante a operação após a inicialização:
Para cada superfície descompactada, o decodificador chama IAMVideoAccelerator::BeginFrame para iniciar o processamento para criar a imagem de saída. Quando ele faz isso, o decodificador envia uma estrutura AMVABeginFrameInfo .
A estrutura AMVABeginFrameInfo contém um índice para um buffer de destino, um ponteiro para alguns dados a serem enviados downstream e um ponteiro para um local onde o acelerador pode colocar alguns dados para o decodificador ler.
OBSERVAÇÃO 1: o acelerador realmente não recebe o índice de buffer de destino, pois é traduzido pelo renderizador antes de ir para baixo.
OBSERVAÇÃO 2: IAMVideoAccelerator::BeginFrame pode ser chamado mais de uma vez entre chamadas para IAMVideoAccelerator::EndFrame.
OBSERVAÇÃO 3: não há nenhuma suposição na operação de interface de que IAMVideoAccelerator::BeginFrame e IAMVideoAccelerator::EndFrame precisem ser chamados para o processamento de cada imagem individual no bitstream.
O que IAMVideoAccelerator::BeginFrame faz, no que diz respeito à interface, é criar uma associação dentro do renderizador entre um índice e uma superfície descompactada. Ele também fornece um meio de chamar uma função específica em um driver de dispositivo (com suporte de um meio de passar dados arbitrários entre o decodificador e o driver do dispositivo).
(No entanto, na operação directx va há um requisito descrito abaixo que IAMVideoAccelerator::BeginFrame e IAMVideoAccelerator::EndFrame precisam ser chamados para o processamento de cada imagem individual no bitstream.)
Para enviar dados descompactados para o acelerador, o decodificador chama:
- IAMVideoAccelerator::QueryRenderStatus para determinar se um buffer é seguro para leitura ou gravação.
- IAMVideoAccelerator::GetBuffer para bloquear e obter acesso a um buffer especificado (se ele não tiver chamado isso anteriormente para obter esse acesso). GetBuffer também pode ser usado para obter uma cópia do conteúdo da última imagem de saída descompactada para a qual IAMVideoAccelerator::BeginFrame foi chamado, fornecendo que IAMVideoAccelerator::EndFrame não foi chamado para esse índice de buffer de destino. Se a DDI retornar uma status de renderização de DDERR_WASSTILLDRAWING para o buffer solicitado, um loop de suspensão será operado no GetBuffer até que essa condição seja desmarcada. Para chamar GetBuffer, o decodificador precisará de algumas informações de uma estrutura de dados AMVACompBufferInfo que é obtida chamando IAMVideoAccelerator::GetCompBufferInfo.
- IAMVideoAccelerator::Execute para indicar que os dados em um conjunto de buffers compactados, conforme indicado em uma matriz de estruturas de dados AMVABUFFERINFO , devem ser processados. Um código de função dwFunction é passado para o driver nesta chamada. Um ponteiro lpPrivateInputData também é passado para alguns dados para enviar downstream e um ponteiro lpPrivateOutputData é passado para um local onde o processo downstream pode colocar alguns dados para o decodificador ler.
- IAMVideoAccelerator::ReleaseBuffer para indicar que o decodificador concluiu o uso de um buffer especificado por enquanto e não precisa mais de acesso bloqueado ao buffer. (Se o decodificador quiser continuar a usar o buffer, ele simplesmente não poderá chamar IAMVideoAccelerator::ReleaseBuffer por enquanto, evitando a necessidade de chamar IAMVideoAccelerator::GetBuffer até que ele realmente pretenda não usar mais o buffer.) O decodificador não deve gravar no buffer depois que Execute for chamado até que QueryRenderStatus indique que o buffer é seguro para gravação.
Para concluir o processamento de saída para um buffer de destino, o decodificador chama IAMVideoAccelerator::EndFrame. Ele pode passar alguns dados arbitrários downstream com essa chamada, e isso é essencialmente tudo o que acontece como resultado dessa chamada. Ele não envia um índice de buffer de destino nesta chamada, portanto, ele não pode indicar ao acelerador precisamente qual buffer de destino foi concluído, a menos que essa indicação esteja contida nos dados arbitrários que são passados.
Para exibir um quadro, o decodificador chama IAMVideoAccelerator::D isplayFrame com o índice do quadro a ser exibido e uma estrutura IMediaSample contendo carimbos de data/hora de início e parada e sinalizadores relevantes, como dwTypeSpecificFlags na estrutura AM_SAMPLE2_PROPERTIES e dwInterlaceFlags na estrutura VIDEOINFOHEADER2 . O decodificador deve verificar se todas as operações de descompactação que afetam o conteúdo do quadro foram concluídas antes de chamar DisplayFrame.
Por fim, o decodificador deve, após a conclusão de todo o processamento, indicar a conclusão de todos os quadros de saída iniciados restantes chamando IAMVideoAccelerator::EndFrame e liberar todos os seus buffers bloqueados chamando IAMVideoAccelerator::ReleaseBuffer para cada buffer não lançado.
Tópicos relacionados