AudioRecord.cpp revision f5879c1448cc6aebc51b26d3ec2399d66144f8f4
1/* 2** 3** Copyright 2008, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18//#define LOG_NDEBUG 0 19#define LOG_TAG "AudioRecord" 20 21#include <stdint.h> 22#include <sys/types.h> 23 24#include <sched.h> 25#include <sys/resource.h> 26 27#include <private/media/AudioTrackShared.h> 28 29#include <media/AudioSystem.h> 30#include <media/AudioRecord.h> 31 32#include <utils/IServiceManager.h> 33#include <utils/Log.h> 34#include <utils/MemoryDealer.h> 35#include <utils/Parcel.h> 36#include <utils/IPCThreadState.h> 37#include <utils/Timers.h> 38#include <cutils/atomic.h> 39 40#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) 41#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) 42 43namespace android { 44 45// --------------------------------------------------------------------------- 46 47AudioRecord::AudioRecord() 48 : mStatus(NO_INIT) 49{ 50} 51 52AudioRecord::AudioRecord( 53 int inputSource, 54 uint32_t sampleRate, 55 int format, 56 int channelCount, 57 int frameCount, 58 uint32_t flags, 59 callback_t cbf, 60 void* user, 61 int notificationFrames) 62 : mStatus(NO_INIT) 63{ 64 mStatus = set(inputSource, sampleRate, format, channelCount, 65 frameCount, flags, cbf, user, notificationFrames); 66} 67 68AudioRecord::~AudioRecord() 69{ 70 if (mStatus == NO_ERROR) { 71 // Make sure that callback function exits in the case where 72 // it is looping on buffer empty condition in obtainBuffer(). 73 // Otherwise the callback thread will never exit. 74 stop(); 75 if (mClientRecordThread != 0) { 76 mClientRecordThread->requestExitAndWait(); 77 mClientRecordThread.clear(); 78 } 79 mAudioRecord.clear(); 80 IPCThreadState::self()->flushCommands(); 81 } 82} 83 84status_t AudioRecord::set( 85 int inputSource, 86 uint32_t sampleRate, 87 int format, 88 int channelCount, 89 int frameCount, 90 uint32_t flags, 91 callback_t cbf, 92 void* user, 93 int notificationFrames, 94 bool threadCanCallJava) 95{ 96 97 LOGV("set(): sampleRate %d, channelCount %d, frameCount %d",sampleRate, channelCount, frameCount); 98 if (mAudioRecord != 0) { 99 return INVALID_OPERATION; 100 } 101 102 const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger(); 103 if (audioFlinger == 0) { 104 return NO_INIT; 105 } 106 107 if (inputSource == DEFAULT_INPUT) { 108 inputSource = MIC_INPUT; 109 } 110 111 if (sampleRate == 0) { 112 sampleRate = DEFAULT_SAMPLE_RATE; 113 } 114 // these below should probably come from the audioFlinger too... 115 if (format == 0) { 116 format = AudioSystem::PCM_16_BIT; 117 } 118 if (channelCount == 0) { 119 channelCount = 1; 120 } 121 122 // validate parameters 123 if (format != AudioSystem::PCM_16_BIT) { 124 return BAD_VALUE; 125 } 126 if (channelCount != 1 && channelCount != 2) { 127 return BAD_VALUE; 128 } 129 130 // validate framecount 131 size_t inputBuffSizeInBytes = -1; 132 if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &inputBuffSizeInBytes) 133 != NO_ERROR) { 134 LOGE("AudioSystem could not query the input buffer size."); 135 return NO_INIT; 136 } 137 if (inputBuffSizeInBytes == 0) { 138 LOGE("Recording parameters are not supported: sampleRate %d, channelCount %d, format %d", 139 sampleRate, channelCount, format); 140 return BAD_VALUE; 141 } 142 int frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1); 143 144 // We use 2* size of input buffer for ping pong use of record buffer. 145 int minFrameCount = 2 * inputBuffSizeInBytes / frameSizeInBytes; 146 LOGV("AudioRecord::set() minFrameCount = %d", minFrameCount); 147 148 if (frameCount == 0) { 149 frameCount = minFrameCount; 150 } else if (frameCount < minFrameCount) { 151 return BAD_VALUE; 152 } 153 154 if (notificationFrames == 0) { 155 notificationFrames = frameCount/2; 156 } 157 158 // open record channel 159 status_t status; 160 sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), inputSource, 161 sampleRate, format, 162 channelCount, 163 frameCount, 164 ((uint16_t)flags) << 16, 165 &status); 166 if (record == 0) { 167 LOGE("AudioFlinger could not create record track, status: %d", status); 168 return status; 169 } 170 sp<IMemory> cblk = record->getCblk(); 171 if (cblk == 0) { 172 return NO_INIT; 173 } 174 if (cbf != 0) { 175 mClientRecordThread = new ClientRecordThread(*this, threadCanCallJava); 176 if (mClientRecordThread == 0) { 177 return NO_INIT; 178 } 179 } 180 181 mStatus = NO_ERROR; 182 183 mAudioRecord = record; 184 mCblkMemory = cblk; 185 mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer()); 186 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); 187 mCblk->out = 0; 188 mSampleRate = sampleRate; 189 mFormat = format; 190 // Update buffer size in case it has been limited by AudioFlinger during track creation 191 mFrameCount = mCblk->frameCount; 192 mChannelCount = channelCount; 193 mActive = 0; 194 mCbf = cbf; 195 mNotificationFrames = notificationFrames; 196 mRemainingFrames = notificationFrames; 197 mUserData = user; 198 // TODO: add audio hardware input latency here 199 mLatency = (1000*mFrameCount) / mSampleRate; 200 mMarkerPosition = 0; 201 mMarkerReached = false; 202 mNewPosition = 0; 203 mUpdatePeriod = 0; 204 mInputSource = (uint8_t)inputSource; 205 206 return NO_ERROR; 207} 208 209status_t AudioRecord::initCheck() const 210{ 211 return mStatus; 212} 213 214// ------------------------------------------------------------------------- 215 216uint32_t AudioRecord::latency() const 217{ 218 return mLatency; 219} 220 221uint32_t AudioRecord::sampleRate() const 222{ 223 return mSampleRate; 224} 225 226int AudioRecord::format() const 227{ 228 return mFormat; 229} 230 231int AudioRecord::channelCount() const 232{ 233 return mChannelCount; 234} 235 236uint32_t AudioRecord::frameCount() const 237{ 238 return mFrameCount; 239} 240 241int AudioRecord::frameSize() const 242{ 243 return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t)); 244} 245 246int AudioRecord::inputSource() const 247{ 248 return (int)mInputSource; 249} 250 251// ------------------------------------------------------------------------- 252 253status_t AudioRecord::start() 254{ 255 status_t ret = NO_ERROR; 256 sp<ClientRecordThread> t = mClientRecordThread; 257 258 LOGV("start"); 259 260 if (t != 0) { 261 if (t->exitPending()) { 262 if (t->requestExitAndWait() == WOULD_BLOCK) { 263 LOGE("AudioRecord::start called from thread"); 264 return WOULD_BLOCK; 265 } 266 } 267 t->mLock.lock(); 268 } 269 270 if (android_atomic_or(1, &mActive) == 0) { 271 mNewPosition = mCblk->user + mUpdatePeriod; 272 mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; 273 mCblk->waitTimeMs = 0; 274 if (t != 0) { 275 t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT); 276 } else { 277 setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT); 278 } 279 ret = mAudioRecord->start(); 280 } 281 282 if (t != 0) { 283 t->mLock.unlock(); 284 } 285 286 return ret; 287} 288 289status_t AudioRecord::stop() 290{ 291 sp<ClientRecordThread> t = mClientRecordThread; 292 293 LOGV("stop"); 294 295 if (t != 0) { 296 t->mLock.lock(); 297 } 298 299 if (android_atomic_and(~1, &mActive) == 1) { 300 mCblk->cv.signal(); 301 mAudioRecord->stop(); 302 // the record head position will reset to 0, so if a marker is set, we need 303 // to activate it again 304 mMarkerReached = false; 305 if (t != 0) { 306 t->requestExit(); 307 } else { 308 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL); 309 } 310 } 311 312 if (t != 0) { 313 t->mLock.unlock(); 314 } 315 316 return NO_ERROR; 317} 318 319bool AudioRecord::stopped() const 320{ 321 return !mActive; 322} 323 324status_t AudioRecord::setMarkerPosition(uint32_t marker) 325{ 326 if (mCbf == 0) return INVALID_OPERATION; 327 328 mMarkerPosition = marker; 329 mMarkerReached = false; 330 331 return NO_ERROR; 332} 333 334status_t AudioRecord::getMarkerPosition(uint32_t *marker) 335{ 336 if (marker == 0) return BAD_VALUE; 337 338 *marker = mMarkerPosition; 339 340 return NO_ERROR; 341} 342 343status_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod) 344{ 345 if (mCbf == 0) return INVALID_OPERATION; 346 347 uint32_t curPosition; 348 getPosition(&curPosition); 349 mNewPosition = curPosition + updatePeriod; 350 mUpdatePeriod = updatePeriod; 351 352 return NO_ERROR; 353} 354 355status_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) 356{ 357 if (updatePeriod == 0) return BAD_VALUE; 358 359 *updatePeriod = mUpdatePeriod; 360 361 return NO_ERROR; 362} 363 364status_t AudioRecord::getPosition(uint32_t *position) 365{ 366 if (position == 0) return BAD_VALUE; 367 368 *position = mCblk->user; 369 370 return NO_ERROR; 371} 372 373 374// ------------------------------------------------------------------------- 375 376status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) 377{ 378 int active; 379 int timeout = 0; 380 status_t result; 381 audio_track_cblk_t* cblk = mCblk; 382 uint32_t framesReq = audioBuffer->frameCount; 383 uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS; 384 385 audioBuffer->frameCount = 0; 386 audioBuffer->size = 0; 387 388 uint32_t framesReady = cblk->framesReady(); 389 390 if (framesReady == 0) { 391 Mutex::Autolock _l(cblk->lock); 392 goto start_loop_here; 393 while (framesReady == 0) { 394 active = mActive; 395 if (UNLIKELY(!active)) 396 return NO_MORE_BUFFERS; 397 if (UNLIKELY(!waitCount)) 398 return WOULD_BLOCK; 399 timeout = 0; 400 result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); 401 if (__builtin_expect(result!=NO_ERROR, false)) { 402 cblk->waitTimeMs += waitTimeMs; 403 if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) { 404 LOGW( "obtainBuffer timed out (is the CPU pegged?) " 405 "user=%08x, server=%08x", cblk->user, cblk->server); 406 timeout = 1; 407 cblk->waitTimeMs = 0; 408 } 409 if (--waitCount == 0) { 410 return TIMED_OUT; 411 } 412 } 413 // read the server count again 414 start_loop_here: 415 framesReady = cblk->framesReady(); 416 } 417 } 418 419 LOGW_IF(timeout, 420 "*** SERIOUS WARNING *** obtainBuffer() timed out " 421 "but didn't need to be locked. We recovered, but " 422 "this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server); 423 424 cblk->waitTimeMs = 0; 425 426 if (framesReq > framesReady) { 427 framesReq = framesReady; 428 } 429 430 uint32_t u = cblk->user; 431 uint32_t bufferEnd = cblk->userBase + cblk->frameCount; 432 433 if (u + framesReq > bufferEnd) { 434 framesReq = bufferEnd - u; 435 } 436 437 audioBuffer->flags = 0; 438 audioBuffer->channelCount= mChannelCount; 439 audioBuffer->format = mFormat; 440 audioBuffer->frameCount = framesReq; 441 audioBuffer->size = framesReq*mChannelCount*sizeof(int16_t); 442 audioBuffer->raw = (int8_t*)cblk->buffer(u); 443 active = mActive; 444 return active ? status_t(NO_ERROR) : status_t(STOPPED); 445} 446 447void AudioRecord::releaseBuffer(Buffer* audioBuffer) 448{ 449 audio_track_cblk_t* cblk = mCblk; 450 cblk->stepUser(audioBuffer->frameCount); 451} 452 453// ------------------------------------------------------------------------- 454 455ssize_t AudioRecord::read(void* buffer, size_t userSize) 456{ 457 ssize_t read = 0; 458 Buffer audioBuffer; 459 int8_t *dst = static_cast<int8_t*>(buffer); 460 461 if (ssize_t(userSize) < 0) { 462 // sanity-check. user is most-likely passing an error code. 463 LOGE("AudioRecord::read(buffer=%p, size=%u (%d)", 464 buffer, userSize, userSize); 465 return BAD_VALUE; 466 } 467 468 LOGV("read size: %d", userSize); 469 470 do { 471 472 audioBuffer.frameCount = userSize/mChannelCount/sizeof(int16_t); 473 474 // Calling obtainBuffer() with a negative wait count causes 475 // an (almost) infinite wait time. 476 status_t err = obtainBuffer(&audioBuffer, -1); 477 if (err < 0) { 478 // out of buffers, return #bytes written 479 if (err == status_t(NO_MORE_BUFFERS)) 480 break; 481 return ssize_t(err); 482 } 483 484 size_t bytesRead = audioBuffer.size; 485 memcpy(dst, audioBuffer.i8, bytesRead); 486 487 dst += bytesRead; 488 userSize -= bytesRead; 489 read += bytesRead; 490 491 releaseBuffer(&audioBuffer); 492 } while (userSize); 493 494 return read; 495} 496 497// ------------------------------------------------------------------------- 498 499bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread) 500{ 501 Buffer audioBuffer; 502 uint32_t frames = mRemainingFrames; 503 size_t readSize; 504 505 // Manage marker callback 506 if (!mMarkerReached && (mMarkerPosition > 0)) { 507 if (mCblk->user >= mMarkerPosition) { 508 mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition); 509 mMarkerReached = true; 510 } 511 } 512 513 // Manage new position callback 514 if (mUpdatePeriod > 0) { 515 while (mCblk->user >= mNewPosition) { 516 mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition); 517 mNewPosition += mUpdatePeriod; 518 } 519 } 520 521 do { 522 audioBuffer.frameCount = frames; 523 // Calling obtainBuffer() with a wait count of 1 524 // limits wait time to WAIT_PERIOD_MS. This prevents from being 525 // stuck here not being able to handle timed events (position, markers). 526 status_t err = obtainBuffer(&audioBuffer, 1); 527 if (err < NO_ERROR) { 528 if (err != TIMED_OUT) { 529 LOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up."); 530 return false; 531 } 532 break; 533 } 534 if (err == status_t(STOPPED)) return false; 535 536 size_t reqSize = audioBuffer.size; 537 mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer); 538 readSize = audioBuffer.size; 539 540 // Sanity check on returned size 541 if (ssize_t(readSize) <= 0) { 542 // The callback is done filling buffers 543 // Keep this thread going to handle timed events and 544 // still try to get more data in intervals of WAIT_PERIOD_MS 545 // but don't just loop and block the CPU, so wait 546 usleep(WAIT_PERIOD_MS*1000); 547 break; 548 } 549 if (readSize > reqSize) readSize = reqSize; 550 551 audioBuffer.size = readSize; 552 audioBuffer.frameCount = readSize/mChannelCount/sizeof(int16_t); 553 frames -= audioBuffer.frameCount; 554 555 releaseBuffer(&audioBuffer); 556 557 } while (frames); 558 559 560 // Manage overrun callback 561 if (mActive && (mCblk->framesAvailable_l() == 0)) { 562 LOGV("Overrun user: %x, server: %x, flowControlFlag %d", mCblk->user, mCblk->server, mCblk->flowControlFlag); 563 if (mCblk->flowControlFlag == 0) { 564 mCbf(EVENT_OVERRUN, mUserData, 0); 565 mCblk->flowControlFlag = 1; 566 } 567 } 568 569 if (frames == 0) { 570 mRemainingFrames = mNotificationFrames; 571 } else { 572 mRemainingFrames = frames; 573 } 574 return true; 575} 576 577// ========================================================================= 578 579AudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver, bool bCanCallJava) 580 : Thread(bCanCallJava), mReceiver(receiver) 581{ 582} 583 584bool AudioRecord::ClientRecordThread::threadLoop() 585{ 586 return mReceiver.processAudioBuffer(this); 587} 588 589// ------------------------------------------------------------------------- 590 591}; // namespace android 592 593