AudioTrackShared.h revision 552f274d82fb4988fb972df69134e031d375abfe
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
26namespace android {
27
28// ----------------------------------------------------------------------------
29
30// Maximum cumulated timeout milliseconds before restarting audioflinger thread
31#define MAX_STARTUP_TIMEOUT_MS  3000    // Longer timeout period at startup to cope with A2DP
32                                        // init time
33#define MAX_RUN_TIMEOUT_MS      1000
34#define WAIT_PERIOD_MS          10
35
36#define CBLK_UNDERRUN   0x01 // set: underrun (out) or overrrun (in), clear: no underrun or overrun
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 // track disabled by AudioFlinger due to underrun, need to re-start
41
42struct AudioTrackSharedStreaming {
43    // similar to NBAIO MonoPipe
44    volatile int32_t mFront;
45    volatile int32_t mRear;
46};
47
48// future
49struct AudioTrackSharedStatic {
50    int mReserved;
51};
52
53// ----------------------------------------------------------------------------
54
55// Important: do not add any virtual methods, including ~
56struct audio_track_cblk_t
57{
58                friend class Proxy;
59                friend class AudioTrackClientProxy;
60                friend class AudioRecordClientProxy;
61                friend class ServerProxy;
62
63    // The data members are grouped so that members accessed frequently and in the same context
64    // are in the same line of data cache.
65                Mutex       lock;           // sizeof(int)
66                Condition   cv;             // sizeof(int)
67
68                // next 4 are offsets within "buffers"
69    volatile    uint32_t    user;
70    volatile    uint32_t    server;
71                uint32_t    userBase;
72                uint32_t    serverBase;
73
74                int         mPad1;          // unused, but preserves cache line alignment
75
76                size_t      frameCount_;    // used during creation to pass actual track buffer size
77                                            // from AudioFlinger to client, and not referenced again
78                                            // FIXME remove here and replace by createTrack() in/out parameter
79                                            // renamed to "_" to detect incorrect use
80
81                // Cache line boundary (32 bytes)
82
83                uint32_t    loopStart;
84                uint32_t    loopEnd;        // read-only for server, read/write for client
85                int         loopCount;      // read/write for client
86
87                // Channel volumes are fixed point U4.12, so 0x1000 means 1.0.
88                // Left channel is in [0:15], right channel is in [16:31].
89                // Always read and write the combined pair atomically.
90                // For AudioTrack only, not used by AudioRecord.
91private:
92                uint32_t    mVolumeLR;
93
94                uint32_t    mSampleRate;    // AudioTrack only: client's requested sample rate in Hz
95                                            // or 0 == default. Write-only client, read-only server.
96
97                uint8_t     mPad2;           // unused
98
99public:
100                // read-only for client, server writes once at initialization and is then read-only
101                uint8_t     mName;           // normal tracks: track name, fast tracks: track index
102
103                // used by client only
104                uint16_t    bufferTimeoutMs; // Maximum cumulated timeout before restarting
105                                             // audioflinger
106
107                uint16_t    waitTimeMs;      // Cumulated wait time, used by client only
108private:
109                // client write-only, server read-only
110                uint16_t    mSendLevel;      // Fixed point U4.12 so 0x1000 means 1.0
111public:
112    volatile    int32_t     flags;
113
114                // Cache line boundary (32 bytes)
115
116#if 0
117                union {
118                    AudioTrackSharedStreaming   mStreaming;
119                    AudioTrackSharedStatic      mStatic;
120                    int                         mAlign[8];
121                } u;
122
123                // Cache line boundary (32 bytes)
124#endif
125
126                // Since the control block is always located in shared memory, this constructor
127                // is only used for placement new().  It is never used for regular new() or stack.
128                            audio_track_cblk_t();
129
130private:
131                // if there is a shared buffer, "buffers" is the value of pointer() for the shared
132                // buffer, otherwise "buffers" points immediately after the control block
133                void*       buffer(void *buffers, uint32_t frameSize, size_t offset) const;
134
135                bool        tryLock();
136
137                // isOut == true means AudioTrack, isOut == false means AudioRecord
138                bool        stepServer(size_t stepCount, size_t frameCount, bool isOut);
139                uint32_t    stepUser(size_t stepCount, size_t frameCount, bool isOut);
140                uint32_t    framesAvailable(size_t frameCount, bool isOut);
141                uint32_t    framesAvailable_l(size_t frameCount, bool isOut);
142                uint32_t    framesReady(bool isOut);
143};
144
145// ----------------------------------------------------------------------------
146
147// Proxy for shared memory control block, to isolate callers from needing to know the details.
148// There is exactly one ClientProxy and one ServerProxy per shared memory control block.
149// The proxies are located in normal memory, and are not multi-thread safe within a given side.
150class Proxy {
151protected:
152    Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize)
153        : mCblk(cblk), mBuffers(buffers), mFrameCount(frameCount), mFrameSize(frameSize) { }
154    virtual ~Proxy() { }
155
156public:
157    void*   buffer(size_t offset) const {
158        return mCblk->buffer(mBuffers, mFrameSize, offset);
159    }
160
161protected:
162    // These refer to shared memory, and are virtual addresses with respect to the current process.
163    // They may have different virtual addresses within the other process.
164    audio_track_cblk_t* const   mCblk;          // the control block
165    void* const                 mBuffers;       // starting address of buffers
166
167    const size_t                mFrameCount;    // not necessarily a power of 2
168    const size_t                mFrameSize;     // in bytes
169#if 0
170    const size_t                mFrameCountP2;  // mFrameCount rounded to power of 2, streaming mode
171#endif
172
173};
174
175// ----------------------------------------------------------------------------
176
177// Proxy seen by AudioTrack client and AudioRecord client
178class ClientProxy : public Proxy {
179protected:
180    ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize)
181        : Proxy(cblk, buffers, frameCount, frameSize) { }
182    virtual ~ClientProxy() { }
183};
184
185// ----------------------------------------------------------------------------
186
187// Proxy used by AudioTrack client, which also includes AudioFlinger::PlaybackThread::OutputTrack
188class AudioTrackClientProxy : public ClientProxy {
189public:
190    AudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize)
191        : ClientProxy(cblk, buffers, frameCount, frameSize) { }
192    virtual ~AudioTrackClientProxy() { }
193
194    // No barriers on the following operations, so the ordering of loads/stores
195    // with respect to other parameters is UNPREDICTABLE. That's considered safe.
196
197    // caller must limit to 0.0 <= sendLevel <= 1.0
198    void        setSendLevel(float sendLevel) {
199        mCblk->mSendLevel = uint16_t(sendLevel * 0x1000);
200    }
201
202    // caller must limit to 0 <= volumeLR <= 0x10001000
203    void        setVolumeLR(uint32_t volumeLR) {
204        mCblk->mVolumeLR = volumeLR;
205    }
206
207    void        setSampleRate(uint32_t sampleRate) {
208        mCblk->mSampleRate = sampleRate;
209    }
210
211    // called by:
212    //   PlaybackThread::OutputTrack::write
213    //   AudioTrack::createTrack_l
214    //   AudioTrack::releaseBuffer
215    //   AudioTrack::reload
216    //   AudioTrack::restoreTrack_l (2 places)
217    size_t      stepUser(size_t stepCount) {
218        return mCblk->stepUser(stepCount, mFrameCount, true /*isOut*/);
219    }
220
221    // called by AudioTrack::obtainBuffer and AudioTrack::processBuffer
222    size_t      framesAvailable() {
223        return mCblk->framesAvailable(mFrameCount, true /*isOut*/);
224    }
225
226    // called by AudioTrack::obtainBuffer and PlaybackThread::OutputTrack::obtainBuffer
227    // FIXME remove this API since it assumes a lock that should be invisible to caller
228    size_t      framesAvailable_l() {
229        return mCblk->framesAvailable_l(mFrameCount, true /*isOut*/);
230    }
231
232};
233
234// ----------------------------------------------------------------------------
235
236// Proxy used by AudioRecord client
237class AudioRecordClientProxy : public ClientProxy {
238public:
239    AudioRecordClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize)
240        : ClientProxy(cblk, buffers, frameCount, frameSize) { }
241    ~AudioRecordClientProxy() { }
242
243    // called by AudioRecord::releaseBuffer
244    size_t      stepUser(size_t stepCount) {
245        return mCblk->stepUser(stepCount, mFrameCount, false /*isOut*/);
246    }
247
248    // called by AudioRecord::processBuffer
249    size_t      framesAvailable() {
250        return mCblk->framesAvailable(mFrameCount, false /*isOut*/);
251    }
252
253    // called by AudioRecord::obtainBuffer
254    size_t      framesReady() {
255        return mCblk->framesReady(false /*isOut*/);
256    }
257
258};
259
260// ----------------------------------------------------------------------------
261
262// Proxy used by AudioFlinger server
263class ServerProxy : public Proxy {
264public:
265    ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut)
266        : Proxy(cblk, buffers, frameCount, frameSize), mIsOut(isOut) { }
267    virtual ~ServerProxy() { }
268
269    // for AudioTrack and AudioRecord
270    bool        step(size_t stepCount) { return mCblk->stepServer(stepCount, mFrameCount, mIsOut); }
271
272    // return value of these methods must be validated by the caller
273    uint32_t    getSampleRate() const { return mCblk->mSampleRate; }
274    uint16_t    getSendLevel_U4_12() const { return mCblk->mSendLevel; }
275    uint32_t    getVolumeLR() const { return mCblk->mVolumeLR; }
276
277    // for AudioTrack only
278    size_t      framesReady() {
279        ALOG_ASSERT(mIsOut);
280        return mCblk->framesReady(true);
281    }
282
283    // for AudioRecord only, called by RecordThread::RecordTrack::getNextBuffer
284    // FIXME remove this API since it assumes a lock that should be invisible to caller
285    size_t      framesAvailableIn_l() {
286        ALOG_ASSERT(!mIsOut);
287        return mCblk->framesAvailable_l(mFrameCount, false);
288    }
289
290private:
291    const bool  mIsOut;     // true for AudioTrack, false for AudioRecord
292
293};
294
295// ----------------------------------------------------------------------------
296
297}; // namespace android
298
299#endif // ANDROID_AUDIO_TRACK_SHARED_H
300