• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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