AudioSource.cpp revision 3c3763d2ee1cd1fba7fe522fbaf0faca315d8c2a
1e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber/* 2e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * Copyright (C) 2010 The Android Open Source Project 3e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * 4e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * you may not use this file except in compliance with the License. 6e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * You may obtain a copy of the License at 7e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * 8e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * 10e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * Unless required by applicable law or agreed to in writing, software 11e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * See the License for the specific language governing permissions and 14e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * limitations under the License. 15e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber */ 16e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 17050b28a593350047845a45a14cc5026221ac1620James Dong//#define LOG_NDEBUG 0 18050b28a593350047845a45a14cc5026221ac1620James Dong#define LOG_TAG "AudioSource" 19050b28a593350047845a45a14cc5026221ac1620James Dong#include <utils/Log.h> 20050b28a593350047845a45a14cc5026221ac1620James Dong 21e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/AudioSource.h> 22e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 23e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/AudioRecord.h> 24e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MediaBufferGroup.h> 25e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MediaDebug.h> 26e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MediaDefs.h> 27e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MetaData.h> 28365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <cutils/properties.h> 2946292fb347d72a314d985e34e5e3743d846cb9b6James Dong#include <stdlib.h> 30e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 31e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Hubernamespace android { 32e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 33e7c9cb48fec02697227bd847cd2e69432659adfdAndreas HuberAudioSource::AudioSource( 34e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber int inputSource, uint32_t sampleRate, uint32_t channels) 35be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong : mStarted(false), 36365a963142093a1cd8efdcea76b5f65096a5b115James Dong mCollectStats(false), 3746292fb347d72a314d985e34e5e3743d846cb9b6James Dong mPrevSampleTimeUs(0), 3847204e1806da9f849464d0cef936851d7e561607James Dong mTotalLostFrames(0), 3947204e1806da9f849464d0cef936851d7e561607James Dong mPrevLostBytes(0), 40e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber mGroup(NULL) { 41be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong 42be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong LOGV("sampleRate: %d, channels: %d", sampleRate, channels); 43f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong CHECK(channels == 1 || channels == 2); 44be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong uint32_t flags = AudioRecord::RECORD_AGC_ENABLE | 45be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong AudioRecord::RECORD_NS_ENABLE | 46be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong AudioRecord::RECORD_IIR_ENABLE; 47be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong 48be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong mRecord = new AudioRecord( 49be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong inputSource, sampleRate, AudioSystem::PCM_16_BIT, 50be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong channels > 1? AudioSystem::CHANNEL_IN_STEREO: AudioSystem::CHANNEL_IN_MONO, 51be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong 4 * kMaxBufferSize / sizeof(int16_t), /* Enable ping-pong buffers */ 52be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong flags); 53be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong 54be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong mInitCheck = mRecord->initCheck(); 55e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 56e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 57e7c9cb48fec02697227bd847cd2e69432659adfdAndreas HuberAudioSource::~AudioSource() { 58e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber if (mStarted) { 59e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber stop(); 60e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber } 61e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 62e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber delete mRecord; 63e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber mRecord = NULL; 64e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 65e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 66e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::initCheck() const { 67e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber return mInitCheck; 68e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 69e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 70e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::start(MetaData *params) { 71e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber if (mStarted) { 72e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber return UNKNOWN_ERROR; 73e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber } 74e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 756e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong if (mInitCheck != OK) { 766e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong return NO_INIT; 776e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong } 786e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong 79365a963142093a1cd8efdcea76b5f65096a5b115James Dong char value[PROPERTY_VALUE_MAX]; 80365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (property_get("media.stagefright.record-stats", value, NULL) 81365a963142093a1cd8efdcea76b5f65096a5b115James Dong && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 82365a963142093a1cd8efdcea76b5f65096a5b115James Dong mCollectStats = true; 83365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 84f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong 85d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong mTrackMaxAmplitude = false; 86d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong mMaxAmplitude = 0; 87d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mInitialReadTimeUs = 0; 88f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimeUs = 0; 89f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong int64_t startTimeUs; 90f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong if (params && params->findInt64(kKeyTime, &startTimeUs)) { 91f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimeUs = startTimeUs; 92f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong } 93e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber status_t err = mRecord->start(); 94e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 95e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber if (err == OK) { 96e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber mGroup = new MediaBufferGroup; 97e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber mGroup->add_buffer(new MediaBuffer(kMaxBufferSize)); 98e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 99e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber mStarted = true; 100e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber } 101e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 102e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber return err; 103e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 104e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 105e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::stop() { 106e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber if (!mStarted) { 107e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber return UNKNOWN_ERROR; 108e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber } 109e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 1106e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong if (mInitCheck != OK) { 1116e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong return NO_INIT; 1126e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong } 1136e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong 114e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber mRecord->stop(); 115e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 116e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber delete mGroup; 117e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber mGroup = NULL; 118e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 119e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber mStarted = false; 120e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 121365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (mCollectStats) { 12247204e1806da9f849464d0cef936851d7e561607James Dong LOGI("Total lost audio frames: %lld", 12347204e1806da9f849464d0cef936851d7e561607James Dong mTotalLostFrames + (mPrevLostBytes >> 1)); 124365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 125365a963142093a1cd8efdcea76b5f65096a5b115James Dong 126e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber return OK; 127e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 128e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 129e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Hubersp<MetaData> AudioSource::getFormat() { 1306e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong if (mInitCheck != OK) { 1316e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong return 0; 1326e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong } 1336e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong 134e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber sp<MetaData> meta = new MetaData; 135e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); 136e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber meta->setInt32(kKeySampleRate, mRecord->getSampleRate()); 137e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber meta->setInt32(kKeyChannelCount, mRecord->channelCount()); 138e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber meta->setInt32(kKeyMaxInputSize, kMaxBufferSize); 139e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 140e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber return meta; 141e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 142e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 14346292fb347d72a314d985e34e5e3743d846cb9b6James Dong/* 14446292fb347d72a314d985e34e5e3743d846cb9b6James Dong * Returns -1 if frame skipping request is too long. 14546292fb347d72a314d985e34e5e3743d846cb9b6James Dong * Returns 0 if there is no need to skip frames. 14646292fb347d72a314d985e34e5e3743d846cb9b6James Dong * Returns 1 if we need to skip frames. 14746292fb347d72a314d985e34e5e3743d846cb9b6James Dong */ 14846292fb347d72a314d985e34e5e3743d846cb9b6James Dongstatic int skipFrame(int64_t timestampUs, 14946292fb347d72a314d985e34e5e3743d846cb9b6James Dong const MediaSource::ReadOptions *options) { 15046292fb347d72a314d985e34e5e3743d846cb9b6James Dong 15146292fb347d72a314d985e34e5e3743d846cb9b6James Dong int64_t skipFrameUs; 15246292fb347d72a314d985e34e5e3743d846cb9b6James Dong if (!options || !options->getSkipFrame(&skipFrameUs)) { 15346292fb347d72a314d985e34e5e3743d846cb9b6James Dong return 0; 15446292fb347d72a314d985e34e5e3743d846cb9b6James Dong } 15546292fb347d72a314d985e34e5e3743d846cb9b6James Dong 15646292fb347d72a314d985e34e5e3743d846cb9b6James Dong if (skipFrameUs <= timestampUs) { 15746292fb347d72a314d985e34e5e3743d846cb9b6James Dong return 0; 15846292fb347d72a314d985e34e5e3743d846cb9b6James Dong } 15946292fb347d72a314d985e34e5e3743d846cb9b6James Dong 16046292fb347d72a314d985e34e5e3743d846cb9b6James Dong // Safe guard against the abuse of the kSkipFrame_Option. 16146292fb347d72a314d985e34e5e3743d846cb9b6James Dong if (skipFrameUs - timestampUs >= 1E6) { 16246292fb347d72a314d985e34e5e3743d846cb9b6James Dong LOGE("Frame skipping requested is way too long: %lld us", 16346292fb347d72a314d985e34e5e3743d846cb9b6James Dong skipFrameUs - timestampUs); 16446292fb347d72a314d985e34e5e3743d846cb9b6James Dong 16546292fb347d72a314d985e34e5e3743d846cb9b6James Dong return -1; 16646292fb347d72a314d985e34e5e3743d846cb9b6James Dong } 16746292fb347d72a314d985e34e5e3743d846cb9b6James Dong 16846292fb347d72a314d985e34e5e3743d846cb9b6James Dong LOGV("skipFrame: %lld us > timestamp: %lld us", 16946292fb347d72a314d985e34e5e3743d846cb9b6James Dong skipFrameUs, timestampUs); 17046292fb347d72a314d985e34e5e3743d846cb9b6James Dong 17146292fb347d72a314d985e34e5e3743d846cb9b6James Dong return 1; 17246292fb347d72a314d985e34e5e3743d846cb9b6James Dong 17346292fb347d72a314d985e34e5e3743d846cb9b6James Dong} 17446292fb347d72a314d985e34e5e3743d846cb9b6James Dong 175f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dongvoid AudioSource::rampVolume( 176f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong int32_t startFrame, int32_t rampDurationFrames, 177f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong uint8_t *data, size_t bytes) { 178f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong 179f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong const int32_t kShift = 14; 180f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong int32_t fixedMultiplier = (startFrame << kShift) / rampDurationFrames; 181f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong const int32_t nChannels = mRecord->channelCount(); 182f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong int32_t stopFrame = startFrame + bytes / sizeof(int16_t); 183f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong int16_t *frame = (int16_t *) data; 184f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong if (stopFrame > rampDurationFrames) { 185f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong stopFrame = rampDurationFrames; 186f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong } 187f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong 188f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong while (startFrame < stopFrame) { 189f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong if (nChannels == 1) { // mono 190f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong frame[0] = (frame[0] * fixedMultiplier) >> kShift; 191f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong ++frame; 192f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong ++startFrame; 193f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong } else { // stereo 194f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong frame[0] = (frame[0] * fixedMultiplier) >> kShift; 195f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong frame[1] = (frame[1] * fixedMultiplier) >> kShift; 196f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong frame += 2; 197f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong startFrame += 2; 198f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong } 199f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong 200f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong // Update the multiplier every 4 frames 201f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong if ((startFrame & 3) == 0) { 202f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong fixedMultiplier = (startFrame << kShift) / rampDurationFrames; 203f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong } 204f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong } 205f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong} 206f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong 207e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::read( 208e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber MediaBuffer **out, const ReadOptions *options) { 2096e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong 2106e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong if (mInitCheck != OK) { 2116e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong return NO_INIT; 2126e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong } 2136e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong 214d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong int64_t readTimeUs = systemTime() / 1000; 215e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber *out = NULL; 216e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 217e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber MediaBuffer *buffer; 218e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber CHECK_EQ(mGroup->acquire_buffer(&buffer), OK); 219e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 22046292fb347d72a314d985e34e5e3743d846cb9b6James Dong int err = 0; 221542db5d438988360d491a5add1040a2df9aa90c9James Dong while (mStarted) { 22246292fb347d72a314d985e34e5e3743d846cb9b6James Dong 223542db5d438988360d491a5add1040a2df9aa90c9James Dong uint32_t numFramesRecorded; 224542db5d438988360d491a5add1040a2df9aa90c9James Dong mRecord->getPosition(&numFramesRecorded); 225542db5d438988360d491a5add1040a2df9aa90c9James Dong 226542db5d438988360d491a5add1040a2df9aa90c9James Dong 22746292fb347d72a314d985e34e5e3743d846cb9b6James Dong if (numFramesRecorded == 0 && mPrevSampleTimeUs == 0) { 228d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mInitialReadTimeUs = readTimeUs; 229542db5d438988360d491a5add1040a2df9aa90c9James Dong // Initial delay 230542db5d438988360d491a5add1040a2df9aa90c9James Dong if (mStartTimeUs > 0) { 231d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong mStartTimeUs = readTimeUs - mStartTimeUs; 232542db5d438988360d491a5add1040a2df9aa90c9James Dong } else { 23346292fb347d72a314d985e34e5e3743d846cb9b6James Dong // Assume latency is constant. 23446292fb347d72a314d985e34e5e3743d846cb9b6James Dong mStartTimeUs += mRecord->latency() * 1000; 235542db5d438988360d491a5add1040a2df9aa90c9James Dong } 23646292fb347d72a314d985e34e5e3743d846cb9b6James Dong mPrevSampleTimeUs = mStartTimeUs; 237542db5d438988360d491a5add1040a2df9aa90c9James Dong } 238542db5d438988360d491a5add1040a2df9aa90c9James Dong 23946292fb347d72a314d985e34e5e3743d846cb9b6James Dong uint32_t sampleRate = mRecord->getSampleRate(); 24046292fb347d72a314d985e34e5e3743d846cb9b6James Dong 24146292fb347d72a314d985e34e5e3743d846cb9b6James Dong // Insert null frames when lost frames are detected. 24246292fb347d72a314d985e34e5e3743d846cb9b6James Dong int64_t timestampUs = mPrevSampleTimeUs; 24346292fb347d72a314d985e34e5e3743d846cb9b6James Dong uint32_t numLostBytes = mRecord->getInputFramesLost() << 1; 24447204e1806da9f849464d0cef936851d7e561607James Dong numLostBytes += mPrevLostBytes; 24546292fb347d72a314d985e34e5e3743d846cb9b6James Dong#if 0 24646292fb347d72a314d985e34e5e3743d846cb9b6James Dong // Simulate lost frames 24747204e1806da9f849464d0cef936851d7e561607James Dong numLostBytes = ((rand() * 1.0 / RAND_MAX)) * 2 * kMaxBufferSize; 24847204e1806da9f849464d0cef936851d7e561607James Dong numLostBytes &= 0xFFFFFFFE; // Alignment requirement 24946292fb347d72a314d985e34e5e3743d846cb9b6James Dong 25046292fb347d72a314d985e34e5e3743d846cb9b6James Dong // Reduce the chance to lose 25146292fb347d72a314d985e34e5e3743d846cb9b6James Dong if (rand() * 1.0 / RAND_MAX >= 0.05) { 25246292fb347d72a314d985e34e5e3743d846cb9b6James Dong numLostBytes = 0; 25346292fb347d72a314d985e34e5e3743d846cb9b6James Dong } 25446292fb347d72a314d985e34e5e3743d846cb9b6James Dong#endif 25546292fb347d72a314d985e34e5e3743d846cb9b6James Dong if (numLostBytes > 0) { 25647204e1806da9f849464d0cef936851d7e561607James Dong if (numLostBytes > kMaxBufferSize) { 25747204e1806da9f849464d0cef936851d7e561607James Dong mPrevLostBytes = numLostBytes - kMaxBufferSize; 25847204e1806da9f849464d0cef936851d7e561607James Dong numLostBytes = kMaxBufferSize; 25947204e1806da9f849464d0cef936851d7e561607James Dong } 26047204e1806da9f849464d0cef936851d7e561607James Dong 26147204e1806da9f849464d0cef936851d7e561607James Dong CHECK_EQ(numLostBytes & 1, 0); 26247204e1806da9f849464d0cef936851d7e561607James Dong timestampUs += ((1000000LL * (numLostBytes >> 1)) + 26347204e1806da9f849464d0cef936851d7e561607James Dong (sampleRate >> 1)) / sampleRate; 26446292fb347d72a314d985e34e5e3743d846cb9b6James Dong 26546292fb347d72a314d985e34e5e3743d846cb9b6James Dong CHECK(timestampUs > mPrevSampleTimeUs); 26646292fb347d72a314d985e34e5e3743d846cb9b6James Dong if (mCollectStats) { 26747204e1806da9f849464d0cef936851d7e561607James Dong mTotalLostFrames += (numLostBytes >> 1); 26846292fb347d72a314d985e34e5e3743d846cb9b6James Dong } 26946292fb347d72a314d985e34e5e3743d846cb9b6James Dong if ((err = skipFrame(timestampUs, options)) == -1) { 27046292fb347d72a314d985e34e5e3743d846cb9b6James Dong buffer->release(); 27146292fb347d72a314d985e34e5e3743d846cb9b6James Dong return UNKNOWN_ERROR; 27246292fb347d72a314d985e34e5e3743d846cb9b6James Dong } else if (err != 0) { 27346292fb347d72a314d985e34e5e3743d846cb9b6James Dong continue; 274542db5d438988360d491a5add1040a2df9aa90c9James Dong } 27546292fb347d72a314d985e34e5e3743d846cb9b6James Dong memset(buffer->data(), 0, numLostBytes); 27646292fb347d72a314d985e34e5e3743d846cb9b6James Dong buffer->set_range(0, numLostBytes); 277d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong if (numFramesRecorded == 0) { 278d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong buffer->meta_data()->setInt64(kKeyTime, mStartTimeUs); 279d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong } 280d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong buffer->meta_data()->setInt64(kKeyDriftTime, readTimeUs - mInitialReadTimeUs); 28146292fb347d72a314d985e34e5e3743d846cb9b6James Dong mPrevSampleTimeUs = timestampUs; 28246292fb347d72a314d985e34e5e3743d846cb9b6James Dong *out = buffer; 28346292fb347d72a314d985e34e5e3743d846cb9b6James Dong return OK; 284f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong } 285e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 28646292fb347d72a314d985e34e5e3743d846cb9b6James Dong ssize_t n = mRecord->read(buffer->data(), buffer->size()); 287542db5d438988360d491a5add1040a2df9aa90c9James Dong if (n < 0) { 288542db5d438988360d491a5add1040a2df9aa90c9James Dong buffer->release(); 289542db5d438988360d491a5add1040a2df9aa90c9James Dong return (status_t)n; 290365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 291e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 29246292fb347d72a314d985e34e5e3743d846cb9b6James Dong int64_t recordDurationUs = (1000000LL * n >> 1) / sampleRate; 29346292fb347d72a314d985e34e5e3743d846cb9b6James Dong timestampUs += recordDurationUs; 29446292fb347d72a314d985e34e5e3743d846cb9b6James Dong if ((err = skipFrame(timestampUs, options)) == -1) { 29546292fb347d72a314d985e34e5e3743d846cb9b6James Dong buffer->release(); 29646292fb347d72a314d985e34e5e3743d846cb9b6James Dong return UNKNOWN_ERROR; 29746292fb347d72a314d985e34e5e3743d846cb9b6James Dong } else if (err != 0) { 298542db5d438988360d491a5add1040a2df9aa90c9James Dong continue; 299542db5d438988360d491a5add1040a2df9aa90c9James Dong } 300e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 301f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong if (mPrevSampleTimeUs - mStartTimeUs < kAutoRampStartUs) { 302f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong // Mute the initial video recording signal 303f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong memset((uint8_t *) buffer->data(), 0, n); 304f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong } else if (mPrevSampleTimeUs - mStartTimeUs < kAutoRampStartUs + kAutoRampDurationUs) { 305f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong int32_t autoRampDurationFrames = 306f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong (kAutoRampDurationUs * sampleRate + 500000LL) / 1000000LL; 307f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong 308f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong int32_t autoRampStartFrames = 309f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong (kAutoRampStartUs * sampleRate + 500000LL) / 1000000LL; 310f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong 311f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong int32_t nFrames = numFramesRecorded - autoRampStartFrames; 312f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong rampVolume(nFrames, autoRampDurationFrames, (uint8_t *) buffer->data(), n); 313f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong } 314542db5d438988360d491a5add1040a2df9aa90c9James Dong if (mTrackMaxAmplitude) { 315542db5d438988360d491a5add1040a2df9aa90c9James Dong trackMaxAmplitude((int16_t *) buffer->data(), n >> 1); 316542db5d438988360d491a5add1040a2df9aa90c9James Dong } 317d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong 318d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong if (numFramesRecorded == 0) { 3193c3763d2ee1cd1fba7fe522fbaf0faca315d8c2aJames Dong buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs); 320d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong } 3213c3763d2ee1cd1fba7fe522fbaf0faca315d8c2aJames Dong 3223c3763d2ee1cd1fba7fe522fbaf0faca315d8c2aJames Dong buffer->meta_data()->setInt64(kKeyTime, mStartTimeUs + mPrevSampleTimeUs); 323d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong buffer->meta_data()->setInt64(kKeyDriftTime, readTimeUs - mInitialReadTimeUs); 32446292fb347d72a314d985e34e5e3743d846cb9b6James Dong CHECK(timestampUs > mPrevSampleTimeUs); 32546292fb347d72a314d985e34e5e3743d846cb9b6James Dong mPrevSampleTimeUs = timestampUs; 326542db5d438988360d491a5add1040a2df9aa90c9James Dong LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld", 327542db5d438988360d491a5add1040a2df9aa90c9James Dong mStartTimeUs, sampleRate, timestampUs); 328f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong 329542db5d438988360d491a5add1040a2df9aa90c9James Dong buffer->set_range(0, n); 330e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 331542db5d438988360d491a5add1040a2df9aa90c9James Dong *out = buffer; 332542db5d438988360d491a5add1040a2df9aa90c9James Dong return OK; 333542db5d438988360d491a5add1040a2df9aa90c9James Dong } 334e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 335e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber return OK; 336e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} 337e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber 338d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dongvoid AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) { 339d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong for (int i = nSamples; i > 0; --i) { 340d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong int16_t value = *data++; 341d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong if (value < 0) { 342d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong value = -value; 343d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong } 344d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong if (mMaxAmplitude < value) { 345d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong mMaxAmplitude = value; 346d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong } 347d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong } 348d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong} 349d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong 350d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dongint16_t AudioSource::getMaxAmplitude() { 351d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong // First call activates the tracking. 352d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong if (!mTrackMaxAmplitude) { 353d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong mTrackMaxAmplitude = true; 354d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong } 355d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong int16_t value = mMaxAmplitude; 356d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong mMaxAmplitude = 0; 357d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong LOGV("max amplitude since last call: %d", value); 358d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong return value; 359d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong} 360d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong 361e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber} // namespace android 362