AudioRecord.cpp revision be916aa1267e2e6b1c148f51d11bcbbc79cb864c
189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project/*
289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Copyright 2008, The Android Open Source Project
489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** you may not use this file except in compliance with the License.
789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** You may obtain a copy of the License at
889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
1089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
1189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
1289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
1389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** See the License for the specific language governing permissions and
1589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** limitations under the License.
1689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project*/
1789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
1889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project//#define LOG_NDEBUG 0
1989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#define LOG_TAG "AudioRecord"
2089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
2189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <stdint.h>
2289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <sys/types.h>
2389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
2489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <sched.h>
2589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <sys/resource.h>
2689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
2789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <private/media/AudioTrackShared.h>
2889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
2989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/AudioSystem.h>
3089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/AudioRecord.h>
31c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent#include <media/mediarecorder.h>
3289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
337562408b2261d38415453378b6188f74fda99d88Mathias Agopian#include <binder/IServiceManager.h>
3489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <utils/Log.h>
357562408b2261d38415453378b6188f74fda99d88Mathias Agopian#include <binder/Parcel.h>
367562408b2261d38415453378b6188f74fda99d88Mathias Agopian#include <binder/IPCThreadState.h>
3789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <utils/Timers.h>
3889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <cutils/atomic.h>
3989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
4189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
4289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectnamespace android {
4489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ---------------------------------------------------------------------------
4689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::AudioRecord()
48be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    : mStatus(NO_INIT), mSessionId(0)
4989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
5089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
5189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
5289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::AudioRecord(
53f5879c1448cc6aebc51b26d3ec2399d66144f8f4Eric Laurent        int inputSource,
5489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        uint32_t sampleRate,
5589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        int format,
56c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        uint32_t channels,
5789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        int frameCount,
5889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        uint32_t flags,
5989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        callback_t cbf,
6089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        void* user,
61be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent        int notificationFrames,
62be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent        int sessionId)
63be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    : mStatus(NO_INIT), mSessionId(0)
6489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
65c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    mStatus = set(inputSource, sampleRate, format, channels,
66be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent            frameCount, flags, cbf, user, notificationFrames, sessionId);
6789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
6889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::~AudioRecord()
7089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
7189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mStatus == NO_ERROR) {
7289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Make sure that callback function exits in the case where
7389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // it is looping on buffer empty condition in obtainBuffer().
7489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Otherwise the callback thread will never exit.
7589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        stop();
7689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (mClientRecordThread != 0) {
7789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            mClientRecordThread->requestExitAndWait();
7889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            mClientRecordThread.clear();
7989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
8089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mAudioRecord.clear();
8189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        IPCThreadState::self()->flushCommands();
8289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
8389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
8489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::set(
86f5879c1448cc6aebc51b26d3ec2399d66144f8f4Eric Laurent        int inputSource,
8789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        uint32_t sampleRate,
8889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        int format,
89c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        uint32_t channels,
9089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        int frameCount,
9189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        uint32_t flags,
9289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        callback_t cbf,
9389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        void* user,
9489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        int notificationFrames,
95be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent        bool threadCanCallJava,
96be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent        int sessionId)
9789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
9889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
99c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    LOGV("set(): sampleRate %d, channels %d, frameCount %d",sampleRate, channels, frameCount);
1001dd70b9f04961a06fcb73a97fca10a53b3245d3cEric Laurent    if (mAudioRecord != 0) {
10189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return INVALID_OPERATION;
10289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
10389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
104c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    if (inputSource == AUDIO_SOURCE_DEFAULT) {
105c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        inputSource = AUDIO_SOURCE_MIC;
10689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
10789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
10889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (sampleRate == 0) {
10989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        sampleRate = DEFAULT_SAMPLE_RATE;
11089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
11189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // these below should probably come from the audioFlinger too...
11289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (format == 0) {
11389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        format = AudioSystem::PCM_16_BIT;
11489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
115c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    // validate parameters
116c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    if (!AudioSystem::isValidFormat(format)) {
117c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        LOGE("Invalid format");
118c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        return BAD_VALUE;
11989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
12089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
121c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    if (!AudioSystem::isInputChannel(channels)) {
12289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
12389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
124be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent
125c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    int channelCount = AudioSystem::popCount(channels);
126c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
1276100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent    audio_io_handle_t input = AudioSystem::getInput(inputSource,
128c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent                                    sampleRate, format, channels, (AudioSystem::audio_in_acoustics)flags);
1296100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent    if (input == 0) {
130148b266afe2ac92b5616c24e8d5160e6f9242f69Eric Laurent        LOGE("Could not get audio input for record source %d", inputSource);
13189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
13289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
13389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
13489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // validate framecount
13589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    size_t inputBuffSizeInBytes = -1;
13689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &inputBuffSizeInBytes)
13789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            != NO_ERROR) {
13889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        LOGE("AudioSystem could not query the input buffer size.");
139c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        return NO_INIT;
14089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
141c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
14289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (inputBuffSizeInBytes == 0) {
14389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        LOGE("Recording parameters are not supported: sampleRate %d, channelCount %d, format %d",
14489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            sampleRate, channelCount, format);
14589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
14689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
147c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
14889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    int frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1);
149c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    if (AudioSystem::isLinearPCM(format)) {
150c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? sizeof(int16_t) : sizeof(int8_t));
151c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    } else {
152c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        frameSizeInBytes = sizeof(int8_t);
153c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    }
154c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
15589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
15689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // We use 2* size of input buffer for ping pong use of record buffer.
15789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    int minFrameCount = 2 * inputBuffSizeInBytes / frameSizeInBytes;
15889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("AudioRecord::set() minFrameCount = %d", minFrameCount);
15989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
16089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (frameCount == 0) {
16189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        frameCount = minFrameCount;
16289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    } else if (frameCount < minFrameCount) {
16389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
16489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
16589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
16689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (notificationFrames == 0) {
16789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        notificationFrames = frameCount/2;
16889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
16989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
170be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    mSessionId = sessionId;
171be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent
17234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    // create the IAudioRecord
17334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    status_t status = openRecord(sampleRate, format, channelCount,
1746100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent                                 frameCount, flags, input);
17534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
17634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    if (status != NO_ERROR) {
17789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return status;
17889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
17934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
18089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (cbf != 0) {
18189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mClientRecordThread = new ClientRecordThread(*this, threadCanCallJava);
18289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (mClientRecordThread == 0) {
18389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            return NO_INIT;
18489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
18589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
18689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
18789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mStatus = NO_ERROR;
18889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
18989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mFormat = format;
19089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // Update buffer size in case it has been limited by AudioFlinger during track creation
19189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mFrameCount = mCblk->frameCount;
192c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    mChannelCount = (uint8_t)channelCount;
1936100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent    mChannels = channels;
19489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mActive = 0;
19589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mCbf = cbf;
19689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mNotificationFrames = notificationFrames;
19789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mRemainingFrames = notificationFrames;
19889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUserData = user;
19989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // TODO: add audio hardware input latency here
200573266210fb2b2e7d86fbd46d0dfe16763611d91Eric Laurent    mLatency = (1000*mFrameCount) / sampleRate;
20189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mMarkerPosition = 0;
2027d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi    mMarkerReached = false;
20389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mNewPosition = 0;
20489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUpdatePeriod = 0;
205f5879c1448cc6aebc51b26d3ec2399d66144f8f4Eric Laurent    mInputSource = (uint8_t)inputSource;
20634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    mFlags = flags;
20705bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent    mInput = input;
20889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
20989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
21089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
21189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
21289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::initCheck() const
21389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
21489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return mStatus;
21589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
21689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
21789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
21889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
21989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectuint32_t AudioRecord::latency() const
22089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
22189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return mLatency;
22289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
22389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
22489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectint AudioRecord::format() const
22589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
22689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return mFormat;
22789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
22889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
22989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectint AudioRecord::channelCount() const
23089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
23189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return mChannelCount;
23289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
23389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
23489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectuint32_t AudioRecord::frameCount() const
23589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
23689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return mFrameCount;
23789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
23889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
23989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectint AudioRecord::frameSize() const
24089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
241c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    if (AudioSystem::isLinearPCM(mFormat)) {
242c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
243c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    } else {
244c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        return sizeof(uint8_t);
245c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    }
24689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
24789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
248f5879c1448cc6aebc51b26d3ec2399d66144f8f4Eric Laurentint AudioRecord::inputSource() const
249f5879c1448cc6aebc51b26d3ec2399d66144f8f4Eric Laurent{
250f5879c1448cc6aebc51b26d3ec2399d66144f8f4Eric Laurent    return (int)mInputSource;
251f5879c1448cc6aebc51b26d3ec2399d66144f8f4Eric Laurent}
252f5879c1448cc6aebc51b26d3ec2399d66144f8f4Eric Laurent
25389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
25489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
25589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::start()
25689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
25789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    status_t ret = NO_ERROR;
25889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    sp<ClientRecordThread> t = mClientRecordThread;
25989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
26089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("start");
26189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
26289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (t != 0) {
26389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (t->exitPending()) {
26489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            if (t->requestExitAndWait() == WOULD_BLOCK) {
26589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                LOGE("AudioRecord::start called from thread");
26689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                return WOULD_BLOCK;
26789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
26889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
26989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        t->mLock.lock();
27089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project     }
27189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
27289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (android_atomic_or(1, &mActive) == 0) {
2736100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent        ret = mAudioRecord->start();
2746100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent        if (ret == DEAD_OBJECT) {
2756100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent            LOGV("start() dead IAudioRecord: creating a new one");
2766100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent            ret = openRecord(mCblk->sampleRate, mFormat, mChannelCount,
2776100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent                    mFrameCount, mFlags, getInput());
27834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent            if (ret == NO_ERROR) {
2796100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent                ret = mAudioRecord->start();
2806100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent            }
2816100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent        }
2826100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent        if (ret == NO_ERROR) {
2836100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent            mNewPosition = mCblk->user + mUpdatePeriod;
2846100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent            mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
2856100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent            mCblk->waitTimeMs = 0;
2866100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent            if (t != 0) {
2876100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent               t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
288c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent            } else {
2896100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent                setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
290c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent            }
2916100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent        } else {
2926100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent            LOGV("start() failed");
2936100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent            android_atomic_and(~1, &mActive);
29489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
29589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
29689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
29789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (t != 0) {
29889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        t->mLock.unlock();
29989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
30089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
30189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return ret;
30289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
30389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
30489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::stop()
30589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
30689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    sp<ClientRecordThread> t = mClientRecordThread;
30789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
30889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("stop");
30989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
31089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (t != 0) {
31189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        t->mLock.lock();
31289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project     }
31389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
31489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (android_atomic_and(~1, &mActive) == 1) {
3151dd70b9f04961a06fcb73a97fca10a53b3245d3cEric Laurent        mCblk->cv.signal();
31689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mAudioRecord->stop();
3177d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi        // the record head position will reset to 0, so if a marker is set, we need
3187d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi        // to activate it again
3197d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi        mMarkerReached = false;
32089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (t != 0) {
32189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            t->requestExit();
32289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        } else {
32389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
32489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
32589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
32689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
32789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (t != 0) {
32889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        t->mLock.unlock();
32989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
33089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
33189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
33289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
33389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
33489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectbool AudioRecord::stopped() const
33589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
33689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return !mActive;
33789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
33889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
339573266210fb2b2e7d86fbd46d0dfe16763611d91Eric Laurentuint32_t AudioRecord::getSampleRate()
340573266210fb2b2e7d86fbd46d0dfe16763611d91Eric Laurent{
341573266210fb2b2e7d86fbd46d0dfe16763611d91Eric Laurent    return mCblk->sampleRate;
342573266210fb2b2e7d86fbd46d0dfe16763611d91Eric Laurent}
343573266210fb2b2e7d86fbd46d0dfe16763611d91Eric Laurent
34489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::setMarkerPosition(uint32_t marker)
34589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
34689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mCbf == 0) return INVALID_OPERATION;
34789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
34889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mMarkerPosition = marker;
3497d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi    mMarkerReached = false;
35089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
35189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
35289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
35389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
35489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::getMarkerPosition(uint32_t *marker)
35589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
35689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (marker == 0) return BAD_VALUE;
35789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
35889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    *marker = mMarkerPosition;
35989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
36089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
36189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
36289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
36389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod)
36489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
36589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mCbf == 0) return INVALID_OPERATION;
36689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
36789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    uint32_t curPosition;
36889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    getPosition(&curPosition);
36989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mNewPosition = curPosition + updatePeriod;
37089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUpdatePeriod = updatePeriod;
37189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
37289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
37389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
37489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
37589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod)
37689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
37789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (updatePeriod == 0) return BAD_VALUE;
37889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
37989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    *updatePeriod = mUpdatePeriod;
38089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
38189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
38289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
38389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
38489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::getPosition(uint32_t *position)
38589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
38689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (position == 0) return BAD_VALUE;
38789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
38889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    *position = mCblk->user;
38989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
39089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
39189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
39289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
39305bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurentunsigned int AudioRecord::getInputFramesLost()
39405bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent{
39505bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent    if (mActive)
39605bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent        return AudioSystem::getInputFramesLost(mInput);
39705bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent    else
39805bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent        return 0;
39905bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent}
40089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
40189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
40289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
40334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurentstatus_t AudioRecord::openRecord(
40434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        uint32_t sampleRate,
40534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        int format,
40634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        int channelCount,
40734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        int frameCount,
4086100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent        uint32_t flags,
4096100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent        audio_io_handle_t input)
41034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent{
41134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    status_t status;
41234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
41334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    if (audioFlinger == 0) {
41434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        return NO_INIT;
41534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    }
41634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
4176100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), input,
41834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                                                       sampleRate, format,
41934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                                                       channelCount,
42034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                                                       frameCount,
42134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                                                       ((uint16_t)flags) << 16,
422be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent                                                       &mSessionId,
42334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                                                       &status);
42434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    if (record == 0) {
42534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        LOGE("AudioFlinger could not create record track, status: %d", status);
42634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        return status;
42734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    }
42834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    sp<IMemory> cblk = record->getCblk();
42934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    if (cblk == 0) {
43034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        LOGE("Could not get control block");
43134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        return NO_INIT;
43234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    }
43334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    mAudioRecord.clear();
43434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    mAudioRecord = record;
43534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    mCblkMemory.clear();
43634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    mCblkMemory = cblk;
43734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
43834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
439d1b449aad6c087a69f5ec66b7facb2845b73f1cbEric Laurent    mCblk->flags &= ~CBLK_DIRECTION_MSK;
4406100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent    mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
4416100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent    mCblk->waitTimeMs = 0;
44234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    return NO_ERROR;
44334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent}
44434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
44589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
44689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
44789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    int active;
44889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    status_t result;
44989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    audio_track_cblk_t* cblk = mCblk;
45089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    uint32_t framesReq = audioBuffer->frameCount;
4511dd70b9f04961a06fcb73a97fca10a53b3245d3cEric Laurent    uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS;
45289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
45389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    audioBuffer->frameCount  = 0;
45489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    audioBuffer->size        = 0;
45589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
45689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    uint32_t framesReady = cblk->framesReady();
45789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
45889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (framesReady == 0) {
45934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        cblk->lock.lock();
46089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        goto start_loop_here;
46189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        while (framesReady == 0) {
46289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            active = mActive;
46334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent            if (UNLIKELY(!active)) {
46434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                cblk->lock.unlock();
46589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                return NO_MORE_BUFFERS;
46634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent            }
46734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent            if (UNLIKELY(!waitCount)) {
46834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                cblk->lock.unlock();
46989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                return WOULD_BLOCK;
47034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent            }
4711dd70b9f04961a06fcb73a97fca10a53b3245d3cEric Laurent            result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
47289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            if (__builtin_expect(result!=NO_ERROR, false)) {
4731dd70b9f04961a06fcb73a97fca10a53b3245d3cEric Laurent                cblk->waitTimeMs += waitTimeMs;
47489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
47589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                    LOGW(   "obtainBuffer timed out (is the CPU pegged?) "
47689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                            "user=%08x, server=%08x", cblk->user, cblk->server);
47734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                    cblk->lock.unlock();
47834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                    result = mAudioRecord->start();
47934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                    if (result == DEAD_OBJECT) {
48034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                        LOGW("obtainBuffer() dead IAudioRecord: creating a new one");
48134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                        result = openRecord(cblk->sampleRate, mFormat, mChannelCount,
4826100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent                                            mFrameCount, mFlags, getInput());
48334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                        if (result == NO_ERROR) {
48434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                            cblk = mCblk;
4856100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent                            mAudioRecord->start();
48634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                        }
48734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                    }
48834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                    cblk->lock.lock();
48989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                    cblk->waitTimeMs = 0;
49089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                }
49189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                if (--waitCount == 0) {
49234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                    cblk->lock.unlock();
49389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                    return TIMED_OUT;
49489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                }
49589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
49689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            // read the server count again
49789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        start_loop_here:
49889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            framesReady = cblk->framesReady();
49989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
50034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        cblk->lock.unlock();
50189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
50289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
50389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    cblk->waitTimeMs = 0;
504c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
50589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (framesReq > framesReady) {
50689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        framesReq = framesReady;
50789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
50889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
50989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    uint32_t u = cblk->user;
51089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
51189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
51289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (u + framesReq > bufferEnd) {
51389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        framesReq = bufferEnd - u;
51489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
51589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
51689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    audioBuffer->flags       = 0;
51789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    audioBuffer->channelCount= mChannelCount;
51889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    audioBuffer->format      = mFormat;
51989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    audioBuffer->frameCount  = framesReq;
520c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    audioBuffer->size        = framesReq*cblk->frameSize;
52189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    audioBuffer->raw         = (int8_t*)cblk->buffer(u);
52289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    active = mActive;
52389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return active ? status_t(NO_ERROR) : status_t(STOPPED);
52489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
52589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
52689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectvoid AudioRecord::releaseBuffer(Buffer* audioBuffer)
52789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
52889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    audio_track_cblk_t* cblk = mCblk;
52989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    cblk->stepUser(audioBuffer->frameCount);
53089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
53189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
5326100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurentaudio_io_handle_t AudioRecord::getInput()
5336100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent{
53405bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent    mInput = AudioSystem::getInput(mInputSource,
5356100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent                                mCblk->sampleRate,
5366100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent                                mFormat, mChannels,
5376100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent                                (AudioSystem::audio_in_acoustics)mFlags);
53805bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent    return mInput;
5396100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent}
5406100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent
541be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurentint AudioRecord::getSessionId()
542be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent{
543be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    return mSessionId;
544be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent}
545be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent
54689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
54789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
54889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectssize_t AudioRecord::read(void* buffer, size_t userSize)
54989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
55089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    ssize_t read = 0;
55189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    Buffer audioBuffer;
55289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    int8_t *dst = static_cast<int8_t*>(buffer);
55389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
55489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (ssize_t(userSize) < 0) {
55589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // sanity-check. user is most-likely passing an error code.
55689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        LOGE("AudioRecord::read(buffer=%p, size=%u (%d)",
55789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                buffer, userSize, userSize);
55889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
55989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
56089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
56189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
56289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    do {
56389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
564c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        audioBuffer.frameCount = userSize/frameSize();
56589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
56688335b1a749fe0157547907a2ce6c9632f4d2592Eric Laurent        // By using a wait count corresponding to twice the timeout period in
56788335b1a749fe0157547907a2ce6c9632f4d2592Eric Laurent        // obtainBuffer() we give a chance to recover once for a read timeout
56888335b1a749fe0157547907a2ce6c9632f4d2592Eric Laurent        // (if media_server crashed for instance) before returning a length of
56988335b1a749fe0157547907a2ce6c9632f4d2592Eric Laurent        // 0 bytes read to the client
57088335b1a749fe0157547907a2ce6c9632f4d2592Eric Laurent        status_t err = obtainBuffer(&audioBuffer, ((2 * MAX_RUN_TIMEOUT_MS) / WAIT_PERIOD_MS));
57189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (err < 0) {
57289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            // out of buffers, return #bytes written
57389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            if (err == status_t(NO_MORE_BUFFERS))
57489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                break;
57588335b1a749fe0157547907a2ce6c9632f4d2592Eric Laurent            if (err == status_t(TIMED_OUT))
57688335b1a749fe0157547907a2ce6c9632f4d2592Eric Laurent                err = 0;
57789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            return ssize_t(err);
57889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
57989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
58089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        size_t bytesRead = audioBuffer.size;
58189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        memcpy(dst, audioBuffer.i8, bytesRead);
58289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
58389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        dst += bytesRead;
58489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        userSize -= bytesRead;
58589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        read += bytesRead;
58689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
58789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        releaseBuffer(&audioBuffer);
58889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    } while (userSize);
58989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
59089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return read;
59189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
59289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
59389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
59489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
59589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectbool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
59689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
59789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    Buffer audioBuffer;
59889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    uint32_t frames = mRemainingFrames;
59989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    size_t readSize;
60089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
60189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // Manage marker callback
6027d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi    if (!mMarkerReached && (mMarkerPosition > 0)) {
60389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (mCblk->user >= mMarkerPosition) {
60489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition);
6057d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi            mMarkerReached = true;
60689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
60789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
60889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
60989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // Manage new position callback
61089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mUpdatePeriod > 0) {
61189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        while (mCblk->user >= mNewPosition) {
61289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition);
61389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            mNewPosition += mUpdatePeriod;
61489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
61589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
61689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
61789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    do {
61889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        audioBuffer.frameCount = frames;
619c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        // Calling obtainBuffer() with a wait count of 1
620c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        // limits wait time to WAIT_PERIOD_MS. This prevents from being
62189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // stuck here not being able to handle timed events (position, markers).
62289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        status_t err = obtainBuffer(&audioBuffer, 1);
62389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (err < NO_ERROR) {
62489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            if (err != TIMED_OUT) {
6251dd70b9f04961a06fcb73a97fca10a53b3245d3cEric Laurent                LOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up.");
62689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                return false;
62789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
62889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            break;
62989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
63089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (err == status_t(STOPPED)) return false;
63189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
63289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        size_t reqSize = audioBuffer.size;
63389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
63489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        readSize = audioBuffer.size;
63589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
63689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Sanity check on returned size
637cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent        if (ssize_t(readSize) <= 0) {
638cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent            // The callback is done filling buffers
639cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent            // Keep this thread going to handle timed events and
640cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent            // still try to get more data in intervals of WAIT_PERIOD_MS
641cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent            // but don't just loop and block the CPU, so wait
642cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent            usleep(WAIT_PERIOD_MS*1000);
643cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent            break;
644cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent        }
64589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (readSize > reqSize) readSize = reqSize;
64689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
64789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        audioBuffer.size = readSize;
648c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        audioBuffer.frameCount = readSize/frameSize();
64989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        frames -= audioBuffer.frameCount;
65089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
65189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        releaseBuffer(&audioBuffer);
65289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
65389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    } while (frames);
65489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
655c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
65689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // Manage overrun callback
65789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mActive && (mCblk->framesAvailable_l() == 0)) {
658d1b449aad6c087a69f5ec66b7facb2845b73f1cbEric Laurent        LOGV("Overrun user: %x, server: %x, flags %04x", mCblk->user, mCblk->server, mCblk->flags);
659d1b449aad6c087a69f5ec66b7facb2845b73f1cbEric Laurent        if ((mCblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) {
66089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            mCbf(EVENT_OVERRUN, mUserData, 0);
661d1b449aad6c087a69f5ec66b7facb2845b73f1cbEric Laurent            mCblk->flags |= CBLK_UNDERRUN_ON;
66289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
66389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
66489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
66589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (frames == 0) {
66689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mRemainingFrames = mNotificationFrames;
66789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    } else {
66889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mRemainingFrames = frames;
66989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
67089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return true;
67189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
67289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
67389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// =========================================================================
67489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
67589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver, bool bCanCallJava)
67689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    : Thread(bCanCallJava), mReceiver(receiver)
67789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
67889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
67989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
68089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectbool AudioRecord::ClientRecordThread::threadLoop()
68189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
68289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return mReceiver.processAudioBuffer(this);
68389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
68489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
68589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
68689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
68789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}; // namespace android
68889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
689