blob: fbc7f90fb2e9a2a3b73da3c32a8d09c24b6371cf [file] [log] [blame]
Andy Hung857d5a22015-03-26 18:46:00 -07001/*
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#define LOG_TAG "BufferProvider"
18//#define LOG_NDEBUG 0
19
jiabin1b746402018-12-14 14:39:35 -080020#include <algorithm>
21
Andy Hung857d5a22015-03-26 18:46:00 -070022#include <audio_utils/primitives.h>
23#include <audio_utils/format.h>
jiabindce8f8c2018-12-10 17:49:31 -080024#include <audio_utils/channels.h>
Dan Willemsen9c99f152018-11-16 15:30:38 -080025#include <sonic.h>
Mikhail Naganov022b9952017-01-04 16:36:51 -080026#include <media/audiohal/EffectBufferHalInterface.h>
Mikhail Naganova0c91332016-09-19 10:01:12 -070027#include <media/audiohal/EffectHalInterface.h>
28#include <media/audiohal/EffectsFactoryHalInterface.h>
Andy Hungc5656cc2015-03-26 19:04:33 -070029#include <media/AudioResamplerPublic.h>
Andy Hung068561c2017-01-03 17:09:32 -080030#include <media/BufferProviders.h>
Mikhail Naganov9fe94012016-10-14 14:57:40 -070031#include <system/audio_effects/effect_downmix.h>
Andy Hung857d5a22015-03-26 18:46:00 -070032#include <utils/Log.h>
33
Andy Hung857d5a22015-03-26 18:46:00 -070034#ifndef ARRAY_SIZE
35#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
36#endif
37
38namespace android {
39
40// ----------------------------------------------------------------------------
Andy Hung857d5a22015-03-26 18:46:00 -070041CopyBufferProvider::CopyBufferProvider(size_t inputFrameSize,
42 size_t outputFrameSize, size_t bufferFrameCount) :
43 mInputFrameSize(inputFrameSize),
44 mOutputFrameSize(outputFrameSize),
45 mLocalBufferFrameCount(bufferFrameCount),
46 mLocalBufferData(NULL),
47 mConsumed(0)
48{
49 ALOGV("CopyBufferProvider(%p)(%zu, %zu, %zu)", this,
50 inputFrameSize, outputFrameSize, bufferFrameCount);
51 LOG_ALWAYS_FATAL_IF(inputFrameSize < outputFrameSize && bufferFrameCount == 0,
52 "Requires local buffer if inputFrameSize(%zu) < outputFrameSize(%zu)",
53 inputFrameSize, outputFrameSize);
54 if (mLocalBufferFrameCount) {
55 (void)posix_memalign(&mLocalBufferData, 32, mLocalBufferFrameCount * mOutputFrameSize);
56 }
57 mBuffer.frameCount = 0;
58}
59
60CopyBufferProvider::~CopyBufferProvider()
61{
Andy Hung930bbf92018-09-11 18:44:27 -070062 ALOGV("%s(%p) %zu %p %p",
63 __func__, this, mBuffer.frameCount, mTrackBufferProvider, mLocalBufferData);
Andy Hung857d5a22015-03-26 18:46:00 -070064 if (mBuffer.frameCount != 0) {
65 mTrackBufferProvider->releaseBuffer(&mBuffer);
66 }
67 free(mLocalBufferData);
68}
69
Glenn Kastend79072e2016-01-06 08:41:20 -080070status_t CopyBufferProvider::getNextBuffer(AudioBufferProvider::Buffer *pBuffer)
Andy Hung857d5a22015-03-26 18:46:00 -070071{
Glenn Kastend79072e2016-01-06 08:41:20 -080072 //ALOGV("CopyBufferProvider(%p)::getNextBuffer(%p (%zu))",
73 // this, pBuffer, pBuffer->frameCount);
Andy Hung857d5a22015-03-26 18:46:00 -070074 if (mLocalBufferFrameCount == 0) {
Glenn Kastend79072e2016-01-06 08:41:20 -080075 status_t res = mTrackBufferProvider->getNextBuffer(pBuffer);
Andy Hung857d5a22015-03-26 18:46:00 -070076 if (res == OK) {
77 copyFrames(pBuffer->raw, pBuffer->raw, pBuffer->frameCount);
78 }
79 return res;
80 }
81 if (mBuffer.frameCount == 0) {
82 mBuffer.frameCount = pBuffer->frameCount;
Glenn Kastend79072e2016-01-06 08:41:20 -080083 status_t res = mTrackBufferProvider->getNextBuffer(&mBuffer);
Andy Hung857d5a22015-03-26 18:46:00 -070084 // At one time an upstream buffer provider had
85 // res == OK and mBuffer.frameCount == 0, doesn't seem to happen now 7/18/2014.
86 //
87 // By API spec, if res != OK, then mBuffer.frameCount == 0.
88 // but there may be improper implementations.
89 ALOG_ASSERT(res == OK || mBuffer.frameCount == 0);
90 if (res != OK || mBuffer.frameCount == 0) { // not needed by API spec, but to be safe.
91 pBuffer->raw = NULL;
92 pBuffer->frameCount = 0;
93 return res;
94 }
95 mConsumed = 0;
96 }
97 ALOG_ASSERT(mConsumed < mBuffer.frameCount);
jiabin1b746402018-12-14 14:39:35 -080098 size_t count = std::min(mLocalBufferFrameCount, mBuffer.frameCount - mConsumed);
99 count = std::min(count, pBuffer->frameCount);
Andy Hung857d5a22015-03-26 18:46:00 -0700100 pBuffer->raw = mLocalBufferData;
101 pBuffer->frameCount = count;
102 copyFrames(pBuffer->raw, (uint8_t*)mBuffer.raw + mConsumed * mInputFrameSize,
103 pBuffer->frameCount);
104 return OK;
105}
106
107void CopyBufferProvider::releaseBuffer(AudioBufferProvider::Buffer *pBuffer)
108{
109 //ALOGV("CopyBufferProvider(%p)::releaseBuffer(%p(%zu))",
110 // this, pBuffer, pBuffer->frameCount);
111 if (mLocalBufferFrameCount == 0) {
112 mTrackBufferProvider->releaseBuffer(pBuffer);
113 return;
114 }
115 // LOG_ALWAYS_FATAL_IF(pBuffer->frameCount == 0, "Invalid framecount");
116 mConsumed += pBuffer->frameCount; // TODO: update for efficiency to reuse existing content
117 if (mConsumed != 0 && mConsumed >= mBuffer.frameCount) {
118 mTrackBufferProvider->releaseBuffer(&mBuffer);
119 ALOG_ASSERT(mBuffer.frameCount == 0);
120 }
121 pBuffer->raw = NULL;
122 pBuffer->frameCount = 0;
123}
124
125void CopyBufferProvider::reset()
126{
127 if (mBuffer.frameCount != 0) {
128 mTrackBufferProvider->releaseBuffer(&mBuffer);
129 }
130 mConsumed = 0;
131}
132
Andy Hung930bbf92018-09-11 18:44:27 -0700133void CopyBufferProvider::setBufferProvider(AudioBufferProvider *p) {
134 ALOGV("%s(%p): mTrackBufferProvider:%p mBuffer.frameCount:%zu",
135 __func__, p, mTrackBufferProvider, mBuffer.frameCount);
136 if (mTrackBufferProvider == p) {
137 return;
138 }
139 mBuffer.frameCount = 0;
140 PassthruBufferProvider::setBufferProvider(p);
141}
142
Andy Hung857d5a22015-03-26 18:46:00 -0700143DownmixerBufferProvider::DownmixerBufferProvider(
144 audio_channel_mask_t inputChannelMask,
145 audio_channel_mask_t outputChannelMask, audio_format_t format,
146 uint32_t sampleRate, int32_t sessionId, size_t bufferFrameCount) :
147 CopyBufferProvider(
148 audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(inputChannelMask),
149 audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(outputChannelMask),
150 bufferFrameCount) // set bufferFrameCount to 0 to do in-place
151{
Mikhail Naganov66916c22017-01-24 17:46:33 -0800152 ALOGV("DownmixerBufferProvider(%p)(%#x, %#x, %#x %u %d %d)",
Andy Hung857d5a22015-03-26 18:46:00 -0700153 this, inputChannelMask, outputChannelMask, format,
Mikhail Naganov66916c22017-01-24 17:46:33 -0800154 sampleRate, sessionId, (int)bufferFrameCount);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700155 if (!sIsMultichannelCapable) {
156 ALOGE("DownmixerBufferProvider() error: not multichannel capable");
157 return;
158 }
159 mEffectsFactory = EffectsFactoryHalInterface::create();
Mikhail Naganov1dc98672016-08-18 17:50:29 -0700160 if (mEffectsFactory == 0) {
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700161 ALOGE("DownmixerBufferProvider() error: could not obtain the effects factory");
162 return;
163 }
164 if (mEffectsFactory->createEffect(&sDwnmFxDesc.uuid,
165 sessionId,
166 SESSION_ID_INVALID_AND_IGNORED,
Eric Laurent3b7f51b2019-11-13 12:57:33 -0800167 AUDIO_PORT_HANDLE_NONE,
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700168 &mDownmixInterface) != 0) {
Andy Hung857d5a22015-03-26 18:46:00 -0700169 ALOGE("DownmixerBufferProvider() error creating downmixer effect");
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700170 mDownmixInterface.clear();
171 mEffectsFactory.clear();
Andy Hung857d5a22015-03-26 18:46:00 -0700172 return;
173 }
174 // channel input configuration will be overridden per-track
175 mDownmixConfig.inputCfg.channels = inputChannelMask; // FIXME: Should be bits
176 mDownmixConfig.outputCfg.channels = outputChannelMask; // FIXME: should be bits
177 mDownmixConfig.inputCfg.format = format;
178 mDownmixConfig.outputCfg.format = format;
179 mDownmixConfig.inputCfg.samplingRate = sampleRate;
180 mDownmixConfig.outputCfg.samplingRate = sampleRate;
181 mDownmixConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
182 mDownmixConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
183 // input and output buffer provider, and frame count will not be used as the downmix effect
184 // process() function is called directly (see DownmixerBufferProvider::getNextBuffer())
185 mDownmixConfig.inputCfg.mask = EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS |
186 EFFECT_CONFIG_FORMAT | EFFECT_CONFIG_ACC_MODE;
187 mDownmixConfig.outputCfg.mask = mDownmixConfig.inputCfg.mask;
Mikhail Naganov68242df2023-10-23 13:43:26 -0700188 mDownmixConfig.inputCfg.buffer.frameCount = bufferFrameCount;
189 mDownmixConfig.outputCfg.buffer.frameCount = bufferFrameCount;
Andy Hung857d5a22015-03-26 18:46:00 -0700190
Mikhail Naganov66916c22017-01-24 17:46:33 -0800191 mInFrameSize =
192 audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(inputChannelMask);
193 mOutFrameSize =
194 audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(outputChannelMask);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800195 status_t status;
Kevin Rocard7588ff42018-01-08 11:11:30 -0800196 status = mEffectsFactory->mirrorBuffer(
Mikhail Naganov66916c22017-01-24 17:46:33 -0800197 nullptr, mInFrameSize * bufferFrameCount, &mInBuffer);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800198 if (status != 0) {
199 ALOGE("DownmixerBufferProvider() error %d while creating input buffer", status);
200 mDownmixInterface.clear();
201 mEffectsFactory.clear();
202 return;
203 }
Kevin Rocard7588ff42018-01-08 11:11:30 -0800204 status = mEffectsFactory->mirrorBuffer(
Mikhail Naganov66916c22017-01-24 17:46:33 -0800205 nullptr, mOutFrameSize * bufferFrameCount, &mOutBuffer);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800206 if (status != 0) {
207 ALOGE("DownmixerBufferProvider() error %d while creating output buffer", status);
208 mInBuffer.clear();
209 mDownmixInterface.clear();
210 mEffectsFactory.clear();
211 return;
212 }
Mikhail Naganov2f607552017-01-11 16:09:03 -0800213 mDownmixInterface->setInBuffer(mInBuffer);
214 mDownmixInterface->setOutBuffer(mOutBuffer);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800215
Andy Hung857d5a22015-03-26 18:46:00 -0700216 int cmdStatus;
217 uint32_t replySize = sizeof(int);
218
219 // Configure downmixer
Mikhail Naganov022b9952017-01-04 16:36:51 -0800220 status = mDownmixInterface->command(
Andy Hung857d5a22015-03-26 18:46:00 -0700221 EFFECT_CMD_SET_CONFIG /*cmdCode*/, sizeof(effect_config_t) /*cmdSize*/,
222 &mDownmixConfig /*pCmdData*/,
223 &replySize, &cmdStatus /*pReplyData*/);
224 if (status != 0 || cmdStatus != 0) {
225 ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while configuring downmixer",
226 status, cmdStatus);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800227 mOutBuffer.clear();
228 mInBuffer.clear();
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700229 mDownmixInterface.clear();
230 mEffectsFactory.clear();
Andy Hung857d5a22015-03-26 18:46:00 -0700231 return;
232 }
233
234 // Enable downmixer
235 replySize = sizeof(int);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700236 status = mDownmixInterface->command(
Andy Hung857d5a22015-03-26 18:46:00 -0700237 EFFECT_CMD_ENABLE /*cmdCode*/, 0 /*cmdSize*/, NULL /*pCmdData*/,
238 &replySize, &cmdStatus /*pReplyData*/);
239 if (status != 0 || cmdStatus != 0) {
240 ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while enabling downmixer",
241 status, cmdStatus);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800242 mOutBuffer.clear();
243 mInBuffer.clear();
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700244 mDownmixInterface.clear();
245 mEffectsFactory.clear();
Andy Hung857d5a22015-03-26 18:46:00 -0700246 return;
247 }
248
249 // Set downmix type
250 // parameter size rounded for padding on 32bit boundary
251 const int psizePadded = ((sizeof(downmix_params_t) - 1)/sizeof(int) + 1) * sizeof(int);
252 const int downmixParamSize =
253 sizeof(effect_param_t) + psizePadded + sizeof(downmix_type_t);
254 effect_param_t * const param = (effect_param_t *) malloc(downmixParamSize);
255 param->psize = sizeof(downmix_params_t);
256 const downmix_params_t downmixParam = DOWNMIX_PARAM_TYPE;
257 memcpy(param->data, &downmixParam, param->psize);
258 const downmix_type_t downmixType = DOWNMIX_TYPE_FOLD;
259 param->vsize = sizeof(downmix_type_t);
260 memcpy(param->data + psizePadded, &downmixType, param->vsize);
261 replySize = sizeof(int);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700262 status = mDownmixInterface->command(
Andy Hung857d5a22015-03-26 18:46:00 -0700263 EFFECT_CMD_SET_PARAM /* cmdCode */, downmixParamSize /* cmdSize */,
264 param /*pCmdData*/, &replySize, &cmdStatus /*pReplyData*/);
265 free(param);
266 if (status != 0 || cmdStatus != 0) {
267 ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while setting downmix type",
268 status, cmdStatus);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800269 mOutBuffer.clear();
270 mInBuffer.clear();
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700271 mDownmixInterface.clear();
272 mEffectsFactory.clear();
Andy Hung857d5a22015-03-26 18:46:00 -0700273 return;
274 }
275 ALOGV("DownmixerBufferProvider() downmix type set to %d", (int) downmixType);
276}
277
278DownmixerBufferProvider::~DownmixerBufferProvider()
279{
280 ALOGV("~DownmixerBufferProvider (%p)", this);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800281 if (mDownmixInterface != 0) {
282 mDownmixInterface->close();
283 }
Andy Hung857d5a22015-03-26 18:46:00 -0700284}
285
286void DownmixerBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
287{
Mikhail Naganov022b9952017-01-04 16:36:51 -0800288 mInBuffer->setExternalData(const_cast<void*>(src));
289 mInBuffer->setFrameCount(frames);
Mikhail Naganov66916c22017-01-24 17:46:33 -0800290 mInBuffer->update(mInFrameSize * frames);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800291 mOutBuffer->setFrameCount(frames);
Mikhail Naganov66916c22017-01-24 17:46:33 -0800292 mOutBuffer->setExternalData(dst);
293 if (dst != src) {
294 // Downmix may be accumulating, need to populate the output buffer
295 // with the dst data.
296 mOutBuffer->update(mOutFrameSize * frames);
297 }
Andy Hung857d5a22015-03-26 18:46:00 -0700298 // may be in-place if src == dst.
Mikhail Naganov022b9952017-01-04 16:36:51 -0800299 status_t res = mDownmixInterface->process();
300 if (res == OK) {
Mikhail Naganov66916c22017-01-24 17:46:33 -0800301 mOutBuffer->commit(mOutFrameSize * frames);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800302 } else {
303 ALOGE("DownmixBufferProvider error %d", res);
304 }
Andy Hung857d5a22015-03-26 18:46:00 -0700305}
306
307/* call once in a pthread_once handler. */
308/*static*/ status_t DownmixerBufferProvider::init()
309{
310 // find multichannel downmix effect if we have to play multichannel content
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700311 sp<EffectsFactoryHalInterface> effectsFactory = EffectsFactoryHalInterface::create();
Mikhail Naganov1dc98672016-08-18 17:50:29 -0700312 if (effectsFactory == 0) {
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700313 ALOGE("AudioMixer() error: could not obtain the effects factory");
314 return NO_INIT;
315 }
Andy Hung857d5a22015-03-26 18:46:00 -0700316 uint32_t numEffects = 0;
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700317 int ret = effectsFactory->queryNumberEffects(&numEffects);
Andy Hung857d5a22015-03-26 18:46:00 -0700318 if (ret != 0) {
319 ALOGE("AudioMixer() error %d querying number of effects", ret);
320 return NO_INIT;
321 }
322 ALOGV("EffectQueryNumberEffects() numEffects=%d", numEffects);
323
324 for (uint32_t i = 0 ; i < numEffects ; i++) {
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700325 if (effectsFactory->getDescriptor(i, &sDwnmFxDesc) == 0) {
Andy Hung857d5a22015-03-26 18:46:00 -0700326 ALOGV("effect %d is called %s", i, sDwnmFxDesc.name);
327 if (memcmp(&sDwnmFxDesc.type, EFFECT_UIID_DOWNMIX, sizeof(effect_uuid_t)) == 0) {
328 ALOGI("found effect \"%s\" from %s",
329 sDwnmFxDesc.name, sDwnmFxDesc.implementor);
330 sIsMultichannelCapable = true;
331 break;
332 }
333 }
334 }
335 ALOGW_IF(!sIsMultichannelCapable, "unable to find downmix effect");
336 return NO_INIT;
337}
338
339/*static*/ bool DownmixerBufferProvider::sIsMultichannelCapable = false;
340/*static*/ effect_descriptor_t DownmixerBufferProvider::sDwnmFxDesc;
341
342RemixBufferProvider::RemixBufferProvider(audio_channel_mask_t inputChannelMask,
343 audio_channel_mask_t outputChannelMask, audio_format_t format,
344 size_t bufferFrameCount) :
345 CopyBufferProvider(
346 audio_bytes_per_sample(format)
347 * audio_channel_count_from_out_mask(inputChannelMask),
348 audio_bytes_per_sample(format)
349 * audio_channel_count_from_out_mask(outputChannelMask),
350 bufferFrameCount),
351 mFormat(format),
352 mSampleSize(audio_bytes_per_sample(format)),
353 mInputChannels(audio_channel_count_from_out_mask(inputChannelMask)),
354 mOutputChannels(audio_channel_count_from_out_mask(outputChannelMask))
355{
356 ALOGV("RemixBufferProvider(%p)(%#x, %#x, %#x) %zu %zu",
357 this, format, inputChannelMask, outputChannelMask,
358 mInputChannels, mOutputChannels);
Andy Hung18aa2702015-05-05 23:48:38 -0700359 (void) memcpy_by_index_array_initialization_from_channel_mask(
360 mIdxAry, ARRAY_SIZE(mIdxAry), outputChannelMask, inputChannelMask);
Andy Hung857d5a22015-03-26 18:46:00 -0700361}
362
363void RemixBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
364{
365 memcpy_by_index_array(dst, mOutputChannels,
366 src, mInputChannels, mIdxAry, mSampleSize, frames);
367}
368
Andy Hungeda3e932021-10-21 13:44:56 -0700369ChannelMixBufferProvider::ChannelMixBufferProvider(audio_channel_mask_t inputChannelMask,
370 audio_channel_mask_t outputChannelMask, audio_format_t format,
371 size_t bufferFrameCount) :
372 CopyBufferProvider(
373 audio_bytes_per_sample(format)
374 * audio_channel_count_from_out_mask(inputChannelMask),
375 audio_bytes_per_sample(format)
376 * audio_channel_count_from_out_mask(outputChannelMask),
377 bufferFrameCount)
Andy Hung8514b932023-04-14 17:58:02 -0700378 , mChannelMix{format == AUDIO_FORMAT_PCM_FLOAT
379 ? audio_utils::channels::IChannelMix::create(outputChannelMask) : nullptr}
380 , mIsValid{mChannelMix && mChannelMix->setInputChannelMask(inputChannelMask)}
Andy Hungeda3e932021-10-21 13:44:56 -0700381{
382 ALOGV("ChannelMixBufferProvider(%p)(%#x, %#x, %#x)",
383 this, format, inputChannelMask, outputChannelMask);
Andy Hungeda3e932021-10-21 13:44:56 -0700384}
385
386void ChannelMixBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
387{
Andy Hung8514b932023-04-14 17:58:02 -0700388 if (mIsValid) {
389 mChannelMix->process(static_cast<const float *>(src), static_cast<float *>(dst),
390 frames, false /* accumulate */);
391 } else {
392 // Should fall back to a different BufferProvider if not valid.
393 ALOGE("%s: Use without being valid!", __func__);
394 }
Andy Hungeda3e932021-10-21 13:44:56 -0700395}
396
Andy Hung857d5a22015-03-26 18:46:00 -0700397ReformatBufferProvider::ReformatBufferProvider(int32_t channelCount,
398 audio_format_t inputFormat, audio_format_t outputFormat,
399 size_t bufferFrameCount) :
400 CopyBufferProvider(
401 channelCount * audio_bytes_per_sample(inputFormat),
402 channelCount * audio_bytes_per_sample(outputFormat),
403 bufferFrameCount),
404 mChannelCount(channelCount),
405 mInputFormat(inputFormat),
406 mOutputFormat(outputFormat)
407{
408 ALOGV("ReformatBufferProvider(%p)(%u, %#x, %#x)",
409 this, channelCount, inputFormat, outputFormat);
410}
411
412void ReformatBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
413{
414 memcpy_by_audio_format(dst, mOutputFormat, src, mInputFormat, frames * mChannelCount);
415}
416
Kevin Rocarde053bfa2017-11-09 22:07:34 -0800417ClampFloatBufferProvider::ClampFloatBufferProvider(int32_t channelCount, size_t bufferFrameCount) :
418 CopyBufferProvider(
419 channelCount * audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT),
420 channelCount * audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT),
421 bufferFrameCount),
422 mChannelCount(channelCount)
423{
424 ALOGV("ClampFloatBufferProvider(%p)(%u)", this, channelCount);
425}
426
427void ClampFloatBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
428{
429 memcpy_to_float_from_float_with_clamping((float*)dst, (const float*)src,
430 frames * mChannelCount,
431 FLOAT_NOMINAL_RANGE_HEADROOM);
432}
433
Andy Hungc5656cc2015-03-26 19:04:33 -0700434TimestretchBufferProvider::TimestretchBufferProvider(int32_t channelCount,
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700435 audio_format_t format, uint32_t sampleRate, const AudioPlaybackRate &playbackRate) :
Andy Hungc5656cc2015-03-26 19:04:33 -0700436 mChannelCount(channelCount),
437 mFormat(format),
438 mSampleRate(sampleRate),
439 mFrameSize(channelCount * audio_bytes_per_sample(format)),
Andy Hungc5656cc2015-03-26 19:04:33 -0700440 mLocalBufferFrameCount(0),
441 mLocalBufferData(NULL),
Ricardo Garciaf097cae2015-04-13 12:17:21 -0700442 mRemaining(0),
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700443 mSonicStream(sonicCreateStream(sampleRate, mChannelCount)),
Ricardo Garcia6c7f0622015-04-30 18:39:16 -0700444 mFallbackFailErrorShown(false),
445 mAudioPlaybackRateValid(false)
Andy Hungc5656cc2015-03-26 19:04:33 -0700446{
Ricardo Garciaf097cae2015-04-13 12:17:21 -0700447 LOG_ALWAYS_FATAL_IF(mSonicStream == NULL,
448 "TimestretchBufferProvider can't allocate Sonic stream");
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700449
450 setPlaybackRate(playbackRate);
451 ALOGV("TimestretchBufferProvider(%p)(%u, %#x, %u %f %f %d %d)",
452 this, channelCount, format, sampleRate, playbackRate.mSpeed,
453 playbackRate.mPitch, playbackRate.mStretchMode, playbackRate.mFallbackMode);
454 mBuffer.frameCount = 0;
Andy Hungc5656cc2015-03-26 19:04:33 -0700455}
456
457TimestretchBufferProvider::~TimestretchBufferProvider()
458{
459 ALOGV("~TimestretchBufferProvider(%p)", this);
Ricardo Garciaf097cae2015-04-13 12:17:21 -0700460 sonicDestroyStream(mSonicStream);
Andy Hungc5656cc2015-03-26 19:04:33 -0700461 if (mBuffer.frameCount != 0) {
462 mTrackBufferProvider->releaseBuffer(&mBuffer);
463 }
464 free(mLocalBufferData);
465}
466
467status_t TimestretchBufferProvider::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -0800468 AudioBufferProvider::Buffer *pBuffer)
Andy Hungc5656cc2015-03-26 19:04:33 -0700469{
Glenn Kastend79072e2016-01-06 08:41:20 -0800470 ALOGV("TimestretchBufferProvider(%p)::getNextBuffer(%p (%zu))",
471 this, pBuffer, pBuffer->frameCount);
Andy Hungc5656cc2015-03-26 19:04:33 -0700472
473 // BYPASS
Glenn Kastend79072e2016-01-06 08:41:20 -0800474 //return mTrackBufferProvider->getNextBuffer(pBuffer);
Andy Hungc5656cc2015-03-26 19:04:33 -0700475
476 // check if previously processed data is sufficient.
477 if (pBuffer->frameCount <= mRemaining) {
478 ALOGV("previous sufficient");
479 pBuffer->raw = mLocalBufferData;
480 return OK;
481 }
482
483 // do we need to resize our buffer?
484 if (pBuffer->frameCount > mLocalBufferFrameCount) {
485 void *newmem;
486 if (posix_memalign(&newmem, 32, pBuffer->frameCount * mFrameSize) == OK) {
487 if (mRemaining != 0) {
488 memcpy(newmem, mLocalBufferData, mRemaining * mFrameSize);
489 }
490 free(mLocalBufferData);
491 mLocalBufferData = newmem;
492 mLocalBufferFrameCount = pBuffer->frameCount;
493 }
494 }
495
496 // need to fetch more data
497 const size_t outputDesired = pBuffer->frameCount - mRemaining;
Andy Hung6d626692015-08-21 12:53:46 -0700498 size_t dstAvailable;
499 do {
500 mBuffer.frameCount = mPlaybackRate.mSpeed == AUDIO_TIMESTRETCH_SPEED_NORMAL
501 ? outputDesired : outputDesired * mPlaybackRate.mSpeed + 1;
Andy Hungc5656cc2015-03-26 19:04:33 -0700502
Glenn Kastend79072e2016-01-06 08:41:20 -0800503 status_t res = mTrackBufferProvider->getNextBuffer(&mBuffer);
Andy Hungc5656cc2015-03-26 19:04:33 -0700504
Andy Hung6d626692015-08-21 12:53:46 -0700505 ALOG_ASSERT(res == OK || mBuffer.frameCount == 0);
506 if (res != OK || mBuffer.frameCount == 0) { // not needed by API spec, but to be safe.
507 ALOGV("upstream provider cannot provide data");
508 if (mRemaining == 0) {
509 pBuffer->raw = NULL;
510 pBuffer->frameCount = 0;
511 return res;
512 } else { // return partial count
513 pBuffer->raw = mLocalBufferData;
514 pBuffer->frameCount = mRemaining;
515 return OK;
516 }
Andy Hungc5656cc2015-03-26 19:04:33 -0700517 }
Andy Hungc5656cc2015-03-26 19:04:33 -0700518
Andy Hung6d626692015-08-21 12:53:46 -0700519 // time-stretch the data
jiabin1b746402018-12-14 14:39:35 -0800520 dstAvailable = std::min(mLocalBufferFrameCount - mRemaining, outputDesired);
Andy Hung6d626692015-08-21 12:53:46 -0700521 size_t srcAvailable = mBuffer.frameCount;
522 processFrames((uint8_t*)mLocalBufferData + mRemaining * mFrameSize, &dstAvailable,
523 mBuffer.raw, &srcAvailable);
Andy Hungc5656cc2015-03-26 19:04:33 -0700524
Andy Hung6d626692015-08-21 12:53:46 -0700525 // release all data consumed
526 mBuffer.frameCount = srcAvailable;
527 mTrackBufferProvider->releaseBuffer(&mBuffer);
528 } while (dstAvailable == 0); // try until we get output data or upstream provider fails.
Andy Hungc5656cc2015-03-26 19:04:33 -0700529
530 // update buffer vars with the actual data processed and return with buffer
531 mRemaining += dstAvailable;
532
533 pBuffer->raw = mLocalBufferData;
534 pBuffer->frameCount = mRemaining;
535
536 return OK;
537}
538
539void TimestretchBufferProvider::releaseBuffer(AudioBufferProvider::Buffer *pBuffer)
540{
541 ALOGV("TimestretchBufferProvider(%p)::releaseBuffer(%p (%zu))",
542 this, pBuffer, pBuffer->frameCount);
543
544 // BYPASS
545 //return mTrackBufferProvider->releaseBuffer(pBuffer);
546
547 // LOG_ALWAYS_FATAL_IF(pBuffer->frameCount == 0, "Invalid framecount");
548 if (pBuffer->frameCount < mRemaining) {
549 memcpy(mLocalBufferData,
550 (uint8_t*)mLocalBufferData + pBuffer->frameCount * mFrameSize,
551 (mRemaining - pBuffer->frameCount) * mFrameSize);
552 mRemaining -= pBuffer->frameCount;
553 } else if (pBuffer->frameCount == mRemaining) {
554 mRemaining = 0;
555 } else {
556 LOG_ALWAYS_FATAL("Releasing more frames(%zu) than available(%zu)",
557 pBuffer->frameCount, mRemaining);
558 }
559
560 pBuffer->raw = NULL;
561 pBuffer->frameCount = 0;
562}
563
564void TimestretchBufferProvider::reset()
565{
566 mRemaining = 0;
567}
568
Andy Hung930bbf92018-09-11 18:44:27 -0700569void TimestretchBufferProvider::setBufferProvider(AudioBufferProvider *p) {
570 ALOGV("%s(%p): mTrackBufferProvider:%p mBuffer.frameCount:%zu",
571 __func__, p, mTrackBufferProvider, mBuffer.frameCount);
572 if (mTrackBufferProvider == p) {
573 return;
574 }
575 mBuffer.frameCount = 0;
576 PassthruBufferProvider::setBufferProvider(p);
577}
578
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700579status_t TimestretchBufferProvider::setPlaybackRate(const AudioPlaybackRate &playbackRate)
Andy Hungc5656cc2015-03-26 19:04:33 -0700580{
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700581 mPlaybackRate = playbackRate;
582 mFallbackFailErrorShown = false;
583 sonicSetSpeed(mSonicStream, mPlaybackRate.mSpeed);
Ricardo Garciaf097cae2015-04-13 12:17:21 -0700584 //TODO: pitch is ignored for now
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700585 //TODO: optimize: if parameters are the same, don't do any extra computation.
Ricardo Garcia6c7f0622015-04-30 18:39:16 -0700586
587 mAudioPlaybackRateValid = isAudioPlaybackRateValid(mPlaybackRate);
Andy Hungc5656cc2015-03-26 19:04:33 -0700588 return OK;
589}
590
591void TimestretchBufferProvider::processFrames(void *dstBuffer, size_t *dstFrames,
592 const void *srcBuffer, size_t *srcFrames)
593{
594 ALOGV("processFrames(%zu %zu) remaining(%zu)", *dstFrames, *srcFrames, mRemaining);
595 // Note dstFrames is the required number of frames.
596
Ricardo Garcia6c7f0622015-04-30 18:39:16 -0700597 if (!mAudioPlaybackRateValid) {
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700598 //fallback mode
Andy Hungcf8d2c82016-08-10 16:02:01 -0700599 // Ensure consumption from src is as expected.
600 // TODO: add logic to track "very accurate" consumption related to speed, original sampling
601 // rate, actual frames processed.
602
603 const size_t targetSrc = *dstFrames * mPlaybackRate.mSpeed;
604 if (*srcFrames < targetSrc) { // limit dst frames to that possible
605 *dstFrames = *srcFrames / mPlaybackRate.mSpeed;
606 } else if (*srcFrames > targetSrc + 1) {
607 *srcFrames = targetSrc + 1;
608 }
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700609 if (*dstFrames > 0) {
610 switch(mPlaybackRate.mFallbackMode) {
611 case AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT:
612 if (*dstFrames <= *srcFrames) {
613 size_t copySize = mFrameSize * *dstFrames;
614 memcpy(dstBuffer, srcBuffer, copySize);
615 } else {
616 // cyclically repeat the source.
617 for (size_t count = 0; count < *dstFrames; count += *srcFrames) {
jiabin1b746402018-12-14 14:39:35 -0800618 size_t remaining = std::min(*srcFrames, *dstFrames - count);
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700619 memcpy((uint8_t*)dstBuffer + mFrameSize * count,
620 srcBuffer, mFrameSize * remaining);
621 }
622 }
623 break;
624 case AUDIO_TIMESTRETCH_FALLBACK_DEFAULT:
625 case AUDIO_TIMESTRETCH_FALLBACK_MUTE:
626 memset(dstBuffer,0, mFrameSize * *dstFrames);
627 break;
628 case AUDIO_TIMESTRETCH_FALLBACK_FAIL:
629 default:
630 if(!mFallbackFailErrorShown) {
631 ALOGE("invalid parameters in TimestretchBufferProvider fallbackMode:%d",
632 mPlaybackRate.mFallbackMode);
633 mFallbackFailErrorShown = true;
634 }
635 break;
636 }
Andy Hungc5656cc2015-03-26 19:04:33 -0700637 }
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700638 } else {
639 switch (mFormat) {
640 case AUDIO_FORMAT_PCM_FLOAT:
641 if (sonicWriteFloatToStream(mSonicStream, (float*)srcBuffer, *srcFrames) != 1) {
642 ALOGE("sonicWriteFloatToStream cannot realloc");
643 *srcFrames = 0; // cannot consume all of srcBuffer
644 }
645 *dstFrames = sonicReadFloatFromStream(mSonicStream, (float*)dstBuffer, *dstFrames);
646 break;
647 case AUDIO_FORMAT_PCM_16_BIT:
648 if (sonicWriteShortToStream(mSonicStream, (short*)srcBuffer, *srcFrames) != 1) {
649 ALOGE("sonicWriteShortToStream cannot realloc");
650 *srcFrames = 0; // cannot consume all of srcBuffer
651 }
652 *dstFrames = sonicReadShortFromStream(mSonicStream, (short*)dstBuffer, *dstFrames);
653 break;
654 default:
655 // could also be caught on construction
656 LOG_ALWAYS_FATAL("invalid format %#x for TimestretchBufferProvider", mFormat);
Ricardo Garciaf097cae2015-04-13 12:17:21 -0700657 }
Andy Hungc5656cc2015-03-26 19:04:33 -0700658 }
659}
jiabindce8f8c2018-12-10 17:49:31 -0800660
jiabinea8fa7a2019-02-22 14:41:50 -0800661AdjustChannelsBufferProvider::AdjustChannelsBufferProvider(
662 audio_format_t format, size_t inChannelCount, size_t outChannelCount,
jiabin0e6babc2021-10-21 20:35:05 +0000663 size_t frameCount, audio_format_t contractedFormat, void* contractedBuffer,
664 size_t contractedOutChannelCount) :
jiabindce8f8c2018-12-10 17:49:31 -0800665 CopyBufferProvider(
666 audio_bytes_per_frame(inChannelCount, format),
jiabinea8fa7a2019-02-22 14:41:50 -0800667 audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format),
jiabindce8f8c2018-12-10 17:49:31 -0800668 frameCount),
669 mFormat(format),
670 mInChannelCount(inChannelCount),
671 mOutChannelCount(outChannelCount),
jiabindce8f8c2018-12-10 17:49:31 -0800672 mSampleSizeInBytes(audio_bytes_per_sample(format)),
jiabinea8fa7a2019-02-22 14:41:50 -0800673 mFrameCount(frameCount),
jiabin0e6babc2021-10-21 20:35:05 +0000674 mContractedFormat(inChannelCount > outChannelCount
675 ? contractedFormat : AUDIO_FORMAT_INVALID),
676 mContractedInChannelCount(inChannelCount > outChannelCount
677 ? inChannelCount - outChannelCount : 0),
678 mContractedOutChannelCount(contractedOutChannelCount),
679 mContractedSampleSizeInBytes(audio_bytes_per_sample(contractedFormat)),
680 mContractedInputFrameSize(mContractedInChannelCount * mContractedSampleSizeInBytes),
jiabindce8f8c2018-12-10 17:49:31 -0800681 mContractedBuffer(contractedBuffer),
682 mContractedWrittenFrames(0)
683{
jiabin0e6babc2021-10-21 20:35:05 +0000684 ALOGV("AdjustChannelsBufferProvider(%p)(%#x, %zu, %zu, %zu, %#x, %p, %zu)",
685 this, format, inChannelCount, outChannelCount, frameCount, contractedFormat,
686 contractedBuffer, contractedOutChannelCount);
jiabindce8f8c2018-12-10 17:49:31 -0800687 if (mContractedFormat != AUDIO_FORMAT_INVALID && mInChannelCount > mOutChannelCount) {
jiabin0e6babc2021-10-21 20:35:05 +0000688 mContractedOutputFrameSize =
689 audio_bytes_per_frame(mContractedOutChannelCount, mContractedFormat);
jiabindce8f8c2018-12-10 17:49:31 -0800690 }
691}
692
jiabinea8fa7a2019-02-22 14:41:50 -0800693status_t AdjustChannelsBufferProvider::getNextBuffer(AudioBufferProvider::Buffer* pBuffer)
jiabindce8f8c2018-12-10 17:49:31 -0800694{
jiabinea8fa7a2019-02-22 14:41:50 -0800695 if (mContractedBuffer != nullptr) {
696 // Restrict frame count only when it is needed to save contracted frames.
697 const size_t outFramesLeft = mFrameCount - mContractedWrittenFrames;
698 if (outFramesLeft < pBuffer->frameCount) {
699 // Restrict the frame count so that we don't write over the size of the output buffer.
700 pBuffer->frameCount = outFramesLeft;
701 }
jiabindce8f8c2018-12-10 17:49:31 -0800702 }
703 return CopyBufferProvider::getNextBuffer(pBuffer);
704}
705
jiabinea8fa7a2019-02-22 14:41:50 -0800706void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
jiabindce8f8c2018-12-10 17:49:31 -0800707{
jiabin0e6babc2021-10-21 20:35:05 +0000708 // For case multi to mono, adjust_channels has special logic that will mix first two input
709 // channels into a single output channel. In that case, use adjust_channels_non_destructive
710 // to keep only one channel data even when contracting to mono.
711 adjust_channels_non_destructive(src, mInChannelCount, dst, mOutChannelCount,
712 mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
713 if (mContractedFormat != AUDIO_FORMAT_INVALID
714 && mContractedBuffer != nullptr) {
715 const size_t contractedIdx = frames * mOutChannelCount * mSampleSizeInBytes;
716 uint8_t* oriBuf = (uint8_t*) dst + contractedIdx;
717 uint8_t* buf = (uint8_t*) mContractedBuffer
718 + mContractedWrittenFrames * mContractedOutputFrameSize;
719 if (mContractedInChannelCount > mContractedOutChannelCount) {
720 // Adjust the channels first as the contracted buffer may not have enough
721 // space for the data.
722 // Use adjust_channels_non_destructive to avoid mix first two channels into one single
723 // output channel when it is multi to mono.
724 adjust_channels_non_destructive(
725 oriBuf, mContractedInChannelCount, oriBuf, mContractedOutChannelCount,
726 mSampleSizeInBytes, frames * mContractedInChannelCount * mSampleSizeInBytes);
jiabinea8fa7a2019-02-22 14:41:50 -0800727 memcpy_by_audio_format(
jiabin0e6babc2021-10-21 20:35:05 +0000728 buf, mContractedFormat, oriBuf, mFormat, mContractedOutChannelCount * frames);
729 } else {
730 // Copy the data first as the dst buffer may not have enough space for extra channel.
731 memcpy_by_audio_format(
732 buf, mContractedFormat, oriBuf, mFormat, mContractedInChannelCount * frames);
733 // Note that if the contracted data is from MONO to MULTICHANNEL, the first 2 channels
734 // will be duplicated with the original single input channel and all the other channels
735 // will be 0-filled.
736 adjust_channels(
737 buf, mContractedInChannelCount, buf, mContractedOutChannelCount,
738 mContractedSampleSizeInBytes, mContractedInputFrameSize * frames);
jiabinea8fa7a2019-02-22 14:41:50 -0800739 }
jiabin0e6babc2021-10-21 20:35:05 +0000740 mContractedWrittenFrames += frames;
jiabindce8f8c2018-12-10 17:49:31 -0800741 }
742}
743
jiabinea8fa7a2019-02-22 14:41:50 -0800744void AdjustChannelsBufferProvider::reset()
jiabindce8f8c2018-12-10 17:49:31 -0800745{
746 mContractedWrittenFrames = 0;
747 CopyBufferProvider::reset();
748}
jiabinc658e452022-10-21 20:52:21 +0000749
750void TeeBufferProvider::copyFrames(void *dst, const void *src, size_t frames) {
751 memcpy(dst, src, frames * mInputFrameSize);
752 if (int teeBufferFrameLeft = mTeeBufferFrameCount - mFrameCopied; teeBufferFrameLeft < frames) {
753 ALOGW("Unable to copy all frames to tee buffer, %d frames dropped",
754 (int)frames - teeBufferFrameLeft);
755 frames = teeBufferFrameLeft;
756 }
757 memcpy(mTeeBuffer + mFrameCopied * mInputFrameSize, src, frames * mInputFrameSize);
758 mFrameCopied += frames;
759}
760
761void TeeBufferProvider::clearFramesCopied() {
762 mFrameCopied = 0;
763}
764
Andy Hung857d5a22015-03-26 18:46:00 -0700765// ----------------------------------------------------------------------------
766} // namespace android