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