1 /* 2 * Copyright 2016 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 OBOE_STREAM_H_ 18 #define OBOE_STREAM_H_ 19 20 #include <atomic> 21 #include <cstdint> 22 #include <ctime> 23 #include <mutex> 24 #include "oboe/Definitions.h" 25 #include "oboe/ResultWithValue.h" 26 #include "oboe/AudioStreamBuilder.h" 27 #include "oboe/AudioStreamBase.h" 28 29 /** WARNING - UNDER CONSTRUCTION - THIS API WILL CHANGE. */ 30 31 namespace oboe { 32 33 /** 34 * The default number of nanoseconds to wait for when performing state change operations on the 35 * stream, such as `start` and `stop`. 36 * 37 * @see oboe::AudioStream::start 38 */ 39 constexpr int64_t kDefaultTimeoutNanos = (2000 * kNanosPerMillisecond); 40 41 /** 42 * Base class for Oboe C++ audio stream. 43 */ 44 class AudioStream : public AudioStreamBase { 45 friend class AudioStreamBuilder; // allow access to setWeakThis() and lockWeakThis() 46 public: 47 AudioStream()48 AudioStream() {} 49 50 /** 51 * Construct an `AudioStream` using the given `AudioStreamBuilder` 52 * 53 * @param builder containing all the stream's attributes 54 */ 55 explicit AudioStream(const AudioStreamBuilder &builder); 56 57 virtual ~AudioStream() = default; 58 59 /** 60 * Open a stream based on the current settings. 61 * 62 * Note that we do not recommend re-opening a stream that has been closed. 63 * TODO Should we prevent re-opening? 64 * 65 * @return 66 */ open()67 virtual Result open() { 68 return Result::OK; // Called by subclasses. Might do more in the future. 69 } 70 71 /** 72 * Close the stream and deallocate any resources from the open() call. 73 */ 74 virtual Result close(); 75 76 /** 77 * Start the stream. This will block until the stream has been started, an error occurs 78 * or `timeoutNanoseconds` has been reached. 79 */ 80 virtual Result start(int64_t timeoutNanoseconds = kDefaultTimeoutNanos); 81 82 /** 83 * Pause the stream. This will block until the stream has been paused, an error occurs 84 * or `timeoutNanoseconds` has been reached. 85 */ 86 virtual Result pause(int64_t timeoutNanoseconds = kDefaultTimeoutNanos); 87 88 /** 89 * Flush the stream. This will block until the stream has been flushed, an error occurs 90 * or `timeoutNanoseconds` has been reached. 91 */ 92 virtual Result flush(int64_t timeoutNanoseconds = kDefaultTimeoutNanos); 93 94 /** 95 * Stop the stream. This will block until the stream has been stopped, an error occurs 96 * or `timeoutNanoseconds` has been reached. 97 */ 98 virtual Result stop(int64_t timeoutNanoseconds = kDefaultTimeoutNanos); 99 100 /* Asynchronous requests. 101 * Use waitForStateChange() if you need to wait for completion. 102 */ 103 104 /** 105 * Start the stream asynchronously. Returns immediately (does not block). Equivalent to calling 106 * `start(0)`. 107 */ 108 virtual Result requestStart() = 0; 109 110 /** 111 * Pause the stream asynchronously. Returns immediately (does not block). Equivalent to calling 112 * `pause(0)`. 113 */ 114 virtual Result requestPause() = 0; 115 116 /** 117 * Flush the stream asynchronously. Returns immediately (does not block). Equivalent to calling 118 * `flush(0)`. 119 */ 120 virtual Result requestFlush() = 0; 121 122 /** 123 * Stop the stream asynchronously. Returns immediately (does not block). Equivalent to calling 124 * `stop(0)`. 125 */ 126 virtual Result requestStop() = 0; 127 128 /** 129 * Query the current state, eg. StreamState::Pausing 130 * 131 * @return state or a negative error. 132 */ 133 virtual StreamState getState() = 0; 134 135 /** 136 * Wait until the stream's current state no longer matches the input state. 137 * The input state is passed to avoid race conditions caused by the state 138 * changing between calls. 139 * 140 * Note that generally applications do not need to call this. It is considered 141 * an advanced technique and is mostly used for testing. 142 * 143 * <pre><code> 144 * int64_t timeoutNanos = 500 * kNanosPerMillisecond; // arbitrary 1/2 second 145 * StreamState currentState = stream->getState(); 146 * StreamState nextState = StreamState::Unknown; 147 * while (result == Result::OK && currentState != StreamState::Paused) { 148 * result = stream->waitForStateChange( 149 * currentState, &nextState, timeoutNanos); 150 * currentState = nextState; 151 * } 152 * </code></pre> 153 * 154 * If the state does not change within the timeout period then it will 155 * return ErrorTimeout. This is true even if timeoutNanoseconds is zero. 156 * 157 * @param inputState The state we want to change away from. 158 * @param nextState Pointer to a variable that will be set to the new state. 159 * @param timeoutNanoseconds The maximum time to wait in nanoseconds. 160 * @return Result::OK or a Result::Error. 161 */ 162 virtual Result waitForStateChange(StreamState inputState, 163 StreamState *nextState, 164 int64_t timeoutNanoseconds) = 0; 165 166 /** 167 * This can be used to adjust the latency of the buffer by changing 168 * the threshold where blocking will occur. 169 * By combining this with getXRunCount(), the latency can be tuned 170 * at run-time for each device. 171 * 172 * This cannot be set higher than getBufferCapacity(). 173 * 174 * @param requestedFrames requested number of frames that can be filled without blocking 175 * @return the resulting buffer size in frames (obtained using value()) or an error (obtained 176 * using error()) 177 */ setBufferSizeInFrames(int32_t)178 virtual ResultWithValue<int32_t> setBufferSizeInFrames(int32_t /* requestedFrames */) { 179 return Result::ErrorUnimplemented; 180 } 181 182 /** 183 * An XRun is an Underrun or an Overrun. 184 * During playing, an underrun will occur if the stream is not written in time 185 * and the system runs out of valid data. 186 * During recording, an overrun will occur if the stream is not read in time 187 * and there is no place to put the incoming data so it is discarded. 188 * 189 * An underrun or overrun can cause an audible "pop" or "glitch". 190 * 191 * @return a result which is either Result::OK with the xRun count as the value, or a 192 * Result::Error* code 193 */ getXRunCount()194 virtual ResultWithValue<int32_t> getXRunCount() { 195 return ResultWithValue<int32_t>(Result::ErrorUnimplemented); 196 } 197 198 /** 199 * @return true if XRun counts are supported on the stream 200 */ 201 virtual bool isXRunCountSupported() const = 0; 202 203 /** 204 * Query the number of frames that are read or written by the endpoint at one time. 205 * 206 * @return burst size 207 */ getFramesPerBurst()208 int32_t getFramesPerBurst() const { 209 return mFramesPerBurst; 210 } 211 212 /** 213 * Get the number of bytes in each audio frame. This is calculated using the channel count 214 * and the sample format. For example, a 2 channel floating point stream will have 215 * 2 * 4 = 8 bytes per frame. 216 * 217 * @return number of bytes in each audio frame. 218 */ getBytesPerFrame()219 int32_t getBytesPerFrame() const { return mChannelCount * getBytesPerSample(); } 220 221 /** 222 * Get the number of bytes per sample. This is calculated using the sample format. For example, 223 * a stream using 16-bit integer samples will have 2 bytes per sample. 224 * 225 * @return the number of bytes per sample. 226 */ 227 int32_t getBytesPerSample() const; 228 229 /** 230 * The number of audio frames written into the stream. 231 * This monotonic counter will never get reset. 232 * 233 * @return the number of frames written so far 234 */ 235 virtual int64_t getFramesWritten(); 236 237 /** 238 * The number of audio frames read from the stream. 239 * This monotonic counter will never get reset. 240 * 241 * @return the number of frames read so far 242 */ 243 virtual int64_t getFramesRead(); 244 245 /** 246 * Calculate the latency of a stream based on getTimestamp(). 247 * 248 * Output latency is the time it takes for a given frame to travel from the 249 * app to some type of digital-to-analog converter. If the DAC is external, for example 250 * in a USB interface or a TV connected by HDMI, then there may be additional latency 251 * that the Android device is unaware of. 252 * 253 * Input latency is the time it takes to a given frame to travel from an analog-to-digital 254 * converter (ADC) to the app. 255 * 256 * Note that the latency of an OUTPUT stream will increase abruptly when you write data to it 257 * and then decrease slowly over time as the data is consumed. 258 * 259 * The latency of an INPUT stream will decrease abruptly when you read data from it 260 * and then increase slowly over time as more data arrives. 261 * 262 * The latency of an OUTPUT stream is generally higher than the INPUT latency 263 * because an app generally tries to keep the OUTPUT buffer full and the INPUT buffer empty. 264 * 265 * @return a ResultWithValue which has a result of Result::OK and a value containing the latency 266 * in milliseconds, or a result of Result::Error*. 267 */ calculateLatencyMillis()268 virtual ResultWithValue<double> calculateLatencyMillis() { 269 return ResultWithValue<double>(Result::ErrorUnimplemented); 270 } 271 272 /** 273 * Get the estimated time that the frame at `framePosition` entered or left the audio processing 274 * pipeline. 275 * 276 * This can be used to coordinate events and interactions with the external environment, and to 277 * estimate the latency of an audio stream. An example of usage can be found in the hello-oboe 278 * sample (search for "calculateCurrentOutputLatencyMillis"). 279 * 280 * The time is based on the implementation's best effort, using whatever knowledge is available 281 * to the system, but cannot account for any delay unknown to the implementation. 282 * 283 * @deprecated since 1.0, use AudioStream::getTimestamp(clockid_t clockId) instead, which 284 * returns ResultWithValue 285 * @param clockId the type of clock to use e.g. CLOCK_MONOTONIC 286 * @param framePosition the frame number to query 287 * @param timeNanoseconds an output parameter which will contain the presentation timestamp 288 */ getTimestamp(clockid_t,int64_t *,int64_t *)289 virtual Result getTimestamp(clockid_t /* clockId */, 290 int64_t* /* framePosition */, 291 int64_t* /* timeNanoseconds */) { 292 return Result::ErrorUnimplemented; 293 } 294 295 /** 296 * Get the estimated time that the frame at `framePosition` entered or left the audio processing 297 * pipeline. 298 * 299 * This can be used to coordinate events and interactions with the external environment, and to 300 * estimate the latency of an audio stream. An example of usage can be found in the hello-oboe 301 * sample (search for "calculateCurrentOutputLatencyMillis"). 302 * 303 * The time is based on the implementation's best effort, using whatever knowledge is available 304 * to the system, but cannot account for any delay unknown to the implementation. 305 * 306 * @param clockId the type of clock to use e.g. CLOCK_MONOTONIC 307 * @return a FrameTimestamp containing the position and time at which a particular audio frame 308 * entered or left the audio processing pipeline, or an error if the operation failed. 309 */ 310 virtual ResultWithValue<FrameTimestamp> getTimestamp(clockid_t /* clockId */); 311 312 // ============== I/O =========================== 313 /** 314 * Write data from the supplied buffer into the stream. This method will block until the write 315 * is complete or it runs out of time. 316 * 317 * If `timeoutNanoseconds` is zero then this call will not wait. 318 * 319 * @param buffer The address of the first sample. 320 * @param numFrames Number of frames to write. Only complete frames will be written. 321 * @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion. 322 * @return a ResultWithValue which has a result of Result::OK and a value containing the number 323 * of frames actually written, or result of Result::Error*. 324 */ write(const void *,int32_t,int64_t)325 virtual ResultWithValue<int32_t> write(const void* /* buffer */, 326 int32_t /* numFrames */, 327 int64_t /* timeoutNanoseconds */ ) { 328 return ResultWithValue<int32_t>(Result::ErrorUnimplemented); 329 } 330 331 /** 332 * Read data into the supplied buffer from the stream. This method will block until the read 333 * is complete or it runs out of time. 334 * 335 * If `timeoutNanoseconds` is zero then this call will not wait. 336 * 337 * @param buffer The address of the first sample. 338 * @param numFrames Number of frames to read. Only complete frames will be read. 339 * @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion. 340 * @return a ResultWithValue which has a result of Result::OK and a value containing the number 341 * of frames actually read, or result of Result::Error*. 342 */ read(void *,int32_t,int64_t)343 virtual ResultWithValue<int32_t> read(void* /* buffer */, 344 int32_t /* numFrames */, 345 int64_t /* timeoutNanoseconds */) { 346 return ResultWithValue<int32_t>(Result::ErrorUnimplemented); 347 } 348 349 /** 350 * Get the underlying audio API which the stream uses. 351 * 352 * @return the API that this stream uses. 353 */ 354 virtual AudioApi getAudioApi() const = 0; 355 356 /** 357 * Returns true if the underlying audio API is AAudio. 358 * 359 * @return true if this stream is implemented using the AAudio API. 360 */ usesAAudio()361 bool usesAAudio() const { 362 return getAudioApi() == AudioApi::AAudio; 363 } 364 365 /** 366 * Only for debugging. Do not use in production. 367 * If you need to call this method something is wrong. 368 * If you think you need it for production then please let us know 369 * so we can modify Oboe so that you don't need this. 370 * 371 * @return nullptr or a pointer to a stream from the system API 372 */ getUnderlyingStream()373 virtual void *getUnderlyingStream() const { 374 return nullptr; 375 } 376 377 /** 378 * Update mFramesWritten. 379 * For internal use only. 380 */ 381 virtual void updateFramesWritten() = 0; 382 383 /** 384 * Update mFramesRead. 385 * For internal use only. 386 */ 387 virtual void updateFramesRead() = 0; 388 389 /* 390 * Swap old callback for new callback. 391 * This not atomic. 392 * This should only be used internally. 393 * @param dataCallback 394 * @return previous dataCallback 395 */ swapDataCallback(AudioStreamDataCallback * dataCallback)396 AudioStreamDataCallback *swapDataCallback(AudioStreamDataCallback *dataCallback) { 397 AudioStreamDataCallback *previousCallback = mDataCallback; 398 mDataCallback = dataCallback; 399 return previousCallback; 400 } 401 402 /* 403 * Swap old callback for new callback. 404 * This not atomic. 405 * This should only be used internally. 406 * @param errorCallback 407 * @return previous errorCallback 408 */ swapErrorCallback(AudioStreamErrorCallback * errorCallback)409 AudioStreamErrorCallback *swapErrorCallback(AudioStreamErrorCallback *errorCallback) { 410 AudioStreamErrorCallback *previousCallback = mErrorCallback; 411 mErrorCallback = errorCallback; 412 return previousCallback; 413 } 414 415 /** 416 * @return number of frames of data currently in the buffer 417 */ 418 ResultWithValue<int32_t> getAvailableFrames(); 419 420 /** 421 * Wait until the stream has a minimum amount of data available in its buffer. 422 * This can be used with an EXCLUSIVE MMAP input stream to avoid reading data too close to 423 * the DSP write position, which may cause glitches. 424 * 425 * @param numFrames minimum frames available 426 * @param timeoutNanoseconds 427 * @return number of frames available, ErrorTimeout 428 */ 429 ResultWithValue<int32_t> waitForAvailableFrames(int32_t numFrames, 430 int64_t timeoutNanoseconds); 431 432 /** 433 * @return last result passed from an error callback 434 */ getLastErrorCallbackResult()435 virtual oboe::Result getLastErrorCallbackResult() const { 436 return mErrorCallbackResult; 437 } 438 439 protected: 440 441 /** 442 * This is used to detect more than one error callback from a stream. 443 * These were bugs in some versions of Android that caused multiple error callbacks. 444 * Internal bug b/63087953 445 * 446 * Calling this sets an atomic<bool> true and returns the previous value. 447 * 448 * @return false on first call, true on subsequent calls 449 */ wasErrorCallbackCalled()450 bool wasErrorCallbackCalled() { 451 return mErrorCallbackCalled.exchange(true); 452 } 453 454 /** 455 * Wait for a transition from one state to another. 456 * @return OK if the endingState was observed, or ErrorUnexpectedState 457 * if any state that was not the startingState or endingState was observed 458 * or ErrorTimeout. 459 */ 460 virtual Result waitForStateTransition(StreamState startingState, 461 StreamState endingState, 462 int64_t timeoutNanoseconds); 463 464 /** 465 * Override this to provide a default for when the application did not specify a callback. 466 * 467 * @param audioData 468 * @param numFrames 469 * @return result 470 */ onDefaultCallback(void *,int)471 virtual DataCallbackResult onDefaultCallback(void* /* audioData */, int /* numFrames */) { 472 return DataCallbackResult::Stop; 473 } 474 475 /** 476 * Override this to provide your own behaviour for the audio callback 477 * 478 * @param audioData container array which audio frames will be written into or read from 479 * @param numFrames number of frames which were read/written 480 * @return the result of the callback: stop or continue 481 * 482 */ 483 DataCallbackResult fireDataCallback(void *audioData, int numFrames); 484 485 /** 486 * @return true if callbacks may be called 487 */ isDataCallbackEnabled()488 bool isDataCallbackEnabled() { 489 return mDataCallbackEnabled; 490 } 491 492 /** 493 * This can be set false internally to prevent callbacks 494 * after DataCallbackResult::Stop has been returned. 495 */ setDataCallbackEnabled(bool enabled)496 void setDataCallbackEnabled(bool enabled) { 497 mDataCallbackEnabled = enabled; 498 } 499 500 /* 501 * Set a weak_ptr to this stream from the shared_ptr so that we can 502 * later use a shared_ptr in the error callback. 503 */ setWeakThis(std::shared_ptr<oboe::AudioStream> & sharedStream)504 void setWeakThis(std::shared_ptr<oboe::AudioStream> &sharedStream) { 505 mWeakThis = sharedStream; 506 } 507 508 /* 509 * Make a shared_ptr that will prevent this stream from being deleted. 510 */ lockWeakThis()511 std::shared_ptr<oboe::AudioStream> lockWeakThis() { 512 return mWeakThis.lock(); 513 } 514 515 std::weak_ptr<AudioStream> mWeakThis; // weak pointer to this object 516 517 /** 518 * Number of frames which have been written into the stream 519 * 520 * This is signed integer to match the counters in AAudio. 521 * At audio rates, the counter will overflow in about six million years. 522 */ 523 std::atomic<int64_t> mFramesWritten{}; 524 525 /** 526 * Number of frames which have been read from the stream. 527 * 528 * This is signed integer to match the counters in AAudio. 529 * At audio rates, the counter will overflow in about six million years. 530 */ 531 std::atomic<int64_t> mFramesRead{}; 532 533 std::mutex mLock; // for synchronizing start/stop/close 534 535 oboe::Result mErrorCallbackResult = oboe::Result::OK; 536 537 /** 538 * Number of frames which will be copied to/from the audio device in a single read/write 539 * operation 540 */ 541 int32_t mFramesPerBurst = kUnspecified; 542 543 private: 544 545 // Log the scheduler if it changes. 546 void checkScheduler(); 547 int mPreviousScheduler = -1; 548 549 std::atomic<bool> mDataCallbackEnabled{false}; 550 std::atomic<bool> mErrorCallbackCalled{false}; 551 }; 552 553 /** 554 * This struct is a stateless functor which closes an AudioStream prior to its deletion. 555 * This means it can be used to safely delete a smart pointer referring to an open stream. 556 */ 557 struct StreamDeleterFunctor { operatorStreamDeleterFunctor558 void operator()(AudioStream *audioStream) { 559 if (audioStream) { 560 audioStream->close(); 561 } 562 delete audioStream; 563 } 564 }; 565 } // namespace oboe 566 567 #endif /* OBOE_STREAM_H_ */ 568