Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
[Функция, связанная с этой страницей, DirectShow, является устаревшей функцией. Он был заменён MediaPlayer, IMFMediaEngineи захватом аудио и видео в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует в новом коде по возможности использовать MediaPlayer, IMFMediaEngine и аудио- и видеозахват в Media Foundation вместо DirectShow. Корпорация Майкрософт предлагает, что существующий код, использующий устаревшие API, будет перезаписан для использования новых API, если это возможно.]
Это шаг 4 руководства написание фильтров преобразования.
Заметка
Этот шаг не требуется для фильтров, производных от CTransInPlaceFilter.
После того как два вывода определяют тип носителя, они выбирают аллокатор для соединения и согласовывают его свойства, такие как размер буфера и количество буферов.
В классе CTransformFilter есть два аллокатора: один для подключения вышестоящего пина, и один для подключения нижестоящего пина. Вышестоящий фильтр выбирает вышестоящий распределитель, а также выбирает свойства распределителя. Входной контакт принимает всё, что передаёт вышестоящий фильтр. Если необходимо изменить это поведение, переопределите метод CBaseInputPin::NotifyAllocator.
Выходной пин-код фильтра преобразования выбирает нижестоящий распределитель. Он выполняет следующие действия.
- Если подчиненный фильтр может предоставить распределитель, выходной контакт использует распределитель этого фильтра. В противном случае выходной пин создаёт новый распределитель.
- Выходной пин-код получает требования к распределителю нижестоящего фильтра (если таковые есть), вызвав IMemInputPin::GetAllocatorRequirements.
- Выходной вывод вызывает метод фильтра преобразования CTransformFilter::DecideBufferSize, который является чисто виртуальным. Параметры этого метода включают в себя указатель на распределитель и структуру ALLOCATOR_PROPERTIES с требованиями нижнего фильтра. Если подчиненный фильтр не имеет требований к распределителю, структура обнуляется.
- В методе DecideBufferSize производный класс задает свойства распределителя путем вызова IMemAllocator::SetProperties.
Как правило, производный класс выбирает свойства распределителя в зависимости от формата выходных данных, требований нижнего фильтра и собственных требований фильтра. Попробуйте выбрать свойства, совместимые с запросом нижестоящего фильтра. В противном случае нижестоящий фильтр может отклонить подключение.
В следующем примере кодировщик RLE задает минимальные значения для размера буфера, выравнивания буфера и количества буферов. Для префикса используется любое значение, запрошенное нижестоящим фильтром. Префикс обычно равен нулю байтов, но некоторые фильтры требуют его. Например, фильтр AVI Mux использует префикс для записи заголовков RIFF.
HRESULT CRleFilter::DecideBufferSize(
IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProp)
{
AM_MEDIA_TYPE mt;
HRESULT hr = m_pOutput->ConnectionMediaType(&mt);
if (FAILED(hr))
{
return hr;
}
ASSERT(mt.formattype == FORMAT_VideoInfo);
BITMAPINFOHEADER *pbmi = HEADER(mt.pbFormat);
pProp->cbBuffer = DIBSIZE(*pbmi) * 2;
if (pProp->cbAlign == 0)
{
pProp->cbAlign = 1;
}
if (pProp->cBuffers == 0)
{
pProp->cBuffers = 1;
}
// Release the format block.
FreeMediaType(mt);
// Set allocator properties.
ALLOCATOR_PROPERTIES Actual;
hr = pAlloc->SetProperties(pProp, &Actual);
if (FAILED(hr))
{
return hr;
}
// Even when it succeeds, check the actual result.
if (pProp->cbBuffer > Actual.cbBuffer)
{
return E_FAIL;
}
return S_OK;
}
Распределитель может быть не в состоянии точно соответствовать вашему запросу. Поэтому метод SetProperties возвращает фактический результат в отдельной структуре ALLOCATOR_PROPERTIES (параметр Фактический в предыдущем примере). Даже если SetProperties успешно, необходимо проверить результат, чтобы убедиться, что они соответствуют минимальным требованиям фильтра.
Настраиваемые распределители
По умолчанию все классы фильтров используют класс CMemAllocator для своих распределителей. Этот класс выделяет память из виртуального адресного пространства клиентского процесса (с помощью VirtualAlloc). Если фильтру необходимо использовать другой вид памяти, например поверхности DirectDraw, можно реализовать пользовательский распределитель. Вы можете использовать класс CBaseAllocator или создать совершенно новый класс распределителя. Если фильтр имеет пользовательский распределитель, переопределите следующие методы в зависимости от того, какой пин-код использует распределитель:
- Входной пин-код: CBaseInputPin::GetAllocator и CBaseInputPin::NotifyAllocator.
- Выходной пин: CBaseOutputPin::DecideAllocator.
Если другой фильтр отказывается подключаться, используя ваш настраиваемый распределитель, ваш фильтр может либо завершить подключение с ошибкой, либо подключиться, используя распределитель другого фильтра. В последнем случае может потребоваться задать внутренний флаг, указывающий тип распределителя. Для примера этого подхода см. класс CDrawImage в разделе .
Далее: шаг 5 . Преобразование изображения.
Связанные разделы