AudioSource.cpp revision 6e20bdf799a6f4efa6c42121a958634ea32ed5cc
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;
87f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mStartTimeUs = 0;
88f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t startTimeUs;
89f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (params && params->findInt64(kKeyTime, &startTimeUs)) {
90f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimeUs = startTimeUs;
91f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
92e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    status_t err = mRecord->start();
93e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
94e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (err == OK) {
95e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        mGroup = new MediaBufferGroup;
96e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        mGroup->add_buffer(new MediaBuffer(kMaxBufferSize));
97e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
98e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        mStarted = true;
99e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
100e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
101e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return err;
102e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
103e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
104e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::stop() {
105e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (!mStarted) {
106e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        return UNKNOWN_ERROR;
107e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
108e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
1096e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    if (mInitCheck != OK) {
1106e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong        return NO_INIT;
1116e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    }
1126e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
113e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    mRecord->stop();
114e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
115e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    delete mGroup;
116e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    mGroup = NULL;
117e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
118e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    mStarted = false;
119e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
120365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (mCollectStats) {
12147204e1806da9f849464d0cef936851d7e561607James Dong        LOGI("Total lost audio frames: %lld",
12247204e1806da9f849464d0cef936851d7e561607James Dong            mTotalLostFrames + (mPrevLostBytes >> 1));
123365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
124365a963142093a1cd8efdcea76b5f65096a5b115James Dong
125e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return OK;
126e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
127e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
128e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Hubersp<MetaData> AudioSource::getFormat() {
1296e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    if (mInitCheck != OK) {
1306e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong        return 0;
1316e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    }
1326e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
133e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    sp<MetaData> meta = new MetaData;
134e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
135e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setInt32(kKeySampleRate, mRecord->getSampleRate());
136e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setInt32(kKeyChannelCount, mRecord->channelCount());
137e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setInt32(kKeyMaxInputSize, kMaxBufferSize);
138e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
139e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return meta;
140e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
141e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
14246292fb347d72a314d985e34e5e3743d846cb9b6James Dong/*
14346292fb347d72a314d985e34e5e3743d846cb9b6James Dong * Returns -1 if frame skipping request is too long.
14446292fb347d72a314d985e34e5e3743d846cb9b6James Dong * Returns  0 if there is no need to skip frames.
14546292fb347d72a314d985e34e5e3743d846cb9b6James Dong * Returns  1 if we need to skip frames.
14646292fb347d72a314d985e34e5e3743d846cb9b6James Dong */
14746292fb347d72a314d985e34e5e3743d846cb9b6James Dongstatic int skipFrame(int64_t timestampUs,
14846292fb347d72a314d985e34e5e3743d846cb9b6James Dong        const MediaSource::ReadOptions *options) {
14946292fb347d72a314d985e34e5e3743d846cb9b6James Dong
15046292fb347d72a314d985e34e5e3743d846cb9b6James Dong    int64_t skipFrameUs;
15146292fb347d72a314d985e34e5e3743d846cb9b6James Dong    if (!options || !options->getSkipFrame(&skipFrameUs)) {
15246292fb347d72a314d985e34e5e3743d846cb9b6James Dong        return 0;
15346292fb347d72a314d985e34e5e3743d846cb9b6James Dong    }
15446292fb347d72a314d985e34e5e3743d846cb9b6James Dong
15546292fb347d72a314d985e34e5e3743d846cb9b6James Dong    if (skipFrameUs <= timestampUs) {
15646292fb347d72a314d985e34e5e3743d846cb9b6James Dong        return 0;
15746292fb347d72a314d985e34e5e3743d846cb9b6James Dong    }
15846292fb347d72a314d985e34e5e3743d846cb9b6James Dong
15946292fb347d72a314d985e34e5e3743d846cb9b6James Dong    // Safe guard against the abuse of the kSkipFrame_Option.
16046292fb347d72a314d985e34e5e3743d846cb9b6James Dong    if (skipFrameUs - timestampUs >= 1E6) {
16146292fb347d72a314d985e34e5e3743d846cb9b6James Dong        LOGE("Frame skipping requested is way too long: %lld us",
16246292fb347d72a314d985e34e5e3743d846cb9b6James Dong            skipFrameUs - timestampUs);
16346292fb347d72a314d985e34e5e3743d846cb9b6James Dong
16446292fb347d72a314d985e34e5e3743d846cb9b6James Dong        return -1;
16546292fb347d72a314d985e34e5e3743d846cb9b6James Dong    }
16646292fb347d72a314d985e34e5e3743d846cb9b6James Dong
16746292fb347d72a314d985e34e5e3743d846cb9b6James Dong    LOGV("skipFrame: %lld us > timestamp: %lld us",
16846292fb347d72a314d985e34e5e3743d846cb9b6James Dong        skipFrameUs, timestampUs);
16946292fb347d72a314d985e34e5e3743d846cb9b6James Dong
17046292fb347d72a314d985e34e5e3743d846cb9b6James Dong    return 1;
17146292fb347d72a314d985e34e5e3743d846cb9b6James Dong
17246292fb347d72a314d985e34e5e3743d846cb9b6James Dong}
17346292fb347d72a314d985e34e5e3743d846cb9b6James Dong
174f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dongvoid AudioSource::rampVolume(
175f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        int32_t startFrame, int32_t rampDurationFrames,
176f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        uint8_t *data,   size_t bytes) {
177f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
178f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    const int32_t kShift = 14;
179f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    int32_t fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
180f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    const int32_t nChannels = mRecord->channelCount();
181f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    int32_t stopFrame = startFrame + bytes / sizeof(int16_t);
182f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    int16_t *frame = (int16_t *) data;
183f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    if (stopFrame > rampDurationFrames) {
184f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        stopFrame = rampDurationFrames;
185f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    }
186f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
187f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    while (startFrame < stopFrame) {
188f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        if (nChannels == 1) {  // mono
189f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame[0] = (frame[0] * fixedMultiplier) >> kShift;
190f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            ++frame;
191f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            ++startFrame;
192f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        } else {               // stereo
193f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame[0] = (frame[0] * fixedMultiplier) >> kShift;
194f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame[1] = (frame[1] * fixedMultiplier) >> kShift;
195f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame += 2;
196f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            startFrame += 2;
197f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        }
198f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
199f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        // Update the multiplier every 4 frames
200f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        if ((startFrame & 3) == 0) {
201f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
202f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        }
203f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    }
204f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong}
205f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
206e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::read(
207e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        MediaBuffer **out, const ReadOptions *options) {
2086e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
2096e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    if (mInitCheck != OK) {
2106e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong        return NO_INIT;
2116e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    }
2126e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
213e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    *out = NULL;
214e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
215e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    MediaBuffer *buffer;
216e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    CHECK_EQ(mGroup->acquire_buffer(&buffer), OK);
217e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
21846292fb347d72a314d985e34e5e3743d846cb9b6James Dong    int err = 0;
219542db5d438988360d491a5add1040a2df9aa90c9James Dong    while (mStarted) {
22046292fb347d72a314d985e34e5e3743d846cb9b6James Dong
221542db5d438988360d491a5add1040a2df9aa90c9James Dong        uint32_t numFramesRecorded;
222542db5d438988360d491a5add1040a2df9aa90c9James Dong        mRecord->getPosition(&numFramesRecorded);
223542db5d438988360d491a5add1040a2df9aa90c9James Dong
224542db5d438988360d491a5add1040a2df9aa90c9James Dong
22546292fb347d72a314d985e34e5e3743d846cb9b6James Dong        if (numFramesRecorded == 0 && mPrevSampleTimeUs == 0) {
226542db5d438988360d491a5add1040a2df9aa90c9James Dong            // Initial delay
227542db5d438988360d491a5add1040a2df9aa90c9James Dong            if (mStartTimeUs > 0) {
22846292fb347d72a314d985e34e5e3743d846cb9b6James Dong                mStartTimeUs = systemTime() / 1000 - mStartTimeUs;
229542db5d438988360d491a5add1040a2df9aa90c9James Dong            } else {
23046292fb347d72a314d985e34e5e3743d846cb9b6James Dong                // Assume latency is constant.
23146292fb347d72a314d985e34e5e3743d846cb9b6James Dong                mStartTimeUs += mRecord->latency() * 1000;
232542db5d438988360d491a5add1040a2df9aa90c9James Dong            }
23346292fb347d72a314d985e34e5e3743d846cb9b6James Dong            mPrevSampleTimeUs = mStartTimeUs;
234542db5d438988360d491a5add1040a2df9aa90c9James Dong        }
235542db5d438988360d491a5add1040a2df9aa90c9James Dong
23646292fb347d72a314d985e34e5e3743d846cb9b6James Dong        uint32_t sampleRate = mRecord->getSampleRate();
23746292fb347d72a314d985e34e5e3743d846cb9b6James Dong
23846292fb347d72a314d985e34e5e3743d846cb9b6James Dong        // Insert null frames when lost frames are detected.
23946292fb347d72a314d985e34e5e3743d846cb9b6James Dong        int64_t timestampUs = mPrevSampleTimeUs;
24046292fb347d72a314d985e34e5e3743d846cb9b6James Dong        uint32_t numLostBytes = mRecord->getInputFramesLost() << 1;
24147204e1806da9f849464d0cef936851d7e561607James Dong        numLostBytes += mPrevLostBytes;
24246292fb347d72a314d985e34e5e3743d846cb9b6James Dong#if 0
24346292fb347d72a314d985e34e5e3743d846cb9b6James Dong        // Simulate lost frames
24447204e1806da9f849464d0cef936851d7e561607James Dong        numLostBytes = ((rand() * 1.0 / RAND_MAX)) * 2 * kMaxBufferSize;
24547204e1806da9f849464d0cef936851d7e561607James Dong        numLostBytes &= 0xFFFFFFFE; // Alignment requirement
24646292fb347d72a314d985e34e5e3743d846cb9b6James Dong
24746292fb347d72a314d985e34e5e3743d846cb9b6James Dong        // Reduce the chance to lose
24846292fb347d72a314d985e34e5e3743d846cb9b6James Dong        if (rand() * 1.0 / RAND_MAX >= 0.05) {
24946292fb347d72a314d985e34e5e3743d846cb9b6James Dong            numLostBytes = 0;
25046292fb347d72a314d985e34e5e3743d846cb9b6James Dong        }
25146292fb347d72a314d985e34e5e3743d846cb9b6James Dong#endif
25246292fb347d72a314d985e34e5e3743d846cb9b6James Dong        if (numLostBytes > 0) {
25347204e1806da9f849464d0cef936851d7e561607James Dong            if (numLostBytes > kMaxBufferSize) {
25447204e1806da9f849464d0cef936851d7e561607James Dong                mPrevLostBytes = numLostBytes - kMaxBufferSize;
25547204e1806da9f849464d0cef936851d7e561607James Dong                numLostBytes = kMaxBufferSize;
25647204e1806da9f849464d0cef936851d7e561607James Dong            }
25747204e1806da9f849464d0cef936851d7e561607James Dong
25847204e1806da9f849464d0cef936851d7e561607James Dong            CHECK_EQ(numLostBytes & 1, 0);
25947204e1806da9f849464d0cef936851d7e561607James Dong            timestampUs += ((1000000LL * (numLostBytes >> 1)) +
26047204e1806da9f849464d0cef936851d7e561607James Dong                    (sampleRate >> 1)) / sampleRate;
26146292fb347d72a314d985e34e5e3743d846cb9b6James Dong
26246292fb347d72a314d985e34e5e3743d846cb9b6James Dong            CHECK(timestampUs > mPrevSampleTimeUs);
26346292fb347d72a314d985e34e5e3743d846cb9b6James Dong            if (mCollectStats) {
26447204e1806da9f849464d0cef936851d7e561607James Dong                mTotalLostFrames += (numLostBytes >> 1);
26546292fb347d72a314d985e34e5e3743d846cb9b6James Dong            }
26646292fb347d72a314d985e34e5e3743d846cb9b6James Dong            if ((err = skipFrame(timestampUs, options)) == -1) {
26746292fb347d72a314d985e34e5e3743d846cb9b6James Dong                buffer->release();
26846292fb347d72a314d985e34e5e3743d846cb9b6James Dong                return UNKNOWN_ERROR;
26946292fb347d72a314d985e34e5e3743d846cb9b6James Dong            } else if (err != 0) {
27046292fb347d72a314d985e34e5e3743d846cb9b6James Dong                continue;
271542db5d438988360d491a5add1040a2df9aa90c9James Dong            }
27246292fb347d72a314d985e34e5e3743d846cb9b6James Dong            memset(buffer->data(), 0, numLostBytes);
27346292fb347d72a314d985e34e5e3743d846cb9b6James Dong            buffer->set_range(0, numLostBytes);
27446292fb347d72a314d985e34e5e3743d846cb9b6James Dong            buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs);
27546292fb347d72a314d985e34e5e3743d846cb9b6James Dong            mPrevSampleTimeUs = timestampUs;
27646292fb347d72a314d985e34e5e3743d846cb9b6James Dong            *out = buffer;
27746292fb347d72a314d985e34e5e3743d846cb9b6James Dong            return OK;
278f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        }
279e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
28046292fb347d72a314d985e34e5e3743d846cb9b6James Dong        ssize_t n = mRecord->read(buffer->data(), buffer->size());
281542db5d438988360d491a5add1040a2df9aa90c9James Dong        if (n < 0) {
282542db5d438988360d491a5add1040a2df9aa90c9James Dong            buffer->release();
283542db5d438988360d491a5add1040a2df9aa90c9James Dong            return (status_t)n;
284365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
285e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
28646292fb347d72a314d985e34e5e3743d846cb9b6James Dong        int64_t recordDurationUs = (1000000LL * n >> 1) / sampleRate;
28746292fb347d72a314d985e34e5e3743d846cb9b6James Dong        timestampUs += recordDurationUs;
28846292fb347d72a314d985e34e5e3743d846cb9b6James Dong        if ((err = skipFrame(timestampUs, options)) == -1) {
28946292fb347d72a314d985e34e5e3743d846cb9b6James Dong            buffer->release();
29046292fb347d72a314d985e34e5e3743d846cb9b6James Dong            return UNKNOWN_ERROR;
29146292fb347d72a314d985e34e5e3743d846cb9b6James Dong        } else if (err != 0) {
292542db5d438988360d491a5add1040a2df9aa90c9James Dong            continue;
293542db5d438988360d491a5add1040a2df9aa90c9James Dong        }
294e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
295f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        if (mPrevSampleTimeUs - mStartTimeUs < kAutoRampStartUs) {
296f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            // Mute the initial video recording signal
297f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            memset((uint8_t *) buffer->data(), 0, n);
298f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        } else if (mPrevSampleTimeUs - mStartTimeUs < kAutoRampStartUs + kAutoRampDurationUs) {
299f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            int32_t autoRampDurationFrames =
300f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong                    (kAutoRampDurationUs * sampleRate + 500000LL) / 1000000LL;
301f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
302f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            int32_t autoRampStartFrames =
303f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong                    (kAutoRampStartUs * sampleRate + 500000LL) / 1000000LL;
304f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
305f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            int32_t nFrames = numFramesRecorded - autoRampStartFrames;
306f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            rampVolume(nFrames, autoRampDurationFrames, (uint8_t *) buffer->data(), n);
307f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        }
308542db5d438988360d491a5add1040a2df9aa90c9James Dong        if (mTrackMaxAmplitude) {
309542db5d438988360d491a5add1040a2df9aa90c9James Dong            trackMaxAmplitude((int16_t *) buffer->data(), n >> 1);
310542db5d438988360d491a5add1040a2df9aa90c9James Dong        }
311d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong
31246292fb347d72a314d985e34e5e3743d846cb9b6James Dong        buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs);
31346292fb347d72a314d985e34e5e3743d846cb9b6James Dong        CHECK(timestampUs > mPrevSampleTimeUs);
31446292fb347d72a314d985e34e5e3743d846cb9b6James Dong        mPrevSampleTimeUs = timestampUs;
315542db5d438988360d491a5add1040a2df9aa90c9James Dong        LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld",
316542db5d438988360d491a5add1040a2df9aa90c9James Dong                mStartTimeUs, sampleRate, timestampUs);
317f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
318542db5d438988360d491a5add1040a2df9aa90c9James Dong        buffer->set_range(0, n);
319e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
320542db5d438988360d491a5add1040a2df9aa90c9James Dong        *out = buffer;
321542db5d438988360d491a5add1040a2df9aa90c9James Dong        return OK;
322542db5d438988360d491a5add1040a2df9aa90c9James Dong    }
323e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
324e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return OK;
325e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
326e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
327d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dongvoid AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) {
328d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    for (int i = nSamples; i > 0; --i) {
329d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        int16_t value = *data++;
330d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        if (value < 0) {
331d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong            value = -value;
332d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        }
333d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        if (mMaxAmplitude < value) {
334d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong            mMaxAmplitude = value;
335d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        }
336d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    }
337d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong}
338d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong
339d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dongint16_t AudioSource::getMaxAmplitude() {
340d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    // First call activates the tracking.
341d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    if (!mTrackMaxAmplitude) {
342d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        mTrackMaxAmplitude = true;
343d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    }
344d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    int16_t value = mMaxAmplitude;
345d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    mMaxAmplitude = 0;
346d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    LOGV("max amplitude since last call: %d", value);
347d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    return value;
348d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong}
349d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong
350e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}  // namespace android
351