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