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