AudioPlayer.cpp revision 50d9a8f7de5f79fa8a36489a53846d6653997e38
1/*
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
17//#define LOG_NDEBUG 0
18#define LOG_TAG "AudioPlayer"
19#include <utils/Log.h>
20#include <cutils/compiler.h>
21
22#include <binder/IPCThreadState.h>
23#include <media/AudioTrack.h>
24#include <media/stagefright/foundation/ADebug.h>
25#include <media/stagefright/foundation/ALooper.h>
26#include <media/stagefright/AudioPlayer.h>
27#include <media/stagefright/MediaDefs.h>
28#include <media/stagefright/MediaErrors.h>
29#include <media/stagefright/MediaSource.h>
30#include <media/stagefright/MetaData.h>
31#include <media/stagefright/Utils.h>
32
33#include "include/AwesomePlayer.h"
34
35namespace android {
36
37AudioPlayer::AudioPlayer(
38        const sp<MediaPlayerBase::AudioSink> &audioSink,
39        uint32_t flags,
40        AwesomePlayer *observer)
41    : mInputBuffer(NULL),
42      mSampleRate(0),
43      mLatencyUs(0),
44      mFrameSize(0),
45      mNumFramesPlayed(0),
46      mNumFramesPlayedSysTimeUs(ALooper::GetNowUs()),
47      mPositionTimeMediaUs(-1),
48      mPositionTimeRealUs(-1),
49      mSeeking(false),
50      mReachedEOS(false),
51      mFinalStatus(OK),
52      mSeekTimeUs(0),
53      mStarted(false),
54      mIsFirstBuffer(false),
55      mFirstBufferResult(OK),
56      mFirstBuffer(NULL),
57      mAudioSink(audioSink),
58      mObserver(observer),
59      mPinnedTimeUs(-1ll),
60      mPlaying(false),
61      mStartPosUs(0),
62      mCreateFlags(flags) {
63}
64
65AudioPlayer::~AudioPlayer() {
66    if (mStarted) {
67        reset();
68    }
69}
70
71void AudioPlayer::setSource(const sp<MediaSource> &source) {
72    CHECK(mSource == NULL);
73    mSource = source;
74}
75
76status_t AudioPlayer::start(bool sourceAlreadyStarted) {
77    CHECK(!mStarted);
78    CHECK(mSource != NULL);
79
80    status_t err;
81    if (!sourceAlreadyStarted) {
82        err = mSource->start();
83
84        if (err != OK) {
85            return err;
86        }
87    }
88
89    // We allow an optional INFO_FORMAT_CHANGED at the very beginning
90    // of playback, if there is one, getFormat below will retrieve the
91    // updated format, if there isn't, we'll stash away the valid buffer
92    // of data to be used on the first audio callback.
93
94    CHECK(mFirstBuffer == NULL);
95
96    MediaSource::ReadOptions options;
97    if (mSeeking) {
98        options.setSeekTo(mSeekTimeUs);
99        mSeeking = false;
100    }
101
102    mFirstBufferResult = mSource->read(&mFirstBuffer, &options);
103    if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
104        ALOGV("INFO_FORMAT_CHANGED!!!");
105
106        CHECK(mFirstBuffer == NULL);
107        mFirstBufferResult = OK;
108        mIsFirstBuffer = false;
109    } else {
110        mIsFirstBuffer = true;
111    }
112
113    sp<MetaData> format = mSource->getFormat();
114    const char *mime;
115    bool success = format->findCString(kKeyMIMEType, &mime);
116    CHECK(success);
117    CHECK(useOffload() || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
118
119    success = format->findInt32(kKeySampleRate, &mSampleRate);
120    CHECK(success);
121
122    int32_t numChannels, channelMask;
123    success = format->findInt32(kKeyChannelCount, &numChannels);
124    CHECK(success);
125
126    if(!format->findInt32(kKeyChannelMask, &channelMask)) {
127        // log only when there's a risk of ambiguity of channel mask selection
128        ALOGI_IF(numChannels > 2,
129                "source format didn't specify channel mask, using (%d) channel order", numChannels);
130        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
131    }
132
133    audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
134
135    if (useOffload()) {
136        if (mapMimeToAudioFormat(audioFormat, mime) != OK) {
137            ALOGE("Couldn't map mime type \"%s\" to a valid AudioSystem::audio_format", mime);
138            audioFormat = AUDIO_FORMAT_INVALID;
139        } else {
140            ALOGV("Mime type \"%s\" mapped to audio_format 0x%x", mime, audioFormat);
141        }
142    }
143
144    int avgBitRate = -1;
145    format->findInt32(kKeyBitRate, &avgBitRate);
146
147    if (mAudioSink.get() != NULL) {
148
149        uint32_t flags = AUDIO_OUTPUT_FLAG_NONE;
150        audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
151
152        if (allowDeepBuffering()) {
153            flags |= AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
154        }
155        if (useOffload()) {
156            flags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
157
158            int64_t durationUs;
159            if (format->findInt64(kKeyDuration, &durationUs)) {
160                offloadInfo.duration_us = durationUs;
161            } else {
162                offloadInfo.duration_us = -1;
163            }
164
165            offloadInfo.sample_rate = mSampleRate;
166            offloadInfo.channel_mask = channelMask;
167            offloadInfo.format = audioFormat;
168            offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
169            offloadInfo.bit_rate = avgBitRate;
170            offloadInfo.has_video = ((mCreateFlags & HAS_VIDEO) != 0);
171            offloadInfo.is_streaming = ((mCreateFlags & IS_STREAMING) != 0);
172        }
173
174        status_t err = mAudioSink->open(
175                mSampleRate, numChannels, channelMask, audioFormat,
176                DEFAULT_AUDIOSINK_BUFFERCOUNT,
177                &AudioPlayer::AudioSinkCallback,
178                this,
179                (audio_output_flags_t)flags,
180                useOffload() ? &offloadInfo : NULL);
181
182        if (err == OK) {
183            mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
184            mFrameSize = mAudioSink->frameSize();
185
186            if (useOffload()) {
187                // If the playback is offloaded to h/w we pass the
188                // HAL some metadata information
189                // We don't want to do this for PCM because it will be going
190                // through the AudioFlinger mixer before reaching the hardware
191                sendMetaDataToHal(mAudioSink, format);
192            }
193
194            err = mAudioSink->start();
195            // do not alter behavior for non offloaded tracks: ignore start status.
196            if (!useOffload()) {
197                err = OK;
198            }
199        }
200
201        if (err != OK) {
202            if (mFirstBuffer != NULL) {
203                mFirstBuffer->release();
204                mFirstBuffer = NULL;
205            }
206
207            if (!sourceAlreadyStarted) {
208                mSource->stop();
209            }
210
211            return err;
212        }
213
214    } else {
215        // playing to an AudioTrack, set up mask if necessary
216        audio_channel_mask_t audioMask = channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER ?
217                audio_channel_out_mask_from_count(numChannels) : channelMask;
218        if (0 == audioMask) {
219            return BAD_VALUE;
220        }
221
222        mAudioTrack = new AudioTrack(
223                AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT, audioMask,
224                0, AUDIO_OUTPUT_FLAG_NONE, &AudioCallback, this, 0);
225
226        if ((err = mAudioTrack->initCheck()) != OK) {
227            mAudioTrack.clear();
228
229            if (mFirstBuffer != NULL) {
230                mFirstBuffer->release();
231                mFirstBuffer = NULL;
232            }
233
234            if (!sourceAlreadyStarted) {
235                mSource->stop();
236            }
237
238            return err;
239        }
240
241        mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
242        mFrameSize = mAudioTrack->frameSize();
243
244        mAudioTrack->start();
245    }
246
247    mStarted = true;
248    mPlaying = true;
249    mPinnedTimeUs = -1ll;
250
251    return OK;
252}
253
254void AudioPlayer::pause(bool playPendingSamples) {
255    CHECK(mStarted);
256
257    if (playPendingSamples) {
258        if (mAudioSink.get() != NULL) {
259            mAudioSink->stop();
260        } else {
261            mAudioTrack->stop();
262        }
263
264        mNumFramesPlayed = 0;
265        mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
266    } else {
267        if (mAudioSink.get() != NULL) {
268            mAudioSink->pause();
269        } else {
270            mAudioTrack->pause();
271        }
272
273        mPinnedTimeUs = ALooper::GetNowUs();
274    }
275
276    mPlaying = false;
277}
278
279status_t AudioPlayer::resume() {
280    CHECK(mStarted);
281    status_t err;
282
283    if (mAudioSink.get() != NULL) {
284        err = mAudioSink->start();
285    } else {
286        err = mAudioTrack->start();
287    }
288
289    if (err == OK) {
290        mPlaying = true;
291    }
292
293    return err;
294}
295
296void AudioPlayer::reset() {
297    CHECK(mStarted);
298
299    ALOGV("reset: mPlaying=%d mReachedEOS=%d useOffload=%d",
300                                mPlaying, mReachedEOS, useOffload() );
301
302    if (mAudioSink.get() != NULL) {
303        mAudioSink->stop();
304        // If we're closing and have reached EOS, we don't want to flush
305        // the track because if it is offloaded there could be a small
306        // amount of residual data in the hardware buffer which we must
307        // play to give gapless playback.
308        // But if we're resetting when paused or before we've reached EOS
309        // we can't be doing a gapless playback and there could be a large
310        // amount of data queued in the hardware if the track is offloaded,
311        // so we must flush to prevent a track switch being delayed playing
312        // the buffered data that we don't want now
313        if (!mPlaying || !mReachedEOS) {
314            mAudioSink->flush();
315        }
316
317        mAudioSink->close();
318    } else {
319        mAudioTrack->stop();
320
321        if (!mPlaying || !mReachedEOS) {
322            mAudioTrack->flush();
323        }
324
325        mAudioTrack.clear();
326    }
327
328    // Make sure to release any buffer we hold onto so that the
329    // source is able to stop().
330
331    if (mFirstBuffer != NULL) {
332        mFirstBuffer->release();
333        mFirstBuffer = NULL;
334    }
335
336    if (mInputBuffer != NULL) {
337        ALOGV("AudioPlayer releasing input buffer.");
338
339        mInputBuffer->release();
340        mInputBuffer = NULL;
341    }
342
343    mSource->stop();
344
345    // The following hack is necessary to ensure that the OMX
346    // component is completely released by the time we may try
347    // to instantiate it again.
348    // When offloading, the OMX component is not used so this hack
349    // is not needed
350    if (!useOffload()) {
351        wp<MediaSource> tmp = mSource;
352        mSource.clear();
353        while (tmp.promote() != NULL) {
354            usleep(1000);
355        }
356    } else {
357        mSource.clear();
358    }
359    IPCThreadState::self()->flushCommands();
360
361    mNumFramesPlayed = 0;
362    mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
363    mPositionTimeMediaUs = -1;
364    mPositionTimeRealUs = -1;
365    mSeeking = false;
366    mReachedEOS = false;
367    mFinalStatus = OK;
368    mStarted = false;
369    mPlaying = false;
370    mStartPosUs = 0;
371}
372
373// static
374void AudioPlayer::AudioCallback(int event, void *user, void *info) {
375    static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
376}
377
378bool AudioPlayer::isSeeking() {
379    Mutex::Autolock autoLock(mLock);
380    return mSeeking;
381}
382
383bool AudioPlayer::reachedEOS(status_t *finalStatus) {
384    *finalStatus = OK;
385
386    Mutex::Autolock autoLock(mLock);
387    *finalStatus = mFinalStatus;
388    return mReachedEOS;
389}
390
391void AudioPlayer::notifyAudioEOS() {
392    ALOGV("AudioPlayer@0x%p notifyAudioEOS", this);
393
394    if (mObserver != NULL) {
395        mObserver->postAudioEOS(0);
396        ALOGV("Notified observer of EOS!");
397    }
398}
399
400status_t AudioPlayer::setPlaybackRatePermille(int32_t ratePermille) {
401    if (mAudioSink.get() != NULL) {
402        return mAudioSink->setPlaybackRatePermille(ratePermille);
403    } else if (mAudioTrack != 0){
404        return mAudioTrack->setSampleRate(ratePermille * mSampleRate / 1000);
405    } else {
406        return NO_INIT;
407    }
408}
409
410// static
411size_t AudioPlayer::AudioSinkCallback(
412        MediaPlayerBase::AudioSink *audioSink,
413        void *buffer, size_t size, void *cookie,
414        MediaPlayerBase::AudioSink::cb_event_t event) {
415    AudioPlayer *me = (AudioPlayer *)cookie;
416
417    switch(event) {
418    case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
419        return me->fillBuffer(buffer, size);
420
421    case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
422        ALOGV("AudioSinkCallback: stream end");
423        me->mReachedEOS = true;
424        me->notifyAudioEOS();
425        break;
426
427    case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
428        ALOGV("AudioSinkCallback: Tear down event");
429        me->mObserver->postAudioTearDown();
430        break;
431    }
432
433    return 0;
434}
435
436void AudioPlayer::AudioCallback(int event, void *info) {
437    switch (event) {
438    case AudioTrack::EVENT_MORE_DATA:
439        {
440        AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
441        size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
442        buffer->size = numBytesWritten;
443        }
444        break;
445
446    case AudioTrack::EVENT_STREAM_END:
447        mReachedEOS = true;
448        notifyAudioEOS();
449        break;
450    }
451}
452
453uint32_t AudioPlayer::getNumFramesPendingPlayout() const {
454    uint32_t numFramesPlayedOut;
455    status_t err;
456
457    if (mAudioSink != NULL) {
458        err = mAudioSink->getPosition(&numFramesPlayedOut);
459    } else {
460        err = mAudioTrack->getPosition(&numFramesPlayedOut);
461    }
462
463    if (err != OK || mNumFramesPlayed < numFramesPlayedOut) {
464        return 0;
465    }
466
467    // mNumFramesPlayed is the number of frames submitted
468    // to the audio sink for playback, but not all of them
469    // may have played out by now.
470    return mNumFramesPlayed - numFramesPlayedOut;
471}
472
473size_t AudioPlayer::fillBuffer(void *data, size_t size) {
474    if (mNumFramesPlayed == 0) {
475        ALOGV("AudioCallback");
476    }
477
478    if (mReachedEOS) {
479        return 0;
480    }
481
482    bool postSeekComplete = false;
483    bool postEOS = false;
484    int64_t postEOSDelayUs = 0;
485
486    size_t size_done = 0;
487    size_t size_remaining = size;
488    while (size_remaining > 0) {
489        MediaSource::ReadOptions options;
490        bool refreshSeekTime = false;
491
492        {
493            Mutex::Autolock autoLock(mLock);
494
495            if (mSeeking) {
496                if (mIsFirstBuffer) {
497                    if (mFirstBuffer != NULL) {
498                        mFirstBuffer->release();
499                        mFirstBuffer = NULL;
500                    }
501                    mIsFirstBuffer = false;
502                }
503
504                options.setSeekTo(mSeekTimeUs);
505                refreshSeekTime = true;
506
507                if (mInputBuffer != NULL) {
508                    mInputBuffer->release();
509                    mInputBuffer = NULL;
510                }
511
512                mSeeking = false;
513                if (mObserver) {
514                    postSeekComplete = true;
515                }
516            }
517        }
518
519        if (mInputBuffer == NULL) {
520            status_t err;
521
522            if (mIsFirstBuffer) {
523                mInputBuffer = mFirstBuffer;
524                mFirstBuffer = NULL;
525                err = mFirstBufferResult;
526
527                mIsFirstBuffer = false;
528            } else {
529                err = mSource->read(&mInputBuffer, &options);
530            }
531
532            CHECK((err == OK && mInputBuffer != NULL)
533                   || (err != OK && mInputBuffer == NULL));
534
535            Mutex::Autolock autoLock(mLock);
536
537            if (err != OK) {
538                if (!mReachedEOS) {
539                    if (useOffload()) {
540                        // no more buffers to push - stop() and wait for STREAM_END
541                        // don't set mReachedEOS until stream end received
542                        if (mAudioSink != NULL) {
543                            mAudioSink->stop();
544                        } else {
545                            mAudioTrack->stop();
546                        }
547                    } else {
548                        if (mObserver) {
549                            // We don't want to post EOS right away but only
550                            // after all frames have actually been played out.
551
552                            // These are the number of frames submitted to the
553                            // AudioTrack that you haven't heard yet.
554                            uint32_t numFramesPendingPlayout =
555                                getNumFramesPendingPlayout();
556
557                            // These are the number of frames we're going to
558                            // submit to the AudioTrack by returning from this
559                            // callback.
560                            uint32_t numAdditionalFrames = size_done / mFrameSize;
561
562                            numFramesPendingPlayout += numAdditionalFrames;
563
564                            int64_t timeToCompletionUs =
565                                (1000000ll * numFramesPendingPlayout) / mSampleRate;
566
567                            ALOGV("total number of frames played: %lld (%lld us)",
568                                    (mNumFramesPlayed + numAdditionalFrames),
569                                    1000000ll * (mNumFramesPlayed + numAdditionalFrames)
570                                        / mSampleRate);
571
572                            ALOGV("%d frames left to play, %lld us (%.2f secs)",
573                                 numFramesPendingPlayout,
574                                 timeToCompletionUs, timeToCompletionUs / 1E6);
575
576                            postEOS = true;
577                            if (mAudioSink->needsTrailingPadding()) {
578                                postEOSDelayUs = timeToCompletionUs + mLatencyUs;
579                            } else {
580                                postEOSDelayUs = 0;
581                            }
582                        }
583
584                        mReachedEOS = true;
585                    }
586                }
587
588                mFinalStatus = err;
589                break;
590            }
591
592            if (mAudioSink != NULL) {
593                mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
594            } else {
595                mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
596            }
597
598            if(mInputBuffer->range_length() != 0) {
599                CHECK(mInputBuffer->meta_data()->findInt64(
600                        kKeyTime, &mPositionTimeMediaUs));
601            }
602
603            // need to adjust the mStartPosUs for offload decoding since parser
604            // might not be able to get the exact seek time requested.
605            if (refreshSeekTime && useOffload()) {
606                if (postSeekComplete) {
607                    ALOGV("fillBuffer is going to post SEEK_COMPLETE");
608                    mObserver->postAudioSeekComplete();
609                    postSeekComplete = false;
610                }
611
612                mStartPosUs = mPositionTimeMediaUs;
613                ALOGV("adjust seek time to: %.2f", mStartPosUs/ 1E6);
614            }
615
616            if (!useOffload()) {
617                mPositionTimeRealUs =
618                    ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
619                        / mSampleRate;
620                ALOGV("buffer->size() = %d, "
621                     "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
622                     mInputBuffer->range_length(),
623                     mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
624            }
625
626        }
627
628        if (mInputBuffer->range_length() == 0) {
629            mInputBuffer->release();
630            mInputBuffer = NULL;
631
632            continue;
633        }
634
635        size_t copy = size_remaining;
636        if (copy > mInputBuffer->range_length()) {
637            copy = mInputBuffer->range_length();
638        }
639
640        memcpy((char *)data + size_done,
641               (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
642               copy);
643
644        mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
645                                mInputBuffer->range_length() - copy);
646
647        size_done += copy;
648        size_remaining -= copy;
649    }
650
651    if (useOffload()) {
652        // We must ask the hardware what it has played
653        mPositionTimeRealUs = getOutputPlayPositionUs_l();
654        ALOGV("mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
655             mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
656    }
657
658    {
659        Mutex::Autolock autoLock(mLock);
660        mNumFramesPlayed += size_done / mFrameSize;
661        mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
662
663        if (mReachedEOS) {
664            mPinnedTimeUs = mNumFramesPlayedSysTimeUs;
665        } else {
666            mPinnedTimeUs = -1ll;
667        }
668    }
669
670    if (postEOS) {
671        mObserver->postAudioEOS(postEOSDelayUs);
672    }
673
674    if (postSeekComplete) {
675        mObserver->postAudioSeekComplete();
676    }
677
678    return size_done;
679}
680
681int64_t AudioPlayer::getRealTimeUs() {
682    Mutex::Autolock autoLock(mLock);
683    if (useOffload()) {
684        if (mSeeking) {
685            return mSeekTimeUs;
686        }
687        mPositionTimeRealUs = getOutputPlayPositionUs_l();
688        return mPositionTimeRealUs;
689    }
690
691    return getRealTimeUsLocked();
692}
693
694int64_t AudioPlayer::getRealTimeUsLocked() const {
695    CHECK(mStarted);
696    CHECK_NE(mSampleRate, 0);
697    int64_t result = -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
698
699    // Compensate for large audio buffers, updates of mNumFramesPlayed
700    // are less frequent, therefore to get a "smoother" notion of time we
701    // compensate using system time.
702    int64_t diffUs;
703    if (mPinnedTimeUs >= 0ll) {
704        diffUs = mPinnedTimeUs;
705    } else {
706        diffUs = ALooper::GetNowUs();
707    }
708
709    diffUs -= mNumFramesPlayedSysTimeUs;
710
711    return result + diffUs;
712}
713
714int64_t AudioPlayer::getOutputPlayPositionUs_l() const
715{
716    uint32_t playedSamples = 0;
717    if (mAudioSink != NULL) {
718        mAudioSink->getPosition(&playedSamples);
719    } else {
720        mAudioTrack->getPosition(&playedSamples);
721    }
722
723    const int64_t playedUs = (static_cast<int64_t>(playedSamples) * 1000000 ) / mSampleRate;
724
725    // HAL position is relative to the first buffer we sent at mStartPosUs
726    const int64_t renderedDuration = mStartPosUs + playedUs;
727    ALOGV("getOutputPlayPositionUs_l %lld", renderedDuration);
728    return renderedDuration;
729}
730
731int64_t AudioPlayer::getMediaTimeUs() {
732    Mutex::Autolock autoLock(mLock);
733
734    if (useOffload()) {
735        if (mSeeking) {
736            return mSeekTimeUs;
737        }
738        mPositionTimeRealUs = getOutputPlayPositionUs_l();
739        ALOGV("getMediaTimeUs getOutputPlayPositionUs_l() mPositionTimeRealUs %lld",
740              mPositionTimeRealUs);
741        return mPositionTimeRealUs;
742    }
743
744    if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
745        if (mSeeking) {
746            return mSeekTimeUs;
747        }
748
749        return 0;
750    }
751
752    int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs;
753    if (realTimeOffset < 0) {
754        realTimeOffset = 0;
755    }
756
757    return mPositionTimeMediaUs + realTimeOffset;
758}
759
760bool AudioPlayer::getMediaTimeMapping(
761        int64_t *realtime_us, int64_t *mediatime_us) {
762    Mutex::Autolock autoLock(mLock);
763
764    if (useOffload()) {
765        mPositionTimeRealUs = getOutputPlayPositionUs_l();
766        *realtime_us = mPositionTimeRealUs;
767        *mediatime_us = mPositionTimeRealUs;
768    } else {
769        *realtime_us = mPositionTimeRealUs;
770        *mediatime_us = mPositionTimeMediaUs;
771    }
772
773    return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
774}
775
776status_t AudioPlayer::seekTo(int64_t time_us) {
777    Mutex::Autolock autoLock(mLock);
778
779    ALOGV("seekTo( %lld )", time_us);
780
781    mSeeking = true;
782    mPositionTimeRealUs = mPositionTimeMediaUs = -1;
783    mReachedEOS = false;
784    mSeekTimeUs = time_us;
785    mStartPosUs = time_us;
786
787    // Flush resets the number of played frames
788    mNumFramesPlayed = 0;
789    mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
790
791    if (mAudioSink != NULL) {
792        if (mPlaying) {
793            mAudioSink->pause();
794        }
795        mAudioSink->flush();
796        if (mPlaying) {
797            mAudioSink->start();
798        }
799    } else {
800        if (mPlaying) {
801            mAudioTrack->pause();
802        }
803        mAudioTrack->flush();
804        if (mPlaying) {
805            mAudioTrack->start();
806        }
807    }
808
809    return OK;
810}
811
812}
813