Высокоточный таймер
Multimedia Timers в msdn посмотри. Он точнее будет и стабильнее.
эх.... да пробовал, работает так же, как и обычный SetTimer. Вообще-то мне надо аналог Sleep, но только более точный... Вроде можно как-то не загружать проц на 100 % ,если в цикле с QueryPerfomanceCounter использовать EnterCriticalSection(), но я об этом не наслышан... где-то ухватил, а вот из головы вылетело где :(
Попробовал я поигратся с критическими секциями, чето нифига не вышло. Говорят что виндовс не ось реального времени, и чтоб получить такой таймер нужно писать драйвер. Поэтому либо загрузка 100% либо дрова.
У мьютекса есть такая фишка WaitForSingleObject. Она ждет освобождение критической секции в течение указанного времени. Что если одним потоком занимать критическую секцию на определенное время и не давать выполняться в это время основному потоку.
А таймер это такая штука, что для точных измерений его лучше не использовать. Т.к. его вызовы ставятся в очередь сообщений, и если в очереди уже есть один вызов таймера, то второй в очередь не ставиться.
...если в очереди уже есть один вызов таймера, то второй в очередь не ставиться.
Это не так. Запросы не теряются(сами).
Это не так. Запросы не теряются(сами).
В ходе проведенных лично мною "опытов" было установленно, что:
1. нельзя установить таймер менее чем на 15 мс (применительно к моей машине, причем независимо загружен ЦП или свободен);
2. запросы не теряются, а пропускаются
В ходе проведенных лично мною "опытов" было установленно, что:
1. нельзя установить таймер менее чем на 15 мс (применительно к моей машине, причем независимо загружен ЦП или свободен);
2. запросы не теряются, а пропускаются
1. По моим данным обычный таймер работает на базе 10мс цикла. Задаешь 1мс получаешь от 1 до 10 мс.
Задаешь 15 - получишь 15 - 20. Обычные прибамбасы дискретизации.
2. Приведи пример кода, где у тебя пропускаются запросы
1. По моим данным обычный таймер работает на базе 10мс цикла. Задаешь 1мс получаешь от 1 до 10 мс.
Задаешь 15 - получишь 15 - 20. Обычные прибамбасы дискретизации.
2. Приведи пример кода, где у тебя пропускаются запросы
Написал прогу для захвата всего происходящего на десктопе и записью в avi-файл со сжатием... Тормозит немного, но это еще цветочки... В общем, делаю так: ставлю таймер на 40 ms, использую SetTimer. Получается 25 fps при вызове таймера (в обработчике таймера просто доьавляются данные в видеопоток функцией AVIStreamWrite). Проблема - длина фрагмента оказывается меньше, чем реальное записываемое время... Значит, прога не успевает! виноват скорее всего, таймер, а не сжатие... без сжатия - все также... Где-то я встречал статейку о том, что обычный виндовский таймер очень нестабильный и работает с погрешностью около 4 ms при хорошей загрузке процессора... Так вот. Кто-нибудь знает, как сделать ТОЧНЫЙ таймер (QueryPerformanceCounter), НО чтобы вся эта конструкция не просто отсчитывала время, а являлась аналогом Sleep() ? :)))
Если работаешь с Video Capture, не замудряйся с таймером. Сделай так: Переопредели обработчик CApp::OnIdle() или без MFC вместо GetMessage() используй if(!PeekMessage()){}. А уже там проверяй с помошью GetTickCount(): если с прошлого вызова данного обработчика прошёл необходимый интервал времени, ко капчи фрейм и жми. Если нет - return или Sleep(), таймер тебе здесь не нужен (да и вообще при работе с видео они не используются)
1. По моим данным обычный таймер работает на базе 10мс цикла. Задаешь 1мс получаешь от 1 до 10 мс.
Задаешь 15 - получишь 15 - 20. Обычные прибамбасы дискретизации.
2. Приведи пример кода, где у тебя пропускаются запросы
Дело в том что при любой задержке от 1 до 15 мс таймер вызывается ровно 63 раза.
Дело в том что при любой задержке от 1 до 15 мс таймер вызывается ровно 63 раза.
Кем вызывается? И как ты это видишь?
А про пример пропуска запросов не забудь пожалуйста
А уже там проверяй с помошью GetTickCount(): если с прошлого вызова данного обработчика прошёл необходимый интервал времени, ко капчи фрейм и жми. Если нет - return или Sleep(), таймер тебе здесь не нужен (да и вообще при работе с видео они не используются)
Спасибо, конечно за совет...
НО! напомню, что я КОДИРУЮ видео в РЕАЛЬНОМ времени, да еще и большого разрешения картинку, тут просто НЕОБХОДИМА точность временного интервала между кадрами, иначе что это будет за видео - то быстрее играет, то медленнее??? ни Sleep(), ни GetTickCount, да и прочие прибамбасы врядли помогут.... выход - через QueryPerfomanceCounter(), это самая точная штуковина, которую я могу еще применить, не влезая в DDK, как мне посоветовали выше :) как отсчитать время этой штучкой - я знаю... но как реализовать задержку на какое-то количество милисекунд(с хорошей точностью) без 100% загрузки ЦП?
Спасибо, конечно за совет...
НО! напомню, что я КОДИРУЮ видео в РЕАЛЬНОМ времени, да еще и большого разрешения картинку, тут просто НЕОБХОДИМА точность временного интервала между кадрами, иначе что это будет за видео - то быстрее играет, то медленнее??? ни Sleep(), ни GetTickCount, да и прочие прибамбасы врядли помогут.... выход - через QueryPerfomanceCounter(), это самая точная штуковина, которую я могу еще применить, не влезая в DDK, как мне посоветовали выше :) как отсчитать время этой штучкой - я знаю... но как реализовать задержку на какое-то количество милисекунд(с хорошей точностью) без 100% загрузки ЦП?
Multimedia timer работает достаточно стабильно
Читал, что ты уже пробовал
Я получал 500 гц без загрузки процессора. Можно и 1кгц. но не выше.
Если интересно могу поделиться
Multimedia timer работает достаточно стабильно
Читал, что ты уже пробовал
Я получал 500 гц без загрузки процессора. Можно и 1кгц. но не выше.
Если интересно могу поделиться
Как уже было сказано Windows не является ОС реального времени, поэтому для точных интервалов времени следует использовать специализированные библиотеки, например DirectX
Спасибо, конечно за совет...
НО! напомню, что я КОДИРУЮ видео в РЕАЛЬНОМ времени, да еще и большого разрешения картинку, тут просто НЕОБХОДИМА точность временного интервала между кадрами, иначе что это будет за видео - то быстрее играет, то медленнее??? ни Sleep(), ни GetTickCount, да и прочие прибамбасы врядли помогут.... выход - через QueryPerfomanceCounter(), это самая точная штуковина, которую я могу еще применить, не влезая в DDK, как мне посоветовали выше :) как отсчитать время этой штучкой - я знаю... но как реализовать задержку на какое-то количество милисекунд(с хорошей точностью) без 100% загрузки ЦП?
НО, НАПОМИНАЮ, таймеры при работе с видео не применяются! Практически все видеоплееры/капчеры работают по изложенному мной принципу (взорви с помощью Dependency Walker какую-нибудь прогу типа Adobe Premiere и найди в списке импортируемых функций хоть какое-нибудь упоминание о таймерах!!!). И что, там закапченное видео проигрывается то быстрее, то медленнее?! Наоборот, батенька, данный подход обеспечивает ровное и непрерывное проигрывание/захват видео вне зависимости от загруженности системы, тем более можно сразу узнать сколько фреймов мы пропустили, если загруженность системы не позволила закапчить/воспроизвести несколько кадров, и как-то исправить сложившуюся ситуацию. Такой подход позволит максимально эффективно использовать производительность системы. А чтобы проц не загружать, можно использовать что-то типа
RequiredTime = 1000/fps;
if (ElapsedTime < RequiredTime)
{
Sleep ((RequiredTime - ElapsedTime) / 2);
return;
}
else
{
Капчим;
Жмём;
return;
}
и всё...
Как уже было сказано Windows не является ОС реального времени, поэтому для точных интервалов времени следует использовать специализированные библиотеки, например DirectX
Как измерить время с пом DirectX?
Какая при этом точность?
Как организовать задержку, не занимая CPU
Ну и из предыдущих:
Кем вызывается таймер 63 раза? И как ты это видишь?
И про пример пропуска запросов не забудь пожалуйста
Как измерить время с пом DirectX?
Какая при этом точность?
Как организовать задержку, не занимая CPU
Ну и из предыдущих:
Кем вызывается таймер 63 раза? И как ты это видишь?
И про пример пропуска запросов не забудь пожалуйста
Да нету в DirectX таймеров. Но, зато в DirectShow есть интерфейс IReferenceClock и его метод GetTime(), возвращающий значение времени в 100 наносекундных единицах. Я с ним не работал, но 100 наносекундные интервалы заставляют призадуматься... Надо как-нибудь попробовать... На всякий случай приложу док по IReferenceClock, взятый из SDK
Как измерить время с пом DirectX?
Какая при этом точность?
Как организовать задержку, не занимая CPU
Ну и из предыдущих:
Кем вызывается таймер 63 раза? И как ты это видишь?
И про пример пропуска запросов не забудь пожалуйста
В DirectX должны быть функции работы с временем.
Пропуск вызовов сообщений таймера основан на том, что
1. очередь сообщений Windows не бесконечна;
2. при вызове таймера n раз, он должен вызваться n раз в любом случае - он вызывается столько раз, сколько успеет.
Да нету в DirectX таймеров. Но, зато в DirectShow есть интерфейс IReferenceClock и его метод GetTime(), возвращающий значение времени в 100 наносекундных единицах. Я с ним не работал, но 100 наносекундные интервалы заставляют призадуматься... Надо как-нибудь попробовать... На всякий случай приложу док по IReferenceClock, взятый из SDK
А разве DirectShow не входит в DirectX ???
НО, НАПОМИНАЮ, таймеры при работе с видео не применяются! Практически все видеоплееры/капчеры работают по изложенному мной принципу (взорви с помощью Dependency Walker какую-нибудь прогу типа Adobe Premiere и найди в списке импортируемых функций хоть какое-нибудь упоминание о таймерах!!!). И что, там закапченное видео проигрывается то быстрее, то медленнее?! Наоборот, батенька, данный подход обеспечивает ровное и непрерывное проигрывание/захват видео вне зависимости от загруженности системы, тем более можно сразу узнать сколько фреймов мы пропустили, если загруженность системы не позволила закапчить/воспроизвести несколько кадров, и как-то исправить сложившуюся ситуацию. Такой подход позволит максимально эффективно использовать производительность системы. А чтобы проц не загружать, можно использовать что-то типа
RequiredTime = 1000/fps;
if (ElapsedTime < RequiredTime)
{
Sleep ((RequiredTime - ElapsedTime) / 2);
return;
}
else
{
Капчим;
Жмём;
return;
}
и всё...
Да, конечно именно так и следует делать, но только желательно использовать эту обработку в дочернем потоке, т.к. весь интерфейс программы "умрет".
А разве DirectShow не входит в DirectX ???
IReferenceClock - часы, а не таймер (хотя их тоже можно назвать таймером, но в этой теме речь идет о совершенно другой функциональности, как раз такой, специальных интерфейсов для которой DirectX не предоставляет)
Да, конечно именно так и следует делать, но только желательно использовать эту обработку в дочернем потоке, т.к. весь интерфейс программы "умрет".
А интерфейс не умрёт, потому что его не будет (автор хочет рипать содержимое экрана, а, значит, для него важна "чистота" рабочего стола). К тому же, основной поток заснёт не более чем на 40 миллисекунд
В DirectX должны быть функции работы с временем.
Пропуск вызовов сообщений таймера основан на том, что
1. очередь сообщений Windows не бесконечна;
2. при вызове таймера n раз, он должен вызваться n раз в любом случае - он вызывается столько раз, сколько успеет.
Для начала, что ты называешь вызовом таймера?
Для начала, что ты называешь вызовом таймера?
Вызов таймера - вызов предопределенной или переопределенной функции.
Вызов таймера - вызов предопределенной или переопределенной функции.
Хочешь ли ты сказать что напр. SetTimer может быть "пропущен"? При вызове какой функции у тебя очередь сообщений переполняется?
Хочешь ли ты сказать что напр. SetTimer может быть "пропущен"? При вызове какой функции у тебя очередь сообщений переполняется?
После вызова SetTimer приложению постоянно посылаются сообщения WM_TIMER, до тех пор пока не будет вызван KillTimer или завершено приложение.
Если в течение определенного времени превышающий время посылки сообщения WM_TIMER функция-обработчик этого сообщения не успеет освободится повторный вызов этой функции не произойдет до тех пор пока она не освободится!!!
При вызове какой функции у тебя очередь сообщений переполняется?
В том то и дело что очередь не переполняется, т.к сообщения таймера не аккумулируются,
После вызова SetTimer приложению постоянно посылаются сообщения WM_TIMER, до тех пор пока не будет вызван KillTimer или завершено приложение.
Если в течение определенного времени превышающий время посылки сообщения WM_TIMER функция-обработчик этого сообщения не успеет освободится повторный вызов этой функции не произойдет до тех пор пока она не освободится!!!
Это все правильно
А твои высказывания, процитированные ниже, пртиворечивы и не соответствуют действительности
В том то и дело что очередь не переполняется, т.к сообщения таймера не аккумулируются,
Все сообщения от таймера ставятся в очередь
.. вызовы ставятся в очередь сообщений, и если в очереди уже есть один вызов таймера, то второй в очередь не ставиться.
Ставится
2. запросы не теряются, а пропускаются
Не пропускаются
Дело в том что при любой задержке от 1 до 15 мс таймер вызывается ровно 63 раза.
Как ты это установил?
Пропуск вызовов сообщений таймера основан на том, что
1. очередь сообщений Windows не бесконечна;
2. при вызове таймера n раз, он должен вызваться n раз в любом случае - он вызывается столько раз, сколько успеет.
Пропусков никаких нет
1. В распоряжении 2GB и нужно сильно и долго стараться, чтобы это все заполонить
2. Если обработка сообщения от таймера в среднем длится дольше, чем период их поступления, то OS тут ни причем.
Пропусков никаких нет
1. В распоряжении 2GB и нужно сильно и долго стараться, чтобы это все заполонить
2. Если обработка сообщения от таймера в среднем длится дольше, чем период их поступления, то OS тут ни причем.
Я могу столько послать сообщений таймера моему приложению, что ни одно другое сообщение не поступит!!!
Простой пример:
установи таймер на период t, в обработчике сообщений тамера загрузи его на время (t + Const);
убей свой таймер через время T, значительно превышаюшее время t,
по твоей логике должно обработаться (T / t1) сообщений от таймера, но их максимум обрабатывается только (T / (t + Const)) + 1;
... в обработчике сообщений тамера загрузи его на время (t + Const);
Что это значит: загрузить таймер новым значением t + Const или в обработчике сообщений загрузить CPU на 100% на время t + Const?
... t1...
Что такое t1?
Что это значит: загрузить таймер новым значением t + Const или в обработчике сообщений загрузить CPU на 100% на время t + Const?
Что такое t1?
SetTimer(2, 1000, NULL);
...
WM_TIMER:
//для 1 таймера
Sleep(200);
nCount++;
//для 2 таймера
KillTimer(1);
KillTimer(2);
через время 2000 смотришь значение nCount, оно равно у тебя 5, а не 10!!!
Что это значит: загрузить таймер новым значением t + Const или в обработчике сообщений загрузить CPU на 100% на время t + Const?
Что такое t1?
Ты можешь сказать что нибудь по существу? или дальше будешь придираться к словам и приводить свои доводы по этому поводу?
Ты можешь сказать что нибудь по существу? или дальше будешь придираться к словам и приводить свои доводы по этому поводу?
Я тебя прошу уточнить,что это значит, для меня это выглядит неоднозначно.
И тогда я отвечу по существу.
"The DispatchMessage Windows function sends a WM_TIMER message when no other messages are in the application's message queue."
и на старуху бывает проруха
Держи
"The DispatchMessage Windows function sends a WM_TIMER message when no other messages are in the application's message queue."
и на старуху бывает проруха
Я тебе говорю, что если в очереди сообщений находится уже одно сообщение от таймера, то ВТОРОЕ в очередь не ставится. А что ты хотел сказать этим, я не понял - действительно сообщение ставится в очередь сообщений приложения, но если в ней еще нет сообщений от этого таймера.
Я тебе говорю, что если в очереди сообщений находится уже одно сообщение от таймера, то ВТОРОЕ в очередь не ставится. А что ты хотел сказать этим, я не понял - действительно сообщение ставится в очередь сообщений приложения, но если в ней еще нет сообщений от этого таймера.
Не надо обсуждение проблемы точного тайминга переводить в бессмысленный спор о том, кто профи, а кто лох. Лучше бы по теме общались... The WM_TIMER message is a low-priority message. The GetMessage and PeekMessage functions post this message only when no other higher-priority messages are in the thread's message queue. Это всем понятно? Переводить, надеюсь, не надо? Если таймер именно с накоплением надо, пользуй CreateTimerQueueTimer/DeleteTimerQueueTimer, в чём вопрос-то?
Не надо обсуждение проблемы точного тайминга переводить в бессмысленный спор о том, кто профи, а кто лох. Лучше бы по теме общались... The WM_TIMER message is a low-priority message. The GetMessage and PeekMessage functions post this message only when no other higher-priority messages are in the thread's message queue. Это всем понятно? Переводить, надеюсь, не надо? Если таймер именно с накоплением надо, пользуй CreateTimerQueueTimer/DeleteTimerQueueTimer, в чём вопрос-то?
Вообще то это все по теме, я пытался объяснить что с помощью WM_TIMER не получится сделать высокоточного таймера и следует использовать другие методы.
Вообще то это все по теме, я пытался объяснить что с помощью WM_TIMER не получится сделать высокоточного таймера и следует использовать другие методы.
Так с этого-то автор и начал тему. Вообще, как уже несколько раз было сказано, Windows - не есть операционная система реального времени, и организовать с большой точностью фызов функции с определённым периодом здесь НЕВОЗМОЖНО. Если так уж приспичило использовать именно такой метод планирования вызова кода, единственное, что можно посоветовать - SetTimer/CreateTimerQueueTimer + HIGH_PRIORITY_CLASS