blob: 3cf4d5c559d88a5e7588a20d34f691faed827d10 [file] [log] [blame]
Andreas Hubere7c9cb42010-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 Dong050b28a2010-04-22 17:27:04 -070017//#define LOG_NDEBUG 0
18#define LOG_TAG "AudioSource"
19#include <utils/Log.h>
20
Andreas Hubere7c9cb42010-01-25 14:27:12 -080021#include <media/AudioRecord.h>
James Dong6b61f432011-02-15 10:08:07 -080022#include <media/stagefright/AudioSource.h>
23#include <media/stagefright/MediaBuffer.h>
Andreas Hubere7c9cb42010-01-25 14:27:12 -080024#include <media/stagefright/MediaDefs.h>
25#include <media/stagefright/MetaData.h>
James Dong6b61f432011-02-15 10:08:07 -080026#include <media/stagefright/foundation/ADebug.h>
Andreas Huberbd381af2012-08-30 10:56:14 -070027#include <media/stagefright/foundation/ALooper.h>
James Dong365a9632010-06-04 13:59:27 -070028#include <cutils/properties.h>
James Dong46292fb2010-07-29 18:06:08 -070029#include <stdlib.h>
Andreas Hubere7c9cb42010-01-25 14:27:12 -080030
31namespace android {
32
James Dong6b61f432011-02-15 10:08:07 -080033static void AudioRecordCallbackFunction(int event, void *user, void *info) {
34 AudioSource *source = (AudioSource *) user;
35 switch (event) {
36 case AudioRecord::EVENT_MORE_DATA: {
Andreas Huberbd381af2012-08-30 10:56:14 -070037 source->dataCallback(*((AudioRecord::Buffer *) info));
James Dong6b61f432011-02-15 10:08:07 -080038 break;
39 }
40 case AudioRecord::EVENT_OVERRUN: {
Steve Block5ff1dd52012-01-05 23:22:43 +000041 ALOGW("AudioRecord reported overrun!");
James Dong6b61f432011-02-15 10:08:07 -080042 break;
43 }
44 default:
45 // does nothing
46 break;
47 }
48}
49
Andreas Hubere7c9cb42010-01-25 14:27:12 -080050AudioSource::AudioSource(
Glenn Kastenab334fd2012-03-14 12:56:06 -070051 audio_source_t inputSource, uint32_t sampleRate, uint32_t channelCount)
James Donga0108692012-06-29 15:14:20 -070052 : mRecord(NULL),
53 mStarted(false),
James Dong6b61f432011-02-15 10:08:07 -080054 mSampleRate(sampleRate),
James Dong46292fb2010-07-29 18:06:08 -070055 mPrevSampleTimeUs(0),
James Dong6b61f432011-02-15 10:08:07 -080056 mNumFramesReceived(0),
Andreas Huberfa0e0332012-10-01 16:03:44 -070057 mNumClientOwnedBuffers(0) {
Glenn Kastenab334fd2012-03-14 12:56:06 -070058 ALOGV("sampleRate: %d, channelCount: %d", sampleRate, channelCount);
59 CHECK(channelCount == 1 || channelCount == 2);
James Dongbe6ec712010-06-14 17:45:35 -070060
Glenn Kasten7da35f22012-11-14 12:54:39 -080061 size_t minFrameCount;
Eric Laurente49f2b42012-06-12 17:09:30 -070062 status_t status = AudioRecord::getMinFrameCount(&minFrameCount,
63 sampleRate,
64 AUDIO_FORMAT_PCM_16_BIT,
Glenn Kastendd8104c2012-07-02 12:42:44 -070065 audio_channel_in_mask_from_count(channelCount));
Eric Laurente49f2b42012-06-12 17:09:30 -070066 if (status == OK) {
67 // make sure that the AudioRecord callback never returns more than the maximum
68 // buffer size
69 int frameCount = kMaxBufferSize / sizeof(int16_t) / channelCount;
70
71 // make sure that the AudioRecord total buffer size is large enough
72 int bufCount = 2;
73 while ((bufCount * frameCount) < minFrameCount) {
74 bufCount++;
75 }
76
Eric Laurente49f2b42012-06-12 17:09:30 -070077 mRecord = new AudioRecord(
78 inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT,
79 audio_channel_in_mask_from_count(channelCount),
80 bufCount * frameCount,
Eric Laurente49f2b42012-06-12 17:09:30 -070081 AudioRecordCallbackFunction,
82 this,
83 frameCount);
84 mInitCheck = mRecord->initCheck();
85 } else {
86 mInitCheck = status;
87 }
Andreas Hubere7c9cb42010-01-25 14:27:12 -080088}
89
90AudioSource::~AudioSource() {
91 if (mStarted) {
James Dongb44c9d22012-02-02 18:04:02 -080092 reset();
Andreas Hubere7c9cb42010-01-25 14:27:12 -080093 }
94
95 delete mRecord;
96 mRecord = NULL;
97}
98
99status_t AudioSource::initCheck() const {
100 return mInitCheck;
101}
102
103status_t AudioSource::start(MetaData *params) {
James Dong6b61f432011-02-15 10:08:07 -0800104 Mutex::Autolock autoLock(mLock);
Andreas Hubere7c9cb42010-01-25 14:27:12 -0800105 if (mStarted) {
106 return UNKNOWN_ERROR;
107 }
108
James Dong6e20bdf2010-09-01 14:02:51 -0700109 if (mInitCheck != OK) {
110 return NO_INIT;
111 }
112
James Dongd3d4e502010-06-24 19:55:31 -0700113 mTrackMaxAmplitude = false;
114 mMaxAmplitude = 0;
James Dongd707fcb2010-09-01 18:48:35 -0700115 mInitialReadTimeUs = 0;
James Dongf60cafe2010-06-19 09:04:18 -0700116 mStartTimeUs = 0;
117 int64_t startTimeUs;
118 if (params && params->findInt64(kKeyTime, &startTimeUs)) {
119 mStartTimeUs = startTimeUs;
120 }
Andreas Hubere7c9cb42010-01-25 14:27:12 -0800121 status_t err = mRecord->start();
Andreas Hubere7c9cb42010-01-25 14:27:12 -0800122 if (err == OK) {
Andreas Hubere7c9cb42010-01-25 14:27:12 -0800123 mStarted = true;
James Dongeaae3842011-01-25 12:37:43 -0800124 } else {
125 delete mRecord;
126 mRecord = NULL;
Andreas Hubere7c9cb42010-01-25 14:27:12 -0800127 }
128
James Dongeaae3842011-01-25 12:37:43 -0800129
Andreas Hubere7c9cb42010-01-25 14:27:12 -0800130 return err;
131}
132
James Dong6b61f432011-02-15 10:08:07 -0800133void AudioSource::releaseQueuedFrames_l() {
Steve Block3856b092011-10-20 11:56:00 +0100134 ALOGV("releaseQueuedFrames_l");
James Dong6b61f432011-02-15 10:08:07 -0800135 List<MediaBuffer *>::iterator it;
136 while (!mBuffersReceived.empty()) {
137 it = mBuffersReceived.begin();
138 (*it)->release();
139 mBuffersReceived.erase(it);
140 }
141}
142
143void AudioSource::waitOutstandingEncodingFrames_l() {
Steve Block3856b092011-10-20 11:56:00 +0100144 ALOGV("waitOutstandingEncodingFrames_l: %lld", mNumClientOwnedBuffers);
James Dong6b61f432011-02-15 10:08:07 -0800145 while (mNumClientOwnedBuffers > 0) {
146 mFrameEncodingCompletionCondition.wait(mLock);
147 }
148}
149
James Dongb44c9d22012-02-02 18:04:02 -0800150status_t AudioSource::reset() {
James Dong6b61f432011-02-15 10:08:07 -0800151 Mutex::Autolock autoLock(mLock);
Andreas Hubere7c9cb42010-01-25 14:27:12 -0800152 if (!mStarted) {
153 return UNKNOWN_ERROR;
154 }
155
James Dong6e20bdf2010-09-01 14:02:51 -0700156 if (mInitCheck != OK) {
157 return NO_INIT;
158 }
159
Andreas Hubere7c9cb42010-01-25 14:27:12 -0800160 mStarted = false;
James Dong6b61f432011-02-15 10:08:07 -0800161 mRecord->stop();
162 waitOutstandingEncodingFrames_l();
163 releaseQueuedFrames_l();
James Dong365a9632010-06-04 13:59:27 -0700164
Andreas Hubere7c9cb42010-01-25 14:27:12 -0800165 return OK;
166}
167
168sp<MetaData> AudioSource::getFormat() {
James Dong6b61f432011-02-15 10:08:07 -0800169 Mutex::Autolock autoLock(mLock);
James Dong6e20bdf2010-09-01 14:02:51 -0700170 if (mInitCheck != OK) {
171 return 0;
172 }
173
Andreas Hubere7c9cb42010-01-25 14:27:12 -0800174 sp<MetaData> meta = new MetaData;
175 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
James Dong6b61f432011-02-15 10:08:07 -0800176 meta->setInt32(kKeySampleRate, mSampleRate);
Andreas Hubere7c9cb42010-01-25 14:27:12 -0800177 meta->setInt32(kKeyChannelCount, mRecord->channelCount());
178 meta->setInt32(kKeyMaxInputSize, kMaxBufferSize);
179
180 return meta;
181}
182
James Dongf1ae1962010-08-26 16:28:17 -0700183void AudioSource::rampVolume(
184 int32_t startFrame, int32_t rampDurationFrames,
185 uint8_t *data, size_t bytes) {
186
187 const int32_t kShift = 14;
188 int32_t fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
189 const int32_t nChannels = mRecord->channelCount();
190 int32_t stopFrame = startFrame + bytes / sizeof(int16_t);
191 int16_t *frame = (int16_t *) data;
192 if (stopFrame > rampDurationFrames) {
193 stopFrame = rampDurationFrames;
194 }
195
196 while (startFrame < stopFrame) {
197 if (nChannels == 1) { // mono
198 frame[0] = (frame[0] * fixedMultiplier) >> kShift;
199 ++frame;
200 ++startFrame;
201 } else { // stereo
202 frame[0] = (frame[0] * fixedMultiplier) >> kShift;
203 frame[1] = (frame[1] * fixedMultiplier) >> kShift;
204 frame += 2;
205 startFrame += 2;
206 }
207
208 // Update the multiplier every 4 frames
209 if ((startFrame & 3) == 0) {
210 fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
211 }
212 }
213}
214
Andreas Hubere7c9cb42010-01-25 14:27:12 -0800215status_t AudioSource::read(
216 MediaBuffer **out, const ReadOptions *options) {
James Dong6b61f432011-02-15 10:08:07 -0800217 Mutex::Autolock autoLock(mLock);
218 *out = NULL;
James Dong6e20bdf2010-09-01 14:02:51 -0700219
220 if (mInitCheck != OK) {
221 return NO_INIT;
222 }
223
James Dong6b61f432011-02-15 10:08:07 -0800224 while (mStarted && mBuffersReceived.empty()) {
225 mFrameAvailableCondition.wait(mLock);
226 }
227 if (!mStarted) {
James Dong542db5d2010-07-21 14:51:35 -0700228 return OK;
James Dong365a9632010-06-04 13:59:27 -0700229 }
James Dong6b61f432011-02-15 10:08:07 -0800230 MediaBuffer *buffer = *mBuffersReceived.begin();
231 mBuffersReceived.erase(mBuffersReceived.begin());
232 ++mNumClientOwnedBuffers;
233 buffer->setObserver(this);
234 buffer->add_ref();
235
236 // Mute/suppress the recording sound
237 int64_t timeUs;
238 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
239 int64_t elapsedTimeUs = timeUs - mStartTimeUs;
240 if (elapsedTimeUs < kAutoRampStartUs) {
241 memset((uint8_t *) buffer->data(), 0, buffer->range_length());
242 } else if (elapsedTimeUs < kAutoRampStartUs + kAutoRampDurationUs) {
243 int32_t autoRampDurationFrames =
244 (kAutoRampDurationUs * mSampleRate + 500000LL) / 1000000LL;
245
246 int32_t autoRampStartFrames =
247 (kAutoRampStartUs * mSampleRate + 500000LL) / 1000000LL;
248
249 int32_t nFrames = mNumFramesReceived - autoRampStartFrames;
250 rampVolume(nFrames, autoRampDurationFrames,
251 (uint8_t *) buffer->data(), buffer->range_length());
252 }
253
254 // Track the max recording signal amplitude.
255 if (mTrackMaxAmplitude) {
256 trackMaxAmplitude(
257 (int16_t *) buffer->data(), buffer->range_length() >> 1);
258 }
259
260 *out = buffer;
261 return OK;
262}
263
264void AudioSource::signalBufferReturned(MediaBuffer *buffer) {
Steve Block3856b092011-10-20 11:56:00 +0100265 ALOGV("signalBufferReturned: %p", buffer->data());
James Dong6b61f432011-02-15 10:08:07 -0800266 Mutex::Autolock autoLock(mLock);
267 --mNumClientOwnedBuffers;
268 buffer->setObserver(0);
269 buffer->release();
270 mFrameEncodingCompletionCondition.signal();
271 return;
272}
273
Andreas Huberbd381af2012-08-30 10:56:14 -0700274status_t AudioSource::dataCallback(const AudioRecord::Buffer& audioBuffer) {
Andreas Huberfa0e0332012-10-01 16:03:44 -0700275 int64_t timeUs = systemTime() / 1000ll;
Andreas Huberbd381af2012-08-30 10:56:14 -0700276
Steve Block3856b092011-10-20 11:56:00 +0100277 ALOGV("dataCallbackTimestamp: %lld us", timeUs);
James Dong6b61f432011-02-15 10:08:07 -0800278 Mutex::Autolock autoLock(mLock);
279 if (!mStarted) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000280 ALOGW("Spurious callback from AudioRecord. Drop the audio data.");
James Dong6b61f432011-02-15 10:08:07 -0800281 return OK;
282 }
283
James Donga4726132011-02-16 12:28:26 -0800284 // Drop retrieved and previously lost audio data.
285 if (mNumFramesReceived == 0 && timeUs < mStartTimeUs) {
286 mRecord->getInputFramesLost();
Steve Block3856b092011-10-20 11:56:00 +0100287 ALOGV("Drop audio data at %lld/%lld us", timeUs, mStartTimeUs);
James Donga4726132011-02-16 12:28:26 -0800288 return OK;
289 }
290
James Dong6b61f432011-02-15 10:08:07 -0800291 if (mNumFramesReceived == 0 && mPrevSampleTimeUs == 0) {
292 mInitialReadTimeUs = timeUs;
293 // Initial delay
Andreas Huberfa0e0332012-10-01 16:03:44 -0700294 if (mStartTimeUs > 0) {
James Dong6b61f432011-02-15 10:08:07 -0800295 mStartTimeUs = timeUs - mStartTimeUs;
296 } else {
297 // Assume latency is constant.
298 mStartTimeUs += mRecord->latency() * 1000;
299 }
Andreas Huberbd381af2012-08-30 10:56:14 -0700300
James Dong6b61f432011-02-15 10:08:07 -0800301 mPrevSampleTimeUs = mStartTimeUs;
302 }
303
James Donga4726132011-02-16 12:28:26 -0800304 size_t numLostBytes = 0;
305 if (mNumFramesReceived > 0) { // Ignore earlier frame lost
306 // getInputFramesLost() returns the number of lost frames.
307 // Convert number of frames lost to number of bytes lost.
308 numLostBytes = mRecord->getInputFramesLost() * mRecord->frameSize();
309 }
310
James Dong6b61f432011-02-15 10:08:07 -0800311 CHECK_EQ(numLostBytes & 1, 0u);
312 CHECK_EQ(audioBuffer.size & 1, 0u);
James Dong6b61f432011-02-15 10:08:07 -0800313 if (numLostBytes > 0) {
James Dongb575ddc2012-02-14 14:58:20 -0800314 // Loss of audio frames should happen rarely; thus the LOGW should
315 // not cause a logging spam
316 ALOGW("Lost audio record data: %d bytes", numLostBytes);
James Dong6b61f432011-02-15 10:08:07 -0800317 }
318
James Dongb575ddc2012-02-14 14:58:20 -0800319 while (numLostBytes > 0) {
320 size_t bufferSize = numLostBytes;
321 if (numLostBytes > kMaxBufferSize) {
322 numLostBytes -= kMaxBufferSize;
323 bufferSize = kMaxBufferSize;
324 } else {
325 numLostBytes = 0;
326 }
327 MediaBuffer *lostAudioBuffer = new MediaBuffer(bufferSize);
328 memset(lostAudioBuffer->data(), 0, bufferSize);
329 lostAudioBuffer->set_range(0, bufferSize);
330 queueInputBuffer_l(lostAudioBuffer, timeUs);
331 }
332
333 if (audioBuffer.size == 0) {
334 ALOGW("Nothing is available from AudioRecord callback buffer");
335 return OK;
336 }
337
338 const size_t bufferSize = audioBuffer.size;
339 MediaBuffer *buffer = new MediaBuffer(bufferSize);
340 memcpy((uint8_t *) buffer->data(),
341 audioBuffer.i16, audioBuffer.size);
James Dong6b61f432011-02-15 10:08:07 -0800342 buffer->set_range(0, bufferSize);
James Dongb575ddc2012-02-14 14:58:20 -0800343 queueInputBuffer_l(buffer, timeUs);
344 return OK;
345}
346
347void AudioSource::queueInputBuffer_l(MediaBuffer *buffer, int64_t timeUs) {
348 const size_t bufferSize = buffer->range_length();
349 const size_t frameSize = mRecord->frameSize();
350 const int64_t timestampUs =
351 mPrevSampleTimeUs +
352 ((1000000LL * (bufferSize / frameSize)) +
353 (mSampleRate >> 1)) / mSampleRate;
James Dong6b61f432011-02-15 10:08:07 -0800354
355 if (mNumFramesReceived == 0) {
356 buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs);
357 }
James Dongb575ddc2012-02-14 14:58:20 -0800358
James Dong6b61f432011-02-15 10:08:07 -0800359 buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs);
360 buffer->meta_data()->setInt64(kKeyDriftTime, timeUs - mInitialReadTimeUs);
361 mPrevSampleTimeUs = timestampUs;
James Dongb575ddc2012-02-14 14:58:20 -0800362 mNumFramesReceived += bufferSize / frameSize;
James Dong6b61f432011-02-15 10:08:07 -0800363 mBuffersReceived.push_back(buffer);
364 mFrameAvailableCondition.signal();
Andreas Hubere7c9cb42010-01-25 14:27:12 -0800365}
366
James Dongd3d4e502010-06-24 19:55:31 -0700367void AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) {
368 for (int i = nSamples; i > 0; --i) {
369 int16_t value = *data++;
370 if (value < 0) {
371 value = -value;
372 }
373 if (mMaxAmplitude < value) {
374 mMaxAmplitude = value;
375 }
376 }
377}
378
379int16_t AudioSource::getMaxAmplitude() {
380 // First call activates the tracking.
381 if (!mTrackMaxAmplitude) {
382 mTrackMaxAmplitude = true;
383 }
384 int16_t value = mMaxAmplitude;
385 mMaxAmplitude = 0;
Steve Block3856b092011-10-20 11:56:00 +0100386 ALOGV("max amplitude since last call: %d", value);
James Dongd3d4e502010-06-24 19:55:31 -0700387 return value;
388}
389
Andreas Hubere7c9cb42010-01-25 14:27:12 -0800390} // namespace android