У меня есть конечная точка графика, который является SampleGrabber где я получаю несжатые данные всех кадров, используя функцию обратного вызова.
В моем коде интерфейса верхнего уровня я хочу иметь функцию ReadNextFrame () который получает данные следующего кадра на графике (пока он не достигнет конца файла).
Плохая реализация с точки зрения производительности будет заключаться в передаче nextFrameIndex в grabberCB класс, указывающий, какой кадр я хочу в данный момент. Так что моя функция обратного вызова пропустит все остальные кадры и выберет только тот, который я хочу. Это дорого, так как график должен пройти весь файл для выбора данных одного кадра.
Я заметил, что есть IVideoFrameStep интерфейс, который в идеале, что я хочу. Но похоже, что этот интерфейс не совместим с Sample Grabber, и его документация гласит:
Декодеры, которые реализуют поиск с точностью до кадра в Microsoft
DirectShow должен реализовывать набор свойств AM_KSPROPSETID_FrameStep,
который используется вместе с интерфейсом IVideoFrameStep.
Я пытался подключить его к моему графику, но IVideoFrameStep :: CanStep () Функция вернула мне false, что означает, что я не могу использовать его с Sample Grabber.
Итак, мой вопрос: есть ли простое и эффективное с точки зрения производительности решение, чтобы я мог иметь свой график, чтобы сохранить текущее состояние, а затем сделать один кадр вперед и получить данные с помощью Sample Grabber?
Вы обнаружили, что IVideoFrameStep
имеет определенные требования к работе, и идея заключается в том, что весь график фильтра выполняет переходы состояний, запускает и приостанавливает воспроизведение только одного кадра.
Чтобы получить все кадры по одному с помощью Sample Grabber, вы можете реализовать более простой подход, который не предъявляет особых требований.
IMediaFilter::SetSyncSource(NULL)
SampleCB
ПерезвонитеSampleCB
выполнить, выполнить свою работу с данными и указать доступность фрейма для кода более высокого уровня, который запускает графикSampleCB
и # 3 выше сделано, не возвращайтесь из метода и вместо этого ожидайте события, которое указывает на то, что вы готовы продолжить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
}
Других решений пока нет …