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