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