xref: /aosp_15_r20/external/oboe/src/common/FilterAudioStream.h (revision 05767d913155b055644481607e6fa1e35e2fe72c)
1 /*
2  * Copyright 2019 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_FILTER_AUDIO_STREAM_H
18 #define OBOE_FILTER_AUDIO_STREAM_H
19 
20 #include <memory>
21 #include <oboe/AudioStream.h>
22 #include "DataConversionFlowGraph.h"
23 
24 namespace oboe {
25 
26 /**
27  * An AudioStream that wraps another AudioStream and provides audio data conversion.
28  * Operations may include channel conversion, data format conversion and/or sample rate conversion.
29  */
30 class FilterAudioStream : public AudioStream, AudioStreamCallback {
31 public:
32 
33     /**
34      * Construct an `AudioStream` using the given `AudioStreamBuilder` and a child AudioStream.
35      *
36      * This should only be called internally by AudioStreamBuilder.
37      * Ownership of childStream will be passed to this object.
38      *
39      * @param builder containing all the stream's attributes
40      */
FilterAudioStream(const AudioStreamBuilder & builder,AudioStream * childStream)41     FilterAudioStream(const AudioStreamBuilder &builder, AudioStream *childStream)
42     : AudioStream(builder)
43     , mChildStream(childStream) {
44         // Intercept the callback if used.
45         if (builder.isErrorCallbackSpecified()) {
46             mErrorCallback = mChildStream->swapErrorCallback(this);
47         }
48         if (builder.isDataCallbackSpecified()) {
49             mDataCallback = mChildStream->swapDataCallback(this);
50         } else {
51             const int size = childStream->getFramesPerBurst() * childStream->getBytesPerFrame();
52             mBlockingBuffer = std::make_unique<uint8_t[]>(size);
53         }
54 
55         // Copy parameters that may not match builder.
56         mBufferCapacityInFrames = mChildStream->getBufferCapacityInFrames();
57         mPerformanceMode = mChildStream->getPerformanceMode();
58         mSharingMode = mChildStream->getSharingMode();
59         mInputPreset = mChildStream->getInputPreset();
60         mFramesPerBurst = mChildStream->getFramesPerBurst();
61         mDeviceId = mChildStream->getDeviceId();
62         mHardwareSampleRate = mChildStream->getHardwareSampleRate();
63         mHardwareChannelCount = mChildStream->getHardwareChannelCount();
64         mHardwareFormat = mChildStream->getHardwareFormat();
65     }
66 
67     virtual ~FilterAudioStream() = default;
68 
getChildStream()69     AudioStream *getChildStream() const {
70         return mChildStream.get();
71     }
72 
73     Result configureFlowGraph();
74 
75     // Close child and parent.
close()76     Result close()  override {
77         const Result result1 = mChildStream->close();
78         const Result result2 = AudioStream::close();
79         return (result1 != Result::OK ? result1 : result2);
80     }
81 
82     /**
83      * Start the stream asynchronously. Returns immediately (does not block). Equivalent to calling
84      * `start(0)`.
85      */
requestStart()86     Result requestStart() override {
87         return mChildStream->requestStart();
88     }
89 
90     /**
91      * Pause the stream asynchronously. Returns immediately (does not block). Equivalent to calling
92      * `pause(0)`.
93      */
requestPause()94     Result requestPause() override {
95         return mChildStream->requestPause();
96     }
97 
98     /**
99      * Flush the stream asynchronously. Returns immediately (does not block). Equivalent to calling
100      * `flush(0)`.
101      */
requestFlush()102     Result requestFlush() override {
103         return mChildStream->requestFlush();
104     }
105 
106     /**
107      * Stop the stream asynchronously. Returns immediately (does not block). Equivalent to calling
108      * `stop(0)`.
109      */
requestStop()110     Result requestStop() override {
111         return mChildStream->requestStop();
112     }
113 
114     ResultWithValue<int32_t> read(void *buffer,
115             int32_t numFrames,
116             int64_t timeoutNanoseconds) override;
117 
118     ResultWithValue<int32_t> write(const void *buffer,
119             int32_t numFrames,
120             int64_t timeoutNanoseconds) override;
121 
getState()122     StreamState getState() override {
123         return mChildStream->getState();
124     }
125 
waitForStateChange(StreamState inputState,StreamState * nextState,int64_t timeoutNanoseconds)126     Result waitForStateChange(
127             StreamState inputState,
128             StreamState *nextState,
129             int64_t timeoutNanoseconds) override {
130         return mChildStream->waitForStateChange(inputState, nextState, timeoutNanoseconds);
131     }
132 
isXRunCountSupported()133     bool isXRunCountSupported() const override {
134         return mChildStream->isXRunCountSupported();
135     }
136 
getAudioApi()137     AudioApi getAudioApi() const override {
138         return mChildStream->getAudioApi();
139     }
140 
updateFramesWritten()141     void updateFramesWritten() override {
142         // TODO for output, just count local writes?
143         mFramesWritten = static_cast<int64_t>(mChildStream->getFramesWritten() * mRateScaler);
144     }
145 
updateFramesRead()146     void updateFramesRead() override {
147         // TODO for input, just count local reads?
148         mFramesRead = static_cast<int64_t>(mChildStream->getFramesRead() * mRateScaler);
149     }
150 
getUnderlyingStream()151     void *getUnderlyingStream() const  override {
152         return mChildStream->getUnderlyingStream();
153     }
154 
setBufferSizeInFrames(int32_t requestedFrames)155     ResultWithValue<int32_t> setBufferSizeInFrames(int32_t requestedFrames) override {
156         return mChildStream->setBufferSizeInFrames(requestedFrames);
157     }
158 
getBufferSizeInFrames()159     int32_t getBufferSizeInFrames() override {
160         mBufferSizeInFrames = mChildStream->getBufferSizeInFrames();
161         return mBufferSizeInFrames;
162     }
163 
getXRunCount()164     ResultWithValue<int32_t> getXRunCount() override {
165         return mChildStream->getXRunCount();
166     }
167 
calculateLatencyMillis()168     ResultWithValue<double> calculateLatencyMillis() override {
169         // This will automatically include the latency of the flowgraph?
170         return mChildStream->calculateLatencyMillis();
171     }
172 
getTimestamp(clockid_t clockId,int64_t * framePosition,int64_t * timeNanoseconds)173     Result getTimestamp(clockid_t clockId,
174             int64_t *framePosition,
175             int64_t *timeNanoseconds) override {
176         int64_t childPosition = 0;
177         Result result = mChildStream->getTimestamp(clockId, &childPosition, timeNanoseconds);
178         // It is OK if framePosition is null.
179         if (framePosition) {
180             *framePosition = childPosition * mRateScaler;
181         }
182         return result;
183     }
184 
185     DataCallbackResult onAudioReady(AudioStream *oboeStream,
186             void *audioData,
187             int32_t numFrames) override;
188 
onError(AudioStream *,Result error)189     bool onError(AudioStream * /*audioStream*/, Result error) override {
190         if (mErrorCallback != nullptr) {
191             return mErrorCallback->onError(this, error);
192         }
193         return false;
194     }
195 
onErrorBeforeClose(AudioStream *,Result error)196     void onErrorBeforeClose(AudioStream * /*oboeStream*/, Result error) override {
197         if (mErrorCallback != nullptr) {
198             mErrorCallback->onErrorBeforeClose(this, error);
199         }
200     }
201 
onErrorAfterClose(AudioStream *,Result error)202     void onErrorAfterClose(AudioStream * /*oboeStream*/, Result error) override {
203         // Close this parent stream because the callback will only close the child.
204         AudioStream::close();
205         if (mErrorCallback != nullptr) {
206             mErrorCallback->onErrorAfterClose(this, error);
207         }
208     }
209 
210     /**
211      * @return last result passed from an error callback
212      */
getLastErrorCallbackResult()213     oboe::Result getLastErrorCallbackResult() const override {
214         return mChildStream->getLastErrorCallbackResult();
215     }
216 
217 private:
218 
219     std::unique_ptr<AudioStream>             mChildStream; // this stream wraps the child stream
220     std::unique_ptr<DataConversionFlowGraph> mFlowGraph; // for converting data
221     std::unique_ptr<uint8_t[]>               mBlockingBuffer; // temp buffer for write()
222     double                                   mRateScaler = 1.0; // ratio parent/child sample rates
223 };
224 
225 } // oboe
226 
227 #endif //OBOE_FILTER_AUDIO_STREAM_H
228