Есть ли способ определить, что файл фильтра DirectShow достиг конца? Под концом файла я подразумеваю, что filtergraph с фильтром SampleGrabber никогда не получит другого вызова SampleCB.
Вот некоторые вещи, которые не работают:
- Доверяйте
IMediaDet::get_StreamLength
(часто говорят, что в видео больше кадров, чем на самом деле) - Trust
IMediaSeeking::GetDuration
(согласуется с IMediaDet, +/- один кадр) - Использовать
IMediaControl::GetState
(график фильтра продолжает работать, даже если все кадры из файла уже обработаны)
Предыстория:
Я занимаюсь обработкой видео, и у меня есть класс, который создает график фильтров с помощью SampleGrabber. Всякий раз, когда вызывается SampleGrabber::SampleCB
, я блокирую его мьютексом, чтобы я мог запустить filtergraph в режиме извлечения. Когда я готов к следующему фрейму, я разблокирую мьютекс в своем основном потоке и жду, пока SampleGrabber::SampleCB
отправит мне сигнал о том, что все готово. Для некоторых видео IMediaDet::get_StreamLength
говорит мне, что в видео больше кадров, чем есть на самом деле. Как только я извлек последний кадр и запросил на один больше, чем существует на самом деле, основной поток блокируется навсегда, потому что SampleGrabber::SampleCB
больше никогда не будет вызываться. Я хотел бы иметь возможность определить, когда SampleGrabber::SampleCB
никогда не будет вызываться для источников файлов. Такие приложения, как Windows Media Player, каким-то образом могут это сделать, потому что графический интерфейс сообщает, что видео закончилось после последнего реального кадра, так что, по-видимому, есть способ сделать это.
ИЗМЕНИТЬ:
Я использую WaitForSingleObject
для реализации блокировки основного потока. Обходной путь, который я использовал до сих пор, заключается в том, чтобы сделать то, что предложил Грег: иметь конечный тайм-аут. К сожалению, это становится немного сложнее. Ожидание может завершиться неудачей по многим причинам, таким как настоящий eof, медленная сетевая файловая система, потеря сетевого соединения, медленный декодер и т. д.