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