• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define LOG_TAG "BufferProvider"
18 //#define LOG_NDEBUG 0
19 
20 #include <algorithm>
21 
22 #include <audio_utils/primitives.h>
23 #include <audio_utils/format.h>
24 #include <audio_utils/channels.h>
25 #include <sonic.h>
26 #include <media/audiohal/EffectBufferHalInterface.h>
27 #include <media/audiohal/EffectHalInterface.h>
28 #include <media/audiohal/EffectsFactoryHalInterface.h>
29 #include <media/AudioResamplerPublic.h>
30 #include <media/BufferProviders.h>
31 #include <system/audio_effects/effect_downmix.h>
32 #include <utils/Log.h>
33 
34 #ifndef ARRAY_SIZE
35 #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
36 #endif
37 
38 namespace android {
39 
40 // ----------------------------------------------------------------------------
CopyBufferProvider(size_t inputFrameSize,size_t outputFrameSize,size_t bufferFrameCount)41 CopyBufferProvider::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 
~CopyBufferProvider()60 CopyBufferProvider::~CopyBufferProvider()
61 {
62     ALOGV("%s(%p) %zu %p %p",
63            __func__, this, mBuffer.frameCount, mTrackBufferProvider, mLocalBufferData);
64     if (mBuffer.frameCount != 0) {
65         mTrackBufferProvider->releaseBuffer(&mBuffer);
66     }
67     free(mLocalBufferData);
68 }
69 
getNextBuffer(AudioBufferProvider::Buffer * pBuffer)70 status_t CopyBufferProvider::getNextBuffer(AudioBufferProvider::Buffer *pBuffer)
71 {
72     //ALOGV("CopyBufferProvider(%p)::getNextBuffer(%p (%zu))",
73     //        this, pBuffer, pBuffer->frameCount);
74     if (mLocalBufferFrameCount == 0) {
75         status_t res = mTrackBufferProvider->getNextBuffer(pBuffer);
76         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;
83         status_t res = mTrackBufferProvider->getNextBuffer(&mBuffer);
84         // 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);
98     size_t count = std::min(mLocalBufferFrameCount, mBuffer.frameCount - mConsumed);
99     count = std::min(count, pBuffer->frameCount);
100     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 
releaseBuffer(AudioBufferProvider::Buffer * pBuffer)107 void 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 
reset()125 void CopyBufferProvider::reset()
126 {
127     if (mBuffer.frameCount != 0) {
128         mTrackBufferProvider->releaseBuffer(&mBuffer);
129     }
130     mConsumed = 0;
131 }
132 
setBufferProvider(AudioBufferProvider * p)133 void 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 
DownmixerBufferProvider(audio_channel_mask_t inputChannelMask,audio_channel_mask_t outputChannelMask,audio_format_t format,uint32_t sampleRate,int32_t sessionId,size_t bufferFrameCount)143 DownmixerBufferProvider::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 {
152     ALOGV("DownmixerBufferProvider(%p)(%#x, %#x, %#x %u %d %d)",
153             this, inputChannelMask, outputChannelMask, format,
154             sampleRate, sessionId, (int)bufferFrameCount);
155     if (!sIsMultichannelCapable) {
156         ALOGE("DownmixerBufferProvider() error: not multichannel capable");
157         return;
158     }
159     mEffectsFactory = EffectsFactoryHalInterface::create();
160     if (mEffectsFactory == 0) {
161         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,
167                                       &mDownmixInterface) != 0) {
168          ALOGE("DownmixerBufferProvider() error creating downmixer effect");
169          mDownmixInterface.clear();
170          mEffectsFactory.clear();
171          return;
172      }
173      // channel input configuration will be overridden per-track
174      mDownmixConfig.inputCfg.channels = inputChannelMask;   // FIXME: Should be bits
175      mDownmixConfig.outputCfg.channels = outputChannelMask; // FIXME: should be bits
176      mDownmixConfig.inputCfg.format = format;
177      mDownmixConfig.outputCfg.format = format;
178      mDownmixConfig.inputCfg.samplingRate = sampleRate;
179      mDownmixConfig.outputCfg.samplingRate = sampleRate;
180      mDownmixConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
181      mDownmixConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
182      // input and output buffer provider, and frame count will not be used as the downmix effect
183      // process() function is called directly (see DownmixerBufferProvider::getNextBuffer())
184      mDownmixConfig.inputCfg.mask = EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS |
185              EFFECT_CONFIG_FORMAT | EFFECT_CONFIG_ACC_MODE;
186      mDownmixConfig.outputCfg.mask = mDownmixConfig.inputCfg.mask;
187 
188      mInFrameSize =
189              audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(inputChannelMask);
190      mOutFrameSize =
191              audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(outputChannelMask);
192      status_t status;
193      status = mEffectsFactory->mirrorBuffer(
194              nullptr, mInFrameSize * bufferFrameCount, &mInBuffer);
195      if (status != 0) {
196          ALOGE("DownmixerBufferProvider() error %d while creating input buffer", status);
197          mDownmixInterface.clear();
198          mEffectsFactory.clear();
199          return;
200      }
201      status = mEffectsFactory->mirrorBuffer(
202              nullptr, mOutFrameSize * bufferFrameCount, &mOutBuffer);
203      if (status != 0) {
204          ALOGE("DownmixerBufferProvider() error %d while creating output buffer", status);
205          mInBuffer.clear();
206          mDownmixInterface.clear();
207          mEffectsFactory.clear();
208          return;
209      }
210      mDownmixInterface->setInBuffer(mInBuffer);
211      mDownmixInterface->setOutBuffer(mOutBuffer);
212 
213      int cmdStatus;
214      uint32_t replySize = sizeof(int);
215 
216      // Configure downmixer
217      status = mDownmixInterface->command(
218              EFFECT_CMD_SET_CONFIG /*cmdCode*/, sizeof(effect_config_t) /*cmdSize*/,
219              &mDownmixConfig /*pCmdData*/,
220              &replySize, &cmdStatus /*pReplyData*/);
221      if (status != 0 || cmdStatus != 0) {
222          ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while configuring downmixer",
223                  status, cmdStatus);
224          mOutBuffer.clear();
225          mInBuffer.clear();
226          mDownmixInterface.clear();
227          mEffectsFactory.clear();
228          return;
229      }
230 
231      // Enable downmixer
232      replySize = sizeof(int);
233      status = mDownmixInterface->command(
234              EFFECT_CMD_ENABLE /*cmdCode*/, 0 /*cmdSize*/, NULL /*pCmdData*/,
235              &replySize, &cmdStatus /*pReplyData*/);
236      if (status != 0 || cmdStatus != 0) {
237          ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while enabling downmixer",
238                  status, cmdStatus);
239          mOutBuffer.clear();
240          mInBuffer.clear();
241          mDownmixInterface.clear();
242          mEffectsFactory.clear();
243          return;
244      }
245 
246      // Set downmix type
247      // parameter size rounded for padding on 32bit boundary
248      const int psizePadded = ((sizeof(downmix_params_t) - 1)/sizeof(int) + 1) * sizeof(int);
249      const int downmixParamSize =
250              sizeof(effect_param_t) + psizePadded + sizeof(downmix_type_t);
251      effect_param_t * const param = (effect_param_t *) malloc(downmixParamSize);
252      param->psize = sizeof(downmix_params_t);
253      const downmix_params_t downmixParam = DOWNMIX_PARAM_TYPE;
254      memcpy(param->data, &downmixParam, param->psize);
255      const downmix_type_t downmixType = DOWNMIX_TYPE_FOLD;
256      param->vsize = sizeof(downmix_type_t);
257      memcpy(param->data + psizePadded, &downmixType, param->vsize);
258      replySize = sizeof(int);
259      status = mDownmixInterface->command(
260              EFFECT_CMD_SET_PARAM /* cmdCode */, downmixParamSize /* cmdSize */,
261              param /*pCmdData*/, &replySize, &cmdStatus /*pReplyData*/);
262      free(param);
263      if (status != 0 || cmdStatus != 0) {
264          ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while setting downmix type",
265                  status, cmdStatus);
266          mOutBuffer.clear();
267          mInBuffer.clear();
268          mDownmixInterface.clear();
269          mEffectsFactory.clear();
270          return;
271      }
272      ALOGV("DownmixerBufferProvider() downmix type set to %d", (int) downmixType);
273 }
274 
~DownmixerBufferProvider()275 DownmixerBufferProvider::~DownmixerBufferProvider()
276 {
277     ALOGV("~DownmixerBufferProvider (%p)", this);
278     if (mDownmixInterface != 0) {
279         mDownmixInterface->close();
280     }
281 }
282 
copyFrames(void * dst,const void * src,size_t frames)283 void DownmixerBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
284 {
285     mInBuffer->setExternalData(const_cast<void*>(src));
286     mInBuffer->setFrameCount(frames);
287     mInBuffer->update(mInFrameSize * frames);
288     mOutBuffer->setFrameCount(frames);
289     mOutBuffer->setExternalData(dst);
290     if (dst != src) {
291         // Downmix may be accumulating, need to populate the output buffer
292         // with the dst data.
293         mOutBuffer->update(mOutFrameSize * frames);
294     }
295     // may be in-place if src == dst.
296     status_t res = mDownmixInterface->process();
297     if (res == OK) {
298         mOutBuffer->commit(mOutFrameSize * frames);
299     } else {
300         ALOGE("DownmixBufferProvider error %d", res);
301     }
302 }
303 
304 /* call once in a pthread_once handler. */
init()305 /*static*/ status_t DownmixerBufferProvider::init()
306 {
307     // find multichannel downmix effect if we have to play multichannel content
308     sp<EffectsFactoryHalInterface> effectsFactory = EffectsFactoryHalInterface::create();
309     if (effectsFactory == 0) {
310         ALOGE("AudioMixer() error: could not obtain the effects factory");
311         return NO_INIT;
312     }
313     uint32_t numEffects = 0;
314     int ret = effectsFactory->queryNumberEffects(&numEffects);
315     if (ret != 0) {
316         ALOGE("AudioMixer() error %d querying number of effects", ret);
317         return NO_INIT;
318     }
319     ALOGV("EffectQueryNumberEffects() numEffects=%d", numEffects);
320 
321     for (uint32_t i = 0 ; i < numEffects ; i++) {
322         if (effectsFactory->getDescriptor(i, &sDwnmFxDesc) == 0) {
323             ALOGV("effect %d is called %s", i, sDwnmFxDesc.name);
324             if (memcmp(&sDwnmFxDesc.type, EFFECT_UIID_DOWNMIX, sizeof(effect_uuid_t)) == 0) {
325                 ALOGI("found effect \"%s\" from %s",
326                         sDwnmFxDesc.name, sDwnmFxDesc.implementor);
327                 sIsMultichannelCapable = true;
328                 break;
329             }
330         }
331     }
332     ALOGW_IF(!sIsMultichannelCapable, "unable to find downmix effect");
333     return NO_INIT;
334 }
335 
336 /*static*/ bool DownmixerBufferProvider::sIsMultichannelCapable = false;
337 /*static*/ effect_descriptor_t DownmixerBufferProvider::sDwnmFxDesc;
338 
RemixBufferProvider(audio_channel_mask_t inputChannelMask,audio_channel_mask_t outputChannelMask,audio_format_t format,size_t bufferFrameCount)339 RemixBufferProvider::RemixBufferProvider(audio_channel_mask_t inputChannelMask,
340         audio_channel_mask_t outputChannelMask, audio_format_t format,
341         size_t bufferFrameCount) :
342         CopyBufferProvider(
343                 audio_bytes_per_sample(format)
344                     * audio_channel_count_from_out_mask(inputChannelMask),
345                 audio_bytes_per_sample(format)
346                     * audio_channel_count_from_out_mask(outputChannelMask),
347                 bufferFrameCount),
348         mFormat(format),
349         mSampleSize(audio_bytes_per_sample(format)),
350         mInputChannels(audio_channel_count_from_out_mask(inputChannelMask)),
351         mOutputChannels(audio_channel_count_from_out_mask(outputChannelMask))
352 {
353     ALOGV("RemixBufferProvider(%p)(%#x, %#x, %#x) %zu %zu",
354             this, format, inputChannelMask, outputChannelMask,
355             mInputChannels, mOutputChannels);
356     (void) memcpy_by_index_array_initialization_from_channel_mask(
357             mIdxAry, ARRAY_SIZE(mIdxAry), outputChannelMask, inputChannelMask);
358 }
359 
copyFrames(void * dst,const void * src,size_t frames)360 void RemixBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
361 {
362     memcpy_by_index_array(dst, mOutputChannels,
363             src, mInputChannels, mIdxAry, mSampleSize, frames);
364 }
365 
ReformatBufferProvider(int32_t channelCount,audio_format_t inputFormat,audio_format_t outputFormat,size_t bufferFrameCount)366 ReformatBufferProvider::ReformatBufferProvider(int32_t channelCount,
367         audio_format_t inputFormat, audio_format_t outputFormat,
368         size_t bufferFrameCount) :
369         CopyBufferProvider(
370                 channelCount * audio_bytes_per_sample(inputFormat),
371                 channelCount * audio_bytes_per_sample(outputFormat),
372                 bufferFrameCount),
373         mChannelCount(channelCount),
374         mInputFormat(inputFormat),
375         mOutputFormat(outputFormat)
376 {
377     ALOGV("ReformatBufferProvider(%p)(%u, %#x, %#x)",
378             this, channelCount, inputFormat, outputFormat);
379 }
380 
copyFrames(void * dst,const void * src,size_t frames)381 void ReformatBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
382 {
383     memcpy_by_audio_format(dst, mOutputFormat, src, mInputFormat, frames * mChannelCount);
384 }
385 
ClampFloatBufferProvider(int32_t channelCount,size_t bufferFrameCount)386 ClampFloatBufferProvider::ClampFloatBufferProvider(int32_t channelCount, size_t bufferFrameCount) :
387         CopyBufferProvider(
388                 channelCount * audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT),
389                 channelCount * audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT),
390                 bufferFrameCount),
391         mChannelCount(channelCount)
392 {
393     ALOGV("ClampFloatBufferProvider(%p)(%u)", this, channelCount);
394 }
395 
copyFrames(void * dst,const void * src,size_t frames)396 void ClampFloatBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
397 {
398     memcpy_to_float_from_float_with_clamping((float*)dst, (const float*)src,
399                                              frames * mChannelCount,
400                                              FLOAT_NOMINAL_RANGE_HEADROOM);
401 }
402 
TimestretchBufferProvider(int32_t channelCount,audio_format_t format,uint32_t sampleRate,const AudioPlaybackRate & playbackRate)403 TimestretchBufferProvider::TimestretchBufferProvider(int32_t channelCount,
404         audio_format_t format, uint32_t sampleRate, const AudioPlaybackRate &playbackRate) :
405         mChannelCount(channelCount),
406         mFormat(format),
407         mSampleRate(sampleRate),
408         mFrameSize(channelCount * audio_bytes_per_sample(format)),
409         mLocalBufferFrameCount(0),
410         mLocalBufferData(NULL),
411         mRemaining(0),
412         mSonicStream(sonicCreateStream(sampleRate, mChannelCount)),
413         mFallbackFailErrorShown(false),
414         mAudioPlaybackRateValid(false)
415 {
416     LOG_ALWAYS_FATAL_IF(mSonicStream == NULL,
417             "TimestretchBufferProvider can't allocate Sonic stream");
418 
419     setPlaybackRate(playbackRate);
420     ALOGV("TimestretchBufferProvider(%p)(%u, %#x, %u %f %f %d %d)",
421             this, channelCount, format, sampleRate, playbackRate.mSpeed,
422             playbackRate.mPitch, playbackRate.mStretchMode, playbackRate.mFallbackMode);
423     mBuffer.frameCount = 0;
424 }
425 
~TimestretchBufferProvider()426 TimestretchBufferProvider::~TimestretchBufferProvider()
427 {
428     ALOGV("~TimestretchBufferProvider(%p)", this);
429     sonicDestroyStream(mSonicStream);
430     if (mBuffer.frameCount != 0) {
431         mTrackBufferProvider->releaseBuffer(&mBuffer);
432     }
433     free(mLocalBufferData);
434 }
435 
getNextBuffer(AudioBufferProvider::Buffer * pBuffer)436 status_t TimestretchBufferProvider::getNextBuffer(
437         AudioBufferProvider::Buffer *pBuffer)
438 {
439     ALOGV("TimestretchBufferProvider(%p)::getNextBuffer(%p (%zu))",
440             this, pBuffer, pBuffer->frameCount);
441 
442     // BYPASS
443     //return mTrackBufferProvider->getNextBuffer(pBuffer);
444 
445     // check if previously processed data is sufficient.
446     if (pBuffer->frameCount <= mRemaining) {
447         ALOGV("previous sufficient");
448         pBuffer->raw = mLocalBufferData;
449         return OK;
450     }
451 
452     // do we need to resize our buffer?
453     if (pBuffer->frameCount > mLocalBufferFrameCount) {
454         void *newmem;
455         if (posix_memalign(&newmem, 32, pBuffer->frameCount * mFrameSize) == OK) {
456             if (mRemaining != 0) {
457                 memcpy(newmem, mLocalBufferData, mRemaining * mFrameSize);
458             }
459             free(mLocalBufferData);
460             mLocalBufferData = newmem;
461             mLocalBufferFrameCount = pBuffer->frameCount;
462         }
463     }
464 
465     // need to fetch more data
466     const size_t outputDesired = pBuffer->frameCount - mRemaining;
467     size_t dstAvailable;
468     do {
469         mBuffer.frameCount = mPlaybackRate.mSpeed == AUDIO_TIMESTRETCH_SPEED_NORMAL
470                 ? outputDesired : outputDesired * mPlaybackRate.mSpeed + 1;
471 
472         status_t res = mTrackBufferProvider->getNextBuffer(&mBuffer);
473 
474         ALOG_ASSERT(res == OK || mBuffer.frameCount == 0);
475         if (res != OK || mBuffer.frameCount == 0) { // not needed by API spec, but to be safe.
476             ALOGV("upstream provider cannot provide data");
477             if (mRemaining == 0) {
478                 pBuffer->raw = NULL;
479                 pBuffer->frameCount = 0;
480                 return res;
481             } else { // return partial count
482                 pBuffer->raw = mLocalBufferData;
483                 pBuffer->frameCount = mRemaining;
484                 return OK;
485             }
486         }
487 
488         // time-stretch the data
489         dstAvailable = std::min(mLocalBufferFrameCount - mRemaining, outputDesired);
490         size_t srcAvailable = mBuffer.frameCount;
491         processFrames((uint8_t*)mLocalBufferData + mRemaining * mFrameSize, &dstAvailable,
492                 mBuffer.raw, &srcAvailable);
493 
494         // release all data consumed
495         mBuffer.frameCount = srcAvailable;
496         mTrackBufferProvider->releaseBuffer(&mBuffer);
497     } while (dstAvailable == 0); // try until we get output data or upstream provider fails.
498 
499     // update buffer vars with the actual data processed and return with buffer
500     mRemaining += dstAvailable;
501 
502     pBuffer->raw = mLocalBufferData;
503     pBuffer->frameCount = mRemaining;
504 
505     return OK;
506 }
507 
releaseBuffer(AudioBufferProvider::Buffer * pBuffer)508 void TimestretchBufferProvider::releaseBuffer(AudioBufferProvider::Buffer *pBuffer)
509 {
510     ALOGV("TimestretchBufferProvider(%p)::releaseBuffer(%p (%zu))",
511        this, pBuffer, pBuffer->frameCount);
512 
513     // BYPASS
514     //return mTrackBufferProvider->releaseBuffer(pBuffer);
515 
516     // LOG_ALWAYS_FATAL_IF(pBuffer->frameCount == 0, "Invalid framecount");
517     if (pBuffer->frameCount < mRemaining) {
518         memcpy(mLocalBufferData,
519                 (uint8_t*)mLocalBufferData + pBuffer->frameCount * mFrameSize,
520                 (mRemaining - pBuffer->frameCount) * mFrameSize);
521         mRemaining -= pBuffer->frameCount;
522     } else if (pBuffer->frameCount == mRemaining) {
523         mRemaining = 0;
524     } else {
525         LOG_ALWAYS_FATAL("Releasing more frames(%zu) than available(%zu)",
526                 pBuffer->frameCount, mRemaining);
527     }
528 
529     pBuffer->raw = NULL;
530     pBuffer->frameCount = 0;
531 }
532 
reset()533 void TimestretchBufferProvider::reset()
534 {
535     mRemaining = 0;
536 }
537 
setBufferProvider(AudioBufferProvider * p)538 void TimestretchBufferProvider::setBufferProvider(AudioBufferProvider *p) {
539     ALOGV("%s(%p): mTrackBufferProvider:%p  mBuffer.frameCount:%zu",
540             __func__, p, mTrackBufferProvider, mBuffer.frameCount);
541     if (mTrackBufferProvider == p) {
542         return;
543     }
544     mBuffer.frameCount = 0;
545     PassthruBufferProvider::setBufferProvider(p);
546 }
547 
setPlaybackRate(const AudioPlaybackRate & playbackRate)548 status_t TimestretchBufferProvider::setPlaybackRate(const AudioPlaybackRate &playbackRate)
549 {
550     mPlaybackRate = playbackRate;
551     mFallbackFailErrorShown = false;
552     sonicSetSpeed(mSonicStream, mPlaybackRate.mSpeed);
553     //TODO: pitch is ignored for now
554     //TODO: optimize: if parameters are the same, don't do any extra computation.
555 
556     mAudioPlaybackRateValid = isAudioPlaybackRateValid(mPlaybackRate);
557     return OK;
558 }
559 
processFrames(void * dstBuffer,size_t * dstFrames,const void * srcBuffer,size_t * srcFrames)560 void TimestretchBufferProvider::processFrames(void *dstBuffer, size_t *dstFrames,
561         const void *srcBuffer, size_t *srcFrames)
562 {
563     ALOGV("processFrames(%zu %zu)  remaining(%zu)", *dstFrames, *srcFrames, mRemaining);
564     // Note dstFrames is the required number of frames.
565 
566     if (!mAudioPlaybackRateValid) {
567         //fallback mode
568         // Ensure consumption from src is as expected.
569         // TODO: add logic to track "very accurate" consumption related to speed, original sampling
570         // rate, actual frames processed.
571 
572         const size_t targetSrc = *dstFrames * mPlaybackRate.mSpeed;
573         if (*srcFrames < targetSrc) { // limit dst frames to that possible
574             *dstFrames = *srcFrames / mPlaybackRate.mSpeed;
575         } else if (*srcFrames > targetSrc + 1) {
576             *srcFrames = targetSrc + 1;
577         }
578         if (*dstFrames > 0) {
579             switch(mPlaybackRate.mFallbackMode) {
580             case AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT:
581                 if (*dstFrames <= *srcFrames) {
582                       size_t copySize = mFrameSize * *dstFrames;
583                       memcpy(dstBuffer, srcBuffer, copySize);
584                   } else {
585                       // cyclically repeat the source.
586                       for (size_t count = 0; count < *dstFrames; count += *srcFrames) {
587                           size_t remaining = std::min(*srcFrames, *dstFrames - count);
588                           memcpy((uint8_t*)dstBuffer + mFrameSize * count,
589                                   srcBuffer, mFrameSize * remaining);
590                       }
591                   }
592                 break;
593             case AUDIO_TIMESTRETCH_FALLBACK_DEFAULT:
594             case AUDIO_TIMESTRETCH_FALLBACK_MUTE:
595                 memset(dstBuffer,0, mFrameSize * *dstFrames);
596                 break;
597             case AUDIO_TIMESTRETCH_FALLBACK_FAIL:
598             default:
599                 if(!mFallbackFailErrorShown) {
600                     ALOGE("invalid parameters in TimestretchBufferProvider fallbackMode:%d",
601                             mPlaybackRate.mFallbackMode);
602                     mFallbackFailErrorShown = true;
603                 }
604                 break;
605             }
606         }
607     } else {
608         switch (mFormat) {
609         case AUDIO_FORMAT_PCM_FLOAT:
610             if (sonicWriteFloatToStream(mSonicStream, (float*)srcBuffer, *srcFrames) != 1) {
611                 ALOGE("sonicWriteFloatToStream cannot realloc");
612                 *srcFrames = 0; // cannot consume all of srcBuffer
613             }
614             *dstFrames = sonicReadFloatFromStream(mSonicStream, (float*)dstBuffer, *dstFrames);
615             break;
616         case AUDIO_FORMAT_PCM_16_BIT:
617             if (sonicWriteShortToStream(mSonicStream, (short*)srcBuffer, *srcFrames) != 1) {
618                 ALOGE("sonicWriteShortToStream cannot realloc");
619                 *srcFrames = 0; // cannot consume all of srcBuffer
620             }
621             *dstFrames = sonicReadShortFromStream(mSonicStream, (short*)dstBuffer, *dstFrames);
622             break;
623         default:
624             // could also be caught on construction
625             LOG_ALWAYS_FATAL("invalid format %#x for TimestretchBufferProvider", mFormat);
626         }
627     }
628 }
629 
AdjustChannelsBufferProvider(audio_format_t format,size_t inChannelCount,size_t outChannelCount,size_t frameCount,audio_format_t contractedFormat,void * contractedBuffer)630 AdjustChannelsBufferProvider::AdjustChannelsBufferProvider(
631         audio_format_t format, size_t inChannelCount, size_t outChannelCount,
632         size_t frameCount, audio_format_t contractedFormat, void* contractedBuffer) :
633         CopyBufferProvider(
634                 audio_bytes_per_frame(inChannelCount, format),
635                 audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format),
636                 frameCount),
637         mFormat(format),
638         mInChannelCount(inChannelCount),
639         mOutChannelCount(outChannelCount),
640         mSampleSizeInBytes(audio_bytes_per_sample(format)),
641         mFrameCount(frameCount),
642         mContractedChannelCount(inChannelCount - outChannelCount),
643         mContractedFormat(contractedFormat),
644         mContractedBuffer(contractedBuffer),
645         mContractedWrittenFrames(0)
646 {
647     ALOGV("AdjustChannelsBufferProvider(%p)(%#x, %zu, %zu, %zu, %#x, %p)", this, format,
648             inChannelCount, outChannelCount, frameCount, contractedFormat, contractedBuffer);
649     if (mContractedFormat != AUDIO_FORMAT_INVALID && mInChannelCount > mOutChannelCount) {
650         mContractedFrameSize = audio_bytes_per_frame(mContractedChannelCount, mContractedFormat);
651     }
652 }
653 
getNextBuffer(AudioBufferProvider::Buffer * pBuffer)654 status_t AdjustChannelsBufferProvider::getNextBuffer(AudioBufferProvider::Buffer* pBuffer)
655 {
656     if (mContractedBuffer != nullptr) {
657         // Restrict frame count only when it is needed to save contracted frames.
658         const size_t outFramesLeft = mFrameCount - mContractedWrittenFrames;
659         if (outFramesLeft < pBuffer->frameCount) {
660             // Restrict the frame count so that we don't write over the size of the output buffer.
661             pBuffer->frameCount = outFramesLeft;
662         }
663     }
664     return CopyBufferProvider::getNextBuffer(pBuffer);
665 }
666 
copyFrames(void * dst,const void * src,size_t frames)667 void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
668 {
669     if (mInChannelCount > mOutChannelCount) {
670         // For case multi to mono, adjust_channels has special logic that will mix first two input
671         // channels into a single output channel. In that case, use adjust_channels_non_destructive
672         // to keep only one channel data even when contracting to mono.
673         adjust_channels_non_destructive(src, mInChannelCount, dst, mOutChannelCount,
674                 mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
675         if (mContractedFormat != AUDIO_FORMAT_INVALID
676             && mContractedBuffer != nullptr) {
677             const size_t contractedIdx = frames * mOutChannelCount * mSampleSizeInBytes;
678             memcpy_by_audio_format(
679                     (uint8_t*) mContractedBuffer + mContractedWrittenFrames * mContractedFrameSize,
680                     mContractedFormat, (uint8_t*) dst + contractedIdx, mFormat,
681                     mContractedChannelCount * frames);
682             mContractedWrittenFrames += frames;
683         }
684     } else {
685         // Prefer expanding data from the end of each audio frame.
686         adjust_channels(src, mInChannelCount, dst, mOutChannelCount,
687                 mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
688     }
689 }
690 
reset()691 void AdjustChannelsBufferProvider::reset()
692 {
693     mContractedWrittenFrames = 0;
694     CopyBufferProvider::reset();
695 }
696 // ----------------------------------------------------------------------------
697 } // namespace android
698