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