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