• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.getCallback() != nullptr) {
46             mStreamCallback = mChildStream->swapCallback(this);
47         } else {
48             const int size = childStream->getFramesPerBurst() * childStream->getBytesPerFrame();
49             mBlockingBuffer = std::make_unique<uint8_t[]>(size);
50         }
51 
52         // Copy parameters that may not match builder.
53         mBufferCapacityInFrames = mChildStream->getBufferCapacityInFrames();
54         mPerformanceMode = mChildStream->getPerformanceMode();
55     }
56 
57     virtual ~FilterAudioStream() = default;
58 
getChildStream()59     AudioStream *getChildStream() const {
60         return mChildStream.get();
61     }
62 
63     Result configureFlowGraph();
64 
65     // Close child and parent.
close()66     Result close()  override {
67         const Result result1 = mChildStream->close();
68         const Result result2 = AudioStream::close();
69         return (result1 != Result::OK ? result1 : result2);
70     }
71 
72     /**
73      * Start the stream asynchronously. Returns immediately (does not block). Equivalent to calling
74      * `start(0)`.
75      */
requestStart()76     Result requestStart() override {
77         return mChildStream->requestStart();
78     }
79 
80     /**
81      * Pause the stream asynchronously. Returns immediately (does not block). Equivalent to calling
82      * `pause(0)`.
83      */
requestPause()84     Result requestPause() override {
85         return mChildStream->requestPause();
86     }
87 
88     /**
89      * Flush the stream asynchronously. Returns immediately (does not block). Equivalent to calling
90      * `flush(0)`.
91      */
requestFlush()92     Result requestFlush() override {
93         return mChildStream->requestFlush();
94     }
95 
96     /**
97      * Stop the stream asynchronously. Returns immediately (does not block). Equivalent to calling
98      * `stop(0)`.
99      */
requestStop()100     Result requestStop() override {
101         return mChildStream->requestStop();
102     }
103 
104     ResultWithValue<int32_t> read(void *buffer,
105             int32_t numFrames,
106             int64_t timeoutNanoseconds) override;
107 
108     ResultWithValue<int32_t> write(const void *buffer,
109             int32_t numFrames,
110             int64_t timeoutNanoseconds) override;
111 
getState()112     StreamState getState() const override {
113         return mChildStream->getState();
114     }
115 
waitForStateChange(StreamState inputState,StreamState * nextState,int64_t timeoutNanoseconds)116     Result waitForStateChange(
117             StreamState inputState,
118             StreamState *nextState,
119             int64_t timeoutNanoseconds) override {
120         return mChildStream->waitForStateChange(inputState, nextState, timeoutNanoseconds);
121     }
122 
isXRunCountSupported()123     bool isXRunCountSupported() const override {
124         return mChildStream->isXRunCountSupported();
125     }
126 
getFramesPerBurst()127     int32_t getFramesPerBurst() override {
128         return mChildStream->getFramesPerBurst();
129     }
130 
getAudioApi()131     AudioApi getAudioApi() const override {
132         return mChildStream->getAudioApi();
133     }
134 
updateFramesWritten()135     void updateFramesWritten() override {
136         // TODO for output, just count local writes?
137         mFramesWritten = static_cast<int64_t>(mChildStream->getFramesWritten() * mRateScaler);
138     }
139 
updateFramesRead()140     void updateFramesRead() override {
141         // TODO for input, just count local reads?
142         mFramesRead = static_cast<int64_t>(mChildStream->getFramesRead() * mRateScaler);
143     }
144 
getUnderlyingStream()145     void *getUnderlyingStream() const  override {
146         return mChildStream->getUnderlyingStream();
147     }
148 
setBufferSizeInFrames(int32_t requestedFrames)149     ResultWithValue<int32_t> setBufferSizeInFrames(int32_t requestedFrames) override {
150         return mChildStream->setBufferSizeInFrames(requestedFrames);
151     }
152 
getBufferSizeInFrames()153     int32_t getBufferSizeInFrames() override {
154         mBufferSizeInFrames = mChildStream->getBufferSizeInFrames();
155         return mBufferSizeInFrames;
156     }
157 
getXRunCount()158     ResultWithValue<int32_t> getXRunCount() const override {
159         return mChildStream->getXRunCount();
160     }
161 
calculateLatencyMillis()162     ResultWithValue<double> calculateLatencyMillis() override {
163         // This will automatically include the latency of the flowgraph?
164         return mChildStream->calculateLatencyMillis();
165     }
166 
getTimestamp(clockid_t clockId,int64_t * framePosition,int64_t * timeNanoseconds)167     Result getTimestamp(clockid_t clockId,
168             int64_t *framePosition,
169             int64_t *timeNanoseconds) override {
170         int64_t childPosition = 0;
171         Result result = mChildStream->getTimestamp(clockId, &childPosition, timeNanoseconds);
172         *framePosition = childPosition * mRateScaler;
173         return result;
174     }
175 
onAudioReady(AudioStream * oboeStream,void * audioData,int32_t numFrames)176     DataCallbackResult onAudioReady(AudioStream *oboeStream,
177             void *audioData,
178             int32_t numFrames) override {
179         int32_t framesProcessed;
180         if (oboeStream->getDirection() == Direction::Output) {
181             framesProcessed = mFlowGraph->read(audioData, numFrames, 0 /* timeout */);
182         } else {
183             framesProcessed = mFlowGraph->write(audioData, numFrames);
184         }
185         return (framesProcessed < numFrames)
186                 ? DataCallbackResult::Stop
187                 : mFlowGraph->getDataCallbackResult();
188     }
189 
onErrorBeforeClose(AudioStream * oboeStream,Result error)190     void onErrorBeforeClose(AudioStream *oboeStream, Result error) override {
191         if (mStreamCallback != nullptr) {
192             mStreamCallback->onErrorBeforeClose(this, error);
193         }
194     }
195 
onErrorAfterClose(AudioStream * oboeStream,Result error)196     void onErrorAfterClose(AudioStream *oboeStream, Result error) override {
197         // Close this parent stream because the callback will only close the child.
198         AudioStream::close();
199         if (mStreamCallback != nullptr) {
200             mStreamCallback->onErrorAfterClose(this, error);
201         }
202     }
203 
204 private:
205 
206     std::unique_ptr<AudioStream>             mChildStream; // this stream wraps the child stream
207     std::unique_ptr<DataConversionFlowGraph> mFlowGraph; // for converting data
208     std::unique_ptr<uint8_t[]>               mBlockingBuffer; // temp buffer for write()
209     double                                   mRateScaler = 1.0; // ratio parent/child sample rates
210 };
211 
212 } // oboe
213 
214 #endif //OBOE_FILTER_AUDIO_STREAM_H
215