AudioSource.cpp revision 542db5d438988360d491a5add1040a2df9aa90c9
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "AudioSource" 19#include <utils/Log.h> 20 21#include <media/stagefright/AudioSource.h> 22 23#include <media/AudioRecord.h> 24#include <media/stagefright/MediaBufferGroup.h> 25#include <media/stagefright/MediaDebug.h> 26#include <media/stagefright/MediaDefs.h> 27#include <media/stagefright/MetaData.h> 28#include <cutils/properties.h> 29#include <sys/time.h> 30#include <time.h> 31 32namespace android { 33 34AudioSource::AudioSource( 35 int inputSource, uint32_t sampleRate, uint32_t channels) 36 : mStarted(false), 37 mCollectStats(false), 38 mTotalReadTimeUs(0), 39 mTotalReadBytes(0), 40 mTotalReads(0), 41 mGroup(NULL) { 42 43 LOGV("sampleRate: %d, channels: %d", sampleRate, channels); 44 uint32_t flags = AudioRecord::RECORD_AGC_ENABLE | 45 AudioRecord::RECORD_NS_ENABLE | 46 AudioRecord::RECORD_IIR_ENABLE; 47 48 mRecord = new AudioRecord( 49 inputSource, sampleRate, AudioSystem::PCM_16_BIT, 50 channels > 1? AudioSystem::CHANNEL_IN_STEREO: AudioSystem::CHANNEL_IN_MONO, 51 4 * kMaxBufferSize / sizeof(int16_t), /* Enable ping-pong buffers */ 52 flags); 53 54 mInitCheck = mRecord->initCheck(); 55} 56 57AudioSource::~AudioSource() { 58 if (mStarted) { 59 stop(); 60 } 61 62 delete mRecord; 63 mRecord = NULL; 64} 65 66status_t AudioSource::initCheck() const { 67 return mInitCheck; 68} 69 70status_t AudioSource::start(MetaData *params) { 71 if (mStarted) { 72 return UNKNOWN_ERROR; 73 } 74 75 char value[PROPERTY_VALUE_MAX]; 76 if (property_get("media.stagefright.record-stats", value, NULL) 77 && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 78 mCollectStats = true; 79 } 80 81 mTrackMaxAmplitude = false; 82 mMaxAmplitude = 0; 83 mStartTimeUs = 0; 84 int64_t startTimeUs; 85 if (params && params->findInt64(kKeyTime, &startTimeUs)) { 86 mStartTimeUs = startTimeUs; 87 } 88 status_t err = mRecord->start(); 89 90 if (err == OK) { 91 mGroup = new MediaBufferGroup; 92 mGroup->add_buffer(new MediaBuffer(kMaxBufferSize)); 93 94 mStarted = true; 95 } 96 97 return err; 98} 99 100status_t AudioSource::stop() { 101 if (!mStarted) { 102 return UNKNOWN_ERROR; 103 } 104 105 mRecord->stop(); 106 107 delete mGroup; 108 mGroup = NULL; 109 110 mStarted = false; 111 112 if (mCollectStats) { 113 LOGI("%lld reads: %.2f bps in %lld us", 114 mTotalReads, 115 (mTotalReadBytes * 8000000.0) / mTotalReadTimeUs, 116 mTotalReadTimeUs); 117 } 118 119 return OK; 120} 121 122sp<MetaData> AudioSource::getFormat() { 123 sp<MetaData> meta = new MetaData; 124 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); 125 meta->setInt32(kKeySampleRate, mRecord->getSampleRate()); 126 meta->setInt32(kKeyChannelCount, mRecord->channelCount()); 127 meta->setInt32(kKeyMaxInputSize, kMaxBufferSize); 128 129 return meta; 130} 131 132status_t AudioSource::read( 133 MediaBuffer **out, const ReadOptions *options) { 134 *out = NULL; 135 ++mTotalReads; 136 137 MediaBuffer *buffer; 138 CHECK_EQ(mGroup->acquire_buffer(&buffer), OK); 139 140 while (mStarted) { 141 uint32_t numFramesRecorded; 142 mRecord->getPosition(&numFramesRecorded); 143 int64_t latency = mRecord->latency() * 1000; 144 145 int64_t readTime = systemTime() / 1000; 146 147 if (numFramesRecorded == 0) { 148 // Initial delay 149 if (mStartTimeUs > 0) { 150 mStartTimeUs = readTime - mStartTimeUs; 151 } else { 152 mStartTimeUs += latency; 153 } 154 } 155 156 ssize_t n = 0; 157 if (mCollectStats) { 158 n = mRecord->read(buffer->data(), buffer->size()); 159 int64_t endTime = systemTime() / 1000; 160 mTotalReadTimeUs += (endTime - readTime); 161 if (n >= 0) { 162 mTotalReadBytes += n; 163 } 164 } else { 165 n = mRecord->read(buffer->data(), buffer->size()); 166 } 167 168 if (n < 0) { 169 buffer->release(); 170 buffer = NULL; 171 172 return (status_t)n; 173 } 174 175 uint32_t sampleRate = mRecord->getSampleRate(); 176 int64_t timestampUs = (1000000LL * numFramesRecorded) / sampleRate + 177 mStartTimeUs; 178 int64_t skipFrameUs; 179 if (!options || !options->getSkipFrame(&skipFrameUs)) { 180 skipFrameUs = timestampUs; // Don't skip frame 181 } 182 183 if (skipFrameUs > timestampUs) { 184 // Safe guard against the abuse of the kSkipFrame_Option. 185 if (skipFrameUs - timestampUs >= 1E6) { 186 LOGE("Frame skipping requested is way too long: %lld us", 187 skipFrameUs - timestampUs); 188 buffer->release(); 189 return UNKNOWN_ERROR; 190 } 191 LOGV("skipFrame: %lld us > timestamp: %lld us, samples %d", 192 skipFrameUs, timestampUs, numFramesRecorded); 193 continue; 194 } 195 196 if (mTrackMaxAmplitude) { 197 trackMaxAmplitude((int16_t *) buffer->data(), n >> 1); 198 } 199 200 buffer->meta_data()->setInt64(kKeyTime, timestampUs); 201 LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld", 202 mStartTimeUs, sampleRate, timestampUs); 203 204 buffer->set_range(0, n); 205 206 *out = buffer; 207 return OK; 208 } 209 210 return OK; 211} 212 213void AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) { 214 for (int i = nSamples; i > 0; --i) { 215 int16_t value = *data++; 216 if (value < 0) { 217 value = -value; 218 } 219 if (mMaxAmplitude < value) { 220 mMaxAmplitude = value; 221 } 222 } 223} 224 225int16_t AudioSource::getMaxAmplitude() { 226 // First call activates the tracking. 227 if (!mTrackMaxAmplitude) { 228 mTrackMaxAmplitude = true; 229 } 230 int16_t value = mMaxAmplitude; 231 mMaxAmplitude = 0; 232 LOGV("max amplitude since last call: %d", value); 233 return value; 234} 235 236} // namespace android 237