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