AudioRecord.cpp revision 88335b1a749fe0157547907a2ce6c9632f4d2592
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    mInput = input;
203
204    return NO_ERROR;
205}
206
207status_t AudioRecord::initCheck() const
208{
209    return mStatus;
210}
211
212// -------------------------------------------------------------------------
213
214uint32_t AudioRecord::latency() const
215{
216    return mLatency;
217}
218
219int AudioRecord::format() const
220{
221    return mFormat;
222}
223
224int AudioRecord::channelCount() const
225{
226    return mChannelCount;
227}
228
229uint32_t AudioRecord::frameCount() const
230{
231    return mFrameCount;
232}
233
234int AudioRecord::frameSize() const
235{
236    if (AudioSystem::isLinearPCM(mFormat)) {
237        return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
238    } else {
239        return sizeof(uint8_t);
240    }
241}
242
243int AudioRecord::inputSource() const
244{
245    return (int)mInputSource;
246}
247
248// -------------------------------------------------------------------------
249
250status_t AudioRecord::start()
251{
252    status_t ret = NO_ERROR;
253    sp<ClientRecordThread> t = mClientRecordThread;
254
255    LOGV("start");
256
257    if (t != 0) {
258        if (t->exitPending()) {
259            if (t->requestExitAndWait() == WOULD_BLOCK) {
260                LOGE("AudioRecord::start called from thread");
261                return WOULD_BLOCK;
262            }
263        }
264        t->mLock.lock();
265     }
266
267    if (android_atomic_or(1, &mActive) == 0) {
268        ret = mAudioRecord->start();
269        if (ret == DEAD_OBJECT) {
270            LOGV("start() dead IAudioRecord: creating a new one");
271            ret = openRecord(mCblk->sampleRate, mFormat, mChannelCount,
272                    mFrameCount, mFlags, getInput());
273            if (ret == NO_ERROR) {
274                ret = mAudioRecord->start();
275            }
276        }
277        if (ret == NO_ERROR) {
278            mNewPosition = mCblk->user + mUpdatePeriod;
279            mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
280            mCblk->waitTimeMs = 0;
281            if (t != 0) {
282               t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
283            } else {
284                setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
285            }
286        } else {
287            LOGV("start() failed");
288            android_atomic_and(~1, &mActive);
289        }
290    }
291
292    if (t != 0) {
293        t->mLock.unlock();
294    }
295
296    return ret;
297}
298
299status_t AudioRecord::stop()
300{
301    sp<ClientRecordThread> t = mClientRecordThread;
302
303    LOGV("stop");
304
305    if (t != 0) {
306        t->mLock.lock();
307     }
308
309    if (android_atomic_and(~1, &mActive) == 1) {
310        mCblk->cv.signal();
311        mAudioRecord->stop();
312        // the record head position will reset to 0, so if a marker is set, we need
313        // to activate it again
314        mMarkerReached = false;
315        if (t != 0) {
316            t->requestExit();
317        } else {
318            setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
319        }
320    }
321
322    if (t != 0) {
323        t->mLock.unlock();
324    }
325
326    return NO_ERROR;
327}
328
329bool AudioRecord::stopped() const
330{
331    return !mActive;
332}
333
334uint32_t AudioRecord::getSampleRate()
335{
336    return mCblk->sampleRate;
337}
338
339status_t AudioRecord::setMarkerPosition(uint32_t marker)
340{
341    if (mCbf == 0) return INVALID_OPERATION;
342
343    mMarkerPosition = marker;
344    mMarkerReached = false;
345
346    return NO_ERROR;
347}
348
349status_t AudioRecord::getMarkerPosition(uint32_t *marker)
350{
351    if (marker == 0) return BAD_VALUE;
352
353    *marker = mMarkerPosition;
354
355    return NO_ERROR;
356}
357
358status_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod)
359{
360    if (mCbf == 0) return INVALID_OPERATION;
361
362    uint32_t curPosition;
363    getPosition(&curPosition);
364    mNewPosition = curPosition + updatePeriod;
365    mUpdatePeriod = updatePeriod;
366
367    return NO_ERROR;
368}
369
370status_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod)
371{
372    if (updatePeriod == 0) return BAD_VALUE;
373
374    *updatePeriod = mUpdatePeriod;
375
376    return NO_ERROR;
377}
378
379status_t AudioRecord::getPosition(uint32_t *position)
380{
381    if (position == 0) return BAD_VALUE;
382
383    *position = mCblk->user;
384
385    return NO_ERROR;
386}
387
388unsigned int AudioRecord::getInputFramesLost()
389{
390    if (mActive)
391        return AudioSystem::getInputFramesLost(mInput);
392    else
393        return 0;
394}
395
396// -------------------------------------------------------------------------
397
398status_t AudioRecord::openRecord(
399        uint32_t sampleRate,
400        int format,
401        int channelCount,
402        int frameCount,
403        uint32_t flags,
404        audio_io_handle_t input)
405{
406    status_t status;
407    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
408    if (audioFlinger == 0) {
409        return NO_INIT;
410    }
411
412    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), input,
413                                                       sampleRate, format,
414                                                       channelCount,
415                                                       frameCount,
416                                                       ((uint16_t)flags) << 16,
417                                                       &status);
418    if (record == 0) {
419        LOGE("AudioFlinger could not create record track, status: %d", status);
420        return status;
421    }
422    sp<IMemory> cblk = record->getCblk();
423    if (cblk == 0) {
424        LOGE("Could not get control block");
425        return NO_INIT;
426    }
427    mAudioRecord.clear();
428    mAudioRecord = record;
429    mCblkMemory.clear();
430    mCblkMemory = cblk;
431    mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
432    mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
433    mCblk->out = 0;
434    mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
435    mCblk->waitTimeMs = 0;
436    return NO_ERROR;
437}
438
439status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
440{
441    int active;
442    status_t result;
443    audio_track_cblk_t* cblk = mCblk;
444    uint32_t framesReq = audioBuffer->frameCount;
445    uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS;
446
447    audioBuffer->frameCount  = 0;
448    audioBuffer->size        = 0;
449
450    uint32_t framesReady = cblk->framesReady();
451
452    if (framesReady == 0) {
453        cblk->lock.lock();
454        goto start_loop_here;
455        while (framesReady == 0) {
456            active = mActive;
457            if (UNLIKELY(!active)) {
458                cblk->lock.unlock();
459                return NO_MORE_BUFFERS;
460            }
461            if (UNLIKELY(!waitCount)) {
462                cblk->lock.unlock();
463                return WOULD_BLOCK;
464            }
465            result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
466            if (__builtin_expect(result!=NO_ERROR, false)) {
467                cblk->waitTimeMs += waitTimeMs;
468                if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
469                    LOGW(   "obtainBuffer timed out (is the CPU pegged?) "
470                            "user=%08x, server=%08x", cblk->user, cblk->server);
471                    cblk->lock.unlock();
472                    result = mAudioRecord->start();
473                    if (result == DEAD_OBJECT) {
474                        LOGW("obtainBuffer() dead IAudioRecord: creating a new one");
475                        result = openRecord(cblk->sampleRate, mFormat, mChannelCount,
476                                            mFrameCount, mFlags, getInput());
477                        if (result == NO_ERROR) {
478                            cblk = mCblk;
479                            mAudioRecord->start();
480                        }
481                    }
482                    cblk->lock.lock();
483                    cblk->waitTimeMs = 0;
484                }
485                if (--waitCount == 0) {
486                    cblk->lock.unlock();
487                    return TIMED_OUT;
488                }
489            }
490            // read the server count again
491        start_loop_here:
492            framesReady = cblk->framesReady();
493        }
494        cblk->lock.unlock();
495    }
496
497    cblk->waitTimeMs = 0;
498
499    if (framesReq > framesReady) {
500        framesReq = framesReady;
501    }
502
503    uint32_t u = cblk->user;
504    uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
505
506    if (u + framesReq > bufferEnd) {
507        framesReq = bufferEnd - u;
508    }
509
510    audioBuffer->flags       = 0;
511    audioBuffer->channelCount= mChannelCount;
512    audioBuffer->format      = mFormat;
513    audioBuffer->frameCount  = framesReq;
514    audioBuffer->size        = framesReq*cblk->frameSize;
515    audioBuffer->raw         = (int8_t*)cblk->buffer(u);
516    active = mActive;
517    return active ? status_t(NO_ERROR) : status_t(STOPPED);
518}
519
520void AudioRecord::releaseBuffer(Buffer* audioBuffer)
521{
522    audio_track_cblk_t* cblk = mCblk;
523    cblk->stepUser(audioBuffer->frameCount);
524}
525
526audio_io_handle_t AudioRecord::getInput()
527{
528    mInput = AudioSystem::getInput(mInputSource,
529                                mCblk->sampleRate,
530                                mFormat, mChannels,
531                                (AudioSystem::audio_in_acoustics)mFlags);
532    return mInput;
533}
534
535// -------------------------------------------------------------------------
536
537ssize_t AudioRecord::read(void* buffer, size_t userSize)
538{
539    ssize_t read = 0;
540    Buffer audioBuffer;
541    int8_t *dst = static_cast<int8_t*>(buffer);
542
543    if (ssize_t(userSize) < 0) {
544        // sanity-check. user is most-likely passing an error code.
545        LOGE("AudioRecord::read(buffer=%p, size=%u (%d)",
546                buffer, userSize, userSize);
547        return BAD_VALUE;
548    }
549
550
551    do {
552
553        audioBuffer.frameCount = userSize/frameSize();
554
555        // By using a wait count corresponding to twice the timeout period in
556        // obtainBuffer() we give a chance to recover once for a read timeout
557        // (if media_server crashed for instance) before returning a length of
558        // 0 bytes read to the client
559        status_t err = obtainBuffer(&audioBuffer, ((2 * MAX_RUN_TIMEOUT_MS) / WAIT_PERIOD_MS));
560        if (err < 0) {
561            // out of buffers, return #bytes written
562            if (err == status_t(NO_MORE_BUFFERS))
563                break;
564            if (err == status_t(TIMED_OUT))
565                err = 0;
566            return ssize_t(err);
567        }
568
569        size_t bytesRead = audioBuffer.size;
570        memcpy(dst, audioBuffer.i8, bytesRead);
571
572        dst += bytesRead;
573        userSize -= bytesRead;
574        read += bytesRead;
575
576        releaseBuffer(&audioBuffer);
577    } while (userSize);
578
579    return read;
580}
581
582// -------------------------------------------------------------------------
583
584bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
585{
586    Buffer audioBuffer;
587    uint32_t frames = mRemainingFrames;
588    size_t readSize;
589
590    // Manage marker callback
591    if (!mMarkerReached && (mMarkerPosition > 0)) {
592        if (mCblk->user >= mMarkerPosition) {
593            mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition);
594            mMarkerReached = true;
595        }
596    }
597
598    // Manage new position callback
599    if (mUpdatePeriod > 0) {
600        while (mCblk->user >= mNewPosition) {
601            mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition);
602            mNewPosition += mUpdatePeriod;
603        }
604    }
605
606    do {
607        audioBuffer.frameCount = frames;
608        // Calling obtainBuffer() with a wait count of 1
609        // limits wait time to WAIT_PERIOD_MS. This prevents from being
610        // stuck here not being able to handle timed events (position, markers).
611        status_t err = obtainBuffer(&audioBuffer, 1);
612        if (err < NO_ERROR) {
613            if (err != TIMED_OUT) {
614                LOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up.");
615                return false;
616            }
617            break;
618        }
619        if (err == status_t(STOPPED)) return false;
620
621        size_t reqSize = audioBuffer.size;
622        mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
623        readSize = audioBuffer.size;
624
625        // Sanity check on returned size
626        if (ssize_t(readSize) <= 0) {
627            // The callback is done filling buffers
628            // Keep this thread going to handle timed events and
629            // still try to get more data in intervals of WAIT_PERIOD_MS
630            // but don't just loop and block the CPU, so wait
631            usleep(WAIT_PERIOD_MS*1000);
632            break;
633        }
634        if (readSize > reqSize) readSize = reqSize;
635
636        audioBuffer.size = readSize;
637        audioBuffer.frameCount = readSize/frameSize();
638        frames -= audioBuffer.frameCount;
639
640        releaseBuffer(&audioBuffer);
641
642    } while (frames);
643
644
645    // Manage overrun callback
646    if (mActive && (mCblk->framesAvailable_l() == 0)) {
647        LOGV("Overrun user: %x, server: %x, flowControlFlag %d", mCblk->user, mCblk->server, mCblk->flowControlFlag);
648        if (mCblk->flowControlFlag == 0) {
649            mCbf(EVENT_OVERRUN, mUserData, 0);
650            mCblk->flowControlFlag = 1;
651        }
652    }
653
654    if (frames == 0) {
655        mRemainingFrames = mNotificationFrames;
656    } else {
657        mRemainingFrames = frames;
658    }
659    return true;
660}
661
662// =========================================================================
663
664AudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver, bool bCanCallJava)
665    : Thread(bCanCallJava), mReceiver(receiver)
666{
667}
668
669bool AudioRecord::ClientRecordThread::threadLoop()
670{
671    return mReceiver.processAudioBuffer(this);
672}
673
674// -------------------------------------------------------------------------
675
676}; // namespace android
677
678