AudioPlayer.cpp revision 2301acc6a9c7a3af4ad01f3d1d0f76f13eca7350
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 /*frameCount*/, AUDIO_OUTPUT_FLAG_NONE, &AudioCallback, this,
225                0 /*notificationFrames*/);
226
227        if ((err = mAudioTrack->initCheck()) != OK) {
228            mAudioTrack.clear();
229
230            if (mFirstBuffer != NULL) {
231                mFirstBuffer->release();
232                mFirstBuffer = NULL;
233            }
234
235            if (!sourceAlreadyStarted) {
236                mSource->stop();
237            }
238
239            return err;
240        }
241
242        mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
243        mFrameSize = mAudioTrack->frameSize();
244
245        mAudioTrack->start();
246    }
247
248    mStarted = true;
249    mPlaying = true;
250    mPinnedTimeUs = -1ll;
251
252    return OK;
253}
254
255void AudioPlayer::pause(bool playPendingSamples) {
256    CHECK(mStarted);
257
258    if (playPendingSamples) {
259        if (mAudioSink.get() != NULL) {
260            mAudioSink->stop();
261        } else {
262            mAudioTrack->stop();
263        }
264
265        mNumFramesPlayed = 0;
266        mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
267    } else {
268        if (mAudioSink.get() != NULL) {
269            mAudioSink->pause();
270        } else {
271            mAudioTrack->pause();
272        }
273
274        mPinnedTimeUs = ALooper::GetNowUs();
275    }
276
277    mPlaying = false;
278}
279
280status_t AudioPlayer::resume() {
281    CHECK(mStarted);
282    status_t err;
283
284    if (mAudioSink.get() != NULL) {
285        err = mAudioSink->start();
286    } else {
287        err = mAudioTrack->start();
288    }
289
290    if (err == OK) {
291        mPlaying = true;
292    }
293
294    return err;
295}
296
297void AudioPlayer::reset() {
298    CHECK(mStarted);
299
300    ALOGV("reset: mPlaying=%d mReachedEOS=%d useOffload=%d",
301                                mPlaying, mReachedEOS, useOffload() );
302
303    if (mAudioSink.get() != NULL) {
304        mAudioSink->stop();
305        // If we're closing and have reached EOS, we don't want to flush
306        // the track because if it is offloaded there could be a small
307        // amount of residual data in the hardware buffer which we must
308        // play to give gapless playback.
309        // But if we're resetting when paused or before we've reached EOS
310        // we can't be doing a gapless playback and there could be a large
311        // amount of data queued in the hardware if the track is offloaded,
312        // so we must flush to prevent a track switch being delayed playing
313        // the buffered data that we don't want now
314        if (!mPlaying || !mReachedEOS) {
315            mAudioSink->flush();
316        }
317
318        mAudioSink->close();
319    } else {
320        mAudioTrack->stop();
321
322        if (!mPlaying || !mReachedEOS) {
323            mAudioTrack->flush();
324        }
325
326        mAudioTrack.clear();
327    }
328
329    // Make sure to release any buffer we hold onto so that the
330    // source is able to stop().
331
332    if (mFirstBuffer != NULL) {
333        mFirstBuffer->release();
334        mFirstBuffer = NULL;
335    }
336
337    if (mInputBuffer != NULL) {
338        ALOGV("AudioPlayer releasing input buffer.");
339
340        mInputBuffer->release();
341        mInputBuffer = NULL;
342    }
343
344    mSource->stop();
345
346    // The following hack is necessary to ensure that the OMX
347    // component is completely released by the time we may try
348    // to instantiate it again.
349    // When offloading, the OMX component is not used so this hack
350    // is not needed
351    if (!useOffload()) {
352        wp<MediaSource> tmp = mSource;
353        mSource.clear();
354        while (tmp.promote() != NULL) {
355            usleep(1000);
356        }
357    } else {
358        mSource.clear();
359    }
360    IPCThreadState::self()->flushCommands();
361
362    mNumFramesPlayed = 0;
363    mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
364    mPositionTimeMediaUs = -1;
365    mPositionTimeRealUs = -1;
366    mSeeking = false;
367    mSeekTimeUs = 0;
368    mReachedEOS = false;
369    mFinalStatus = OK;
370    mStarted = false;
371    mPlaying = false;
372    mStartPosUs = 0;
373}
374
375// static
376void AudioPlayer::AudioCallback(int event, void *user, void *info) {
377    static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
378}
379
380bool AudioPlayer::isSeeking() {
381    Mutex::Autolock autoLock(mLock);
382    return mSeeking;
383}
384
385bool AudioPlayer::reachedEOS(status_t *finalStatus) {
386    *finalStatus = OK;
387
388    Mutex::Autolock autoLock(mLock);
389    *finalStatus = mFinalStatus;
390    return mReachedEOS;
391}
392
393void AudioPlayer::notifyAudioEOS() {
394    ALOGV("AudioPlayer@0x%p notifyAudioEOS", this);
395
396    if (mObserver != NULL) {
397        mObserver->postAudioEOS(0);
398        ALOGV("Notified observer of EOS!");
399    }
400}
401
402status_t AudioPlayer::setPlaybackRatePermille(int32_t ratePermille) {
403    if (mAudioSink.get() != NULL) {
404        return mAudioSink->setPlaybackRatePermille(ratePermille);
405    } else if (mAudioTrack != 0){
406        return mAudioTrack->setSampleRate(ratePermille * mSampleRate / 1000);
407    } else {
408        return NO_INIT;
409    }
410}
411
412// static
413size_t AudioPlayer::AudioSinkCallback(
414        MediaPlayerBase::AudioSink * /* audioSink */,
415        void *buffer, size_t size, void *cookie,
416        MediaPlayerBase::AudioSink::cb_event_t event) {
417    AudioPlayer *me = (AudioPlayer *)cookie;
418
419    switch(event) {
420    case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
421        return me->fillBuffer(buffer, size);
422
423    case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
424        ALOGV("AudioSinkCallback: stream end");
425        me->mReachedEOS = true;
426        me->notifyAudioEOS();
427        break;
428
429    case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
430        ALOGV("AudioSinkCallback: Tear down event");
431        me->mObserver->postAudioTearDown();
432        break;
433    }
434
435    return 0;
436}
437
438void AudioPlayer::AudioCallback(int event, void *info) {
439    switch (event) {
440    case AudioTrack::EVENT_MORE_DATA:
441        {
442        AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
443        size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
444        buffer->size = numBytesWritten;
445        }
446        break;
447
448    case AudioTrack::EVENT_STREAM_END:
449        mReachedEOS = true;
450        notifyAudioEOS();
451        break;
452    }
453}
454
455uint32_t AudioPlayer::getNumFramesPendingPlayout() const {
456    uint32_t numFramesPlayedOut;
457    status_t err;
458
459    if (mAudioSink != NULL) {
460        err = mAudioSink->getPosition(&numFramesPlayedOut);
461    } else {
462        err = mAudioTrack->getPosition(&numFramesPlayedOut);
463    }
464
465    if (err != OK || mNumFramesPlayed < numFramesPlayedOut) {
466        return 0;
467    }
468
469    // mNumFramesPlayed is the number of frames submitted
470    // to the audio sink for playback, but not all of them
471    // may have played out by now.
472    return mNumFramesPlayed - numFramesPlayedOut;
473}
474
475size_t AudioPlayer::fillBuffer(void *data, size_t size) {
476    if (mNumFramesPlayed == 0) {
477        ALOGV("AudioCallback");
478    }
479
480    if (mReachedEOS) {
481        return 0;
482    }
483
484    bool postSeekComplete = false;
485    bool postEOS = false;
486    int64_t postEOSDelayUs = 0;
487
488    size_t size_done = 0;
489    size_t size_remaining = size;
490    while (size_remaining > 0) {
491        MediaSource::ReadOptions options;
492        bool refreshSeekTime = false;
493
494        {
495            Mutex::Autolock autoLock(mLock);
496
497            if (mSeeking) {
498                if (mIsFirstBuffer) {
499                    if (mFirstBuffer != NULL) {
500                        mFirstBuffer->release();
501                        mFirstBuffer = NULL;
502                    }
503                    mIsFirstBuffer = false;
504                }
505
506                options.setSeekTo(mSeekTimeUs);
507                refreshSeekTime = true;
508
509                if (mInputBuffer != NULL) {
510                    mInputBuffer->release();
511                    mInputBuffer = NULL;
512                }
513
514                mSeeking = false;
515                if (mObserver) {
516                    postSeekComplete = true;
517                }
518            }
519        }
520
521        if (mInputBuffer == NULL) {
522            status_t err;
523
524            if (mIsFirstBuffer) {
525                mInputBuffer = mFirstBuffer;
526                mFirstBuffer = NULL;
527                err = mFirstBufferResult;
528
529                mIsFirstBuffer = false;
530            } else {
531                err = mSource->read(&mInputBuffer, &options);
532            }
533
534            CHECK((err == OK && mInputBuffer != NULL)
535                   || (err != OK && mInputBuffer == NULL));
536
537            Mutex::Autolock autoLock(mLock);
538
539            if (err != OK) {
540                if (!mReachedEOS) {
541                    if (useOffload()) {
542                        // no more buffers to push - stop() and wait for STREAM_END
543                        // don't set mReachedEOS until stream end received
544                        if (mAudioSink != NULL) {
545                            mAudioSink->stop();
546                        } else {
547                            mAudioTrack->stop();
548                        }
549                    } else {
550                        if (mObserver) {
551                            // We don't want to post EOS right away but only
552                            // after all frames have actually been played out.
553
554                            // These are the number of frames submitted to the
555                            // AudioTrack that you haven't heard yet.
556                            uint32_t numFramesPendingPlayout =
557                                getNumFramesPendingPlayout();
558
559                            // These are the number of frames we're going to
560                            // submit to the AudioTrack by returning from this
561                            // callback.
562                            uint32_t numAdditionalFrames = size_done / mFrameSize;
563
564                            numFramesPendingPlayout += numAdditionalFrames;
565
566                            int64_t timeToCompletionUs =
567                                (1000000ll * numFramesPendingPlayout) / mSampleRate;
568
569                            ALOGV("total number of frames played: %lld (%lld us)",
570                                    (mNumFramesPlayed + numAdditionalFrames),
571                                    1000000ll * (mNumFramesPlayed + numAdditionalFrames)
572                                        / mSampleRate);
573
574                            ALOGV("%d frames left to play, %lld us (%.2f secs)",
575                                 numFramesPendingPlayout,
576                                 timeToCompletionUs, timeToCompletionUs / 1E6);
577
578                            postEOS = true;
579                            if (mAudioSink->needsTrailingPadding()) {
580                                postEOSDelayUs = timeToCompletionUs + mLatencyUs;
581                            } else {
582                                postEOSDelayUs = 0;
583                            }
584                        }
585
586                        mReachedEOS = true;
587                    }
588                }
589
590                mFinalStatus = err;
591                break;
592            }
593
594            if (mAudioSink != NULL) {
595                mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
596            } else {
597                mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
598            }
599
600            if(mInputBuffer->range_length() != 0) {
601                CHECK(mInputBuffer->meta_data()->findInt64(
602                        kKeyTime, &mPositionTimeMediaUs));
603            }
604
605            // need to adjust the mStartPosUs for offload decoding since parser
606            // might not be able to get the exact seek time requested.
607            if (refreshSeekTime) {
608                if (useOffload()) {
609                    if (postSeekComplete) {
610                        ALOGV("fillBuffer is going to post SEEK_COMPLETE");
611                        mObserver->postAudioSeekComplete();
612                        postSeekComplete = false;
613                    }
614
615                    mStartPosUs = mPositionTimeMediaUs;
616                    ALOGV("adjust seek time to: %.2f", mStartPosUs/ 1E6);
617                }
618                // clear seek time with mLock locked and once we have valid mPositionTimeMediaUs
619                // and mPositionTimeRealUs
620                // before clearing mSeekTimeUs check if a new seek request has been received while
621                // we were reading from the source with mLock released.
622                if (!mSeeking) {
623                    mSeekTimeUs = 0;
624                }
625            }
626
627            if (!useOffload()) {
628                mPositionTimeRealUs =
629                    ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
630                        / mSampleRate;
631                ALOGV("buffer->size() = %d, "
632                     "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
633                     mInputBuffer->range_length(),
634                     mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
635            }
636
637        }
638
639        if (mInputBuffer->range_length() == 0) {
640            mInputBuffer->release();
641            mInputBuffer = NULL;
642
643            continue;
644        }
645
646        size_t copy = size_remaining;
647        if (copy > mInputBuffer->range_length()) {
648            copy = mInputBuffer->range_length();
649        }
650
651        memcpy((char *)data + size_done,
652               (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
653               copy);
654
655        mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
656                                mInputBuffer->range_length() - copy);
657
658        size_done += copy;
659        size_remaining -= copy;
660    }
661
662    if (useOffload()) {
663        // We must ask the hardware what it has played
664        mPositionTimeRealUs = getOutputPlayPositionUs_l();
665        ALOGV("mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
666             mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
667    }
668
669    {
670        Mutex::Autolock autoLock(mLock);
671        mNumFramesPlayed += size_done / mFrameSize;
672        mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
673
674        if (mReachedEOS) {
675            mPinnedTimeUs = mNumFramesPlayedSysTimeUs;
676        } else {
677            mPinnedTimeUs = -1ll;
678        }
679    }
680
681    if (postEOS) {
682        mObserver->postAudioEOS(postEOSDelayUs);
683    }
684
685    if (postSeekComplete) {
686        mObserver->postAudioSeekComplete();
687    }
688
689    return size_done;
690}
691
692int64_t AudioPlayer::getRealTimeUs() {
693    Mutex::Autolock autoLock(mLock);
694    if (useOffload()) {
695        if (mSeeking) {
696            return mSeekTimeUs;
697        }
698        mPositionTimeRealUs = getOutputPlayPositionUs_l();
699        return mPositionTimeRealUs;
700    }
701
702    return getRealTimeUsLocked();
703}
704
705int64_t AudioPlayer::getRealTimeUsLocked() const {
706    CHECK(mStarted);
707    CHECK_NE(mSampleRate, 0);
708    int64_t result = -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
709
710    // Compensate for large audio buffers, updates of mNumFramesPlayed
711    // are less frequent, therefore to get a "smoother" notion of time we
712    // compensate using system time.
713    int64_t diffUs;
714    if (mPinnedTimeUs >= 0ll) {
715        diffUs = mPinnedTimeUs;
716    } else {
717        diffUs = ALooper::GetNowUs();
718    }
719
720    diffUs -= mNumFramesPlayedSysTimeUs;
721
722    return result + diffUs;
723}
724
725int64_t AudioPlayer::getOutputPlayPositionUs_l()
726{
727    uint32_t playedSamples = 0;
728    uint32_t sampleRate;
729    if (mAudioSink != NULL) {
730        mAudioSink->getPosition(&playedSamples);
731        sampleRate = mAudioSink->getSampleRate();
732    } else {
733        mAudioTrack->getPosition(&playedSamples);
734        sampleRate = mAudioTrack->getSampleRate();
735    }
736    if (sampleRate != 0) {
737        mSampleRate = sampleRate;
738    }
739
740    int64_t playedUs;
741    if (mSampleRate != 0) {
742        playedUs = (static_cast<int64_t>(playedSamples) * 1000000 ) / mSampleRate;
743    } else {
744        playedUs = 0;
745    }
746
747    // HAL position is relative to the first buffer we sent at mStartPosUs
748    const int64_t renderedDuration = mStartPosUs + playedUs;
749    ALOGV("getOutputPlayPositionUs_l %lld", renderedDuration);
750    return renderedDuration;
751}
752
753int64_t AudioPlayer::getMediaTimeUs() {
754    Mutex::Autolock autoLock(mLock);
755
756    if (useOffload()) {
757        if (mSeeking) {
758            return mSeekTimeUs;
759        }
760        mPositionTimeRealUs = getOutputPlayPositionUs_l();
761        ALOGV("getMediaTimeUs getOutputPlayPositionUs_l() mPositionTimeRealUs %lld",
762              mPositionTimeRealUs);
763        return mPositionTimeRealUs;
764    }
765
766
767    if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
768        // mSeekTimeUs is either seek time while seeking or 0 if playback did not start.
769        return mSeekTimeUs;
770    }
771
772    int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs;
773    if (realTimeOffset < 0) {
774        realTimeOffset = 0;
775    }
776
777    return mPositionTimeMediaUs + realTimeOffset;
778}
779
780bool AudioPlayer::getMediaTimeMapping(
781        int64_t *realtime_us, int64_t *mediatime_us) {
782    Mutex::Autolock autoLock(mLock);
783
784    if (useOffload()) {
785        mPositionTimeRealUs = getOutputPlayPositionUs_l();
786        *realtime_us = mPositionTimeRealUs;
787        *mediatime_us = mPositionTimeRealUs;
788    } else {
789        *realtime_us = mPositionTimeRealUs;
790        *mediatime_us = mPositionTimeMediaUs;
791    }
792
793    return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
794}
795
796status_t AudioPlayer::seekTo(int64_t time_us) {
797    Mutex::Autolock autoLock(mLock);
798
799    ALOGV("seekTo( %lld )", time_us);
800
801    mSeeking = true;
802    mPositionTimeRealUs = mPositionTimeMediaUs = -1;
803    mReachedEOS = false;
804    mSeekTimeUs = time_us;
805    mStartPosUs = time_us;
806
807    // Flush resets the number of played frames
808    mNumFramesPlayed = 0;
809    mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
810
811    if (mAudioSink != NULL) {
812        if (mPlaying) {
813            mAudioSink->pause();
814        }
815        mAudioSink->flush();
816        if (mPlaying) {
817            mAudioSink->start();
818        }
819    } else {
820        if (mPlaying) {
821            mAudioTrack->pause();
822        }
823        mAudioTrack->flush();
824        if (mPlaying) {
825            mAudioTrack->start();
826        }
827    }
828
829    return OK;
830}
831
832}
833