Есть примитивный видео-плеер. На входе - rgb-кадры, имеющие timestamp, когда их нужно показывать. Обновляем объект "кадр", делаем InvalidateRect, в WM_PAINT делаем SetDIBitsToDevice. Все в простейшем варианте. Вопрос: как, имея timestamps, лучше всего организовать таймер? Можно даже считать что FPS константный и мы его знаем. Вот варианты, но каждый из них мне не нравится по причине того, что ожидания между кадрами достаточно малы, но при этом требуют точности. 1. SetTimer - Механизм - отправка сообщения WM_TIMER, а любая очередь сообщений по определению не гарантирует моментального отклика. Теоретически сообщение может идти хрен знает сколько. Кроме того, периодичность, на сколько мне известно, имеет относительно большую для данной задачи гранулярность. 1/18.2 секунды? Поправьте, если я ошибаюсь. 2. Цикл из Sleep(1 / FPS). Опять же, вроде бы и тут та же гранулярность. Плюс - поток будет опаздывать на время, которое тратится вне Sleep. 3. GetTickCount перед циклом и внутри цикла. Исходя из них вычисляем точно какой сейчас показывать кадр. Но тогда непонятно, чем занять процессор между кадрами? Какой-то "точный" Sleep? Не крутиться же постоянно while (!is_it_time(GetTickCount()) - это даст 100% загрузку проца. 4. Какие-то трюки с евентами и WaitForSingleObject? Но опять же остается непонятным, кто будет отмерять время. Что посоветуете?
_DEN_ GetTickCount - имеет гронулярность. Используй мультимидийный таймер он позволит получать до 1000 вызовов колбек процедуры в секунду с равномерным шагом. Что касается точности то ее негарантирует никто, так как виндовс это не система реального времени. Так что синхронизироваться по RDSTC не помешает.
Pavia timeSetEvent / timeKillEvent - оно? Для получения тиков можно использовать timeGetTime() - он не имеет гранулярности.
_DEN_ Оно. timeGetTime прибольшой загрузки процессора может выдовать неожиданные результаты. Так что я за RDSTC.
Тогда у меня пока что схематичный сценарий такой: std::queue<frame> frames; void receiving_thread() { frames.push(receive_frame()); } void timer_proc(frame current) { show(current); frame next = frames.front(); timeSetEvent(next.timestamp - timeGetTime(), 0, timer_proc, next, 0); }
_DEN_ Все имеет свою "гранулярность" Поэтому перед юзаньем ММ-таймера не забудь вызвать timeBeginPeriod(1), иначе можешь получить ту же дефолтную гранулярность в 10-15 мс Причем timeBeginPeriod влияет на всю систему - в т.ч. и на разрешение Sleep, GetTickCount и т.п. и даже на частоту переключения потоков ?!!
Ну не знаю, дофига есть плееров у которых загрузка cpu 100%. Но можно примерно оценить сколько времени до след. кадра и если его валом, то вызвать например sleep(10); Я так делал в bink проигрывателе, загрузка 50%, жить можно. Потом высокая точность с бесконечным циклом нафиг не нужна, так что обошёлся timeGetTime. FPS думаю не нужен, вполне можно в бесконечном цикле проверять какой кадр сейчас необходимо отрисовывать. Единственно я делал через DirectDraw, а оно конечно пошустрее gdi, хотя блиттинг и в gdi шустр. З.Ы C сообщениями лучше не связываться, они ходят хрен знает как. Вобще чем больше плеер захватит cpu, тем для него лучше.