Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2012 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_NBAIO_H |
| 18 | #define ANDROID_AUDIO_NBAIO_H |
| 19 | |
| 20 | // Non-blocking audio I/O interface |
| 21 | // |
| 22 | // This header file has the abstract interfaces only. Concrete implementation classes are declared |
| 23 | // elsewhere. Implementations _should_ be non-blocking for all methods, especially read() and |
| 24 | // write(), but this is not enforced. In general, implementations do not need to be multi-thread |
| 25 | // safe, and any exceptions are noted in the particular implementation. |
| 26 | |
| 27 | #include <limits.h> |
| 28 | #include <stdlib.h> |
John Grossman | 2c3b2da | 2012-08-02 17:08:54 -0700 | [diff] [blame] | 29 | #include <utils/Errors.h> |
Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 30 | #include <utils/RefBase.h> |
Glenn Kasten | 767094d | 2013-08-23 13:51:43 -0700 | [diff] [blame] | 31 | #include <media/AudioTimestamp.h> |
Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 32 | |
| 33 | namespace android { |
| 34 | |
| 35 | // In addition to the usual status_t |
| 36 | enum { |
| 37 | NEGOTIATE = 0x80000010, // Must (re-)negotiate format. For negotiate() only, the offeree |
| 38 | // doesn't accept offers, and proposes counter-offers |
| 39 | OVERRUN = 0x80000011, // availableToRead(), read(), or readVia() detected lost input due |
| 40 | // to overrun; an event is counted and the caller should re-try |
| 41 | UNDERRUN = 0x80000012, // availableToWrite(), write(), or writeVia() detected a gap in |
| 42 | // output due to underrun (not being called often enough, or with |
| 43 | // enough data); an event is counted and the caller should re-try |
| 44 | }; |
| 45 | |
| 46 | // Negotiation of format is based on the data provider and data sink, or the data consumer and |
| 47 | // data source, exchanging prioritized arrays of offers and counter-offers until a single offer is |
| 48 | // mutually agreed upon. Each offer is an NBAIO_Format. For simplicity and performance, |
Glenn Kasten | b64497e | 2012-10-01 09:47:30 -0700 | [diff] [blame] | 49 | // NBAIO_Format is a typedef that ties together the most important combinations of the various |
Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 50 | // attributes, rather than a struct with separate fields for format, sample rate, channel count, |
| 51 | // interleave, packing, alignment, etc. The reason is that NBAIO_Format tries to abstract out only |
Glenn Kasten | b64497e | 2012-10-01 09:47:30 -0700 | [diff] [blame] | 52 | // the combinations that are actually needed within AudioFlinger. If the list of combinations grows |
Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 53 | // too large, then this decision should be re-visited. |
Glenn Kasten | b64497e | 2012-10-01 09:47:30 -0700 | [diff] [blame] | 54 | // Sample rate and channel count are explicit, PCM interleaved 16-bit is assumed. |
| 55 | typedef unsigned NBAIO_Format; |
| 56 | enum { |
| 57 | Format_Invalid |
Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 58 | }; |
| 59 | |
| 60 | // Return the frame size of an NBAIO_Format in bytes |
Glenn Kasten | 72e54af | 2014-01-31 09:37:35 -0800 | [diff] [blame^] | 61 | size_t Format_frameSize(const NBAIO_Format& format); |
Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 62 | |
| 63 | // Return the frame size of an NBAIO_Format as a bit shift |
Glenn Kasten | 72e54af | 2014-01-31 09:37:35 -0800 | [diff] [blame^] | 64 | size_t Format_frameBitShift(const NBAIO_Format& format); |
Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 65 | |
| 66 | // Convert a sample rate in Hz and channel count to an NBAIO_Format |
| 67 | NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount); |
| 68 | |
| 69 | // Return the sample rate in Hz of an NBAIO_Format |
Glenn Kasten | 72e54af | 2014-01-31 09:37:35 -0800 | [diff] [blame^] | 70 | unsigned Format_sampleRate(const NBAIO_Format& format); |
Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 71 | |
| 72 | // Return the channel count of an NBAIO_Format |
Glenn Kasten | 72e54af | 2014-01-31 09:37:35 -0800 | [diff] [blame^] | 73 | unsigned Format_channelCount(const NBAIO_Format& format); |
Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 74 | |
| 75 | // Callbacks used by NBAIO_Sink::writeVia() and NBAIO_Source::readVia() below. |
| 76 | typedef ssize_t (*writeVia_t)(void *user, void *buffer, size_t count); |
John Grossman | 2c3b2da | 2012-08-02 17:08:54 -0700 | [diff] [blame] | 77 | typedef ssize_t (*readVia_t)(void *user, const void *buffer, |
| 78 | size_t count, int64_t readPTS); |
Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 79 | |
| 80 | // Abstract class (interface) representing a data port. |
| 81 | class NBAIO_Port : public RefBase { |
| 82 | |
| 83 | public: |
| 84 | |
| 85 | // negotiate() must called first. The purpose of negotiate() is to check compatibility of |
| 86 | // formats, not to automatically adapt if they are incompatible. It's the responsibility of |
| 87 | // whoever sets up the graph connections to make sure formats are compatible, and this method |
| 88 | // just verifies that. The edges are "dumb" and don't attempt to adapt to bad connections. |
| 89 | // How it works: offerer proposes an array of formats, in descending order of preference from |
| 90 | // offers[0] to offers[numOffers - 1]. If offeree accepts one of these formats, it returns |
| 91 | // the index of that offer. Otherwise, offeree sets numCounterOffers to the number of |
| 92 | // counter-offers (up to a maximumum of the entry value of numCounterOffers), fills in the |
| 93 | // provided array counterOffers[] with its counter-offers, in descending order of preference |
| 94 | // from counterOffers[0] to counterOffers[numCounterOffers - 1], and returns NEGOTIATE. |
| 95 | // Note that since the offerer allocates space for counter-offers, but only the offeree knows |
| 96 | // how many counter-offers it has, there may be insufficient space for all counter-offers. |
| 97 | // In that case, the offeree sets numCounterOffers to the requested number of counter-offers |
| 98 | // (which is greater than the entry value of numCounterOffers), fills in as many of the most |
| 99 | // important counterOffers as will fit, and returns NEGOTIATE. As this implies a re-allocation, |
| 100 | // it should be used as a last resort. It is preferable for the offerer to simply allocate a |
| 101 | // larger space to begin with, and/or for the offeree to tolerate a smaller space than desired. |
| 102 | // Alternatively, the offerer can pass NULL for offers and counterOffers, and zero for |
| 103 | // numOffers. This indicates that it has not allocated space for any counter-offers yet. |
| 104 | // In this case, the offerree should set numCounterOffers appropriately and return NEGOTIATE. |
| 105 | // Then the offerer will allocate the correct amount of memory and retry. |
| 106 | // Format_Invalid is not allowed as either an offer or counter-offer. |
| 107 | // Returns: |
| 108 | // >= 0 Offer accepted. |
| 109 | // NEGOTIATE No offer accepted, and counter-offer(s) optionally made. See above for details. |
| 110 | virtual ssize_t negotiate(const NBAIO_Format offers[], size_t numOffers, |
| 111 | NBAIO_Format counterOffers[], size_t& numCounterOffers); |
| 112 | |
| 113 | // Return the current negotiated format, or Format_Invalid if negotiation has not been done, |
| 114 | // or if re-negotiation is required. |
| 115 | virtual NBAIO_Format format() const { return mNegotiated ? mFormat : Format_Invalid; } |
| 116 | |
| 117 | protected: |
Glenn Kasten | 72e54af | 2014-01-31 09:37:35 -0800 | [diff] [blame^] | 118 | NBAIO_Port(const NBAIO_Format& format) : mNegotiated(false), mFormat(format), |
| 119 | mBitShift(Format_frameBitShift(format)) { } |
Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 120 | virtual ~NBAIO_Port() { } |
| 121 | |
| 122 | // Implementations are free to ignore these if they don't need them |
| 123 | |
| 124 | bool mNegotiated; // mNegotiated implies (mFormat != Format_Invalid) |
| 125 | NBAIO_Format mFormat; // (mFormat != Format_Invalid) does not imply mNegotiated |
| 126 | size_t mBitShift; // assign in parallel with any assignment to mFormat |
| 127 | }; |
| 128 | |
| 129 | // Abstract class (interface) representing a non-blocking data sink, for use by a data provider. |
| 130 | class NBAIO_Sink : public NBAIO_Port { |
| 131 | |
| 132 | public: |
| 133 | |
| 134 | // For the next two APIs: |
| 135 | // 32 bits rolls over after 27 hours at 44.1 kHz; if that concerns you then poll periodically. |
| 136 | |
| 137 | // Return the number of frames written successfully since construction. |
| 138 | virtual size_t framesWritten() const { return mFramesWritten; } |
| 139 | |
| 140 | // Number of frames lost due to underrun since construction. |
| 141 | virtual size_t framesUnderrun() const { return 0; } |
| 142 | |
| 143 | // Number of underruns since construction, where a set of contiguous lost frames is one event. |
| 144 | virtual size_t underruns() const { return 0; } |
| 145 | |
| 146 | // Estimate of number of frames that could be written successfully now without blocking. |
| 147 | // When a write() is actually attempted, the implementation is permitted to return a smaller or |
| 148 | // larger transfer count, however it will make a good faith effort to give an accurate estimate. |
| 149 | // Errors: |
| 150 | // NEGOTIATE (Re-)negotiation is needed. |
| 151 | // UNDERRUN write() has not been called frequently enough, or with enough frames to keep up. |
| 152 | // An underrun event is counted, and the caller should re-try this operation. |
| 153 | // WOULD_BLOCK Determining how many frames can be written without blocking would itself block. |
| 154 | virtual ssize_t availableToWrite() const { return SSIZE_MAX; } |
| 155 | |
| 156 | // Transfer data to sink from single input buffer. Implies a copy. |
| 157 | // Inputs: |
| 158 | // buffer Non-NULL buffer owned by provider. |
| 159 | // count Maximum number of frames to transfer. |
| 160 | // Return value: |
| 161 | // > 0 Number of frames successfully transferred prior to first error. |
| 162 | // = 0 Count was zero. |
| 163 | // < 0 status_t error occurred prior to the first frame transfer. |
| 164 | // Errors: |
| 165 | // NEGOTIATE (Re-)negotiation is needed. |
| 166 | // WOULD_BLOCK No frames can be transferred without blocking. |
| 167 | // UNDERRUN write() has not been called frequently enough, or with enough frames to keep up. |
| 168 | // An underrun event is counted, and the caller should re-try this operation. |
| 169 | virtual ssize_t write(const void *buffer, size_t count) = 0; |
| 170 | |
| 171 | // Transfer data to sink using a series of callbacks. More suitable for zero-fill, synthesis, |
| 172 | // and non-contiguous transfers (e.g. circular buffer or writev). |
| 173 | // Inputs: |
| 174 | // via Callback function that the sink will call as many times as needed to consume data. |
| 175 | // total Estimate of the number of frames the provider has available. This is an estimate, |
| 176 | // and it can provide a different number of frames during the series of callbacks. |
| 177 | // user Arbitrary void * reserved for data provider. |
| 178 | // block Number of frames per block, that is a suggested value for 'count' in each callback. |
| 179 | // Zero means no preference. This parameter is a hint only, and may be ignored. |
| 180 | // Return value: |
| 181 | // > 0 Total number of frames successfully transferred prior to first error. |
| 182 | // = 0 Count was zero. |
| 183 | // < 0 status_t error occurred prior to the first frame transfer. |
| 184 | // Errors: |
| 185 | // NEGOTIATE (Re-)negotiation is needed. |
| 186 | // WOULD_BLOCK No frames can be transferred without blocking. |
| 187 | // UNDERRUN write() has not been called frequently enough, or with enough frames to keep up. |
| 188 | // An underrun event is counted, and the caller should re-try this operation. |
| 189 | // |
| 190 | // The 'via' callback is called by the data sink as follows: |
| 191 | // Inputs: |
| 192 | // user Arbitrary void * reserved for data provider. |
| 193 | // buffer Non-NULL buffer owned by sink that callback should fill in with data, |
| 194 | // up to a maximum of 'count' frames. |
| 195 | // count Maximum number of frames to transfer during this callback. |
| 196 | // Return value: |
| 197 | // > 0 Number of frames successfully transferred during this callback prior to first error. |
| 198 | // = 0 Count was zero. |
| 199 | // < 0 status_t error occurred prior to the first frame transfer during this callback. |
| 200 | virtual ssize_t writeVia(writeVia_t via, size_t total, void *user, size_t block = 0); |
| 201 | |
John Grossman | 2c3b2da | 2012-08-02 17:08:54 -0700 | [diff] [blame] | 202 | // Get the time (on the LocalTime timeline) at which the first frame of audio of the next write |
| 203 | // operation to this sink will be eventually rendered by the HAL. |
| 204 | // Inputs: |
| 205 | // ts A pointer pointing to the int64_t which will hold the result. |
| 206 | // Return value: |
| 207 | // OK Everything went well, *ts holds the time at which the first audio frame of the next |
| 208 | // write operation will be rendered, or AudioBufferProvider::kInvalidPTS if this sink |
| 209 | // does not know the answer for some reason. Sinks which eventually lead to a HAL |
| 210 | // which implements get_next_write_timestamp may return Invalid temporarily if the DMA |
| 211 | // output of the audio driver has not started yet. Sinks which lead to a HAL which |
| 212 | // does not implement get_next_write_timestamp, or which don't lead to a HAL at all, |
| 213 | // will always return kInvalidPTS. |
| 214 | // <other> Something unexpected happened internally. Check the logs and start debugging. |
| 215 | virtual status_t getNextWriteTimestamp(int64_t *ts) { return INVALID_OPERATION; } |
| 216 | |
Glenn Kasten | 767094d | 2013-08-23 13:51:43 -0700 | [diff] [blame] | 217 | // Returns NO_ERROR if a timestamp is available. The timestamp includes the total number |
| 218 | // of frames presented to an external observer, together with the value of CLOCK_MONOTONIC |
| 219 | // as of this presentation count. |
| 220 | virtual status_t getTimestamp(AudioTimestamp& timestamp) { return INVALID_OPERATION; } |
| 221 | |
Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 222 | protected: |
Glenn Kasten | 72e54af | 2014-01-31 09:37:35 -0800 | [diff] [blame^] | 223 | NBAIO_Sink(const NBAIO_Format& format = Format_Invalid) : NBAIO_Port(format), mFramesWritten(0) { } |
Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 224 | virtual ~NBAIO_Sink() { } |
| 225 | |
| 226 | // Implementations are free to ignore these if they don't need them |
| 227 | size_t mFramesWritten; |
| 228 | }; |
| 229 | |
| 230 | // Abstract class (interface) representing a non-blocking data source, for use by a data consumer. |
| 231 | class NBAIO_Source : public NBAIO_Port { |
| 232 | |
| 233 | public: |
| 234 | |
| 235 | // For the next two APIs: |
| 236 | // 32 bits rolls over after 27 hours at 44.1 kHz; if that concerns you then poll periodically. |
| 237 | |
| 238 | // Number of frames read successfully since construction. |
| 239 | virtual size_t framesRead() const { return mFramesRead; } |
| 240 | |
| 241 | // Number of frames lost due to overrun since construction. |
| 242 | // Not const because implementations may need to do I/O. |
| 243 | virtual size_t framesOverrun() /*const*/ { return 0; } |
| 244 | |
| 245 | // Number of overruns since construction, where a set of contiguous lost frames is one event. |
| 246 | // Not const because implementations may need to do I/O. |
| 247 | virtual size_t overruns() /*const*/ { return 0; } |
| 248 | |
| 249 | // Estimate of number of frames that could be read successfully now. |
| 250 | // When a read() is actually attempted, the implementation is permitted to return a smaller or |
| 251 | // larger transfer count, however it will make a good faith effort to give an accurate estimate. |
| 252 | // Errors: |
| 253 | // NEGOTIATE (Re-)negotiation is needed. |
| 254 | // OVERRUN One or more frames were lost due to overrun, try again to read more recent data. |
| 255 | // WOULD_BLOCK Determining how many frames can be read without blocking would itself block. |
| 256 | virtual ssize_t availableToRead() { return SSIZE_MAX; } |
| 257 | |
| 258 | // Transfer data from source into single destination buffer. Implies a copy. |
| 259 | // Inputs: |
| 260 | // buffer Non-NULL destination buffer owned by consumer. |
| 261 | // count Maximum number of frames to transfer. |
John Grossman | 2c3b2da | 2012-08-02 17:08:54 -0700 | [diff] [blame] | 262 | // readPTS The presentation time (on the LocalTime timeline) for which data |
| 263 | // is being requested, or kInvalidPTS if not known. |
Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 264 | // Return value: |
| 265 | // > 0 Number of frames successfully transferred prior to first error. |
| 266 | // = 0 Count was zero. |
| 267 | // < 0 status_t error occurred prior to the first frame transfer. |
| 268 | // Errors: |
| 269 | // NEGOTIATE (Re-)negotiation is needed. |
| 270 | // WOULD_BLOCK No frames can be transferred without blocking. |
| 271 | // OVERRUN read() has not been called frequently enough, or with enough frames to keep up. |
| 272 | // One or more frames were lost due to overrun, try again to read more recent data. |
John Grossman | 2c3b2da | 2012-08-02 17:08:54 -0700 | [diff] [blame] | 273 | virtual ssize_t read(void *buffer, size_t count, int64_t readPTS) = 0; |
Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 274 | |
| 275 | // Transfer data from source using a series of callbacks. More suitable for zero-fill, |
| 276 | // synthesis, and non-contiguous transfers (e.g. circular buffer or readv). |
| 277 | // Inputs: |
| 278 | // via Callback function that the source will call as many times as needed to provide data. |
| 279 | // total Estimate of the number of frames the consumer desires. This is an estimate, |
| 280 | // and it can consume a different number of frames during the series of callbacks. |
| 281 | // user Arbitrary void * reserved for data consumer. |
John Grossman | 2c3b2da | 2012-08-02 17:08:54 -0700 | [diff] [blame] | 282 | // readPTS The presentation time (on the LocalTime timeline) for which data |
| 283 | // is being requested, or kInvalidPTS if not known. |
Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 284 | // block Number of frames per block, that is a suggested value for 'count' in each callback. |
| 285 | // Zero means no preference. This parameter is a hint only, and may be ignored. |
| 286 | // Return value: |
| 287 | // > 0 Total number of frames successfully transferred prior to first error. |
| 288 | // = 0 Count was zero. |
| 289 | // < 0 status_t error occurred prior to the first frame transfer. |
| 290 | // Errors: |
| 291 | // NEGOTIATE (Re-)negotiation is needed. |
| 292 | // WOULD_BLOCK No frames can be transferred without blocking. |
| 293 | // OVERRUN read() has not been called frequently enough, or with enough frames to keep up. |
| 294 | // One or more frames were lost due to overrun, try again to read more recent data. |
| 295 | // |
| 296 | // The 'via' callback is called by the data source as follows: |
| 297 | // Inputs: |
| 298 | // user Arbitrary void * reserved for data consumer. |
| 299 | // dest Non-NULL buffer owned by source that callback should consume data from, |
| 300 | // up to a maximum of 'count' frames. |
| 301 | // count Maximum number of frames to transfer during this callback. |
| 302 | // Return value: |
| 303 | // > 0 Number of frames successfully transferred during this callback prior to first error. |
| 304 | // = 0 Count was zero. |
| 305 | // < 0 status_t error occurred prior to the first frame transfer during this callback. |
John Grossman | 2c3b2da | 2012-08-02 17:08:54 -0700 | [diff] [blame] | 306 | virtual ssize_t readVia(readVia_t via, size_t total, void *user, |
| 307 | int64_t readPTS, size_t block = 0); |
Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 308 | |
Glenn Kasten | 894d6be | 2013-08-26 10:29:28 -0700 | [diff] [blame] | 309 | // Invoked asynchronously by corresponding sink when a new timestamp is available. |
| 310 | // Default implementation ignores the timestamp. |
| 311 | virtual void onTimestamp(const AudioTimestamp& timestamp) { } |
| 312 | |
Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 313 | protected: |
Glenn Kasten | 72e54af | 2014-01-31 09:37:35 -0800 | [diff] [blame^] | 314 | NBAIO_Source(const NBAIO_Format& format = Format_Invalid) : NBAIO_Port(format), mFramesRead(0) { } |
Glenn Kasten | 0106623 | 2012-02-27 11:50:44 -0800 | [diff] [blame] | 315 | virtual ~NBAIO_Source() { } |
| 316 | |
| 317 | // Implementations are free to ignore these if they don't need them |
| 318 | size_t mFramesRead; |
| 319 | }; |
| 320 | |
| 321 | } // namespace android |
| 322 | |
| 323 | #endif // ANDROID_AUDIO_NBAIO_H |