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