From 183dc7772d7eba127aab63829c7ca0359d817593 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 23 Mar 2012 15:35:48 -0700 Subject: fix visualizer inactivity detection Current method implemented by the visualizer to detect that audioflinger has stopped providing audio buffers does not work if the application reads pcm captures too fast. The fix consist in implementing a method based on real time measurement only. One drawback is that the new method makes use of system calls that add some overhead to the process and capture functions. Change-Id: I53bd596b856f1cc7f0f47e08413af3335227100b --- media/libeffects/visualizer/EffectVisualizer.cpp | 33 +++++++++++++++++------- 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'media/libeffects/visualizer/EffectVisualizer.cpp') diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp index 51c8b68..bdb1a1c 100644 --- a/media/libeffects/visualizer/EffectVisualizer.cpp +++ b/media/libeffects/visualizer/EffectVisualizer.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -47,9 +48,9 @@ enum visualizer_state_e { VISUALIZER_STATE_ACTIVE, }; -// maximum number of reads from same buffer before resetting capture buffer. This means +// maximum time since last capture buffer update before resetting capture buffer. This means // that the framework has stopped playing audio and we must start returning silence -#define MAX_STALL_COUNT 10 +#define MAX_STALL_TIME_MS 1000 struct VisualizerContext { const struct effect_interface_s *mItfe; @@ -59,7 +60,7 @@ struct VisualizerContext { uint8_t mState; uint8_t mCurrentBuf; uint8_t mLastBuf; - uint8_t mStallCount; + struct timespec mBufferUpdateTime; uint8_t mCaptureBuf[2][VISUALIZER_CAPTURE_SIZE_MAX]; }; @@ -72,7 +73,7 @@ void Visualizer_reset(VisualizerContext *pContext) pContext->mCaptureIdx = 0; pContext->mCurrentBuf = 0; pContext->mLastBuf = 1; - pContext->mStallCount = 0; + pContext->mBufferUpdateTime.tv_sec = 0; memset(pContext->mCaptureBuf[0], 0x80, VISUALIZER_CAPTURE_SIZE_MAX); memset(pContext->mCaptureBuf[1], 0x80, VISUALIZER_CAPTURE_SIZE_MAX); } @@ -321,6 +322,11 @@ int Visualizer_process( if (pContext->mCaptureIdx == pContext->mCaptureSize) { pContext->mCurrentBuf ^= 1; pContext->mCaptureIdx = 0; + + // update last buffer update time stamp + if (clock_gettime(CLOCK_MONOTONIC, &pContext->mBufferUpdateTime) < 0) { + pContext->mBufferUpdateTime.tv_sec = 0; + } } if (inBuffer->raw != outBuffer->raw) { @@ -453,16 +459,25 @@ int Visualizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, pContext->mCaptureSize); // if audio framework has stopped playing audio although the effect is still // active we must clear the capture buffer to return silence - if (pContext->mLastBuf == pContext->mCurrentBuf) { - if (pContext->mStallCount < MAX_STALL_COUNT) { - if (++pContext->mStallCount == MAX_STALL_COUNT) { + if ((pContext->mLastBuf == pContext->mCurrentBuf) && + (pContext->mBufferUpdateTime.tv_sec != 0)) { + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { + time_t secs = ts.tv_sec - pContext->mBufferUpdateTime.tv_sec; + long nsec = ts.tv_nsec - pContext->mBufferUpdateTime.tv_nsec; + if (nsec < 0) { + --secs; + nsec += 1000000000; + } + uint32_t deltaMs = secs * 1000 + nsec / 1000000; + if (deltaMs > MAX_STALL_TIME_MS) { + ALOGV("capture going to idle"); + pContext->mBufferUpdateTime.tv_sec = 0; memset(pContext->mCaptureBuf[pContext->mCurrentBuf ^ 1], 0x80, pContext->mCaptureSize); } } - } else { - pContext->mStallCount = 0; } pContext->mLastBuf = pContext->mCurrentBuf; } else { -- cgit v1.1