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