AudioSource.cpp revision be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7
1e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber/*
2e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * Copyright (C) 2010 The Android Open Source Project
3e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber *
4e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * you may not use this file except in compliance with the License.
6e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * You may obtain a copy of the License at
7e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber *
8e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber *
10e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * Unless required by applicable law or agreed to in writing, software
11e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * See the License for the specific language governing permissions and
14e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * limitations under the License.
15e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber */
16e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
17050b28a593350047845a45a14cc5026221ac1620James Dong//#define LOG_NDEBUG 0
18050b28a593350047845a45a14cc5026221ac1620James Dong#define LOG_TAG "AudioSource"
19050b28a593350047845a45a14cc5026221ac1620James Dong#include <utils/Log.h>
20050b28a593350047845a45a14cc5026221ac1620James Dong
21e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/AudioSource.h>
22e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
23e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/AudioRecord.h>
24e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MediaBufferGroup.h>
25e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MediaDebug.h>
26e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MediaDefs.h>
27e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MetaData.h>
28365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <cutils/properties.h>
29365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <sys/time.h>
30365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <time.h>
31e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
32e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Hubernamespace android {
33e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
34e7c9cb48fec02697227bd847cd2e69432659adfdAndreas HuberAudioSource::AudioSource(
35e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        int inputSource, uint32_t sampleRate, uint32_t channels)
36be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong    : mStarted(false),
37365a963142093a1cd8efdcea76b5f65096a5b115James Dong      mCollectStats(false),
38365a963142093a1cd8efdcea76b5f65096a5b115James Dong      mTotalReadTimeUs(0),
39365a963142093a1cd8efdcea76b5f65096a5b115James Dong      mTotalReadBytes(0),
40365a963142093a1cd8efdcea76b5f65096a5b115James Dong      mTotalReads(0),
41e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber      mGroup(NULL) {
42be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong
43be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong    LOGV("sampleRate: %d, channels: %d", sampleRate, channels);
44be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong    uint32_t flags = AudioRecord::RECORD_AGC_ENABLE |
45be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                     AudioRecord::RECORD_NS_ENABLE  |
46be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                     AudioRecord::RECORD_IIR_ENABLE;
47be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong
48be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong    mRecord = new AudioRecord(
49be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                inputSource, sampleRate, AudioSystem::PCM_16_BIT,
50be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                channels > 1? AudioSystem::CHANNEL_IN_STEREO: AudioSystem::CHANNEL_IN_MONO,
51be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                4 * kMaxBufferSize / sizeof(int16_t), /* Enable ping-pong buffers */
52be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                flags);
53be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong
54be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong    mInitCheck = mRecord->initCheck();
55e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
56e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
57e7c9cb48fec02697227bd847cd2e69432659adfdAndreas HuberAudioSource::~AudioSource() {
58e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (mStarted) {
59e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        stop();
60e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
61e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
62e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    delete mRecord;
63e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    mRecord = NULL;
64e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
65e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
66e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::initCheck() const {
67e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return mInitCheck;
68e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
69e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
70e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::start(MetaData *params) {
71e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (mStarted) {
72e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        return UNKNOWN_ERROR;
73e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
74e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
75365a963142093a1cd8efdcea76b5f65096a5b115James Dong    char value[PROPERTY_VALUE_MAX];
76365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (property_get("media.stagefright.record-stats", value, NULL)
77365a963142093a1cd8efdcea76b5f65096a5b115James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
78365a963142093a1cd8efdcea76b5f65096a5b115James Dong        mCollectStats = true;
79365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
80e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    status_t err = mRecord->start();
81e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
82e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (err == OK) {
83e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        mGroup = new MediaBufferGroup;
84e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        mGroup->add_buffer(new MediaBuffer(kMaxBufferSize));
85e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
86e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        mStarted = true;
87e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
88e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
89e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return err;
90e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
91e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
92e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::stop() {
93e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (!mStarted) {
94e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        return UNKNOWN_ERROR;
95e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
96e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
97e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    mRecord->stop();
98e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
99e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    delete mGroup;
100e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    mGroup = NULL;
101e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
102e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    mStarted = false;
103e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
104365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (mCollectStats) {
105365a963142093a1cd8efdcea76b5f65096a5b115James Dong        LOGI("%lld reads: %.2f bps in %lld us",
106365a963142093a1cd8efdcea76b5f65096a5b115James Dong                mTotalReads,
107365a963142093a1cd8efdcea76b5f65096a5b115James Dong                (mTotalReadBytes * 8000000.0) / mTotalReadTimeUs,
108365a963142093a1cd8efdcea76b5f65096a5b115James Dong                mTotalReadTimeUs);
109365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
110365a963142093a1cd8efdcea76b5f65096a5b115James Dong
111e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return OK;
112e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
113e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
114e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Hubersp<MetaData> AudioSource::getFormat() {
115e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    sp<MetaData> meta = new MetaData;
116e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
117e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setInt32(kKeySampleRate, mRecord->getSampleRate());
118e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setInt32(kKeyChannelCount, mRecord->channelCount());
119e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setInt32(kKeyMaxInputSize, kMaxBufferSize);
120e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
121e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return meta;
122e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
123e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
124e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::read(
125e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        MediaBuffer **out, const ReadOptions *options) {
126e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    *out = NULL;
127365a963142093a1cd8efdcea76b5f65096a5b115James Dong    ++mTotalReads;
128e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
129e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    MediaBuffer *buffer;
130e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    CHECK_EQ(mGroup->acquire_buffer(&buffer), OK);
131e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
132e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    uint32_t numFramesRecorded;
133e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    mRecord->getPosition(&numFramesRecorded);
134a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t latency = mRecord->latency() * 1000;
135a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    uint32_t sampleRate = mRecord->getSampleRate();
136a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    int64_t timestampUs = (1000000LL * numFramesRecorded) / sampleRate - latency;
137a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    LOGV("latency: %lld, sample rate: %d, timestamp: %lld",
138a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong            latency, sampleRate, timestampUs);
139e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
140a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong    buffer->meta_data()->setInt64(kKeyTime, timestampUs);
141e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
142365a963142093a1cd8efdcea76b5f65096a5b115James Dong    ssize_t n = 0;
143365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (mCollectStats) {
144365a963142093a1cd8efdcea76b5f65096a5b115James Dong        struct timeval tv_start, tv_end;
145365a963142093a1cd8efdcea76b5f65096a5b115James Dong        gettimeofday(&tv_start, NULL);
146365a963142093a1cd8efdcea76b5f65096a5b115James Dong        n = mRecord->read(buffer->data(), buffer->size());
147365a963142093a1cd8efdcea76b5f65096a5b115James Dong        gettimeofday(&tv_end, NULL);
148365a963142093a1cd8efdcea76b5f65096a5b115James Dong        mTotalReadTimeUs += ((1000000LL * (tv_end.tv_sec - tv_start.tv_sec))
149365a963142093a1cd8efdcea76b5f65096a5b115James Dong                + (tv_end.tv_usec - tv_start.tv_usec));
150365a963142093a1cd8efdcea76b5f65096a5b115James Dong        if (n >= 0) {
151365a963142093a1cd8efdcea76b5f65096a5b115James Dong            mTotalReadBytes += n;
152365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
153365a963142093a1cd8efdcea76b5f65096a5b115James Dong    } else {
154365a963142093a1cd8efdcea76b5f65096a5b115James Dong        n = mRecord->read(buffer->data(), buffer->size());
155365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
156e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
157e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (n < 0) {
158e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        buffer->release();
159e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        buffer = NULL;
160e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
161e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        return (status_t)n;
162e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
163e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
164e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    buffer->set_range(0, n);
165e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
166e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    *out = buffer;
167e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
168e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return OK;
169e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
170e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
171e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}  // namespace android
172