Поделиться через


Настройка типов мультимедиа в DMO

[Функция, связанная с этой страницей DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngine, и аудио/ видео захвата в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует использовать в новом коде MediaPlayer, IMFMediaEngine и аудио/видеозахват в Media Foundation вместо DirectShow, когда это возможно. Корпорация Майкрософт предлагает переписать существующий код, в котором используются устаревшие API, чтобы по возможности использовать новые API.]

Прежде чем DMO сможет обработать какие-либо данные, клиент должен задать тип носителя для каждого потока. (Существует одно незначительное исключение из этого правила. См. дополнительные потоки.) Чтобы найти количество потоков, вызовите метод IMediaObject::GetStreamCount :

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

Этот метод возвращает два значения: количество входных и выходных данных. Эти значения являются фиксированными для времени существования объекта DMO.

Предпочтительные типы

Для каждого потока DMO назначает список возможных типов мультимедиа в порядке предпочтения. Например, предпочтительными типами могут быть 32-RGB, 24-разрядные RGB и 16-разрядные RGB в этом порядке. Когда клиент задает типы мультимедиа, он может использовать эти списки в качестве указания. Чтобы получить предпочтительный тип для потока, вызовите метод IMediaObject::GetInputType или метод IMediaObject::GetOutputType . Укажите номер потока и значение индекса для типа (начиная с нуля). Например, следующий код извлекает первый предпочтительный тип из первого входного потока:

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

Чтобы перечислить все предпочтительные типы мультимедиа в заданном потоке, используйте цикл, который увеличивает индекс типа, пока метод не вернет DMO_E_NO_MORE_ITEMS, как показано в следующем примере:

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

Обратите внимание на следующие моменты о предпочтительных типах:

  • DMO может возвращать тип без блока форматирования. Например, объект DMO может указать тип видео, например 24-разрядный RGB, не указывая ширину и высоту изображения. Однако при установке типа необходимо предоставить полный блок форматирования. (Для некоторых типов мультимедиа, таких как MIDI, никогда не требуется блок формата. В этом случае это замечание не применяется.)
  • DMO не требуется для поддержки всех сочетаний предпочтительных типов, которые он возвращает. Например, если объект DMO содержит два потока и каждый из них имеет четыре предпочтительных типа, существует 16 возможных сочетаний, но не все из них гарантированно являются допустимыми.
  • Когда клиент задает тип мультимедиа для одного потока, DMO может обновить предпочтительные типы для других потоков, чтобы отразить новое состояние. Однако это не требуется.
  • Для некоторых потоков DMO может не предлагать предпочтительные типы. Как правило, объект DMO должен предлагать по крайней мере некоторые предпочтительные типы в некоторых потоках.
  • DMO не требуется, чтобы предлагать полный список типов мультимедиа, которые он может принять. Могут быть "неадвертированные" типы, которые DMO поддерживает, но не предлагает в качестве предпочтительных типов.

Короче говоря, клиент должен рассматривать предпочтительные типы только как рекомендации. Единственный способ узнать, какие типы поддерживаются, — протестировать их, как описано в следующем разделе.

Задание типа мультимедиа в потоке

Используйте методы IMediaObject::SetInputType и IMediaObject::SetOutputType , чтобы задать тип для каждого потока. Необходимо указать DMO_MEDIA_TYPE структуру, содержащую полное описание типа носителя. В следующем примере задается тип носителя для входного потока 0, используя 16-разрядный стереофонический звук PCM с частотой 44,1 кГц:

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

Чтобы протестировать тип мультимедиа без его настройки, вызовите SetInputType или SetOutputType с флагом DMO_SET_TYPEF_TEST_ONLY. Метод возвращает S_OK, если тип допустим, или S_FALSE в противном случае:

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

Так как параметры в одном потоке могут влиять на другой, может потребоваться очистить тип мультимедиа потока. Для этого вызовите SetInputType или SetOutputType с флагом DMO_SET_TYPEF_CLEAR.

Для DMO декодера клиент обычно сначала задает тип входных данных, а затем выбирает тип вывода. Для DMO кодировщика клиент сначала задает тип вывода, а затем тип входных данных.

Непосредственное размещение объектов DMO