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