| The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 |  | 
| Glenn Kasten | c56f342 | 2014-03-21 17:53:17 -0700 | [diff] [blame] | 23 | #include <audio_utils/minifloat.h> | 
| The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 24 | #include <utils/threads.h> | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 25 | #include <utils/Log.h> | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 26 | #include <utils/RefBase.h> | 
| Glenn Kasten | 53dbe77 | 2015-01-06 10:46:38 -0800 | [diff] [blame] | 27 | #include <audio_utils/roundup.h> | 
| Andy Hung | 8edb8dc | 2015-03-26 19:13:55 -0700 | [diff] [blame] | 28 | #include <media/AudioResamplerPublic.h> | 
| Andy Hung | 3f0c902 | 2016-01-15 17:49:46 -0800 | [diff] [blame] | 29 | #include <media/AudioTimestamp.h> | 
| Andy Hung | 90e8a97 | 2015-11-09 16:42:40 -0800 | [diff] [blame] | 30 | #include <media/Modulo.h> | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 31 | #include <media/SingleStateQueue.h> | 
| The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 32 |  | 
|  | 33 | namespace android { | 
|  | 34 |  | 
|  | 35 | // ---------------------------------------------------------------------------- | 
|  | 36 |  | 
| Glenn Kasten | 96f60d8 | 2013-07-12 10:21:18 -0700 | [diff] [blame] | 37 | // for audio_track_cblk_t::mFlags | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 38 | #define CBLK_UNDERRUN   0x01 // set by server immediately on output underrun, cleared by client | 
| Glenn Kasten | 864585d | 2012-11-06 16:15:41 -0800 | [diff] [blame] | 39 | #define CBLK_FORCEREADY 0x02 // set: track is considered ready immediately by AudioFlinger, | 
| Glenn Kasten | 9c5fdd8 | 2012-11-05 13:38:15 -0800 | [diff] [blame] | 40 | // clear: track is ready when buffer full | 
| Glenn Kasten | 864585d | 2012-11-06 16:15:41 -0800 | [diff] [blame] | 41 | #define CBLK_INVALID    0x04 // track buffer invalidated by AudioFlinger, need to re-create | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 42 | #define CBLK_DISABLED   0x08 // output track disabled by AudioFlinger due to underrun, | 
|  | 43 | // need to re-start.  Unlike CBLK_UNDERRUN, this is not set | 
|  | 44 | // immediately, but only after a long string of underruns. | 
|  | 45 | // 0x10 unused | 
|  | 46 | #define CBLK_LOOP_CYCLE 0x20 // set by server each time a loop cycle other than final one completes | 
|  | 47 | #define CBLK_LOOP_FINAL 0x40 // set by server when the final loop cycle completes | 
|  | 48 | #define CBLK_BUFFER_END 0x80 // set by server when the position reaches end of buffer if not looping | 
|  | 49 | #define CBLK_OVERRUN   0x100 // set by server immediately on input overrun, cleared by client | 
|  | 50 | #define CBLK_INTERRUPT 0x200 // set by client on interrupt(), cleared by client in obtainBuffer() | 
| Richard Fitzgerald | ad3af33 | 2013-03-25 16:54:37 +0000 | [diff] [blame] | 51 | #define CBLK_STREAM_END_DONE 0x400 // set by server on render completion, cleared by client | 
|  | 52 |  | 
|  | 53 | //EL_FIXME 20 seconds may not be enough and must be reconciled with new obtainBuffer implementation | 
| Glenn Kasten | e198c36 | 2013-08-13 09:13:36 -0700 | [diff] [blame] | 54 | #define MAX_RUN_OFFLOADED_TIMEOUT_MS 20000 // assuming up to a maximum of 20 seconds of offloaded | 
| The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 55 |  | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 56 | struct AudioTrackSharedStreaming { | 
|  | 57 | // similar to NBAIO MonoPipe | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 58 | // in continuously incrementing frame units, take modulo buffer size, which must be a power of 2 | 
| Glenn Kasten | f59497b | 2015-01-26 16:35:47 -0800 | [diff] [blame] | 59 | volatile int32_t mFront;    // read by consumer (output: server, input: client) | 
|  | 60 | volatile int32_t mRear;     // written by producer (output: client, input: server) | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 61 | volatile int32_t mFlush;    // incremented by client to indicate a request to flush; | 
|  | 62 | // server notices and discards all data between mFront and mRear | 
| Phil Burk | 2812d9e | 2016-01-04 10:34:30 -0800 | [diff] [blame] | 63 | volatile uint32_t mUnderrunFrames; // server increments for each unavailable but desired frame | 
|  | 64 | volatile uint32_t mUnderrunCount;  // server increments for each underrun occurrence | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 65 | }; | 
|  | 66 |  | 
| Andy Hung | 9b46158 | 2014-12-01 17:56:29 -0800 | [diff] [blame] | 67 | // Represents a single state of an AudioTrack that was created in static mode (shared memory buffer | 
|  | 68 | // supplied by the client).  This state needs to be communicated from the client to server.  As this | 
|  | 69 | // state is too large to be updated atomically without a mutex, and mutexes aren't allowed here, the | 
|  | 70 | // state is wrapped by a SingleStateQueue. | 
|  | 71 | struct StaticAudioTrackState { | 
|  | 72 | // Do not define constructors, destructors, or virtual methods as this is part of a | 
|  | 73 | // union in shared memory and they will not get called properly. | 
|  | 74 |  | 
|  | 75 | // These fields should both be size_t, but since they are located in shared memory we | 
|  | 76 | // force to 32-bit.  The client and server may have different typedefs for size_t. | 
|  | 77 |  | 
|  | 78 | // The state has a sequence counter to indicate whether changes are made to loop or position. | 
|  | 79 | // The sequence counter also currently indicates whether loop or position is first depending | 
|  | 80 | // on which is greater; it jumps by max(mLoopSequence, mPositionSequence) + 1. | 
|  | 81 |  | 
|  | 82 | uint32_t    mLoopStart; | 
|  | 83 | uint32_t    mLoopEnd; | 
|  | 84 | int32_t     mLoopCount; | 
|  | 85 | uint32_t    mLoopSequence; // a sequence counter to indicate changes to loop | 
|  | 86 | uint32_t    mPosition; | 
|  | 87 | uint32_t    mPositionSequence; // a sequence counter to indicate changes to position | 
|  | 88 | }; | 
|  | 89 |  | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 90 | typedef SingleStateQueue<StaticAudioTrackState> StaticAudioTrackSingleStateQueue; | 
|  | 91 |  | 
| Andy Hung | 4ede21d | 2014-12-12 15:37:34 -0800 | [diff] [blame] | 92 | struct StaticAudioTrackPosLoop { | 
|  | 93 | // Do not define constructors, destructors, or virtual methods as this is part of a | 
|  | 94 | // union in shared memory and will not get called properly. | 
|  | 95 |  | 
|  | 96 | // These fields should both be size_t, but since they are located in shared memory we | 
|  | 97 | // force to 32-bit.  The client and server may have different typedefs for size_t. | 
|  | 98 |  | 
|  | 99 | // This struct information is stored in a single state queue to communicate the | 
|  | 100 | // static AudioTrack server state to the client while data is consumed. | 
|  | 101 | // It is smaller than StaticAudioTrackState to prevent unnecessary information from | 
|  | 102 | // being sent. | 
|  | 103 |  | 
|  | 104 | uint32_t mBufferPosition; | 
|  | 105 | int32_t  mLoopCount; | 
|  | 106 | }; | 
|  | 107 |  | 
|  | 108 | typedef SingleStateQueue<StaticAudioTrackPosLoop> StaticAudioTrackPosLoopQueue; | 
|  | 109 |  | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 110 | struct AudioTrackSharedStatic { | 
| Andy Hung | 4ede21d | 2014-12-12 15:37:34 -0800 | [diff] [blame] | 111 | // client requests to the server for loop or position changes. | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 112 | StaticAudioTrackSingleStateQueue::Shared | 
|  | 113 | mSingleStateQueue; | 
| Andy Hung | 4ede21d | 2014-12-12 15:37:34 -0800 | [diff] [blame] | 114 | // position info updated asynchronously by server and read by client, | 
|  | 115 | // "for entertainment purposes only" | 
|  | 116 | StaticAudioTrackPosLoopQueue::Shared | 
|  | 117 | mPosLoopQueue; | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 118 | }; | 
|  | 119 |  | 
| Ricardo Garcia | 5a8a95d | 2015-04-18 14:47:04 -0700 | [diff] [blame] | 120 | typedef SingleStateQueue<AudioPlaybackRate> PlaybackRateQueue; | 
| Andy Hung | 8edb8dc | 2015-03-26 19:13:55 -0700 | [diff] [blame] | 121 |  | 
| Andy Hung | 3f0c902 | 2016-01-15 17:49:46 -0800 | [diff] [blame] | 122 | typedef SingleStateQueue<ExtendedTimestamp> ExtendedTimestampQueue; | 
|  | 123 |  | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 124 | // ---------------------------------------------------------------------------- | 
|  | 125 |  | 
| Glenn Kasten | 1a0ae5b | 2012-02-03 10:24:48 -0800 | [diff] [blame] | 126 | // Important: do not add any virtual methods, including ~ | 
| The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 127 | struct audio_track_cblk_t | 
|  | 128 | { | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 129 | // Since the control block is always located in shared memory, this constructor | 
|  | 130 | // is only used for placement new().  It is never used for regular new() or stack. | 
|  | 131 | audio_track_cblk_t(); | 
|  | 132 | /*virtual*/ ~audio_track_cblk_t() { } | 
|  | 133 |  | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 134 | friend class Proxy; | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 135 | friend class ClientProxy; | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 136 | friend class AudioTrackClientProxy; | 
|  | 137 | friend class AudioRecordClientProxy; | 
|  | 138 | friend class ServerProxy; | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 139 | friend class AudioTrackServerProxy; | 
|  | 140 | friend class AudioRecordServerProxy; | 
| The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 141 |  | 
|  | 142 | // The data members are grouped so that members accessed frequently and in the same context | 
|  | 143 | // are in the same line of data cache. | 
| Glenn Kasten | 99e53b8 | 2012-01-19 08:59:58 -0800 | [diff] [blame] | 144 |  | 
| Glenn Kasten | f20e1d8 | 2013-07-12 09:45:18 -0700 | [diff] [blame] | 145 | uint32_t    mServer;    // Number of filled frames consumed by server (mIsOut), | 
|  | 146 | // or filled frames provided by server (!mIsOut). | 
|  | 147 | // It is updated asynchronously by server without a barrier. | 
| Glenn Kasten | b187de1 | 2014-12-30 08:18:15 -0800 | [diff] [blame] | 148 | // The value should be used | 
|  | 149 | // "for entertainment purposes only", | 
| Glenn Kasten | f20e1d8 | 2013-07-12 09:45:18 -0700 | [diff] [blame] | 150 | // which means don't make important decisions based on it. | 
| Glenn Kasten | 22eb4e2 | 2012-11-07 14:03:00 -0800 | [diff] [blame] | 151 |  | 
| Glenn Kasten | 74935e4 | 2013-12-19 08:56:45 -0800 | [diff] [blame] | 152 | uint32_t    mPad1;      // unused | 
| Glenn Kasten | 99e53b8 | 2012-01-19 08:59:58 -0800 | [diff] [blame] | 153 |  | 
| Glenn Kasten | 0d09a9b | 2013-06-24 12:06:46 -0700 | [diff] [blame] | 154 | volatile    int32_t     mFutex;     // event flag: down (P) by client, | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 155 | // up (V) by server or binderDied() or interrupt() | 
| Glenn Kasten | 0d09a9b | 2013-06-24 12:06:46 -0700 | [diff] [blame] | 156 | #define CBLK_FUTEX_WAKE 1               // if event flag bit is set, then a deferred wake is pending | 
| Glenn Kasten | 99e53b8 | 2012-01-19 08:59:58 -0800 | [diff] [blame] | 157 |  | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 158 | private: | 
|  | 159 |  | 
| Glenn Kasten | fdac7c0 | 2014-01-28 11:03:28 -0800 | [diff] [blame] | 160 | // This field should be a size_t, but since it is located in shared memory we | 
|  | 161 | // force to 32-bit.  The client and server may have different typedefs for size_t. | 
|  | 162 | uint32_t    mMinimum;       // server wakes up client if available >= mMinimum | 
| Glenn Kasten | b1cf75c | 2012-01-17 12:20:54 -0800 | [diff] [blame] | 163 |  | 
| Glenn Kasten | c56f342 | 2014-03-21 17:53:17 -0700 | [diff] [blame] | 164 | // Stereo gains for AudioTrack only, not used by AudioRecord. | 
|  | 165 | gain_minifloat_packed_t mVolumeLR; | 
| Glenn Kasten | b1cf75c | 2012-01-17 12:20:54 -0800 | [diff] [blame] | 166 |  | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 167 | uint32_t    mSampleRate;    // AudioTrack only: client's requested sample rate in Hz | 
|  | 168 | // or 0 == default. Write-only client, read-only server. | 
| Glenn Kasten | 99e53b8 | 2012-01-19 08:59:58 -0800 | [diff] [blame] | 169 |  | 
| Ricardo Garcia | 5a8a95d | 2015-04-18 14:47:04 -0700 | [diff] [blame] | 170 | PlaybackRateQueue::Shared mPlaybackRateQueue; | 
| Andy Hung | 8edb8dc | 2015-03-26 19:13:55 -0700 | [diff] [blame] | 171 |  | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 172 | // client write-only, server read-only | 
|  | 173 | uint16_t    mSendLevel;      // Fixed point U4.12 so 0x1000 means 1.0 | 
|  | 174 |  | 
| Colin Cross | b8c35f9 | 2017-04-27 16:15:51 -0700 | [diff] [blame] | 175 | uint16_t    mPad2 __attribute__((__unused__)); // unused | 
| Eric Laurent | d1b449a | 2010-05-14 03:26:45 -0700 | [diff] [blame] | 176 |  | 
| Andy Hung | 3f0c902 | 2016-01-15 17:49:46 -0800 | [diff] [blame] | 177 | // server write-only, client read | 
| Eric Laurent | 8ce8e26 | 2016-02-16 11:59:23 -0800 | [diff] [blame] | 178 | ExtendedTimestampQueue::Shared mExtendedTimestampQueue; | 
| Andy Hung | 818e7a3 | 2016-02-16 18:08:07 -0800 | [diff] [blame] | 179 |  | 
| Phil Burk | e8972b0 | 2016-03-04 11:29:57 -0800 | [diff] [blame] | 180 | // This is set by AudioTrack.setBufferSizeInFrames(). | 
|  | 181 | // A write will not fill the buffer above this limit. | 
|  | 182 | volatile    uint32_t   mBufferSizeInFrames;  // effective size of the buffer | 
|  | 183 |  | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 184 | public: | 
| Glenn Kasten | 99e53b8 | 2012-01-19 08:59:58 -0800 | [diff] [blame] | 185 |  | 
| Glenn Kasten | 96f60d8 | 2013-07-12 10:21:18 -0700 | [diff] [blame] | 186 | volatile    int32_t     mFlags;         // combinations of CBLK_* | 
| Eric Laurent | 38ccae2 | 2011-03-28 18:37:07 -0700 | [diff] [blame] | 187 |  | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 188 | public: | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 189 | union { | 
|  | 190 | AudioTrackSharedStreaming   mStreaming; | 
|  | 191 | AudioTrackSharedStatic      mStatic; | 
|  | 192 | int                         mAlign[8]; | 
|  | 193 | } u; | 
|  | 194 |  | 
|  | 195 | // Cache line boundary (32 bytes) | 
| The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 196 | }; | 
|  | 197 |  | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 198 | // ---------------------------------------------------------------------------- | 
|  | 199 |  | 
|  | 200 | // Proxy for shared memory control block, to isolate callers from needing to know the details. | 
|  | 201 | // There is exactly one ClientProxy and one ServerProxy per shared memory control block. | 
|  | 202 | // The proxies are located in normal memory, and are not multi-thread safe within a given side. | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 203 | class Proxy : public RefBase { | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 204 | protected: | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 205 | Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut, | 
|  | 206 | bool clientInServer); | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 207 | virtual ~Proxy() { } | 
|  | 208 |  | 
|  | 209 | public: | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 210 | struct Buffer { | 
|  | 211 | size_t  mFrameCount;            // number of frames available in this buffer | 
|  | 212 | void*   mRaw;                   // pointer to first frame | 
|  | 213 | size_t  mNonContig;             // number of additional non-contiguous frames available | 
|  | 214 | }; | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 215 |  | 
| Phil Burk | c0adecb | 2016-01-08 12:44:11 -0800 | [diff] [blame] | 216 | size_t frameCount() const { return mFrameCount; } | 
|  | 217 |  | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 218 | protected: | 
|  | 219 | // These refer to shared memory, and are virtual addresses with respect to the current process. | 
|  | 220 | // They may have different virtual addresses within the other process. | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 221 | audio_track_cblk_t* const   mCblk;  // the control block | 
|  | 222 | void* const     mBuffers;           // starting address of buffers | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 223 |  | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 224 | const size_t    mFrameCount;        // not necessarily a power of 2 | 
|  | 225 | const size_t    mFrameSize;         // in bytes | 
|  | 226 | const size_t    mFrameCountP2;      // mFrameCount rounded to power of 2, streaming mode | 
|  | 227 | const bool      mIsOut;             // true for AudioTrack, false for AudioRecord | 
|  | 228 | const bool      mClientInServer;    // true for OutputTrack, false for AudioTrack & AudioRecord | 
|  | 229 | bool            mIsShutdown;        // latch set to true when shared memory corruption detected | 
| Glenn Kasten | 7db7df0 | 2013-06-25 16:13:23 -0700 | [diff] [blame] | 230 | size_t          mUnreleased;        // unreleased frames remaining from most recent obtainBuffer | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 231 | }; | 
|  | 232 |  | 
|  | 233 | // ---------------------------------------------------------------------------- | 
|  | 234 |  | 
|  | 235 | // Proxy seen by AudioTrack client and AudioRecord client | 
|  | 236 | class ClientProxy : public Proxy { | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 237 | public: | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 238 | ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, | 
|  | 239 | bool isOut, bool clientInServer); | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 240 | virtual ~ClientProxy() { } | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 241 |  | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 242 | static const struct timespec kForever; | 
|  | 243 | static const struct timespec kNonBlocking; | 
|  | 244 |  | 
|  | 245 | // Obtain a buffer with filled frames (reading) or empty frames (writing). | 
|  | 246 | // It is permitted to call obtainBuffer() multiple times in succession, without any intervening | 
|  | 247 | // calls to releaseBuffer().  In that case, the final obtainBuffer() is the one that effectively | 
|  | 248 | // sets or extends the unreleased frame count. | 
|  | 249 | // On entry: | 
|  | 250 | //  buffer->mFrameCount should be initialized to maximum number of desired frames, | 
|  | 251 | //      which must be > 0. | 
|  | 252 | //  buffer->mNonContig is unused. | 
|  | 253 | //  buffer->mRaw is unused. | 
|  | 254 | //  requested is the requested timeout in local monotonic delta time units: | 
|  | 255 | //      NULL or &kNonBlocking means non-blocking (zero timeout). | 
|  | 256 | //      &kForever means block forever (infinite timeout). | 
|  | 257 | //      Other values mean a specific timeout in local monotonic delta time units. | 
|  | 258 | //  elapsed is a pointer to a location that will hold the total local monotonic time that | 
|  | 259 | //      elapsed while blocked, or NULL if not needed. | 
|  | 260 | // On exit: | 
|  | 261 | //  buffer->mFrameCount has the actual number of contiguous available frames, | 
|  | 262 | //      which is always 0 when the return status != NO_ERROR. | 
|  | 263 | //  buffer->mNonContig is the number of additional non-contiguous available frames. | 
|  | 264 | //  buffer->mRaw is a pointer to the first available frame, | 
|  | 265 | //      or NULL when buffer->mFrameCount == 0. | 
|  | 266 | // The return status is one of: | 
|  | 267 | //  NO_ERROR    Success, buffer->mFrameCount > 0. | 
|  | 268 | //  WOULD_BLOCK Non-blocking mode and no frames are available. | 
|  | 269 | //  TIMED_OUT   Timeout occurred before any frames became available. | 
|  | 270 | //              This can happen even for infinite timeout, due to a spurious wakeup. | 
|  | 271 | //              In this case, the caller should investigate and then re-try as appropriate. | 
|  | 272 | //  DEAD_OBJECT Server has died or invalidated, caller should destroy this proxy and re-create. | 
|  | 273 | //  -EINTR      Call has been interrupted.  Look around to see why, and then perhaps try again. | 
|  | 274 | //  NO_INIT     Shared memory is corrupt. | 
| Eric Laurent | 4d231dc | 2016-03-11 18:38:23 -0800 | [diff] [blame] | 275 | //  NOT_ENOUGH_DATA Server has disabled the track because of underrun: restart the track | 
|  | 276 | //              if still in active state. | 
| Glenn Kasten | 7db7df0 | 2013-06-25 16:13:23 -0700 | [diff] [blame] | 277 | // Assertion failure on entry, if buffer == NULL or buffer->mFrameCount == 0. | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 278 | status_t    obtainBuffer(Buffer* buffer, const struct timespec *requested = NULL, | 
|  | 279 | struct timespec *elapsed = NULL); | 
|  | 280 |  | 
|  | 281 | // Release (some of) the frames last obtained. | 
|  | 282 | // On entry, buffer->mFrameCount should have the number of frames to release, | 
|  | 283 | // which must (cumulatively) be <= the number of frames last obtained but not yet released. | 
|  | 284 | // buffer->mRaw is ignored, but is normally same pointer returned by last obtainBuffer(). | 
|  | 285 | // It is permitted to call releaseBuffer() multiple times to release the frames in chunks. | 
|  | 286 | // On exit: | 
|  | 287 | //  buffer->mFrameCount is zero. | 
|  | 288 | //  buffer->mRaw is NULL. | 
|  | 289 | void        releaseBuffer(Buffer* buffer); | 
|  | 290 |  | 
|  | 291 | // Call after detecting server's death | 
|  | 292 | void        binderDied(); | 
|  | 293 |  | 
|  | 294 | // Call to force an obtainBuffer() to return quickly with -EINTR | 
|  | 295 | void        interrupt(); | 
|  | 296 |  | 
| Andy Hung | 90e8a97 | 2015-11-09 16:42:40 -0800 | [diff] [blame] | 297 | Modulo<uint32_t> getPosition() { | 
| Glenn Kasten | f20e1d8 | 2013-07-12 09:45:18 -0700 | [diff] [blame] | 298 | return mEpoch + mCblk->mServer; | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 299 | } | 
|  | 300 |  | 
| Phil Burk | c0adecb | 2016-01-08 12:44:11 -0800 | [diff] [blame] | 301 | void        setEpoch(const Modulo<uint32_t> &epoch) { | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 302 | mEpoch = epoch; | 
|  | 303 | } | 
|  | 304 |  | 
|  | 305 | void        setMinimum(size_t minimum) { | 
| Glenn Kasten | fdac7c0 | 2014-01-28 11:03:28 -0800 | [diff] [blame] | 306 | // This can only happen on a 64-bit client | 
|  | 307 | if (minimum > UINT32_MAX) { | 
|  | 308 | minimum = UINT32_MAX; | 
|  | 309 | } | 
|  | 310 | mCblk->mMinimum = (uint32_t) minimum; | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 311 | } | 
|  | 312 |  | 
|  | 313 | // Return the number of frames that would need to be obtained and released | 
|  | 314 | // in order for the client to be aligned at start of buffer | 
|  | 315 | virtual size_t  getMisalignment(); | 
|  | 316 |  | 
| Andy Hung | 90e8a97 | 2015-11-09 16:42:40 -0800 | [diff] [blame] | 317 | Modulo<uint32_t> getEpoch() const { | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 318 | return mEpoch; | 
|  | 319 | } | 
|  | 320 |  | 
| Phil Burk | e8972b0 | 2016-03-04 11:29:57 -0800 | [diff] [blame] | 321 | uint32_t      getBufferSizeInFrames() const { return mBufferSizeInFrames; } | 
|  | 322 | // See documentation for AudioTrack::setBufferSizeInFrames() | 
|  | 323 | uint32_t      setBufferSizeInFrames(uint32_t requestedSize); | 
| Phil Burk | c0adecb | 2016-01-08 12:44:11 -0800 | [diff] [blame] | 324 |  | 
| Andy Hung | 6ae5843 | 2016-02-16 18:32:24 -0800 | [diff] [blame] | 325 | status_t    getTimestamp(ExtendedTimestamp *timestamp) { | 
|  | 326 | if (timestamp == nullptr) { | 
|  | 327 | return BAD_VALUE; | 
|  | 328 | } | 
|  | 329 | (void) mTimestampObserver.poll(mTimestamp); | 
|  | 330 | *timestamp = mTimestamp; | 
|  | 331 | return OK; | 
|  | 332 | } | 
|  | 333 |  | 
|  | 334 | void        clearTimestamp() { | 
|  | 335 | mTimestamp.clear(); | 
|  | 336 | } | 
|  | 337 |  | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 338 | private: | 
| Phil Burk | e8972b0 | 2016-03-04 11:29:57 -0800 | [diff] [blame] | 339 | // This is a copy of mCblk->mBufferSizeInFrames | 
|  | 340 | uint32_t   mBufferSizeInFrames;  // effective size of the buffer | 
|  | 341 |  | 
| Andy Hung | 90e8a97 | 2015-11-09 16:42:40 -0800 | [diff] [blame] | 342 | Modulo<uint32_t> mEpoch; | 
| Andy Hung | 6ae5843 | 2016-02-16 18:32:24 -0800 | [diff] [blame] | 343 |  | 
|  | 344 | // The shared buffer contents referred to by the timestamp observer | 
|  | 345 | // is initialized when the server proxy created.  A local zero timestamp | 
|  | 346 | // is initialized by the client constructor. | 
|  | 347 | ExtendedTimestampQueue::Observer mTimestampObserver; | 
|  | 348 | ExtendedTimestamp mTimestamp; // initialized by constructor | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 349 | }; | 
|  | 350 |  | 
|  | 351 | // ---------------------------------------------------------------------------- | 
|  | 352 |  | 
|  | 353 | // Proxy used by AudioTrack client, which also includes AudioFlinger::PlaybackThread::OutputTrack | 
|  | 354 | class AudioTrackClientProxy : public ClientProxy { | 
|  | 355 | public: | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 356 | AudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, | 
|  | 357 | size_t frameSize, bool clientInServer = false) | 
|  | 358 | : ClientProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, | 
| Andy Hung | 8edb8dc | 2015-03-26 19:13:55 -0700 | [diff] [blame] | 359 | clientInServer), | 
| Andy Hung | 6ae5843 | 2016-02-16 18:32:24 -0800 | [diff] [blame] | 360 | mPlaybackRateMutator(&cblk->mPlaybackRateQueue) { | 
|  | 361 | } | 
|  | 362 |  | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 363 | virtual ~AudioTrackClientProxy() { } | 
|  | 364 |  | 
|  | 365 | // No barriers on the following operations, so the ordering of loads/stores | 
|  | 366 | // with respect to other parameters is UNPREDICTABLE. That's considered safe. | 
|  | 367 |  | 
|  | 368 | // caller must limit to 0.0 <= sendLevel <= 1.0 | 
|  | 369 | void        setSendLevel(float sendLevel) { | 
|  | 370 | mCblk->mSendLevel = uint16_t(sendLevel * 0x1000); | 
|  | 371 | } | 
|  | 372 |  | 
| Glenn Kasten | c56f342 | 2014-03-21 17:53:17 -0700 | [diff] [blame] | 373 | // set stereo gains | 
|  | 374 | void        setVolumeLR(gain_minifloat_packed_t volumeLR) { | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 375 | mCblk->mVolumeLR = volumeLR; | 
|  | 376 | } | 
|  | 377 |  | 
|  | 378 | void        setSampleRate(uint32_t sampleRate) { | 
|  | 379 | mCblk->mSampleRate = sampleRate; | 
|  | 380 | } | 
|  | 381 |  | 
| Ricardo Garcia | 5a8a95d | 2015-04-18 14:47:04 -0700 | [diff] [blame] | 382 | void        setPlaybackRate(const AudioPlaybackRate& playbackRate) { | 
| Andy Hung | 8edb8dc | 2015-03-26 19:13:55 -0700 | [diff] [blame] | 383 | mPlaybackRateMutator.push(playbackRate); | 
|  | 384 | } | 
|  | 385 |  | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 386 | virtual void flush(); | 
|  | 387 |  | 
|  | 388 | virtual uint32_t    getUnderrunFrames() const { | 
|  | 389 | return mCblk->u.mStreaming.mUnderrunFrames; | 
|  | 390 | } | 
| Phil Burk | 2812d9e | 2016-01-04 10:34:30 -0800 | [diff] [blame] | 391 | virtual uint32_t    getUnderrunCount() const { | 
|  | 392 | return mCblk->u.mStreaming.mUnderrunCount; | 
|  | 393 | } | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 394 |  | 
|  | 395 | bool        clearStreamEndDone();   // and return previous value | 
|  | 396 |  | 
|  | 397 | bool        getStreamEndDone() const; | 
|  | 398 |  | 
| Richard Fitzgerald | b1a270d | 2013-05-14 12:12:21 +0100 | [diff] [blame] | 399 | status_t    waitStreamEndDone(const struct timespec *requested); | 
| Andy Hung | 8edb8dc | 2015-03-26 19:13:55 -0700 | [diff] [blame] | 400 |  | 
|  | 401 | private: | 
| Ricardo Garcia | 5a8a95d | 2015-04-18 14:47:04 -0700 | [diff] [blame] | 402 | PlaybackRateQueue::Mutator   mPlaybackRateMutator; | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 403 | }; | 
|  | 404 |  | 
|  | 405 | class StaticAudioTrackClientProxy : public AudioTrackClientProxy { | 
|  | 406 | public: | 
|  | 407 | StaticAudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, | 
|  | 408 | size_t frameSize); | 
|  | 409 | virtual ~StaticAudioTrackClientProxy() { } | 
|  | 410 |  | 
|  | 411 | virtual void    flush(); | 
|  | 412 |  | 
|  | 413 | #define MIN_LOOP    16  // minimum length of each loop iteration in frames | 
| Andy Hung | 9b46158 | 2014-12-01 17:56:29 -0800 | [diff] [blame] | 414 |  | 
|  | 415 | // setLoop(), setBufferPosition(), and setBufferPositionAndLoop() set the | 
|  | 416 | // static buffer position and looping parameters.  These commands are not | 
|  | 417 | // synchronous (they do not wait or block); instead they take effect at the | 
|  | 418 | // next buffer data read from the server side. However, the client side | 
|  | 419 | // getters will read a cached version of the position and loop variables | 
|  | 420 | // until the setting takes effect. | 
|  | 421 | // | 
|  | 422 | // setBufferPositionAndLoop() is equivalent to calling, in order, setLoop() and | 
|  | 423 | // setBufferPosition(). | 
|  | 424 | // | 
|  | 425 | // The functions should not be relied upon to do parameter or state checking. | 
|  | 426 | // That is done at the AudioTrack level. | 
|  | 427 |  | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 428 | void    setLoop(size_t loopStart, size_t loopEnd, int loopCount); | 
| Andy Hung | 9b46158 | 2014-12-01 17:56:29 -0800 | [diff] [blame] | 429 | void    setBufferPosition(size_t position); | 
|  | 430 | void    setBufferPositionAndLoop(size_t position, size_t loopStart, size_t loopEnd, | 
|  | 431 | int loopCount); | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 432 | size_t  getBufferPosition(); | 
| Andy Hung | 4ede21d | 2014-12-12 15:37:34 -0800 | [diff] [blame] | 433 | // getBufferPositionAndLoopCount() provides the proper snapshot of | 
|  | 434 | // position and loopCount together. | 
|  | 435 | void    getBufferPositionAndLoopCount(size_t *position, int *loopCount); | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 436 |  | 
|  | 437 | virtual size_t  getMisalignment() { | 
|  | 438 | return 0; | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 439 | } | 
|  | 440 |  | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 441 | virtual uint32_t    getUnderrunFrames() const { | 
|  | 442 | return 0; | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 443 | } | 
|  | 444 |  | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 445 | private: | 
|  | 446 | StaticAudioTrackSingleStateQueue::Mutator   mMutator; | 
| Andy Hung | 4ede21d | 2014-12-12 15:37:34 -0800 | [diff] [blame] | 447 | StaticAudioTrackPosLoopQueue::Observer      mPosLoopObserver; | 
| Andy Hung | 9b46158 | 2014-12-01 17:56:29 -0800 | [diff] [blame] | 448 | StaticAudioTrackState   mState;   // last communicated state to server | 
| Andy Hung | 4ede21d | 2014-12-12 15:37:34 -0800 | [diff] [blame] | 449 | StaticAudioTrackPosLoop mPosLoop; // snapshot of position and loop. | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 450 | }; | 
|  | 451 |  | 
|  | 452 | // ---------------------------------------------------------------------------- | 
|  | 453 |  | 
|  | 454 | // Proxy used by AudioRecord client | 
|  | 455 | class AudioRecordClientProxy : public ClientProxy { | 
|  | 456 | public: | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 457 | AudioRecordClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, | 
|  | 458 | size_t frameSize) | 
|  | 459 | : ClientProxy(cblk, buffers, frameCount, frameSize, | 
| Andy Hung | 6ae5843 | 2016-02-16 18:32:24 -0800 | [diff] [blame] | 460 | false /*isOut*/, false /*clientInServer*/) { } | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 461 | ~AudioRecordClientProxy() { } | 
| Andy Hung | 3f0c902 | 2016-01-15 17:49:46 -0800 | [diff] [blame] | 462 |  | 
| Andy Hung | 3f0c902 | 2016-01-15 17:49:46 -0800 | [diff] [blame] | 463 | // Advances the client read pointer to the server write head pointer | 
|  | 464 | // effectively flushing the client read buffer. The effect is | 
|  | 465 | // instantaneous. Returns the number of frames flushed. | 
|  | 466 | uint32_t    flush() { | 
|  | 467 | int32_t rear = android_atomic_acquire_load(&mCblk->u.mStreaming.mRear); | 
|  | 468 | int32_t front = mCblk->u.mStreaming.mFront; | 
|  | 469 | android_atomic_release_store(rear, &mCblk->u.mStreaming.mFront); | 
|  | 470 | return (Modulo<int32_t>(rear) - front).unsignedValue(); | 
|  | 471 | } | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 472 | }; | 
|  | 473 |  | 
|  | 474 | // ---------------------------------------------------------------------------- | 
|  | 475 |  | 
|  | 476 | // Proxy used by AudioFlinger server | 
|  | 477 | class ServerProxy : public Proxy { | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 478 | protected: | 
|  | 479 | ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, | 
|  | 480 | bool isOut, bool clientInServer); | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 481 | public: | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 482 | virtual ~ServerProxy() { } | 
|  | 483 |  | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 484 | // Obtain a buffer with filled frames (writing) or empty frames (reading). | 
|  | 485 | // It is permitted to call obtainBuffer() multiple times in succession, without any intervening | 
|  | 486 | // calls to releaseBuffer().  In that case, the final obtainBuffer() is the one that effectively | 
|  | 487 | // sets or extends the unreleased frame count. | 
|  | 488 | // Always non-blocking. | 
|  | 489 | // On entry: | 
|  | 490 | //  buffer->mFrameCount should be initialized to maximum number of desired frames, | 
|  | 491 | //      which must be > 0. | 
|  | 492 | //  buffer->mNonContig is unused. | 
|  | 493 | //  buffer->mRaw is unused. | 
| Glenn Kasten | 2e422c4 | 2013-10-18 13:00:29 -0700 | [diff] [blame] | 494 | //  ackFlush is true iff being called from Track::start to acknowledge a pending flush. | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 495 | // On exit: | 
|  | 496 | //  buffer->mFrameCount has the actual number of contiguous available frames, | 
|  | 497 | //      which is always 0 when the return status != NO_ERROR. | 
|  | 498 | //  buffer->mNonContig is the number of additional non-contiguous available frames. | 
|  | 499 | //  buffer->mRaw is a pointer to the first available frame, | 
|  | 500 | //      or NULL when buffer->mFrameCount == 0. | 
|  | 501 | // The return status is one of: | 
|  | 502 | //  NO_ERROR    Success, buffer->mFrameCount > 0. | 
|  | 503 | //  WOULD_BLOCK No frames are available. | 
|  | 504 | //  NO_INIT     Shared memory is corrupt. | 
| Glenn Kasten | 2e422c4 | 2013-10-18 13:00:29 -0700 | [diff] [blame] | 505 | virtual status_t    obtainBuffer(Buffer* buffer, bool ackFlush = false); | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 506 |  | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 507 | // Release (some of) the frames last obtained. | 
|  | 508 | // On entry, buffer->mFrameCount should have the number of frames to release, | 
|  | 509 | // which must (cumulatively) be <= the number of frames last obtained but not yet released. | 
|  | 510 | // It is permitted to call releaseBuffer() multiple times to release the frames in chunks. | 
|  | 511 | // buffer->mRaw is ignored, but is normally same pointer returned by last obtainBuffer(). | 
|  | 512 | // On exit: | 
|  | 513 | //  buffer->mFrameCount is zero. | 
|  | 514 | //  buffer->mRaw is NULL. | 
|  | 515 | virtual void        releaseBuffer(Buffer* buffer); | 
|  | 516 |  | 
| Andy Hung | 6ae5843 | 2016-02-16 18:32:24 -0800 | [diff] [blame] | 517 | // Return the total number of frames that AudioFlinger has obtained and released | 
|  | 518 | virtual int64_t     framesReleased() const { return mReleased; } | 
|  | 519 |  | 
|  | 520 | // Expose timestamp to client proxy. Should only be called by a single thread. | 
|  | 521 | virtual void        setTimestamp(const ExtendedTimestamp ×tamp) { | 
|  | 522 | mTimestampMutator.push(timestamp); | 
|  | 523 | } | 
|  | 524 |  | 
| Phil Burk | 4bb650b | 2016-09-09 12:11:17 -0700 | [diff] [blame] | 525 | // Flushes the shared ring buffer if the client had requested it using mStreaming.mFlush. | 
|  | 526 | // If flush occurs then: | 
|  | 527 | //   cblk->u.mStreaming.mFront, ServerProxy::mFlush and ServerProxy::mFlushed will be modified | 
|  | 528 | //   client will be notified via Futex | 
|  | 529 | virtual void    flushBufferIfNeeded(); | 
|  | 530 |  | 
| Andy Hung | ea2b9c0 | 2016-02-12 17:06:53 -0800 | [diff] [blame] | 531 | // Total count of the number of flushed frames since creation (never reset). | 
|  | 532 | virtual int64_t     framesFlushed() const { return mFlushed; } | 
|  | 533 |  | 
| Phil Burk | e8972b0 | 2016-03-04 11:29:57 -0800 | [diff] [blame] | 534 | // Get dynamic buffer size from the shared control block. | 
|  | 535 | uint32_t            getBufferSizeInFrames() const { | 
|  | 536 | return android_atomic_acquire_load((int32_t *)&mCblk->mBufferSizeInFrames); | 
|  | 537 | } | 
|  | 538 |  | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 539 | protected: | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 540 | size_t      mAvailToClient; // estimated frames available to client prior to releaseBuffer() | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 541 | int32_t     mFlush;         // our copy of cblk->u.mStreaming.mFlush, for streaming output only | 
| Andy Hung | 3f0c902 | 2016-01-15 17:49:46 -0800 | [diff] [blame] | 542 | int64_t     mReleased;      // our copy of cblk->mServer, at 64 bit resolution | 
| Andy Hung | ea2b9c0 | 2016-02-12 17:06:53 -0800 | [diff] [blame] | 543 | int64_t     mFlushed;       // flushed frames to account for client-server discrepancy | 
| Andy Hung | 6ae5843 | 2016-02-16 18:32:24 -0800 | [diff] [blame] | 544 | ExtendedTimestampQueue::Mutator mTimestampMutator; | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 545 | }; | 
|  | 546 |  | 
|  | 547 | // Proxy used by AudioFlinger for servicing AudioTrack | 
|  | 548 | class AudioTrackServerProxy : public ServerProxy { | 
|  | 549 | public: | 
|  | 550 | AudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 551 | size_t frameSize, bool clientInServer = false, uint32_t sampleRate = 0) | 
| Andy Hung | 8edb8dc | 2015-03-26 19:13:55 -0700 | [diff] [blame] | 552 | : ServerProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, clientInServer), | 
| Phil Burk | 2812d9e | 2016-01-04 10:34:30 -0800 | [diff] [blame] | 553 | mPlaybackRateObserver(&cblk->mPlaybackRateQueue), | 
| Andy Hung | 818e7a3 | 2016-02-16 18:08:07 -0800 | [diff] [blame] | 554 | mUnderrunCount(0), mUnderrunning(false), mDrained(true) { | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 555 | mCblk->mSampleRate = sampleRate; | 
| Ricardo Garcia | 5a8a95d | 2015-04-18 14:47:04 -0700 | [diff] [blame] | 556 | mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT; | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 557 | } | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 558 | protected: | 
|  | 559 | virtual ~AudioTrackServerProxy() { } | 
|  | 560 |  | 
|  | 561 | public: | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 562 | // return value of these methods must be validated by the caller | 
|  | 563 | uint32_t    getSampleRate() const { return mCblk->mSampleRate; } | 
|  | 564 | uint16_t    getSendLevel_U4_12() const { return mCblk->mSendLevel; } | 
| Glenn Kasten | c56f342 | 2014-03-21 17:53:17 -0700 | [diff] [blame] | 565 | gain_minifloat_packed_t getVolumeLR() const { return mCblk->mVolumeLR; } | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 566 |  | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 567 | // estimated total number of filled frames available to server to read, | 
|  | 568 | // which may include non-contiguous frames | 
|  | 569 | virtual size_t      framesReady(); | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 570 |  | 
| Andy Hung | 2c6c3bb | 2017-06-16 14:01:45 -0700 | [diff] [blame^] | 571 | // Safe frames ready query used by dump() - this has no side effects. | 
|  | 572 | virtual size_t      framesReadySafe() const; | 
|  | 573 |  | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 574 | // Currently AudioFlinger will call framesReady() for a fast track from two threads: | 
|  | 575 | // FastMixer thread, and normal mixer thread.  This is dangerous, as the proxy is intended | 
|  | 576 | // to be called from at most one thread of server, and one thread of client. | 
|  | 577 | // As a temporary workaround, this method informs the proxy implementation that it | 
|  | 578 | // should avoid doing a state queue poll from within framesReady(). | 
|  | 579 | // FIXME Change AudioFlinger to not call framesReady() from normal mixer thread. | 
|  | 580 | virtual void        framesReadyIsCalledByMultipleThreads() { } | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 581 |  | 
|  | 582 | bool     setStreamEndDone();    // and return previous value | 
| Glenn Kasten | 82aaf94 | 2013-07-17 16:05:07 -0700 | [diff] [blame] | 583 |  | 
|  | 584 | // Add to the tally of underrun frames, and inform client of underrun | 
|  | 585 | virtual void        tallyUnderrunFrames(uint32_t frameCount); | 
|  | 586 |  | 
|  | 587 | // Return the total number of frames which AudioFlinger desired but were unavailable, | 
|  | 588 | // and thus which resulted in an underrun. | 
|  | 589 | virtual uint32_t    getUnderrunFrames() const { return mCblk->u.mStreaming.mUnderrunFrames; } | 
| Glenn Kasten | bd096fd | 2013-08-23 13:53:56 -0700 | [diff] [blame] | 590 |  | 
| Andy Hung | 8edb8dc | 2015-03-26 19:13:55 -0700 | [diff] [blame] | 591 | // Return the playback speed and pitch read atomically. Not multi-thread safe on server side. | 
| Ricardo Garcia | 5a8a95d | 2015-04-18 14:47:04 -0700 | [diff] [blame] | 592 | AudioPlaybackRate getPlaybackRate(); | 
| Andy Hung | 8edb8dc | 2015-03-26 19:13:55 -0700 | [diff] [blame] | 593 |  | 
| Andy Hung | 818e7a3 | 2016-02-16 18:08:07 -0800 | [diff] [blame] | 594 | // Set the internal drain state of the track buffer from the timestamp received. | 
|  | 595 | virtual void        setDrained(bool drained) { | 
|  | 596 | mDrained.store(drained); | 
|  | 597 | } | 
|  | 598 |  | 
|  | 599 | // Check if the internal drain state of the track buffer. | 
|  | 600 | // This is not a guarantee, but advisory for determining whether the track is | 
|  | 601 | // fully played out. | 
|  | 602 | virtual bool        isDrained() const { | 
|  | 603 | return mDrained.load(); | 
|  | 604 | } | 
|  | 605 |  | 
| Andy Hung | 8edb8dc | 2015-03-26 19:13:55 -0700 | [diff] [blame] | 606 | private: | 
| Ricardo Garcia | 5a8a95d | 2015-04-18 14:47:04 -0700 | [diff] [blame] | 607 | AudioPlaybackRate             mPlaybackRate;  // last observed playback rate | 
|  | 608 | PlaybackRateQueue::Observer   mPlaybackRateObserver; | 
| Phil Burk | 2812d9e | 2016-01-04 10:34:30 -0800 | [diff] [blame] | 609 |  | 
|  | 610 | // The server keeps a copy here where it is safe from the client. | 
|  | 611 | uint32_t                      mUnderrunCount; // echoed to mCblk | 
|  | 612 | bool                          mUnderrunning;  // used to detect edge of underrun | 
| Andy Hung | 818e7a3 | 2016-02-16 18:08:07 -0800 | [diff] [blame] | 613 |  | 
|  | 614 | std::atomic<bool>             mDrained; // is the track buffer drained | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 615 | }; | 
|  | 616 |  | 
|  | 617 | class StaticAudioTrackServerProxy : public AudioTrackServerProxy { | 
|  | 618 | public: | 
|  | 619 | StaticAudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, | 
|  | 620 | size_t frameSize); | 
|  | 621 | protected: | 
|  | 622 | virtual ~StaticAudioTrackServerProxy() { } | 
|  | 623 |  | 
|  | 624 | public: | 
|  | 625 | virtual size_t      framesReady(); | 
| Andy Hung | 2c6c3bb | 2017-06-16 14:01:45 -0700 | [diff] [blame^] | 626 | virtual size_t      framesReadySafe() const override; | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 627 | virtual void        framesReadyIsCalledByMultipleThreads(); | 
| Glenn Kasten | 2e422c4 | 2013-10-18 13:00:29 -0700 | [diff] [blame] | 628 | virtual status_t    obtainBuffer(Buffer* buffer, bool ackFlush); | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 629 | virtual void        releaseBuffer(Buffer* buffer); | 
| Glenn Kasten | 82aaf94 | 2013-07-17 16:05:07 -0700 | [diff] [blame] | 630 | virtual void        tallyUnderrunFrames(uint32_t frameCount); | 
|  | 631 | virtual uint32_t    getUnderrunFrames() const { return 0; } | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 632 |  | 
|  | 633 | private: | 
| Andy Hung | 9b46158 | 2014-12-01 17:56:29 -0800 | [diff] [blame] | 634 | status_t            updateStateWithLoop(StaticAudioTrackState *localState, | 
|  | 635 | const StaticAudioTrackState &update) const; | 
|  | 636 | status_t            updateStateWithPosition(StaticAudioTrackState *localState, | 
|  | 637 | const StaticAudioTrackState &update) const; | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 638 | ssize_t             pollPosition(); // poll for state queue update, and return current position | 
|  | 639 | StaticAudioTrackSingleStateQueue::Observer  mObserver; | 
| Andy Hung | 4ede21d | 2014-12-12 15:37:34 -0800 | [diff] [blame] | 640 | StaticAudioTrackPosLoopQueue::Mutator       mPosLoopMutator; | 
| Andy Hung | cb2129b | 2014-11-11 12:17:22 -0800 | [diff] [blame] | 641 | size_t              mFramesReadySafe; // Assuming size_t read/writes are atomic on 32 / 64 bit | 
|  | 642 | // processors, this is a thread-safe version of | 
|  | 643 | // mFramesReady. | 
|  | 644 | int64_t             mFramesReady;     // The number of frames ready in the static buffer | 
|  | 645 | // including loops.  This is 64 bits since loop mode | 
|  | 646 | // can cause a track to appear to have a large number | 
|  | 647 | // of frames. INT64_MAX means an infinite loop. | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 648 | bool                mFramesReadyIsCalledByMultipleThreads; | 
| Andy Hung | 9b46158 | 2014-12-01 17:56:29 -0800 | [diff] [blame] | 649 | StaticAudioTrackState mState;         // Server side state. Any updates from client must be | 
|  | 650 | // passed by the mObserver SingleStateQueue. | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 651 | }; | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 652 |  | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 653 | // Proxy used by AudioFlinger for servicing AudioRecord | 
|  | 654 | class AudioRecordServerProxy : public ServerProxy { | 
|  | 655 | public: | 
|  | 656 | AudioRecordServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 657 | size_t frameSize, bool clientInServer) | 
| Andy Hung | 6ae5843 | 2016-02-16 18:32:24 -0800 | [diff] [blame] | 658 | : ServerProxy(cblk, buffers, frameCount, frameSize, false /*isOut*/, clientInServer) { } | 
| Andy Hung | 3f0c902 | 2016-01-15 17:49:46 -0800 | [diff] [blame] | 659 |  | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 660 | protected: | 
|  | 661 | virtual ~AudioRecordServerProxy() { } | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 662 | }; | 
| The Android Open Source Project | 89fa4ad | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 663 |  | 
|  | 664 | // ---------------------------------------------------------------------------- | 
|  | 665 |  | 
|  | 666 | }; // namespace android | 
|  | 667 |  | 
|  | 668 | #endif // ANDROID_AUDIO_TRACK_SHARED_H |