AudioSource.cpp revision b44c9d2bdc0d5b9cb03254022a58e017b516e9e6
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 channels) 51 : mStarted(false), 52 mSampleRate(sampleRate), 53 mPrevSampleTimeUs(0), 54 mNumFramesReceived(0), 55 mNumClientOwnedBuffers(0) { 56 57 ALOGV("sampleRate: %d, channels: %d", sampleRate, channels); 58 CHECK(channels == 1 || channels == 2); 59 uint32_t flags = AudioRecord::RECORD_AGC_ENABLE | 60 AudioRecord::RECORD_NS_ENABLE | 61 AudioRecord::RECORD_IIR_ENABLE; 62 mRecord = new AudioRecord( 63 inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT, 64 channels > 1? AUDIO_CHANNEL_IN_STEREO: AUDIO_CHANNEL_IN_MONO, 65 4 * kMaxBufferSize / sizeof(int16_t), /* Enable ping-pong buffers */ 66 flags, 67 AudioRecordCallbackFunction, 68 this); 69 70 mInitCheck = mRecord->initCheck(); 71} 72 73AudioSource::~AudioSource() { 74 if (mStarted) { 75 reset(); 76 } 77 78 delete mRecord; 79 mRecord = NULL; 80} 81 82status_t AudioSource::initCheck() const { 83 return mInitCheck; 84} 85 86status_t AudioSource::start(MetaData *params) { 87 Mutex::Autolock autoLock(mLock); 88 if (mStarted) { 89 return UNKNOWN_ERROR; 90 } 91 92 if (mInitCheck != OK) { 93 return NO_INIT; 94 } 95 96 mTrackMaxAmplitude = false; 97 mMaxAmplitude = 0; 98 mInitialReadTimeUs = 0; 99 mStartTimeUs = 0; 100 int64_t startTimeUs; 101 if (params && params->findInt64(kKeyTime, &startTimeUs)) { 102 mStartTimeUs = startTimeUs; 103 } 104 status_t err = mRecord->start(); 105 if (err == OK) { 106 mStarted = true; 107 } else { 108 delete mRecord; 109 mRecord = NULL; 110 } 111 112 113 return err; 114} 115 116void AudioSource::releaseQueuedFrames_l() { 117 ALOGV("releaseQueuedFrames_l"); 118 List<MediaBuffer *>::iterator it; 119 while (!mBuffersReceived.empty()) { 120 it = mBuffersReceived.begin(); 121 (*it)->release(); 122 mBuffersReceived.erase(it); 123 } 124} 125 126void AudioSource::waitOutstandingEncodingFrames_l() { 127 ALOGV("waitOutstandingEncodingFrames_l: %lld", mNumClientOwnedBuffers); 128 while (mNumClientOwnedBuffers > 0) { 129 mFrameEncodingCompletionCondition.wait(mLock); 130 } 131} 132 133status_t AudioSource::reset() { 134 Mutex::Autolock autoLock(mLock); 135 if (!mStarted) { 136 return UNKNOWN_ERROR; 137 } 138 139 if (mInitCheck != OK) { 140 return NO_INIT; 141 } 142 143 mStarted = false; 144 mRecord->stop(); 145 waitOutstandingEncodingFrames_l(); 146 releaseQueuedFrames_l(); 147 148 return OK; 149} 150 151sp<MetaData> AudioSource::getFormat() { 152 Mutex::Autolock autoLock(mLock); 153 if (mInitCheck != OK) { 154 return 0; 155 } 156 157 sp<MetaData> meta = new MetaData; 158 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); 159 meta->setInt32(kKeySampleRate, mSampleRate); 160 meta->setInt32(kKeyChannelCount, mRecord->channelCount()); 161 meta->setInt32(kKeyMaxInputSize, kMaxBufferSize); 162 163 return meta; 164} 165 166void AudioSource::rampVolume( 167 int32_t startFrame, int32_t rampDurationFrames, 168 uint8_t *data, size_t bytes) { 169 170 const int32_t kShift = 14; 171 int32_t fixedMultiplier = (startFrame << kShift) / rampDurationFrames; 172 const int32_t nChannels = mRecord->channelCount(); 173 int32_t stopFrame = startFrame + bytes / sizeof(int16_t); 174 int16_t *frame = (int16_t *) data; 175 if (stopFrame > rampDurationFrames) { 176 stopFrame = rampDurationFrames; 177 } 178 179 while (startFrame < stopFrame) { 180 if (nChannels == 1) { // mono 181 frame[0] = (frame[0] * fixedMultiplier) >> kShift; 182 ++frame; 183 ++startFrame; 184 } else { // stereo 185 frame[0] = (frame[0] * fixedMultiplier) >> kShift; 186 frame[1] = (frame[1] * fixedMultiplier) >> kShift; 187 frame += 2; 188 startFrame += 2; 189 } 190 191 // Update the multiplier every 4 frames 192 if ((startFrame & 3) == 0) { 193 fixedMultiplier = (startFrame << kShift) / rampDurationFrames; 194 } 195 } 196} 197 198status_t AudioSource::read( 199 MediaBuffer **out, const ReadOptions *options) { 200 Mutex::Autolock autoLock(mLock); 201 *out = NULL; 202 203 if (mInitCheck != OK) { 204 return NO_INIT; 205 } 206 207 while (mStarted && mBuffersReceived.empty()) { 208 mFrameAvailableCondition.wait(mLock); 209 } 210 if (!mStarted) { 211 return OK; 212 } 213 MediaBuffer *buffer = *mBuffersReceived.begin(); 214 mBuffersReceived.erase(mBuffersReceived.begin()); 215 ++mNumClientOwnedBuffers; 216 buffer->setObserver(this); 217 buffer->add_ref(); 218 219 // Mute/suppress the recording sound 220 int64_t timeUs; 221 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs)); 222 int64_t elapsedTimeUs = timeUs - mStartTimeUs; 223 if (elapsedTimeUs < kAutoRampStartUs) { 224 memset((uint8_t *) buffer->data(), 0, buffer->range_length()); 225 } else if (elapsedTimeUs < kAutoRampStartUs + kAutoRampDurationUs) { 226 int32_t autoRampDurationFrames = 227 (kAutoRampDurationUs * mSampleRate + 500000LL) / 1000000LL; 228 229 int32_t autoRampStartFrames = 230 (kAutoRampStartUs * mSampleRate + 500000LL) / 1000000LL; 231 232 int32_t nFrames = mNumFramesReceived - autoRampStartFrames; 233 rampVolume(nFrames, autoRampDurationFrames, 234 (uint8_t *) buffer->data(), buffer->range_length()); 235 } 236 237 // Track the max recording signal amplitude. 238 if (mTrackMaxAmplitude) { 239 trackMaxAmplitude( 240 (int16_t *) buffer->data(), buffer->range_length() >> 1); 241 } 242 243 *out = buffer; 244 return OK; 245} 246 247void AudioSource::signalBufferReturned(MediaBuffer *buffer) { 248 ALOGV("signalBufferReturned: %p", buffer->data()); 249 Mutex::Autolock autoLock(mLock); 250 --mNumClientOwnedBuffers; 251 buffer->setObserver(0); 252 buffer->release(); 253 mFrameEncodingCompletionCondition.signal(); 254 return; 255} 256 257status_t AudioSource::dataCallbackTimestamp( 258 const AudioRecord::Buffer& audioBuffer, int64_t timeUs) { 259 ALOGV("dataCallbackTimestamp: %lld us", timeUs); 260 Mutex::Autolock autoLock(mLock); 261 if (!mStarted) { 262 ALOGW("Spurious callback from AudioRecord. Drop the audio data."); 263 return OK; 264 } 265 266 // Drop retrieved and previously lost audio data. 267 if (mNumFramesReceived == 0 && timeUs < mStartTimeUs) { 268 mRecord->getInputFramesLost(); 269 ALOGV("Drop audio data at %lld/%lld us", timeUs, mStartTimeUs); 270 return OK; 271 } 272 273 if (mNumFramesReceived == 0 && mPrevSampleTimeUs == 0) { 274 mInitialReadTimeUs = timeUs; 275 // Initial delay 276 if (mStartTimeUs > 0) { 277 mStartTimeUs = timeUs - mStartTimeUs; 278 } else { 279 // Assume latency is constant. 280 mStartTimeUs += mRecord->latency() * 1000; 281 } 282 mPrevSampleTimeUs = mStartTimeUs; 283 } 284 285 int64_t timestampUs = mPrevSampleTimeUs; 286 287 size_t numLostBytes = 0; 288 if (mNumFramesReceived > 0) { // Ignore earlier frame lost 289 // getInputFramesLost() returns the number of lost frames. 290 // Convert number of frames lost to number of bytes lost. 291 numLostBytes = mRecord->getInputFramesLost() * mRecord->frameSize(); 292 } 293 294 CHECK_EQ(numLostBytes & 1, 0u); 295 CHECK_EQ(audioBuffer.size & 1, 0u); 296 size_t bufferSize = numLostBytes + audioBuffer.size; 297 MediaBuffer *buffer = new MediaBuffer(bufferSize); 298 if (numLostBytes > 0) { 299 memset(buffer->data(), 0, numLostBytes); 300 memcpy((uint8_t *) buffer->data() + numLostBytes, 301 audioBuffer.i16, audioBuffer.size); 302 } else { 303 if (audioBuffer.size == 0) { 304 ALOGW("Nothing is available from AudioRecord callback buffer"); 305 buffer->release(); 306 return OK; 307 } 308 memcpy((uint8_t *) buffer->data(), 309 audioBuffer.i16, audioBuffer.size); 310 } 311 312 buffer->set_range(0, bufferSize); 313 timestampUs += ((1000000LL * (bufferSize >> 1)) + 314 (mSampleRate >> 1)) / mSampleRate; 315 316 if (mNumFramesReceived == 0) { 317 buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs); 318 } 319 buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs); 320 buffer->meta_data()->setInt64(kKeyDriftTime, timeUs - mInitialReadTimeUs); 321 mPrevSampleTimeUs = timestampUs; 322 mNumFramesReceived += buffer->range_length() / sizeof(int16_t); 323 mBuffersReceived.push_back(buffer); 324 mFrameAvailableCondition.signal(); 325 326 return OK; 327} 328 329void AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) { 330 for (int i = nSamples; i > 0; --i) { 331 int16_t value = *data++; 332 if (value < 0) { 333 value = -value; 334 } 335 if (mMaxAmplitude < value) { 336 mMaxAmplitude = value; 337 } 338 } 339} 340 341int16_t AudioSource::getMaxAmplitude() { 342 // First call activates the tracking. 343 if (!mTrackMaxAmplitude) { 344 mTrackMaxAmplitude = true; 345 } 346 int16_t value = mMaxAmplitude; 347 mMaxAmplitude = 0; 348 ALOGV("max amplitude since last call: %d", value); 349 return value; 350} 351 352} // namespace android 353