Как организовать таймер?

Тема в разделе "WASM.WIN32", создана пользователем _DEN_, 12 янв 2009.

  1. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Есть примитивный видео-плеер.

    На входе - 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? Но опять же остается непонятным, кто будет отмерять время.

    Что посоветуете?
     
  2. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    _DEN_
    GetTickCount - имеет гронулярность.
    Используй мультимидийный таймер он позволит получать до 1000 вызовов колбек процедуры в секунду с равномерным шагом. Что касается точности то ее негарантирует никто, так как виндовс это не система реального времени.
    Так что синхронизироваться по RDSTC не помешает.
     
  3. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Pavia

    timeSetEvent / timeKillEvent - оно?

    Для получения тиков можно использовать timeGetTime() - он не имеет гранулярности.
     
  4. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    _DEN_
    Оно. timeGetTime прибольшой загрузки процессора может выдовать неожиданные результаты. Так что я за RDSTC.
     
  5. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Pavia

    У меня PocketPC - не уверен что там ассемблер такой же :)
     
  6. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Тогда у меня пока что схематичный сценарий такой:

    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);
    }
     
  7. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    _DEN_
    Все имеет свою "гранулярность" ;)
    Поэтому перед юзаньем ММ-таймера не забудь вызвать timeBeginPeriod(1), иначе можешь получить ту же дефолтную гранулярность в 10-15 мс ;) Причем timeBeginPeriod влияет на всю систему - в т.ч. и на разрешение Sleep, GetTickCount и т.п. и даже на частоту переключения потоков ?!!
     
  8. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Ну не знаю, дофига есть плееров у которых загрузка cpu 100%. Но можно примерно оценить сколько времени до след. кадра и если его валом, то вызвать например sleep(10);
    Я так делал в bink проигрывателе, загрузка 50%, жить можно. Потом высокая точность с бесконечным циклом нафиг не нужна, так что обошёлся timeGetTime. FPS думаю не нужен, вполне можно в бесконечном цикле проверять какой кадр сейчас необходимо отрисовывать. Единственно я делал через DirectDraw, а оно конечно пошустрее gdi, хотя блиттинг и в gdi шустр.

    З.Ы C сообщениями лучше не связываться, они ходят хрен знает как. Вобще чем больше плеер захватит cpu, тем для него лучше. :)
     
  9. findlook

    findlook New Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    1
    Вот именно, очень сложно грамотно написать.