• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      * Note that due to issues in Android before R, we recommend NOT calling
266      * this method from a data callback. See this tech note for more details.
267      * https://github.com/google/oboe/blob/main/docs/notes/rlsbuffer.md
268      *
269      * @return a ResultWithValue which has a result of Result::OK and a value containing the latency
270      * in milliseconds, or a result of Result::Error*.
271      */
calculateLatencyMillis()272     virtual ResultWithValue<double> calculateLatencyMillis() {
273         return ResultWithValue<double>(Result::ErrorUnimplemented);
274     }
275 
276     /**
277      * Get the estimated time that the frame at `framePosition` entered or left the audio processing
278      * pipeline.
279      *
280      * This can be used to coordinate events and interactions with the external environment, and to
281      * estimate the latency of an audio stream. An example of usage can be found in the hello-oboe
282      * sample (search for "calculateCurrentOutputLatencyMillis").
283      *
284      * The time is based on the implementation's best effort, using whatever knowledge is available
285      * to the system, but cannot account for any delay unknown to the implementation.
286      *
287      * Note that due to issues in Android before R, we recommend NOT calling
288      * this method from a data callback. See this tech note for more details.
289      * https://github.com/google/oboe/blob/main/docs/notes/rlsbuffer.md
290      *
291      * @deprecated since 1.0, use AudioStream::getTimestamp(clockid_t clockId) instead, which
292      * returns ResultWithValue
293      * @param clockId the type of clock to use e.g. CLOCK_MONOTONIC
294      * @param framePosition the frame number to query
295      * @param timeNanoseconds an output parameter which will contain the presentation timestamp
296      */
getTimestamp(clockid_t,int64_t *,int64_t *)297     virtual Result getTimestamp(clockid_t /* clockId  */,
298                                 int64_t* /* framePosition */,
299                                 int64_t* /* timeNanoseconds */) {
300         return Result::ErrorUnimplemented;
301     }
302 
303     /**
304      * Get the estimated time that the frame at `framePosition` entered or left the audio processing
305      * pipeline.
306      *
307      * This can be used to coordinate events and interactions with the external environment, and to
308      * estimate the latency of an audio stream. An example of usage can be found in the hello-oboe
309      * sample (search for "calculateCurrentOutputLatencyMillis").
310      *
311      * The time is based on the implementation's best effort, using whatever knowledge is available
312      * to the system, but cannot account for any delay unknown to the implementation.
313      *
314      * Note that due to issues in Android before R, we recommend NOT calling
315      * this method from a data callback. See this tech note for more details.
316      * https://github.com/google/oboe/blob/main/docs/notes/rlsbuffer.md
317      *
318      * See
319      * @param clockId the type of clock to use e.g. CLOCK_MONOTONIC
320      * @return a FrameTimestamp containing the position and time at which a particular audio frame
321      * entered or left the audio processing pipeline, or an error if the operation failed.
322      */
323     virtual ResultWithValue<FrameTimestamp> getTimestamp(clockid_t /* clockId */);
324 
325     // ============== I/O ===========================
326     /**
327      * Write data from the supplied buffer into the stream. This method will block until the write
328      * is complete or it runs out of time.
329      *
330      * If `timeoutNanoseconds` is zero then this call will not wait.
331      *
332      * @param buffer The address of the first sample.
333      * @param numFrames Number of frames to write. Only complete frames will be written.
334      * @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion.
335      * @return a ResultWithValue which has a result of Result::OK and a value containing the number
336      * of frames actually written, or result of Result::Error*.
337      */
write(const void *,int32_t,int64_t)338     virtual ResultWithValue<int32_t> write(const void* /* buffer */,
339                              int32_t /* numFrames */,
340                              int64_t /* timeoutNanoseconds */ ) {
341         return ResultWithValue<int32_t>(Result::ErrorUnimplemented);
342     }
343 
344     /**
345      * Read data into the supplied buffer from the stream. This method will block until the read
346      * is complete or it runs out of time.
347      *
348      * If `timeoutNanoseconds` is zero then this call will not wait.
349      *
350      * @param buffer The address of the first sample.
351      * @param numFrames Number of frames to read. Only complete frames will be read.
352      * @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion.
353      * @return a ResultWithValue which has a result of Result::OK and a value containing the number
354      * of frames actually read, or result of Result::Error*.
355      */
read(void *,int32_t,int64_t)356     virtual ResultWithValue<int32_t> read(void* /* buffer */,
357                             int32_t /* numFrames */,
358                             int64_t /* timeoutNanoseconds */) {
359         return ResultWithValue<int32_t>(Result::ErrorUnimplemented);
360     }
361 
362     /**
363      * Get the underlying audio API which the stream uses.
364      *
365      * @return the API that this stream uses.
366      */
367     virtual AudioApi getAudioApi() const = 0;
368 
369     /**
370      * Returns true if the underlying audio API is AAudio.
371      *
372      * @return true if this stream is implemented using the AAudio API.
373      */
usesAAudio()374     bool usesAAudio() const {
375         return getAudioApi() == AudioApi::AAudio;
376     }
377 
378     /**
379      * Only for debugging. Do not use in production.
380      * If you need to call this method something is wrong.
381      * If you think you need it for production then please let us know
382      * so we can modify Oboe so that you don't need this.
383      *
384      * @return nullptr or a pointer to a stream from the system API
385      */
getUnderlyingStream()386     virtual void *getUnderlyingStream() const {
387         return nullptr;
388     }
389 
390     /**
391      * Update mFramesWritten.
392      * For internal use only.
393      */
394     virtual void updateFramesWritten() = 0;
395 
396     /**
397      * Update mFramesRead.
398      * For internal use only.
399      */
400     virtual void updateFramesRead() = 0;
401 
402     /*
403      * Swap old callback for new callback.
404      * This not atomic.
405      * This should only be used internally.
406      * @param dataCallback
407      * @return previous dataCallback
408      */
swapDataCallback(AudioStreamDataCallback * dataCallback)409     AudioStreamDataCallback *swapDataCallback(AudioStreamDataCallback *dataCallback) {
410         AudioStreamDataCallback *previousCallback = mDataCallback;
411         mDataCallback = dataCallback;
412         return previousCallback;
413     }
414 
415     /*
416      * Swap old callback for new callback.
417      * This not atomic.
418      * This should only be used internally.
419      * @param errorCallback
420      * @return previous errorCallback
421      */
swapErrorCallback(AudioStreamErrorCallback * errorCallback)422     AudioStreamErrorCallback *swapErrorCallback(AudioStreamErrorCallback *errorCallback) {
423         AudioStreamErrorCallback *previousCallback = mErrorCallback;
424         mErrorCallback = errorCallback;
425         return previousCallback;
426     }
427 
428     /**
429      * @return number of frames of data currently in the buffer
430      */
431     ResultWithValue<int32_t> getAvailableFrames();
432 
433     /**
434      * Wait until the stream has a minimum amount of data available in its buffer.
435      * This can be used with an EXCLUSIVE MMAP input stream to avoid reading data too close to
436      * the DSP write position, which may cause glitches.
437      *
438      * Starting with Oboe 1.7.1, the numFrames will be clipped internally against the
439      * BufferCapacity minus BurstSize. This is to prevent trying to wait for more frames
440      * than could possibly be available. In this case, the return value may be less than numFrames.
441      * Note that there may still be glitching if numFrames is too high.
442      *
443      * @param numFrames requested minimum frames available
444      * @param timeoutNanoseconds
445      * @return number of frames available, ErrorTimeout
446      */
447     ResultWithValue<int32_t> waitForAvailableFrames(int32_t numFrames,
448                                                     int64_t timeoutNanoseconds);
449 
450     /**
451      * @return last result passed from an error callback
452      */
getLastErrorCallbackResult()453     virtual oboe::Result getLastErrorCallbackResult() const {
454         return mErrorCallbackResult;
455     }
456 
457 
getDelayBeforeCloseMillis()458     int32_t getDelayBeforeCloseMillis() const {
459         return mDelayBeforeCloseMillis;
460     }
461 
462     /**
463      * Set the time to sleep before closing the internal stream.
464      *
465      * Sometimes a callback can occur shortly after a stream has been stopped and
466      * even after a close! If the stream has been closed then the callback
467      * might access memory that has been freed, which could cause a crash.
468      * This seems to be more likely in Android P or earlier.
469      * But it can also occur in later versions. By sleeping, we give time for
470      * the callback threads to finish.
471      *
472      * Note that this only has an effect when OboeGlobals::areWorkaroundsEnabled() is true.
473      *
474      * @param delayBeforeCloseMillis time to sleep before close.
475      */
setDelayBeforeCloseMillis(int32_t delayBeforeCloseMillis)476     void setDelayBeforeCloseMillis(int32_t delayBeforeCloseMillis) {
477         mDelayBeforeCloseMillis = delayBeforeCloseMillis;
478     }
479 
480 protected:
481 
482     /**
483      * This is used to detect more than one error callback from a stream.
484      * These were bugs in some versions of Android that caused multiple error callbacks.
485      * Internal bug b/63087953
486      *
487      * Calling this sets an atomic<bool> true and returns the previous value.
488      *
489      * @return false on first call, true on subsequent calls
490      */
wasErrorCallbackCalled()491     bool wasErrorCallbackCalled() {
492         return mErrorCallbackCalled.exchange(true);
493     }
494 
495     /**
496      * Wait for a transition from one state to another.
497      * @return OK if the endingState was observed, or ErrorUnexpectedState
498      *   if any state that was not the startingState or endingState was observed
499      *   or ErrorTimeout.
500      */
501     virtual Result waitForStateTransition(StreamState startingState,
502                                           StreamState endingState,
503                                           int64_t timeoutNanoseconds);
504 
505     /**
506      * Override this to provide a default for when the application did not specify a callback.
507      *
508      * @param audioData
509      * @param numFrames
510      * @return result
511      */
onDefaultCallback(void *,int)512     virtual DataCallbackResult onDefaultCallback(void* /* audioData  */, int /* numFrames */) {
513         return DataCallbackResult::Stop;
514     }
515 
516     /**
517      * Override this to provide your own behaviour for the audio callback
518      *
519      * @param audioData container array which audio frames will be written into or read from
520      * @param numFrames number of frames which were read/written
521      * @return the result of the callback: stop or continue
522      *
523      */
524     DataCallbackResult fireDataCallback(void *audioData, int numFrames);
525 
526     /**
527      * @return true if callbacks may be called
528      */
isDataCallbackEnabled()529     bool isDataCallbackEnabled() {
530         return mDataCallbackEnabled;
531     }
532 
533     /**
534      * This can be set false internally to prevent callbacks
535      * after DataCallbackResult::Stop has been returned.
536      */
setDataCallbackEnabled(bool enabled)537     void setDataCallbackEnabled(bool enabled) {
538         mDataCallbackEnabled = enabled;
539     }
540 
541     /**
542      * This should only be called as a stream is being opened.
543      * Otherwise we might override setDelayBeforeCloseMillis().
544      */
545     void calculateDefaultDelayBeforeCloseMillis();
546 
547     /**
548      * Try to avoid a race condition when closing.
549      */
sleepBeforeClose()550     void sleepBeforeClose() {
551         if (mDelayBeforeCloseMillis > 0) {
552             usleep(mDelayBeforeCloseMillis * 1000);
553         }
554     }
555 
556     /*
557      * Set a weak_ptr to this stream from the shared_ptr so that we can
558      * later use a shared_ptr in the error callback.
559      */
setWeakThis(std::shared_ptr<oboe::AudioStream> & sharedStream)560     void setWeakThis(std::shared_ptr<oboe::AudioStream> &sharedStream) {
561         mWeakThis = sharedStream;
562     }
563 
564     /*
565      * Make a shared_ptr that will prevent this stream from being deleted.
566      */
lockWeakThis()567     std::shared_ptr<oboe::AudioStream> lockWeakThis() {
568         return mWeakThis.lock();
569     }
570 
571     std::weak_ptr<AudioStream> mWeakThis; // weak pointer to this object
572 
573     /**
574      * Number of frames which have been written into the stream
575      *
576      * This is signed integer to match the counters in AAudio.
577      * At audio rates, the counter will overflow in about six million years.
578      */
579     std::atomic<int64_t> mFramesWritten{};
580 
581     /**
582      * Number of frames which have been read from the stream.
583      *
584      * This is signed integer to match the counters in AAudio.
585      * At audio rates, the counter will overflow in about six million years.
586      */
587     std::atomic<int64_t> mFramesRead{};
588 
589     std::mutex           mLock; // for synchronizing start/stop/close
590 
591     oboe::Result         mErrorCallbackResult = oboe::Result::OK;
592 
593     /**
594      * Number of frames which will be copied to/from the audio device in a single read/write
595      * operation
596      */
597     int32_t              mFramesPerBurst = kUnspecified;
598 
599     // Time to sleep in order to prevent a race condition with a callback after a close().
600     // Two milliseconds may be enough but 10 msec is even safer.
601     static constexpr int kMinDelayBeforeCloseMillis = 10;
602     int32_t              mDelayBeforeCloseMillis = kMinDelayBeforeCloseMillis;
603 
604 private:
605 
606     // Log the scheduler if it changes.
607     void                 checkScheduler();
608     int                  mPreviousScheduler = -1;
609 
610     std::atomic<bool>    mDataCallbackEnabled{false};
611     std::atomic<bool>    mErrorCallbackCalled{false};
612 };
613 
614 /**
615  * This struct is a stateless functor which closes an AudioStream prior to its deletion.
616  * This means it can be used to safely delete a smart pointer referring to an open stream.
617  */
618     struct StreamDeleterFunctor {
operatorStreamDeleterFunctor619         void operator()(AudioStream  *audioStream) {
620             if (audioStream) {
621                 audioStream->close();
622             }
623             delete audioStream;
624         }
625     };
626 } // namespace oboe
627 
628 #endif /* OBOE_STREAM_H_ */
629