blob: bd04a26266244f923f698e02bbb1222c18f5b5ba [file] [log] [blame]
Andreas Hubere46b7be2009-07-14 16:56:47 -07001/*
2 * Copyright (C) 2009 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
Andreas Huberc997aca2009-11-05 16:34:39 -080017//#define LOG_NDEBUG 0
Andreas Hubere46b7be2009-07-14 16:56:47 -070018#define LOG_TAG "AudioPlayer"
19#include <utils/Log.h>
20
Andreas Huber5f0d5ce2010-03-01 14:27:00 -080021#include <binder/IPCThreadState.h>
Andreas Hubere46b7be2009-07-14 16:56:47 -070022#include <media/AudioTrack.h>
23#include <media/stagefright/AudioPlayer.h>
Andreas Huberb5ceb9e2009-08-26 14:48:20 -070024#include <media/stagefright/MediaDebug.h>
Andreas Hubere6c40962009-09-10 14:13:30 -070025#include <media/stagefright/MediaDefs.h>
Andreas Huber16263d92010-07-20 09:44:34 -070026#include <media/stagefright/MediaErrors.h>
Andreas Hubere46b7be2009-07-14 16:56:47 -070027#include <media/stagefright/MediaSource.h>
28#include <media/stagefright/MetaData.h>
29
Andreas Huber2b359ed2010-09-28 11:56:39 -070030#include "include/AwesomePlayer.h"
31
Andreas Hubere46b7be2009-07-14 16:56:47 -070032namespace android {
33
Andreas Huber2b359ed2010-09-28 11:56:39 -070034AudioPlayer::AudioPlayer(
35 const sp<MediaPlayerBase::AudioSink> &audioSink,
36 AwesomePlayer *observer)
Andreas Huberbe06d262009-08-14 14:37:10 -070037 : mAudioTrack(NULL),
Andreas Hubere46b7be2009-07-14 16:56:47 -070038 mInputBuffer(NULL),
39 mSampleRate(0),
40 mLatencyUs(0),
41 mFrameSize(0),
42 mNumFramesPlayed(0),
43 mPositionTimeMediaUs(-1),
44 mPositionTimeRealUs(-1),
45 mSeeking(false),
Andreas Huber70d10c02010-02-03 11:37:29 -080046 mReachedEOS(false),
Andreas Huberd7d22eb2010-02-23 13:45:33 -080047 mFinalStatus(OK),
Andreas Hubere46b7be2009-07-14 16:56:47 -070048 mStarted(false),
Andreas Huber16263d92010-07-20 09:44:34 -070049 mIsFirstBuffer(false),
50 mFirstBufferResult(OK),
51 mFirstBuffer(NULL),
Andreas Huber2b359ed2010-09-28 11:56:39 -070052 mAudioSink(audioSink),
53 mObserver(observer) {
Andreas Hubere46b7be2009-07-14 16:56:47 -070054}
55
56AudioPlayer::~AudioPlayer() {
57 if (mStarted) {
Andreas Huberc743f452010-10-05 10:25:34 -070058 reset();
Andreas Hubere46b7be2009-07-14 16:56:47 -070059 }
60}
61
Andreas Huberbe06d262009-08-14 14:37:10 -070062void AudioPlayer::setSource(const sp<MediaSource> &source) {
Andreas Huberb5ceb9e2009-08-26 14:48:20 -070063 CHECK_EQ(mSource, NULL);
Andreas Hubere46b7be2009-07-14 16:56:47 -070064 mSource = source;
65}
66
Andreas Huberdc9927d2010-03-08 15:46:13 -080067status_t AudioPlayer::start(bool sourceAlreadyStarted) {
Andreas Huberb5ceb9e2009-08-26 14:48:20 -070068 CHECK(!mStarted);
69 CHECK(mSource != NULL);
Andreas Hubere46b7be2009-07-14 16:56:47 -070070
Andreas Huberdc9927d2010-03-08 15:46:13 -080071 status_t err;
72 if (!sourceAlreadyStarted) {
73 err = mSource->start();
Andreas Huber62eac002010-01-29 13:24:58 -080074
Andreas Huberdc9927d2010-03-08 15:46:13 -080075 if (err != OK) {
76 return err;
77 }
Andreas Huber62eac002010-01-29 13:24:58 -080078 }
Andreas Hubere46b7be2009-07-14 16:56:47 -070079
Andreas Huber16263d92010-07-20 09:44:34 -070080 // We allow an optional INFO_FORMAT_CHANGED at the very beginning
81 // of playback, if there is one, getFormat below will retrieve the
82 // updated format, if there isn't, we'll stash away the valid buffer
83 // of data to be used on the first audio callback.
84
85 CHECK(mFirstBuffer == NULL);
86
87 mFirstBufferResult = mSource->read(&mFirstBuffer);
88 if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
89 LOGV("INFO_FORMAT_CHANGED!!!");
90
91 CHECK(mFirstBuffer == NULL);
92 mFirstBufferResult = OK;
93 mIsFirstBuffer = false;
94 } else {
95 mIsFirstBuffer = true;
96 }
97
Andreas Hubere46b7be2009-07-14 16:56:47 -070098 sp<MetaData> format = mSource->getFormat();
99 const char *mime;
100 bool success = format->findCString(kKeyMIMEType, &mime);
Andreas Huberb5ceb9e2009-08-26 14:48:20 -0700101 CHECK(success);
Andreas Hubere6c40962009-09-10 14:13:30 -0700102 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
Andreas Hubere46b7be2009-07-14 16:56:47 -0700103
104 success = format->findInt32(kKeySampleRate, &mSampleRate);
Andreas Huberb5ceb9e2009-08-26 14:48:20 -0700105 CHECK(success);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700106
107 int32_t numChannels;
108 success = format->findInt32(kKeyChannelCount, &numChannels);
Andreas Huberb5ceb9e2009-08-26 14:48:20 -0700109 CHECK(success);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700110
111 if (mAudioSink.get() != NULL) {
112 status_t err = mAudioSink->open(
113 mSampleRate, numChannels, AudioSystem::PCM_16_BIT,
114 DEFAULT_AUDIOSINK_BUFFERCOUNT,
115 &AudioPlayer::AudioSinkCallback, this);
Andreas Huber62eac002010-01-29 13:24:58 -0800116 if (err != OK) {
Andreas Huber16263d92010-07-20 09:44:34 -0700117 if (mFirstBuffer != NULL) {
118 mFirstBuffer->release();
119 mFirstBuffer = NULL;
120 }
121
122 if (!sourceAlreadyStarted) {
123 mSource->stop();
124 }
Andreas Huber62eac002010-01-29 13:24:58 -0800125
126 return err;
127 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700128
129 mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
130 mFrameSize = mAudioSink->frameSize();
131
132 mAudioSink->start();
133 } else {
134 mAudioTrack = new AudioTrack(
135 AudioSystem::MUSIC, mSampleRate, AudioSystem::PCM_16_BIT,
Andreas Huber8a432772009-07-28 10:03:13 -0700136 (numChannels == 2)
137 ? AudioSystem::CHANNEL_OUT_STEREO
138 : AudioSystem::CHANNEL_OUT_MONO,
Andreas Huber662292a2010-04-13 09:58:39 -0700139 0, 0, &AudioCallback, this, 0);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700140
Kenny Root3cbd62c2010-02-18 09:03:06 -0800141 if ((err = mAudioTrack->initCheck()) != OK) {
Andreas Huber62eac002010-01-29 13:24:58 -0800142 delete mAudioTrack;
143 mAudioTrack = NULL;
144
Andreas Huber16263d92010-07-20 09:44:34 -0700145 if (mFirstBuffer != NULL) {
146 mFirstBuffer->release();
147 mFirstBuffer = NULL;
148 }
149
150 if (!sourceAlreadyStarted) {
151 mSource->stop();
152 }
Andreas Huber62eac002010-01-29 13:24:58 -0800153
Kenny Root3cbd62c2010-02-18 09:03:06 -0800154 return err;
Andreas Huber62eac002010-01-29 13:24:58 -0800155 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700156
157 mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
158 mFrameSize = mAudioTrack->frameSize();
159
160 mAudioTrack->start();
161 }
162
163 mStarted = true;
Andreas Huber62eac002010-01-29 13:24:58 -0800164
165 return OK;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700166}
167
Andreas Huberc743f452010-10-05 10:25:34 -0700168void AudioPlayer::pause(bool playPendingSamples) {
Andreas Huberb5ceb9e2009-08-26 14:48:20 -0700169 CHECK(mStarted);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700170
Andreas Huberc743f452010-10-05 10:25:34 -0700171 if (playPendingSamples) {
172 if (mAudioSink.get() != NULL) {
173 mAudioSink->stop();
174 } else {
175 mAudioTrack->stop();
176 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700177 } else {
Andreas Huberc743f452010-10-05 10:25:34 -0700178 if (mAudioSink.get() != NULL) {
179 mAudioSink->pause();
180 } else {
181 mAudioTrack->pause();
182 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700183 }
184}
185
186void AudioPlayer::resume() {
Andreas Huberb5ceb9e2009-08-26 14:48:20 -0700187 CHECK(mStarted);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700188
189 if (mAudioSink.get() != NULL) {
190 mAudioSink->start();
191 } else {
192 mAudioTrack->start();
193 }
194}
195
Andreas Huberc743f452010-10-05 10:25:34 -0700196void AudioPlayer::reset() {
Andreas Huberb5ceb9e2009-08-26 14:48:20 -0700197 CHECK(mStarted);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700198
199 if (mAudioSink.get() != NULL) {
200 mAudioSink->stop();
Andreas Huberaee3c632010-01-11 15:35:19 -0800201 mAudioSink->close();
Andreas Hubere46b7be2009-07-14 16:56:47 -0700202 } else {
203 mAudioTrack->stop();
204
205 delete mAudioTrack;
206 mAudioTrack = NULL;
207 }
Andreas Huberaee3c632010-01-11 15:35:19 -0800208
Andreas Hubere46b7be2009-07-14 16:56:47 -0700209 // Make sure to release any buffer we hold onto so that the
210 // source is able to stop().
Andreas Huber16263d92010-07-20 09:44:34 -0700211
212 if (mFirstBuffer != NULL) {
213 mFirstBuffer->release();
214 mFirstBuffer = NULL;
215 }
216
Andreas Hubere46b7be2009-07-14 16:56:47 -0700217 if (mInputBuffer != NULL) {
Andreas Huberc997aca2009-11-05 16:34:39 -0800218 LOGV("AudioPlayer releasing input buffer.");
Andreas Hubere46b7be2009-07-14 16:56:47 -0700219
220 mInputBuffer->release();
221 mInputBuffer = NULL;
222 }
223
224 mSource->stop();
Andreas Huberaee3c632010-01-11 15:35:19 -0800225
Andreas Huber5f0d5ce2010-03-01 14:27:00 -0800226 // The following hack is necessary to ensure that the OMX
227 // component is completely released by the time we may try
228 // to instantiate it again.
229 wp<MediaSource> tmp = mSource;
230 mSource.clear();
231 while (tmp.promote() != NULL) {
232 usleep(1000);
233 }
234 IPCThreadState::self()->flushCommands();
235
Andreas Hubere46b7be2009-07-14 16:56:47 -0700236 mNumFramesPlayed = 0;
237 mPositionTimeMediaUs = -1;
238 mPositionTimeRealUs = -1;
239 mSeeking = false;
Andreas Huber70d10c02010-02-03 11:37:29 -0800240 mReachedEOS = false;
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800241 mFinalStatus = OK;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700242 mStarted = false;
243}
244
245// static
246void AudioPlayer::AudioCallback(int event, void *user, void *info) {
247 static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
248}
249
Andreas Huber70d10c02010-02-03 11:37:29 -0800250bool AudioPlayer::isSeeking() {
251 Mutex::Autolock autoLock(mLock);
252 return mSeeking;
253}
254
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800255bool AudioPlayer::reachedEOS(status_t *finalStatus) {
256 *finalStatus = OK;
257
Andreas Huber70d10c02010-02-03 11:37:29 -0800258 Mutex::Autolock autoLock(mLock);
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800259 *finalStatus = mFinalStatus;
Andreas Huber70d10c02010-02-03 11:37:29 -0800260 return mReachedEOS;
261}
262
Andreas Hubere46b7be2009-07-14 16:56:47 -0700263// static
Andreas Huber6ed937e2010-02-09 16:59:18 -0800264size_t AudioPlayer::AudioSinkCallback(
Andreas Hubere46b7be2009-07-14 16:56:47 -0700265 MediaPlayerBase::AudioSink *audioSink,
266 void *buffer, size_t size, void *cookie) {
267 AudioPlayer *me = (AudioPlayer *)cookie;
268
Andreas Huber6ed937e2010-02-09 16:59:18 -0800269 return me->fillBuffer(buffer, size);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700270}
271
272void AudioPlayer::AudioCallback(int event, void *info) {
273 if (event != AudioTrack::EVENT_MORE_DATA) {
274 return;
275 }
276
277 AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
Andreas Huber6ed937e2010-02-09 16:59:18 -0800278 size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
279
280 buffer->size = numBytesWritten;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700281}
282
Andreas Huber6ed937e2010-02-09 16:59:18 -0800283size_t AudioPlayer::fillBuffer(void *data, size_t size) {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700284 if (mNumFramesPlayed == 0) {
Andreas Huberc997aca2009-11-05 16:34:39 -0800285 LOGV("AudioCallback");
Andreas Hubere46b7be2009-07-14 16:56:47 -0700286 }
287
Andreas Huber70d10c02010-02-03 11:37:29 -0800288 if (mReachedEOS) {
Andreas Huber4aeec2d2011-01-26 10:41:38 -0800289 memset(data, 0, size);
290
291 return size;
Andreas Huber70d10c02010-02-03 11:37:29 -0800292 }
293
Andreas Hubere46b7be2009-07-14 16:56:47 -0700294 size_t size_done = 0;
295 size_t size_remaining = size;
296 while (size_remaining > 0) {
297 MediaSource::ReadOptions options;
298
299 {
300 Mutex::Autolock autoLock(mLock);
301
302 if (mSeeking) {
Andreas Huber16263d92010-07-20 09:44:34 -0700303 if (mIsFirstBuffer) {
304 if (mFirstBuffer != NULL) {
305 mFirstBuffer->release();
306 mFirstBuffer = NULL;
307 }
308 mIsFirstBuffer = false;
309 }
310
Andreas Hubere46b7be2009-07-14 16:56:47 -0700311 options.setSeekTo(mSeekTimeUs);
312
313 if (mInputBuffer != NULL) {
314 mInputBuffer->release();
315 mInputBuffer = NULL;
316 }
Gloria Wang2b7bb212010-02-04 17:43:09 -0800317
318 mSeeking = false;
Andreas Huber2b359ed2010-09-28 11:56:39 -0700319 if (mObserver) {
320 mObserver->postAudioSeekComplete();
321 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700322 }
323 }
324
325 if (mInputBuffer == NULL) {
Andreas Huber16263d92010-07-20 09:44:34 -0700326 status_t err;
327
328 if (mIsFirstBuffer) {
329 mInputBuffer = mFirstBuffer;
330 mFirstBuffer = NULL;
331 err = mFirstBufferResult;
332
333 mIsFirstBuffer = false;
334 } else {
335 err = mSource->read(&mInputBuffer, &options);
336 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700337
Andreas Huberb5ceb9e2009-08-26 14:48:20 -0700338 CHECK((err == OK && mInputBuffer != NULL)
Andreas Hubere46b7be2009-07-14 16:56:47 -0700339 || (err != OK && mInputBuffer == NULL));
340
Andreas Huber70d10c02010-02-03 11:37:29 -0800341 Mutex::Autolock autoLock(mLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800342
Andreas Hubere46b7be2009-07-14 16:56:47 -0700343 if (err != OK) {
Andreas Huber2b359ed2010-09-28 11:56:39 -0700344 if (mObserver && !mReachedEOS) {
345 mObserver->postAudioEOS();
346 }
347
Andreas Huber70d10c02010-02-03 11:37:29 -0800348 mReachedEOS = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800349 mFinalStatus = err;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700350 break;
351 }
352
Andreas Huberfa8de752009-10-08 10:07:49 -0700353 CHECK(mInputBuffer->meta_data()->findInt64(
354 kKeyTime, &mPositionTimeMediaUs));
Andreas Huber8a432772009-07-28 10:03:13 -0700355
Andreas Hubere46b7be2009-07-14 16:56:47 -0700356 mPositionTimeRealUs =
Andreas Huber065f69e2010-02-03 15:35:59 -0800357 ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
Andreas Huber8a432772009-07-28 10:03:13 -0700358 / mSampleRate;
Andreas Huberc997aca2009-11-05 16:34:39 -0800359
360 LOGV("buffer->size() = %d, "
361 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
362 mInputBuffer->range_length(),
363 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700364 }
365
366 if (mInputBuffer->range_length() == 0) {
367 mInputBuffer->release();
368 mInputBuffer = NULL;
369
370 continue;
371 }
372
373 size_t copy = size_remaining;
374 if (copy > mInputBuffer->range_length()) {
375 copy = mInputBuffer->range_length();
376 }
377
378 memcpy((char *)data + size_done,
379 (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
380 copy);
381
382 mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
383 mInputBuffer->range_length() - copy);
Andreas Huberaee3c632010-01-11 15:35:19 -0800384
Andreas Hubere46b7be2009-07-14 16:56:47 -0700385 size_done += copy;
386 size_remaining -= copy;
387 }
388
389 Mutex::Autolock autoLock(mLock);
Andreas Huber6ed937e2010-02-09 16:59:18 -0800390 mNumFramesPlayed += size_done / mFrameSize;
391
392 return size_done;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700393}
394
395int64_t AudioPlayer::getRealTimeUs() {
396 Mutex::Autolock autoLock(mLock);
397 return getRealTimeUsLocked();
398}
399
400int64_t AudioPlayer::getRealTimeUsLocked() const {
401 return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
402}
403
404int64_t AudioPlayer::getMediaTimeUs() {
405 Mutex::Autolock autoLock(mLock);
406
Andreas Huberc119f7e2010-02-03 10:23:26 -0800407 if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
Andreas Huber59529e12011-03-25 16:36:13 -0700408 if (mSeeking) {
409 return mSeekTimeUs;
410 }
411
Andreas Huberc119f7e2010-02-03 10:23:26 -0800412 return 0;
413 }
414
Andreas Huber065f69e2010-02-03 15:35:59 -0800415 int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs;
416 if (realTimeOffset < 0) {
417 realTimeOffset = 0;
418 }
419
420 return mPositionTimeMediaUs + realTimeOffset;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700421}
422
423bool AudioPlayer::getMediaTimeMapping(
424 int64_t *realtime_us, int64_t *mediatime_us) {
425 Mutex::Autolock autoLock(mLock);
426
427 *realtime_us = mPositionTimeRealUs;
428 *mediatime_us = mPositionTimeMediaUs;
429
Andreas Huberc119f7e2010-02-03 10:23:26 -0800430 return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700431}
432
433status_t AudioPlayer::seekTo(int64_t time_us) {
434 Mutex::Autolock autoLock(mLock);
435
436 mSeeking = true;
Andreas Huber59529e12011-03-25 16:36:13 -0700437 mPositionTimeRealUs = mPositionTimeMediaUs = -1;
Andreas Huber70d10c02010-02-03 11:37:29 -0800438 mReachedEOS = false;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700439 mSeekTimeUs = time_us;
440
Andreas Huberad3fcfe2010-09-28 13:13:38 -0700441 if (mAudioSink != NULL) {
442 mAudioSink->flush();
443 } else {
444 mAudioTrack->flush();
445 }
446
Andreas Hubere46b7be2009-07-14 16:56:47 -0700447 return OK;
448}
449
450}