blob: dd69e6ba54d37f3394258e61701970c191faa290 [file] [log] [blame]
Andreas Huber20111aa2009-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 Huberdae04ca2009-11-05 16:34:39 -080017//#define LOG_NDEBUG 0
Andreas Huber20111aa2009-07-14 16:56:47 -070018#define LOG_TAG "AudioPlayer"
19#include <utils/Log.h>
20
Andreas Huber25155ff2010-03-01 14:27:00 -080021#include <binder/IPCThreadState.h>
Andreas Huber20111aa2009-07-14 16:56:47 -070022#include <media/AudioTrack.h>
23#include <media/stagefright/AudioPlayer.h>
Andreas Huber0c891992009-08-26 14:48:20 -070024#include <media/stagefright/MediaDebug.h>
Andreas Huber18291bc2009-09-10 14:13:30 -070025#include <media/stagefright/MediaDefs.h>
Andreas Huber3cc219d2010-07-20 09:44:34 -070026#include <media/stagefright/MediaErrors.h>
Andreas Huber20111aa2009-07-14 16:56:47 -070027#include <media/stagefright/MediaSource.h>
28#include <media/stagefright/MetaData.h>
29
Andreas Hubered54ad02010-09-28 11:56:39 -070030#include "include/AwesomePlayer.h"
31
Andreas Huber20111aa2009-07-14 16:56:47 -070032namespace android {
33
Andreas Hubered54ad02010-09-28 11:56:39 -070034AudioPlayer::AudioPlayer(
35 const sp<MediaPlayerBase::AudioSink> &audioSink,
36 AwesomePlayer *observer)
Andreas Huber693d2712009-08-14 14:37:10 -070037 : mAudioTrack(NULL),
Andreas Huber20111aa2009-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 Huber1862a332010-02-03 11:37:29 -080046 mReachedEOS(false),
Andreas Huber5295c0c2010-02-23 13:45:33 -080047 mFinalStatus(OK),
Andreas Huber20111aa2009-07-14 16:56:47 -070048 mStarted(false),
Andreas Huber3cc219d2010-07-20 09:44:34 -070049 mIsFirstBuffer(false),
50 mFirstBufferResult(OK),
51 mFirstBuffer(NULL),
Andreas Hubered54ad02010-09-28 11:56:39 -070052 mAudioSink(audioSink),
53 mObserver(observer) {
Andreas Huber20111aa2009-07-14 16:56:47 -070054}
55
56AudioPlayer::~AudioPlayer() {
57 if (mStarted) {
Andreas Huberb2e39542010-10-05 10:25:34 -070058 reset();
Andreas Huber20111aa2009-07-14 16:56:47 -070059 }
60}
61
Andreas Huber693d2712009-08-14 14:37:10 -070062void AudioPlayer::setSource(const sp<MediaSource> &source) {
Andreas Huber0c891992009-08-26 14:48:20 -070063 CHECK_EQ(mSource, NULL);
Andreas Huber20111aa2009-07-14 16:56:47 -070064 mSource = source;
65}
66
Andreas Hubere7e3b782010-03-08 15:46:13 -080067status_t AudioPlayer::start(bool sourceAlreadyStarted) {
Andreas Huber0c891992009-08-26 14:48:20 -070068 CHECK(!mStarted);
69 CHECK(mSource != NULL);
Andreas Huber20111aa2009-07-14 16:56:47 -070070
Andreas Hubere7e3b782010-03-08 15:46:13 -080071 status_t err;
72 if (!sourceAlreadyStarted) {
73 err = mSource->start();
Andreas Huber88c030e2010-01-29 13:24:58 -080074
Andreas Hubere7e3b782010-03-08 15:46:13 -080075 if (err != OK) {
76 return err;
77 }
Andreas Huber88c030e2010-01-29 13:24:58 -080078 }
Andreas Huber20111aa2009-07-14 16:56:47 -070079
Andreas Huber3cc219d2010-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 Huberc0dfc5b2011-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 Huber3cc219d2010-07-20 09:44:34 -070094 if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
95 LOGV("INFO_FORMAT_CHANGED!!!");
96
97 CHECK(mFirstBuffer == NULL);
98 mFirstBufferResult = OK;
99 mIsFirstBuffer = false;
100 } else {
101 mIsFirstBuffer = true;
102 }
103
Andreas Huber20111aa2009-07-14 16:56:47 -0700104 sp<MetaData> format = mSource->getFormat();
105 const char *mime;
106 bool success = format->findCString(kKeyMIMEType, &mime);
Andreas Huber0c891992009-08-26 14:48:20 -0700107 CHECK(success);
Andreas Huber18291bc2009-09-10 14:13:30 -0700108 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
Andreas Huber20111aa2009-07-14 16:56:47 -0700109
110 success = format->findInt32(kKeySampleRate, &mSampleRate);
Andreas Huber0c891992009-08-26 14:48:20 -0700111 CHECK(success);
Andreas Huber20111aa2009-07-14 16:56:47 -0700112
113 int32_t numChannels;
114 success = format->findInt32(kKeyChannelCount, &numChannels);
Andreas Huber0c891992009-08-26 14:48:20 -0700115 CHECK(success);
Andreas Huber20111aa2009-07-14 16:56:47 -0700116
117 if (mAudioSink.get() != NULL) {
118 status_t err = mAudioSink->open(
Dima Zavinfce7a472011-04-19 22:30:36 -0700119 mSampleRate, numChannels, AUDIO_FORMAT_PCM_16_BIT,
Andreas Huber20111aa2009-07-14 16:56:47 -0700120 DEFAULT_AUDIOSINK_BUFFERCOUNT,
121 &AudioPlayer::AudioSinkCallback, this);
Andreas Huber88c030e2010-01-29 13:24:58 -0800122 if (err != OK) {
Andreas Huber3cc219d2010-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 Huber88c030e2010-01-29 13:24:58 -0800131
132 return err;
133 }
Andreas Huber20111aa2009-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 Zavinfce7a472011-04-19 22:30:36 -0700141 AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT,
Andreas Huber00242452009-07-28 10:03:13 -0700142 (numChannels == 2)
Dima Zavinfce7a472011-04-19 22:30:36 -0700143 ? AUDIO_CHANNEL_OUT_STEREO
144 : AUDIO_CHANNEL_OUT_MONO,
Andreas Hubera98420e2010-04-13 09:58:39 -0700145 0, 0, &AudioCallback, this, 0);
Andreas Huber20111aa2009-07-14 16:56:47 -0700146
Kenny Root32dcebf2010-02-18 09:03:06 -0800147 if ((err = mAudioTrack->initCheck()) != OK) {
Andreas Huber88c030e2010-01-29 13:24:58 -0800148 delete mAudioTrack;
149 mAudioTrack = NULL;
150
Andreas Huber3cc219d2010-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 Huber88c030e2010-01-29 13:24:58 -0800159
Kenny Root32dcebf2010-02-18 09:03:06 -0800160 return err;
Andreas Huber88c030e2010-01-29 13:24:58 -0800161 }
Andreas Huber20111aa2009-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 Huber88c030e2010-01-29 13:24:58 -0800170
171 return OK;
Andreas Huber20111aa2009-07-14 16:56:47 -0700172}
173
Andreas Huberb2e39542010-10-05 10:25:34 -0700174void AudioPlayer::pause(bool playPendingSamples) {
Andreas Huber0c891992009-08-26 14:48:20 -0700175 CHECK(mStarted);
Andreas Huber20111aa2009-07-14 16:56:47 -0700176
Andreas Huberb2e39542010-10-05 10:25:34 -0700177 if (playPendingSamples) {
178 if (mAudioSink.get() != NULL) {
179 mAudioSink->stop();
180 } else {
181 mAudioTrack->stop();
182 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700183 } else {
Andreas Huberb2e39542010-10-05 10:25:34 -0700184 if (mAudioSink.get() != NULL) {
185 mAudioSink->pause();
186 } else {
187 mAudioTrack->pause();
188 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700189 }
190}
191
192void AudioPlayer::resume() {
Andreas Huber0c891992009-08-26 14:48:20 -0700193 CHECK(mStarted);
Andreas Huber20111aa2009-07-14 16:56:47 -0700194
195 if (mAudioSink.get() != NULL) {
196 mAudioSink->start();
197 } else {
198 mAudioTrack->start();
199 }
200}
201
Andreas Huberb2e39542010-10-05 10:25:34 -0700202void AudioPlayer::reset() {
Andreas Huber0c891992009-08-26 14:48:20 -0700203 CHECK(mStarted);
Andreas Huber20111aa2009-07-14 16:56:47 -0700204
205 if (mAudioSink.get() != NULL) {
206 mAudioSink->stop();
Andreas Huberfc9ba092010-01-11 15:35:19 -0800207 mAudioSink->close();
Andreas Huber20111aa2009-07-14 16:56:47 -0700208 } else {
209 mAudioTrack->stop();
210
211 delete mAudioTrack;
212 mAudioTrack = NULL;
213 }
Andreas Huberfc9ba092010-01-11 15:35:19 -0800214
Andreas Huber20111aa2009-07-14 16:56:47 -0700215 // Make sure to release any buffer we hold onto so that the
216 // source is able to stop().
Andreas Huber3cc219d2010-07-20 09:44:34 -0700217
218 if (mFirstBuffer != NULL) {
219 mFirstBuffer->release();
220 mFirstBuffer = NULL;
221 }
222
Andreas Huber20111aa2009-07-14 16:56:47 -0700223 if (mInputBuffer != NULL) {
Andreas Huberdae04ca2009-11-05 16:34:39 -0800224 LOGV("AudioPlayer releasing input buffer.");
Andreas Huber20111aa2009-07-14 16:56:47 -0700225
226 mInputBuffer->release();
227 mInputBuffer = NULL;
228 }
229
230 mSource->stop();
Andreas Huberfc9ba092010-01-11 15:35:19 -0800231
Andreas Huber25155ff2010-03-01 14:27:00 -0800232 // The following hack is necessary to ensure that the OMX
233 // component is completely released by the time we may try
234 // to instantiate it again.
235 wp<MediaSource> tmp = mSource;
236 mSource.clear();
237 while (tmp.promote() != NULL) {
238 usleep(1000);
239 }
240 IPCThreadState::self()->flushCommands();
241
Andreas Huber20111aa2009-07-14 16:56:47 -0700242 mNumFramesPlayed = 0;
243 mPositionTimeMediaUs = -1;
244 mPositionTimeRealUs = -1;
245 mSeeking = false;
Andreas Huber1862a332010-02-03 11:37:29 -0800246 mReachedEOS = false;
Andreas Huber5295c0c2010-02-23 13:45:33 -0800247 mFinalStatus = OK;
Andreas Huber20111aa2009-07-14 16:56:47 -0700248 mStarted = false;
249}
250
251// static
Glenn Kastend217a8c2011-06-01 15:20:35 -0700252void AudioPlayer::AudioCallback(int event, void *user, void *info) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700253 static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
254}
255
Andreas Huber1862a332010-02-03 11:37:29 -0800256bool AudioPlayer::isSeeking() {
257 Mutex::Autolock autoLock(mLock);
258 return mSeeking;
259}
260
Andreas Huber5295c0c2010-02-23 13:45:33 -0800261bool AudioPlayer::reachedEOS(status_t *finalStatus) {
262 *finalStatus = OK;
263
Andreas Huber1862a332010-02-03 11:37:29 -0800264 Mutex::Autolock autoLock(mLock);
Andreas Huber5295c0c2010-02-23 13:45:33 -0800265 *finalStatus = mFinalStatus;
Andreas Huber1862a332010-02-03 11:37:29 -0800266 return mReachedEOS;
267}
268
Andreas Huber20111aa2009-07-14 16:56:47 -0700269// static
Andreas Huber7d5b8a72010-02-09 16:59:18 -0800270size_t AudioPlayer::AudioSinkCallback(
Andreas Huber20111aa2009-07-14 16:56:47 -0700271 MediaPlayerBase::AudioSink *audioSink,
272 void *buffer, size_t size, void *cookie) {
273 AudioPlayer *me = (AudioPlayer *)cookie;
274
Andreas Huber7d5b8a72010-02-09 16:59:18 -0800275 return me->fillBuffer(buffer, size);
Andreas Huber20111aa2009-07-14 16:56:47 -0700276}
277
Glenn Kastend217a8c2011-06-01 15:20:35 -0700278void AudioPlayer::AudioCallback(int event, void *info) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700279 if (event != AudioTrack::EVENT_MORE_DATA) {
280 return;
281 }
282
283 AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
Andreas Huber7d5b8a72010-02-09 16:59:18 -0800284 size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
285
286 buffer->size = numBytesWritten;
Andreas Huber20111aa2009-07-14 16:56:47 -0700287}
288
Andreas Huber84b343f2011-03-22 10:31:21 -0700289uint32_t AudioPlayer::getNumFramesPendingPlayout() const {
290 uint32_t numFramesPlayedOut;
291 status_t err;
292
293 if (mAudioSink != NULL) {
294 err = mAudioSink->getPosition(&numFramesPlayedOut);
295 } else {
296 err = mAudioTrack->getPosition(&numFramesPlayedOut);
297 }
298
299 if (err != OK || mNumFramesPlayed < numFramesPlayedOut) {
300 return 0;
301 }
302
303 // mNumFramesPlayed is the number of frames submitted
304 // to the audio sink for playback, but not all of them
305 // may have played out by now.
306 return mNumFramesPlayed - numFramesPlayedOut;
307}
308
Andreas Huber7d5b8a72010-02-09 16:59:18 -0800309size_t AudioPlayer::fillBuffer(void *data, size_t size) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700310 if (mNumFramesPlayed == 0) {
Andreas Huberdae04ca2009-11-05 16:34:39 -0800311 LOGV("AudioCallback");
Andreas Huber20111aa2009-07-14 16:56:47 -0700312 }
313
Andreas Huber1862a332010-02-03 11:37:29 -0800314 if (mReachedEOS) {
Andreas Huber51c1e0e2011-04-04 11:43:40 -0700315 return 0;
Andreas Huber1862a332010-02-03 11:37:29 -0800316 }
317
Andreas Huberbd7b7172011-04-04 09:12:56 -0700318 bool postSeekComplete = false;
319 bool postEOS = false;
320 int64_t postEOSDelayUs = 0;
321
Andreas Huber20111aa2009-07-14 16:56:47 -0700322 size_t size_done = 0;
323 size_t size_remaining = size;
324 while (size_remaining > 0) {
325 MediaSource::ReadOptions options;
326
327 {
328 Mutex::Autolock autoLock(mLock);
329
330 if (mSeeking) {
Andreas Huber3cc219d2010-07-20 09:44:34 -0700331 if (mIsFirstBuffer) {
332 if (mFirstBuffer != NULL) {
333 mFirstBuffer->release();
334 mFirstBuffer = NULL;
335 }
336 mIsFirstBuffer = false;
337 }
338
Andreas Huber20111aa2009-07-14 16:56:47 -0700339 options.setSeekTo(mSeekTimeUs);
340
341 if (mInputBuffer != NULL) {
342 mInputBuffer->release();
343 mInputBuffer = NULL;
344 }
Gloria Wangcb9859b2010-02-04 17:43:09 -0800345
346 mSeeking = false;
Andreas Hubered54ad02010-09-28 11:56:39 -0700347 if (mObserver) {
Andreas Huberbd7b7172011-04-04 09:12:56 -0700348 postSeekComplete = true;
Andreas Hubered54ad02010-09-28 11:56:39 -0700349 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700350 }
351 }
352
353 if (mInputBuffer == NULL) {
Andreas Huber3cc219d2010-07-20 09:44:34 -0700354 status_t err;
355
356 if (mIsFirstBuffer) {
357 mInputBuffer = mFirstBuffer;
358 mFirstBuffer = NULL;
359 err = mFirstBufferResult;
360
361 mIsFirstBuffer = false;
362 } else {
363 err = mSource->read(&mInputBuffer, &options);
364 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700365
Andreas Huber0c891992009-08-26 14:48:20 -0700366 CHECK((err == OK && mInputBuffer != NULL)
Andreas Huber20111aa2009-07-14 16:56:47 -0700367 || (err != OK && mInputBuffer == NULL));
368
Andreas Huber1862a332010-02-03 11:37:29 -0800369 Mutex::Autolock autoLock(mLock);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800370
Andreas Huber20111aa2009-07-14 16:56:47 -0700371 if (err != OK) {
Andreas Hubered54ad02010-09-28 11:56:39 -0700372 if (mObserver && !mReachedEOS) {
Andreas Huber84b343f2011-03-22 10:31:21 -0700373 // We don't want to post EOS right away but only
374 // after all frames have actually been played out.
375
376 // These are the number of frames submitted to the
377 // AudioTrack that you haven't heard yet.
378 uint32_t numFramesPendingPlayout =
379 getNumFramesPendingPlayout();
380
381 // These are the number of frames we're going to
382 // submit to the AudioTrack by returning from this
383 // callback.
384 uint32_t numAdditionalFrames = size_done / mFrameSize;
385
386 numFramesPendingPlayout += numAdditionalFrames;
387
388 int64_t timeToCompletionUs =
389 (1000000ll * numFramesPendingPlayout) / mSampleRate;
390
391 LOGV("total number of frames played: %lld (%lld us)",
392 (mNumFramesPlayed + numAdditionalFrames),
393 1000000ll * (mNumFramesPlayed + numAdditionalFrames)
394 / mSampleRate);
395
396 LOGV("%d frames left to play, %lld us (%.2f secs)",
397 numFramesPendingPlayout,
398 timeToCompletionUs, timeToCompletionUs / 1E6);
399
Andreas Huberbd7b7172011-04-04 09:12:56 -0700400 postEOS = true;
401 postEOSDelayUs = timeToCompletionUs + mLatencyUs;
Andreas Hubered54ad02010-09-28 11:56:39 -0700402 }
403
Andreas Huber1862a332010-02-03 11:37:29 -0800404 mReachedEOS = true;
Andreas Huber5295c0c2010-02-23 13:45:33 -0800405 mFinalStatus = err;
Andreas Huber20111aa2009-07-14 16:56:47 -0700406 break;
407 }
408
Andreas Huber48c948b2009-10-08 10:07:49 -0700409 CHECK(mInputBuffer->meta_data()->findInt64(
410 kKeyTime, &mPositionTimeMediaUs));
Andreas Huber00242452009-07-28 10:03:13 -0700411
Andreas Huber20111aa2009-07-14 16:56:47 -0700412 mPositionTimeRealUs =
Andreas Huber80a68de2010-02-03 15:35:59 -0800413 ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
Andreas Huber00242452009-07-28 10:03:13 -0700414 / mSampleRate;
Andreas Huberdae04ca2009-11-05 16:34:39 -0800415
416 LOGV("buffer->size() = %d, "
417 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
418 mInputBuffer->range_length(),
419 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
Andreas Huber20111aa2009-07-14 16:56:47 -0700420 }
421
422 if (mInputBuffer->range_length() == 0) {
423 mInputBuffer->release();
424 mInputBuffer = NULL;
425
426 continue;
427 }
428
429 size_t copy = size_remaining;
430 if (copy > mInputBuffer->range_length()) {
431 copy = mInputBuffer->range_length();
432 }
433
434 memcpy((char *)data + size_done,
435 (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
436 copy);
437
438 mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
439 mInputBuffer->range_length() - copy);
Andreas Huberfc9ba092010-01-11 15:35:19 -0800440
Andreas Huber20111aa2009-07-14 16:56:47 -0700441 size_done += copy;
442 size_remaining -= copy;
443 }
444
Andreas Huberbd7b7172011-04-04 09:12:56 -0700445 {
446 Mutex::Autolock autoLock(mLock);
447 mNumFramesPlayed += size_done / mFrameSize;
448 }
449
450 if (postEOS) {
451 mObserver->postAudioEOS(postEOSDelayUs);
452 }
453
454 if (postSeekComplete) {
455 mObserver->postAudioSeekComplete();
456 }
Andreas Huber7d5b8a72010-02-09 16:59:18 -0800457
458 return size_done;
Andreas Huber20111aa2009-07-14 16:56:47 -0700459}
460
461int64_t AudioPlayer::getRealTimeUs() {
462 Mutex::Autolock autoLock(mLock);
463 return getRealTimeUsLocked();
464}
465
466int64_t AudioPlayer::getRealTimeUsLocked() const {
467 return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
468}
469
470int64_t AudioPlayer::getMediaTimeUs() {
471 Mutex::Autolock autoLock(mLock);
472
Andreas Huberad6516d2010-02-03 10:23:26 -0800473 if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
Andreas Huberfe9b7192011-03-25 16:36:13 -0700474 if (mSeeking) {
475 return mSeekTimeUs;
476 }
477
Andreas Huberad6516d2010-02-03 10:23:26 -0800478 return 0;
479 }
480
Andreas Huber80a68de2010-02-03 15:35:59 -0800481 int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs;
482 if (realTimeOffset < 0) {
483 realTimeOffset = 0;
484 }
485
486 return mPositionTimeMediaUs + realTimeOffset;
Andreas Huber20111aa2009-07-14 16:56:47 -0700487}
488
489bool AudioPlayer::getMediaTimeMapping(
490 int64_t *realtime_us, int64_t *mediatime_us) {
491 Mutex::Autolock autoLock(mLock);
492
493 *realtime_us = mPositionTimeRealUs;
494 *mediatime_us = mPositionTimeMediaUs;
495
Andreas Huberad6516d2010-02-03 10:23:26 -0800496 return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
Andreas Huber20111aa2009-07-14 16:56:47 -0700497}
498
499status_t AudioPlayer::seekTo(int64_t time_us) {
500 Mutex::Autolock autoLock(mLock);
501
502 mSeeking = true;
Andreas Huberfe9b7192011-03-25 16:36:13 -0700503 mPositionTimeRealUs = mPositionTimeMediaUs = -1;
Andreas Huber1862a332010-02-03 11:37:29 -0800504 mReachedEOS = false;
Andreas Huber20111aa2009-07-14 16:56:47 -0700505 mSeekTimeUs = time_us;
506
Andreas Huberc7d368d2010-09-28 13:13:38 -0700507 if (mAudioSink != NULL) {
508 mAudioSink->flush();
509 } else {
510 mAudioTrack->flush();
511 }
512
Andreas Huber20111aa2009-07-14 16:56:47 -0700513 return OK;
514}
515
516}