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