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