FastMixer.cpp revision 1bc088a918d7038603230637d640941953b314d4
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        mGenerations[i] = 0;
83    }
84#ifdef FAST_THREAD_STATISTICS
85    mOldLoad.tv_sec = 0;
86    mOldLoad.tv_nsec = 0;
87#endif
88}
89
90FastMixer::~FastMixer()
91{
92}
93
94FastMixerStateQueue* FastMixer::sq()
95{
96    return &mSQ;
97}
98
99const FastThreadState *FastMixer::poll()
100{
101    return mSQ.poll();
102}
103
104void FastMixer::setNBLogWriter(NBLog::Writer *logWriter)
105{
106    // FIXME If mMixer is set or changed prior to this, we don't inform correctly.
107    //       Should cache logWriter and re-apply it at the assignment to mMixer.
108    if (mMixer != NULL) {
109        mMixer->setNBLogWriter(logWriter);
110    }
111}
112
113void FastMixer::onIdle()
114{
115    mPreIdle = *(const FastMixerState *)mCurrent;
116    mCurrent = &mPreIdle;
117}
118
119void FastMixer::onExit()
120{
121    delete mMixer;
122    free(mMixerBuffer);
123    free(mSinkBuffer);
124}
125
126bool FastMixer::isSubClassCommand(FastThreadState::Command command)
127{
128    switch ((FastMixerState::Command) command) {
129    case FastMixerState::MIX:
130    case FastMixerState::WRITE:
131    case FastMixerState::MIX_WRITE:
132        return true;
133    default:
134        return false;
135    }
136}
137
138void FastMixer::onStateChange()
139{
140    const FastMixerState * const current = (const FastMixerState *) mCurrent;
141    const FastMixerState * const previous = (const FastMixerState *) mPrevious;
142    FastMixerDumpState * const dumpState = (FastMixerDumpState *) mDumpState;
143    const size_t frameCount = current->mFrameCount;
144
145    // update boottime offset, in case it has changed
146    mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME] =
147            mBoottimeOffset.load();
148
149    // handle state change here, but since we want to diff the state,
150    // we're prepared for previous == &sInitial the first time through
151    unsigned previousTrackMask;
152
153    // check for change in output HAL configuration
154    NBAIO_Format previousFormat = mFormat;
155    if (current->mOutputSinkGen != mOutputSinkGen) {
156        mOutputSink = current->mOutputSink;
157        mOutputSinkGen = current->mOutputSinkGen;
158        if (mOutputSink == NULL) {
159            mFormat = Format_Invalid;
160            mSampleRate = 0;
161            mSinkChannelCount = 0;
162            mSinkChannelMask = AUDIO_CHANNEL_NONE;
163        } else {
164            mFormat = mOutputSink->format();
165            mSampleRate = Format_sampleRate(mFormat);
166            mSinkChannelCount = Format_channelCount(mFormat);
167            LOG_ALWAYS_FATAL_IF(mSinkChannelCount > AudioMixer::MAX_NUM_CHANNELS);
168
169            // TODO: Add channel mask to NBAIO_Format
170            // We assume that the channel mask must be a valid positional channel mask.
171            mSinkChannelMask = audio_channel_out_mask_from_count(mSinkChannelCount);
172        }
173        dumpState->mSampleRate = mSampleRate;
174    }
175
176    if ((!Format_isEqual(mFormat, previousFormat)) || (frameCount != previous->mFrameCount)) {
177        // FIXME to avoid priority inversion, don't delete here
178        delete mMixer;
179        mMixer = NULL;
180        free(mMixerBuffer);
181        mMixerBuffer = NULL;
182        free(mSinkBuffer);
183        mSinkBuffer = NULL;
184        if (frameCount > 0 && mSampleRate > 0) {
185            // The mixer produces either 16 bit PCM or float output, select
186            // float output if the HAL supports higher than 16 bit precision.
187            mMixerBufferFormat = mFormat.mFormat == AUDIO_FORMAT_PCM_16_BIT ?
188                    AUDIO_FORMAT_PCM_16_BIT : AUDIO_FORMAT_PCM_FLOAT;
189            // FIXME new may block for unbounded time at internal mutex of the heap
190            //       implementation; it would be better to have normal mixer allocate for us
191            //       to avoid blocking here and to prevent possible priority inversion
192            mMixer = new AudioMixer(frameCount, mSampleRate);
193            // FIXME See the other FIXME at FastMixer::setNBLogWriter()
194            const size_t mixerFrameSize = mSinkChannelCount
195                    * audio_bytes_per_sample(mMixerBufferFormat);
196            mMixerBufferSize = mixerFrameSize * frameCount;
197            (void)posix_memalign(&mMixerBuffer, 32, mMixerBufferSize);
198            const size_t sinkFrameSize = mSinkChannelCount
199                    * audio_bytes_per_sample(mFormat.mFormat);
200            if (sinkFrameSize > mixerFrameSize) { // need a sink buffer
201                mSinkBufferSize = sinkFrameSize * frameCount;
202                (void)posix_memalign(&mSinkBuffer, 32, mSinkBufferSize);
203            }
204            mPeriodNs = (frameCount * 1000000000LL) / mSampleRate;    // 1.00
205            mUnderrunNs = (frameCount * 1750000000LL) / mSampleRate;  // 1.75
206            mOverrunNs = (frameCount * 500000000LL) / mSampleRate;    // 0.50
207            mForceNs = (frameCount * 950000000LL) / mSampleRate;      // 0.95
208            mWarmupNsMin = (frameCount * 750000000LL) / mSampleRate;  // 0.75
209            mWarmupNsMax = (frameCount * 1250000000LL) / mSampleRate; // 1.25
210        } else {
211            mPeriodNs = 0;
212            mUnderrunNs = 0;
213            mOverrunNs = 0;
214            mForceNs = 0;
215            mWarmupNsMin = 0;
216            mWarmupNsMax = LONG_MAX;
217        }
218        mMixerBufferState = UNDEFINED;
219#if !LOG_NDEBUG
220        for (unsigned i = 0; i < FastMixerState::sMaxFastTracks; ++i) {
221            mFastTrackNames[i] = -1;
222        }
223#endif
224        // we need to reconfigure all active tracks
225        previousTrackMask = 0;
226        mFastTracksGen = current->mFastTracksGen - 1;
227        dumpState->mFrameCount = frameCount;
228    } else {
229        previousTrackMask = previous->mTrackMask;
230    }
231
232    // check for change in active track set
233    const unsigned currentTrackMask = current->mTrackMask;
234    dumpState->mTrackMask = currentTrackMask;
235    if (current->mFastTracksGen != mFastTracksGen) {
236        ALOG_ASSERT(mMixerBuffer != NULL);
237
238        // process removed tracks first to avoid running out of track names
239        unsigned removedTracks = previousTrackMask & ~currentTrackMask;
240        while (removedTracks != 0) {
241            int i = __builtin_ctz(removedTracks);
242            removedTracks &= ~(1 << i);
243            const FastTrack* fastTrack = &current->mFastTracks[i];
244            ALOG_ASSERT(fastTrack->mBufferProvider == NULL);
245            if (mMixer != NULL) {
246                mMixer->destroy(i);
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                const int name = i; // for clarity, choose name as fast track index.
265                status_t status = mMixer->create(
266                        name,
267                        fastTrack->mChannelMask,
268                        fastTrack->mFormat, AUDIO_SESSION_OUTPUT_MIX);
269                LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
270                        "%s: cannot create track name"
271                        " %d, mask %#x, format %#x, sessionId %d in AudioMixer",
272                        __func__, name,
273                        fastTrack->mChannelMask, fastTrack->mFormat, AUDIO_SESSION_OUTPUT_MIX);
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                    const int name = i;
306                    mMixer->setBufferProvider(name, bufferProvider);
307                    if (fastTrack->mVolumeProvider == NULL) {
308                        float f = AudioMixer::UNITY_GAIN_FLOAT;
309                        mMixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &f);
310                        mMixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &f);
311                    }
312                    mMixer->setParameter(name, AudioMixer::RESAMPLE,
313                            AudioMixer::REMOVE, NULL);
314                    mMixer->setParameter(
315                            name,
316                            AudioMixer::TRACK,
317                            AudioMixer::MIXER_FORMAT, (void *)mMixerBufferFormat);
318                    mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::FORMAT,
319                            (void *)(uintptr_t)fastTrack->mFormat);
320                    mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK,
321                            (void *)(uintptr_t)fastTrack->mChannelMask);
322                    mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MIXER_CHANNEL_MASK,
323                            (void *)(uintptr_t)mSinkChannelMask);
324                    // already enabled
325                }
326                mGenerations[i] = fastTrack->mGeneration;
327            }
328        }
329
330        mFastTracksGen = current->mFastTracksGen;
331
332        dumpState->mNumTracks = popcount(currentTrackMask);
333    }
334}
335
336void FastMixer::onWork()
337{
338    // TODO: pass an ID parameter to indicate which time series we want to write to in NBLog.cpp
339    // Or: pass both of these into a single call with a boolean
340    if (mIsWarm) {
341        LOG_HIST_TS();
342    } else {
343        LOG_AUDIO_STATE();
344    }
345    const FastMixerState * const current = (const FastMixerState *) mCurrent;
346    FastMixerDumpState * const dumpState = (FastMixerDumpState *) mDumpState;
347    const FastMixerState::Command command = mCommand;
348    const size_t frameCount = current->mFrameCount;
349
350    if ((command & FastMixerState::MIX) && (mMixer != NULL) && mIsWarm) {
351        ALOG_ASSERT(mMixerBuffer != NULL);
352
353        // AudioMixer::mState.enabledTracks is undefined if mState.hook == process__validate,
354        // so we keep a side copy of enabledTracks
355        bool anyEnabledTracks = false;
356
357        // for each track, update volume and check for underrun
358        unsigned currentTrackMask = current->mTrackMask;
359        while (currentTrackMask != 0) {
360            int i = __builtin_ctz(currentTrackMask);
361            currentTrackMask &= ~(1 << i);
362            const FastTrack* fastTrack = &current->mFastTracks[i];
363
364            const int64_t trackFramesWrittenButNotPresented =
365                mNativeFramesWrittenButNotPresented;
366            const int64_t trackFramesWritten = fastTrack->mBufferProvider->framesReleased();
367            ExtendedTimestamp perTrackTimestamp(mTimestamp);
368
369            // Can't provide an ExtendedTimestamp before first frame presented.
370            // Also, timestamp may not go to very last frame on stop().
371            if (trackFramesWritten >= trackFramesWrittenButNotPresented &&
372                    perTrackTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0) {
373                perTrackTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] =
374                        trackFramesWritten - trackFramesWrittenButNotPresented;
375            } else {
376                perTrackTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = 0;
377                perTrackTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] = -1;
378            }
379            perTrackTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER] = trackFramesWritten;
380            fastTrack->mBufferProvider->onTimestamp(perTrackTimestamp);
381
382            const int name = i;
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