AudioPlayer.cpp revision d411b4ca2945cd8974a3a78199fce94646950128
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    mSeekTimeUs = 0;
367    mReachedEOS = false;
368    mFinalStatus = OK;
369    mStarted = false;
370    mPlaying = false;
371    mStartPosUs = 0;
372}
373
374// static
375void AudioPlayer::AudioCallback(int event, void *user, void *info) {
376    static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
377}
378
379bool AudioPlayer::isSeeking() {
380    Mutex::Autolock autoLock(mLock);
381    return mSeeking;
382}
383
384bool AudioPlayer::reachedEOS(status_t *finalStatus) {
385    *finalStatus = OK;
386
387    Mutex::Autolock autoLock(mLock);
388    *finalStatus = mFinalStatus;
389    return mReachedEOS;
390}
391
392void AudioPlayer::notifyAudioEOS() {
393    ALOGV("AudioPlayer@0x%p notifyAudioEOS", this);
394
395    if (mObserver != NULL) {
396        mObserver->postAudioEOS(0);
397        ALOGV("Notified observer of EOS!");
398    }
399}
400
401status_t AudioPlayer::setPlaybackRatePermille(int32_t ratePermille) {
402    if (mAudioSink.get() != NULL) {
403        return mAudioSink->setPlaybackRatePermille(ratePermille);
404    } else if (mAudioTrack != 0){
405        return mAudioTrack->setSampleRate(ratePermille * mSampleRate / 1000);
406    } else {
407        return NO_INIT;
408    }
409}
410
411// static
412size_t AudioPlayer::AudioSinkCallback(
413        MediaPlayerBase::AudioSink * /* audioSink */,
414        void *buffer, size_t size, void *cookie,
415        MediaPlayerBase::AudioSink::cb_event_t event) {
416    AudioPlayer *me = (AudioPlayer *)cookie;
417
418    switch(event) {
419    case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
420        return me->fillBuffer(buffer, size);
421
422    case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
423        ALOGV("AudioSinkCallback: stream end");
424        me->mReachedEOS = true;
425        me->notifyAudioEOS();
426        break;
427
428    case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
429        ALOGV("AudioSinkCallback: Tear down event");
430        me->mObserver->postAudioTearDown();
431        break;
432    }
433
434    return 0;
435}
436
437void AudioPlayer::AudioCallback(int event, void *info) {
438    switch (event) {
439    case AudioTrack::EVENT_MORE_DATA:
440        {
441        AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
442        size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
443        buffer->size = numBytesWritten;
444        }
445        break;
446
447    case AudioTrack::EVENT_STREAM_END:
448        mReachedEOS = true;
449        notifyAudioEOS();
450        break;
451    }
452}
453
454uint32_t AudioPlayer::getNumFramesPendingPlayout() const {
455    uint32_t numFramesPlayedOut;
456    status_t err;
457
458    if (mAudioSink != NULL) {
459        err = mAudioSink->getPosition(&numFramesPlayedOut);
460    } else {
461        err = mAudioTrack->getPosition(&numFramesPlayedOut);
462    }
463
464    if (err != OK || mNumFramesPlayed < numFramesPlayedOut) {
465        return 0;
466    }
467
468    // mNumFramesPlayed is the number of frames submitted
469    // to the audio sink for playback, but not all of them
470    // may have played out by now.
471    return mNumFramesPlayed - numFramesPlayedOut;
472}
473
474size_t AudioPlayer::fillBuffer(void *data, size_t size) {
475    if (mNumFramesPlayed == 0) {
476        ALOGV("AudioCallback");
477    }
478
479    if (mReachedEOS) {
480        return 0;
481    }
482
483    bool postSeekComplete = false;
484    bool postEOS = false;
485    int64_t postEOSDelayUs = 0;
486
487    size_t size_done = 0;
488    size_t size_remaining = size;
489    while (size_remaining > 0) {
490        MediaSource::ReadOptions options;
491        bool refreshSeekTime = false;
492
493        {
494            Mutex::Autolock autoLock(mLock);
495
496            if (mSeeking) {
497                if (mIsFirstBuffer) {
498                    if (mFirstBuffer != NULL) {
499                        mFirstBuffer->release();
500                        mFirstBuffer = NULL;
501                    }
502                    mIsFirstBuffer = false;
503                }
504
505                options.setSeekTo(mSeekTimeUs);
506                refreshSeekTime = true;
507
508                if (mInputBuffer != NULL) {
509                    mInputBuffer->release();
510                    mInputBuffer = NULL;
511                }
512
513                mSeeking = false;
514                if (mObserver) {
515                    postSeekComplete = true;
516                }
517            }
518        }
519
520        if (mInputBuffer == NULL) {
521            status_t err;
522
523            if (mIsFirstBuffer) {
524                mInputBuffer = mFirstBuffer;
525                mFirstBuffer = NULL;
526                err = mFirstBufferResult;
527
528                mIsFirstBuffer = false;
529            } else {
530                err = mSource->read(&mInputBuffer, &options);
531            }
532
533            CHECK((err == OK && mInputBuffer != NULL)
534                   || (err != OK && mInputBuffer == NULL));
535
536            Mutex::Autolock autoLock(mLock);
537
538            if (err != OK) {
539                if (!mReachedEOS) {
540                    if (useOffload()) {
541                        // no more buffers to push - stop() and wait for STREAM_END
542                        // don't set mReachedEOS until stream end received
543                        if (mAudioSink != NULL) {
544                            mAudioSink->stop();
545                        } else {
546                            mAudioTrack->stop();
547                        }
548                    } else {
549                        if (mObserver) {
550                            // We don't want to post EOS right away but only
551                            // after all frames have actually been played out.
552
553                            // These are the number of frames submitted to the
554                            // AudioTrack that you haven't heard yet.
555                            uint32_t numFramesPendingPlayout =
556                                getNumFramesPendingPlayout();
557
558                            // These are the number of frames we're going to
559                            // submit to the AudioTrack by returning from this
560                            // callback.
561                            uint32_t numAdditionalFrames = size_done / mFrameSize;
562
563                            numFramesPendingPlayout += numAdditionalFrames;
564
565                            int64_t timeToCompletionUs =
566                                (1000000ll * numFramesPendingPlayout) / mSampleRate;
567
568                            ALOGV("total number of frames played: %lld (%lld us)",
569                                    (mNumFramesPlayed + numAdditionalFrames),
570                                    1000000ll * (mNumFramesPlayed + numAdditionalFrames)
571                                        / mSampleRate);
572
573                            ALOGV("%d frames left to play, %lld us (%.2f secs)",
574                                 numFramesPendingPlayout,
575                                 timeToCompletionUs, timeToCompletionUs / 1E6);
576
577                            postEOS = true;
578                            if (mAudioSink->needsTrailingPadding()) {
579                                postEOSDelayUs = timeToCompletionUs + mLatencyUs;
580                            } else {
581                                postEOSDelayUs = 0;
582                            }
583                        }
584
585                        mReachedEOS = true;
586                    }
587                }
588
589                mFinalStatus = err;
590                break;
591            }
592
593            if (mAudioSink != NULL) {
594                mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
595            } else {
596                mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
597            }
598
599            if(mInputBuffer->range_length() != 0) {
600                CHECK(mInputBuffer->meta_data()->findInt64(
601                        kKeyTime, &mPositionTimeMediaUs));
602            }
603
604            // need to adjust the mStartPosUs for offload decoding since parser
605            // might not be able to get the exact seek time requested.
606            if (refreshSeekTime) {
607                if (useOffload()) {
608                    if (postSeekComplete) {
609                        ALOGV("fillBuffer is going to post SEEK_COMPLETE");
610                        mObserver->postAudioSeekComplete();
611                        postSeekComplete = false;
612                    }
613
614                    mStartPosUs = mPositionTimeMediaUs;
615                    ALOGV("adjust seek time to: %.2f", mStartPosUs/ 1E6);
616                }
617                // clear seek time with mLock locked and once we have valid mPositionTimeMediaUs
618                // and mPositionTimeRealUs
619                // before clearing mSeekTimeUs check if a new seek request has been received while
620                // we were reading from the source with mLock released.
621                if (!mSeeking) {
622                    mSeekTimeUs = 0;
623                }
624            }
625
626            if (!useOffload()) {
627                mPositionTimeRealUs =
628                    ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
629                        / mSampleRate;
630                ALOGV("buffer->size() = %d, "
631                     "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
632                     mInputBuffer->range_length(),
633                     mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
634            }
635
636        }
637
638        if (mInputBuffer->range_length() == 0) {
639            mInputBuffer->release();
640            mInputBuffer = NULL;
641
642            continue;
643        }
644
645        size_t copy = size_remaining;
646        if (copy > mInputBuffer->range_length()) {
647            copy = mInputBuffer->range_length();
648        }
649
650        memcpy((char *)data + size_done,
651               (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
652               copy);
653
654        mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
655                                mInputBuffer->range_length() - copy);
656
657        size_done += copy;
658        size_remaining -= copy;
659    }
660
661    if (useOffload()) {
662        // We must ask the hardware what it has played
663        mPositionTimeRealUs = getOutputPlayPositionUs_l();
664        ALOGV("mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
665             mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
666    }
667
668    {
669        Mutex::Autolock autoLock(mLock);
670        mNumFramesPlayed += size_done / mFrameSize;
671        mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
672
673        if (mReachedEOS) {
674            mPinnedTimeUs = mNumFramesPlayedSysTimeUs;
675        } else {
676            mPinnedTimeUs = -1ll;
677        }
678    }
679
680    if (postEOS) {
681        mObserver->postAudioEOS(postEOSDelayUs);
682    }
683
684    if (postSeekComplete) {
685        mObserver->postAudioSeekComplete();
686    }
687
688    return size_done;
689}
690
691int64_t AudioPlayer::getRealTimeUs() {
692    Mutex::Autolock autoLock(mLock);
693    if (useOffload()) {
694        if (mSeeking) {
695            return mSeekTimeUs;
696        }
697        mPositionTimeRealUs = getOutputPlayPositionUs_l();
698        return mPositionTimeRealUs;
699    }
700
701    return getRealTimeUsLocked();
702}
703
704int64_t AudioPlayer::getRealTimeUsLocked() const {
705    CHECK(mStarted);
706    CHECK_NE(mSampleRate, 0);
707    int64_t result = -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
708
709    // Compensate for large audio buffers, updates of mNumFramesPlayed
710    // are less frequent, therefore to get a "smoother" notion of time we
711    // compensate using system time.
712    int64_t diffUs;
713    if (mPinnedTimeUs >= 0ll) {
714        diffUs = mPinnedTimeUs;
715    } else {
716        diffUs = ALooper::GetNowUs();
717    }
718
719    diffUs -= mNumFramesPlayedSysTimeUs;
720
721    return result + diffUs;
722}
723
724int64_t AudioPlayer::getOutputPlayPositionUs_l()
725{
726    uint32_t playedSamples = 0;
727    uint32_t sampleRate;
728    if (mAudioSink != NULL) {
729        mAudioSink->getPosition(&playedSamples);
730        sampleRate = mAudioSink->getSampleRate();
731    } else {
732        mAudioTrack->getPosition(&playedSamples);
733        sampleRate = mAudioTrack->getSampleRate();
734    }
735    if (sampleRate != 0) {
736        mSampleRate = sampleRate;
737    }
738
739    int64_t playedUs;
740    if (mSampleRate != 0) {
741        playedUs = (static_cast<int64_t>(playedSamples) * 1000000 ) / mSampleRate;
742    } else {
743        playedUs = 0;
744    }
745
746    // HAL position is relative to the first buffer we sent at mStartPosUs
747    const int64_t renderedDuration = mStartPosUs + playedUs;
748    ALOGV("getOutputPlayPositionUs_l %lld", renderedDuration);
749    return renderedDuration;
750}
751
752int64_t AudioPlayer::getMediaTimeUs() {
753    Mutex::Autolock autoLock(mLock);
754
755    if (useOffload()) {
756        if (mSeeking) {
757            return mSeekTimeUs;
758        }
759        mPositionTimeRealUs = getOutputPlayPositionUs_l();
760        ALOGV("getMediaTimeUs getOutputPlayPositionUs_l() mPositionTimeRealUs %lld",
761              mPositionTimeRealUs);
762        return mPositionTimeRealUs;
763    }
764
765
766    if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
767        // mSeekTimeUs is either seek time while seeking or 0 if playback did not start.
768        return mSeekTimeUs;
769    }
770
771    int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs;
772    if (realTimeOffset < 0) {
773        realTimeOffset = 0;
774    }
775
776    return mPositionTimeMediaUs + realTimeOffset;
777}
778
779bool AudioPlayer::getMediaTimeMapping(
780        int64_t *realtime_us, int64_t *mediatime_us) {
781    Mutex::Autolock autoLock(mLock);
782
783    if (useOffload()) {
784        mPositionTimeRealUs = getOutputPlayPositionUs_l();
785        *realtime_us = mPositionTimeRealUs;
786        *mediatime_us = mPositionTimeRealUs;
787    } else {
788        *realtime_us = mPositionTimeRealUs;
789        *mediatime_us = mPositionTimeMediaUs;
790    }
791
792    return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
793}
794
795status_t AudioPlayer::seekTo(int64_t time_us) {
796    Mutex::Autolock autoLock(mLock);
797
798    ALOGV("seekTo( %lld )", time_us);
799
800    mSeeking = true;
801    mPositionTimeRealUs = mPositionTimeMediaUs = -1;
802    mReachedEOS = false;
803    mSeekTimeUs = time_us;
804    mStartPosUs = time_us;
805
806    // Flush resets the number of played frames
807    mNumFramesPlayed = 0;
808    mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
809
810    if (mAudioSink != NULL) {
811        if (mPlaying) {
812            mAudioSink->pause();
813        }
814        mAudioSink->flush();
815        if (mPlaying) {
816            mAudioSink->start();
817        }
818    } else {
819        if (mPlaying) {
820            mAudioTrack->pause();
821        }
822        mAudioTrack->flush();
823        if (mPlaying) {
824            mAudioTrack->start();
825        }
826    }
827
828    return OK;
829}
830
831}
832