blob: bbdec024b148317691b9b3a0c3f92b286a244973 [file] [log] [blame]
Andreas Huber07bf09d2010-01-25 14:27:12 -08001/*
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
James Dongabed93a2010-04-22 17:27:04 -070017//#define LOG_NDEBUG 0
18#define LOG_TAG "AudioSource"
19#include <utils/Log.h>
20
Andreas Huber07bf09d2010-01-25 14:27:12 -080021#include <media/AudioRecord.h>
James Dongd33a4cc2011-02-15 10:08:07 -080022#include <media/stagefright/AudioSource.h>
23#include <media/stagefright/MediaBuffer.h>
Andreas Huber07bf09d2010-01-25 14:27:12 -080024#include <media/stagefright/MediaDefs.h>
25#include <media/stagefright/MetaData.h>
James Dongd33a4cc2011-02-15 10:08:07 -080026#include <media/stagefright/foundation/ADebug.h>
James Dongdae9fd32010-06-04 13:59:27 -070027#include <cutils/properties.h>
James Dongc3ae9372010-07-29 18:06:08 -070028#include <stdlib.h>
Andreas Huber07bf09d2010-01-25 14:27:12 -080029
30namespace android {
31
James Dongd33a4cc2011-02-15 10:08:07 -080032static void AudioRecordCallbackFunction(int event, void *user, void *info) {
33 AudioSource *source = (AudioSource *) user;
34 switch (event) {
35 case AudioRecord::EVENT_MORE_DATA: {
36 source->dataCallbackTimestamp(*((AudioRecord::Buffer *) info), systemTime() / 1000);
37 break;
38 }
39 case AudioRecord::EVENT_OVERRUN: {
40 LOGW("AudioRecord reported overrun!");
41 break;
42 }
43 default:
44 // does nothing
45 break;
46 }
47}
48
Andreas Huber07bf09d2010-01-25 14:27:12 -080049AudioSource::AudioSource(
50 int inputSource, uint32_t sampleRate, uint32_t channels)
James Dongd77d2a92010-06-14 17:45:35 -070051 : mStarted(false),
James Dongd33a4cc2011-02-15 10:08:07 -080052 mSampleRate(sampleRate),
James Dongc3ae9372010-07-29 18:06:08 -070053 mPrevSampleTimeUs(0),
James Dongd33a4cc2011-02-15 10:08:07 -080054 mNumFramesReceived(0),
55 mNumClientOwnedBuffers(0) {
James Dongd77d2a92010-06-14 17:45:35 -070056
57 LOGV("sampleRate: %d, channels: %d", sampleRate, channels);
James Dongd7f1c3d2010-08-26 16:28:17 -070058 CHECK(channels == 1 || channels == 2);
James Dongd77d2a92010-06-14 17:45:35 -070059 uint32_t flags = AudioRecord::RECORD_AGC_ENABLE |
60 AudioRecord::RECORD_NS_ENABLE |
61 AudioRecord::RECORD_IIR_ENABLE;
James Dongd77d2a92010-06-14 17:45:35 -070062 mRecord = new AudioRecord(
63 inputSource, sampleRate, AudioSystem::PCM_16_BIT,
64 channels > 1? AudioSystem::CHANNEL_IN_STEREO: AudioSystem::CHANNEL_IN_MONO,
65 4 * kMaxBufferSize / sizeof(int16_t), /* Enable ping-pong buffers */
James Dongd33a4cc2011-02-15 10:08:07 -080066 flags,
67 AudioRecordCallbackFunction,
68 this);
James Dongd77d2a92010-06-14 17:45:35 -070069
70 mInitCheck = mRecord->initCheck();
Andreas Huber07bf09d2010-01-25 14:27:12 -080071}
72
73AudioSource::~AudioSource() {
74 if (mStarted) {
75 stop();
76 }
77
78 delete mRecord;
79 mRecord = NULL;
80}
81
82status_t AudioSource::initCheck() const {
83 return mInitCheck;
84}
85
86status_t AudioSource::start(MetaData *params) {
James Dongd33a4cc2011-02-15 10:08:07 -080087 Mutex::Autolock autoLock(mLock);
Andreas Huber07bf09d2010-01-25 14:27:12 -080088 if (mStarted) {
89 return UNKNOWN_ERROR;
90 }
91
James Donga87544b2010-09-01 14:02:51 -070092 if (mInitCheck != OK) {
93 return NO_INIT;
94 }
95
James Dong57e7f832010-06-24 19:55:31 -070096 mTrackMaxAmplitude = false;
97 mMaxAmplitude = 0;
James Dong4c238152010-09-01 18:48:35 -070098 mInitialReadTimeUs = 0;
James Dong36e573b2010-06-19 09:04:18 -070099 mStartTimeUs = 0;
100 int64_t startTimeUs;
101 if (params && params->findInt64(kKeyTime, &startTimeUs)) {
102 mStartTimeUs = startTimeUs;
103 }
Andreas Huber07bf09d2010-01-25 14:27:12 -0800104 status_t err = mRecord->start();
Andreas Huber07bf09d2010-01-25 14:27:12 -0800105 if (err == OK) {
Andreas Huber07bf09d2010-01-25 14:27:12 -0800106 mStarted = true;
James Dongd7ef5b62011-01-25 12:37:43 -0800107 } else {
108 delete mRecord;
109 mRecord = NULL;
Andreas Huber07bf09d2010-01-25 14:27:12 -0800110 }
111
James Dongd7ef5b62011-01-25 12:37:43 -0800112
Andreas Huber07bf09d2010-01-25 14:27:12 -0800113 return err;
114}
115
James Dongd33a4cc2011-02-15 10:08:07 -0800116void AudioSource::releaseQueuedFrames_l() {
117 LOGV("releaseQueuedFrames_l");
118 List<MediaBuffer *>::iterator it;
119 while (!mBuffersReceived.empty()) {
120 it = mBuffersReceived.begin();
121 (*it)->release();
122 mBuffersReceived.erase(it);
123 }
124}
125
126void AudioSource::waitOutstandingEncodingFrames_l() {
127 LOGV("waitOutstandingEncodingFrames_l: %lld", mNumClientOwnedBuffers);
128 while (mNumClientOwnedBuffers > 0) {
129 mFrameEncodingCompletionCondition.wait(mLock);
130 }
131}
132
Andreas Huber07bf09d2010-01-25 14:27:12 -0800133status_t AudioSource::stop() {
James Dongd33a4cc2011-02-15 10:08:07 -0800134 Mutex::Autolock autoLock(mLock);
Andreas Huber07bf09d2010-01-25 14:27:12 -0800135 if (!mStarted) {
136 return UNKNOWN_ERROR;
137 }
138
James Donga87544b2010-09-01 14:02:51 -0700139 if (mInitCheck != OK) {
140 return NO_INIT;
141 }
142
Andreas Huber07bf09d2010-01-25 14:27:12 -0800143 mStarted = false;
James Dongd33a4cc2011-02-15 10:08:07 -0800144 mRecord->stop();
145 waitOutstandingEncodingFrames_l();
146 releaseQueuedFrames_l();
James Dongdae9fd32010-06-04 13:59:27 -0700147
Andreas Huber07bf09d2010-01-25 14:27:12 -0800148 return OK;
149}
150
151sp<MetaData> AudioSource::getFormat() {
James Dongd33a4cc2011-02-15 10:08:07 -0800152 Mutex::Autolock autoLock(mLock);
James Donga87544b2010-09-01 14:02:51 -0700153 if (mInitCheck != OK) {
154 return 0;
155 }
156
Andreas Huber07bf09d2010-01-25 14:27:12 -0800157 sp<MetaData> meta = new MetaData;
158 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
James Dongd33a4cc2011-02-15 10:08:07 -0800159 meta->setInt32(kKeySampleRate, mSampleRate);
Andreas Huber07bf09d2010-01-25 14:27:12 -0800160 meta->setInt32(kKeyChannelCount, mRecord->channelCount());
161 meta->setInt32(kKeyMaxInputSize, kMaxBufferSize);
162
163 return meta;
164}
165
James Dongd7f1c3d2010-08-26 16:28:17 -0700166void AudioSource::rampVolume(
167 int32_t startFrame, int32_t rampDurationFrames,
168 uint8_t *data, size_t bytes) {
169
170 const int32_t kShift = 14;
171 int32_t fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
172 const int32_t nChannels = mRecord->channelCount();
173 int32_t stopFrame = startFrame + bytes / sizeof(int16_t);
174 int16_t *frame = (int16_t *) data;
175 if (stopFrame > rampDurationFrames) {
176 stopFrame = rampDurationFrames;
177 }
178
179 while (startFrame < stopFrame) {
180 if (nChannels == 1) { // mono
181 frame[0] = (frame[0] * fixedMultiplier) >> kShift;
182 ++frame;
183 ++startFrame;
184 } else { // stereo
185 frame[0] = (frame[0] * fixedMultiplier) >> kShift;
186 frame[1] = (frame[1] * fixedMultiplier) >> kShift;
187 frame += 2;
188 startFrame += 2;
189 }
190
191 // Update the multiplier every 4 frames
192 if ((startFrame & 3) == 0) {
193 fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
194 }
195 }
196}
197
Andreas Huber07bf09d2010-01-25 14:27:12 -0800198status_t AudioSource::read(
199 MediaBuffer **out, const ReadOptions *options) {
James Dongd33a4cc2011-02-15 10:08:07 -0800200 Mutex::Autolock autoLock(mLock);
201 *out = NULL;
James Donga87544b2010-09-01 14:02:51 -0700202
203 if (mInitCheck != OK) {
204 return NO_INIT;
205 }
206
James Dongd33a4cc2011-02-15 10:08:07 -0800207 while (mStarted && mBuffersReceived.empty()) {
208 mFrameAvailableCondition.wait(mLock);
209 }
210 if (!mStarted) {
James Dong53d4e0d2010-07-21 14:51:35 -0700211 return OK;
James Dongdae9fd32010-06-04 13:59:27 -0700212 }
James Dongd33a4cc2011-02-15 10:08:07 -0800213 MediaBuffer *buffer = *mBuffersReceived.begin();
214 mBuffersReceived.erase(mBuffersReceived.begin());
215 ++mNumClientOwnedBuffers;
216 buffer->setObserver(this);
217 buffer->add_ref();
218
219 // Mute/suppress the recording sound
220 int64_t timeUs;
221 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
222 int64_t elapsedTimeUs = timeUs - mStartTimeUs;
223 if (elapsedTimeUs < kAutoRampStartUs) {
224 memset((uint8_t *) buffer->data(), 0, buffer->range_length());
225 } else if (elapsedTimeUs < kAutoRampStartUs + kAutoRampDurationUs) {
226 int32_t autoRampDurationFrames =
227 (kAutoRampDurationUs * mSampleRate + 500000LL) / 1000000LL;
228
229 int32_t autoRampStartFrames =
230 (kAutoRampStartUs * mSampleRate + 500000LL) / 1000000LL;
231
232 int32_t nFrames = mNumFramesReceived - autoRampStartFrames;
233 rampVolume(nFrames, autoRampDurationFrames,
234 (uint8_t *) buffer->data(), buffer->range_length());
235 }
236
237 // Track the max recording signal amplitude.
238 if (mTrackMaxAmplitude) {
239 trackMaxAmplitude(
240 (int16_t *) buffer->data(), buffer->range_length() >> 1);
241 }
242
243 *out = buffer;
244 return OK;
245}
246
247void AudioSource::signalBufferReturned(MediaBuffer *buffer) {
248 LOGV("signalBufferReturned: %p", buffer->data());
249 Mutex::Autolock autoLock(mLock);
250 --mNumClientOwnedBuffers;
251 buffer->setObserver(0);
252 buffer->release();
253 mFrameEncodingCompletionCondition.signal();
254 return;
255}
256
257status_t AudioSource::dataCallbackTimestamp(
258 const AudioRecord::Buffer& audioBuffer, int64_t timeUs) {
259 LOGV("dataCallbackTimestamp: %lld us", timeUs);
260 Mutex::Autolock autoLock(mLock);
261 if (!mStarted) {
262 LOGW("Spurious callback from AudioRecord. Drop the audio data.");
263 return OK;
264 }
265
James Dongcbeebb12011-02-16 12:28:26 -0800266 // Drop retrieved and previously lost audio data.
267 if (mNumFramesReceived == 0 && timeUs < mStartTimeUs) {
268 mRecord->getInputFramesLost();
269 LOGV("Drop audio data at %lld/%lld us", timeUs, mStartTimeUs);
270 return OK;
271 }
272
James Dongd33a4cc2011-02-15 10:08:07 -0800273 if (mNumFramesReceived == 0 && mPrevSampleTimeUs == 0) {
274 mInitialReadTimeUs = timeUs;
275 // Initial delay
276 if (mStartTimeUs > 0) {
277 mStartTimeUs = timeUs - mStartTimeUs;
278 } else {
279 // Assume latency is constant.
280 mStartTimeUs += mRecord->latency() * 1000;
281 }
282 mPrevSampleTimeUs = mStartTimeUs;
283 }
284
285 int64_t timestampUs = mPrevSampleTimeUs;
286
James Dongcbeebb12011-02-16 12:28:26 -0800287 size_t numLostBytes = 0;
288 if (mNumFramesReceived > 0) { // Ignore earlier frame lost
289 // getInputFramesLost() returns the number of lost frames.
290 // Convert number of frames lost to number of bytes lost.
291 numLostBytes = mRecord->getInputFramesLost() * mRecord->frameSize();
292 }
293
James Dongd33a4cc2011-02-15 10:08:07 -0800294 CHECK_EQ(numLostBytes & 1, 0u);
295 CHECK_EQ(audioBuffer.size & 1, 0u);
296 size_t bufferSize = numLostBytes + audioBuffer.size;
297 MediaBuffer *buffer = new MediaBuffer(bufferSize);
298 if (numLostBytes > 0) {
299 memset(buffer->data(), 0, numLostBytes);
300 memcpy((uint8_t *) buffer->data() + numLostBytes,
301 audioBuffer.i16, audioBuffer.size);
302 } else {
303 if (audioBuffer.size == 0) {
304 LOGW("Nothing is available from AudioRecord callback buffer");
305 buffer->release();
306 return OK;
307 }
308 memcpy((uint8_t *) buffer->data(),
309 audioBuffer.i16, audioBuffer.size);
310 }
311
312 buffer->set_range(0, bufferSize);
313 timestampUs += ((1000000LL * (bufferSize >> 1)) +
314 (mSampleRate >> 1)) / mSampleRate;
315
316 if (mNumFramesReceived == 0) {
317 buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs);
318 }
319 buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs);
320 buffer->meta_data()->setInt64(kKeyDriftTime, timeUs - mInitialReadTimeUs);
321 mPrevSampleTimeUs = timestampUs;
322 mNumFramesReceived += buffer->range_length() / sizeof(int16_t);
323 mBuffersReceived.push_back(buffer);
324 mFrameAvailableCondition.signal();
Andreas Huber07bf09d2010-01-25 14:27:12 -0800325
Andreas Huber07bf09d2010-01-25 14:27:12 -0800326 return OK;
327}
328
James Dong57e7f832010-06-24 19:55:31 -0700329void AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) {
330 for (int i = nSamples; i > 0; --i) {
331 int16_t value = *data++;
332 if (value < 0) {
333 value = -value;
334 }
335 if (mMaxAmplitude < value) {
336 mMaxAmplitude = value;
337 }
338 }
339}
340
341int16_t AudioSource::getMaxAmplitude() {
342 // First call activates the tracking.
343 if (!mTrackMaxAmplitude) {
344 mTrackMaxAmplitude = true;
345 }
346 int16_t value = mMaxAmplitude;
347 mMaxAmplitude = 0;
348 LOGV("max amplitude since last call: %d", value);
349 return value;
350}
351
Andreas Huber07bf09d2010-01-25 14:27:12 -0800352} // namespace android