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