blob: f84e37fe016d6d6f4eb17ee4e68cbb204ef1cbce [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
Jean-Michel Trivi4ed260f2012-03-02 14:54:07 -0800113 int32_t numChannels, channelMask;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700114 success = format->findInt32(kKeyChannelCount, &numChannels);
Andreas Huberb5ceb9e2009-08-26 14:48:20 -0700115 CHECK(success);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700116
Jean-Michel Trivi4ed260f2012-03-02 14:54:07 -0800117 if(!format->findInt32(kKeyChannelMask, &channelMask)) {
118 ALOGW("source format didn't specify channel mask, using channel order");
119 channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
120 }
121
Andreas Hubere46b7be2009-07-14 16:56:47 -0700122 if (mAudioSink.get() != NULL) {
123 status_t err = mAudioSink->open(
Jean-Michel Trivi4ed260f2012-03-02 14:54:07 -0800124 mSampleRate, numChannels, channelMask, AUDIO_FORMAT_PCM_16_BIT,
Andreas Hubere46b7be2009-07-14 16:56:47 -0700125 DEFAULT_AUDIOSINK_BUFFERCOUNT,
126 &AudioPlayer::AudioSinkCallback, this);
Andreas Huber62eac002010-01-29 13:24:58 -0800127 if (err != OK) {
Andreas Huber16263d92010-07-20 09:44:34 -0700128 if (mFirstBuffer != NULL) {
129 mFirstBuffer->release();
130 mFirstBuffer = NULL;
131 }
132
133 if (!sourceAlreadyStarted) {
134 mSource->stop();
135 }
Andreas Huber62eac002010-01-29 13:24:58 -0800136
137 return err;
138 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700139
140 mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
141 mFrameSize = mAudioSink->frameSize();
142
143 mAudioSink->start();
144 } else {
Jean-Michel Trivi4ed260f2012-03-02 14:54:07 -0800145 // playing to an AudioTrack, set up mask if necessary
146 audio_channel_mask_t audioMask = channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER ?
147 audio_channel_mask_from_count(numChannels) : channelMask;
148 if (0 == audioMask) {
149 return BAD_VALUE;
150 }
151
Andreas Hubere46b7be2009-07-14 16:56:47 -0700152 mAudioTrack = new AudioTrack(
Jean-Michel Trivi4ed260f2012-03-02 14:54:07 -0800153 AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT, audioMask,
Andreas Huber662292a2010-04-13 09:58:39 -0700154 0, 0, &AudioCallback, this, 0);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700155
Kenny Root3cbd62c2010-02-18 09:03:06 -0800156 if ((err = mAudioTrack->initCheck()) != OK) {
Andreas Huber62eac002010-01-29 13:24:58 -0800157 delete mAudioTrack;
158 mAudioTrack = NULL;
159
Andreas Huber16263d92010-07-20 09:44:34 -0700160 if (mFirstBuffer != NULL) {
161 mFirstBuffer->release();
162 mFirstBuffer = NULL;
163 }
164
165 if (!sourceAlreadyStarted) {
166 mSource->stop();
167 }
Andreas Huber62eac002010-01-29 13:24:58 -0800168
Kenny Root3cbd62c2010-02-18 09:03:06 -0800169 return err;
Andreas Huber62eac002010-01-29 13:24:58 -0800170 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700171
172 mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
173 mFrameSize = mAudioTrack->frameSize();
174
175 mAudioTrack->start();
176 }
177
178 mStarted = true;
Andreas Huber62eac002010-01-29 13:24:58 -0800179
180 return OK;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700181}
182
Andreas Huberc743f452010-10-05 10:25:34 -0700183void AudioPlayer::pause(bool playPendingSamples) {
Andreas Huberb5ceb9e2009-08-26 14:48:20 -0700184 CHECK(mStarted);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700185
Andreas Huberc743f452010-10-05 10:25:34 -0700186 if (playPendingSamples) {
187 if (mAudioSink.get() != NULL) {
188 mAudioSink->stop();
189 } else {
190 mAudioTrack->stop();
191 }
Andreas Huber9ba16f62011-08-26 11:26:25 -0700192
193 mNumFramesPlayed = 0;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700194 } else {
Andreas Huberc743f452010-10-05 10:25:34 -0700195 if (mAudioSink.get() != NULL) {
196 mAudioSink->pause();
197 } else {
198 mAudioTrack->pause();
199 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700200 }
201}
202
203void AudioPlayer::resume() {
Andreas Huberb5ceb9e2009-08-26 14:48:20 -0700204 CHECK(mStarted);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700205
206 if (mAudioSink.get() != NULL) {
207 mAudioSink->start();
208 } else {
209 mAudioTrack->start();
210 }
211}
212
Andreas Huberc743f452010-10-05 10:25:34 -0700213void AudioPlayer::reset() {
Andreas Huberb5ceb9e2009-08-26 14:48:20 -0700214 CHECK(mStarted);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700215
216 if (mAudioSink.get() != NULL) {
217 mAudioSink->stop();
Andreas Huberaee3c632010-01-11 15:35:19 -0800218 mAudioSink->close();
Andreas Hubere46b7be2009-07-14 16:56:47 -0700219 } else {
220 mAudioTrack->stop();
221
222 delete mAudioTrack;
223 mAudioTrack = NULL;
224 }
Andreas Huberaee3c632010-01-11 15:35:19 -0800225
Andreas Hubere46b7be2009-07-14 16:56:47 -0700226 // Make sure to release any buffer we hold onto so that the
227 // source is able to stop().
Andreas Huber16263d92010-07-20 09:44:34 -0700228
229 if (mFirstBuffer != NULL) {
230 mFirstBuffer->release();
231 mFirstBuffer = NULL;
232 }
233
Andreas Hubere46b7be2009-07-14 16:56:47 -0700234 if (mInputBuffer != NULL) {
Steve Block71f2cf12011-10-20 11:56:00 +0100235 ALOGV("AudioPlayer releasing input buffer.");
Andreas Hubere46b7be2009-07-14 16:56:47 -0700236
237 mInputBuffer->release();
238 mInputBuffer = NULL;
239 }
240
241 mSource->stop();
Andreas Huberaee3c632010-01-11 15:35:19 -0800242
Andreas Huber5f0d5ce2010-03-01 14:27:00 -0800243 // The following hack is necessary to ensure that the OMX
244 // component is completely released by the time we may try
245 // to instantiate it again.
246 wp<MediaSource> tmp = mSource;
247 mSource.clear();
248 while (tmp.promote() != NULL) {
249 usleep(1000);
250 }
251 IPCThreadState::self()->flushCommands();
252
Andreas Hubere46b7be2009-07-14 16:56:47 -0700253 mNumFramesPlayed = 0;
254 mPositionTimeMediaUs = -1;
255 mPositionTimeRealUs = -1;
256 mSeeking = false;
Andreas Huber70d10c02010-02-03 11:37:29 -0800257 mReachedEOS = false;
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800258 mFinalStatus = OK;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700259 mStarted = false;
260}
261
262// static
Glenn Kastene46a86f2011-06-01 15:20:35 -0700263void AudioPlayer::AudioCallback(int event, void *user, void *info) {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700264 static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
265}
266
Andreas Huber70d10c02010-02-03 11:37:29 -0800267bool AudioPlayer::isSeeking() {
268 Mutex::Autolock autoLock(mLock);
269 return mSeeking;
270}
271
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800272bool AudioPlayer::reachedEOS(status_t *finalStatus) {
273 *finalStatus = OK;
274
Andreas Huber70d10c02010-02-03 11:37:29 -0800275 Mutex::Autolock autoLock(mLock);
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800276 *finalStatus = mFinalStatus;
Andreas Huber70d10c02010-02-03 11:37:29 -0800277 return mReachedEOS;
278}
279
Jean-Michel Trivie901a5c2012-02-02 09:06:31 -0800280status_t AudioPlayer::setPlaybackRatePermille(int32_t ratePermille) {
281 if (mAudioSink.get() != NULL) {
282 return mAudioSink->setPlaybackRatePermille(ratePermille);
283 } else if (mAudioTrack != NULL){
284 return mAudioTrack->setSampleRate(ratePermille * mSampleRate / 1000);
285 } else {
286 return NO_INIT;
287 }
288}
289
Andreas Hubere46b7be2009-07-14 16:56:47 -0700290// static
Andreas Huber6ed937e2010-02-09 16:59:18 -0800291size_t AudioPlayer::AudioSinkCallback(
Andreas Hubere46b7be2009-07-14 16:56:47 -0700292 MediaPlayerBase::AudioSink *audioSink,
293 void *buffer, size_t size, void *cookie) {
294 AudioPlayer *me = (AudioPlayer *)cookie;
295
Andreas Huber6ed937e2010-02-09 16:59:18 -0800296 return me->fillBuffer(buffer, size);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700297}
298
Glenn Kastene46a86f2011-06-01 15:20:35 -0700299void AudioPlayer::AudioCallback(int event, void *info) {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700300 if (event != AudioTrack::EVENT_MORE_DATA) {
301 return;
302 }
303
304 AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
Andreas Huber6ed937e2010-02-09 16:59:18 -0800305 size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
306
307 buffer->size = numBytesWritten;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700308}
309
Andreas Huber4dc482d2011-03-22 10:31:21 -0700310uint32_t AudioPlayer::getNumFramesPendingPlayout() const {
311 uint32_t numFramesPlayedOut;
312 status_t err;
313
314 if (mAudioSink != NULL) {
315 err = mAudioSink->getPosition(&numFramesPlayedOut);
316 } else {
317 err = mAudioTrack->getPosition(&numFramesPlayedOut);
318 }
319
320 if (err != OK || mNumFramesPlayed < numFramesPlayedOut) {
321 return 0;
322 }
323
324 // mNumFramesPlayed is the number of frames submitted
325 // to the audio sink for playback, but not all of them
326 // may have played out by now.
327 return mNumFramesPlayed - numFramesPlayedOut;
328}
329
Andreas Huber6ed937e2010-02-09 16:59:18 -0800330size_t AudioPlayer::fillBuffer(void *data, size_t size) {
Andreas Hubere46b7be2009-07-14 16:56:47 -0700331 if (mNumFramesPlayed == 0) {
Steve Block71f2cf12011-10-20 11:56:00 +0100332 ALOGV("AudioCallback");
Andreas Hubere46b7be2009-07-14 16:56:47 -0700333 }
334
Andreas Huber70d10c02010-02-03 11:37:29 -0800335 if (mReachedEOS) {
Andreas Huberc6e3b272011-04-04 11:43:40 -0700336 return 0;
Andreas Huber70d10c02010-02-03 11:37:29 -0800337 }
338
Andreas Huber8e64c312011-04-04 09:12:56 -0700339 bool postSeekComplete = false;
340 bool postEOS = false;
341 int64_t postEOSDelayUs = 0;
342
Andreas Hubere46b7be2009-07-14 16:56:47 -0700343 size_t size_done = 0;
344 size_t size_remaining = size;
345 while (size_remaining > 0) {
346 MediaSource::ReadOptions options;
347
348 {
349 Mutex::Autolock autoLock(mLock);
350
351 if (mSeeking) {
Andreas Huber16263d92010-07-20 09:44:34 -0700352 if (mIsFirstBuffer) {
353 if (mFirstBuffer != NULL) {
354 mFirstBuffer->release();
355 mFirstBuffer = NULL;
356 }
357 mIsFirstBuffer = false;
358 }
359
Andreas Hubere46b7be2009-07-14 16:56:47 -0700360 options.setSeekTo(mSeekTimeUs);
361
362 if (mInputBuffer != NULL) {
363 mInputBuffer->release();
364 mInputBuffer = NULL;
365 }
Gloria Wang2b7bb212010-02-04 17:43:09 -0800366
367 mSeeking = false;
Andreas Huber2b359ed2010-09-28 11:56:39 -0700368 if (mObserver) {
Andreas Huber8e64c312011-04-04 09:12:56 -0700369 postSeekComplete = true;
Andreas Huber2b359ed2010-09-28 11:56:39 -0700370 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700371 }
372 }
373
374 if (mInputBuffer == NULL) {
Andreas Huber16263d92010-07-20 09:44:34 -0700375 status_t err;
376
377 if (mIsFirstBuffer) {
378 mInputBuffer = mFirstBuffer;
379 mFirstBuffer = NULL;
380 err = mFirstBufferResult;
381
382 mIsFirstBuffer = false;
383 } else {
384 err = mSource->read(&mInputBuffer, &options);
385 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700386
Andreas Huberb5ceb9e2009-08-26 14:48:20 -0700387 CHECK((err == OK && mInputBuffer != NULL)
Andreas Hubere46b7be2009-07-14 16:56:47 -0700388 || (err != OK && mInputBuffer == NULL));
389
Andreas Huber70d10c02010-02-03 11:37:29 -0800390 Mutex::Autolock autoLock(mLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800391
Andreas Hubere46b7be2009-07-14 16:56:47 -0700392 if (err != OK) {
Andreas Huber2b359ed2010-09-28 11:56:39 -0700393 if (mObserver && !mReachedEOS) {
Andreas Huber4dc482d2011-03-22 10:31:21 -0700394 // We don't want to post EOS right away but only
395 // after all frames have actually been played out.
396
397 // These are the number of frames submitted to the
398 // AudioTrack that you haven't heard yet.
399 uint32_t numFramesPendingPlayout =
400 getNumFramesPendingPlayout();
401
402 // These are the number of frames we're going to
403 // submit to the AudioTrack by returning from this
404 // callback.
405 uint32_t numAdditionalFrames = size_done / mFrameSize;
406
407 numFramesPendingPlayout += numAdditionalFrames;
408
409 int64_t timeToCompletionUs =
410 (1000000ll * numFramesPendingPlayout) / mSampleRate;
411
Steve Block71f2cf12011-10-20 11:56:00 +0100412 ALOGV("total number of frames played: %lld (%lld us)",
Andreas Huber4dc482d2011-03-22 10:31:21 -0700413 (mNumFramesPlayed + numAdditionalFrames),
414 1000000ll * (mNumFramesPlayed + numAdditionalFrames)
415 / mSampleRate);
416
Steve Block71f2cf12011-10-20 11:56:00 +0100417 ALOGV("%d frames left to play, %lld us (%.2f secs)",
Andreas Huber4dc482d2011-03-22 10:31:21 -0700418 numFramesPendingPlayout,
419 timeToCompletionUs, timeToCompletionUs / 1E6);
420
Andreas Huber8e64c312011-04-04 09:12:56 -0700421 postEOS = true;
Marco Nelissen84b83202012-02-28 16:07:44 -0800422 if (mAudioSink->needsTrailingPadding()) {
423 postEOSDelayUs = timeToCompletionUs + mLatencyUs;
424 } else {
425 postEOSDelayUs = 0;
426 }
Andreas Huber2b359ed2010-09-28 11:56:39 -0700427 }
428
Andreas Huber70d10c02010-02-03 11:37:29 -0800429 mReachedEOS = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800430 mFinalStatus = err;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700431 break;
432 }
433
Eric Laurent380b7052012-03-05 17:27:11 -0800434 if (mAudioSink != NULL) {
435 mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
436 } else {
437 mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
438 }
439
Andreas Huberfa8de752009-10-08 10:07:49 -0700440 CHECK(mInputBuffer->meta_data()->findInt64(
441 kKeyTime, &mPositionTimeMediaUs));
Andreas Huber8a432772009-07-28 10:03:13 -0700442
Andreas Hubere46b7be2009-07-14 16:56:47 -0700443 mPositionTimeRealUs =
Marco Nelissen1eb0e4a2012-03-09 10:34:37 -0800444 -mLatencyUs + ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
Andreas Huber8a432772009-07-28 10:03:13 -0700445 / mSampleRate;
Marco Nelissen1eb0e4a2012-03-09 10:34:37 -0800446 if (mPositionTimeRealUs < 0) {
447 mPositionTimeRealUs = 0;
448 }
Andreas Huberc997aca2009-11-05 16:34:39 -0800449
Steve Block71f2cf12011-10-20 11:56:00 +0100450 ALOGV("buffer->size() = %d, "
Andreas Huberc997aca2009-11-05 16:34:39 -0800451 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
452 mInputBuffer->range_length(),
453 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700454 }
455
456 if (mInputBuffer->range_length() == 0) {
457 mInputBuffer->release();
458 mInputBuffer = NULL;
459
460 continue;
461 }
462
463 size_t copy = size_remaining;
464 if (copy > mInputBuffer->range_length()) {
465 copy = mInputBuffer->range_length();
466 }
467
468 memcpy((char *)data + size_done,
469 (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
470 copy);
471
472 mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
473 mInputBuffer->range_length() - copy);
Andreas Huberaee3c632010-01-11 15:35:19 -0800474
Andreas Hubere46b7be2009-07-14 16:56:47 -0700475 size_done += copy;
476 size_remaining -= copy;
477 }
478
Andreas Huber8e64c312011-04-04 09:12:56 -0700479 {
480 Mutex::Autolock autoLock(mLock);
481 mNumFramesPlayed += size_done / mFrameSize;
482 }
483
484 if (postEOS) {
485 mObserver->postAudioEOS(postEOSDelayUs);
486 }
487
488 if (postSeekComplete) {
489 mObserver->postAudioSeekComplete();
490 }
Andreas Huber6ed937e2010-02-09 16:59:18 -0800491
492 return size_done;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700493}
494
495int64_t AudioPlayer::getRealTimeUs() {
496 Mutex::Autolock autoLock(mLock);
497 return getRealTimeUsLocked();
498}
499
500int64_t AudioPlayer::getRealTimeUsLocked() const {
Andreas Huber84584472011-09-08 11:33:47 -0700501 CHECK(mStarted);
502 CHECK_NE(mSampleRate, 0);
Marco Nelissen1eb0e4a2012-03-09 10:34:37 -0800503 int64_t t = -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
504 if (t < 0) return 0;
505 return t;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700506}
507
508int64_t AudioPlayer::getMediaTimeUs() {
509 Mutex::Autolock autoLock(mLock);
510
Andreas Huberc119f7e2010-02-03 10:23:26 -0800511 if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
Andreas Huber59529e12011-03-25 16:36:13 -0700512 if (mSeeking) {
513 return mSeekTimeUs;
514 }
515
Andreas Huberc119f7e2010-02-03 10:23:26 -0800516 return 0;
517 }
518
Andreas Huber065f69e2010-02-03 15:35:59 -0800519 int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs;
520 if (realTimeOffset < 0) {
521 realTimeOffset = 0;
522 }
523
524 return mPositionTimeMediaUs + realTimeOffset;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700525}
526
527bool AudioPlayer::getMediaTimeMapping(
528 int64_t *realtime_us, int64_t *mediatime_us) {
529 Mutex::Autolock autoLock(mLock);
530
531 *realtime_us = mPositionTimeRealUs;
532 *mediatime_us = mPositionTimeMediaUs;
533
Andreas Huberc119f7e2010-02-03 10:23:26 -0800534 return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700535}
536
537status_t AudioPlayer::seekTo(int64_t time_us) {
538 Mutex::Autolock autoLock(mLock);
539
540 mSeeking = true;
Andreas Huber59529e12011-03-25 16:36:13 -0700541 mPositionTimeRealUs = mPositionTimeMediaUs = -1;
Andreas Huber70d10c02010-02-03 11:37:29 -0800542 mReachedEOS = false;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700543 mSeekTimeUs = time_us;
544
James Dongdbf85122011-09-27 22:47:25 -0700545 // Flush resets the number of played frames
546 mNumFramesPlayed = 0;
547
Andreas Huberad3fcfe2010-09-28 13:13:38 -0700548 if (mAudioSink != NULL) {
549 mAudioSink->flush();
550 } else {
551 mAudioTrack->flush();
552 }
553
Andreas Hubere46b7be2009-07-14 16:56:47 -0700554 return OK;
555}
556
557}