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