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