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