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