AudioSource.cpp revision 6e20bdf799a6f4efa6c42121a958634ea32ed5cc
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 <stdlib.h> 30 31namespace android { 32 33AudioSource::AudioSource( 34 int inputSource, uint32_t sampleRate, uint32_t channels) 35 : mStarted(false), 36 mCollectStats(false), 37 mPrevSampleTimeUs(0), 38 mTotalLostFrames(0), 39 mPrevLostBytes(0), 40 mGroup(NULL) { 41 42 LOGV("sampleRate: %d, channels: %d", sampleRate, channels); 43 CHECK(channels == 1 || channels == 2); 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 if (mInitCheck != OK) { 76 return NO_INIT; 77 } 78 79 char value[PROPERTY_VALUE_MAX]; 80 if (property_get("media.stagefright.record-stats", value, NULL) 81 && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 82 mCollectStats = true; 83 } 84 85 mTrackMaxAmplitude = false; 86 mMaxAmplitude = 0; 87 mStartTimeUs = 0; 88 int64_t startTimeUs; 89 if (params && params->findInt64(kKeyTime, &startTimeUs)) { 90 mStartTimeUs = startTimeUs; 91 } 92 status_t err = mRecord->start(); 93 94 if (err == OK) { 95 mGroup = new MediaBufferGroup; 96 mGroup->add_buffer(new MediaBuffer(kMaxBufferSize)); 97 98 mStarted = true; 99 } 100 101 return err; 102} 103 104status_t AudioSource::stop() { 105 if (!mStarted) { 106 return UNKNOWN_ERROR; 107 } 108 109 if (mInitCheck != OK) { 110 return NO_INIT; 111 } 112 113 mRecord->stop(); 114 115 delete mGroup; 116 mGroup = NULL; 117 118 mStarted = false; 119 120 if (mCollectStats) { 121 LOGI("Total lost audio frames: %lld", 122 mTotalLostFrames + (mPrevLostBytes >> 1)); 123 } 124 125 return OK; 126} 127 128sp<MetaData> AudioSource::getFormat() { 129 if (mInitCheck != OK) { 130 return 0; 131 } 132 133 sp<MetaData> meta = new MetaData; 134 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); 135 meta->setInt32(kKeySampleRate, mRecord->getSampleRate()); 136 meta->setInt32(kKeyChannelCount, mRecord->channelCount()); 137 meta->setInt32(kKeyMaxInputSize, kMaxBufferSize); 138 139 return meta; 140} 141 142/* 143 * Returns -1 if frame skipping request is too long. 144 * Returns 0 if there is no need to skip frames. 145 * Returns 1 if we need to skip frames. 146 */ 147static int skipFrame(int64_t timestampUs, 148 const MediaSource::ReadOptions *options) { 149 150 int64_t skipFrameUs; 151 if (!options || !options->getSkipFrame(&skipFrameUs)) { 152 return 0; 153 } 154 155 if (skipFrameUs <= timestampUs) { 156 return 0; 157 } 158 159 // Safe guard against the abuse of the kSkipFrame_Option. 160 if (skipFrameUs - timestampUs >= 1E6) { 161 LOGE("Frame skipping requested is way too long: %lld us", 162 skipFrameUs - timestampUs); 163 164 return -1; 165 } 166 167 LOGV("skipFrame: %lld us > timestamp: %lld us", 168 skipFrameUs, timestampUs); 169 170 return 1; 171 172} 173 174void AudioSource::rampVolume( 175 int32_t startFrame, int32_t rampDurationFrames, 176 uint8_t *data, size_t bytes) { 177 178 const int32_t kShift = 14; 179 int32_t fixedMultiplier = (startFrame << kShift) / rampDurationFrames; 180 const int32_t nChannels = mRecord->channelCount(); 181 int32_t stopFrame = startFrame + bytes / sizeof(int16_t); 182 int16_t *frame = (int16_t *) data; 183 if (stopFrame > rampDurationFrames) { 184 stopFrame = rampDurationFrames; 185 } 186 187 while (startFrame < stopFrame) { 188 if (nChannels == 1) { // mono 189 frame[0] = (frame[0] * fixedMultiplier) >> kShift; 190 ++frame; 191 ++startFrame; 192 } else { // stereo 193 frame[0] = (frame[0] * fixedMultiplier) >> kShift; 194 frame[1] = (frame[1] * fixedMultiplier) >> kShift; 195 frame += 2; 196 startFrame += 2; 197 } 198 199 // Update the multiplier every 4 frames 200 if ((startFrame & 3) == 0) { 201 fixedMultiplier = (startFrame << kShift) / rampDurationFrames; 202 } 203 } 204} 205 206status_t AudioSource::read( 207 MediaBuffer **out, const ReadOptions *options) { 208 209 if (mInitCheck != OK) { 210 return NO_INIT; 211 } 212 213 *out = NULL; 214 215 MediaBuffer *buffer; 216 CHECK_EQ(mGroup->acquire_buffer(&buffer), OK); 217 218 int err = 0; 219 while (mStarted) { 220 221 uint32_t numFramesRecorded; 222 mRecord->getPosition(&numFramesRecorded); 223 224 225 if (numFramesRecorded == 0 && mPrevSampleTimeUs == 0) { 226 // Initial delay 227 if (mStartTimeUs > 0) { 228 mStartTimeUs = systemTime() / 1000 - mStartTimeUs; 229 } else { 230 // Assume latency is constant. 231 mStartTimeUs += mRecord->latency() * 1000; 232 } 233 mPrevSampleTimeUs = mStartTimeUs; 234 } 235 236 uint32_t sampleRate = mRecord->getSampleRate(); 237 238 // Insert null frames when lost frames are detected. 239 int64_t timestampUs = mPrevSampleTimeUs; 240 uint32_t numLostBytes = mRecord->getInputFramesLost() << 1; 241 numLostBytes += mPrevLostBytes; 242#if 0 243 // Simulate lost frames 244 numLostBytes = ((rand() * 1.0 / RAND_MAX)) * 2 * kMaxBufferSize; 245 numLostBytes &= 0xFFFFFFFE; // Alignment requirement 246 247 // Reduce the chance to lose 248 if (rand() * 1.0 / RAND_MAX >= 0.05) { 249 numLostBytes = 0; 250 } 251#endif 252 if (numLostBytes > 0) { 253 if (numLostBytes > kMaxBufferSize) { 254 mPrevLostBytes = numLostBytes - kMaxBufferSize; 255 numLostBytes = kMaxBufferSize; 256 } 257 258 CHECK_EQ(numLostBytes & 1, 0); 259 timestampUs += ((1000000LL * (numLostBytes >> 1)) + 260 (sampleRate >> 1)) / sampleRate; 261 262 CHECK(timestampUs > mPrevSampleTimeUs); 263 if (mCollectStats) { 264 mTotalLostFrames += (numLostBytes >> 1); 265 } 266 if ((err = skipFrame(timestampUs, options)) == -1) { 267 buffer->release(); 268 return UNKNOWN_ERROR; 269 } else if (err != 0) { 270 continue; 271 } 272 memset(buffer->data(), 0, numLostBytes); 273 buffer->set_range(0, numLostBytes); 274 buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs); 275 mPrevSampleTimeUs = timestampUs; 276 *out = buffer; 277 return OK; 278 } 279 280 ssize_t n = mRecord->read(buffer->data(), buffer->size()); 281 if (n < 0) { 282 buffer->release(); 283 return (status_t)n; 284 } 285 286 int64_t recordDurationUs = (1000000LL * n >> 1) / sampleRate; 287 timestampUs += recordDurationUs; 288 if ((err = skipFrame(timestampUs, options)) == -1) { 289 buffer->release(); 290 return UNKNOWN_ERROR; 291 } else if (err != 0) { 292 continue; 293 } 294 295 if (mPrevSampleTimeUs - mStartTimeUs < kAutoRampStartUs) { 296 // Mute the initial video recording signal 297 memset((uint8_t *) buffer->data(), 0, n); 298 } else if (mPrevSampleTimeUs - mStartTimeUs < kAutoRampStartUs + kAutoRampDurationUs) { 299 int32_t autoRampDurationFrames = 300 (kAutoRampDurationUs * sampleRate + 500000LL) / 1000000LL; 301 302 int32_t autoRampStartFrames = 303 (kAutoRampStartUs * sampleRate + 500000LL) / 1000000LL; 304 305 int32_t nFrames = numFramesRecorded - autoRampStartFrames; 306 rampVolume(nFrames, autoRampDurationFrames, (uint8_t *) buffer->data(), n); 307 } 308 if (mTrackMaxAmplitude) { 309 trackMaxAmplitude((int16_t *) buffer->data(), n >> 1); 310 } 311 312 buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs); 313 CHECK(timestampUs > mPrevSampleTimeUs); 314 mPrevSampleTimeUs = timestampUs; 315 LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld", 316 mStartTimeUs, sampleRate, timestampUs); 317 318 buffer->set_range(0, n); 319 320 *out = buffer; 321 return OK; 322 } 323 324 return OK; 325} 326 327void AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) { 328 for (int i = nSamples; i > 0; --i) { 329 int16_t value = *data++; 330 if (value < 0) { 331 value = -value; 332 } 333 if (mMaxAmplitude < value) { 334 mMaxAmplitude = value; 335 } 336 } 337} 338 339int16_t AudioSource::getMaxAmplitude() { 340 // First call activates the tracking. 341 if (!mTrackMaxAmplitude) { 342 mTrackMaxAmplitude = true; 343 } 344 int16_t value = mMaxAmplitude; 345 mMaxAmplitude = 0; 346 LOGV("max amplitude since last call: %d", value); 347 return value; 348} 349 350} // namespace android 351