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
43 namespace android {
44 // ---------------------------------------------------------------------------
45
46 // static
getMinFrameCount(int * frameCount,uint32_t sampleRate,int format,int channelCount)47 status_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
AudioRecord()79 AudioRecord::AudioRecord()
80 : mStatus(NO_INIT), mSessionId(0)
81 {
82 }
83
AudioRecord(int inputSource,uint32_t sampleRate,int format,uint32_t channels,int frameCount,uint32_t flags,callback_t cbf,void * user,int notificationFrames,int sessionId)84 AudioRecord::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
~AudioRecord()101 AudioRecord::~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
set(int inputSource,uint32_t sampleRate,int format,uint32_t channels,int frameCount,uint32_t flags,callback_t cbf,void * user,int notificationFrames,bool threadCanCallJava,int sessionId)117 status_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
initCheck() const225 status_t AudioRecord::initCheck() const
226 {
227 return mStatus;
228 }
229
230 // -------------------------------------------------------------------------
231
latency() const232 uint32_t AudioRecord::latency() const
233 {
234 return mLatency;
235 }
236
format() const237 int AudioRecord::format() const
238 {
239 return mFormat;
240 }
241
channelCount() const242 int AudioRecord::channelCount() const
243 {
244 return mChannelCount;
245 }
246
frameCount() const247 uint32_t AudioRecord::frameCount() const
248 {
249 return mFrameCount;
250 }
251
frameSize() const252 int 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
inputSource() const261 int AudioRecord::inputSource() const
262 {
263 return (int)mInputSource;
264 }
265
266 // -------------------------------------------------------------------------
267
start()268 status_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
stop()317 status_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
stopped() const347 bool AudioRecord::stopped() const
348 {
349 return !mActive;
350 }
351
getSampleRate()352 uint32_t AudioRecord::getSampleRate()
353 {
354 return mCblk->sampleRate;
355 }
356
setMarkerPosition(uint32_t marker)357 status_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
getMarkerPosition(uint32_t * marker)367 status_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
setPositionUpdatePeriod(uint32_t updatePeriod)376 status_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
getPositionUpdatePeriod(uint32_t * updatePeriod)388 status_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
getPosition(uint32_t * position)397 status_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
getInputFramesLost()406 unsigned int AudioRecord::getInputFramesLost()
407 {
408 if (mActive)
409 return AudioSystem::getInputFramesLost(mInput);
410 else
411 return 0;
412 }
413
414 // -------------------------------------------------------------------------
415
openRecord(uint32_t sampleRate,int format,int channelCount,int frameCount,uint32_t flags,audio_io_handle_t input)416 status_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
obtainBuffer(Buffer * audioBuffer,int32_t waitCount)458 status_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
releaseBuffer(Buffer * audioBuffer)539 void AudioRecord::releaseBuffer(Buffer* audioBuffer)
540 {
541 audio_track_cblk_t* cblk = mCblk;
542 cblk->stepUser(audioBuffer->frameCount);
543 }
544
getInput()545 audio_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
getSessionId()554 int AudioRecord::getSessionId()
555 {
556 return mSessionId;
557 }
558
559 // -------------------------------------------------------------------------
560
read(void * buffer,size_t userSize)561 ssize_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
processAudioBuffer(const sp<ClientRecordThread> & thread)608 bool 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
ClientRecordThread(AudioRecord & receiver,bool bCanCallJava)688 AudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver, bool bCanCallJava)
689 : Thread(bCanCallJava), mReceiver(receiver)
690 {
691 }
692
threadLoop()693 bool AudioRecord::ClientRecordThread::threadLoop()
694 {
695 return mReceiver.processAudioBuffer(this);
696 }
697
698 // -------------------------------------------------------------------------
699
700 }; // namespace android
701
702