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