Definindo tipos de mídia em um DMO

[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.]

Antes que um DMO possa processar qualquer dado, o cliente deve definir o tipo de mídia para cada fluxo. (Há uma pequena exceção a essa regra; consulte Fluxos opcionais.) Para localizar o número de fluxos, chame o método IMediaObject::GetStreamCount :

DWORD cInput = 0, cOutput = 0;
pDMO->GetStreamCount(&cInput, &cOutput);

Esse método retorna dois valores, o número de entradas e o número de saídas. Esses valores são fixos durante o tempo de vida do DMO.

Tipos preferenciais

Para cada fluxo, o DMO atribui uma lista de tipos de mídia possíveis, em ordem de preferência. Por exemplo, os tipos preferenciais podem ser RGB de 32, RGB de 24 bits e RGB de 16 bits nessa ordem. Quando o cliente define os tipos de mídia, ele pode usar essas listas como uma dica. Para recuperar um tipo preferencial para um fluxo, chame o método IMediaObject::GetInputType ou o método IMediaObject::GetOutputType . Especifique o número de fluxo e um valor de índice para o tipo (começando de zero). Por exemplo, o código a seguir recupera o primeiro tipo preferencial do primeiro fluxo de entrada:

DMO_MEDIA_TYPE mt
hr = pDMO->GetInputType(0, 0, &mt)
if (SUCCEEDED(hr))
{
    // Examine this media type (not shown).
    /* ... */

    // Free the format block.
    MoFreeMediaType(&mt);
}

Para enumerar todos os tipos de mídia preferenciais em um determinado fluxo, use um loop que incremente o índice de tipo até que o método retorne DMO_E_NO_MORE_ITEMS, conforme mostrado no exemplo a seguir:

DMO_MEDIA_TYPE mt;
DWORD dwType = 0;
while (hr = pDMO->GetInputType(0, dwType, &mt), SUCCEEDED(hr))
{
    // Examine this media type (not shown).
    /* ... */

    // Free the format block.
    MoFreeMediaType(&mt);
    ++dwType;
}

Você deve observar os seguintes pontos sobre tipos preferenciais:

  • O DMO pode retornar um tipo que não tem nenhum bloco de formato. Por exemplo, um DMO poderia especificar um tipo de vídeo, como RGB de 24 bits, sem fornecer a largura e a altura da imagem. No entanto, ao definir o tipo, você deve fornecer um bloco de formato completo. (Alguns tipos de mídia, como MIDI, nunca exigem um bloco de formato; nesse caso, esse comentário não se aplica.)
  • O DMO não é necessário para dar suporte a cada combinação de tipos preferenciais que retorna. Por exemplo, se um DMO tiver dois fluxos e cada fluxo tiver quatro tipos preferenciais, haverá 16 combinações possíveis, mas nem todas têm a garantia de serem válidas.
  • Quando o cliente define o tipo de mídia para um fluxo, o DMO pode atualizar os tipos preferenciais para outros fluxos para refletir o novo estado. No entanto, não é necessário fazê-lo.
  • Para alguns fluxos, o DMO pode não oferecer nenhum tipo preferencial. Normalmente, um DMO deve oferecer pelo menos alguns tipos preferenciais em alguns fluxos.
  • O DMO não é necessário para oferecer uma lista completa dos tipos de mídia que ele pode aceitar. Pode haver tipos "não convertidos" aos quais o DMO dá suporte, mas não oferece como tipos preferenciais.

Em suma, o cliente deve tratar os tipos preferenciais apenas como diretrizes. A única maneira de saber com certeza quais tipos têm suporte é testá-los, conforme descrito na próxima seção.

Definindo o tipo de mídia em um fluxo

Use os métodos IMediaObject::SetInputType e IMediaObject::SetOutputType para definir o tipo para cada fluxo. Você deve fornecer uma estrutura DMO_MEDIA_TYPE que contenha uma descrição completa do tipo de mídia. O exemplo a seguir define o tipo de mídia no fluxo de entrada 0, usando áudio PCM estéreo de 16 bits de 44,1 kHz:

DMO_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(DMO_MEDIA_TYPE));
// Allocate memory for the format block.
HRESULT hr = MoInitMediaType(&mt, sizeof(WAVEFORMATEX));
if (SUCCEEDED(hr))
{
    // Set the type GUIDs.
    mt.majortype  = MEDIATYPE_Audio;
    mt.subtype    = MEDIASUBTYPE_PCM;
    mt.formattype = FORMAT_WaveFormatEx;

    // Initialize the format block.
    WAVEFORMATEX *pWave = reinterpret_cast<WAVEFORMATEX*>(mt.pbFormat);
    pWave->wFormatTag = WAVE_FORMAT_PCM;
    pWave->nChannels = 2;
    pWave->nSamplesPerSec = 44100;
    pWave->wBitsPerSample = 16;
    pWave->nBlockAlign = (pWave->nChannels * pWave->wBitsPerSample) / 8;
    pWave->nAvgBytesPerSec = pWave->nSamplesPerSec * pWave->nBlockAlign;
    pWave->cbSize = 0;

    // Set the media type.
    hr = pDMO->SetInputType(0, &mt, 0); 

    // Release the format block.
    MoFreeMediaType(&mt);
}

Para testar um tipo de mídia sem defini-lo, chame SetInputType ou SetOutputType com o sinalizador DMO_SET_TYPEF_TEST_ONLY. O método retornará S_OK se o tipo for aceitável ou S_FALSE caso contrário:

if (S_OK == pDMO->SetInputType(0, &mt, DMO_SET_TYPEF_TEST_ONLY)
{
    // Media type is OK.
}

Como as configurações em um fluxo podem afetar outro fluxo, talvez seja necessário limpar o tipo de mídia de um fluxo. Para fazer isso, chame SetInputType ou SetOutputType com o sinalizador DMO_SET_TYPEF_CLEAR.

Para um DMO de decodificador, o cliente normalmente definiria o tipo de entrada primeiro e, em seguida, escolheria um tipo de saída. Para um DMO do codificador, o cliente definiria o tipo de saída primeiro e, em seguida, o tipo de entrada.

Hospedar diretamente um DMO