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