AudioSource.cpp revision 3856b090cd04ba5dd4a59a12430ed724d5995909
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/AudioRecord.h>
226b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong#include <media/stagefright/AudioSource.h>
236b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong#include <media/stagefright/MediaBuffer.h>
24e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MediaDefs.h>
25e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MetaData.h>
266b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong#include <media/stagefright/foundation/ADebug.h>
27365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <cutils/properties.h>
2846292fb347d72a314d985e34e5e3743d846cb9b6James Dong#include <stdlib.h>
29e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
30e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Hubernamespace android {
31e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
326b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dongstatic void AudioRecordCallbackFunction(int event, void *user, void *info) {
336b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    AudioSource *source = (AudioSource *) user;
346b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    switch (event) {
356b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        case AudioRecord::EVENT_MORE_DATA: {
366b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong            source->dataCallbackTimestamp(*((AudioRecord::Buffer *) info), systemTime() / 1000);
376b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong            break;
386b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        }
396b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        case AudioRecord::EVENT_OVERRUN: {
406b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong            LOGW("AudioRecord reported overrun!");
416b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong            break;
426b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        }
436b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        default:
446b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong            // does nothing
456b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong            break;
466b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
476b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong}
486b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong
49e7c9cb48fec02697227bd847cd2e69432659adfdAndreas HuberAudioSource::AudioSource(
50e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        int inputSource, uint32_t sampleRate, uint32_t channels)
51be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong    : mStarted(false),
526b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong      mSampleRate(sampleRate),
5346292fb347d72a314d985e34e5e3743d846cb9b6James Dong      mPrevSampleTimeUs(0),
546b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong      mNumFramesReceived(0),
556b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong      mNumClientOwnedBuffers(0) {
56be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong
573856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("sampleRate: %d, channels: %d", sampleRate, channels);
58f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    CHECK(channels == 1 || channels == 2);
59be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong    uint32_t flags = AudioRecord::RECORD_AGC_ENABLE |
60be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                     AudioRecord::RECORD_NS_ENABLE  |
61be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                     AudioRecord::RECORD_IIR_ENABLE;
62be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong    mRecord = new AudioRecord(
63fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin                inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT,
64fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin                channels > 1? AUDIO_CHANNEL_IN_STEREO: AUDIO_CHANNEL_IN_MONO,
65be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                4 * kMaxBufferSize / sizeof(int16_t), /* Enable ping-pong buffers */
666b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong                flags,
676b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong                AudioRecordCallbackFunction,
686b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong                this);
69be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong
70be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong    mInitCheck = mRecord->initCheck();
71e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
72e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
73e7c9cb48fec02697227bd847cd2e69432659adfdAndreas HuberAudioSource::~AudioSource() {
74e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (mStarted) {
75e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        stop();
76e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
77e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
78e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    delete mRecord;
79e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    mRecord = NULL;
80e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
81e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
82e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::initCheck() const {
83e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return mInitCheck;
84e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
85e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
86e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::start(MetaData *params) {
876b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    Mutex::Autolock autoLock(mLock);
88e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (mStarted) {
89e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        return UNKNOWN_ERROR;
90e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
91e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
926e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    if (mInitCheck != OK) {
936e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong        return NO_INIT;
946e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    }
956e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
96d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    mTrackMaxAmplitude = false;
97d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    mMaxAmplitude = 0;
98d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mInitialReadTimeUs = 0;
99f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mStartTimeUs = 0;
100f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t startTimeUs;
101f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (params && params->findInt64(kKeyTime, &startTimeUs)) {
102f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimeUs = startTimeUs;
103f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
104e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    status_t err = mRecord->start();
105e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (err == OK) {
106e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        mStarted = true;
107eaae38445a340c4857c1c5569475879a728e63b7James Dong    } else {
108eaae38445a340c4857c1c5569475879a728e63b7James Dong        delete mRecord;
109eaae38445a340c4857c1c5569475879a728e63b7James Dong        mRecord = NULL;
110e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
111e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
112eaae38445a340c4857c1c5569475879a728e63b7James Dong
113e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return err;
114e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
115e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
1166b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dongvoid AudioSource::releaseQueuedFrames_l() {
1173856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("releaseQueuedFrames_l");
1186b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    List<MediaBuffer *>::iterator it;
1196b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    while (!mBuffersReceived.empty()) {
1206b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        it = mBuffersReceived.begin();
1216b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        (*it)->release();
1226b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        mBuffersReceived.erase(it);
1236b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
1246b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong}
1256b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong
1266b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dongvoid AudioSource::waitOutstandingEncodingFrames_l() {
1273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("waitOutstandingEncodingFrames_l: %lld", mNumClientOwnedBuffers);
1286b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    while (mNumClientOwnedBuffers > 0) {
1296b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        mFrameEncodingCompletionCondition.wait(mLock);
1306b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
1316b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong}
1326b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong
133e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::stop() {
1346b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    Mutex::Autolock autoLock(mLock);
135e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (!mStarted) {
136e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        return UNKNOWN_ERROR;
137e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
138e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
1396e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    if (mInitCheck != OK) {
1406e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong        return NO_INIT;
1416e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    }
1426e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
143e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    mStarted = false;
1446b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    mRecord->stop();
1456b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    waitOutstandingEncodingFrames_l();
1466b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    releaseQueuedFrames_l();
147365a963142093a1cd8efdcea76b5f65096a5b115James Dong
148e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return OK;
149e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
150e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
151e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Hubersp<MetaData> AudioSource::getFormat() {
1526b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    Mutex::Autolock autoLock(mLock);
1536e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    if (mInitCheck != OK) {
1546e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong        return 0;
1556e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    }
1566e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
157e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    sp<MetaData> meta = new MetaData;
158e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
1596b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    meta->setInt32(kKeySampleRate, mSampleRate);
160e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setInt32(kKeyChannelCount, mRecord->channelCount());
161e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setInt32(kKeyMaxInputSize, kMaxBufferSize);
162e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
163e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return meta;
164e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
165e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
166f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dongvoid AudioSource::rampVolume(
167f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        int32_t startFrame, int32_t rampDurationFrames,
168f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        uint8_t *data,   size_t bytes) {
169f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
170f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    const int32_t kShift = 14;
171f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    int32_t fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
172f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    const int32_t nChannels = mRecord->channelCount();
173f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    int32_t stopFrame = startFrame + bytes / sizeof(int16_t);
174f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    int16_t *frame = (int16_t *) data;
175f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    if (stopFrame > rampDurationFrames) {
176f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        stopFrame = rampDurationFrames;
177f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    }
178f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
179f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    while (startFrame < stopFrame) {
180f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        if (nChannels == 1) {  // mono
181f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame[0] = (frame[0] * fixedMultiplier) >> kShift;
182f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            ++frame;
183f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            ++startFrame;
184f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        } else {               // stereo
185f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame[0] = (frame[0] * fixedMultiplier) >> kShift;
186f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame[1] = (frame[1] * fixedMultiplier) >> kShift;
187f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame += 2;
188f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            startFrame += 2;
189f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        }
190f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
191f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        // Update the multiplier every 4 frames
192f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        if ((startFrame & 3) == 0) {
193f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
194f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        }
195f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    }
196f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong}
197f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
198e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::read(
199e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        MediaBuffer **out, const ReadOptions *options) {
2006b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    Mutex::Autolock autoLock(mLock);
2016b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    *out = NULL;
2026e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
2036e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    if (mInitCheck != OK) {
2046e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong        return NO_INIT;
2056e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    }
2066e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
2076b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    while (mStarted && mBuffersReceived.empty()) {
2086b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        mFrameAvailableCondition.wait(mLock);
2096b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
2106b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    if (!mStarted) {
2116b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        return OK;
2126b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
2136b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    MediaBuffer *buffer = *mBuffersReceived.begin();
2146b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    mBuffersReceived.erase(mBuffersReceived.begin());
2156b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    ++mNumClientOwnedBuffers;
2166b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    buffer->setObserver(this);
2176b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    buffer->add_ref();
2186b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong
2196b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    // Mute/suppress the recording sound
2206b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    int64_t timeUs;
2216b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
2226b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    int64_t elapsedTimeUs = timeUs - mStartTimeUs;
2236b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    if (elapsedTimeUs < kAutoRampStartUs) {
2246b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        memset((uint8_t *) buffer->data(), 0, buffer->range_length());
2256b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    } else if (elapsedTimeUs < kAutoRampStartUs + kAutoRampDurationUs) {
2266b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        int32_t autoRampDurationFrames =
2276b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong                    (kAutoRampDurationUs * mSampleRate + 500000LL) / 1000000LL;
2286b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong
2296b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        int32_t autoRampStartFrames =
2306b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong                    (kAutoRampStartUs * mSampleRate + 500000LL) / 1000000LL;
2316b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong
2326b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        int32_t nFrames = mNumFramesReceived - autoRampStartFrames;
2336b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        rampVolume(nFrames, autoRampDurationFrames,
2346b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong                (uint8_t *) buffer->data(), buffer->range_length());
2356b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
236542db5d438988360d491a5add1040a2df9aa90c9James Dong
2376b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    // Track the max recording signal amplitude.
2386b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    if (mTrackMaxAmplitude) {
2396b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        trackMaxAmplitude(
2406b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong            (int16_t *) buffer->data(), buffer->range_length() >> 1);
2416b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
242542db5d438988360d491a5add1040a2df9aa90c9James Dong
2436b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    *out = buffer;
2446b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    return OK;
2456b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong}
246542db5d438988360d491a5add1040a2df9aa90c9James Dong
2476b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dongvoid AudioSource::signalBufferReturned(MediaBuffer *buffer) {
2483856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("signalBufferReturned: %p", buffer->data());
2496b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    Mutex::Autolock autoLock(mLock);
2506b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    --mNumClientOwnedBuffers;
2516b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    buffer->setObserver(0);
2526b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    buffer->release();
2536b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    mFrameEncodingCompletionCondition.signal();
2546b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    return;
2556b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong}
25646292fb347d72a314d985e34e5e3743d846cb9b6James Dong
2576b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dongstatus_t AudioSource::dataCallbackTimestamp(
2586b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        const AudioRecord::Buffer& audioBuffer, int64_t timeUs) {
2593856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("dataCallbackTimestamp: %lld us", timeUs);
2606b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    Mutex::Autolock autoLock(mLock);
2616b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    if (!mStarted) {
2626b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        LOGW("Spurious callback from AudioRecord. Drop the audio data.");
2636b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        return OK;
2646b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
26546292fb347d72a314d985e34e5e3743d846cb9b6James Dong
266a472613aec322e25891abf5c77bf3f7e3c244920James Dong    // Drop retrieved and previously lost audio data.
267a472613aec322e25891abf5c77bf3f7e3c244920James Dong    if (mNumFramesReceived == 0 && timeUs < mStartTimeUs) {
268a472613aec322e25891abf5c77bf3f7e3c244920James Dong        mRecord->getInputFramesLost();
2693856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Drop audio data at %lld/%lld us", timeUs, mStartTimeUs);
270a472613aec322e25891abf5c77bf3f7e3c244920James Dong        return OK;
271a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
272a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2736b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    if (mNumFramesReceived == 0 && mPrevSampleTimeUs == 0) {
2746b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        mInitialReadTimeUs = timeUs;
2756b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        // Initial delay
2766b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        if (mStartTimeUs > 0) {
2776b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong            mStartTimeUs = timeUs - mStartTimeUs;
2786b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        } else {
2796b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong            // Assume latency is constant.
2806b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong            mStartTimeUs += mRecord->latency() * 1000;
281f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        }
2826b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        mPrevSampleTimeUs = mStartTimeUs;
2836b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
284e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
2856b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    int64_t timestampUs = mPrevSampleTimeUs;
2866b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong
287a472613aec322e25891abf5c77bf3f7e3c244920James Dong    size_t numLostBytes = 0;
288a472613aec322e25891abf5c77bf3f7e3c244920James Dong    if (mNumFramesReceived > 0) {  // Ignore earlier frame lost
289a472613aec322e25891abf5c77bf3f7e3c244920James Dong        // getInputFramesLost() returns the number of lost frames.
290a472613aec322e25891abf5c77bf3f7e3c244920James Dong        // Convert number of frames lost to number of bytes lost.
291a472613aec322e25891abf5c77bf3f7e3c244920James Dong        numLostBytes = mRecord->getInputFramesLost() * mRecord->frameSize();
292a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
293a472613aec322e25891abf5c77bf3f7e3c244920James Dong
2946b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    CHECK_EQ(numLostBytes & 1, 0u);
2956b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    CHECK_EQ(audioBuffer.size & 1, 0u);
2966b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    size_t bufferSize = numLostBytes + audioBuffer.size;
2976b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    MediaBuffer *buffer = new MediaBuffer(bufferSize);
2986b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    if (numLostBytes > 0) {
2996b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        memset(buffer->data(), 0, numLostBytes);
3006b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        memcpy((uint8_t *) buffer->data() + numLostBytes,
3016b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong                    audioBuffer.i16, audioBuffer.size);
3026b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    } else {
3036b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        if (audioBuffer.size == 0) {
3046b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong            LOGW("Nothing is available from AudioRecord callback buffer");
305542db5d438988360d491a5add1040a2df9aa90c9James Dong            buffer->release();
3066b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong            return OK;
307d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong        }
3086b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        memcpy((uint8_t *) buffer->data(),
3096b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong                audioBuffer.i16, audioBuffer.size);
3106b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
3113c3763d2ee1cd1fba7fe522fbaf0faca315d8c2aJames Dong
3126b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    buffer->set_range(0, bufferSize);
3136b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    timestampUs += ((1000000LL * (bufferSize >> 1)) +
3146b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong                    (mSampleRate >> 1)) / mSampleRate;
315e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
3166b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    if (mNumFramesReceived == 0) {
3176b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs);
318542db5d438988360d491a5add1040a2df9aa90c9James Dong    }
3196b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs);
3206b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    buffer->meta_data()->setInt64(kKeyDriftTime, timeUs - mInitialReadTimeUs);
3216b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    mPrevSampleTimeUs = timestampUs;
3226b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    mNumFramesReceived += buffer->range_length() / sizeof(int16_t);
3236b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    mBuffersReceived.push_back(buffer);
3246b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    mFrameAvailableCondition.signal();
325e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
326e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return OK;
327e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
328e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
329d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dongvoid AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) {
330d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    for (int i = nSamples; i > 0; --i) {
331d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        int16_t value = *data++;
332d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        if (value < 0) {
333d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong            value = -value;
334d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        }
335d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        if (mMaxAmplitude < value) {
336d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong            mMaxAmplitude = value;
337d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        }
338d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    }
339d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong}
340d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong
341d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dongint16_t AudioSource::getMaxAmplitude() {
342d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    // First call activates the tracking.
343d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    if (!mTrackMaxAmplitude) {
344d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        mTrackMaxAmplitude = true;
345d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    }
346d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    int16_t value = mMaxAmplitude;
347d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    mMaxAmplitude = 0;
3483856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("max amplitude since last call: %d", value);
349d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    return value;
350d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong}
351d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong
352e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}  // namespace android
353