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
75a87544b35fda354cd24e1b7e803570e8926da918James Dong    if (mInitCheck != OK) {
76a87544b35fda354cd24e1b7e803570e8926da918James Dong        return NO_INIT;
77a87544b35fda354cd24e1b7e803570e8926da918James Dong    }
78a87544b35fda354cd24e1b7e803570e8926da918James Dong
79dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong    char value[PROPERTY_VALUE_MAX];
80dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong    if (property_get("media.stagefright.record-stats", value, NULL)
81dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
82dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong        mCollectStats = true;
83dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong    }
8436e573bf7db5888f92c52eda26e0771aaa2406e4James Dong
8557e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    mTrackMaxAmplitude = false;
8657e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    mMaxAmplitude = 0;
874c23815c3986e50f0cfad3976d748e600f1befa2James Dong    mInitialReadTimeUs = 0;
8836e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    mStartTimeUs = 0;
8936e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    int64_t startTimeUs;
9036e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    if (params && params->findInt64(kKeyTime, &startTimeUs)) {
9136e573bf7db5888f92c52eda26e0771aaa2406e4James Dong        mStartTimeUs = startTimeUs;
9236e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    }
9307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    status_t err = mRecord->start();
9407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
9507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    if (err == OK) {
9607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        mGroup = new MediaBufferGroup;
9707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        mGroup->add_buffer(new MediaBuffer(kMaxBufferSize));
9807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
9907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        mStarted = true;
10007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    }
10107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
10207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    return err;
10307bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
10407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
10507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huberstatus_t AudioSource::stop() {
10607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    if (!mStarted) {
10707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        return UNKNOWN_ERROR;
10807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    }
10907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
110a87544b35fda354cd24e1b7e803570e8926da918James Dong    if (mInitCheck != OK) {
111a87544b35fda354cd24e1b7e803570e8926da918James Dong        return NO_INIT;
112a87544b35fda354cd24e1b7e803570e8926da918James Dong    }
113a87544b35fda354cd24e1b7e803570e8926da918James Dong
11407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    mRecord->stop();
11507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
11607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    delete mGroup;
11707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    mGroup = NULL;
11807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
11907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    mStarted = false;
12007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
121dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong    if (mCollectStats) {
122afe5305855e2f3d830337f768028615a44d4aa16James Dong        LOGI("Total lost audio frames: %lld",
123afe5305855e2f3d830337f768028615a44d4aa16James Dong            mTotalLostFrames + (mPrevLostBytes >> 1));
124dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong    }
125dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong
12607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    return OK;
12707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
12807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
12907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Hubersp<MetaData> AudioSource::getFormat() {
130a87544b35fda354cd24e1b7e803570e8926da918James Dong    if (mInitCheck != OK) {
131a87544b35fda354cd24e1b7e803570e8926da918James Dong        return 0;
132a87544b35fda354cd24e1b7e803570e8926da918James Dong    }
133a87544b35fda354cd24e1b7e803570e8926da918James Dong
13407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    sp<MetaData> meta = new MetaData;
13507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
13607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    meta->setInt32(kKeySampleRate, mRecord->getSampleRate());
13707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    meta->setInt32(kKeyChannelCount, mRecord->channelCount());
13807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    meta->setInt32(kKeyMaxInputSize, kMaxBufferSize);
13907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
14007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    return meta;
14107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
14207bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
143c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong/*
144c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong * Returns -1 if frame skipping request is too long.
145c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong * Returns  0 if there is no need to skip frames.
146c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong * Returns  1 if we need to skip frames.
147c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong */
148c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dongstatic int skipFrame(int64_t timestampUs,
149c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        const MediaSource::ReadOptions *options) {
150c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
151c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    int64_t skipFrameUs;
152c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    if (!options || !options->getSkipFrame(&skipFrameUs)) {
153c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        return 0;
154c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    }
155c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
156c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    if (skipFrameUs <= timestampUs) {
157c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        return 0;
158c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    }
159c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
160c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    // Safe guard against the abuse of the kSkipFrame_Option.
161c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    if (skipFrameUs - timestampUs >= 1E6) {
162c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        LOGE("Frame skipping requested is way too long: %lld us",
163c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            skipFrameUs - timestampUs);
164c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
165c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        return -1;
166c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    }
167c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
168c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    LOGV("skipFrame: %lld us > timestamp: %lld us",
169c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        skipFrameUs, timestampUs);
170c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
171c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    return 1;
172c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
173c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong}
174c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
175d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dongvoid AudioSource::rampVolume(
176d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        int32_t startFrame, int32_t rampDurationFrames,
177d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        uint8_t *data,   size_t bytes) {
178d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong
179d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong    const int32_t kShift = 14;
180d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong    int32_t fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
181d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong    const int32_t nChannels = mRecord->channelCount();
182d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong    int32_t stopFrame = startFrame + bytes / sizeof(int16_t);
183d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong    int16_t *frame = (int16_t *) data;
184d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong    if (stopFrame > rampDurationFrames) {
185d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        stopFrame = rampDurationFrames;
186d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong    }
187d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong
188d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong    while (startFrame < stopFrame) {
189d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        if (nChannels == 1) {  // mono
190d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            frame[0] = (frame[0] * fixedMultiplier) >> kShift;
191d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            ++frame;
192d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            ++startFrame;
193d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        } else {               // stereo
194d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            frame[0] = (frame[0] * fixedMultiplier) >> kShift;
195d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            frame[1] = (frame[1] * fixedMultiplier) >> kShift;
196d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            frame += 2;
197d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            startFrame += 2;
198d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        }
199d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong
200d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        // Update the multiplier every 4 frames
201d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        if ((startFrame & 3) == 0) {
202d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
203d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        }
204d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong    }
205d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong}
206d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong
20707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huberstatus_t AudioSource::read(
20807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
209a87544b35fda354cd24e1b7e803570e8926da918James Dong
210a87544b35fda354cd24e1b7e803570e8926da918James Dong    if (mInitCheck != OK) {
211a87544b35fda354cd24e1b7e803570e8926da918James Dong        return NO_INIT;
212a87544b35fda354cd24e1b7e803570e8926da918James Dong    }
213a87544b35fda354cd24e1b7e803570e8926da918James Dong
2144c23815c3986e50f0cfad3976d748e600f1befa2James Dong    int64_t readTimeUs = systemTime() / 1000;
21507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    *out = NULL;
21607bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
21707bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    MediaBuffer *buffer;
21807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    CHECK_EQ(mGroup->acquire_buffer(&buffer), OK);
21907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
220c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong    int err = 0;
22153d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong    while (mStarted) {
222c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
22353d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        uint32_t numFramesRecorded;
22453d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        mRecord->getPosition(&numFramesRecorded);
22553d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong
22653d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong
227c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        if (numFramesRecorded == 0 && mPrevSampleTimeUs == 0) {
2284c23815c3986e50f0cfad3976d748e600f1befa2James Dong            mInitialReadTimeUs = readTimeUs;
22953d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong            // Initial delay
23053d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong            if (mStartTimeUs > 0) {
2314c23815c3986e50f0cfad3976d748e600f1befa2James Dong                mStartTimeUs = readTimeUs - mStartTimeUs;
23253d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong            } else {
233c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong                // Assume latency is constant.
234c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong                mStartTimeUs += mRecord->latency() * 1000;
23553d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong            }
236c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            mPrevSampleTimeUs = mStartTimeUs;
23753d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        }
23853d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong
239c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        uint32_t sampleRate = mRecord->getSampleRate();
240c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
241c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        // Insert null frames when lost frames are detected.
242c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        int64_t timestampUs = mPrevSampleTimeUs;
243c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        uint32_t numLostBytes = mRecord->getInputFramesLost() << 1;
244afe5305855e2f3d830337f768028615a44d4aa16James Dong        numLostBytes += mPrevLostBytes;
245c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong#if 0
246c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        // Simulate lost frames
247afe5305855e2f3d830337f768028615a44d4aa16James Dong        numLostBytes = ((rand() * 1.0 / RAND_MAX)) * 2 * kMaxBufferSize;
248afe5305855e2f3d830337f768028615a44d4aa16James Dong        numLostBytes &= 0xFFFFFFFE; // Alignment requirement
249c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
250c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        // Reduce the chance to lose
251c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        if (rand() * 1.0 / RAND_MAX >= 0.05) {
252c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            numLostBytes = 0;
253c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        }
254c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong#endif
255c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        if (numLostBytes > 0) {
256afe5305855e2f3d830337f768028615a44d4aa16James Dong            if (numLostBytes > kMaxBufferSize) {
257afe5305855e2f3d830337f768028615a44d4aa16James Dong                mPrevLostBytes = numLostBytes - kMaxBufferSize;
258afe5305855e2f3d830337f768028615a44d4aa16James Dong                numLostBytes = kMaxBufferSize;
2597589ebfbfd1e01217b21861fd4b7bfdcc26c2e84James Dong            } else {
2607589ebfbfd1e01217b21861fd4b7bfdcc26c2e84James Dong                mPrevLostBytes = 0;
261afe5305855e2f3d830337f768028615a44d4aa16James Dong            }
262afe5305855e2f3d830337f768028615a44d4aa16James Dong
263afe5305855e2f3d830337f768028615a44d4aa16James Dong            CHECK_EQ(numLostBytes & 1, 0);
264afe5305855e2f3d830337f768028615a44d4aa16James Dong            timestampUs += ((1000000LL * (numLostBytes >> 1)) +
265afe5305855e2f3d830337f768028615a44d4aa16James Dong                    (sampleRate >> 1)) / sampleRate;
266c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong
267c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            CHECK(timestampUs > mPrevSampleTimeUs);
268c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            if (mCollectStats) {
269afe5305855e2f3d830337f768028615a44d4aa16James Dong                mTotalLostFrames += (numLostBytes >> 1);
270c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            }
271c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            if ((err = skipFrame(timestampUs, options)) == -1) {
272c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong                buffer->release();
273c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong                return UNKNOWN_ERROR;
274c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            } else if (err != 0) {
275c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong                continue;
27653d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong            }
277c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            memset(buffer->data(), 0, numLostBytes);
278c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            buffer->set_range(0, numLostBytes);
2794c23815c3986e50f0cfad3976d748e600f1befa2James Dong            if (numFramesRecorded == 0) {
2807589ebfbfd1e01217b21861fd4b7bfdcc26c2e84James Dong                buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs);
2814c23815c3986e50f0cfad3976d748e600f1befa2James Dong            }
2827589ebfbfd1e01217b21861fd4b7bfdcc26c2e84James Dong            buffer->meta_data()->setInt64(kKeyTime, mStartTimeUs + mPrevSampleTimeUs);
2834c23815c3986e50f0cfad3976d748e600f1befa2James Dong            buffer->meta_data()->setInt64(kKeyDriftTime, readTimeUs - mInitialReadTimeUs);
284c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            mPrevSampleTimeUs = timestampUs;
285c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            *out = buffer;
286c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            return OK;
28736e573bf7db5888f92c52eda26e0771aaa2406e4James Dong        }
28807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
289c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        ssize_t n = mRecord->read(buffer->data(), buffer->size());
2908a1a0fd1dc8c612f3ba7db955db11a18b5209ed4James Dong        if (n <= 0) {
2918a1a0fd1dc8c612f3ba7db955db11a18b5209ed4James Dong            LOGE("Read from AudioRecord returns: %ld", n);
29253d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong            buffer->release();
2938a1a0fd1dc8c612f3ba7db955db11a18b5209ed4James Dong            return UNKNOWN_ERROR;
294dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong        }
29507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
296c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        int64_t recordDurationUs = (1000000LL * n >> 1) / sampleRate;
297c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        timestampUs += recordDurationUs;
298c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        if ((err = skipFrame(timestampUs, options)) == -1) {
299c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            buffer->release();
300c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong            return UNKNOWN_ERROR;
301c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        } else if (err != 0) {
30253d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong            continue;
30353d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        }
30407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
305d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        if (mPrevSampleTimeUs - mStartTimeUs < kAutoRampStartUs) {
306d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            // Mute the initial video recording signal
307d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            memset((uint8_t *) buffer->data(), 0, n);
308d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        } else if (mPrevSampleTimeUs - mStartTimeUs < kAutoRampStartUs + kAutoRampDurationUs) {
309d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            int32_t autoRampDurationFrames =
310d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong                    (kAutoRampDurationUs * sampleRate + 500000LL) / 1000000LL;
311d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong
312d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            int32_t autoRampStartFrames =
313d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong                    (kAutoRampStartUs * sampleRate + 500000LL) / 1000000LL;
314d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong
315d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            int32_t nFrames = numFramesRecorded - autoRampStartFrames;
316d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong            rampVolume(nFrames, autoRampDurationFrames, (uint8_t *) buffer->data(), n);
317d7f1c3d69274fef8772a663ce1c792fd0466fcc5James Dong        }
31853d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        if (mTrackMaxAmplitude) {
31953d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong            trackMaxAmplitude((int16_t *) buffer->data(), n >> 1);
32053d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        }
32157e7f83c0336db3f03666f077bce4c2692a88cf6James Dong
3224c23815c3986e50f0cfad3976d748e600f1befa2James Dong        if (numFramesRecorded == 0) {
323d015ccf62b4e87756e2f7785af92338d35a21c15James Dong            buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs);
3244c23815c3986e50f0cfad3976d748e600f1befa2James Dong        }
325d015ccf62b4e87756e2f7785af92338d35a21c15James Dong
326d015ccf62b4e87756e2f7785af92338d35a21c15James Dong        buffer->meta_data()->setInt64(kKeyTime, mStartTimeUs + mPrevSampleTimeUs);
3274c23815c3986e50f0cfad3976d748e600f1befa2James Dong        buffer->meta_data()->setInt64(kKeyDriftTime, readTimeUs - mInitialReadTimeUs);
328c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        CHECK(timestampUs > mPrevSampleTimeUs);
329c3ae937a95cbaf4afbe8aa006dc3db4c27f0ad44James Dong        mPrevSampleTimeUs = timestampUs;
33053d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld",
33153d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong                mStartTimeUs, sampleRate, timestampUs);
33236e573bf7db5888f92c52eda26e0771aaa2406e4James Dong
33353d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        buffer->set_range(0, n);
33407bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
33553d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        *out = buffer;
33653d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong        return OK;
33753d4e0d58e2d5c18f6e026c705af833b9bdd7abaJames Dong    }
33807bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
33907bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber    return OK;
34007bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}
34107bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber
34257e7f83c0336db3f03666f077bce4c2692a88cf6James Dongvoid AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) {
34357e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    for (int i = nSamples; i > 0; --i) {
34457e7f83c0336db3f03666f077bce4c2692a88cf6James Dong        int16_t value = *data++;
34557e7f83c0336db3f03666f077bce4c2692a88cf6James Dong        if (value < 0) {
34657e7f83c0336db3f03666f077bce4c2692a88cf6James Dong            value = -value;
34757e7f83c0336db3f03666f077bce4c2692a88cf6James Dong        }
34857e7f83c0336db3f03666f077bce4c2692a88cf6James Dong        if (mMaxAmplitude < value) {
34957e7f83c0336db3f03666f077bce4c2692a88cf6James Dong            mMaxAmplitude = value;
35057e7f83c0336db3f03666f077bce4c2692a88cf6James Dong        }
35157e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    }
35257e7f83c0336db3f03666f077bce4c2692a88cf6James Dong}
35357e7f83c0336db3f03666f077bce4c2692a88cf6James Dong
35457e7f83c0336db3f03666f077bce4c2692a88cf6James Dongint16_t AudioSource::getMaxAmplitude() {
35557e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    // First call activates the tracking.
35657e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    if (!mTrackMaxAmplitude) {
35757e7f83c0336db3f03666f077bce4c2692a88cf6James Dong        mTrackMaxAmplitude = true;
35857e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    }
35957e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    int16_t value = mMaxAmplitude;
36057e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    mMaxAmplitude = 0;
36157e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    LOGV("max amplitude since last call: %d", value);
36257e7f83c0336db3f03666f077bce4c2692a88cf6James Dong    return value;
36357e7f83c0336db3f03666f077bce4c2692a88cf6James Dong}
36457e7f83c0336db3f03666f077bce4c2692a88cf6James Dong
36507bf09da4a365282fc35f800b62a83e0fa5533e2Andreas Huber}  // namespace android
366