Home | History | Annotate | Download | only in media
      1 /*
      2  * Copyright (C) 2007 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 #ifndef ANDROID_AUDIO_TRACK_SHARED_H
     18 #define ANDROID_AUDIO_TRACK_SHARED_H
     19 
     20 #include <stdint.h>
     21 #include <sys/types.h>
     22 
     23 #include <audio_utils/minifloat.h>
     24 #include <utils/threads.h>
     25 #include <utils/Log.h>
     26 #include <utils/RefBase.h>
     27 #include <media/nbaio/roundup.h>
     28 #include <media/SingleStateQueue.h>
     29 #include <private/media/StaticAudioTrackState.h>
     30 
     31 namespace android {
     32 
     33 // ----------------------------------------------------------------------------
     34 
     35 // for audio_track_cblk_t::mFlags
     36 #define CBLK_UNDERRUN   0x01 // set by server immediately on output underrun, cleared by client
     37 #define CBLK_FORCEREADY 0x02 // set: track is considered ready immediately by AudioFlinger,
     38                              // clear: track is ready when buffer full
     39 #define CBLK_INVALID    0x04 // track buffer invalidated by AudioFlinger, need to re-create
     40 #define CBLK_DISABLED   0x08 // output track disabled by AudioFlinger due to underrun,
     41                              // need to re-start.  Unlike CBLK_UNDERRUN, this is not set
     42                              // immediately, but only after a long string of underruns.
     43 // 0x10 unused
     44 #define CBLK_LOOP_CYCLE 0x20 // set by server each time a loop cycle other than final one completes
     45 #define CBLK_LOOP_FINAL 0x40 // set by server when the final loop cycle completes
     46 #define CBLK_BUFFER_END 0x80 // set by server when the position reaches end of buffer if not looping
     47 #define CBLK_OVERRUN   0x100 // set by server immediately on input overrun, cleared by client
     48 #define CBLK_INTERRUPT 0x200 // set by client on interrupt(), cleared by client in obtainBuffer()
     49 #define CBLK_STREAM_END_DONE 0x400 // set by server on render completion, cleared by client
     50 
     51 //EL_FIXME 20 seconds may not be enough and must be reconciled with new obtainBuffer implementation
     52 #define MAX_RUN_OFFLOADED_TIMEOUT_MS 20000 // assuming up to a maximum of 20 seconds of offloaded
     53 
     54 struct AudioTrackSharedStreaming {
     55     // similar to NBAIO MonoPipe
     56     // in continuously incrementing frame units, take modulo buffer size, which must be a power of 2
     57     volatile int32_t mFront;    // read by server
     58     volatile int32_t mRear;     // write by client
     59     volatile int32_t mFlush;    // incremented by client to indicate a request to flush;
     60                                 // server notices and discards all data between mFront and mRear
     61     volatile uint32_t mUnderrunFrames;  // server increments for each unavailable but desired frame
     62 };
     63 
     64 typedef SingleStateQueue<StaticAudioTrackState> StaticAudioTrackSingleStateQueue;
     65 
     66 struct AudioTrackSharedStatic {
     67     StaticAudioTrackSingleStateQueue::Shared
     68                     mSingleStateQueue;
     69     // This field should be a size_t, but since it is located in shared memory we
     70     // force to 32-bit.  The client and server may have different typedefs for size_t.
     71     uint32_t        mBufferPosition;    // updated asynchronously by server,
     72                                         // "for entertainment purposes only"
     73 };
     74 
     75 // ----------------------------------------------------------------------------
     76 
     77 // Important: do not add any virtual methods, including ~
     78 struct audio_track_cblk_t
     79 {
     80                 // Since the control block is always located in shared memory, this constructor
     81                 // is only used for placement new().  It is never used for regular new() or stack.
     82                             audio_track_cblk_t();
     83                 /*virtual*/ ~audio_track_cblk_t() { }
     84 
     85                 friend class Proxy;
     86                 friend class ClientProxy;
     87                 friend class AudioTrackClientProxy;
     88                 friend class AudioRecordClientProxy;
     89                 friend class ServerProxy;
     90                 friend class AudioTrackServerProxy;
     91                 friend class AudioRecordServerProxy;
     92 
     93     // The data members are grouped so that members accessed frequently and in the same context
     94     // are in the same line of data cache.
     95 
     96                 uint32_t    mServer;    // Number of filled frames consumed by server (mIsOut),
     97                                         // or filled frames provided by server (!mIsOut).
     98                                         // It is updated asynchronously by server without a barrier.
     99                                         // The value should be used "for entertainment purposes only",
    100                                         // which means don't make important decisions based on it.
    101 
    102                 uint32_t    mPad1;      // unused
    103 
    104     volatile    int32_t     mFutex;     // event flag: down (P) by client,
    105                                         // up (V) by server or binderDied() or interrupt()
    106 #define CBLK_FUTEX_WAKE 1               // if event flag bit is set, then a deferred wake is pending
    107 
    108 private:
    109 
    110                 // This field should be a size_t, but since it is located in shared memory we
    111                 // force to 32-bit.  The client and server may have different typedefs for size_t.
    112                 uint32_t    mMinimum;       // server wakes up client if available >= mMinimum
    113 
    114                 // Stereo gains for AudioTrack only, not used by AudioRecord.
    115                 gain_minifloat_packed_t mVolumeLR;
    116 
    117                 uint32_t    mSampleRate;    // AudioTrack only: client's requested sample rate in Hz
    118                                             // or 0 == default. Write-only client, read-only server.
    119 
    120                 // client write-only, server read-only
    121                 uint16_t    mSendLevel;      // Fixed point U4.12 so 0x1000 means 1.0
    122 
    123                 uint16_t    mPad2;           // unused
    124 
    125 public:
    126 
    127     volatile    int32_t     mFlags;         // combinations of CBLK_*
    128 
    129                 // Cache line boundary (32 bytes)
    130 
    131 public:
    132                 union {
    133                     AudioTrackSharedStreaming   mStreaming;
    134                     AudioTrackSharedStatic      mStatic;
    135                     int                         mAlign[8];
    136                 } u;
    137 
    138                 // Cache line boundary (32 bytes)
    139 };
    140 
    141 // ----------------------------------------------------------------------------
    142 
    143 // Proxy for shared memory control block, to isolate callers from needing to know the details.
    144 // There is exactly one ClientProxy and one ServerProxy per shared memory control block.
    145 // The proxies are located in normal memory, and are not multi-thread safe within a given side.
    146 class Proxy : public RefBase {
    147 protected:
    148     Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut,
    149             bool clientInServer);
    150     virtual ~Proxy() { }
    151 
    152 public:
    153     struct Buffer {
    154         size_t  mFrameCount;            // number of frames available in this buffer
    155         void*   mRaw;                   // pointer to first frame
    156         size_t  mNonContig;             // number of additional non-contiguous frames available
    157     };
    158 
    159 protected:
    160     // These refer to shared memory, and are virtual addresses with respect to the current process.
    161     // They may have different virtual addresses within the other process.
    162     audio_track_cblk_t* const   mCblk;  // the control block
    163     void* const     mBuffers;           // starting address of buffers
    164 
    165     const size_t    mFrameCount;        // not necessarily a power of 2
    166     const size_t    mFrameSize;         // in bytes
    167     const size_t    mFrameCountP2;      // mFrameCount rounded to power of 2, streaming mode
    168     const bool      mIsOut;             // true for AudioTrack, false for AudioRecord
    169     const bool      mClientInServer;    // true for OutputTrack, false for AudioTrack & AudioRecord
    170     bool            mIsShutdown;        // latch set to true when shared memory corruption detected
    171     size_t          mUnreleased;        // unreleased frames remaining from most recent obtainBuffer
    172 };
    173 
    174 // ----------------------------------------------------------------------------
    175 
    176 // Proxy seen by AudioTrack client and AudioRecord client
    177 class ClientProxy : public Proxy {
    178 public:
    179     ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize,
    180             bool isOut, bool clientInServer);
    181     virtual ~ClientProxy() { }
    182 
    183     static const struct timespec kForever;
    184     static const struct timespec kNonBlocking;
    185 
    186     // Obtain a buffer with filled frames (reading) or empty frames (writing).
    187     // It is permitted to call obtainBuffer() multiple times in succession, without any intervening
    188     // calls to releaseBuffer().  In that case, the final obtainBuffer() is the one that effectively
    189     // sets or extends the unreleased frame count.
    190     // On entry:
    191     //  buffer->mFrameCount should be initialized to maximum number of desired frames,
    192     //      which must be > 0.
    193     //  buffer->mNonContig is unused.
    194     //  buffer->mRaw is unused.
    195     //  requested is the requested timeout in local monotonic delta time units:
    196     //      NULL or &kNonBlocking means non-blocking (zero timeout).
    197     //      &kForever means block forever (infinite timeout).
    198     //      Other values mean a specific timeout in local monotonic delta time units.
    199     //  elapsed is a pointer to a location that will hold the total local monotonic time that
    200     //      elapsed while blocked, or NULL if not needed.
    201     // On exit:
    202     //  buffer->mFrameCount has the actual number of contiguous available frames,
    203     //      which is always 0 when the return status != NO_ERROR.
    204     //  buffer->mNonContig is the number of additional non-contiguous available frames.
    205     //  buffer->mRaw is a pointer to the first available frame,
    206     //      or NULL when buffer->mFrameCount == 0.
    207     // The return status is one of:
    208     //  NO_ERROR    Success, buffer->mFrameCount > 0.
    209     //  WOULD_BLOCK Non-blocking mode and no frames are available.
    210     //  TIMED_OUT   Timeout occurred before any frames became available.
    211     //              This can happen even for infinite timeout, due to a spurious wakeup.
    212     //              In this case, the caller should investigate and then re-try as appropriate.
    213     //  DEAD_OBJECT Server has died or invalidated, caller should destroy this proxy and re-create.
    214     //  -EINTR      Call has been interrupted.  Look around to see why, and then perhaps try again.
    215     //  NO_INIT     Shared memory is corrupt.
    216     // Assertion failure on entry, if buffer == NULL or buffer->mFrameCount == 0.
    217     status_t    obtainBuffer(Buffer* buffer, const struct timespec *requested = NULL,
    218             struct timespec *elapsed = NULL);
    219 
    220     // Release (some of) the frames last obtained.
    221     // On entry, buffer->mFrameCount should have the number of frames to release,
    222     // which must (cumulatively) be <= the number of frames last obtained but not yet released.
    223     // buffer->mRaw is ignored, but is normally same pointer returned by last obtainBuffer().
    224     // It is permitted to call releaseBuffer() multiple times to release the frames in chunks.
    225     // On exit:
    226     //  buffer->mFrameCount is zero.
    227     //  buffer->mRaw is NULL.
    228     void        releaseBuffer(Buffer* buffer);
    229 
    230     // Call after detecting server's death
    231     void        binderDied();
    232 
    233     // Call to force an obtainBuffer() to return quickly with -EINTR
    234     void        interrupt();
    235 
    236     size_t      getPosition() {
    237         return mEpoch + mCblk->mServer;
    238     }
    239 
    240     void        setEpoch(size_t epoch) {
    241         mEpoch = epoch;
    242     }
    243 
    244     void        setMinimum(size_t minimum) {
    245         // This can only happen on a 64-bit client
    246         if (minimum > UINT32_MAX) {
    247             minimum = UINT32_MAX;
    248         }
    249         mCblk->mMinimum = (uint32_t) minimum;
    250     }
    251 
    252     // Return the number of frames that would need to be obtained and released
    253     // in order for the client to be aligned at start of buffer
    254     virtual size_t  getMisalignment();
    255 
    256     size_t      getEpoch() const {
    257         return mEpoch;
    258     }
    259 
    260     size_t      getFramesFilled();
    261 
    262 private:
    263     size_t      mEpoch;
    264 };
    265 
    266 // ----------------------------------------------------------------------------
    267 
    268 // Proxy used by AudioTrack client, which also includes AudioFlinger::PlaybackThread::OutputTrack
    269 class AudioTrackClientProxy : public ClientProxy {
    270 public:
    271     AudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
    272             size_t frameSize, bool clientInServer = false)
    273         : ClientProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/,
    274           clientInServer) { }
    275     virtual ~AudioTrackClientProxy() { }
    276 
    277     // No barriers on the following operations, so the ordering of loads/stores
    278     // with respect to other parameters is UNPREDICTABLE. That's considered safe.
    279 
    280     // caller must limit to 0.0 <= sendLevel <= 1.0
    281     void        setSendLevel(float sendLevel) {
    282         mCblk->mSendLevel = uint16_t(sendLevel * 0x1000);
    283     }
    284 
    285     // set stereo gains
    286     void        setVolumeLR(gain_minifloat_packed_t volumeLR) {
    287         mCblk->mVolumeLR = volumeLR;
    288     }
    289 
    290     void        setSampleRate(uint32_t sampleRate) {
    291         mCblk->mSampleRate = sampleRate;
    292     }
    293 
    294     virtual void flush();
    295 
    296     virtual uint32_t    getUnderrunFrames() const {
    297         return mCblk->u.mStreaming.mUnderrunFrames;
    298     }
    299 
    300     bool        clearStreamEndDone();   // and return previous value
    301 
    302     bool        getStreamEndDone() const;
    303 
    304     status_t    waitStreamEndDone(const struct timespec *requested);
    305 };
    306 
    307 class StaticAudioTrackClientProxy : public AudioTrackClientProxy {
    308 public:
    309     StaticAudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
    310             size_t frameSize);
    311     virtual ~StaticAudioTrackClientProxy() { }
    312 
    313     virtual void    flush();
    314 
    315 #define MIN_LOOP    16  // minimum length of each loop iteration in frames
    316             void    setLoop(size_t loopStart, size_t loopEnd, int loopCount);
    317             size_t  getBufferPosition();
    318 
    319     virtual size_t  getMisalignment() {
    320         return 0;
    321     }
    322 
    323     virtual uint32_t    getUnderrunFrames() const {
    324         return 0;
    325     }
    326 
    327 private:
    328     StaticAudioTrackSingleStateQueue::Mutator   mMutator;
    329     size_t          mBufferPosition;    // so that getBufferPosition() appears to be synchronous
    330 };
    331 
    332 // ----------------------------------------------------------------------------
    333 
    334 // Proxy used by AudioRecord client
    335 class AudioRecordClientProxy : public ClientProxy {
    336 public:
    337     AudioRecordClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
    338             size_t frameSize)
    339         : ClientProxy(cblk, buffers, frameCount, frameSize,
    340             false /*isOut*/, false /*clientInServer*/) { }
    341     ~AudioRecordClientProxy() { }
    342 };
    343 
    344 // ----------------------------------------------------------------------------
    345 
    346 // Proxy used by AudioFlinger server
    347 class ServerProxy : public Proxy {
    348 protected:
    349     ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize,
    350             bool isOut, bool clientInServer);
    351 public:
    352     virtual ~ServerProxy() { }
    353 
    354     // Obtain a buffer with filled frames (writing) or empty frames (reading).
    355     // It is permitted to call obtainBuffer() multiple times in succession, without any intervening
    356     // calls to releaseBuffer().  In that case, the final obtainBuffer() is the one that effectively
    357     // sets or extends the unreleased frame count.
    358     // Always non-blocking.
    359     // On entry:
    360     //  buffer->mFrameCount should be initialized to maximum number of desired frames,
    361     //      which must be > 0.
    362     //  buffer->mNonContig is unused.
    363     //  buffer->mRaw is unused.
    364     //  ackFlush is true iff being called from Track::start to acknowledge a pending flush.
    365     // On exit:
    366     //  buffer->mFrameCount has the actual number of contiguous available frames,
    367     //      which is always 0 when the return status != NO_ERROR.
    368     //  buffer->mNonContig is the number of additional non-contiguous available frames.
    369     //  buffer->mRaw is a pointer to the first available frame,
    370     //      or NULL when buffer->mFrameCount == 0.
    371     // The return status is one of:
    372     //  NO_ERROR    Success, buffer->mFrameCount > 0.
    373     //  WOULD_BLOCK No frames are available.
    374     //  NO_INIT     Shared memory is corrupt.
    375     virtual status_t    obtainBuffer(Buffer* buffer, bool ackFlush = false);
    376 
    377     // Release (some of) the frames last obtained.
    378     // On entry, buffer->mFrameCount should have the number of frames to release,
    379     // which must (cumulatively) be <= the number of frames last obtained but not yet released.
    380     // It is permitted to call releaseBuffer() multiple times to release the frames in chunks.
    381     // buffer->mRaw is ignored, but is normally same pointer returned by last obtainBuffer().
    382     // On exit:
    383     //  buffer->mFrameCount is zero.
    384     //  buffer->mRaw is NULL.
    385     virtual void        releaseBuffer(Buffer* buffer);
    386 
    387 protected:
    388     size_t      mAvailToClient; // estimated frames available to client prior to releaseBuffer()
    389     int32_t     mFlush;         // our copy of cblk->u.mStreaming.mFlush, for streaming output only
    390 };
    391 
    392 // Proxy used by AudioFlinger for servicing AudioTrack
    393 class AudioTrackServerProxy : public ServerProxy {
    394 public:
    395     AudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
    396             size_t frameSize, bool clientInServer = false, uint32_t sampleRate = 0)
    397         : ServerProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, clientInServer) {
    398         mCblk->mSampleRate = sampleRate;
    399     }
    400 protected:
    401     virtual ~AudioTrackServerProxy() { }
    402 
    403 public:
    404     // return value of these methods must be validated by the caller
    405     uint32_t    getSampleRate() const { return mCblk->mSampleRate; }
    406     uint16_t    getSendLevel_U4_12() const { return mCblk->mSendLevel; }
    407     gain_minifloat_packed_t getVolumeLR() const { return mCblk->mVolumeLR; }
    408 
    409     // estimated total number of filled frames available to server to read,
    410     // which may include non-contiguous frames
    411     virtual size_t      framesReady();
    412 
    413     // Currently AudioFlinger will call framesReady() for a fast track from two threads:
    414     // FastMixer thread, and normal mixer thread.  This is dangerous, as the proxy is intended
    415     // to be called from at most one thread of server, and one thread of client.
    416     // As a temporary workaround, this method informs the proxy implementation that it
    417     // should avoid doing a state queue poll from within framesReady().
    418     // FIXME Change AudioFlinger to not call framesReady() from normal mixer thread.
    419     virtual void        framesReadyIsCalledByMultipleThreads() { }
    420 
    421     bool     setStreamEndDone();    // and return previous value
    422 
    423     // Add to the tally of underrun frames, and inform client of underrun
    424     virtual void        tallyUnderrunFrames(uint32_t frameCount);
    425 
    426     // Return the total number of frames which AudioFlinger desired but were unavailable,
    427     // and thus which resulted in an underrun.
    428     virtual uint32_t    getUnderrunFrames() const { return mCblk->u.mStreaming.mUnderrunFrames; }
    429 
    430     // Return the total number of frames that AudioFlinger has obtained and released
    431     virtual size_t      framesReleased() const { return mCblk->mServer; }
    432 };
    433 
    434 class StaticAudioTrackServerProxy : public AudioTrackServerProxy {
    435 public:
    436     StaticAudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
    437             size_t frameSize);
    438 protected:
    439     virtual ~StaticAudioTrackServerProxy() { }
    440 
    441 public:
    442     virtual size_t      framesReady();
    443     virtual void        framesReadyIsCalledByMultipleThreads();
    444     virtual status_t    obtainBuffer(Buffer* buffer, bool ackFlush);
    445     virtual void        releaseBuffer(Buffer* buffer);
    446     virtual void        tallyUnderrunFrames(uint32_t frameCount);
    447     virtual uint32_t    getUnderrunFrames() const { return 0; }
    448 
    449 private:
    450     ssize_t             pollPosition(); // poll for state queue update, and return current position
    451     StaticAudioTrackSingleStateQueue::Observer  mObserver;
    452     size_t              mPosition;  // server's current play position in frames, relative to 0
    453     size_t              mEnd;       // cached value computed from mState, safe for asynchronous read
    454     bool                mFramesReadyIsCalledByMultipleThreads;
    455     StaticAudioTrackState   mState;
    456 };
    457 
    458 // Proxy used by AudioFlinger for servicing AudioRecord
    459 class AudioRecordServerProxy : public ServerProxy {
    460 public:
    461     AudioRecordServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
    462             size_t frameSize, bool clientInServer)
    463         : ServerProxy(cblk, buffers, frameCount, frameSize, false /*isOut*/, clientInServer) { }
    464 protected:
    465     virtual ~AudioRecordServerProxy() { }
    466 };
    467 
    468 // ----------------------------------------------------------------------------
    469 
    470 }; // namespace android
    471 
    472 #endif // ANDROID_AUDIO_TRACK_SHARED_H
    473