AudioSource.cpp revision d7f1c3d69274fef8772a663ce1c792fd0466fcc5
107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber/*
207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber * Copyright (C) 2010 The Android Open Source Project
307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber *
407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber * you may not use this file except in compliance with the License.
607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber * You may obtain a copy of the License at
707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber *
807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber *
1007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber * Unless required by applicable law or agreed to in writing, software
1107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber * See the License for the specific language governing permissions and
1407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber * limitations under the License.
1507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber */
1607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
17abed93a51b6b476ecb23a2c22faa43a219eb60a7James Dong//#define LOG_NDEBUG 0
18abed93a51b6b476ecb23a2c22faa43a219eb60a7James Dong#define LOG_TAG "AudioSource"
19abed93a51b6b476ecb23a2c22faa43a219eb60a7James Dong#include <utils/Log.h>
20abed93a51b6b476ecb23a2c22faa43a219eb60a7James Dong
2107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber#include <media/stagefright/AudioSource.h>
2207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
2307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber#include <media/AudioRecord.h>
2407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
2507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber#include <media/stagefright/MediaDebug.h>
2607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber#include <media/stagefright/MediaDefs.h>
2707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber#include <media/stagefright/MetaData.h>
28dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong#include <cutils/properties.h>
29c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong#include <stdlib.h>
3007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
3107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Hubernamespace android {
3207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
3307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas HuberAudioSource::AudioSource(
3407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        int inputSource, uint32_t sampleRate, uint32_t channels)
35d77d2a980c6fbdc00b7d62a34d9b799dcf8c9514James Dong    : mStarted(false),
36dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong      mCollectStats(false),
37c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong      mPrevSampleTimeUs(0),
38afe5305855e2f3d830337f768028615a44d4aa16James Dong      mTotalLostFrames(0),
39afe5305855e2f3d830337f768028615a44d4aa16James Dong      mPrevLostBytes(0),
4007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber      mGroup(NULL) {
41d77d2a980c6fbdc00b7d62a34d9b799dcf8c9514James Dong
42d77d2a980c6fbdc00b7d62a34d9b799dcf8c9514James Dong    LOGV("sampleRate: %d, channels: %d", sampleRate, channels);
43d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong    CHECK(channels == 1 || channels == 2);
44d77d2a980c6fbdc00b7d62a34d9b799dcf8c9514James Dong    uint32_t flags = AudioRecord::RECORD_AGC_ENABLE |
45d77d2a980c6fbdc00b7d62a34d9b799dcf8c9514James Dong                     AudioRecord::RECORD_NS_ENABLE  |
46d77d2a980c6fbdc00b7d62a34d9b799dcf8c9514James Dong                     AudioRecord::RECORD_IIR_ENABLE;
47d77d2a980c6fbdc00b7d62a34d9b799dcf8c9514James Dong
48d77d2a980c6fbdc00b7d62a34d9b799dcf8c9514James Dong    mRecord = new AudioRecord(
49d77d2a980c6fbdc00b7d62a34d9b799dcf8c9514James Dong                inputSource, sampleRate, AudioSystem::PCM_16_BIT,
50d77d2a980c6fbdc00b7d62a34d9b799dcf8c9514James Dong                channels > 1? AudioSystem::CHANNEL_IN_STEREO: AudioSystem::CHANNEL_IN_MONO,
51d77d2a980c6fbdc00b7d62a34d9b799dcf8c9514James Dong                4 * kMaxBufferSize / sizeof(int16_t), /* Enable ping-pong buffers */
52d77d2a980c6fbdc00b7d62a34d9b799dcf8c9514James Dong                flags);
53d77d2a980c6fbdc00b7d62a34d9b799dcf8c9514James Dong
54d77d2a980c6fbdc00b7d62a34d9b799dcf8c9514James Dong    mInitCheck = mRecord->initCheck();
5507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
5607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
5707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas HuberAudioSource::~AudioSource() {
5807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    if (mStarted) {
5907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        stop();
6007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    }
6107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
6207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    delete mRecord;
6307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    mRecord = NULL;
6407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
6507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
6607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huberstatus_t AudioSource::initCheck() const {
6707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    return mInitCheck;
6807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
6907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
7007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huberstatus_t AudioSource::start(MetaData *params) {
7107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    if (mStarted) {
7207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        return UNKNOWN_ERROR;
7307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    }
7407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
75dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong    char value[PROPERTY_VALUE_MAX];
76dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong    if (property_get("media.stagefright.record-stats", value, NULL)
77dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
78dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong        mCollectStats = true;
79dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong    }
8036e573bf7db5888f92c52eda26e0771aaa2406e4James Dong
8157e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    mTrackMaxAmplitude = false;
8257e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    mMaxAmplitude = 0;
8336e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    mStartTimeUs = 0;
8436e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    int64_t startTimeUs;
8536e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    if (params && params->findInt64(kKeyTime, &startTimeUs)) {
8636e573bf7db5888f92c52eda26e0771aaa2406e4James Dong        mStartTimeUs = startTimeUs;
8736e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    }
8807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    status_t err = mRecord->start();
8907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
9007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    if (err == OK) {
9107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        mGroup = new MediaBufferGroup;
9207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        mGroup->add_buffer(new MediaBuffer(kMaxBufferSize));
9307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
9407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        mStarted = true;
9507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    }
9607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
9707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    return err;
9807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
9907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
10007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huberstatus_t AudioSource::stop() {
10107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    if (!mStarted) {
10207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        return UNKNOWN_ERROR;
10307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    }
10407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
10507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    mRecord->stop();
10607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
10707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    delete mGroup;
10807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    mGroup = NULL;
10907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
11007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    mStarted = false;
11107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
112dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong    if (mCollectStats) {
113afe5305855e2f3d830337f768028615a44d4aa16James Dong        LOGI("Total lost audio frames: %lld",
114afe5305855e2f3d830337f768028615a44d4aa16James Dong            mTotalLostFrames + (mPrevLostBytes >> 1));
115dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong    }
116dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong
11707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    return OK;
11807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
11907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
12007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Hubersp<MetaData> AudioSource::getFormat() {
12107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    sp<MetaData> meta = new MetaData;
12207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
12307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    meta->setInt32(kKeySampleRate, mRecord->getSampleRate());
12407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    meta->setInt32(kKeyChannelCount, mRecord->channelCount());
12507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    meta->setInt32(kKeyMaxInputSize, kMaxBufferSize);
12607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
12707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    return meta;
12807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
12907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
130c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong/*
131c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong * Returns -1 if frame skipping request is too long.
132c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong * Returns  0 if there is no need to skip frames.
133c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong * Returns  1 if we need to skip frames.
134c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong */
135c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dongstatic int skipFrame(int64_t timestampUs,
136c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        const MediaSource::ReadOptions *options) {
137c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
138c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    int64_t skipFrameUs;
139c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    if (!options || !options->getSkipFrame(&skipFrameUs)) {
140c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        return 0;
141c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    }
142c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
143c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    if (skipFrameUs <= timestampUs) {
144c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        return 0;
145c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    }
146c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
147c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    // Safe guard against the abuse of the kSkipFrame_Option.
148c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    if (skipFrameUs - timestampUs >= 1E6) {
149c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        LOGE("Frame skipping requested is way too long: %lld us",
150c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            skipFrameUs - timestampUs);
151c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
152c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        return -1;
153c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    }
154c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
155c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    LOGV("skipFrame: %lld us > timestamp: %lld us",
156c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        skipFrameUs, timestampUs);
157c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
158c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    return 1;
159c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
160c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong}
161c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
162d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dongvoid AudioSource::rampVolume(
163d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        int32_t startFrame, int32_t rampDurationFrames,
164d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        uint8_t *data,   size_t bytes) {
165d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong
166d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong    const int32_t kShift = 14;
167d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong    int32_t fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
168d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong    const int32_t nChannels = mRecord->channelCount();
169d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong    int32_t stopFrame = startFrame + bytes / sizeof(int16_t);
170d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong    int16_t *frame = (int16_t *) data;
171d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong    if (stopFrame > rampDurationFrames) {
172d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        stopFrame = rampDurationFrames;
173d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong    }
174d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong
175d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong    while (startFrame < stopFrame) {
176d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        if (nChannels == 1) {  // mono
177d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            frame[0] = (frame[0] * fixedMultiplier) >> kShift;
178d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            ++frame;
179d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            ++startFrame;
180d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        } else {               // stereo
181d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            frame[0] = (frame[0] * fixedMultiplier) >> kShift;
182d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            frame[1] = (frame[1] * fixedMultiplier) >> kShift;
183d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            frame += 2;
184d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            startFrame += 2;
185d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        }
186d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong
187d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        // Update the multiplier every 4 frames
188d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        if ((startFrame & 3) == 0) {
189d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
190d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        }
191d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong    }
192d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong}
193d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong
19407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huberstatus_t AudioSource::read(
19507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
19607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    *out = NULL;
19707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
19807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    MediaBuffer *buffer;
19907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    CHECK_EQ(mGroup->acquire_buffer(&buffer), OK);
20007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
201c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    int err = 0;
20253d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong    while (mStarted) {
203c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
20453d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        uint32_t numFramesRecorded;
20553d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        mRecord->getPosition(&numFramesRecorded);
20653d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong
20753d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong
208c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        if (numFramesRecorded == 0 && mPrevSampleTimeUs == 0) {
20953d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong            // Initial delay
21053d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong            if (mStartTimeUs > 0) {
211c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong                mStartTimeUs = systemTime() / 1000 - mStartTimeUs;
21253d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong            } else {
213c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong                // Assume latency is constant.
214c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong                mStartTimeUs += mRecord->latency() * 1000;
21553d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong            }
216c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            mPrevSampleTimeUs = mStartTimeUs;
21753d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        }
21853d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong
219c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        uint32_t sampleRate = mRecord->getSampleRate();
220c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
221c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        // Insert null frames when lost frames are detected.
222c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        int64_t timestampUs = mPrevSampleTimeUs;
223c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        uint32_t numLostBytes = mRecord->getInputFramesLost() << 1;
224afe5305855e2f3d830337f768028615a44d4aa16James Dong        numLostBytes += mPrevLostBytes;
225c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong#if 0
226c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        // Simulate lost frames
227afe5305855e2f3d830337f768028615a44d4aa16James Dong        numLostBytes = ((rand() * 1.0 / RAND_MAX)) * 2 * kMaxBufferSize;
228afe5305855e2f3d830337f768028615a44d4aa16James Dong        numLostBytes &= 0xFFFFFFFE; // Alignment requirement
229c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
230c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        // Reduce the chance to lose
231c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        if (rand() * 1.0 / RAND_MAX >= 0.05) {
232c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            numLostBytes = 0;
233c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        }
234c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong#endif
235c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        if (numLostBytes > 0) {
236afe5305855e2f3d830337f768028615a44d4aa16James Dong            if (numLostBytes > kMaxBufferSize) {
237afe5305855e2f3d830337f768028615a44d4aa16James Dong                mPrevLostBytes = numLostBytes - kMaxBufferSize;
238afe5305855e2f3d830337f768028615a44d4aa16James Dong                numLostBytes = kMaxBufferSize;
239afe5305855e2f3d830337f768028615a44d4aa16James Dong            }
240afe5305855e2f3d830337f768028615a44d4aa16James Dong
241afe5305855e2f3d830337f768028615a44d4aa16James Dong            CHECK_EQ(numLostBytes & 1, 0);
242afe5305855e2f3d830337f768028615a44d4aa16James Dong            timestampUs += ((1000000LL * (numLostBytes >> 1)) +
243afe5305855e2f3d830337f768028615a44d4aa16James Dong                    (sampleRate >> 1)) / sampleRate;
244c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
245c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            CHECK(timestampUs > mPrevSampleTimeUs);
246c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            if (mCollectStats) {
247afe5305855e2f3d830337f768028615a44d4aa16James Dong                mTotalLostFrames += (numLostBytes >> 1);
248c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            }
249c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            if ((err = skipFrame(timestampUs, options)) == -1) {
250c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong                buffer->release();
251c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong                return UNKNOWN_ERROR;
252c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            } else if (err != 0) {
253c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong                continue;
25453d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong            }
255c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            memset(buffer->data(), 0, numLostBytes);
256c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            buffer->set_range(0, numLostBytes);
257c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs);
258c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            mPrevSampleTimeUs = timestampUs;
259c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            *out = buffer;
260c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            return OK;
26136e573bf7db5888f92c52eda26e0771aaa2406e4James Dong        }
26207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
263c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        ssize_t n = mRecord->read(buffer->data(), buffer->size());
26453d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        if (n < 0) {
26553d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong            buffer->release();
26653d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong            return (status_t)n;
267dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong        }
26807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
269c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        int64_t recordDurationUs = (1000000LL * n >> 1) / sampleRate;
270c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        timestampUs += recordDurationUs;
271c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        if ((err = skipFrame(timestampUs, options)) == -1) {
272c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            buffer->release();
273c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            return UNKNOWN_ERROR;
274c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        } else if (err != 0) {
27553d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong            continue;
27653d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        }
27707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
278d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        if (mPrevSampleTimeUs - mStartTimeUs < kAutoRampStartUs) {
279d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            // Mute the initial video recording signal
280d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            memset((uint8_t *) buffer->data(), 0, n);
281d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        } else if (mPrevSampleTimeUs - mStartTimeUs < kAutoRampStartUs + kAutoRampDurationUs) {
282d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            int32_t autoRampDurationFrames =
283d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong                    (kAutoRampDurationUs * sampleRate + 500000LL) / 1000000LL;
284d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong
285d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            int32_t autoRampStartFrames =
286d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong                    (kAutoRampStartUs * sampleRate + 500000LL) / 1000000LL;
287d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong
288d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            int32_t nFrames = numFramesRecorded - autoRampStartFrames;
289d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            rampVolume(nFrames, autoRampDurationFrames, (uint8_t *) buffer->data(), n);
290d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        }
29153d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        if (mTrackMaxAmplitude) {
29253d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong            trackMaxAmplitude((int16_t *) buffer->data(), n >> 1);
29353d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        }
29457e7f83c0336db3f03666f077bce4c2692a88cf6James Dong
295c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs);
296c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        CHECK(timestampUs > mPrevSampleTimeUs);
297afe5305855e2f3d830337f768028615a44d4aa16James Dong        if (mTotalLostFrames == 0) {
298c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            CHECK_EQ(mPrevSampleTimeUs,
299c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong                mStartTimeUs + (1000000LL * numFramesRecorded) / sampleRate);
300c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        }
301c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        mPrevSampleTimeUs = timestampUs;
30253d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld",
30353d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong                mStartTimeUs, sampleRate, timestampUs);
30436e573bf7db5888f92c52eda26e0771aaa2406e4James Dong
30553d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        buffer->set_range(0, n);
30607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
30753d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        *out = buffer;
30853d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        return OK;
30953d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong    }
31007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
31107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    return OK;
31207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
31307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
31457e7f83c0336db3f03666f077bce4c2692a88cf6James Dongvoid AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) {
31557e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    for (int i = nSamples; i > 0; --i) {
31657e7f83c0336db3f03666f077bce4c2692a88cf6James Dong        int16_t value = *data++;
31757e7f83c0336db3f03666f077bce4c2692a88cf6James Dong        if (value < 0) {
31857e7f83c0336db3f03666f077bce4c2692a88cf6James Dong            value = -value;
31957e7f83c0336db3f03666f077bce4c2692a88cf6James Dong        }
32057e7f83c0336db3f03666f077bce4c2692a88cf6James Dong        if (mMaxAmplitude < value) {
32157e7f83c0336db3f03666f077bce4c2692a88cf6James Dong            mMaxAmplitude = value;
32257e7f83c0336db3f03666f077bce4c2692a88cf6James Dong        }
32357e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    }
32457e7f83c0336db3f03666f077bce4c2692a88cf6James Dong}
32557e7f83c0336db3f03666f077bce4c2692a88cf6James Dong
32657e7f83c0336db3f03666f077bce4c2692a88cf6James Dongint16_t AudioSource::getMaxAmplitude() {
32757e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    // First call activates the tracking.
32857e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    if (!mTrackMaxAmplitude) {
32957e7f83c0336db3f03666f077bce4c2692a88cf6James Dong        mTrackMaxAmplitude = true;
33057e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    }
33157e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    int16_t value = mMaxAmplitude;
33257e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    mMaxAmplitude = 0;
33357e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    LOGV("max amplitude since last call: %d", value);
33457e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    return value;
33557e7f83c0336db3f03666f077bce4c2692a88cf6James Dong}
33657e7f83c0336db3f03666f077bce4c2692a88cf6James Dong
33707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}  // namespace android
338