summaryrefslogtreecommitdiffstats
path: root/include/private/media/AudioTrackShared.h
blob: 41e20f809bf09d3c4f72ca4b45604df60032b249 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_AUDIO_TRACK_SHARED_H
#define ANDROID_AUDIO_TRACK_SHARED_H

#include <stdint.h>
#include <sys/types.h>

#include <utils/threads.h>
#include <utils/Log.h>

namespace android {

// ----------------------------------------------------------------------------

// Maximum cumulated timeout milliseconds before restarting audioflinger thread
#define MAX_STARTUP_TIMEOUT_MS  3000    // Longer timeout period at startup to cope with A2DP
                                        // init time
#define MAX_RUN_TIMEOUT_MS      1000
#define WAIT_PERIOD_MS          10

#define CBLK_UNDERRUN   0x01 // set: underrun (out) or overrrun (in), clear: no underrun or overrun
#define CBLK_FORCEREADY 0x02 // set: track is considered ready immediately by AudioFlinger,
                             // clear: track is ready when buffer full
#define CBLK_INVALID    0x04 // track buffer invalidated by AudioFlinger, need to re-create
#define CBLK_DISABLED   0x08 // track disabled by AudioFlinger due to underrun, need to re-start

struct AudioTrackSharedStreaming {
    // similar to NBAIO MonoPipe
    volatile int32_t mFront;
    volatile int32_t mRear;
};

// future
struct AudioTrackSharedStatic {
    int mReserved;
};

// ----------------------------------------------------------------------------

// Important: do not add any virtual methods, including ~
struct audio_track_cblk_t
{
                friend class Proxy;
                friend class AudioTrackClientProxy;
                friend class AudioRecordClientProxy;
                friend class ServerProxy;

    // The data members are grouped so that members accessed frequently and in the same context
    // are in the same line of data cache.
                Mutex       lock;           // sizeof(int)
                Condition   cv;             // sizeof(int)

                // next 4 are offsets within "buffers"
    volatile    uint32_t    user;
    volatile    uint32_t    server;
                uint32_t    userBase;
                uint32_t    serverBase;

                int         mPad1;          // unused, but preserves cache line alignment

                size_t      frameCount_;    // used during creation to pass actual track buffer size
                                            // from AudioFlinger to client, and not referenced again
                                            // FIXME remove here and replace by createTrack() in/out parameter
                                            // renamed to "_" to detect incorrect use

                // Cache line boundary (32 bytes)

                uint32_t    loopStart;
                uint32_t    loopEnd;        // read-only for server, read/write for client
                int         loopCount;      // read/write for client

                // Channel volumes are fixed point U4.12, so 0x1000 means 1.0.
                // Left channel is in [0:15], right channel is in [16:31].
                // Always read and write the combined pair atomically.
                // For AudioTrack only, not used by AudioRecord.
private:
                uint32_t    mVolumeLR;

                uint32_t    mSampleRate;    // AudioTrack only: client's requested sample rate in Hz
                                            // or 0 == default. Write-only client, read-only server.

                uint8_t     mPad2;           // unused

public:
                // read-only for client, server writes once at initialization and is then read-only
                uint8_t     mName;           // normal tracks: track name, fast tracks: track index

                // used by client only
                uint16_t    bufferTimeoutMs; // Maximum cumulated timeout before restarting
                                             // audioflinger

                uint16_t    waitTimeMs;      // Cumulated wait time, used by client only
private:
                // client write-only, server read-only
                uint16_t    mSendLevel;      // Fixed point U4.12 so 0x1000 means 1.0
public:
    volatile    int32_t     flags;

                // Cache line boundary (32 bytes)

#if 0
                union {
                    AudioTrackSharedStreaming   mStreaming;
                    AudioTrackSharedStatic      mStatic;
                    int                         mAlign[8];
                } u;

                // Cache line boundary (32 bytes)
#endif

                // Since the control block is always located in shared memory, this constructor
                // is only used for placement new().  It is never used for regular new() or stack.
                            audio_track_cblk_t();

private:
                // if there is a shared buffer, "buffers" is the value of pointer() for the shared
                // buffer, otherwise "buffers" points immediately after the control block
                void*       buffer(void *buffers, uint32_t frameSize, size_t offset) const;

                bool        tryLock();

                // isOut == true means AudioTrack, isOut == false means AudioRecord
                bool        stepServer(size_t stepCount, size_t frameCount, bool isOut);
                uint32_t    stepUser(size_t stepCount, size_t frameCount, bool isOut);
                uint32_t    framesAvailable(size_t frameCount, bool isOut);
                uint32_t    framesAvailable_l(size_t frameCount, bool isOut);
                uint32_t    framesReady(bool isOut);
};

// ----------------------------------------------------------------------------

// Proxy for shared memory control block, to isolate callers from needing to know the details.
// There is exactly one ClientProxy and one ServerProxy per shared memory control block.
// The proxies are located in normal memory, and are not multi-thread safe within a given side.
class Proxy {
protected:
    Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize)
        : mCblk(cblk), mBuffers(buffers), mFrameCount(frameCount), mFrameSize(frameSize) { }
    virtual ~Proxy() { }

public:
    void*   buffer(size_t offset) const {
        return mCblk->buffer(mBuffers, mFrameSize, offset);
    }

protected:
    // These refer to shared memory, and are virtual addresses with respect to the current process.
    // They may have different virtual addresses within the other process.
    audio_track_cblk_t* const   mCblk;          // the control block
    void* const                 mBuffers;       // starting address of buffers

    const size_t                mFrameCount;    // not necessarily a power of 2
    const size_t                mFrameSize;     // in bytes
#if 0
    const size_t                mFrameCountP2;  // mFrameCount rounded to power of 2, streaming mode
#endif

};

// ----------------------------------------------------------------------------

// Proxy seen by AudioTrack client and AudioRecord client
class ClientProxy : public Proxy {
protected:
    ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize)
        : Proxy(cblk, buffers, frameCount, frameSize) { }
    virtual ~ClientProxy() { }
};

// ----------------------------------------------------------------------------

// Proxy used by AudioTrack client, which also includes AudioFlinger::PlaybackThread::OutputTrack
class AudioTrackClientProxy : public ClientProxy {
public:
    AudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize)
        : ClientProxy(cblk, buffers, frameCount, frameSize) { }
    virtual ~AudioTrackClientProxy() { }

    // No barriers on the following operations, so the ordering of loads/stores
    // with respect to other parameters is UNPREDICTABLE. That's considered safe.

    // caller must limit to 0.0 <= sendLevel <= 1.0
    void        setSendLevel(float sendLevel) {
        mCblk->mSendLevel = uint16_t(sendLevel * 0x1000);
    }

    // caller must limit to 0 <= volumeLR <= 0x10001000
    void        setVolumeLR(uint32_t volumeLR) {
        mCblk->mVolumeLR = volumeLR;
    }

    void        setSampleRate(uint32_t sampleRate) {
        mCblk->mSampleRate = sampleRate;
    }

    // called by:
    //   PlaybackThread::OutputTrack::write
    //   AudioTrack::createTrack_l
    //   AudioTrack::releaseBuffer
    //   AudioTrack::reload
    //   AudioTrack::restoreTrack_l (2 places)
    size_t      stepUser(size_t stepCount) {
        return mCblk->stepUser(stepCount, mFrameCount, true /*isOut*/);
    }

    // called by AudioTrack::obtainBuffer and AudioTrack::processBuffer
    size_t      framesAvailable() {
        return mCblk->framesAvailable(mFrameCount, true /*isOut*/);
    }

    // called by AudioTrack::obtainBuffer and PlaybackThread::OutputTrack::obtainBuffer
    // FIXME remove this API since it assumes a lock that should be invisible to caller
    size_t      framesAvailable_l() {
        return mCblk->framesAvailable_l(mFrameCount, true /*isOut*/);
    }

};

// ----------------------------------------------------------------------------

// Proxy used by AudioRecord client
class AudioRecordClientProxy : public ClientProxy {
public:
    AudioRecordClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize)
        : ClientProxy(cblk, buffers, frameCount, frameSize) { }
    ~AudioRecordClientProxy() { }

    // called by AudioRecord::releaseBuffer
    size_t      stepUser(size_t stepCount) {
        return mCblk->stepUser(stepCount, mFrameCount, false /*isOut*/);
    }

    // called by AudioRecord::processBuffer
    size_t      framesAvailable() {
        return mCblk->framesAvailable(mFrameCount, false /*isOut*/);
    }

    // called by AudioRecord::obtainBuffer
    size_t      framesReady() {
        return mCblk->framesReady(false /*isOut*/);
    }

};

// ----------------------------------------------------------------------------

// Proxy used by AudioFlinger server
class ServerProxy : public Proxy {
public:
    ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut)
        : Proxy(cblk, buffers, frameCount, frameSize), mIsOut(isOut) { }
    virtual ~ServerProxy() { }

    // for AudioTrack and AudioRecord
    bool        step(size_t stepCount) { return mCblk->stepServer(stepCount, mFrameCount, mIsOut); }

    // return value of these methods must be validated by the caller
    uint32_t    getSampleRate() const { return mCblk->mSampleRate; }
    uint16_t    getSendLevel_U4_12() const { return mCblk->mSendLevel; }
    uint32_t    getVolumeLR() const { return mCblk->mVolumeLR; }

    // for AudioTrack only
    size_t      framesReady() {
        ALOG_ASSERT(mIsOut);
        return mCblk->framesReady(true);
    }

    // for AudioRecord only, called by RecordThread::RecordTrack::getNextBuffer
    // FIXME remove this API since it assumes a lock that should be invisible to caller
    size_t      framesAvailableIn_l() {
        ALOG_ASSERT(!mIsOut);
        return mCblk->framesAvailable_l(mFrameCount, false);
    }

private:
    const bool  mIsOut;     // true for AudioTrack, false for AudioRecord

};

// ----------------------------------------------------------------------------

}; // namespace android

#endif // ANDROID_AUDIO_TRACK_SHARED_H