Настройка типов мультимедиа в 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 кодировщика клиент сначала задает тип вывода, а затем тип входных данных.
Связанные темы