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