xref: /aosp_15_r20/external/oboe/include/oboe/AudioStream.h (revision 05767d913155b055644481607e6fa1e35e2fe72c)
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      * Free the audio resources associated with a stream created by AAudioStreamBuilder_openStream().
73      *
74      * AAudioStream_close() should be called at some point after calling this function.
75      *
76      * After this call, the stream will be in AAUDIO_STREAM_STATE_CLOSING
77      *
78      * This function is useful if you want to release the audio resources immediately, but still allow
79      * queries to the stream to occur from other threads. This often happens if you are monitoring
80      * stream progress from a UI thread.
81      *
82      * NOTE: This function is only fully implemented for MMAP streams, which are low latency streams
83      * supported by some devices. On other "Legacy" streams some audio resources will still be in use
84      * and some callbacks may still be in process after this call.
85      *
86      * Available in AAudio since API level 30. Returns Result::ErrorUnimplemented otherwise.
87      *
88      * * @return either Result::OK or an error.
89      */
release()90     virtual Result release() {
91         return Result::ErrorUnimplemented;
92     }
93 
94     /**
95      * Close the stream and deallocate any resources from the open() call.
96      */
97     virtual Result close();
98 
99     /**
100      * Start the stream. This will block until the stream has been started, an error occurs
101      * or `timeoutNanoseconds` has been reached.
102      */
103     virtual Result start(int64_t timeoutNanoseconds = kDefaultTimeoutNanos);
104 
105     /**
106      * Pause the stream. This will block until the stream has been paused, an error occurs
107      * or `timeoutNanoseconds` has been reached.
108      */
109     virtual Result pause(int64_t timeoutNanoseconds = kDefaultTimeoutNanos);
110 
111     /**
112      * Flush the stream. This will block until the stream has been flushed, an error occurs
113      * or `timeoutNanoseconds` has been reached.
114      */
115     virtual Result flush(int64_t timeoutNanoseconds = kDefaultTimeoutNanos);
116 
117     /**
118      * Stop the stream. This will block until the stream has been stopped, an error occurs
119      * or `timeoutNanoseconds` has been reached.
120      */
121     virtual Result stop(int64_t timeoutNanoseconds = kDefaultTimeoutNanos);
122 
123     /* Asynchronous requests.
124      * Use waitForStateChange() if you need to wait for completion.
125      */
126 
127     /**
128      * Start the stream asynchronously. Returns immediately (does not block). Equivalent to calling
129      * `start(0)`.
130      */
131     virtual Result requestStart() = 0;
132 
133     /**
134      * Pause the stream asynchronously. Returns immediately (does not block). Equivalent to calling
135      * `pause(0)`.
136      */
137     virtual Result requestPause() = 0;
138 
139     /**
140      * Flush the stream asynchronously. Returns immediately (does not block). Equivalent to calling
141      * `flush(0)`.
142      */
143     virtual Result requestFlush() = 0;
144 
145     /**
146      * Stop the stream asynchronously. Returns immediately (does not block). Equivalent to calling
147      * `stop(0)`.
148      */
149     virtual Result requestStop() = 0;
150 
151     /**
152      * Query the current state, eg. StreamState::Pausing
153      *
154      * @return state or a negative error.
155      */
156     virtual StreamState getState() = 0;
157 
158     /**
159      * Wait until the stream's current state no longer matches the input state.
160      * The input state is passed to avoid race conditions caused by the state
161      * changing between calls.
162      *
163      * Note that generally applications do not need to call this. It is considered
164      * an advanced technique and is mostly used for testing.
165      *
166      * <pre><code>
167      * int64_t timeoutNanos = 500 * kNanosPerMillisecond; // arbitrary 1/2 second
168      * StreamState currentState = stream->getState();
169      * StreamState nextState = StreamState::Unknown;
170      * while (result == Result::OK && currentState != StreamState::Paused) {
171      *     result = stream->waitForStateChange(
172      *                                   currentState, &nextState, timeoutNanos);
173      *     currentState = nextState;
174      * }
175      * </code></pre>
176      *
177      * If the state does not change within the timeout period then it will
178      * return ErrorTimeout. This is true even if timeoutNanoseconds is zero.
179      *
180      * @param inputState The state we want to change away from.
181      * @param nextState Pointer to a variable that will be set to the new state.
182      * @param timeoutNanoseconds The maximum time to wait in nanoseconds.
183      * @return Result::OK or a Result::Error.
184      */
185     virtual Result waitForStateChange(StreamState inputState,
186                                           StreamState *nextState,
187                                           int64_t timeoutNanoseconds) = 0;
188 
189     /**
190     * This can be used to adjust the latency of the buffer by changing
191     * the threshold where blocking will occur.
192     * By combining this with getXRunCount(), the latency can be tuned
193     * at run-time for each device.
194     *
195     * This cannot be set higher than getBufferCapacity().
196     *
197     * This should only be used with Output streams. It will
198     * be ignored for Input streams because they are generally kept as empty as possible.
199     *
200     * For OpenSL ES, this method only has an effect on output stream that do NOT
201     * use a callback. The blocking writes goes into a buffer in Oboe and the size of that
202     * buffer is controlled by this method.
203     *
204     * @param requestedFrames requested number of frames that can be filled without blocking
205     * @return the resulting buffer size in frames (obtained using value()) or an error (obtained
206     * using error())
207     */
setBufferSizeInFrames(int32_t)208     virtual ResultWithValue<int32_t> setBufferSizeInFrames(int32_t /* requestedFrames  */) {
209         return Result::ErrorUnimplemented;
210     }
211 
212     /**
213      * An XRun is an Underrun or an Overrun.
214      * During playing, an underrun will occur if the stream is not written in time
215      * and the system runs out of valid data.
216      * During recording, an overrun will occur if the stream is not read in time
217      * and there is no place to put the incoming data so it is discarded.
218      *
219      * An underrun or overrun can cause an audible "pop" or "glitch".
220      *
221      * @return a result which is either Result::OK with the xRun count as the value, or a
222      * Result::Error* code
223      */
getXRunCount()224     virtual ResultWithValue<int32_t> getXRunCount() {
225         return ResultWithValue<int32_t>(Result::ErrorUnimplemented);
226     }
227 
228     /**
229      * @return true if XRun counts are supported on the stream
230      */
231     virtual bool isXRunCountSupported() const = 0;
232 
233     /**
234      * Query the number of frames that are read or written by the endpoint at one time.
235      *
236      * @return burst size
237      */
getFramesPerBurst()238     int32_t getFramesPerBurst() const {
239         return mFramesPerBurst;
240     }
241 
242     /**
243      * Get the number of bytes in each audio frame. This is calculated using the channel count
244      * and the sample format. For example, a 2 channel floating point stream will have
245      * 2 * 4 = 8 bytes per frame.
246      *
247      * @return number of bytes in each audio frame.
248      */
getBytesPerFrame()249     int32_t getBytesPerFrame() const { return mChannelCount * getBytesPerSample(); }
250 
251     /**
252      * Get the number of bytes per sample. This is calculated using the sample format. For example,
253      * a stream using 16-bit integer samples will have 2 bytes per sample.
254      *
255      * @return the number of bytes per sample.
256      */
257     int32_t getBytesPerSample() const;
258 
259     /**
260      * The number of audio frames written into the stream.
261      * This monotonic counter will never get reset.
262      *
263      * @return the number of frames written so far
264      */
265     virtual int64_t getFramesWritten();
266 
267     /**
268      * The number of audio frames read from the stream.
269      * This monotonic counter will never get reset.
270      *
271      * @return the number of frames read so far
272      */
273     virtual int64_t getFramesRead();
274 
275     /**
276      * Calculate the latency of a stream based on getTimestamp().
277      *
278      * Output latency is the time it takes for a given frame to travel from the
279      * app to some type of digital-to-analog converter. If the DAC is external, for example
280      * in a USB interface or a TV connected by HDMI, then there may be additional latency
281      * that the Android device is unaware of.
282      *
283      * Input latency is the time it takes to a given frame to travel from an analog-to-digital
284      * converter (ADC) to the app.
285      *
286      * Note that the latency of an OUTPUT stream will increase abruptly when you write data to it
287      * and then decrease slowly over time as the data is consumed.
288      *
289      * The latency of an INPUT stream will decrease abruptly when you read data from it
290      * and then increase slowly over time as more data arrives.
291      *
292      * The latency of an OUTPUT stream is generally higher than the INPUT latency
293      * because an app generally tries to keep the OUTPUT buffer full and the INPUT buffer empty.
294      *
295      * Note that due to issues in Android before R, we recommend NOT calling
296      * this method from a data callback. See this tech note for more details.
297      * https://github.com/google/oboe/wiki/TechNote_ReleaseBuffer
298      *
299      * @return a ResultWithValue which has a result of Result::OK and a value containing the latency
300      * in milliseconds, or a result of Result::Error*.
301      */
calculateLatencyMillis()302     virtual ResultWithValue<double> calculateLatencyMillis() {
303         return ResultWithValue<double>(Result::ErrorUnimplemented);
304     }
305 
306     /**
307      * Get the estimated time that the frame at `framePosition` entered or left the audio processing
308      * pipeline.
309      *
310      * This can be used to coordinate events and interactions with the external environment, and to
311      * estimate the latency of an audio stream. An example of usage can be found in the hello-oboe
312      * sample (search for "calculateCurrentOutputLatencyMillis").
313      *
314      * The time is based on the implementation's best effort, using whatever knowledge is available
315      * to the system, but cannot account for any delay unknown to the implementation.
316      *
317      * Note that due to issues in Android before R, we recommend NOT calling
318      * this method from a data callback. See this tech note for more details.
319      * https://github.com/google/oboe/wiki/TechNote_ReleaseBuffer
320      *
321      * @deprecated since 1.0, use AudioStream::getTimestamp(clockid_t clockId) instead, which
322      * returns ResultWithValue
323      * @param clockId the type of clock to use e.g. CLOCK_MONOTONIC
324      * @param framePosition the frame number to query
325      * @param timeNanoseconds an output parameter which will contain the presentation timestamp
326      */
getTimestamp(clockid_t,int64_t *,int64_t *)327     virtual Result getTimestamp(clockid_t /* clockId  */,
328                                 int64_t* /* framePosition */,
329                                 int64_t* /* timeNanoseconds */) {
330         return Result::ErrorUnimplemented;
331     }
332 
333     /**
334      * Get the estimated time that the frame at `framePosition` entered or left the audio processing
335      * pipeline.
336      *
337      * This can be used to coordinate events and interactions with the external environment, and to
338      * estimate the latency of an audio stream. An example of usage can be found in the hello-oboe
339      * sample (search for "calculateCurrentOutputLatencyMillis").
340      *
341      * The time is based on the implementation's best effort, using whatever knowledge is available
342      * to the system, but cannot account for any delay unknown to the implementation.
343      *
344      * Note that due to issues in Android before R, we recommend NOT calling
345      * this method from a data callback. See this tech note for more details.
346      * https://github.com/google/oboe/wiki/TechNote_ReleaseBuffer
347      *
348      * See
349      * @param clockId the type of clock to use e.g. CLOCK_MONOTONIC
350      * @return a FrameTimestamp containing the position and time at which a particular audio frame
351      * entered or left the audio processing pipeline, or an error if the operation failed.
352      */
353     virtual ResultWithValue<FrameTimestamp> getTimestamp(clockid_t /* clockId */);
354 
355     // ============== I/O ===========================
356     /**
357      * Write data from the supplied buffer into the stream. This method will block until the write
358      * is complete or it runs out of time.
359      *
360      * If `timeoutNanoseconds` is zero then this call will not wait.
361      *
362      * @param buffer The address of the first sample.
363      * @param numFrames Number of frames to write. Only complete frames will be written.
364      * @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion.
365      * @return a ResultWithValue which has a result of Result::OK and a value containing the number
366      * of frames actually written, or result of Result::Error*.
367      */
write(const void *,int32_t,int64_t)368     virtual ResultWithValue<int32_t> write(const void* /* buffer */,
369                              int32_t /* numFrames */,
370                              int64_t /* timeoutNanoseconds */ ) {
371         return ResultWithValue<int32_t>(Result::ErrorUnimplemented);
372     }
373 
374     /**
375      * Read data into the supplied buffer from the stream. This method will block until the read
376      * is complete or it runs out of time.
377      *
378      * If `timeoutNanoseconds` is zero then this call will not wait.
379      *
380      * @param buffer The address of the first sample.
381      * @param numFrames Number of frames to read. Only complete frames will be read.
382      * @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion.
383      * @return a ResultWithValue which has a result of Result::OK and a value containing the number
384      * of frames actually read, or result of Result::Error*.
385      */
read(void *,int32_t,int64_t)386     virtual ResultWithValue<int32_t> read(void* /* buffer */,
387                             int32_t /* numFrames */,
388                             int64_t /* timeoutNanoseconds */) {
389         return ResultWithValue<int32_t>(Result::ErrorUnimplemented);
390     }
391 
392     /**
393      * Get the underlying audio API which the stream uses.
394      *
395      * @return the API that this stream uses.
396      */
397     virtual AudioApi getAudioApi() const = 0;
398 
399     /**
400      * Returns true if the underlying audio API is AAudio.
401      *
402      * @return true if this stream is implemented using the AAudio API.
403      */
usesAAudio()404     bool usesAAudio() const {
405         return getAudioApi() == AudioApi::AAudio;
406     }
407 
408     /**
409      * Only for debugging. Do not use in production.
410      * If you need to call this method something is wrong.
411      * If you think you need it for production then please let us know
412      * so we can modify Oboe so that you don't need this.
413      *
414      * @return nullptr or a pointer to a stream from the system API
415      */
getUnderlyingStream()416     virtual void *getUnderlyingStream() const {
417         return nullptr;
418     }
419 
420     /**
421      * Update mFramesWritten.
422      * For internal use only.
423      */
424     virtual void updateFramesWritten() = 0;
425 
426     /**
427      * Update mFramesRead.
428      * For internal use only.
429      */
430     virtual void updateFramesRead() = 0;
431 
432     /*
433      * Swap old callback for new callback.
434      * This not atomic.
435      * This should only be used internally.
436      * @param dataCallback
437      * @return previous dataCallback
438      */
swapDataCallback(AudioStreamDataCallback * dataCallback)439     AudioStreamDataCallback *swapDataCallback(AudioStreamDataCallback *dataCallback) {
440         AudioStreamDataCallback *previousCallback = mDataCallback;
441         mDataCallback = dataCallback;
442         return previousCallback;
443     }
444 
445     /*
446      * Swap old callback for new callback.
447      * This not atomic.
448      * This should only be used internally.
449      * @param errorCallback
450      * @return previous errorCallback
451      */
swapErrorCallback(AudioStreamErrorCallback * errorCallback)452     AudioStreamErrorCallback *swapErrorCallback(AudioStreamErrorCallback *errorCallback) {
453         AudioStreamErrorCallback *previousCallback = mErrorCallback;
454         mErrorCallback = errorCallback;
455         return previousCallback;
456     }
457 
458     /**
459      * @return number of frames of data currently in the buffer
460      */
461     ResultWithValue<int32_t> getAvailableFrames();
462 
463     /**
464      * Wait until the stream has a minimum amount of data available in its buffer.
465      * This can be used with an EXCLUSIVE MMAP input stream to avoid reading data too close to
466      * the DSP write position, which may cause glitches.
467      *
468      * Starting with Oboe 1.7.1, the numFrames will be clipped internally against the
469      * BufferCapacity minus BurstSize. This is to prevent trying to wait for more frames
470      * than could possibly be available. In this case, the return value may be less than numFrames.
471      * Note that there may still be glitching if numFrames is too high.
472      *
473      * @param numFrames requested minimum frames available
474      * @param timeoutNanoseconds
475      * @return number of frames available, ErrorTimeout
476      */
477     ResultWithValue<int32_t> waitForAvailableFrames(int32_t numFrames,
478                                                     int64_t timeoutNanoseconds);
479 
480     /**
481      * @return last result passed from an error callback
482      */
getLastErrorCallbackResult()483     virtual oboe::Result getLastErrorCallbackResult() const {
484         return mErrorCallbackResult;
485     }
486 
487 
getDelayBeforeCloseMillis()488     int32_t getDelayBeforeCloseMillis() const {
489         return mDelayBeforeCloseMillis;
490     }
491 
492     /**
493      * Set the time to sleep before closing the internal stream.
494      *
495      * Sometimes a callback can occur shortly after a stream has been stopped and
496      * even after a close! If the stream has been closed then the callback
497      * might access memory that has been freed, which could cause a crash.
498      * This seems to be more likely in Android P or earlier.
499      * But it can also occur in later versions. By sleeping, we give time for
500      * the callback threads to finish.
501      *
502      * Note that this only has an effect when OboeGlobals::areWorkaroundsEnabled() is true.
503      *
504      * @param delayBeforeCloseMillis time to sleep before close.
505      */
setDelayBeforeCloseMillis(int32_t delayBeforeCloseMillis)506     void setDelayBeforeCloseMillis(int32_t delayBeforeCloseMillis) {
507         mDelayBeforeCloseMillis = delayBeforeCloseMillis;
508     }
509 
510     /**
511      * Enable or disable a device specific CPU performance hint.
512      * Runtime benchmarks such as the callback duration may be used to
513      * speed up the CPU and improve real-time performance.
514      *
515      * Note that this feature is device specific and may not be implemented.
516      * Also the benefits may vary by device.
517      *
518      * The flag will be checked in the Oboe data callback. If it transitions from false to true
519      * then the PerformanceHint feature will be started.
520      * This only needs to be called once.
521      *
522      * You may want to enable this if you have a dynamically changing workload
523      * and you notice that you are getting underruns and glitches when your workload increases.
524      * This might happen, for example, if you suddenly go from playing one note to
525      * ten notes on a synthesizer.
526      *
527      * Try the CPU Load test in OboeTester if you would like to experiment with this interactively.
528      *
529      * On some devices, this may be implemented using the "ADPF" library.
530      *
531      * @param enabled true if you would like a performance boost
532      */
setPerformanceHintEnabled(bool enabled)533     void setPerformanceHintEnabled(bool enabled) {
534         mPerformanceHintEnabled = enabled;
535     }
536 
537     /**
538      * This only tells you if the feature has been requested.
539      * It does not tell you if the PerformanceHint feature is implemented or active on the device.
540      *
541      * @return true if set using setPerformanceHintEnabled().
542      */
isPerformanceHintEnabled()543     bool isPerformanceHintEnabled() {
544         return mPerformanceHintEnabled;
545     }
546 
547 protected:
548 
549     /**
550      * This is used to detect more than one error callback from a stream.
551      * These were bugs in some versions of Android that caused multiple error callbacks.
552      * Internal bug b/63087953
553      *
554      * Calling this sets an atomic<bool> true and returns the previous value.
555      *
556      * @return false on first call, true on subsequent calls
557      */
wasErrorCallbackCalled()558     bool wasErrorCallbackCalled() {
559         return mErrorCallbackCalled.exchange(true);
560     }
561 
562     /**
563      * Wait for a transition from one state to another.
564      * @return OK if the endingState was observed, or ErrorUnexpectedState
565      *   if any state that was not the startingState or endingState was observed
566      *   or ErrorTimeout.
567      */
568     virtual Result waitForStateTransition(StreamState startingState,
569                                           StreamState endingState,
570                                           int64_t timeoutNanoseconds);
571 
572     /**
573      * Override this to provide a default for when the application did not specify a callback.
574      *
575      * @param audioData
576      * @param numFrames
577      * @return result
578      */
onDefaultCallback(void *,int)579     virtual DataCallbackResult onDefaultCallback(void* /* audioData  */, int /* numFrames */) {
580         return DataCallbackResult::Stop;
581     }
582 
583     /**
584      * Override this to provide your own behaviour for the audio callback
585      *
586      * @param audioData container array which audio frames will be written into or read from
587      * @param numFrames number of frames which were read/written
588      * @return the result of the callback: stop or continue
589      *
590      */
591     DataCallbackResult fireDataCallback(void *audioData, int numFrames);
592 
593     /**
594      * @return true if callbacks may be called
595      */
isDataCallbackEnabled()596     bool isDataCallbackEnabled() {
597         return mDataCallbackEnabled;
598     }
599 
600     /**
601      * This can be set false internally to prevent callbacks
602      * after DataCallbackResult::Stop has been returned.
603      */
setDataCallbackEnabled(bool enabled)604     void setDataCallbackEnabled(bool enabled) {
605         mDataCallbackEnabled = enabled;
606     }
607 
608     /**
609      * This should only be called as a stream is being opened.
610      * Otherwise we might override setDelayBeforeCloseMillis().
611      */
612     void calculateDefaultDelayBeforeCloseMillis();
613 
614     /**
615      * Try to avoid a race condition when closing.
616      */
sleepBeforeClose()617     void sleepBeforeClose() {
618         if (mDelayBeforeCloseMillis > 0) {
619             usleep(mDelayBeforeCloseMillis * 1000);
620         }
621     }
622 
623     /**
624      * This may be called internally at the beginning of a callback.
625      */
beginPerformanceHintInCallback()626     virtual void beginPerformanceHintInCallback() {}
627 
628     /**
629      * This may be called internally at the end of a callback.
630      * @param numFrames passed to the callback
631      */
endPerformanceHintInCallback(int32_t)632     virtual void endPerformanceHintInCallback(int32_t /*numFrames*/) {}
633 
634     /**
635      * This will be called when the stream is closed just in case performance hints were enabled.
636      */
closePerformanceHint()637     virtual void closePerformanceHint() {}
638 
639     /*
640      * Set a weak_ptr to this stream from the shared_ptr so that we can
641      * later use a shared_ptr in the error callback.
642      */
setWeakThis(std::shared_ptr<oboe::AudioStream> & sharedStream)643     void setWeakThis(std::shared_ptr<oboe::AudioStream> &sharedStream) {
644         mWeakThis = sharedStream;
645     }
646 
647     /*
648      * Make a shared_ptr that will prevent this stream from being deleted.
649      */
lockWeakThis()650     std::shared_ptr<oboe::AudioStream> lockWeakThis() {
651         return mWeakThis.lock();
652     }
653 
654     std::weak_ptr<AudioStream> mWeakThis; // weak pointer to this object
655 
656     /**
657      * Number of frames which have been written into the stream
658      *
659      * This is signed integer to match the counters in AAudio.
660      * At audio rates, the counter will overflow in about six million years.
661      */
662     std::atomic<int64_t> mFramesWritten{};
663 
664     /**
665      * Number of frames which have been read from the stream.
666      *
667      * This is signed integer to match the counters in AAudio.
668      * At audio rates, the counter will overflow in about six million years.
669      */
670     std::atomic<int64_t> mFramesRead{};
671 
672     std::mutex           mLock; // for synchronizing start/stop/close
673 
674     oboe::Result         mErrorCallbackResult = oboe::Result::OK;
675 
676     /**
677      * Number of frames which will be copied to/from the audio device in a single read/write
678      * operation
679      */
680     int32_t              mFramesPerBurst = kUnspecified;
681 
682     // Time to sleep in order to prevent a race condition with a callback after a close().
683     // Two milliseconds may be enough but 10 msec is even safer.
684     static constexpr int kMinDelayBeforeCloseMillis = 10;
685     int32_t              mDelayBeforeCloseMillis = kMinDelayBeforeCloseMillis;
686 
687 private:
688 
689     // Log the scheduler if it changes.
690     void                 checkScheduler();
691     int                  mPreviousScheduler = -1;
692 
693     std::atomic<bool>    mDataCallbackEnabled{false};
694     std::atomic<bool>    mErrorCallbackCalled{false};
695 
696     std::atomic<bool>    mPerformanceHintEnabled{false}; // set only by app
697 };
698 
699 /**
700  * This struct is a stateless functor which closes an AudioStream prior to its deletion.
701  * This means it can be used to safely delete a smart pointer referring to an open stream.
702  */
703     struct StreamDeleterFunctor {
operatorStreamDeleterFunctor704         void operator()(AudioStream  *audioStream) {
705             if (audioStream) {
706                 audioStream->close();
707             }
708             delete audioStream;
709         }
710     };
711 } // namespace oboe
712 
713 #endif /* OBOE_STREAM_H_ */
714