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> 27082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber#include <media/stagefright/foundation/ALooper.h> 28365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <cutils/properties.h> 2946292fb347d72a314d985e34e5e3743d846cb9b6James Dong#include <stdlib.h> 30e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 31e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Hubernamespace android { 32e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 336b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dongstatic void AudioRecordCallbackFunction(int event, void *user, void *info) { 346b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong AudioSource *source = (AudioSource *) user; 356b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong switch (event) { 366b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong case AudioRecord::EVENT_MORE_DATA: { 37082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber source->dataCallback(*((AudioRecord::Buffer *) info)); 386b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong break; 396b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong } 406b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong case AudioRecord::EVENT_OVERRUN: { 415ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("AudioRecord reported overrun!"); 426b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong break; 436b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong } 446b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong default: 456b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong // does nothing 466b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong break; 476b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong } 486b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong} 496b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong 50e7c9cb48fec02697227bd847cd2e69432659adfdAndreas HuberAudioSource::AudioSource( 51ab334fd351ae5a0e18903da123d63e565b536874Glenn Kasten audio_source_t inputSource, uint32_t sampleRate, uint32_t channelCount) 52a0108697f86d8625eb7ad3f13e422427fe7573caJames Dong : mRecord(NULL), 53a0108697f86d8625eb7ad3f13e422427fe7573caJames Dong mStarted(false), 546b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong mSampleRate(sampleRate), 5546292fb347d72a314d985e34e5e3743d846cb9b6James Dong mPrevSampleTimeUs(0), 566b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong mNumFramesReceived(0), 57af5dd7753e62353411cf0daf3b513c38818e9662Andreas Huber mNumClientOwnedBuffers(0) { 58ab334fd351ae5a0e18903da123d63e565b536874Glenn Kasten ALOGV("sampleRate: %d, channelCount: %d", sampleRate, channelCount); 59ab334fd351ae5a0e18903da123d63e565b536874Glenn Kasten CHECK(channelCount == 1 || channelCount == 2); 60be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong 61e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent int minFrameCount; 62e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent status_t status = AudioRecord::getMinFrameCount(&minFrameCount, 63e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent sampleRate, 64e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent AUDIO_FORMAT_PCM_16_BIT, 65dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten audio_channel_in_mask_from_count(channelCount)); 66e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent if (status == OK) { 67e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent // make sure that the AudioRecord callback never returns more than the maximum 68e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent // buffer size 69e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent int frameCount = kMaxBufferSize / sizeof(int16_t) / channelCount; 70e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent 71e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent // make sure that the AudioRecord total buffer size is large enough 72e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent int bufCount = 2; 73e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent while ((bufCount * frameCount) < minFrameCount) { 74e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent bufCount++; 75e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent } 76e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent 77e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent mRecord = new AudioRecord( 78e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT, 79e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent audio_channel_in_mask_from_count(channelCount), 80e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent bufCount * frameCount, 81e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent AudioRecordCallbackFunction, 82e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent this, 83e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent frameCount); 84e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent mInitCheck = mRecord->initCheck(); 85e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent } else { 86e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent mInitCheck = status; 87e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent } 88e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 89e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 90e7c9cb48fec02697227bd847cd2e69432659adfdAndreas HuberAudioSource::~AudioSource() { 91e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber if (mStarted) { 92b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dong reset(); 93e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber } 94e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 95e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber delete mRecord; 96e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber mRecord = NULL; 97e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 98e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 99e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::initCheck() const { 100e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber return mInitCheck; 101e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 102e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 103e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::start(MetaData *params) { 1046b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong Mutex::Autolock autoLock(mLock); 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 113d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong mTrackMaxAmplitude = false; 114d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong mMaxAmplitude = 0; 115d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mInitialReadTimeUs = 0; 116f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimeUs = 0; 117f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong int64_t startTimeUs; 118f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong if (params && params->findInt64(kKeyTime, &startTimeUs)) { 119f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimeUs = startTimeUs; 120f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong } 121e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber status_t err = mRecord->start(); 122e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber if (err == OK) { 123e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber mStarted = true; 124eaae38445a340c4857c1c5569475879a728e63b7James Dong } else { 125eaae38445a340c4857c1c5569475879a728e63b7James Dong delete mRecord; 126eaae38445a340c4857c1c5569475879a728e63b7James Dong mRecord = NULL; 127e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber } 128e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 129eaae38445a340c4857c1c5569475879a728e63b7James Dong 130e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber return err; 131e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 132e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 1336b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dongvoid AudioSource::releaseQueuedFrames_l() { 1343856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("releaseQueuedFrames_l"); 1356b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong List<MediaBuffer *>::iterator it; 1366b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong while (!mBuffersReceived.empty()) { 1376b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong it = mBuffersReceived.begin(); 1386b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong (*it)->release(); 1396b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong mBuffersReceived.erase(it); 1406b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong } 1416b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong} 1426b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong 1436b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dongvoid AudioSource::waitOutstandingEncodingFrames_l() { 1443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("waitOutstandingEncodingFrames_l: %lld", mNumClientOwnedBuffers); 1456b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong while (mNumClientOwnedBuffers > 0) { 1466b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong mFrameEncodingCompletionCondition.wait(mLock); 1476b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong } 1486b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong} 1496b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong 150b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dongstatus_t AudioSource::reset() { 1516b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong Mutex::Autolock autoLock(mLock); 152e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber if (!mStarted) { 153e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber return UNKNOWN_ERROR; 154e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber } 155e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 1566e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong if (mInitCheck != OK) { 1576e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong return NO_INIT; 1586e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong } 1596e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong 160e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber mStarted = false; 1616b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong mRecord->stop(); 1626b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong waitOutstandingEncodingFrames_l(); 1636b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong releaseQueuedFrames_l(); 164365a963142093a1cd8efdcea76b5f65096a5b115James Dong 165e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber return OK; 166e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 167e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 168e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Hubersp<MetaData> AudioSource::getFormat() { 1696b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong Mutex::Autolock autoLock(mLock); 1706e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong if (mInitCheck != OK) { 1716e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong return 0; 1726e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong } 1736e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong 174e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber sp<MetaData> meta = new MetaData; 175e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); 1766b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong meta->setInt32(kKeySampleRate, mSampleRate); 177e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber meta->setInt32(kKeyChannelCount, mRecord->channelCount()); 178e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber meta->setInt32(kKeyMaxInputSize, kMaxBufferSize); 179e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 180e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber return meta; 181e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 182e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 183f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dongvoid AudioSource::rampVolume( 184f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong int32_t startFrame, int32_t rampDurationFrames, 185f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong uint8_t *data, size_t bytes) { 186f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong 187f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong const int32_t kShift = 14; 188f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong int32_t fixedMultiplier = (startFrame << kShift) / rampDurationFrames; 189f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong const int32_t nChannels = mRecord->channelCount(); 190f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong int32_t stopFrame = startFrame + bytes / sizeof(int16_t); 191f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong int16_t *frame = (int16_t *) data; 192f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong if (stopFrame > rampDurationFrames) { 193f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong stopFrame = rampDurationFrames; 194f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong } 195f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong 196f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong while (startFrame < stopFrame) { 197f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong if (nChannels == 1) { // mono 198f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong frame[0] = (frame[0] * fixedMultiplier) >> kShift; 199f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong ++frame; 200f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong ++startFrame; 201f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong } else { // stereo 202f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong frame[0] = (frame[0] * fixedMultiplier) >> kShift; 203f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong frame[1] = (frame[1] * fixedMultiplier) >> kShift; 204f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong frame += 2; 205f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong startFrame += 2; 206f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong } 207f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong 208f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong // Update the multiplier every 4 frames 209f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong if ((startFrame & 3) == 0) { 210f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong fixedMultiplier = (startFrame << kShift) / rampDurationFrames; 211f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong } 212f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong } 213f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong} 214f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong 215e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::read( 216e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber MediaBuffer **out, const ReadOptions *options) { 2176b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong Mutex::Autolock autoLock(mLock); 2186b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong *out = NULL; 2196e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong 2206e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong if (mInitCheck != OK) { 2216e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong return NO_INIT; 2226e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong } 2236e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong 2246b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong while (mStarted && mBuffersReceived.empty()) { 2256b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong mFrameAvailableCondition.wait(mLock); 2266b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong } 2276b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong if (!mStarted) { 2286b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong return OK; 2296b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong } 2306b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong MediaBuffer *buffer = *mBuffersReceived.begin(); 2316b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong mBuffersReceived.erase(mBuffersReceived.begin()); 2326b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong ++mNumClientOwnedBuffers; 2336b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong buffer->setObserver(this); 2346b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong buffer->add_ref(); 2356b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong 2366b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong // Mute/suppress the recording sound 2376b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong int64_t timeUs; 2386b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs)); 2396b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong int64_t elapsedTimeUs = timeUs - mStartTimeUs; 2406b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong if (elapsedTimeUs < kAutoRampStartUs) { 2416b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong memset((uint8_t *) buffer->data(), 0, buffer->range_length()); 2426b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong } else if (elapsedTimeUs < kAutoRampStartUs + kAutoRampDurationUs) { 2436b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong int32_t autoRampDurationFrames = 2446b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong (kAutoRampDurationUs * mSampleRate + 500000LL) / 1000000LL; 2456b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong 2466b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong int32_t autoRampStartFrames = 2476b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong (kAutoRampStartUs * mSampleRate + 500000LL) / 1000000LL; 2486b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong 2496b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong int32_t nFrames = mNumFramesReceived - autoRampStartFrames; 2506b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong rampVolume(nFrames, autoRampDurationFrames, 2516b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong (uint8_t *) buffer->data(), buffer->range_length()); 2526b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong } 253542db5d438988360d491a5add1040a2df9aa90c9James Dong 2546b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong // Track the max recording signal amplitude. 2556b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong if (mTrackMaxAmplitude) { 2566b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong trackMaxAmplitude( 2576b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong (int16_t *) buffer->data(), buffer->range_length() >> 1); 2586b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong } 259542db5d438988360d491a5add1040a2df9aa90c9James Dong 2606b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong *out = buffer; 2616b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong return OK; 2626b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong} 263542db5d438988360d491a5add1040a2df9aa90c9James Dong 2646b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dongvoid AudioSource::signalBufferReturned(MediaBuffer *buffer) { 2653856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("signalBufferReturned: %p", buffer->data()); 2666b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong Mutex::Autolock autoLock(mLock); 2676b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong --mNumClientOwnedBuffers; 2686b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong buffer->setObserver(0); 2696b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong buffer->release(); 2706b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong mFrameEncodingCompletionCondition.signal(); 2716b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong return; 2726b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong} 27346292fb347d72a314d985e34e5e3743d846cb9b6James Dong 274082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huberstatus_t AudioSource::dataCallback(const AudioRecord::Buffer& audioBuffer) { 275af5dd7753e62353411cf0daf3b513c38818e9662Andreas Huber int64_t timeUs = systemTime() / 1000ll; 276082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber 2773856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("dataCallbackTimestamp: %lld us", timeUs); 2786b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong Mutex::Autolock autoLock(mLock); 2796b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong if (!mStarted) { 2805ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("Spurious callback from AudioRecord. Drop the audio data."); 2816b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong return OK; 2826b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong } 28346292fb347d72a314d985e34e5e3743d846cb9b6James Dong 284a472613aec322e25891abf5c77bf3f7e3c244920James Dong // Drop retrieved and previously lost audio data. 285a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (mNumFramesReceived == 0 && timeUs < mStartTimeUs) { 286a472613aec322e25891abf5c77bf3f7e3c244920James Dong mRecord->getInputFramesLost(); 2873856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Drop audio data at %lld/%lld us", timeUs, mStartTimeUs); 288a472613aec322e25891abf5c77bf3f7e3c244920James Dong return OK; 289a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 290a472613aec322e25891abf5c77bf3f7e3c244920James Dong 2916b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong if (mNumFramesReceived == 0 && mPrevSampleTimeUs == 0) { 2926b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong mInitialReadTimeUs = timeUs; 2936b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong // Initial delay 294af5dd7753e62353411cf0daf3b513c38818e9662Andreas Huber if (mStartTimeUs > 0) { 2956b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong mStartTimeUs = timeUs - mStartTimeUs; 2966b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong } else { 2976b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong // Assume latency is constant. 2986b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong mStartTimeUs += mRecord->latency() * 1000; 299f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong } 300082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber 3016b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong mPrevSampleTimeUs = mStartTimeUs; 3026b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong } 303e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 304a472613aec322e25891abf5c77bf3f7e3c244920James Dong size_t numLostBytes = 0; 305a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (mNumFramesReceived > 0) { // Ignore earlier frame lost 306a472613aec322e25891abf5c77bf3f7e3c244920James Dong // getInputFramesLost() returns the number of lost frames. 307a472613aec322e25891abf5c77bf3f7e3c244920James Dong // Convert number of frames lost to number of bytes lost. 308a472613aec322e25891abf5c77bf3f7e3c244920James Dong numLostBytes = mRecord->getInputFramesLost() * mRecord->frameSize(); 309a472613aec322e25891abf5c77bf3f7e3c244920James Dong } 310a472613aec322e25891abf5c77bf3f7e3c244920James Dong 3116b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong CHECK_EQ(numLostBytes & 1, 0u); 3126b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong CHECK_EQ(audioBuffer.size & 1, 0u); 3136b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong if (numLostBytes > 0) { 314b575ddce78d266fa218006f90306158dda5c8f56James Dong // Loss of audio frames should happen rarely; thus the LOGW should 315b575ddce78d266fa218006f90306158dda5c8f56James Dong // not cause a logging spam 316b575ddce78d266fa218006f90306158dda5c8f56James Dong ALOGW("Lost audio record data: %d bytes", numLostBytes); 317b575ddce78d266fa218006f90306158dda5c8f56James Dong } 318b575ddce78d266fa218006f90306158dda5c8f56James Dong 319b575ddce78d266fa218006f90306158dda5c8f56James Dong while (numLostBytes > 0) { 320b575ddce78d266fa218006f90306158dda5c8f56James Dong size_t bufferSize = numLostBytes; 321b575ddce78d266fa218006f90306158dda5c8f56James Dong if (numLostBytes > kMaxBufferSize) { 322b575ddce78d266fa218006f90306158dda5c8f56James Dong numLostBytes -= kMaxBufferSize; 323b575ddce78d266fa218006f90306158dda5c8f56James Dong bufferSize = kMaxBufferSize; 324b575ddce78d266fa218006f90306158dda5c8f56James Dong } else { 325b575ddce78d266fa218006f90306158dda5c8f56James Dong numLostBytes = 0; 326d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong } 327b575ddce78d266fa218006f90306158dda5c8f56James Dong MediaBuffer *lostAudioBuffer = new MediaBuffer(bufferSize); 328b575ddce78d266fa218006f90306158dda5c8f56James Dong memset(lostAudioBuffer->data(), 0, bufferSize); 329b575ddce78d266fa218006f90306158dda5c8f56James Dong lostAudioBuffer->set_range(0, bufferSize); 330b575ddce78d266fa218006f90306158dda5c8f56James Dong queueInputBuffer_l(lostAudioBuffer, timeUs); 331b575ddce78d266fa218006f90306158dda5c8f56James Dong } 332b575ddce78d266fa218006f90306158dda5c8f56James Dong 333b575ddce78d266fa218006f90306158dda5c8f56James Dong if (audioBuffer.size == 0) { 334b575ddce78d266fa218006f90306158dda5c8f56James Dong ALOGW("Nothing is available from AudioRecord callback buffer"); 335b575ddce78d266fa218006f90306158dda5c8f56James Dong return OK; 3366b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong } 3373c3763d2ee1cd1fba7fe522fbaf0faca315d8c2aJames Dong 338b575ddce78d266fa218006f90306158dda5c8f56James Dong const size_t bufferSize = audioBuffer.size; 339b575ddce78d266fa218006f90306158dda5c8f56James Dong MediaBuffer *buffer = new MediaBuffer(bufferSize); 340b575ddce78d266fa218006f90306158dda5c8f56James Dong memcpy((uint8_t *) buffer->data(), 341b575ddce78d266fa218006f90306158dda5c8f56James Dong audioBuffer.i16, audioBuffer.size); 3426b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong buffer->set_range(0, bufferSize); 343b575ddce78d266fa218006f90306158dda5c8f56James Dong queueInputBuffer_l(buffer, timeUs); 344b575ddce78d266fa218006f90306158dda5c8f56James Dong return OK; 345b575ddce78d266fa218006f90306158dda5c8f56James Dong} 346b575ddce78d266fa218006f90306158dda5c8f56James Dong 347b575ddce78d266fa218006f90306158dda5c8f56James Dongvoid AudioSource::queueInputBuffer_l(MediaBuffer *buffer, int64_t timeUs) { 348b575ddce78d266fa218006f90306158dda5c8f56James Dong const size_t bufferSize = buffer->range_length(); 349b575ddce78d266fa218006f90306158dda5c8f56James Dong const size_t frameSize = mRecord->frameSize(); 350b575ddce78d266fa218006f90306158dda5c8f56James Dong const int64_t timestampUs = 351b575ddce78d266fa218006f90306158dda5c8f56James Dong mPrevSampleTimeUs + 352b575ddce78d266fa218006f90306158dda5c8f56James Dong ((1000000LL * (bufferSize / frameSize)) + 353b575ddce78d266fa218006f90306158dda5c8f56James Dong (mSampleRate >> 1)) / mSampleRate; 354e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 3556b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong if (mNumFramesReceived == 0) { 3566b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs); 357542db5d438988360d491a5add1040a2df9aa90c9James Dong } 358b575ddce78d266fa218006f90306158dda5c8f56James Dong 3596b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs); 3606b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong buffer->meta_data()->setInt64(kKeyDriftTime, timeUs - mInitialReadTimeUs); 3616b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong mPrevSampleTimeUs = timestampUs; 362b575ddce78d266fa218006f90306158dda5c8f56James Dong mNumFramesReceived += bufferSize / frameSize; 3636b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong mBuffersReceived.push_back(buffer); 3646b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong mFrameAvailableCondition.signal(); 365e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 366e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 367d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dongvoid AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) { 368d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong for (int i = nSamples; i > 0; --i) { 369d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong int16_t value = *data++; 370d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong if (value < 0) { 371d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong value = -value; 372d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong } 373d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong if (mMaxAmplitude < value) { 374d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong mMaxAmplitude = value; 375d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong } 376d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong } 377d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong} 378d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong 379d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dongint16_t AudioSource::getMaxAmplitude() { 380d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong // First call activates the tracking. 381d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong if (!mTrackMaxAmplitude) { 382d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong mTrackMaxAmplitude = true; 383d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong } 384d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong int16_t value = mMaxAmplitude; 385d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong mMaxAmplitude = 0; 3863856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("max amplitude since last call: %d", value); 387d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong return value; 388d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong} 389d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong 390e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} // namespace android 391