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