AudioSource.cpp revision e49f2b424318aa8e830e7a1338e5e32ab82992f9
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/AudioRecord.h> 22#include <media/stagefright/AudioSource.h> 23#include <media/stagefright/MediaBuffer.h> 24#include <media/stagefright/MediaDefs.h> 25#include <media/stagefright/MetaData.h> 26#include <media/stagefright/foundation/ADebug.h> 27#include <cutils/properties.h> 28#include <stdlib.h> 29 30namespace android { 31 32static void AudioRecordCallbackFunction(int event, void *user, void *info) { 33 AudioSource *source = (AudioSource *) user; 34 switch (event) { 35 case AudioRecord::EVENT_MORE_DATA: { 36 source->dataCallbackTimestamp(*((AudioRecord::Buffer *) info), systemTime() / 1000); 37 break; 38 } 39 case AudioRecord::EVENT_OVERRUN: { 40 ALOGW("AudioRecord reported overrun!"); 41 break; 42 } 43 default: 44 // does nothing 45 break; 46 } 47} 48 49AudioSource::AudioSource( 50 audio_source_t inputSource, uint32_t sampleRate, uint32_t channelCount) 51 : mStarted(false), 52 mSampleRate(sampleRate), 53 mPrevSampleTimeUs(0), 54 mNumFramesReceived(0), 55 mNumClientOwnedBuffers(0) { 56 57 ALOGV("sampleRate: %d, channelCount: %d", sampleRate, channelCount); 58 CHECK(channelCount == 1 || channelCount == 2); 59 60 int minFrameCount; 61 status_t status = AudioRecord::getMinFrameCount(&minFrameCount, 62 sampleRate, 63 AUDIO_FORMAT_PCM_16_BIT, 64 channelCount); 65 if (status == OK) { 66 // make sure that the AudioRecord callback never returns more than the maximum 67 // buffer size 68 int frameCount = kMaxBufferSize / sizeof(int16_t) / channelCount; 69 70 // make sure that the AudioRecord total buffer size is large enough 71 int bufCount = 2; 72 while ((bufCount * frameCount) < minFrameCount) { 73 bufCount++; 74 } 75 76 AudioRecord::record_flags flags = (AudioRecord::record_flags) 77 (AudioRecord::RECORD_AGC_ENABLE | 78 AudioRecord::RECORD_NS_ENABLE | 79 AudioRecord::RECORD_IIR_ENABLE); 80 mRecord = new AudioRecord( 81 inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT, 82 audio_channel_in_mask_from_count(channelCount), 83 bufCount * frameCount, 84 flags, 85 AudioRecordCallbackFunction, 86 this, 87 frameCount); 88 mInitCheck = mRecord->initCheck(); 89 } else { 90 mInitCheck = status; 91 } 92} 93 94AudioSource::~AudioSource() { 95 if (mStarted) { 96 reset(); 97 } 98 99 delete mRecord; 100 mRecord = NULL; 101} 102 103status_t AudioSource::initCheck() const { 104 return mInitCheck; 105} 106 107status_t AudioSource::start(MetaData *params) { 108 Mutex::Autolock autoLock(mLock); 109 if (mStarted) { 110 return UNKNOWN_ERROR; 111 } 112 113 if (mInitCheck != OK) { 114 return NO_INIT; 115 } 116 117 mTrackMaxAmplitude = false; 118 mMaxAmplitude = 0; 119 mInitialReadTimeUs = 0; 120 mStartTimeUs = 0; 121 int64_t startTimeUs; 122 if (params && params->findInt64(kKeyTime, &startTimeUs)) { 123 mStartTimeUs = startTimeUs; 124 } 125 status_t err = mRecord->start(); 126 if (err == OK) { 127 mStarted = true; 128 } else { 129 delete mRecord; 130 mRecord = NULL; 131 } 132 133 134 return err; 135} 136 137void AudioSource::releaseQueuedFrames_l() { 138 ALOGV("releaseQueuedFrames_l"); 139 List<MediaBuffer *>::iterator it; 140 while (!mBuffersReceived.empty()) { 141 it = mBuffersReceived.begin(); 142 (*it)->release(); 143 mBuffersReceived.erase(it); 144 } 145} 146 147void AudioSource::waitOutstandingEncodingFrames_l() { 148 ALOGV("waitOutstandingEncodingFrames_l: %lld", mNumClientOwnedBuffers); 149 while (mNumClientOwnedBuffers > 0) { 150 mFrameEncodingCompletionCondition.wait(mLock); 151 } 152} 153 154status_t AudioSource::reset() { 155 Mutex::Autolock autoLock(mLock); 156 if (!mStarted) { 157 return UNKNOWN_ERROR; 158 } 159 160 if (mInitCheck != OK) { 161 return NO_INIT; 162 } 163 164 mStarted = false; 165 mRecord->stop(); 166 waitOutstandingEncodingFrames_l(); 167 releaseQueuedFrames_l(); 168 169 return OK; 170} 171 172sp<MetaData> AudioSource::getFormat() { 173 Mutex::Autolock autoLock(mLock); 174 if (mInitCheck != OK) { 175 return 0; 176 } 177 178 sp<MetaData> meta = new MetaData; 179 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); 180 meta->setInt32(kKeySampleRate, mSampleRate); 181 meta->setInt32(kKeyChannelCount, mRecord->channelCount()); 182 meta->setInt32(kKeyMaxInputSize, kMaxBufferSize); 183 184 return meta; 185} 186 187void AudioSource::rampVolume( 188 int32_t startFrame, int32_t rampDurationFrames, 189 uint8_t *data, size_t bytes) { 190 191 const int32_t kShift = 14; 192 int32_t fixedMultiplier = (startFrame << kShift) / rampDurationFrames; 193 const int32_t nChannels = mRecord->channelCount(); 194 int32_t stopFrame = startFrame + bytes / sizeof(int16_t); 195 int16_t *frame = (int16_t *) data; 196 if (stopFrame > rampDurationFrames) { 197 stopFrame = rampDurationFrames; 198 } 199 200 while (startFrame < stopFrame) { 201 if (nChannels == 1) { // mono 202 frame[0] = (frame[0] * fixedMultiplier) >> kShift; 203 ++frame; 204 ++startFrame; 205 } else { // stereo 206 frame[0] = (frame[0] * fixedMultiplier) >> kShift; 207 frame[1] = (frame[1] * fixedMultiplier) >> kShift; 208 frame += 2; 209 startFrame += 2; 210 } 211 212 // Update the multiplier every 4 frames 213 if ((startFrame & 3) == 0) { 214 fixedMultiplier = (startFrame << kShift) / rampDurationFrames; 215 } 216 } 217} 218 219status_t AudioSource::read( 220 MediaBuffer **out, const ReadOptions *options) { 221 Mutex::Autolock autoLock(mLock); 222 *out = NULL; 223 224 if (mInitCheck != OK) { 225 return NO_INIT; 226 } 227 228 while (mStarted && mBuffersReceived.empty()) { 229 mFrameAvailableCondition.wait(mLock); 230 } 231 if (!mStarted) { 232 return OK; 233 } 234 MediaBuffer *buffer = *mBuffersReceived.begin(); 235 mBuffersReceived.erase(mBuffersReceived.begin()); 236 ++mNumClientOwnedBuffers; 237 buffer->setObserver(this); 238 buffer->add_ref(); 239 240 // Mute/suppress the recording sound 241 int64_t timeUs; 242 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs)); 243 int64_t elapsedTimeUs = timeUs - mStartTimeUs; 244 if (elapsedTimeUs < kAutoRampStartUs) { 245 memset((uint8_t *) buffer->data(), 0, buffer->range_length()); 246 } else if (elapsedTimeUs < kAutoRampStartUs + kAutoRampDurationUs) { 247 int32_t autoRampDurationFrames = 248 (kAutoRampDurationUs * mSampleRate + 500000LL) / 1000000LL; 249 250 int32_t autoRampStartFrames = 251 (kAutoRampStartUs * mSampleRate + 500000LL) / 1000000LL; 252 253 int32_t nFrames = mNumFramesReceived - autoRampStartFrames; 254 rampVolume(nFrames, autoRampDurationFrames, 255 (uint8_t *) buffer->data(), buffer->range_length()); 256 } 257 258 // Track the max recording signal amplitude. 259 if (mTrackMaxAmplitude) { 260 trackMaxAmplitude( 261 (int16_t *) buffer->data(), buffer->range_length() >> 1); 262 } 263 264 *out = buffer; 265 return OK; 266} 267 268void AudioSource::signalBufferReturned(MediaBuffer *buffer) { 269 ALOGV("signalBufferReturned: %p", buffer->data()); 270 Mutex::Autolock autoLock(mLock); 271 --mNumClientOwnedBuffers; 272 buffer->setObserver(0); 273 buffer->release(); 274 mFrameEncodingCompletionCondition.signal(); 275 return; 276} 277 278status_t AudioSource::dataCallbackTimestamp( 279 const AudioRecord::Buffer& audioBuffer, int64_t timeUs) { 280 ALOGV("dataCallbackTimestamp: %lld us", timeUs); 281 Mutex::Autolock autoLock(mLock); 282 if (!mStarted) { 283 ALOGW("Spurious callback from AudioRecord. Drop the audio data."); 284 return OK; 285 } 286 287 // Drop retrieved and previously lost audio data. 288 if (mNumFramesReceived == 0 && timeUs < mStartTimeUs) { 289 mRecord->getInputFramesLost(); 290 ALOGV("Drop audio data at %lld/%lld us", timeUs, mStartTimeUs); 291 return OK; 292 } 293 294 if (mNumFramesReceived == 0 && mPrevSampleTimeUs == 0) { 295 mInitialReadTimeUs = timeUs; 296 // Initial delay 297 if (mStartTimeUs > 0) { 298 mStartTimeUs = timeUs - mStartTimeUs; 299 } else { 300 // Assume latency is constant. 301 mStartTimeUs += mRecord->latency() * 1000; 302 } 303 mPrevSampleTimeUs = mStartTimeUs; 304 } 305 306 size_t numLostBytes = 0; 307 if (mNumFramesReceived > 0) { // Ignore earlier frame lost 308 // getInputFramesLost() returns the number of lost frames. 309 // Convert number of frames lost to number of bytes lost. 310 numLostBytes = mRecord->getInputFramesLost() * mRecord->frameSize(); 311 } 312 313 CHECK_EQ(numLostBytes & 1, 0u); 314 CHECK_EQ(audioBuffer.size & 1, 0u); 315 if (numLostBytes > 0) { 316 // Loss of audio frames should happen rarely; thus the LOGW should 317 // not cause a logging spam 318 ALOGW("Lost audio record data: %d bytes", numLostBytes); 319 } 320 321 while (numLostBytes > 0) { 322 size_t bufferSize = numLostBytes; 323 if (numLostBytes > kMaxBufferSize) { 324 numLostBytes -= kMaxBufferSize; 325 bufferSize = kMaxBufferSize; 326 } else { 327 numLostBytes = 0; 328 } 329 MediaBuffer *lostAudioBuffer = new MediaBuffer(bufferSize); 330 memset(lostAudioBuffer->data(), 0, bufferSize); 331 lostAudioBuffer->set_range(0, bufferSize); 332 queueInputBuffer_l(lostAudioBuffer, timeUs); 333 } 334 335 if (audioBuffer.size == 0) { 336 ALOGW("Nothing is available from AudioRecord callback buffer"); 337 return OK; 338 } 339 340 const size_t bufferSize = audioBuffer.size; 341 MediaBuffer *buffer = new MediaBuffer(bufferSize); 342 memcpy((uint8_t *) buffer->data(), 343 audioBuffer.i16, audioBuffer.size); 344 buffer->set_range(0, bufferSize); 345 queueInputBuffer_l(buffer, timeUs); 346 return OK; 347} 348 349void AudioSource::queueInputBuffer_l(MediaBuffer *buffer, int64_t timeUs) { 350 const size_t bufferSize = buffer->range_length(); 351 const size_t frameSize = mRecord->frameSize(); 352 const int64_t timestampUs = 353 mPrevSampleTimeUs + 354 ((1000000LL * (bufferSize / frameSize)) + 355 (mSampleRate >> 1)) / mSampleRate; 356 357 if (mNumFramesReceived == 0) { 358 buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs); 359 } 360 361 buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs); 362 buffer->meta_data()->setInt64(kKeyDriftTime, timeUs - mInitialReadTimeUs); 363 mPrevSampleTimeUs = timestampUs; 364 mNumFramesReceived += bufferSize / frameSize; 365 mBuffersReceived.push_back(buffer); 366 mFrameAvailableCondition.signal(); 367} 368 369void AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) { 370 for (int i = nSamples; i > 0; --i) { 371 int16_t value = *data++; 372 if (value < 0) { 373 value = -value; 374 } 375 if (mMaxAmplitude < value) { 376 mMaxAmplitude = value; 377 } 378 } 379} 380 381int16_t AudioSource::getMaxAmplitude() { 382 // First call activates the tracking. 383 if (!mTrackMaxAmplitude) { 384 mTrackMaxAmplitude = true; 385 } 386 int16_t value = mMaxAmplitude; 387 mMaxAmplitude = 0; 388 ALOGV("max amplitude since last call: %d", value); 389 return value; 390} 391 392} // namespace android 393