From 79cc627a9acae89d05b4e0c213b97ad4c0aec619 Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Tue, 14 Jul 2020 18:49:21 -0700 Subject: timer: don't advance time_frameno when paused This requires a bit of adjustment in the get_frame time_cond wait loop so it still services the event loop when woken without advance At least now get_frame has no explicit pause code, but it does require the timer keep firing while paused so it signals time_cond. --- src/rmd_get_frame.c | 26 ++++++++++++++------------ src/rmd_timer.c | 21 ++++++++++++++++----- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/rmd_get_frame.c b/src/rmd_get_frame.c index 4f8343a..5c6e800 100644 --- a/src/rmd_get_frame.c +++ b/src/rmd_get_frame.c @@ -332,9 +332,22 @@ void *rmdGetFrame(ProgData *pdata) { unsigned time_frameno; pthread_mutex_lock(&pdata->time_mutex); - while (pdata->capture_frameno >= pdata->time_frameno) + while (pdata->capture_frameno >= pdata->time_frameno) { pthread_cond_wait(&pdata->time_cond, &pdata->time_mutex); + if (pdata->capture_frameno >= pdata->time_frameno) { + /* *Likely* paused, but could be a spurious wakeup. + * either way, it's harmless to service the event loop + * before waiting again. This is how the timer keeps + * the event loop serviced by signaling us without + * advancing time_frameno. + */ + pthread_mutex_unlock(&pdata->time_mutex); + rmdEventLoop(pdata); + pthread_mutex_lock(&pdata->time_mutex); + } + } + time_frameno = pdata->time_frameno; pthread_mutex_unlock(&pdata->time_mutex); @@ -342,17 +355,6 @@ void *rmdGetFrame(ProgData *pdata) { //events (if not full_shots) rmdEventLoop(pdata); - if (pdata->paused) { - /* This is a bit janky, but there's need to service the event loop - * when paused, so instead of blocking on pause_cond, a short sleep - * is performed. - * Since the timer keeps running currently when paused, the above - * cond_wait() will never prevent us from reaching here. - */ - nanosleep(&(struct timespec){ .tv_nsec = 50000000 }, NULL); - continue; - } - //switch back and front buffers (full_shots only) if (d_buff) img_sel = img_sel ? 0 : 1; diff --git a/src/rmd_timer.c b/src/rmd_timer.c index f584bf2..a523166 100644 --- a/src/rmd_timer.c +++ b/src/rmd_timer.c @@ -113,14 +113,25 @@ void *rmdTimer(ProgData *pdata) { } } + /* When paused, stop advancing time_frameno, get_frame only progresses + * when time_frameno > capture_frameno. But get_frame needs to service + * the event loop even when paused, so still signal time_cond just with + * pdata->time_frameno frozen. get_frame will then handle time_cond + * wakeups where capture_frameno >= time_frameno as "poll events". + */ + if (pdata->paused) + frame_step = 0; pthread_mutex_unlock(&pdata->pause_mutex); - if (!pdata->args.nosound) - sync_streams(pdata, &frame_step, &delay); + if (frame_step) { + if (!pdata->args.nosound) + sync_streams(pdata, &frame_step, &delay); + + pthread_mutex_lock(&pdata->time_mutex); + pdata->time_frameno += frame_step; + pthread_mutex_unlock(&pdata->time_mutex); + } - pthread_mutex_lock(&pdata->time_mutex); - pdata->time_frameno += frame_step; - pthread_mutex_unlock(&pdata->time_mutex); pthread_cond_signal(&pdata->time_cond); nanosleep(&delay, NULL); -- cgit v1.2.1