AudioSource.cpp revision 46292fb347d72a314d985e34e5e3743d846cb9b6
1e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber/* 2e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * Copyright (C) 2010 The Android Open Source Project 3e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * 4e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * you may not use this file except in compliance with the License. 6e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * You may obtain a copy of the License at 7e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * 8e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * 10e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * Unless required by applicable law or agreed to in writing, software 11e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * See the License for the specific language governing permissions and 14e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * limitations under the License. 15e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber */ 16e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 17050b28a593350047845a45a14cc5026221ac1620James Dong//#define LOG_NDEBUG 0 18050b28a593350047845a45a14cc5026221ac1620James Dong#define LOG_TAG "AudioSource" 19050b28a593350047845a45a14cc5026221ac1620James Dong#include <utils/Log.h> 20050b28a593350047845a45a14cc5026221ac1620James Dong 21e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/AudioSource.h> 22e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 23e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/AudioRecord.h> 24e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MediaBufferGroup.h> 25e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MediaDebug.h> 26e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MediaDefs.h> 27e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MetaData.h> 28365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <cutils/properties.h> 2946292fb347d72a314d985e34e5e3743d846cb9b6James Dong#include <stdlib.h> 30e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 31e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Hubernamespace android { 32e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 33e7c9cb48fec02697227bd847cd2e69432659adfdAndreas HuberAudioSource::AudioSource( 34e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber int inputSource, uint32_t sampleRate, uint32_t channels) 35be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong : mStarted(false), 36365a963142093a1cd8efdcea76b5f65096a5b115James Dong mCollectStats(false), 3746292fb347d72a314d985e34e5e3743d846cb9b6James Dong mPrevSampleTimeUs(0), 3846292fb347d72a314d985e34e5e3743d846cb9b6James Dong mNumLostFrames(0), 39e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber mGroup(NULL) { 40be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong 41be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong LOGV("sampleRate: %d, channels: %d", sampleRate, channels); 42be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong uint32_t flags = AudioRecord::RECORD_AGC_ENABLE | 43be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong AudioRecord::RECORD_NS_ENABLE | 44be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong AudioRecord::RECORD_IIR_ENABLE; 45be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong 46be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong mRecord = new AudioRecord( 47be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong inputSource, sampleRate, AudioSystem::PCM_16_BIT, 48be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong channels > 1? AudioSystem::CHANNEL_IN_STEREO: AudioSystem::CHANNEL_IN_MONO, 49be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong 4 * kMaxBufferSize / sizeof(int16_t), /* Enable ping-pong buffers */ 50be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong flags); 51be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong 52be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong mInitCheck = mRecord->initCheck(); 53e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 54e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 55e7c9cb48fec02697227bd847cd2e69432659adfdAndreas HuberAudioSource::~AudioSource() { 56e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber if (mStarted) { 57e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber stop(); 58e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber } 59e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 60e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber delete mRecord; 61e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber mRecord = NULL; 62e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 63e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 64e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::initCheck() const { 65e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber return mInitCheck; 66e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 67e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 68e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::start(MetaData *params) { 69e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber if (mStarted) { 70e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber return UNKNOWN_ERROR; 71e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber } 72e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 73365a963142093a1cd8efdcea76b5f65096a5b115James Dong char value[PROPERTY_VALUE_MAX]; 74365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (property_get("media.stagefright.record-stats", value, NULL) 75365a963142093a1cd8efdcea76b5f65096a5b115James Dong && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 76365a963142093a1cd8efdcea76b5f65096a5b115James Dong mCollectStats = true; 77365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 78f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong 79d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong mTrackMaxAmplitude = false; 80d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong mMaxAmplitude = 0; 81f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimeUs = 0; 82f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong int64_t startTimeUs; 83f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong if (params && params->findInt64(kKeyTime, &startTimeUs)) { 84f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimeUs = startTimeUs; 85f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong } 86e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber status_t err = mRecord->start(); 87e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 88e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber if (err == OK) { 89e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber mGroup = new MediaBufferGroup; 90e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber mGroup->add_buffer(new MediaBuffer(kMaxBufferSize)); 91e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 92e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber mStarted = true; 93e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber } 94e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 95e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber return err; 96e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 97e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 98e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::stop() { 99e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber if (!mStarted) { 100e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber return UNKNOWN_ERROR; 101e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber } 102e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 103e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber mRecord->stop(); 104e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 105e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber delete mGroup; 106e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber mGroup = NULL; 107e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 108e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber mStarted = false; 109e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 110365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (mCollectStats) { 11146292fb347d72a314d985e34e5e3743d846cb9b6James Dong LOGI("Total lost audio frames: %lld", mNumLostFrames); 112365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 113365a963142093a1cd8efdcea76b5f65096a5b115James Dong 114e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber return OK; 115e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 116e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 117e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Hubersp<MetaData> AudioSource::getFormat() { 118e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber sp<MetaData> meta = new MetaData; 119e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); 120e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber meta->setInt32(kKeySampleRate, mRecord->getSampleRate()); 121e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber meta->setInt32(kKeyChannelCount, mRecord->channelCount()); 122e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber meta->setInt32(kKeyMaxInputSize, kMaxBufferSize); 123e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 124e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber return meta; 125e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 126e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 12746292fb347d72a314d985e34e5e3743d846cb9b6James Dong/* 12846292fb347d72a314d985e34e5e3743d846cb9b6James Dong * Returns -1 if frame skipping request is too long. 12946292fb347d72a314d985e34e5e3743d846cb9b6James Dong * Returns 0 if there is no need to skip frames. 13046292fb347d72a314d985e34e5e3743d846cb9b6James Dong * Returns 1 if we need to skip frames. 13146292fb347d72a314d985e34e5e3743d846cb9b6James Dong */ 13246292fb347d72a314d985e34e5e3743d846cb9b6James Dongstatic int skipFrame(int64_t timestampUs, 13346292fb347d72a314d985e34e5e3743d846cb9b6James Dong const MediaSource::ReadOptions *options) { 13446292fb347d72a314d985e34e5e3743d846cb9b6James Dong 13546292fb347d72a314d985e34e5e3743d846cb9b6James Dong int64_t skipFrameUs; 13646292fb347d72a314d985e34e5e3743d846cb9b6James Dong if (!options || !options->getSkipFrame(&skipFrameUs)) { 13746292fb347d72a314d985e34e5e3743d846cb9b6James Dong return 0; 13846292fb347d72a314d985e34e5e3743d846cb9b6James Dong } 13946292fb347d72a314d985e34e5e3743d846cb9b6James Dong 14046292fb347d72a314d985e34e5e3743d846cb9b6James Dong if (skipFrameUs <= timestampUs) { 14146292fb347d72a314d985e34e5e3743d846cb9b6James Dong return 0; 14246292fb347d72a314d985e34e5e3743d846cb9b6James Dong } 14346292fb347d72a314d985e34e5e3743d846cb9b6James Dong 14446292fb347d72a314d985e34e5e3743d846cb9b6James Dong // Safe guard against the abuse of the kSkipFrame_Option. 14546292fb347d72a314d985e34e5e3743d846cb9b6James Dong if (skipFrameUs - timestampUs >= 1E6) { 14646292fb347d72a314d985e34e5e3743d846cb9b6James Dong LOGE("Frame skipping requested is way too long: %lld us", 14746292fb347d72a314d985e34e5e3743d846cb9b6James Dong skipFrameUs - timestampUs); 14846292fb347d72a314d985e34e5e3743d846cb9b6James Dong 14946292fb347d72a314d985e34e5e3743d846cb9b6James Dong return -1; 15046292fb347d72a314d985e34e5e3743d846cb9b6James Dong } 15146292fb347d72a314d985e34e5e3743d846cb9b6James Dong 15246292fb347d72a314d985e34e5e3743d846cb9b6James Dong LOGV("skipFrame: %lld us > timestamp: %lld us", 15346292fb347d72a314d985e34e5e3743d846cb9b6James Dong skipFrameUs, timestampUs); 15446292fb347d72a314d985e34e5e3743d846cb9b6James Dong 15546292fb347d72a314d985e34e5e3743d846cb9b6James Dong return 1; 15646292fb347d72a314d985e34e5e3743d846cb9b6James Dong 15746292fb347d72a314d985e34e5e3743d846cb9b6James Dong} 15846292fb347d72a314d985e34e5e3743d846cb9b6James Dong 159e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::read( 160e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber MediaBuffer **out, const ReadOptions *options) { 161e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber *out = NULL; 162e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 163e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber MediaBuffer *buffer; 164e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber CHECK_EQ(mGroup->acquire_buffer(&buffer), OK); 165e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 16646292fb347d72a314d985e34e5e3743d846cb9b6James Dong int err = 0; 167542db5d438988360d491a5add1040a2df9aa90c9James Dong while (mStarted) { 16846292fb347d72a314d985e34e5e3743d846cb9b6James Dong 169542db5d438988360d491a5add1040a2df9aa90c9James Dong uint32_t numFramesRecorded; 170542db5d438988360d491a5add1040a2df9aa90c9James Dong mRecord->getPosition(&numFramesRecorded); 171542db5d438988360d491a5add1040a2df9aa90c9James Dong 172542db5d438988360d491a5add1040a2df9aa90c9James Dong 17346292fb347d72a314d985e34e5e3743d846cb9b6James Dong if (numFramesRecorded == 0 && mPrevSampleTimeUs == 0) { 174542db5d438988360d491a5add1040a2df9aa90c9James Dong // Initial delay 175542db5d438988360d491a5add1040a2df9aa90c9James Dong if (mStartTimeUs > 0) { 17646292fb347d72a314d985e34e5e3743d846cb9b6James Dong mStartTimeUs = systemTime() / 1000 - mStartTimeUs; 177542db5d438988360d491a5add1040a2df9aa90c9James Dong } else { 17846292fb347d72a314d985e34e5e3743d846cb9b6James Dong // Assume latency is constant. 17946292fb347d72a314d985e34e5e3743d846cb9b6James Dong mStartTimeUs += mRecord->latency() * 1000; 180542db5d438988360d491a5add1040a2df9aa90c9James Dong } 18146292fb347d72a314d985e34e5e3743d846cb9b6James Dong mPrevSampleTimeUs = mStartTimeUs; 182542db5d438988360d491a5add1040a2df9aa90c9James Dong } 183542db5d438988360d491a5add1040a2df9aa90c9James Dong 18446292fb347d72a314d985e34e5e3743d846cb9b6James Dong uint32_t sampleRate = mRecord->getSampleRate(); 18546292fb347d72a314d985e34e5e3743d846cb9b6James Dong 18646292fb347d72a314d985e34e5e3743d846cb9b6James Dong // Insert null frames when lost frames are detected. 18746292fb347d72a314d985e34e5e3743d846cb9b6James Dong int64_t timestampUs = mPrevSampleTimeUs; 18846292fb347d72a314d985e34e5e3743d846cb9b6James Dong uint32_t numLostBytes = mRecord->getInputFramesLost() << 1; 18946292fb347d72a314d985e34e5e3743d846cb9b6James Dong#if 0 19046292fb347d72a314d985e34e5e3743d846cb9b6James Dong // Simulate lost frames 19146292fb347d72a314d985e34e5e3743d846cb9b6James Dong numLostBytes = ((rand() * 1.0 / RAND_MAX)) * kMaxBufferSize; 19246292fb347d72a314d985e34e5e3743d846cb9b6James Dong numLostBytes &= 0xFFFFFFFE; // Alignment request 19346292fb347d72a314d985e34e5e3743d846cb9b6James Dong 19446292fb347d72a314d985e34e5e3743d846cb9b6James Dong // Reduce the chance to lose 19546292fb347d72a314d985e34e5e3743d846cb9b6James Dong if (rand() * 1.0 / RAND_MAX >= 0.05) { 19646292fb347d72a314d985e34e5e3743d846cb9b6James Dong numLostBytes = 0; 19746292fb347d72a314d985e34e5e3743d846cb9b6James Dong } 19846292fb347d72a314d985e34e5e3743d846cb9b6James Dong#endif 19946292fb347d72a314d985e34e5e3743d846cb9b6James Dong if (numLostBytes > 0) { 20046292fb347d72a314d985e34e5e3743d846cb9b6James Dong // Not expect too many lost frames! 20146292fb347d72a314d985e34e5e3743d846cb9b6James Dong CHECK(numLostBytes <= kMaxBufferSize); 20246292fb347d72a314d985e34e5e3743d846cb9b6James Dong 20346292fb347d72a314d985e34e5e3743d846cb9b6James Dong timestampUs += (1000000LL * numLostBytes >> 1) / sampleRate; 20446292fb347d72a314d985e34e5e3743d846cb9b6James Dong CHECK(timestampUs > mPrevSampleTimeUs); 20546292fb347d72a314d985e34e5e3743d846cb9b6James Dong if (mCollectStats) { 20646292fb347d72a314d985e34e5e3743d846cb9b6James Dong mNumLostFrames += (numLostBytes >> 1); 20746292fb347d72a314d985e34e5e3743d846cb9b6James Dong } 20846292fb347d72a314d985e34e5e3743d846cb9b6James Dong if ((err = skipFrame(timestampUs, options)) == -1) { 20946292fb347d72a314d985e34e5e3743d846cb9b6James Dong buffer->release(); 21046292fb347d72a314d985e34e5e3743d846cb9b6James Dong return UNKNOWN_ERROR; 21146292fb347d72a314d985e34e5e3743d846cb9b6James Dong } else if (err != 0) { 21246292fb347d72a314d985e34e5e3743d846cb9b6James Dong continue; 213542db5d438988360d491a5add1040a2df9aa90c9James Dong } 21446292fb347d72a314d985e34e5e3743d846cb9b6James Dong memset(buffer->data(), 0, numLostBytes); 21546292fb347d72a314d985e34e5e3743d846cb9b6James Dong buffer->set_range(0, numLostBytes); 21646292fb347d72a314d985e34e5e3743d846cb9b6James Dong buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs); 21746292fb347d72a314d985e34e5e3743d846cb9b6James Dong mPrevSampleTimeUs = timestampUs; 21846292fb347d72a314d985e34e5e3743d846cb9b6James Dong *out = buffer; 21946292fb347d72a314d985e34e5e3743d846cb9b6James Dong return OK; 220f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong } 221e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 22246292fb347d72a314d985e34e5e3743d846cb9b6James Dong ssize_t n = mRecord->read(buffer->data(), buffer->size()); 223542db5d438988360d491a5add1040a2df9aa90c9James Dong if (n < 0) { 224542db5d438988360d491a5add1040a2df9aa90c9James Dong buffer->release(); 225542db5d438988360d491a5add1040a2df9aa90c9James Dong return (status_t)n; 226365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 227e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 22846292fb347d72a314d985e34e5e3743d846cb9b6James Dong int64_t recordDurationUs = (1000000LL * n >> 1) / sampleRate; 22946292fb347d72a314d985e34e5e3743d846cb9b6James Dong timestampUs += recordDurationUs; 23046292fb347d72a314d985e34e5e3743d846cb9b6James Dong if ((err = skipFrame(timestampUs, options)) == -1) { 23146292fb347d72a314d985e34e5e3743d846cb9b6James Dong buffer->release(); 23246292fb347d72a314d985e34e5e3743d846cb9b6James Dong return UNKNOWN_ERROR; 23346292fb347d72a314d985e34e5e3743d846cb9b6James Dong } else if (err != 0) { 234542db5d438988360d491a5add1040a2df9aa90c9James Dong continue; 235542db5d438988360d491a5add1040a2df9aa90c9James Dong } 236e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 237542db5d438988360d491a5add1040a2df9aa90c9James Dong if (mTrackMaxAmplitude) { 238542db5d438988360d491a5add1040a2df9aa90c9James Dong trackMaxAmplitude((int16_t *) buffer->data(), n >> 1); 239542db5d438988360d491a5add1040a2df9aa90c9James Dong } 240d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong 24146292fb347d72a314d985e34e5e3743d846cb9b6James Dong buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs); 24246292fb347d72a314d985e34e5e3743d846cb9b6James Dong CHECK(timestampUs > mPrevSampleTimeUs); 24346292fb347d72a314d985e34e5e3743d846cb9b6James Dong if (mNumLostFrames == 0) { 24446292fb347d72a314d985e34e5e3743d846cb9b6James Dong CHECK_EQ(mPrevSampleTimeUs, 24546292fb347d72a314d985e34e5e3743d846cb9b6James Dong mStartTimeUs + (1000000LL * numFramesRecorded) / sampleRate); 24646292fb347d72a314d985e34e5e3743d846cb9b6James Dong } 24746292fb347d72a314d985e34e5e3743d846cb9b6James Dong mPrevSampleTimeUs = timestampUs; 248542db5d438988360d491a5add1040a2df9aa90c9James Dong LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld", 249542db5d438988360d491a5add1040a2df9aa90c9James Dong mStartTimeUs, sampleRate, timestampUs); 250f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong 251542db5d438988360d491a5add1040a2df9aa90c9James Dong buffer->set_range(0, n); 252e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 253542db5d438988360d491a5add1040a2df9aa90c9James Dong *out = buffer; 254542db5d438988360d491a5add1040a2df9aa90c9James Dong return OK; 255542db5d438988360d491a5add1040a2df9aa90c9James Dong } 256e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 257e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber return OK; 258e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 259e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 260d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dongvoid AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) { 261d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong for (int i = nSamples; i > 0; --i) { 262d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong int16_t value = *data++; 263d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong if (value < 0) { 264d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong value = -value; 265d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong } 266d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong if (mMaxAmplitude < value) { 267d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong mMaxAmplitude = value; 268d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong } 269d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong } 270d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong} 271d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong 272d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dongint16_t AudioSource::getMaxAmplitude() { 273d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong // First call activates the tracking. 274d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong if (!mTrackMaxAmplitude) { 275d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong mTrackMaxAmplitude = true; 276d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong } 277d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong int16_t value = mMaxAmplitude; 278d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong mMaxAmplitude = 0; 279d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong LOGV("max amplitude since last call: %d", value); 280d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong return value; 281d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong} 282d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong 283e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} // namespace android 284