Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
[Функция, связанная с этой страницей, DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngineи захват аудио и видео в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует использовать новый код MediaPlayer, IMFMediaEngine и аудио-видеозахват в Media Foundation вместо DirectShowпо возможности. Корпорация Майкрософт предлагает, что существующий код, использующий устаревшие API, будет перезаписан для использования новых API, если это возможно.]
Это шаг 5 руководства по созданию фильтров преобразования.
Фильтр вышестоящего потока отправляет мультимедийные образцы фильтру трансформации, вызывая метод IMemInputPin::Receive на входном штыре фильтра трансформации. Чтобы обработать данные, фильтр преобразования вызывает чисто виртуальный метод преобразования. Классы CTransformFilter и CTransInPlaceFilter используют две разные версии этого метода.
- CTransformFilter::Transform принимает указатель на входной образец и указатель на выходной образец. Перед вызовом метода фильтр копирует свойства образца из входного примера в выходной пример, включая метки времени.
- CTransInPlaceFilter::Transform принимает указатель на входной образец. Фильтр изменяет данные на месте.
Если метод трансформации возвращает S_OK, фильтр доставляет семпл далее по потоку. Чтобы пропустить кадр, верните S_FALSE. Если возникает ошибка потоковой передачи, верните код сбоя.
В следующем примере показано, как кодировщик RLE может реализовать этот метод. Ваша собственная реализация может значительно отличаться в зависимости от того, что делает фильтр.
HRESULT CRleFilter::Transform(IMediaSample *pSource, IMediaSample *pDest)
{
// Get pointers to the underlying buffers.
BYTE *pBufferIn, *pBufferOut;
hr = pSource->GetPointer(&pBufferIn);
if (FAILED(hr))
{
return hr;
}
hr = pDest->GetPointer(&pBufferOut);
if (FAILED(hr))
{
return hr;
}
// Process the data.
DWORD cbDest = EncodeFrame(pBufferIn, pBufferOut);
KASSERT((long)cbDest <= pDest->GetSize());
pDest->SetActualDataLength(cbDest);
pDest->SetSyncPoint(TRUE);
return S_OK;
}
В этом примере предполагается, что EncodeFrame является частным методом, реализующим кодировку RLE. Сам алгоритм кодирования не описан здесь; Дополнительные сведения см. в разделе "Сжатие растровых карт" в документации по пакету SDK для платформы.
Сначала в примере вызывается IMediaSample::GetPointer для получения адресов базовых буферов. Он передает эти данные в частный метод EncoderFrame. Затем он вызывает IMediaSample::SetActualDataLength, чтобы указать длину закодированных данных. Нижестоящий фильтр нуждается в этой информации, чтобы он правильно управлял буфером. Наконец, метод вызывает IMediaSample::SetSyncPoint, чтобы задать флаг ключевого кадра TRUE. Кодировка длины выполнения не использует разностные кадры, поэтому каждый кадр является ключевым кадром. Для разностных кадров задайте значение FALSE.
Другие проблемы, которые необходимо рассмотреть, включают:
Метки времени. класс CTransformFilter ставит метки времени на выходной сэмпл перед вызовом метода Transform . Он копирует значения метки времени из входного примера, не изменяя их. Если фильтру нужно изменить метки времени, вызовите IMediaSample::SetTime в выходном примере.
Изменение формата. Вышестоящий фильтр может изменять форматы в процессе потока, прикрепляя тип мультимедиа к образцу. Прежде чем это сделать, он вызывает IPin::QueryAccept на входной контакт фильтра. В классе CTransformFilter сначала вызывается CheckInputType, затем CheckTransform. Подчиненный фильтр также может изменять типы носителей, используя тот же механизм. В собственном фильтре есть две вещи, которые следует отслеживать:
- Убедитесь, что QueryAccept не возвращает ложные подтверждения.
- Если фильтр принимает изменения формата, проверьте их внутри метода Transform посредством вызова IMediaSample::GetMediaType. Если этот метод возвращает S_OK, фильтр должен реагировать на изменение формата.
Дополнительные сведения см. в разделе Динамические изменения формата.
Потоки. В CTransformFilter и CTransInPlaceFilterфильтр преобразования синхронно предоставляет выходные образцы внутри метода Receive. Фильтр не создает рабочие потоки для обработки данных. Как правило, у фильтра преобразования нет причин создавать рабочие потоки.
Далее: Шаг 6. Добавление поддержки COM.
Связанные разделы