AudioSource.cpp revision a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7f
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "AudioSource" 19#include <utils/Log.h> 20 21#include <media/stagefright/AudioSource.h> 22 23#include <media/AudioRecord.h> 24#include <media/stagefright/MediaBufferGroup.h> 25#include <media/stagefright/MediaDebug.h> 26#include <media/stagefright/MediaDefs.h> 27#include <media/stagefright/MetaData.h> 28#include <cutils/properties.h> 29#include <sys/time.h> 30#include <time.h> 31 32namespace android { 33 34AudioSource::AudioSource( 35 int inputSource, uint32_t sampleRate, uint32_t channels) 36 : mRecord(new AudioRecord( 37 inputSource, sampleRate, AudioSystem::PCM_16_BIT, channels)), 38 mInitCheck(mRecord->initCheck()), 39 mStarted(false), 40 mCollectStats(false), 41 mTotalReadTimeUs(0), 42 mTotalReadBytes(0), 43 mTotalReads(0), 44 mGroup(NULL) { 45} 46 47AudioSource::~AudioSource() { 48 if (mStarted) { 49 stop(); 50 } 51 52 delete mRecord; 53 mRecord = NULL; 54} 55 56status_t AudioSource::initCheck() const { 57 return mInitCheck; 58} 59 60status_t AudioSource::start(MetaData *params) { 61 if (mStarted) { 62 return UNKNOWN_ERROR; 63 } 64 65 char value[PROPERTY_VALUE_MAX]; 66 if (property_get("media.stagefright.record-stats", value, NULL) 67 && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 68 mCollectStats = true; 69 } 70 status_t err = mRecord->start(); 71 72 if (err == OK) { 73 mGroup = new MediaBufferGroup; 74 mGroup->add_buffer(new MediaBuffer(kMaxBufferSize)); 75 76 mStarted = true; 77 } 78 79 return err; 80} 81 82status_t AudioSource::stop() { 83 if (!mStarted) { 84 return UNKNOWN_ERROR; 85 } 86 87 mRecord->stop(); 88 89 delete mGroup; 90 mGroup = NULL; 91 92 mStarted = false; 93 94 if (mCollectStats) { 95 LOGI("%lld reads: %.2f bps in %lld us", 96 mTotalReads, 97 (mTotalReadBytes * 8000000.0) / mTotalReadTimeUs, 98 mTotalReadTimeUs); 99 } 100 101 return OK; 102} 103 104sp<MetaData> AudioSource::getFormat() { 105 sp<MetaData> meta = new MetaData; 106 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); 107 meta->setInt32(kKeySampleRate, mRecord->getSampleRate()); 108 meta->setInt32(kKeyChannelCount, mRecord->channelCount()); 109 meta->setInt32(kKeyMaxInputSize, kMaxBufferSize); 110 111 return meta; 112} 113 114status_t AudioSource::read( 115 MediaBuffer **out, const ReadOptions *options) { 116 *out = NULL; 117 ++mTotalReads; 118 119 MediaBuffer *buffer; 120 CHECK_EQ(mGroup->acquire_buffer(&buffer), OK); 121 122 uint32_t numFramesRecorded; 123 mRecord->getPosition(&numFramesRecorded); 124 int64_t latency = mRecord->latency() * 1000; 125 uint32_t sampleRate = mRecord->getSampleRate(); 126 int64_t timestampUs = (1000000LL * numFramesRecorded) / sampleRate - latency; 127 LOGV("latency: %lld, sample rate: %d, timestamp: %lld", 128 latency, sampleRate, timestampUs); 129 130 buffer->meta_data()->setInt64(kKeyTime, timestampUs); 131 132 ssize_t n = 0; 133 if (mCollectStats) { 134 struct timeval tv_start, tv_end; 135 gettimeofday(&tv_start, NULL); 136 n = mRecord->read(buffer->data(), buffer->size()); 137 gettimeofday(&tv_end, NULL); 138 mTotalReadTimeUs += ((1000000LL * (tv_end.tv_sec - tv_start.tv_sec)) 139 + (tv_end.tv_usec - tv_start.tv_usec)); 140 if (n >= 0) { 141 mTotalReadBytes += n; 142 } 143 } else { 144 n = mRecord->read(buffer->data(), buffer->size()); 145 } 146 147 if (n < 0) { 148 buffer->release(); 149 buffer = NULL; 150 151 return (status_t)n; 152 } 153 154 buffer->set_range(0, n); 155 156 *out = buffer; 157 158 return OK; 159} 160 161} // namespace android 162