Andy Hung | 857d5a2 | 2015-03-26 18:46:00 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2015 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 ANDROID_BUFFER_PROVIDERS_H |
| 18 | #define ANDROID_BUFFER_PROVIDERS_H |
| 19 | |
| 20 | #include <stdint.h> |
| 21 | #include <sys/types.h> |
| 22 | |
Andy Hung | 857d5a2 | 2015-03-26 18:46:00 -0700 | [diff] [blame] | 23 | #include <media/AudioBufferProvider.h> |
Andy Hung | 8981605 | 2017-01-11 17:08:23 -0800 | [diff] [blame] | 24 | #include <media/AudioResamplerPublic.h> |
Andy Hung | 857d5a2 | 2015-03-26 18:46:00 -0700 | [diff] [blame] | 25 | #include <system/audio.h> |
Mikhail Naganov | 00260b5 | 2016-10-13 12:54:24 -0700 | [diff] [blame] | 26 | #include <system/audio_effect.h> |
Mikhail Naganov | 4a3d5c2 | 2016-08-15 13:47:42 -0700 | [diff] [blame] | 27 | #include <utils/StrongPointer.h> |
Andy Hung | 857d5a2 | 2015-03-26 18:46:00 -0700 | [diff] [blame] | 28 | |
Andy Hung | 068561c | 2017-01-03 17:09:32 -0800 | [diff] [blame] | 29 | // external forward declaration from external/sonic/sonic.h |
| 30 | struct sonicStreamStruct; |
| 31 | typedef struct sonicStreamStruct *sonicStream; |
| 32 | |
Andy Hung | 857d5a2 | 2015-03-26 18:46:00 -0700 | [diff] [blame] | 33 | namespace android { |
| 34 | |
Mikhail Naganov | 022b995 | 2017-01-04 16:36:51 -0800 | [diff] [blame] | 35 | class EffectBufferHalInterface; |
Mikhail Naganov | 4a3d5c2 | 2016-08-15 13:47:42 -0700 | [diff] [blame] | 36 | class EffectHalInterface; |
| 37 | class EffectsFactoryHalInterface; |
| 38 | |
Andy Hung | 857d5a2 | 2015-03-26 18:46:00 -0700 | [diff] [blame] | 39 | // ---------------------------------------------------------------------------- |
| 40 | |
| 41 | class PassthruBufferProvider : public AudioBufferProvider { |
| 42 | public: |
| 43 | PassthruBufferProvider() : mTrackBufferProvider(NULL) { } |
| 44 | |
| 45 | virtual ~PassthruBufferProvider() { } |
| 46 | |
| 47 | // call this to release the buffer to the upstream provider. |
| 48 | // treat it as an audio discontinuity for future samples. |
| 49 | virtual void reset() { } |
| 50 | |
| 51 | // set the upstream buffer provider. Consider calling "reset" before this function. |
| 52 | virtual void setBufferProvider(AudioBufferProvider *p) { |
| 53 | mTrackBufferProvider = p; |
| 54 | } |
| 55 | |
| 56 | protected: |
| 57 | AudioBufferProvider *mTrackBufferProvider; |
| 58 | }; |
| 59 | |
| 60 | // Base AudioBufferProvider class used for DownMixerBufferProvider, RemixBufferProvider, |
| 61 | // and ReformatBufferProvider. |
| 62 | // It handles a private buffer for use in converting format or channel masks from the |
| 63 | // input data to a form acceptable by the mixer. |
| 64 | // TODO: Make a ResamplerBufferProvider when integers are entirely removed from the |
| 65 | // processing pipeline. |
| 66 | class CopyBufferProvider : public PassthruBufferProvider { |
| 67 | public: |
| 68 | // Use a private buffer of bufferFrameCount frames (each frame is outputFrameSize bytes). |
| 69 | // If bufferFrameCount is 0, no private buffer is created and in-place modification of |
| 70 | // the upstream buffer provider's buffers is performed by copyFrames(). |
| 71 | CopyBufferProvider(size_t inputFrameSize, size_t outputFrameSize, |
| 72 | size_t bufferFrameCount); |
| 73 | virtual ~CopyBufferProvider(); |
| 74 | |
| 75 | // Overrides AudioBufferProvider methods |
Glenn Kasten | d79072e | 2016-01-06 08:41:20 -0800 | [diff] [blame] | 76 | virtual status_t getNextBuffer(Buffer *buffer); |
Andy Hung | 857d5a2 | 2015-03-26 18:46:00 -0700 | [diff] [blame] | 77 | virtual void releaseBuffer(Buffer *buffer); |
| 78 | |
| 79 | // Overrides PassthruBufferProvider |
| 80 | virtual void reset(); |
| 81 | |
| 82 | // this function should be supplied by the derived class. It converts |
| 83 | // #frames in the *src pointer to the *dst pointer. It is public because |
| 84 | // some providers will allow this to work on arbitrary buffers outside |
| 85 | // of the internal buffers. |
| 86 | virtual void copyFrames(void *dst, const void *src, size_t frames) = 0; |
| 87 | |
| 88 | protected: |
| 89 | const size_t mInputFrameSize; |
| 90 | const size_t mOutputFrameSize; |
| 91 | private: |
| 92 | AudioBufferProvider::Buffer mBuffer; |
| 93 | const size_t mLocalBufferFrameCount; |
| 94 | void *mLocalBufferData; |
| 95 | size_t mConsumed; |
| 96 | }; |
| 97 | |
| 98 | // DownmixerBufferProvider derives from CopyBufferProvider to provide |
| 99 | // position dependent downmixing by an Audio Effect. |
| 100 | class DownmixerBufferProvider : public CopyBufferProvider { |
| 101 | public: |
| 102 | DownmixerBufferProvider(audio_channel_mask_t inputChannelMask, |
| 103 | audio_channel_mask_t outputChannelMask, audio_format_t format, |
| 104 | uint32_t sampleRate, int32_t sessionId, size_t bufferFrameCount); |
| 105 | virtual ~DownmixerBufferProvider(); |
| 106 | //Overrides |
| 107 | virtual void copyFrames(void *dst, const void *src, size_t frames); |
| 108 | |
Mikhail Naganov | 4a3d5c2 | 2016-08-15 13:47:42 -0700 | [diff] [blame] | 109 | bool isValid() const { return mDownmixInterface.get() != NULL; } |
Andy Hung | 857d5a2 | 2015-03-26 18:46:00 -0700 | [diff] [blame] | 110 | static status_t init(); |
| 111 | static bool isMultichannelCapable() { return sIsMultichannelCapable; } |
| 112 | |
| 113 | protected: |
Mikhail Naganov | 4a3d5c2 | 2016-08-15 13:47:42 -0700 | [diff] [blame] | 114 | sp<EffectsFactoryHalInterface> mEffectsFactory; |
| 115 | sp<EffectHalInterface> mDownmixInterface; |
Mikhail Naganov | 66916c2 | 2017-01-24 17:46:33 -0800 | [diff] [blame] | 116 | size_t mInFrameSize; |
| 117 | size_t mOutFrameSize; |
Mikhail Naganov | 022b995 | 2017-01-04 16:36:51 -0800 | [diff] [blame] | 118 | sp<EffectBufferHalInterface> mInBuffer; |
| 119 | sp<EffectBufferHalInterface> mOutBuffer; |
Andy Hung | 857d5a2 | 2015-03-26 18:46:00 -0700 | [diff] [blame] | 120 | effect_config_t mDownmixConfig; |
| 121 | |
| 122 | // effect descriptor for the downmixer used by the mixer |
| 123 | static effect_descriptor_t sDwnmFxDesc; |
| 124 | // indicates whether a downmix effect has been found and is usable by this mixer |
| 125 | static bool sIsMultichannelCapable; |
| 126 | // FIXME: should we allow effects outside of the framework? |
| 127 | // We need to here. A special ioId that must be <= -2 so it does not map to a session. |
| 128 | static const int32_t SESSION_ID_INVALID_AND_IGNORED = -2; |
| 129 | }; |
| 130 | |
| 131 | // RemixBufferProvider derives from CopyBufferProvider to perform an |
| 132 | // upmix or downmix to the proper channel count and mask. |
| 133 | class RemixBufferProvider : public CopyBufferProvider { |
| 134 | public: |
| 135 | RemixBufferProvider(audio_channel_mask_t inputChannelMask, |
| 136 | audio_channel_mask_t outputChannelMask, audio_format_t format, |
| 137 | size_t bufferFrameCount); |
| 138 | //Overrides |
| 139 | virtual void copyFrames(void *dst, const void *src, size_t frames); |
| 140 | |
| 141 | protected: |
| 142 | const audio_format_t mFormat; |
| 143 | const size_t mSampleSize; |
| 144 | const size_t mInputChannels; |
| 145 | const size_t mOutputChannels; |
| 146 | int8_t mIdxAry[sizeof(uint32_t) * 8]; // 32 bits => channel indices |
| 147 | }; |
| 148 | |
| 149 | // ReformatBufferProvider derives from CopyBufferProvider to convert the input data |
| 150 | // to an acceptable mixer input format type. |
| 151 | class ReformatBufferProvider : public CopyBufferProvider { |
| 152 | public: |
| 153 | ReformatBufferProvider(int32_t channelCount, |
| 154 | audio_format_t inputFormat, audio_format_t outputFormat, |
| 155 | size_t bufferFrameCount); |
| 156 | virtual void copyFrames(void *dst, const void *src, size_t frames); |
| 157 | |
| 158 | protected: |
| 159 | const uint32_t mChannelCount; |
| 160 | const audio_format_t mInputFormat; |
| 161 | const audio_format_t mOutputFormat; |
| 162 | }; |
| 163 | |
Andy Hung | c5656cc | 2015-03-26 19:04:33 -0700 | [diff] [blame] | 164 | // TimestretchBufferProvider derives from PassthruBufferProvider for time stretching |
| 165 | class TimestretchBufferProvider : public PassthruBufferProvider { |
| 166 | public: |
| 167 | TimestretchBufferProvider(int32_t channelCount, |
Ricardo Garcia | 5a8a95d | 2015-04-18 14:47:04 -0700 | [diff] [blame] | 168 | audio_format_t format, uint32_t sampleRate, |
| 169 | const AudioPlaybackRate &playbackRate); |
Andy Hung | c5656cc | 2015-03-26 19:04:33 -0700 | [diff] [blame] | 170 | virtual ~TimestretchBufferProvider(); |
| 171 | |
| 172 | // Overrides AudioBufferProvider methods |
Glenn Kasten | d79072e | 2016-01-06 08:41:20 -0800 | [diff] [blame] | 173 | virtual status_t getNextBuffer(Buffer* buffer); |
Andy Hung | c5656cc | 2015-03-26 19:04:33 -0700 | [diff] [blame] | 174 | virtual void releaseBuffer(Buffer* buffer); |
| 175 | |
| 176 | // Overrides PassthruBufferProvider |
| 177 | virtual void reset(); |
| 178 | |
Ricardo Garcia | 5a8a95d | 2015-04-18 14:47:04 -0700 | [diff] [blame] | 179 | virtual status_t setPlaybackRate(const AudioPlaybackRate &playbackRate); |
Andy Hung | c5656cc | 2015-03-26 19:04:33 -0700 | [diff] [blame] | 180 | |
| 181 | // processes frames |
| 182 | // dstBuffer is where to place the data |
| 183 | // dstFrames [in/out] is the desired frames (return with actual placed in buffer) |
| 184 | // srcBuffer is the source data |
| 185 | // srcFrames [in/out] is the available source frames (return with consumed) |
| 186 | virtual void processFrames(void *dstBuffer, size_t *dstFrames, |
| 187 | const void *srcBuffer, size_t *srcFrames); |
| 188 | |
| 189 | protected: |
| 190 | const uint32_t mChannelCount; |
| 191 | const audio_format_t mFormat; |
| 192 | const uint32_t mSampleRate; // const for now (TODO change this) |
| 193 | const size_t mFrameSize; |
Ricardo Garcia | 5a8a95d | 2015-04-18 14:47:04 -0700 | [diff] [blame] | 194 | AudioPlaybackRate mPlaybackRate; |
Andy Hung | c5656cc | 2015-03-26 19:04:33 -0700 | [diff] [blame] | 195 | |
| 196 | private: |
Ricardo Garcia | 5a8a95d | 2015-04-18 14:47:04 -0700 | [diff] [blame] | 197 | AudioBufferProvider::Buffer mBuffer; // for upstream request |
| 198 | size_t mLocalBufferFrameCount; // size of local buffer |
| 199 | void *mLocalBufferData; // internally allocated buffer for data returned |
| 200 | // to caller |
| 201 | size_t mRemaining; // remaining data in local buffer |
| 202 | sonicStream mSonicStream; // handle to sonic timestretch object |
| 203 | //FIXME: this dependency should be abstracted out |
| 204 | bool mFallbackFailErrorShown; // log fallback error only once |
Ricardo Garcia | 6c7f062 | 2015-04-30 18:39:16 -0700 | [diff] [blame] | 205 | bool mAudioPlaybackRateValid; // flag for current parameters validity |
Andy Hung | c5656cc | 2015-03-26 19:04:33 -0700 | [diff] [blame] | 206 | }; |
| 207 | |
Andy Hung | 857d5a2 | 2015-03-26 18:46:00 -0700 | [diff] [blame] | 208 | // ---------------------------------------------------------------------------- |
| 209 | } // namespace android |
| 210 | |
| 211 | #endif // ANDROID_BUFFER_PROVIDERS_H |