ISampleGrabberFilter шаг за шагом

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

В моем коде интерфейса верхнего уровня я хочу иметь функцию ReadNextFrame () который получает данные следующего кадра на графике (пока он не достигнет конца файла).

Плохая реализация с точки зрения производительности будет заключаться в передаче nextFrameIndex в grabberCB класс, указывающий, какой кадр я хочу в данный момент. Так что моя функция обратного вызова пропустит все остальные кадры и выберет только тот, который я хочу. Это дорого, так как график должен пройти весь файл для выбора данных одного кадра.

Я заметил, что есть IVideoFrameStep интерфейс, который в идеале, что я хочу. Но похоже, что этот интерфейс не совместим с Sample Grabber, и его документация гласит:

Декодеры, которые реализуют поиск с точностью до кадра в Microsoft
DirectShow должен реализовывать набор свойств AM_KSPROPSETID_FrameStep,
который используется вместе с интерфейсом IVideoFrameStep.

Я пытался подключить его к моему графику, но IVideoFrameStep :: CanStep () Функция вернула мне false, что означает, что я не могу использовать его с Sample Grabber.

Итак, мой вопрос: есть ли простое и эффективное с точки зрения производительности решение, чтобы я мог иметь свой график, чтобы сохранить текущее состояние, а затем сделать один кадр вперед и получить данные с помощью Sample Grabber?

3

Решение

Вы обнаружили, что IVideoFrameStep имеет определенные требования к работе, и идея заключается в том, что весь график фильтра выполняет переходы состояний, запускает и приостанавливает воспроизведение только одного кадра.

Чтобы получить все кадры по одному с помощью Sample Grabber, вы можете реализовать более простой подход, который не предъявляет особых требований.

  1. Ваш график фильтра работает; имело бы смысл убрать часы с графика — смотрите IMediaFilter::SetSyncSource(NULL)
  2. Иметь образец Grabber на интересующей позиции с SampleCB Перезвоните
  3. Как только у вас есть SampleCB выполнить, выполнить свою работу с данными и указать доступность фрейма для кода более высокого уровня, который запускает график
  4. Пока внутри SampleCB и # 3 выше сделано, не возвращайтесь из метода и вместо этого ожидайте события, которое указывает на то, что вы готовы продолжить
  5. Код приложения высокого уровня обработает фрейм и установит событие с # 4 выше, позволяя SampleCB выйти и продолжить работу по получению нового кадра; с новым кадром вы повторяете с # 3 выше.

То есть твой SampleCB wait блокирует весь конвейер, сохраняя его состояние в течение необходимого времени, позволяя вам обрабатывать кадр за кадром в удобном темпе.

Псевдокод для SampleCB будет (с событиями ручной установки / сброса):

data m_Data;
event m_DataAvailability;
event m_NextFrameRequest;

void SampleCB(Frame)
{
m_Data = Frame.GetData();
m_DataAvailability.Set();
m_NextFrameRequest.WaitFor(); // Sleeping here until signaled to continue
m_NextFrameRequest.Reset();
}

data ReadNextFrame()
{
m_DataAvailability.WaitFor();
data Data = m_Data;
m_DataAvailability.Reset(); // Current data processed, we need next portion
m_NextFrameRequest.Set(); // Indicate that we allow next callback call
return Data; // Make captured frame available
}
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]