AudioSource.cpp revision 3c3763d2ee1cd1fba7fe522fbaf0faca315d8c2a
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),
3847204e1806da9f849464d0cef936851d7e561607James Dong      mTotalLostFrames(0),
3947204e1806da9f849464d0cef936851d7e561607James Dong      mPrevLostBytes(0),
40e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber      mGroup(NULL) {
41be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong
42be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong    LOGV("sampleRate: %d, channels: %d", sampleRate, channels);
43f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    CHECK(channels == 1 || channels == 2);
44be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong    uint32_t flags = AudioRecord::RECORD_AGC_ENABLE |
45be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                     AudioRecord::RECORD_NS_ENABLE  |
46be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                     AudioRecord::RECORD_IIR_ENABLE;
47be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong
48be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong    mRecord = new AudioRecord(
49be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                inputSource, sampleRate, AudioSystem::PCM_16_BIT,
50be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                channels > 1? AudioSystem::CHANNEL_IN_STEREO: AudioSystem::CHANNEL_IN_MONO,
51be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                4 * kMaxBufferSize / sizeof(int16_t), /* Enable ping-pong buffers */
52be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                flags);
53be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong
54be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong    mInitCheck = mRecord->initCheck();
55e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
56e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
57e7c9cb48fec02697227bd847cd2e69432659adfdAndreas HuberAudioSource::~AudioSource() {
58e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (mStarted) {
59e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        stop();
60e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
61e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
62e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    delete mRecord;
63e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    mRecord = NULL;
64e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
65e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
66e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::initCheck() const {
67e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return mInitCheck;
68e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
69e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
70e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::start(MetaData *params) {
71e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (mStarted) {
72e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        return UNKNOWN_ERROR;
73e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
74e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
756e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    if (mInitCheck != OK) {
766e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong        return NO_INIT;
776e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    }
786e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
79365a963142093a1cd8efdcea76b5f65096a5b115James Dong    char value[PROPERTY_VALUE_MAX];
80365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (property_get("media.stagefright.record-stats", value, NULL)
81365a963142093a1cd8efdcea76b5f65096a5b115James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
82365a963142093a1cd8efdcea76b5f65096a5b115James Dong        mCollectStats = true;
83365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
84f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
85d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    mTrackMaxAmplitude = false;
86d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    mMaxAmplitude = 0;
87d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mInitialReadTimeUs = 0;
88f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mStartTimeUs = 0;
89f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t startTimeUs;
90f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (params && params->findInt64(kKeyTime, &startTimeUs)) {
91f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimeUs = startTimeUs;
92f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
93e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    status_t err = mRecord->start();
94e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
95e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (err == OK) {
96e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        mGroup = new MediaBufferGroup;
97e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        mGroup->add_buffer(new MediaBuffer(kMaxBufferSize));
98e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
99e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        mStarted = true;
100e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
101e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
102e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return err;
103e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
104e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
105e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::stop() {
106e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (!mStarted) {
107e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        return UNKNOWN_ERROR;
108e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
109e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
1106e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    if (mInitCheck != OK) {
1116e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong        return NO_INIT;
1126e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    }
1136e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
114e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    mRecord->stop();
115e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
116e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    delete mGroup;
117e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    mGroup = NULL;
118e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
119e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    mStarted = false;
120e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
121365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (mCollectStats) {
12247204e1806da9f849464d0cef936851d7e561607James Dong        LOGI("Total lost audio frames: %lld",
12347204e1806da9f849464d0cef936851d7e561607James Dong            mTotalLostFrames + (mPrevLostBytes >> 1));
124365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
125365a963142093a1cd8efdcea76b5f65096a5b115James Dong
126e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return OK;
127e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
128e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
129e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Hubersp<MetaData> AudioSource::getFormat() {
1306e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    if (mInitCheck != OK) {
1316e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong        return 0;
1326e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    }
1336e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
134e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    sp<MetaData> meta = new MetaData;
135e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
136e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setInt32(kKeySampleRate, mRecord->getSampleRate());
137e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setInt32(kKeyChannelCount, mRecord->channelCount());
138e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setInt32(kKeyMaxInputSize, kMaxBufferSize);
139e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
140e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return meta;
141e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
142e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
14346292fb347d72a314d985e34e5e3743d846cb9b6James Dong/*
14446292fb347d72a314d985e34e5e3743d846cb9b6James Dong * Returns -1 if frame skipping request is too long.
14546292fb347d72a314d985e34e5e3743d846cb9b6James Dong * Returns  0 if there is no need to skip frames.
14646292fb347d72a314d985e34e5e3743d846cb9b6James Dong * Returns  1 if we need to skip frames.
14746292fb347d72a314d985e34e5e3743d846cb9b6James Dong */
14846292fb347d72a314d985e34e5e3743d846cb9b6James Dongstatic int skipFrame(int64_t timestampUs,
14946292fb347d72a314d985e34e5e3743d846cb9b6James Dong        const MediaSource::ReadOptions *options) {
15046292fb347d72a314d985e34e5e3743d846cb9b6James Dong
15146292fb347d72a314d985e34e5e3743d846cb9b6James Dong    int64_t skipFrameUs;
15246292fb347d72a314d985e34e5e3743d846cb9b6James Dong    if (!options || !options->getSkipFrame(&skipFrameUs)) {
15346292fb347d72a314d985e34e5e3743d846cb9b6James Dong        return 0;
15446292fb347d72a314d985e34e5e3743d846cb9b6James Dong    }
15546292fb347d72a314d985e34e5e3743d846cb9b6James Dong
15646292fb347d72a314d985e34e5e3743d846cb9b6James Dong    if (skipFrameUs <= timestampUs) {
15746292fb347d72a314d985e34e5e3743d846cb9b6James Dong        return 0;
15846292fb347d72a314d985e34e5e3743d846cb9b6James Dong    }
15946292fb347d72a314d985e34e5e3743d846cb9b6James Dong
16046292fb347d72a314d985e34e5e3743d846cb9b6James Dong    // Safe guard against the abuse of the kSkipFrame_Option.
16146292fb347d72a314d985e34e5e3743d846cb9b6James Dong    if (skipFrameUs - timestampUs >= 1E6) {
16246292fb347d72a314d985e34e5e3743d846cb9b6James Dong        LOGE("Frame skipping requested is way too long: %lld us",
16346292fb347d72a314d985e34e5e3743d846cb9b6James Dong            skipFrameUs - timestampUs);
16446292fb347d72a314d985e34e5e3743d846cb9b6James Dong
16546292fb347d72a314d985e34e5e3743d846cb9b6James Dong        return -1;
16646292fb347d72a314d985e34e5e3743d846cb9b6James Dong    }
16746292fb347d72a314d985e34e5e3743d846cb9b6James Dong
16846292fb347d72a314d985e34e5e3743d846cb9b6James Dong    LOGV("skipFrame: %lld us > timestamp: %lld us",
16946292fb347d72a314d985e34e5e3743d846cb9b6James Dong        skipFrameUs, timestampUs);
17046292fb347d72a314d985e34e5e3743d846cb9b6James Dong
17146292fb347d72a314d985e34e5e3743d846cb9b6James Dong    return 1;
17246292fb347d72a314d985e34e5e3743d846cb9b6James Dong
17346292fb347d72a314d985e34e5e3743d846cb9b6James Dong}
17446292fb347d72a314d985e34e5e3743d846cb9b6James Dong
175f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dongvoid AudioSource::rampVolume(
176f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        int32_t startFrame, int32_t rampDurationFrames,
177f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        uint8_t *data,   size_t bytes) {
178f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
179f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    const int32_t kShift = 14;
180f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    int32_t fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
181f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    const int32_t nChannels = mRecord->channelCount();
182f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    int32_t stopFrame = startFrame + bytes / sizeof(int16_t);
183f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    int16_t *frame = (int16_t *) data;
184f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    if (stopFrame > rampDurationFrames) {
185f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        stopFrame = rampDurationFrames;
186f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    }
187f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
188f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    while (startFrame < stopFrame) {
189f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        if (nChannels == 1) {  // mono
190f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame[0] = (frame[0] * fixedMultiplier) >> kShift;
191f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            ++frame;
192f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            ++startFrame;
193f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        } else {               // stereo
194f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame[0] = (frame[0] * fixedMultiplier) >> kShift;
195f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame[1] = (frame[1] * fixedMultiplier) >> kShift;
196f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame += 2;
197f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            startFrame += 2;
198f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        }
199f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
200f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        // Update the multiplier every 4 frames
201f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        if ((startFrame & 3) == 0) {
202f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
203f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        }
204f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    }
205f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong}
206f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
207e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::read(
208e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        MediaBuffer **out, const ReadOptions *options) {
2096e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
2106e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    if (mInitCheck != OK) {
2116e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong        return NO_INIT;
2126e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    }
2136e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
214d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    int64_t readTimeUs = systemTime() / 1000;
215e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    *out = NULL;
216e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
217e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    MediaBuffer *buffer;
218e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    CHECK_EQ(mGroup->acquire_buffer(&buffer), OK);
219e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
22046292fb347d72a314d985e34e5e3743d846cb9b6James Dong    int err = 0;
221542db5d438988360d491a5add1040a2df9aa90c9James Dong    while (mStarted) {
22246292fb347d72a314d985e34e5e3743d846cb9b6James Dong
223542db5d438988360d491a5add1040a2df9aa90c9James Dong        uint32_t numFramesRecorded;
224542db5d438988360d491a5add1040a2df9aa90c9James Dong        mRecord->getPosition(&numFramesRecorded);
225542db5d438988360d491a5add1040a2df9aa90c9James Dong
226542db5d438988360d491a5add1040a2df9aa90c9James Dong
22746292fb347d72a314d985e34e5e3743d846cb9b6James Dong        if (numFramesRecorded == 0 && mPrevSampleTimeUs == 0) {
228d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong            mInitialReadTimeUs = readTimeUs;
229542db5d438988360d491a5add1040a2df9aa90c9James Dong            // Initial delay
230542db5d438988360d491a5add1040a2df9aa90c9James Dong            if (mStartTimeUs > 0) {
231d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong                mStartTimeUs = readTimeUs - mStartTimeUs;
232542db5d438988360d491a5add1040a2df9aa90c9James Dong            } else {
23346292fb347d72a314d985e34e5e3743d846cb9b6James Dong                // Assume latency is constant.
23446292fb347d72a314d985e34e5e3743d846cb9b6James Dong                mStartTimeUs += mRecord->latency() * 1000;
235542db5d438988360d491a5add1040a2df9aa90c9James Dong            }
23646292fb347d72a314d985e34e5e3743d846cb9b6James Dong            mPrevSampleTimeUs = mStartTimeUs;
237542db5d438988360d491a5add1040a2df9aa90c9James Dong        }
238542db5d438988360d491a5add1040a2df9aa90c9James Dong
23946292fb347d72a314d985e34e5e3743d846cb9b6James Dong        uint32_t sampleRate = mRecord->getSampleRate();
24046292fb347d72a314d985e34e5e3743d846cb9b6James Dong
24146292fb347d72a314d985e34e5e3743d846cb9b6James Dong        // Insert null frames when lost frames are detected.
24246292fb347d72a314d985e34e5e3743d846cb9b6James Dong        int64_t timestampUs = mPrevSampleTimeUs;
24346292fb347d72a314d985e34e5e3743d846cb9b6James Dong        uint32_t numLostBytes = mRecord->getInputFramesLost() << 1;
24447204e1806da9f849464d0cef936851d7e561607James Dong        numLostBytes += mPrevLostBytes;
24546292fb347d72a314d985e34e5e3743d846cb9b6James Dong#if 0
24646292fb347d72a314d985e34e5e3743d846cb9b6James Dong        // Simulate lost frames
24747204e1806da9f849464d0cef936851d7e561607James Dong        numLostBytes = ((rand() * 1.0 / RAND_MAX)) * 2 * kMaxBufferSize;
24847204e1806da9f849464d0cef936851d7e561607James Dong        numLostBytes &= 0xFFFFFFFE; // Alignment requirement
24946292fb347d72a314d985e34e5e3743d846cb9b6James Dong
25046292fb347d72a314d985e34e5e3743d846cb9b6James Dong        // Reduce the chance to lose
25146292fb347d72a314d985e34e5e3743d846cb9b6James Dong        if (rand() * 1.0 / RAND_MAX >= 0.05) {
25246292fb347d72a314d985e34e5e3743d846cb9b6James Dong            numLostBytes = 0;
25346292fb347d72a314d985e34e5e3743d846cb9b6James Dong        }
25446292fb347d72a314d985e34e5e3743d846cb9b6James Dong#endif
25546292fb347d72a314d985e34e5e3743d846cb9b6James Dong        if (numLostBytes > 0) {
25647204e1806da9f849464d0cef936851d7e561607James Dong            if (numLostBytes > kMaxBufferSize) {
25747204e1806da9f849464d0cef936851d7e561607James Dong                mPrevLostBytes = numLostBytes - kMaxBufferSize;
25847204e1806da9f849464d0cef936851d7e561607James Dong                numLostBytes = kMaxBufferSize;
25947204e1806da9f849464d0cef936851d7e561607James Dong            }
26047204e1806da9f849464d0cef936851d7e561607James Dong
26147204e1806da9f849464d0cef936851d7e561607James Dong            CHECK_EQ(numLostBytes & 1, 0);
26247204e1806da9f849464d0cef936851d7e561607James Dong            timestampUs += ((1000000LL * (numLostBytes >> 1)) +
26347204e1806da9f849464d0cef936851d7e561607James Dong                    (sampleRate >> 1)) / sampleRate;
26446292fb347d72a314d985e34e5e3743d846cb9b6James Dong
26546292fb347d72a314d985e34e5e3743d846cb9b6James Dong            CHECK(timestampUs > mPrevSampleTimeUs);
26646292fb347d72a314d985e34e5e3743d846cb9b6James Dong            if (mCollectStats) {
26747204e1806da9f849464d0cef936851d7e561607James Dong                mTotalLostFrames += (numLostBytes >> 1);
26846292fb347d72a314d985e34e5e3743d846cb9b6James Dong            }
26946292fb347d72a314d985e34e5e3743d846cb9b6James Dong            if ((err = skipFrame(timestampUs, options)) == -1) {
27046292fb347d72a314d985e34e5e3743d846cb9b6James Dong                buffer->release();
27146292fb347d72a314d985e34e5e3743d846cb9b6James Dong                return UNKNOWN_ERROR;
27246292fb347d72a314d985e34e5e3743d846cb9b6James Dong            } else if (err != 0) {
27346292fb347d72a314d985e34e5e3743d846cb9b6James Dong                continue;
274542db5d438988360d491a5add1040a2df9aa90c9James Dong            }
27546292fb347d72a314d985e34e5e3743d846cb9b6James Dong            memset(buffer->data(), 0, numLostBytes);
27646292fb347d72a314d985e34e5e3743d846cb9b6James Dong            buffer->set_range(0, numLostBytes);
277d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong            if (numFramesRecorded == 0) {
278d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong                buffer->meta_data()->setInt64(kKeyTime, mStartTimeUs);
279d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong            }
280d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong            buffer->meta_data()->setInt64(kKeyDriftTime, readTimeUs - mInitialReadTimeUs);
28146292fb347d72a314d985e34e5e3743d846cb9b6James Dong            mPrevSampleTimeUs = timestampUs;
28246292fb347d72a314d985e34e5e3743d846cb9b6James Dong            *out = buffer;
28346292fb347d72a314d985e34e5e3743d846cb9b6James Dong            return OK;
284f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        }
285e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
28646292fb347d72a314d985e34e5e3743d846cb9b6James Dong        ssize_t n = mRecord->read(buffer->data(), buffer->size());
287542db5d438988360d491a5add1040a2df9aa90c9James Dong        if (n < 0) {
288542db5d438988360d491a5add1040a2df9aa90c9James Dong            buffer->release();
289542db5d438988360d491a5add1040a2df9aa90c9James Dong            return (status_t)n;
290365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
291e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
29246292fb347d72a314d985e34e5e3743d846cb9b6James Dong        int64_t recordDurationUs = (1000000LL * n >> 1) / sampleRate;
29346292fb347d72a314d985e34e5e3743d846cb9b6James Dong        timestampUs += recordDurationUs;
29446292fb347d72a314d985e34e5e3743d846cb9b6James Dong        if ((err = skipFrame(timestampUs, options)) == -1) {
29546292fb347d72a314d985e34e5e3743d846cb9b6James Dong            buffer->release();
29646292fb347d72a314d985e34e5e3743d846cb9b6James Dong            return UNKNOWN_ERROR;
29746292fb347d72a314d985e34e5e3743d846cb9b6James Dong        } else if (err != 0) {
298542db5d438988360d491a5add1040a2df9aa90c9James Dong            continue;
299542db5d438988360d491a5add1040a2df9aa90c9James Dong        }
300e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
301f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        if (mPrevSampleTimeUs - mStartTimeUs < kAutoRampStartUs) {
302f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            // Mute the initial video recording signal
303f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            memset((uint8_t *) buffer->data(), 0, n);
304f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        } else if (mPrevSampleTimeUs - mStartTimeUs < kAutoRampStartUs + kAutoRampDurationUs) {
305f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            int32_t autoRampDurationFrames =
306f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong                    (kAutoRampDurationUs * sampleRate + 500000LL) / 1000000LL;
307f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
308f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            int32_t autoRampStartFrames =
309f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong                    (kAutoRampStartUs * sampleRate + 500000LL) / 1000000LL;
310f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
311f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            int32_t nFrames = numFramesRecorded - autoRampStartFrames;
312f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            rampVolume(nFrames, autoRampDurationFrames, (uint8_t *) buffer->data(), n);
313f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        }
314542db5d438988360d491a5add1040a2df9aa90c9James Dong        if (mTrackMaxAmplitude) {
315542db5d438988360d491a5add1040a2df9aa90c9James Dong            trackMaxAmplitude((int16_t *) buffer->data(), n >> 1);
316542db5d438988360d491a5add1040a2df9aa90c9James Dong        }
317d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong
318d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong        if (numFramesRecorded == 0) {
3193c3763d2ee1cd1fba7fe522fbaf0faca315d8c2aJames Dong            buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs);
320d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong        }
3213c3763d2ee1cd1fba7fe522fbaf0faca315d8c2aJames Dong
3223c3763d2ee1cd1fba7fe522fbaf0faca315d8c2aJames Dong        buffer->meta_data()->setInt64(kKeyTime, mStartTimeUs + mPrevSampleTimeUs);
323d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong        buffer->meta_data()->setInt64(kKeyDriftTime, readTimeUs - mInitialReadTimeUs);
32446292fb347d72a314d985e34e5e3743d846cb9b6James Dong        CHECK(timestampUs > mPrevSampleTimeUs);
32546292fb347d72a314d985e34e5e3743d846cb9b6James Dong        mPrevSampleTimeUs = timestampUs;
326542db5d438988360d491a5add1040a2df9aa90c9James Dong        LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld",
327542db5d438988360d491a5add1040a2df9aa90c9James Dong                mStartTimeUs, sampleRate, timestampUs);
328f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
329542db5d438988360d491a5add1040a2df9aa90c9James Dong        buffer->set_range(0, n);
330e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
331542db5d438988360d491a5add1040a2df9aa90c9James Dong        *out = buffer;
332542db5d438988360d491a5add1040a2df9aa90c9James Dong        return OK;
333542db5d438988360d491a5add1040a2df9aa90c9James Dong    }
334e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
335e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return OK;
336e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
337e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
338d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dongvoid AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) {
339d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    for (int i = nSamples; i > 0; --i) {
340d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        int16_t value = *data++;
341d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        if (value < 0) {
342d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong            value = -value;
343d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        }
344d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        if (mMaxAmplitude < value) {
345d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong            mMaxAmplitude = value;
346d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        }
347d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    }
348d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong}
349d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong
350d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dongint16_t AudioSource::getMaxAmplitude() {
351d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    // First call activates the tracking.
352d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    if (!mTrackMaxAmplitude) {
353d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        mTrackMaxAmplitude = true;
354d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    }
355d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    int16_t value = mMaxAmplitude;
356d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    mMaxAmplitude = 0;
357d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    LOGV("max amplitude since last call: %d", value);
358d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    return value;
359d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong}
360d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong
361e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}  // namespace android
362