FastMixer.cpp revision cb4432af8dc3abc8dc4cc8e5d6080cc68a862ea1
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17// <IMPORTANT_WARNING> 18// Design rules for threadLoop() are given in the comments at section "Fast mixer thread" of 19// StateQueue.h. In particular, avoid library and system calls except at well-known points. 20// The design rules are only for threadLoop(), and don't apply to FastMixerDumpState methods. 21// </IMPORTANT_WARNING> 22 23#define LOG_TAG "FastMixer" 24//#define LOG_NDEBUG 0 25 26#define ATRACE_TAG ATRACE_TAG_AUDIO 27 28#include "Configuration.h" 29#include <time.h> 30#include <utils/Debug.h> 31#include <utils/Log.h> 32#include <utils/Trace.h> 33#include <system/audio.h> 34#ifdef FAST_THREAD_STATISTICS 35#include <cpustats/CentralTendencyStatistics.h> 36#ifdef CPU_FREQUENCY_STATISTICS 37#include <cpustats/ThreadCpuUsage.h> 38#endif 39#endif 40#include <audio_utils/format.h> 41#include "AudioMixer.h" 42#include "FastMixer.h" 43 44namespace android { 45 46/*static*/ const FastMixerState FastMixer::sInitial; 47 48FastMixer::FastMixer() : FastThread(), 49 mSlopNs(0), 50 // mFastTrackNames 51 // mGenerations 52 mOutputSink(NULL), 53 mOutputSinkGen(0), 54 mMixer(NULL), 55 mSinkBuffer(NULL), 56 mSinkBufferSize(0), 57 mSinkChannelCount(FCC_2), 58 mMixerBuffer(NULL), 59 mMixerBufferSize(0), 60 mMixerBufferFormat(AUDIO_FORMAT_PCM_16_BIT), 61 mMixerBufferState(UNDEFINED), 62 mFormat(Format_Invalid), 63 mSampleRate(0), 64 mFastTracksGen(0), 65 mTotalNativeFramesWritten(0), 66 // timestamp 67 mNativeFramesWrittenButNotPresented(0) // the = 0 is to silence the compiler 68{ 69 // FIXME pass sInitial as parameter to base class constructor, and make it static local 70 mPrevious = &sInitial; 71 mCurrent = &sInitial; 72 73 mDummyDumpState = &mDummyFastMixerDumpState; 74 // TODO: Add channel mask to NBAIO_Format. 75 // We assume that the channel mask must be a valid positional channel mask. 76 mSinkChannelMask = audio_channel_out_mask_from_count(mSinkChannelCount); 77 78 unsigned i; 79 for (i = 0; i < FastMixerState::kMaxFastTracks; ++i) { 80 mFastTrackNames[i] = -1; 81 mGenerations[i] = 0; 82 } 83#ifdef FAST_THREAD_STATISTICS 84 mOldLoad.tv_sec = 0; 85 mOldLoad.tv_nsec = 0; 86#endif 87} 88 89FastMixer::~FastMixer() 90{ 91} 92 93FastMixerStateQueue* FastMixer::sq() 94{ 95 return &mSQ; 96} 97 98const FastThreadState *FastMixer::poll() 99{ 100 return mSQ.poll(); 101} 102 103void FastMixer::setLog(NBLog::Writer *logWriter) 104{ 105 if (mMixer != NULL) { 106 mMixer->setLog(logWriter); 107 } 108} 109 110void FastMixer::onIdle() 111{ 112 mPreIdle = *(const FastMixerState *)mCurrent; 113 mCurrent = &mPreIdle; 114} 115 116void FastMixer::onExit() 117{ 118 delete mMixer; 119 free(mMixerBuffer); 120 free(mSinkBuffer); 121} 122 123bool FastMixer::isSubClassCommand(FastThreadState::Command command) 124{ 125 switch ((FastMixerState::Command) command) { 126 case FastMixerState::MIX: 127 case FastMixerState::WRITE: 128 case FastMixerState::MIX_WRITE: 129 return true; 130 default: 131 return false; 132 } 133} 134 135void FastMixer::onStateChange() 136{ 137 const FastMixerState * const current = (const FastMixerState *) mCurrent; 138 const FastMixerState * const previous = (const FastMixerState *) mPrevious; 139 FastMixerDumpState * const dumpState = (FastMixerDumpState *) mDumpState; 140 const size_t frameCount = current->mFrameCount; 141 142 // handle state change here, but since we want to diff the state, 143 // we're prepared for previous == &sInitial the first time through 144 unsigned previousTrackMask; 145 146 // check for change in output HAL configuration 147 NBAIO_Format previousFormat = mFormat; 148 if (current->mOutputSinkGen != mOutputSinkGen) { 149 mOutputSink = current->mOutputSink; 150 mOutputSinkGen = current->mOutputSinkGen; 151 if (mOutputSink == NULL) { 152 mFormat = Format_Invalid; 153 mSampleRate = 0; 154 mSinkChannelCount = 0; 155 mSinkChannelMask = AUDIO_CHANNEL_NONE; 156 } else { 157 mFormat = mOutputSink->format(); 158 mSampleRate = Format_sampleRate(mFormat); 159 mSinkChannelCount = Format_channelCount(mFormat); 160 LOG_ALWAYS_FATAL_IF(mSinkChannelCount > AudioMixer::MAX_NUM_CHANNELS); 161 162 // TODO: Add channel mask to NBAIO_Format 163 // We assume that the channel mask must be a valid positional channel mask. 164 mSinkChannelMask = audio_channel_out_mask_from_count(mSinkChannelCount); 165 } 166 dumpState->mSampleRate = mSampleRate; 167 } 168 169 if ((!Format_isEqual(mFormat, previousFormat)) || (frameCount != previous->mFrameCount)) { 170 // FIXME to avoid priority inversion, don't delete here 171 delete mMixer; 172 mMixer = NULL; 173 free(mMixerBuffer); 174 mMixerBuffer = NULL; 175 free(mSinkBuffer); 176 mSinkBuffer = NULL; 177 if (frameCount > 0 && mSampleRate > 0) { 178 // The mixer produces either 16 bit PCM or float output, select 179 // float output if the HAL supports higher than 16 bit precision. 180 mMixerBufferFormat = mFormat.mFormat == AUDIO_FORMAT_PCM_16_BIT ? 181 AUDIO_FORMAT_PCM_16_BIT : AUDIO_FORMAT_PCM_FLOAT; 182 // FIXME new may block for unbounded time at internal mutex of the heap 183 // implementation; it would be better to have normal mixer allocate for us 184 // to avoid blocking here and to prevent possible priority inversion 185 mMixer = new AudioMixer(frameCount, mSampleRate, FastMixerState::kMaxFastTracks); 186 const size_t mixerFrameSize = mSinkChannelCount 187 * audio_bytes_per_sample(mMixerBufferFormat); 188 mMixerBufferSize = mixerFrameSize * frameCount; 189 (void)posix_memalign(&mMixerBuffer, 32, mMixerBufferSize); 190 const size_t sinkFrameSize = mSinkChannelCount 191 * audio_bytes_per_sample(mFormat.mFormat); 192 if (sinkFrameSize > mixerFrameSize) { // need a sink buffer 193 mSinkBufferSize = sinkFrameSize * frameCount; 194 (void)posix_memalign(&mSinkBuffer, 32, mSinkBufferSize); 195 } 196 mPeriodNs = (frameCount * 1000000000LL) / mSampleRate; // 1.00 197 mUnderrunNs = (frameCount * 1750000000LL) / mSampleRate; // 1.75 198 mOverrunNs = (frameCount * 500000000LL) / mSampleRate; // 0.50 199 mForceNs = (frameCount * 950000000LL) / mSampleRate; // 0.95 200 mWarmupNsMin = (frameCount * 750000000LL) / mSampleRate; // 0.75 201 mWarmupNsMax = (frameCount * 1250000000LL) / mSampleRate; // 1.25 202 } else { 203 mPeriodNs = 0; 204 mUnderrunNs = 0; 205 mOverrunNs = 0; 206 mForceNs = 0; 207 mWarmupNsMin = 0; 208 mWarmupNsMax = LONG_MAX; 209 } 210 mMixerBufferState = UNDEFINED; 211#if !LOG_NDEBUG 212 for (unsigned i = 0; i < FastMixerState::kMaxFastTracks; ++i) { 213 mFastTrackNames[i] = -1; 214 } 215#endif 216 // we need to reconfigure all active tracks 217 previousTrackMask = 0; 218 mFastTracksGen = current->mFastTracksGen - 1; 219 dumpState->mFrameCount = frameCount; 220 } else { 221 previousTrackMask = previous->mTrackMask; 222 } 223 224 // check for change in active track set 225 const unsigned currentTrackMask = current->mTrackMask; 226 dumpState->mTrackMask = currentTrackMask; 227 if (current->mFastTracksGen != mFastTracksGen) { 228 ALOG_ASSERT(mMixerBuffer != NULL); 229 int name; 230 231 // process removed tracks first to avoid running out of track names 232 unsigned removedTracks = previousTrackMask & ~currentTrackMask; 233 while (removedTracks != 0) { 234 int i = __builtin_ctz(removedTracks); 235 removedTracks &= ~(1 << i); 236 const FastTrack* fastTrack = ¤t->mFastTracks[i]; 237 ALOG_ASSERT(fastTrack->mBufferProvider == NULL); 238 if (mMixer != NULL) { 239 name = mFastTrackNames[i]; 240 ALOG_ASSERT(name >= 0); 241 mMixer->deleteTrackName(name); 242 } 243#if !LOG_NDEBUG 244 mFastTrackNames[i] = -1; 245#endif 246 // don't reset track dump state, since other side is ignoring it 247 mGenerations[i] = fastTrack->mGeneration; 248 } 249 250 // now process added tracks 251 unsigned addedTracks = currentTrackMask & ~previousTrackMask; 252 while (addedTracks != 0) { 253 int i = __builtin_ctz(addedTracks); 254 addedTracks &= ~(1 << i); 255 const FastTrack* fastTrack = ¤t->mFastTracks[i]; 256 AudioBufferProvider *bufferProvider = fastTrack->mBufferProvider; 257 ALOG_ASSERT(bufferProvider != NULL && mFastTrackNames[i] == -1); 258 if (mMixer != NULL) { 259 name = mMixer->getTrackName(fastTrack->mChannelMask, 260 fastTrack->mFormat, AUDIO_SESSION_OUTPUT_MIX); 261 ALOG_ASSERT(name >= 0); 262 mFastTrackNames[i] = name; 263 mMixer->setBufferProvider(name, bufferProvider); 264 mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MAIN_BUFFER, 265 (void *)mMixerBuffer); 266 // newly allocated track names default to full scale volume 267 mMixer->setParameter( 268 name, 269 AudioMixer::TRACK, 270 AudioMixer::MIXER_FORMAT, (void *)mMixerBufferFormat); 271 mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::FORMAT, 272 (void *)(uintptr_t)fastTrack->mFormat); 273 mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK, 274 (void *)(uintptr_t)fastTrack->mChannelMask); 275 mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MIXER_CHANNEL_MASK, 276 (void *)(uintptr_t)mSinkChannelMask); 277 mMixer->enable(name); 278 } 279 mGenerations[i] = fastTrack->mGeneration; 280 } 281 282 // finally process (potentially) modified tracks; these use the same slot 283 // but may have a different buffer provider or volume provider 284 unsigned modifiedTracks = currentTrackMask & previousTrackMask; 285 while (modifiedTracks != 0) { 286 int i = __builtin_ctz(modifiedTracks); 287 modifiedTracks &= ~(1 << i); 288 const FastTrack* fastTrack = ¤t->mFastTracks[i]; 289 if (fastTrack->mGeneration != mGenerations[i]) { 290 // this track was actually modified 291 AudioBufferProvider *bufferProvider = fastTrack->mBufferProvider; 292 ALOG_ASSERT(bufferProvider != NULL); 293 if (mMixer != NULL) { 294 name = mFastTrackNames[i]; 295 ALOG_ASSERT(name >= 0); 296 mMixer->setBufferProvider(name, bufferProvider); 297 if (fastTrack->mVolumeProvider == NULL) { 298 float f = AudioMixer::UNITY_GAIN_FLOAT; 299 mMixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &f); 300 mMixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &f); 301 } 302 mMixer->setParameter(name, AudioMixer::RESAMPLE, 303 AudioMixer::REMOVE, NULL); 304 mMixer->setParameter( 305 name, 306 AudioMixer::TRACK, 307 AudioMixer::MIXER_FORMAT, (void *)mMixerBufferFormat); 308 mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::FORMAT, 309 (void *)(uintptr_t)fastTrack->mFormat); 310 mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK, 311 (void *)(uintptr_t)fastTrack->mChannelMask); 312 mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MIXER_CHANNEL_MASK, 313 (void *)(uintptr_t)mSinkChannelMask); 314 // already enabled 315 } 316 mGenerations[i] = fastTrack->mGeneration; 317 } 318 } 319 320 mFastTracksGen = current->mFastTracksGen; 321 322 dumpState->mNumTracks = popcount(currentTrackMask); 323 } 324} 325 326void FastMixer::onWork() 327{ 328 const FastMixerState * const current = (const FastMixerState *) mCurrent; 329 FastMixerDumpState * const dumpState = (FastMixerDumpState *) mDumpState; 330 const FastMixerState::Command command = mCommand; 331 const size_t frameCount = current->mFrameCount; 332 333 if ((command & FastMixerState::MIX) && (mMixer != NULL) && mIsWarm) { 334 ALOG_ASSERT(mMixerBuffer != NULL); 335 // for each track, update volume and check for underrun 336 unsigned currentTrackMask = current->mTrackMask; 337 while (currentTrackMask != 0) { 338 int i = __builtin_ctz(currentTrackMask); 339 currentTrackMask &= ~(1 << i); 340 const FastTrack* fastTrack = ¤t->mFastTracks[i]; 341 342 // Refresh the per-track timestamp 343 if (mTimestampStatus == NO_ERROR) { 344 uint32_t trackFramesWrittenButNotPresented = 345 mNativeFramesWrittenButNotPresented; 346 uint32_t trackFramesWritten = fastTrack->mBufferProvider->framesReleased(); 347 // Can't provide an AudioTimestamp before first frame presented, 348 // or during the brief 32-bit wraparound window 349 if (trackFramesWritten >= trackFramesWrittenButNotPresented) { 350 AudioTimestamp perTrackTimestamp; 351 perTrackTimestamp.mPosition = 352 trackFramesWritten - trackFramesWrittenButNotPresented; 353 perTrackTimestamp.mTime = mTimestamp.mTime; 354 fastTrack->mBufferProvider->onTimestamp(perTrackTimestamp); 355 } 356 } 357 358 int name = mFastTrackNames[i]; 359 ALOG_ASSERT(name >= 0); 360 if (fastTrack->mVolumeProvider != NULL) { 361 gain_minifloat_packed_t vlr = fastTrack->mVolumeProvider->getVolumeLR(); 362 float vlf = float_from_gain(gain_minifloat_unpack_left(vlr)); 363 float vrf = float_from_gain(gain_minifloat_unpack_right(vlr)); 364 365 mMixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &vlf); 366 mMixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &vrf); 367 } 368 // FIXME The current implementation of framesReady() for fast tracks 369 // takes a tryLock, which can block 370 // up to 1 ms. If enough active tracks all blocked in sequence, this would result 371 // in the overall fast mix cycle being delayed. Should use a non-blocking FIFO. 372 size_t framesReady = fastTrack->mBufferProvider->framesReady(); 373 if (ATRACE_ENABLED()) { 374 // I wish we had formatted trace names 375 char traceName[16]; 376 strcpy(traceName, "fRdy"); 377 traceName[4] = i + (i < 10 ? '0' : 'A' - 10); 378 traceName[5] = '\0'; 379 ATRACE_INT(traceName, framesReady); 380 } 381 FastTrackDump *ftDump = &dumpState->mTracks[i]; 382 FastTrackUnderruns underruns = ftDump->mUnderruns; 383 if (framesReady < frameCount) { 384 if (framesReady == 0) { 385 underruns.mBitFields.mEmpty++; 386 underruns.mBitFields.mMostRecent = UNDERRUN_EMPTY; 387 mMixer->disable(name); 388 } else { 389 // allow mixing partial buffer 390 underruns.mBitFields.mPartial++; 391 underruns.mBitFields.mMostRecent = UNDERRUN_PARTIAL; 392 mMixer->enable(name); 393 } 394 } else { 395 underruns.mBitFields.mFull++; 396 underruns.mBitFields.mMostRecent = UNDERRUN_FULL; 397 mMixer->enable(name); 398 } 399 ftDump->mUnderruns = underruns; 400 ftDump->mFramesReady = framesReady; 401 } 402 403 int64_t pts; 404 if (mOutputSink == NULL || (OK != mOutputSink->getNextWriteTimestamp(&pts))) { 405 pts = AudioBufferProvider::kInvalidPTS; 406 } 407 408 // process() is CPU-bound 409 mMixer->process(pts); 410 mMixerBufferState = MIXED; 411 } else if (mMixerBufferState == MIXED) { 412 mMixerBufferState = UNDEFINED; 413 } 414 //bool didFullWrite = false; // dumpsys could display a count of partial writes 415 if ((command & FastMixerState::WRITE) && (mOutputSink != NULL) && (mMixerBuffer != NULL)) { 416 if (mMixerBufferState == UNDEFINED) { 417 memset(mMixerBuffer, 0, mMixerBufferSize); 418 mMixerBufferState = ZEROED; 419 } 420 // prepare the buffer used to write to sink 421 void *buffer = mSinkBuffer != NULL ? mSinkBuffer : mMixerBuffer; 422 if (mFormat.mFormat != mMixerBufferFormat) { // sink format not the same as mixer format 423 memcpy_by_audio_format(buffer, mFormat.mFormat, mMixerBuffer, mMixerBufferFormat, 424 frameCount * Format_channelCount(mFormat)); 425 } 426 // if non-NULL, then duplicate write() to this non-blocking sink 427 NBAIO_Sink* teeSink; 428 if ((teeSink = current->mTeeSink) != NULL) { 429 (void) teeSink->write(buffer, frameCount); 430 } 431 // FIXME write() is non-blocking and lock-free for a properly implemented NBAIO sink, 432 // but this code should be modified to handle both non-blocking and blocking sinks 433 dumpState->mWriteSequence++; 434 ATRACE_BEGIN("write"); 435 ssize_t framesWritten = mOutputSink->write(buffer, frameCount); 436 ATRACE_END(); 437 dumpState->mWriteSequence++; 438 if (framesWritten >= 0) { 439 ALOG_ASSERT((size_t) framesWritten <= frameCount); 440 mTotalNativeFramesWritten += framesWritten; 441 dumpState->mFramesWritten = mTotalNativeFramesWritten; 442 //if ((size_t) framesWritten == frameCount) { 443 // didFullWrite = true; 444 //} 445 } else { 446 dumpState->mWriteErrors++; 447 } 448 mAttemptedWrite = true; 449 // FIXME count # of writes blocked excessively, CPU usage, etc. for dump 450 451 mTimestampStatus = mOutputSink->getTimestamp(mTimestamp); 452 if (mTimestampStatus == NO_ERROR) { 453 uint32_t totalNativeFramesPresented = mTimestamp.mPosition; 454 if (totalNativeFramesPresented <= mTotalNativeFramesWritten) { 455 mNativeFramesWrittenButNotPresented = 456 mTotalNativeFramesWritten - totalNativeFramesPresented; 457 } else { 458 // HAL reported that more frames were presented than were written 459 mTimestampStatus = INVALID_OPERATION; 460 } 461 } 462 } 463} 464 465} // namespace android 466