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() const = 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() const { 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 */ 208 virtual int32_t getFramesPerBurst() = 0; 209 210 /** 211 * Get the number of bytes in each audio frame. This is calculated using the channel count 212 * and the sample format. For example, a 2 channel floating point stream will have 213 * 2 * 4 = 8 bytes per frame. 214 * 215 * @return number of bytes in each audio frame. 216 */ getBytesPerFrame()217 int32_t getBytesPerFrame() const { return mChannelCount * getBytesPerSample(); } 218 219 /** 220 * Get the number of bytes per sample. This is calculated using the sample format. For example, 221 * a stream using 16-bit integer samples will have 2 bytes per sample. 222 * 223 * @return the number of bytes per sample. 224 */ 225 int32_t getBytesPerSample() const; 226 227 /** 228 * The number of audio frames written into the stream. 229 * This monotonic counter will never get reset. 230 * 231 * @return the number of frames written so far 232 */ 233 virtual int64_t getFramesWritten(); 234 235 /** 236 * The number of audio frames read from the stream. 237 * This monotonic counter will never get reset. 238 * 239 * @return the number of frames read so far 240 */ 241 virtual int64_t getFramesRead(); 242 243 /** 244 * Calculate the latency of a stream based on getTimestamp(). 245 * 246 * Output latency is the time it takes for a given frame to travel from the 247 * app to some type of digital-to-analog converter. If the DAC is external, for example 248 * in a USB interface or a TV connected by HDMI, then there may be additional latency 249 * that the Android device is unaware of. 250 * 251 * Input latency is the time it takes to a given frame to travel from an analog-to-digital 252 * converter (ADC) to the app. 253 * 254 * Note that the latency of an OUTPUT stream will increase abruptly when you write data to it 255 * and then decrease slowly over time as the data is consumed. 256 * 257 * The latency of an INPUT stream will decrease abruptly when you read data from it 258 * and then increase slowly over time as more data arrives. 259 * 260 * The latency of an OUTPUT stream is generally higher than the INPUT latency 261 * because an app generally tries to keep the OUTPUT buffer full and the INPUT buffer empty. 262 * 263 * @return a ResultWithValue which has a result of Result::OK and a value containing the latency 264 * in milliseconds, or a result of Result::Error*. 265 */ calculateLatencyMillis()266 virtual ResultWithValue<double> calculateLatencyMillis() { 267 return ResultWithValue<double>(Result::ErrorUnimplemented); 268 } 269 270 /** 271 * Get the estimated time that the frame at `framePosition` entered or left the audio processing 272 * pipeline. 273 * 274 * This can be used to coordinate events and interactions with the external environment, and to 275 * estimate the latency of an audio stream. An example of usage can be found in the hello-oboe 276 * sample (search for "calculateCurrentOutputLatencyMillis"). 277 * 278 * The time is based on the implementation's best effort, using whatever knowledge is available 279 * to the system, but cannot account for any delay unknown to the implementation. 280 * 281 * @deprecated since 1.0, use AudioStream::getTimestamp(clockid_t clockId) instead, which 282 * returns ResultWithValue 283 * @param clockId the type of clock to use e.g. CLOCK_MONOTONIC 284 * @param framePosition the frame number to query 285 * @param timeNanoseconds an output parameter which will contain the presentation timestamp 286 */ getTimestamp(clockid_t,int64_t *,int64_t *)287 virtual Result getTimestamp(clockid_t /* clockId */, 288 int64_t* /* framePosition */, 289 int64_t* /* timeNanoseconds */) { 290 return Result::ErrorUnimplemented; 291 } 292 293 /** 294 * Get the estimated time that the frame at `framePosition` entered or left the audio processing 295 * pipeline. 296 * 297 * This can be used to coordinate events and interactions with the external environment, and to 298 * estimate the latency of an audio stream. An example of usage can be found in the hello-oboe 299 * sample (search for "calculateCurrentOutputLatencyMillis"). 300 * 301 * The time is based on the implementation's best effort, using whatever knowledge is available 302 * to the system, but cannot account for any delay unknown to the implementation. 303 * 304 * @param clockId the type of clock to use e.g. CLOCK_MONOTONIC 305 * @return a FrameTimestamp containing the position and time at which a particular audio frame 306 * entered or left the audio processing pipeline, or an error if the operation failed. 307 */ 308 virtual ResultWithValue<FrameTimestamp> getTimestamp(clockid_t /* clockId */); 309 310 // ============== I/O =========================== 311 /** 312 * Write data from the supplied buffer into the stream. This method will block until the write 313 * is complete or it runs out of time. 314 * 315 * If `timeoutNanoseconds` is zero then this call will not wait. 316 * 317 * @param buffer The address of the first sample. 318 * @param numFrames Number of frames to write. Only complete frames will be written. 319 * @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion. 320 * @return a ResultWithValue which has a result of Result::OK and a value containing the number 321 * of frames actually written, or result of Result::Error*. 322 */ write(const void *,int32_t,int64_t)323 virtual ResultWithValue<int32_t> write(const void* /* buffer */, 324 int32_t /* numFrames */, 325 int64_t /* timeoutNanoseconds */ ) { 326 return ResultWithValue<int32_t>(Result::ErrorUnimplemented); 327 } 328 329 /** 330 * Read data into the supplied buffer from the stream. This method will block until the read 331 * is complete or it runs out of time. 332 * 333 * If `timeoutNanoseconds` is zero then this call will not wait. 334 * 335 * @param buffer The address of the first sample. 336 * @param numFrames Number of frames to read. Only complete frames will be read. 337 * @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion. 338 * @return a ResultWithValue which has a result of Result::OK and a value containing the number 339 * of frames actually read, or result of Result::Error*. 340 */ read(void *,int32_t,int64_t)341 virtual ResultWithValue<int32_t> read(void* /* buffer */, 342 int32_t /* numFrames */, 343 int64_t /* timeoutNanoseconds */) { 344 return ResultWithValue<int32_t>(Result::ErrorUnimplemented); 345 } 346 347 /** 348 * Get the underlying audio API which the stream uses. 349 * 350 * @return the API that this stream uses. 351 */ 352 virtual AudioApi getAudioApi() const = 0; 353 354 /** 355 * Returns true if the underlying audio API is AAudio. 356 * 357 * @return true if this stream is implemented using the AAudio API. 358 */ usesAAudio()359 bool usesAAudio() const { 360 return getAudioApi() == AudioApi::AAudio; 361 } 362 363 /** 364 * Only for debugging. Do not use in production. 365 * If you need to call this method something is wrong. 366 * If you think you need it for production then please let us know 367 * so we can modify Oboe so that you don't need this. 368 * 369 * @return nullptr or a pointer to a stream from the system API 370 */ getUnderlyingStream()371 virtual void *getUnderlyingStream() const { 372 return nullptr; 373 } 374 375 /** 376 * Launch a thread that will stop the stream. 377 */ 378 void launchStopThread(); 379 380 /** 381 * Update mFramesWritten. 382 * For internal use only. 383 */ 384 virtual void updateFramesWritten() = 0; 385 386 /** 387 * Update mFramesRead. 388 * For internal use only. 389 */ 390 virtual void updateFramesRead() = 0; 391 392 /* 393 * Swap old callback for new callback. 394 * This not atomic. 395 * This should only be used internally. 396 * @param dataCallback 397 * @return previous dataCallback 398 */ swapDataCallback(AudioStreamDataCallback * dataCallback)399 AudioStreamDataCallback *swapDataCallback(AudioStreamDataCallback *dataCallback) { 400 AudioStreamDataCallback *previousCallback = mDataCallback; 401 mDataCallback = dataCallback; 402 return previousCallback; 403 } 404 405 /* 406 * Swap old callback for new callback. 407 * This not atomic. 408 * This should only be used internally. 409 * @param errorCallback 410 * @return previous errorCallback 411 */ swapErrorCallback(AudioStreamErrorCallback * errorCallback)412 AudioStreamErrorCallback *swapErrorCallback(AudioStreamErrorCallback *errorCallback) { 413 AudioStreamErrorCallback *previousCallback = mErrorCallback; 414 mErrorCallback = errorCallback; 415 return previousCallback; 416 } 417 418 /** 419 * @return number of frames of data currently in the buffer 420 */ 421 ResultWithValue<int32_t> getAvailableFrames(); 422 423 /** 424 * Wait until the stream has a minimum amount of data available in its buffer. 425 * This can be used with an EXCLUSIVE MMAP input stream to avoid reading data too close to 426 * the DSP write position, which may cause glitches. 427 * 428 * @param numFrames minimum frames available 429 * @param timeoutNanoseconds 430 * @return number of frames available, ErrorTimeout 431 */ 432 ResultWithValue<int32_t> waitForAvailableFrames(int32_t numFrames, 433 int64_t timeoutNanoseconds); 434 435 /** 436 * @return last result passed from an error callback 437 */ getLastErrorCallbackResult()438 virtual oboe::Result getLastErrorCallbackResult() const { 439 return mErrorCallbackResult; 440 } 441 442 protected: 443 444 /** 445 * This is used to detect more than one error callback from a stream. 446 * These were bugs in some versions of Android that caused multiple error callbacks. 447 * Internal bug b/63087953 448 * 449 * Calling this sets an atomic<bool> true and returns the previous value. 450 * 451 * @return false on first call, true on subsequent calls 452 */ wasErrorCallbackCalled()453 bool wasErrorCallbackCalled() { 454 return mErrorCallbackCalled.exchange(true); 455 } 456 457 /** 458 * Wait for a transition from one state to another. 459 * @return OK if the endingState was observed, or ErrorUnexpectedState 460 * if any state that was not the startingState or endingState was observed 461 * or ErrorTimeout. 462 */ 463 virtual Result waitForStateTransition(StreamState startingState, 464 StreamState endingState, 465 int64_t timeoutNanoseconds); 466 467 /** 468 * Override this to provide a default for when the application did not specify a callback. 469 * 470 * @param audioData 471 * @param numFrames 472 * @return result 473 */ onDefaultCallback(void *,int)474 virtual DataCallbackResult onDefaultCallback(void* /* audioData */, int /* numFrames */) { 475 return DataCallbackResult::Stop; 476 } 477 478 /** 479 * Override this to provide your own behaviour for the audio callback 480 * 481 * @param audioData container array which audio frames will be written into or read from 482 * @param numFrames number of frames which were read/written 483 * @return the result of the callback: stop or continue 484 * 485 */ 486 DataCallbackResult fireDataCallback(void *audioData, int numFrames); 487 488 /** 489 * @return true if callbacks may be called 490 */ isDataCallbackEnabled()491 bool isDataCallbackEnabled() { 492 return mDataCallbackEnabled; 493 } 494 495 /** 496 * This can be set false internally to prevent callbacks 497 * after DataCallbackResult::Stop has been returned. 498 */ setDataCallbackEnabled(bool enabled)499 void setDataCallbackEnabled(bool enabled) { 500 mDataCallbackEnabled = enabled; 501 } 502 503 /* 504 * Set a weak_ptr to this stream from the shared_ptr so that we can 505 * later use a shared_ptr in the error callback. 506 */ setWeakThis(std::shared_ptr<oboe::AudioStream> & sharedStream)507 void setWeakThis(std::shared_ptr<oboe::AudioStream> &sharedStream) { 508 mWeakThis = sharedStream; 509 } 510 511 /* 512 * Make a shared_ptr that will prevent this stream from being deleted. 513 */ lockWeakThis()514 std::shared_ptr<oboe::AudioStream> lockWeakThis() { 515 return mWeakThis.lock(); 516 } 517 518 std::weak_ptr<AudioStream> mWeakThis; // weak pointer to this object 519 520 /** 521 * Number of frames which have been written into the stream 522 * 523 * This is signed integer to match the counters in AAudio. 524 * At audio rates, the counter will overflow in about six million years. 525 */ 526 std::atomic<int64_t> mFramesWritten{}; 527 528 /** 529 * Number of frames which have been read from the stream. 530 * 531 * This is signed integer to match the counters in AAudio. 532 * At audio rates, the counter will overflow in about six million years. 533 */ 534 std::atomic<int64_t> mFramesRead{}; 535 536 std::mutex mLock; // for synchronizing start/stop/close 537 538 oboe::Result mErrorCallbackResult = oboe::Result::OK; 539 540 private: 541 542 // Log the scheduler if it changes. 543 void checkScheduler(); 544 int mPreviousScheduler = -1; 545 546 std::atomic<bool> mDataCallbackEnabled{false}; 547 std::atomic<bool> mErrorCallbackCalled{false}; 548 549 }; 550 551 /** 552 * This struct is a stateless functor which closes an AudioStream prior to its deletion. 553 * This means it can be used to safely delete a smart pointer referring to an open stream. 554 */ 555 struct StreamDeleterFunctor { operatorStreamDeleterFunctor556 void operator()(AudioStream *audioStream) { 557 if (audioStream) { 558 audioStream->close(); 559 } 560 delete audioStream; 561 } 562 }; 563 } // namespace oboe 564 565 #endif /* OBOE_STREAM_H_ */ 566