FastMixer.cpp revision 21e8c50bd13ebe44f3088e26c9c6df0e163c469c
197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten/* 297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * Copyright (C) 2012 The Android Open Source Project 397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * 497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * you may not use this file except in compliance with the License. 697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * You may obtain a copy of the License at 797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * 897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * 1097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * Unless required by applicable law or agreed to in writing, software 1197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 1297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * See the License for the specific language governing permissions and 1497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten * limitations under the License. 1597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten */ 1697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 1797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#define LOG_TAG "FastMixer" 1897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten//#define LOG_NDEBUG 0 1997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 2097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#include <sys/atomics.h> 2197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#include <time.h> 2297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#include <utils/Log.h> 2397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#include <system/audio.h> 2497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#ifdef FAST_MIXER_STATISTICS 2597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#include <cpustats/CentralTendencyStatistics.h> 2697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#endif 2797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#include "AudioMixer.h" 2897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#include "FastMixer.h" 2997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 3097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#define FAST_HOT_IDLE_NS 1000000L // 1 ms: time to sleep while hot idling 3197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#define FAST_DEFAULT_NS 999999999L // ~1 sec: default time to sleep 3297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 3397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kastennamespace android { 3497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 3597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten// Fast mixer thread 3697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kastenbool FastMixer::threadLoop() 3797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten{ 3897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten static const FastMixerState initial; 3997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten const FastMixerState *previous = &initial, *current = &initial; 4097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten FastMixerState preIdle; // copy of state before we went into idle 4197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten struct timespec oldTs = {0, 0}; 4297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten bool oldTsValid = false; 4397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten long slopNs = 0; // accumulated time we've woken up too early (> 0) or too late (< 0) 4497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten long sleepNs = -1; // -1: busy wait, 0: sched_yield, > 0: nanosleep 4597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten int fastTrackNames[FastMixerState::kMaxFastTracks]; // handles used by mixer to identify tracks 4697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten int generations[FastMixerState::kMaxFastTracks]; // last observed mFastTracks[i].mGeneration 4797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten unsigned i; 4897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten for (i = 0; i < FastMixerState::kMaxFastTracks; ++i) { 4997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten fastTrackNames[i] = -1; 5097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten generations[i] = 0; 5197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 5297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten NBAIO_Sink *outputSink = NULL; 5397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten int outputSinkGen = 0; 5497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten AudioMixer* mixer = NULL; 5597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten short *mixBuffer = NULL; 5697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten enum {UNDEFINED, MIXED, ZEROED} mixBufferState = UNDEFINED; 5797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten NBAIO_Format format = Format_Invalid; 5897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten unsigned sampleRate = 0; 5997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten int fastTracksGen = 0; 6097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten long periodNs = 0; // expected period; the time required to render one mix buffer 6197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten long underrunNs = 0; // an underrun is likely if an actual cycle is greater than this value 6297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten long overrunNs = 0; // an overrun is likely if an actual cycle if less than this value 6397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten FastMixerDumpState dummyDumpState, *dumpState = &dummyDumpState; 6497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten bool ignoreNextOverrun = true; // used to ignore initial overrun and first after an underrun 6597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#ifdef FAST_MIXER_STATISTICS 6697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten CentralTendencyStatistics cts; // cycle times in seconds 6797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten static const unsigned kMaxSamples = 1000; 6897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#endif 6997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten unsigned coldGen = 0; // last observed mColdGen 7097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 7197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten for (;;) { 7297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 7397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // either nanosleep, sched_yield, or busy wait 7497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (sleepNs >= 0) { 7597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (sleepNs > 0) { 7697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(sleepNs < 1000000000); 7797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten const struct timespec req = {0, sleepNs}; 7897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten nanosleep(&req, NULL); 7997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else { 8097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sched_yield(); 8197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 8297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 8397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // default to long sleep for next cycle 8497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sleepNs = FAST_DEFAULT_NS; 8597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 8697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // poll for state change 8797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten const FastMixerState *next = mSQ.poll(); 8897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (next == NULL) { 8997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // continue to use the default initial state until a real state is available 9097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(current == &initial && previous == &initial); 9197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten next = current; 9297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 9397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 9497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten FastMixerState::Command command = next->mCommand; 9597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (next != current) { 9697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 9797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // As soon as possible of learning of a new dump area, start using it 9897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten dumpState = next->mDumpState != NULL ? next->mDumpState : &dummyDumpState; 9997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 10097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // We want to always have a valid reference to the previous (non-idle) state. 10197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // However, the state queue only guarantees access to current and previous states. 10297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // So when there is a transition from a non-idle state into an idle state, we make a 10397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // copy of the last known non-idle state so it is still available on return from idle. 10497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // The possible transitions are: 10597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // non-idle -> non-idle update previous from current in-place 10697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // non-idle -> idle update previous from copy of current 10797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // idle -> idle don't update previous 10897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // idle -> non-idle don't update previous 10997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (!(current->mCommand & FastMixerState::IDLE)) { 11097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (command & FastMixerState::IDLE) { 11197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten preIdle = *current; 11297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten current = &preIdle; 11397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten oldTsValid = false; 11497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ignoreNextOverrun = true; 11597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 11697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten previous = current; 11797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 11897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten current = next; 11997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 12097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#if !LOG_NDEBUG 12197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten next = NULL; // not referenced again 12297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#endif 12397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 12497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten dumpState->mCommand = command; 12597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 12697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten switch (command) { 12797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::INITIAL: 12897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::HOT_IDLE: 12997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sleepNs = FAST_HOT_IDLE_NS; 13097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten continue; 13197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::COLD_IDLE: 13297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // only perform a cold idle command once 13321e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten // FIXME consider checking previous state and only perform if previous != COLD_IDLE 13497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (current->mColdGen != coldGen) { 13597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten int32_t *coldFutexAddr = current->mColdFutexAddr; 13697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(coldFutexAddr != NULL); 13797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten int32_t old = android_atomic_dec(coldFutexAddr); 13897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (old <= 0) { 13997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten __futex_syscall4(coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, NULL); 14097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 14197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sleepNs = -1; 14297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten coldGen = current->mColdGen; 14397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else { 14497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sleepNs = FAST_HOT_IDLE_NS; 14597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 14697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten continue; 14797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::EXIT: 14897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten delete mixer; 14997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten delete[] mixBuffer; 15097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten return false; 15197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::MIX: 15297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::WRITE: 15397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::MIX_WRITE: 15497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten break; 15597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten default: 15697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten LOG_FATAL("bad command %d", command); 15797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 15897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 15997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // there is a non-idle state available to us; did the state change? 16097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten size_t frameCount = current->mFrameCount; 16197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (current != previous) { 16297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 16397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // handle state change here, but since we want to diff the state, 16497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // we're prepared for previous == &initial the first time through 16597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten unsigned previousTrackMask; 16697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 16797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // check for change in output HAL configuration 16897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten NBAIO_Format previousFormat = format; 16997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (current->mOutputSinkGen != outputSinkGen) { 17097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten outputSink = current->mOutputSink; 17197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten outputSinkGen = current->mOutputSinkGen; 17297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (outputSink == NULL) { 17397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten format = Format_Invalid; 17497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sampleRate = 0; 17597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else { 17697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten format = outputSink->format(); 17797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sampleRate = Format_sampleRate(format); 17897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(Format_channelCount(format) == 2); 17997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 18021e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten dumpState->mSampleRate = sampleRate; 18197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 18297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 18397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if ((format != previousFormat) || (frameCount != previous->mFrameCount)) { 18497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // FIXME to avoid priority inversion, don't delete here 18597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten delete mixer; 18697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer = NULL; 18797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten delete[] mixBuffer; 18897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixBuffer = NULL; 18997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (frameCount > 0 && sampleRate > 0) { 19097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // FIXME new may block for unbounded time at internal mutex of the heap 19197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // implementation; it would be better to have normal mixer allocate for us 19297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // to avoid blocking here and to prevent possible priority inversion 19397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer = new AudioMixer(frameCount, sampleRate, FastMixerState::kMaxFastTracks); 19497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixBuffer = new short[frameCount * 2]; 19597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten periodNs = (frameCount * 1000000000LL) / sampleRate; // 1.00 19697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten underrunNs = (frameCount * 1750000000LL) / sampleRate; // 1.75 19797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten overrunNs = (frameCount * 250000000LL) / sampleRate; // 0.25 19897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else { 19997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten periodNs = 0; 20097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten underrunNs = 0; 20197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten overrunNs = 0; 20297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 20397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixBufferState = UNDEFINED; 20497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#if !LOG_NDEBUG 20597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten for (i = 0; i < FastMixerState::kMaxFastTracks; ++i) { 20697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten fastTrackNames[i] = -1; 20797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 20897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#endif 20997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // we need to reconfigure all active tracks 21097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten previousTrackMask = 0; 21197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten fastTracksGen = current->mFastTracksGen - 1; 21221e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten dumpState->mFrameCount = frameCount; 21397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else { 21497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten previousTrackMask = previous->mTrackMask; 21597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 21697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 21797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // check for change in active track set 21897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten unsigned currentTrackMask = current->mTrackMask; 21997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (current->mFastTracksGen != fastTracksGen) { 22097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(mixBuffer != NULL); 22197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten int name; 22297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 22397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // process removed tracks first to avoid running out of track names 22497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten unsigned removedTracks = previousTrackMask & ~currentTrackMask; 22597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten while (removedTracks != 0) { 22697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten i = __builtin_ctz(removedTracks); 22797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten removedTracks &= ~(1 << i); 22897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten const FastTrack* fastTrack = ¤t->mFastTracks[i]; 22997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (mixer != NULL) { 23097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten name = fastTrackNames[i]; 23197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(name >= 0); 23297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer->deleteTrackName(name); 23397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 23497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#if !LOG_NDEBUG 23597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten fastTrackNames[i] = -1; 23697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#endif 23797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten generations[i] = fastTrack->mGeneration; 23897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 23997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 24097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // now process added tracks 24197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten unsigned addedTracks = currentTrackMask & ~previousTrackMask; 24297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten while (addedTracks != 0) { 24397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten i = __builtin_ctz(addedTracks); 24497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten addedTracks &= ~(1 << i); 24597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten const FastTrack* fastTrack = ¤t->mFastTracks[i]; 24697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten AudioBufferProvider *bufferProvider = fastTrack->mBufferProvider; 24797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(bufferProvider != NULL && fastTrackNames[i] == -1); 24897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (mixer != NULL) { 2499bd23229fdec1657398abc682ccccfce1c95f8aaJean-Michel Trivi // calling getTrackName with default channel mask 2509bd23229fdec1657398abc682ccccfce1c95f8aaJean-Michel Trivi name = mixer->getTrackName(AUDIO_CHANNEL_OUT_STEREO); 25197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(name >= 0); 25297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten fastTrackNames[i] = name; 25397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer->setBufferProvider(name, bufferProvider); 25497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MAIN_BUFFER, 25597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten (void *) mixBuffer); 25697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // newly allocated track names default to full scale volume 25721e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten if (fastTrack->mSampleRate != 0 && fastTrack->mSampleRate != sampleRate) { 25821e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten mixer->setParameter(name, AudioMixer::RESAMPLE, 25921e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten AudioMixer::SAMPLE_RATE, (void*) fastTrack->mSampleRate); 26021e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten } 26121e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK, 26221e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten (void *) fastTrack->mChannelMask); 26397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer->enable(name); 26497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 26597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten generations[i] = fastTrack->mGeneration; 26697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 26797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 26897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // finally process modified tracks; these use the same slot 26997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // but may have a different buffer provider or volume provider 27097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten unsigned modifiedTracks = currentTrackMask & previousTrackMask; 27197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten while (modifiedTracks != 0) { 27297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten i = __builtin_ctz(modifiedTracks); 27397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten modifiedTracks &= ~(1 << i); 27497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten const FastTrack* fastTrack = ¤t->mFastTracks[i]; 27597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (fastTrack->mGeneration != generations[i]) { 27697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten AudioBufferProvider *bufferProvider = fastTrack->mBufferProvider; 27797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(bufferProvider != NULL); 27897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (mixer != NULL) { 27997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten name = fastTrackNames[i]; 28097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(name >= 0); 28197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer->setBufferProvider(name, bufferProvider); 28297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (fastTrack->mVolumeProvider == NULL) { 28397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, 28497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten (void *)0x1000); 28597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, 28697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten (void *)0x1000); 28797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 28821e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten if (fastTrack->mSampleRate != 0 && 28921e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten fastTrack->mSampleRate != sampleRate) { 29021e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten mixer->setParameter(name, AudioMixer::RESAMPLE, 29121e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten AudioMixer::SAMPLE_RATE, (void*) fastTrack->mSampleRate); 29221e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten } else { 29321e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten mixer->setParameter(name, AudioMixer::RESAMPLE, 29421e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten AudioMixer::REMOVE, NULL); 29521e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten } 29621e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK, 29721e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten (void *) fastTrack->mChannelMask); 29897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // already enabled 29997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 30097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten generations[i] = fastTrack->mGeneration; 30197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 30297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 30397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 30497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten fastTracksGen = current->mFastTracksGen; 30597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 30697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten dumpState->mNumTracks = popcount(currentTrackMask); 30797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 30897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 30997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#if 1 // FIXME shouldn't need this 31097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // only process state change once 31197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten previous = current; 31297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#endif 31397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 31497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 31597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // do work using current state here 31697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if ((command & FastMixerState::MIX) && (mixer != NULL)) { 31797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(mixBuffer != NULL); 31897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // update volumes 31997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten unsigned volumeTracks = current->mTrackMask; 32097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten while (volumeTracks != 0) { 32197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten i = __builtin_ctz(volumeTracks); 32297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten volumeTracks &= ~(1 << i); 32397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten const FastTrack* fastTrack = ¤t->mFastTracks[i]; 32497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten int name = fastTrackNames[i]; 32597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOG_ASSERT(name >= 0); 32697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (fastTrack->mVolumeProvider != NULL) { 32797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten uint32_t vlr = fastTrack->mVolumeProvider->getVolumeLR(); 32897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, 32997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten (void *)(vlr & 0xFFFF)); 33097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, 33197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten (void *)(vlr >> 16)); 33297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 33397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 33497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // process() is CPU-bound 33597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixer->process(AudioBufferProvider::kInvalidPTS); 33697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixBufferState = MIXED; 33797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else if (mixBufferState == MIXED) { 33897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixBufferState = UNDEFINED; 33997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 34097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if ((command & FastMixerState::WRITE) && (outputSink != NULL) && (mixBuffer != NULL)) { 34197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (mixBufferState == UNDEFINED) { 34297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten memset(mixBuffer, 0, frameCount * 2 * sizeof(short)); 34397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mixBufferState = ZEROED; 34497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 34597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // FIXME write() is non-blocking and lock-free for a properly implemented NBAIO sink, 34697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // but this code should be modified to handle both non-blocking and blocking sinks 34797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten dumpState->mWriteSequence++; 34897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ssize_t framesWritten = outputSink->write(mixBuffer, frameCount); 34997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten dumpState->mWriteSequence++; 35097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (framesWritten >= 0) { 35197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten dumpState->mFramesWritten += framesWritten; 35297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else { 35397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten dumpState->mWriteErrors++; 35497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 35597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // FIXME count # of writes blocked excessively, CPU usage, etc. for dump 35697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 35797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 35897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // To be exactly periodic, compute the next sleep time based on current time. 35997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // This code doesn't have long-term stability when the sink is non-blocking. 36097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // FIXME To avoid drift, use the local audio clock or watch the sink's fill status. 36197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten struct timespec newTs; 36297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten int rc = clock_gettime(CLOCK_MONOTONIC, &newTs); 36397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (rc == 0) { 36497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (oldTsValid) { 36597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten time_t sec = newTs.tv_sec - oldTs.tv_sec; 36697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten long nsec = newTs.tv_nsec - oldTs.tv_nsec; 36797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (nsec < 0) { 36897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten --sec; 36997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten nsec += 1000000000; 37097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 37197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (sec > 0 || nsec > underrunNs) { 37297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // FIXME only log occasionally 37397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOGV("underrun: time since last cycle %d.%03ld sec", 37497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten (int) sec, nsec / 1000000L); 37597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten dumpState->mUnderruns++; 37697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sleepNs = -1; 37797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ignoreNextOverrun = true; 37897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else if (nsec < overrunNs) { 37997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (ignoreNextOverrun) { 38097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ignoreNextOverrun = false; 38197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else { 38297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // FIXME only log occasionally 38397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ALOGV("overrun: time since last cycle %d.%03ld sec", 38497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten (int) sec, nsec / 1000000L); 38597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten dumpState->mOverruns++; 38697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 38797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sleepNs = periodNs - overrunNs; 38897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else { 38997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sleepNs = -1; 39097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ignoreNextOverrun = false; 39197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 39297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#ifdef FAST_MIXER_STATISTICS 39397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // long-term statistics 39497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten cts.sample(sec + nsec * 1e-9); 39597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten if (cts.n() >= kMaxSamples) { 39697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten dumpState->mMean = cts.mean(); 39797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten dumpState->mMinimum = cts.minimum(); 39897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten dumpState->mMaximum = cts.maximum(); 39997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten dumpState->mStddev = cts.stddev(); 40097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten cts.reset(); 40197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 40297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#endif 40397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else { 40497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // first time through the loop 40597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten oldTsValid = true; 40697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sleepNs = periodNs; 40797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten ignoreNextOverrun = true; 40897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 40997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten oldTs = newTs; 41097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } else { 41197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // monotonic clock is broken 41297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten oldTsValid = false; 41397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten sleepNs = periodNs; 41497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 41597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 41697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } // for (;;) 41797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 41897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten // never return 'true'; Thread::_threadLoop() locks mutex which can result in priority inversion 41997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten} 42097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 42197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn KastenFastMixerDumpState::FastMixerDumpState() : 42297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mCommand(FastMixerState::INITIAL), mWriteSequence(0), mFramesWritten(0), 42321e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten mNumTracks(0), mWriteErrors(0), mUnderruns(0), mOverruns(0), 42421e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten mSampleRate(0), mFrameCount(0) 42597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#ifdef FAST_MIXER_STATISTICS 42697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten , mMean(0.0), mMinimum(0.0), mMaximum(0.0), mStddev(0.0) 42797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#endif 42897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten{ 42997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten} 43097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 43197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn KastenFastMixerDumpState::~FastMixerDumpState() 43297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten{ 43397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten} 43497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 43597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kastenvoid FastMixerDumpState::dump(int fd) 43697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten{ 43797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#define COMMAND_MAX 32 43897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten char string[COMMAND_MAX]; 43997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten switch (mCommand) { 44097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::INITIAL: 44197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten strcpy(string, "INITIAL"); 44297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten break; 44397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::HOT_IDLE: 44497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten strcpy(string, "HOT_IDLE"); 44597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten break; 44697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::COLD_IDLE: 44797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten strcpy(string, "COLD_IDLE"); 44897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten break; 44997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::EXIT: 45097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten strcpy(string, "EXIT"); 45197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten break; 45297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::MIX: 45397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten strcpy(string, "MIX"); 45497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten break; 45597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::WRITE: 45697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten strcpy(string, "WRITE"); 45797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten break; 45897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten case FastMixerState::MIX_WRITE: 45997b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten strcpy(string, "MIX_WRITE"); 46097b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten break; 46197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten default: 46297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten snprintf(string, COMMAND_MAX, "%d", mCommand); 46397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten break; 46497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten } 46597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten fdprintf(fd, "FastMixer command=%s writeSequence=%u framesWritten=%u\n" 46621e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten " numTracks=%u writeErrors=%u underruns=%u overruns=%u\n" 46721e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten " sampleRate=%u frameCount=%u\n", 46897b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten string, mWriteSequence, mFramesWritten, 46921e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten mNumTracks, mWriteErrors, mUnderruns, mOverruns, 47021e8c50bd13ebe44f3088e26c9c6df0e163c469cGlenn Kasten mSampleRate, mFrameCount); 47197b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#ifdef FAST_MIXER_STATISTICS 47297b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten fdprintf(fd, " cycle time in ms: mean=%.1f min=%.1f max=%.1f stddev=%.1f\n", 47397b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten mMean*1e3, mMinimum*1e3, mMaximum*1e3, mStddev*1e3); 47497b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten#endif 47597b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten} 47697b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten 47797b5d0d5b5ef766eb5dd680d05a5d199662d4ae0Glenn Kasten} // namespace android 478