Настройка формата вывода видео
[Функция, связанная с этой страницей DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngine, и аудио/ видео захвата в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует использовать в новом коде MediaPlayer, IMFMediaEngine и аудио/видеозахват в Media Foundation вместо DirectShow, когда это возможно. Корпорация Майкрософт предлагает переписать существующий код, в котором используются устаревшие API, чтобы по возможности использовать новые API.]
Примечание
Функциональные возможности, описанные в этом разделе, являются устаревшими. Чтобы настроить выходной формат устройства захвата, приложение должно использовать структуру AM_MEDIA_TYPE , возвращаемую IAMStreamConfig::GetFormat в параметре pmt .
Устройство захвата может поддерживать ряд форматов вывода. Например, устройство может поддерживать 16-разрядную RGB, 32-разрядную RGB и YUYV. В каждом из этих форматов устройство может поддерживать диапазон размеров кадров.
На устройстве WDM интерфейс IAMStreamConfig используется для создания отчетов о форматах, поддерживаемых устройством, и для задания формата. (Для устаревших устройств VFW используйте диалоговое окно Видеоформат VFW, как описано в разделе Отображение диалоговых окон захвата VFW.) Интерфейс IAMStreamConfig предоставляется в контакте захвата, контакте предварительного просмотра или в обоих вариантах. Используйте метод ICaptureGraphBuilder2::FindInterface , чтобы получить указатель интерфейса:
IAMStreamConfig *pConfig = NULL;
hr = pBuild->FindInterface(
&PIN_CATEGORY_PREVIEW, // Preview pin.
0, // Any media type.
pCap, // Pointer to the capture filter.
IID_IAMStreamConfig, (void**)&pConfig);
Устройство имеет список поддерживаемых типов мультимедиа. Для каждого типа мультимедиа устройство также предоставляет набор возможностей. К ним относятся диапазон размеров кадров, доступных для этого формата, то, насколько хорошо устройство может растянуть или сжать изображение, а также диапазон частоты кадров.
Чтобы получить количество типов мультимедиа, вызовите метод IAMStreamConfig::GetNumberOfCapabilities . Метод возвращает два значения:
- Количество типов мультимедиа.
- Размер структуры, содержащей сведения о возможностях.
Значение размера необходимо, так как интерфейс IAMStreamConfig используется как для аудио, так и для видео (и может быть расширен на другие типы мультимедиа). Для видео возможности описываются с помощью структуры VIDEO_STREAM_CONFIG_CAPS , а аудио — AUDIO_STREAM_CONFIG_CAPS структуры.
Чтобы перечислить типы мультимедиа, вызовите метод IAMStreamConfig::GetStreamCaps с отсчитываемого от нуля индекса. Метод GetStreamCaps возвращает тип носителя и соответствующую структуру возможностей:
int iCount = 0, iSize = 0;
hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize);
// Check the size to make sure we pass in the correct structure.
if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS))
{
// Use the video capabilities structure.
for (int iFormat = 0; iFormat < iCount; iFormat++)
{
VIDEO_STREAM_CONFIG_CAPS scc;
AM_MEDIA_TYPE *pmtConfig;
hr = pConfig->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc);
if (SUCCEEDED(hr))
{
/* Examine the format, and possibly use it. */
// Delete the media type when you are done.
DeleteMediaType(pmtConfig);
}
}
Обратите внимание, как выделяются структуры для метода GetStreamCaps . Метод выделяет структуру типа мультимедиа, а вызывающий объект — структуру возможностей. Приведите структуру возможностей к указателю массива байтов. Завершив работу с типом носителя, удалите структуру AM_MEDIA_TYPE вместе с блоком формата типа мультимедиа.
Вы можете настроить устройство для использования формата, возвращаемого методом GetStreamCaps . Просто вызовите IAMStreamConfig::SetFormat с типом носителя:
hr = pConfig->SetFormat(pmtConfig);
Если контакт не подключен, он попытается использовать этот формат при подключении. Если контакт уже подключен, он пытается повторно подключиться с использованием нового формата. В любом случае нисходящий фильтр может отклонить формат.
Вы также можете изменить тип носителя перед его передачей в метод SetFormat . Именно здесь происходит VIDEO_STREAM_CONFIG_CAPS структура. Здесь описаны все допустимые способы изменения типа мультимедиа. Чтобы использовать эти сведения, необходимо понимать сведения о конкретном типе мультимедиа.
Например, предположим, что GetStreamCaps возвращает 24-разрядный формат RGB с размером кадра 320 x 240 пикселей. Эти сведения можно получить, изучив основной тип, подтип и блок формата типа носителя:
if ((pmtConfig.majortype == MEDIATYPE_Video) &&
(pmtConfig.subtype == MEDIASUBTYPE_RGB24) &&
(pmtConfig.formattype == FORMAT_VideoInfo) &&
(pmtConfig.cbFormat >= sizeof (VIDEOINFOHEADER)) &&
(pmtConfig.pbFormat != NULL))
{
VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pmtConfig.pbFormat;
// pVih contains the detailed format information.
LONG lWidth = pVih->bmiHeader.biWidth;
LONG lHeight = pVih->bmiHeader.biHeight;
}
Структура VIDEO_STREAM_CONFIG_CAPS предоставляет минимальную и максимальную ширину и высоту, которые можно использовать для этого типа мультимедиа. Он также предоставляет размер шага, который определяет приращения, с помощью которых можно настроить ширину или высоту. Например, устройство может вернуть следующее:
- MinOutputSize: 160 x 120
- MaxOutputSize: 320 x 240
- OutputGranularityX: 8 пикселей (размер горизонтального шага)
- OutputGranularityY: 8 пикселей (размер вертикального шага)
Учитывая эти числа, можно задать ширину для чего угодно в диапазоне (160, 168, 176, ... 304, 312, 320) и высота к чему-либо в диапазоне (120, 128, 136, ... 104, 112, 120). Этот процесс представлен на схеме ниже.
Чтобы задать новый размер кадра, непосредственно измените структуру AM_MEDIA_TYPE , возвращенную в GetStreamCaps:
pVih->bmiHeader.biWidth = 160;
pVih->bmiHeader.biHeight = 120;
pVih->bmiHeader.biSizeImage = DIBSIZE(pVih->bmiHeader);
Затем передайте тип носителя в метод SetFormat , как описано выше.
Элементы MinFrameInterval и MaxFrameIntervalVIDEO_STREAM_CONFIG_CAPS — это минимальная и максимальная длина каждого видеокадра, которую можно преобразовать в частоту кадров следующим образом:
frames per second = 10,000,000 / frame duration
Чтобы запросить определенную частоту кадров, измените значение AvgTimePerFrame в структуре VIDEOINFOHEADER или VIDEOINFOHEADER2 в типе носителя. Устройство может не поддерживать все возможные значения в диапазоне от минимального до максимального, поэтому драйвер будет использовать ближайшее к нему значение. Чтобы узнать, какое значение фактически использовал драйвер, вызовите IAMStreamConfig::GetFormat после вызова SetFormat.
Некоторые драйверы могут указывать значение MAXLONGLONG (0x7FFFFFFFFFFFFFFF) для значения MaxFrameInterval, что фактически означает отсутствие максимальной длительности. Однако вам может потребоваться обеспечить минимальную частоту кадров в приложении, например 1 кадр/с.
Связанные темы