blob: 9a9c3efa48d3c7a05a7666e2ae4e6b2215808355 [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>
Andreas Huber84584472011-09-08 11:33:47 -070023#include <media/stagefright/foundation/ADebug.h>
Andreas Hubere46b7be2009-07-14 16:56:47 -070024#include <media/stagefright/AudioPlayer.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 Huber84584472011-09-08 11:33:47 -070063 CHECK(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
Andreas Huber5fd43e32011-05-10 13:56:39 -070087 MediaSource::ReadOptions options;
88 if (mSeeking) {
89 options.setSeekTo(mSeekTimeUs);
90 mSeeking = false;
91 }
92
93 mFirstBufferResult = mSource->read(&mFirstBuffer, &options);
Andreas Huber16263d92010-07-20 09:44:34 -070094 if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
Steve Block71f2cf12011-10-20 11:56:00 +010095 ALOGV("INFO_FORMAT_CHANGED!!!");
Andreas Huber16263d92010-07-20 09:44:34 -070096
97 CHECK(mFirstBuffer == NULL);
98 mFirstBufferResult = OK;
99 mIsFirstBuffer = false;
100 } else {
101 mIsFirstBuffer = true;
102 }
103
Andreas Hubere46b7be2009-07-14 16:56:47 -0700104 sp<MetaData> format = mSource->getFormat();
105 const char *mime;
106 bool success = format->findCString(kKeyMIMEType, &mime);
Andreas Huberb5ceb9e2009-08-26 14:48:20 -0700107 CHECK(success);
Andreas Hubere6c40962009-09-10 14:13:30 -0700108 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
Andreas Hubere46b7be2009-07-14 16:56:47 -0700109
110 success = format->findInt32(kKeySampleRate, &mSampleRate);
Andreas Huberb5ceb9e2009-08-26 14:48:20 -0700111 CHECK(success);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700112
113 int32_t numChannels;
114 success = format->findInt32(kKeyChannelCount, &numChannels);
Andreas Huberb5ceb9e2009-08-26 14:48:20 -0700115 CHECK(success);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700116
117 if (mAudioSink.get() != NULL) {
118 status_t err = mAudioSink->open(
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700119 mSampleRate, numChannels, AUDIO_FORMAT_PCM_16_BIT,
Andreas Hubere46b7be2009-07-14 16:56:47 -0700120 DEFAULT_AUDIOSINK_BUFFERCOUNT,
121 &AudioPlayer::AudioSinkCallback, this);
Andreas Huber62eac002010-01-29 13:24:58 -0800122 if (err != OK) {
Andreas Huber16263d92010-07-20 09:44:34 -0700123 if (mFirstBuffer != NULL) {
124 mFirstBuffer->release();
125 mFirstBuffer = NULL;
126 }
127
128 if (!sourceAlreadyStarted) {
129 mSource->stop();
130 }
Andreas Huber62eac002010-01-29 13:24:58 -0800131
132 return err;
133 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700134
135 mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
136 mFrameSize = mAudioSink->frameSize();
137
138 mAudioSink->start();
139 } else {
140 mAudioTrack = new AudioTrack(
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700141 AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT,
Andreas Huber8a432772009-07-28 10:03:13 -0700142 (numChannels == 2)
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700143 ? AUDIO_CHANNEL_OUT_STEREO
144 : AUDIO_CHANNEL_OUT_MONO,
Andreas Huber662292a2010-04-13 09:58:39 -0700145 0, 0, &AudioCallback, this, 0);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700146
Kenny Root3cbd62c2010-02-18 09:03:06 -0800147 if ((err = mAudioTrack->initCheck()) != OK) {
Andreas Huber62eac002010-01-29 13:24:58 -0800148 delete mAudioTrack;
149 mAudioTrack = NULL;
150
Andreas Huber16263d92010-07-20 09:44:34 -0700151 if (mFirstBuffer != NULL) {
152 mFirstBuffer->release();
153 mFirstBuffer = NULL;
154 }
155
156 if (!sourceAlreadyStarted) {
157 mSource->stop();
158 }
Andreas Huber62eac002010-01-29 13:24:58 -0800159
Kenny Root3cbd62c2010-02-18 09:03:06 -0800160 return err;
Andreas Huber62eac002010-01-29 13:24:58 -0800161 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700162
163 mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
164 mFrameSize = mAudioTrack->frameSize();
165
166 mAudioTrack->start();
167 }
168
169 mStarted = true;
Andreas Huber62eac002010-01-29 13:24:58 -0800170
171 return OK;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700172}
173
Andreas Huberc743f452010-10-05 10:25:34 -0700174void AudioPlayer::pause(bool playPendingSamples) {
Andreas Huberb5ceb9e2009-08-26 14:48:20 -0700175 CHECK(mStarted);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700176
Andreas Huberc743f452010-10-05 10:25:34 -0700177 if (playPendingSamples) {
178 if (mAudioSink.get() != NULL) {
179 mAudioSink->stop();
180 } else {
181 mAudioTrack->stop();
182 }
Andreas Huber9ba16f62011-08-26 11:26:25 -0700183
184 mNumFramesPlayed = 0;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700185 } else {
Andreas Huberc743f452010-10-05 10:25:34 -0700186 if (mAudioSink.get() != NULL) {
187 mAudioSink->pause();
188 } else {
189 mAudioTrack->pause();
190 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700191 }
192}
193
194void AudioPlayer::resume() {
Andreas Huberb5ceb9e2009-08-26 14:48:20 -0700195 CHECK(mStarted);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700196
197 if (mAudioSink.get() != NULL) {
198 mAudioSink->start();
199 } else {
200 mAudioTrack->start();
201 }
202}
203
Andreas Huberc743f452010-10-05 10:25:34 -0700204void AudioPlayer::reset() {
Andreas Huberb5ceb9e2009-08-26 14:48:20 -0700205 CHECK(mStarted);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700206
207 if (mAudioSink.get() != NULL) {
208 mAudioSink->stop();
Andreas Huberaee3c632010-01-11 15:35:19 -0800209 mAudioSink->close();
Andreas Hubere46b7be2009-07-14 16:56:47 -0700210 } else {
211 mAudioTrack->stop();
212
213 delete mAudioTrack;
214 mAudioTrack = NULL;
215 }
Andreas Huberaee3c632010-01-11 15:35:19 -0800216
Andreas Hubere46b7be2009-07-14 16:56:47 -0700217 // Make sure to release any buffer we hold onto so that the
218 // source is able to stop().
Andreas Huber16263d92010-07-20 09:44:34 -0700219
220 if (mFirstBuffer != NULL) {
221 mFirstBuffer->release();
222 mFirstBuffer = NULL;
223 }
224
Andreas Hubere46b7be2009-07-14 16:56:47 -0700225 if (mInputBuffer != NULL) {
Steve Block71f2cf12011-10-20 11:56:00 +0100226 ALOGV("AudioPlayer releasing input buffer.");
Andreas Hubere46b7be2009-07-14 16:56:47 -0700227
228 mInputBuffer->release();
229 mInputBuffer = NULL;
230 }
231
232 mSource->stop();
Andreas Huberaee3c632010-01-11 15:35:19 -0800233
Andreas Huber5f0d5ce2010-03-01 14:27:00 -0800234 // The following hack is necessary to ensure that the OMX
235 // component is completely released by the time we may try
236 // to instantiate it again.
237 wp<MediaSource> tmp = mSource;
238 mSource.clear();
239 while (tmp.promote() != NULL) {
240 usleep(1000);
241 }
242 IPCThreadState::self()->flushCommands();
243
Andreas Hubere46b7be2009-07-14 16:56:47 -0700244 mNumFramesPlayed = 0;
245 mPositionTimeMediaUs = -1;
246 mPositionTimeRealUs = -1;
247 mSeeking = false;
Andreas Huber70d10c02010-02-03 11:37:29 -0800248 mReachedEOS = false;
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800249 mFinalStatus = OK;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700250 mStarted = false;
251}
252
253// static
Glenn Kastene46a86f2011-06-01 15:20:35 -0700254void AudioPlayer::AudioCallback(int event, void *user, void *info) {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700255 static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
256}
257
Andreas Huber70d10c02010-02-03 11:37:29 -0800258bool AudioPlayer::isSeeking() {
259 Mutex::Autolock autoLock(mLock);
260 return mSeeking;
261}
262
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800263bool AudioPlayer::reachedEOS(status_t *finalStatus) {
264 *finalStatus = OK;
265
Andreas Huber70d10c02010-02-03 11:37:29 -0800266 Mutex::Autolock autoLock(mLock);
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800267 *finalStatus = mFinalStatus;
Andreas Huber70d10c02010-02-03 11:37:29 -0800268 return mReachedEOS;
269}
270
Andreas Hubere46b7be2009-07-14 16:56:47 -0700271// static
Andreas Huber6ed937e2010-02-09 16:59:18 -0800272size_t AudioPlayer::AudioSinkCallback(
Andreas Hubere46b7be2009-07-14 16:56:47 -0700273 MediaPlayerBase::AudioSink *audioSink,
274 void *buffer, size_t size, void *cookie) {
275 AudioPlayer *me = (AudioPlayer *)cookie;
276
Andreas Huber6ed937e2010-02-09 16:59:18 -0800277 return me->fillBuffer(buffer, size);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700278}
279
Glenn Kastene46a86f2011-06-01 15:20:35 -0700280void AudioPlayer::AudioCallback(int event, void *info) {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700281 if (event != AudioTrack::EVENT_MORE_DATA) {
282 return;
283 }
284
285 AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
Andreas Huber6ed937e2010-02-09 16:59:18 -0800286 size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
287
288 buffer->size = numBytesWritten;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700289}
290
Andreas Huber4dc482d2011-03-22 10:31:21 -0700291uint32_t AudioPlayer::getNumFramesPendingPlayout() const {
292 uint32_t numFramesPlayedOut;
293 status_t err;
294
295 if (mAudioSink != NULL) {
296 err = mAudioSink->getPosition(&numFramesPlayedOut);
297 } else {
298 err = mAudioTrack->getPosition(&numFramesPlayedOut);
299 }
300
301 if (err != OK || mNumFramesPlayed < numFramesPlayedOut) {
302 return 0;
303 }
304
305 // mNumFramesPlayed is the number of frames submitted
306 // to the audio sink for playback, but not all of them
307 // may have played out by now.
308 return mNumFramesPlayed - numFramesPlayedOut;
309}
310
Andreas Huber6ed937e2010-02-09 16:59:18 -0800311size_t AudioPlayer::fillBuffer(void *data, size_t size) {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700312 if (mNumFramesPlayed == 0) {
Steve Block71f2cf12011-10-20 11:56:00 +0100313 ALOGV("AudioCallback");
Andreas Hubere46b7be2009-07-14 16:56:47 -0700314 }
315
Andreas Huber70d10c02010-02-03 11:37:29 -0800316 if (mReachedEOS) {
Andreas Huberc6e3b272011-04-04 11:43:40 -0700317 return 0;
Andreas Huber70d10c02010-02-03 11:37:29 -0800318 }
319
Andreas Huber8e64c312011-04-04 09:12:56 -0700320 bool postSeekComplete = false;
321 bool postEOS = false;
322 int64_t postEOSDelayUs = 0;
323
Andreas Hubere46b7be2009-07-14 16:56:47 -0700324 size_t size_done = 0;
325 size_t size_remaining = size;
326 while (size_remaining > 0) {
327 MediaSource::ReadOptions options;
328
329 {
330 Mutex::Autolock autoLock(mLock);
331
332 if (mSeeking) {
Andreas Huber16263d92010-07-20 09:44:34 -0700333 if (mIsFirstBuffer) {
334 if (mFirstBuffer != NULL) {
335 mFirstBuffer->release();
336 mFirstBuffer = NULL;
337 }
338 mIsFirstBuffer = false;
339 }
340
Andreas Hubere46b7be2009-07-14 16:56:47 -0700341 options.setSeekTo(mSeekTimeUs);
342
343 if (mInputBuffer != NULL) {
344 mInputBuffer->release();
345 mInputBuffer = NULL;
346 }
Gloria Wang2b7bb212010-02-04 17:43:09 -0800347
348 mSeeking = false;
Andreas Huber2b359ed2010-09-28 11:56:39 -0700349 if (mObserver) {
Andreas Huber8e64c312011-04-04 09:12:56 -0700350 postSeekComplete = true;
Andreas Huber2b359ed2010-09-28 11:56:39 -0700351 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700352 }
353 }
354
355 if (mInputBuffer == NULL) {
Andreas Huber16263d92010-07-20 09:44:34 -0700356 status_t err;
357
358 if (mIsFirstBuffer) {
359 mInputBuffer = mFirstBuffer;
360 mFirstBuffer = NULL;
361 err = mFirstBufferResult;
362
363 mIsFirstBuffer = false;
364 } else {
365 err = mSource->read(&mInputBuffer, &options);
366 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700367
Andreas Huberb5ceb9e2009-08-26 14:48:20 -0700368 CHECK((err == OK && mInputBuffer != NULL)
Andreas Hubere46b7be2009-07-14 16:56:47 -0700369 || (err != OK && mInputBuffer == NULL));
370
Andreas Huber70d10c02010-02-03 11:37:29 -0800371 Mutex::Autolock autoLock(mLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800372
Andreas Hubere46b7be2009-07-14 16:56:47 -0700373 if (err != OK) {
Andreas Huber2b359ed2010-09-28 11:56:39 -0700374 if (mObserver && !mReachedEOS) {
Andreas Huber4dc482d2011-03-22 10:31:21 -0700375 // We don't want to post EOS right away but only
376 // after all frames have actually been played out.
377
378 // These are the number of frames submitted to the
379 // AudioTrack that you haven't heard yet.
380 uint32_t numFramesPendingPlayout =
381 getNumFramesPendingPlayout();
382
383 // These are the number of frames we're going to
384 // submit to the AudioTrack by returning from this
385 // callback.
386 uint32_t numAdditionalFrames = size_done / mFrameSize;
387
388 numFramesPendingPlayout += numAdditionalFrames;
389
390 int64_t timeToCompletionUs =
391 (1000000ll * numFramesPendingPlayout) / mSampleRate;
392
Steve Block71f2cf12011-10-20 11:56:00 +0100393 ALOGV("total number of frames played: %lld (%lld us)",
Andreas Huber4dc482d2011-03-22 10:31:21 -0700394 (mNumFramesPlayed + numAdditionalFrames),
395 1000000ll * (mNumFramesPlayed + numAdditionalFrames)
396 / mSampleRate);
397
Steve Block71f2cf12011-10-20 11:56:00 +0100398 ALOGV("%d frames left to play, %lld us (%.2f secs)",
Andreas Huber4dc482d2011-03-22 10:31:21 -0700399 numFramesPendingPlayout,
400 timeToCompletionUs, timeToCompletionUs / 1E6);
401
Andreas Huber8e64c312011-04-04 09:12:56 -0700402 postEOS = true;
403 postEOSDelayUs = timeToCompletionUs + mLatencyUs;
Andreas Huber2b359ed2010-09-28 11:56:39 -0700404 }
405
Andreas Huber70d10c02010-02-03 11:37:29 -0800406 mReachedEOS = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800407 mFinalStatus = err;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700408 break;
409 }
410
Andreas Huberfa8de752009-10-08 10:07:49 -0700411 CHECK(mInputBuffer->meta_data()->findInt64(
412 kKeyTime, &mPositionTimeMediaUs));
Andreas Huber8a432772009-07-28 10:03:13 -0700413
Andreas Hubere46b7be2009-07-14 16:56:47 -0700414 mPositionTimeRealUs =
Andreas Huber065f69e2010-02-03 15:35:59 -0800415 ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
Andreas Huber8a432772009-07-28 10:03:13 -0700416 / mSampleRate;
Andreas Huberc997aca2009-11-05 16:34:39 -0800417
Steve Block71f2cf12011-10-20 11:56:00 +0100418 ALOGV("buffer->size() = %d, "
Andreas Huberc997aca2009-11-05 16:34:39 -0800419 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
420 mInputBuffer->range_length(),
421 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700422 }
423
424 if (mInputBuffer->range_length() == 0) {
425 mInputBuffer->release();
426 mInputBuffer = NULL;
427
428 continue;
429 }
430
431 size_t copy = size_remaining;
432 if (copy > mInputBuffer->range_length()) {
433 copy = mInputBuffer->range_length();
434 }
435
436 memcpy((char *)data + size_done,
437 (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
438 copy);
439
440 mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
441 mInputBuffer->range_length() - copy);
Andreas Huberaee3c632010-01-11 15:35:19 -0800442
Andreas Hubere46b7be2009-07-14 16:56:47 -0700443 size_done += copy;
444 size_remaining -= copy;
445 }
446
Andreas Huber8e64c312011-04-04 09:12:56 -0700447 {
448 Mutex::Autolock autoLock(mLock);
449 mNumFramesPlayed += size_done / mFrameSize;
450 }
451
452 if (postEOS) {
453 mObserver->postAudioEOS(postEOSDelayUs);
454 }
455
456 if (postSeekComplete) {
457 mObserver->postAudioSeekComplete();
458 }
Andreas Huber6ed937e2010-02-09 16:59:18 -0800459
460 return size_done;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700461}
462
463int64_t AudioPlayer::getRealTimeUs() {
464 Mutex::Autolock autoLock(mLock);
465 return getRealTimeUsLocked();
466}
467
468int64_t AudioPlayer::getRealTimeUsLocked() const {
Andreas Huber84584472011-09-08 11:33:47 -0700469 CHECK(mStarted);
470 CHECK_NE(mSampleRate, 0);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700471 return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
472}
473
474int64_t AudioPlayer::getMediaTimeUs() {
475 Mutex::Autolock autoLock(mLock);
476
Andreas Huberc119f7e2010-02-03 10:23:26 -0800477 if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
Andreas Huber59529e12011-03-25 16:36:13 -0700478 if (mSeeking) {
479 return mSeekTimeUs;
480 }
481
Andreas Huberc119f7e2010-02-03 10:23:26 -0800482 return 0;
483 }
484
Andreas Huber065f69e2010-02-03 15:35:59 -0800485 int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs;
486 if (realTimeOffset < 0) {
487 realTimeOffset = 0;
488 }
489
490 return mPositionTimeMediaUs + realTimeOffset;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700491}
492
493bool AudioPlayer::getMediaTimeMapping(
494 int64_t *realtime_us, int64_t *mediatime_us) {
495 Mutex::Autolock autoLock(mLock);
496
497 *realtime_us = mPositionTimeRealUs;
498 *mediatime_us = mPositionTimeMediaUs;
499
Andreas Huberc119f7e2010-02-03 10:23:26 -0800500 return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700501}
502
503status_t AudioPlayer::seekTo(int64_t time_us) {
504 Mutex::Autolock autoLock(mLock);
505
506 mSeeking = true;
Andreas Huber59529e12011-03-25 16:36:13 -0700507 mPositionTimeRealUs = mPositionTimeMediaUs = -1;
Andreas Huber70d10c02010-02-03 11:37:29 -0800508 mReachedEOS = false;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700509 mSeekTimeUs = time_us;
510
James Dongdbf85122011-09-27 22:47:25 -0700511 // Flush resets the number of played frames
512 mNumFramesPlayed = 0;
513
Andreas Huberad3fcfe2010-09-28 13:13:38 -0700514 if (mAudioSink != NULL) {
515 mAudioSink->flush();
516 } else {
517 mAudioTrack->flush();
518 }
519
Andreas Hubere46b7be2009-07-14 16:56:47 -0700520 return OK;
521}
522
523}