1d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong/*
2d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong * Copyright (C) 2011 The Android Open Source Project
3d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong *
4d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong * Licensed under the Apache License, Version 2.0 (the "License");
5d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong * you may not use this file except in compliance with the License.
6d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong * You may obtain a copy of the License at
7d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong *
8d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong *      http://www.apache.org/licenses/LICENSE-2.0
9d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong *
10d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong * Unless required by applicable law or agreed to in writing, software
11d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong * distributed under the License is distributed on an "AS IS" BASIS,
12d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong * See the License for the specific language governing permissions and
14d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong * limitations under the License.
15d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong */
16d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
17d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong//#define LOG_NDEBUG 0
18d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong#define LOG_TAG "AudioPlayerBase"
19d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong#include <utils/Log.h>
20d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
21d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong#include <binder/IPCThreadState.h>
22d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong#include <media/AudioTrack.h>
23d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong#include <media/stagefright/MediaDebug.h>
24d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong#include <media/stagefright/MediaDefs.h>
25d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong#include <media/stagefright/MediaErrors.h>
26d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong#include <media/stagefright/MediaSource.h>
27d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong#include <media/stagefright/MetaData.h>
28d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
29d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong#include "AudioPlayerBase.h"
30d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong#include "PreviewPlayerBase.h"
31d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
32d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dongnamespace android {
33d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
34d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James DongAudioPlayerBase::AudioPlayerBase(
35d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        const sp<MediaPlayerBase::AudioSink> &audioSink,
36d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        PreviewPlayerBase *observer)
37d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    : mAudioTrack(NULL),
38d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong      mInputBuffer(NULL),
39d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong      mSampleRate(0),
40d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong      mLatencyUs(0),
41d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong      mFrameSize(0),
42d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong      mNumFramesPlayed(0),
43d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong      mPositionTimeMediaUs(-1),
44d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong      mPositionTimeRealUs(-1),
45d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong      mSeeking(false),
46d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong      mReachedEOS(false),
47d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong      mFinalStatus(OK),
48d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong      mStarted(false),
49d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong      mIsFirstBuffer(false),
50d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong      mFirstBufferResult(OK),
51d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong      mFirstBuffer(NULL),
52d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong      mAudioSink(audioSink),
53d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong      mObserver(observer) {
54d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
55d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
56d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James DongAudioPlayerBase::~AudioPlayerBase() {
57d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    if (mStarted) {
58d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        reset();
59d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
60d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
61d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
62d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dongvoid AudioPlayerBase::setSource(const sp<MediaSource> &source) {
63d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    CHECK_EQ(mSource, NULL);
64d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    mSource = source;
65d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
66d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
67d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dongstatus_t AudioPlayerBase::start(bool sourceAlreadyStarted) {
68d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    CHECK(!mStarted);
69d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    CHECK(mSource != NULL);
70d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
71d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    status_t err;
72d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    if (!sourceAlreadyStarted) {
73d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        err = mSource->start();
74d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
75d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        if (err != OK) {
76d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            return err;
77d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        }
78d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
79d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
80d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    // We allow an optional INFO_FORMAT_CHANGED at the very beginning
81d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    // of playback, if there is one, getFormat below will retrieve the
82d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    // updated format, if there isn't, we'll stash away the valid buffer
83d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    // of data to be used on the first audio callback.
84d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
85d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    CHECK(mFirstBuffer == NULL);
86d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
87d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    mFirstBufferResult = mSource->read(&mFirstBuffer);
88d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
89d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        LOGV("INFO_FORMAT_CHANGED!!!");
90d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
91d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        CHECK(mFirstBuffer == NULL);
92d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mFirstBufferResult = OK;
93d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mIsFirstBuffer = false;
94d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    } else {
95d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mIsFirstBuffer = true;
96d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
97d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
98d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    sp<MetaData> format = mSource->getFormat();
99d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    const char *mime;
100d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    bool success = format->findCString(kKeyMIMEType, &mime);
101d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    CHECK(success);
102d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
103d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
104d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    success = format->findInt32(kKeySampleRate, &mSampleRate);
105d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    CHECK(success);
106d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
107d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    int32_t numChannels;
108d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    success = format->findInt32(kKeyChannelCount, &numChannels);
109d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    CHECK(success);
110d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
111d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    if (mAudioSink.get() != NULL) {
112d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        status_t err = mAudioSink->open(
113d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                mSampleRate, numChannels, AUDIO_FORMAT_PCM_16_BIT,
114d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                DEFAULT_AUDIOSINK_BUFFERCOUNT,
115d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                &AudioPlayerBase::AudioSinkCallback, this);
116d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        if (err != OK) {
117d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            if (mFirstBuffer != NULL) {
118d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                mFirstBuffer->release();
119d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                mFirstBuffer = NULL;
120d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            }
121d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
122d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            if (!sourceAlreadyStarted) {
123d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                mSource->stop();
124d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            }
125d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
126d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            return err;
127d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        }
128d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
129d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
130d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mFrameSize = mAudioSink->frameSize();
131d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
132d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mAudioSink->start();
133d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    } else {
134d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mAudioTrack = new AudioTrack(
135d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT,
136d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                (numChannels == 2)
137d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    ? AUDIO_CHANNEL_OUT_STEREO
138d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    : AUDIO_CHANNEL_OUT_MONO,
139d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                0, 0, &AudioCallback, this, 0);
140d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
141d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        if ((err = mAudioTrack->initCheck()) != OK) {
142d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            delete mAudioTrack;
143d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            mAudioTrack = NULL;
144d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
145d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            if (mFirstBuffer != NULL) {
146d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                mFirstBuffer->release();
147d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                mFirstBuffer = NULL;
148d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            }
149d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
150d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            if (!sourceAlreadyStarted) {
151d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                mSource->stop();
152d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            }
153d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
154d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            return err;
155d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        }
156d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
157d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
158d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mFrameSize = mAudioTrack->frameSize();
159d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
160d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mAudioTrack->start();
161d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
162d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
163d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    mStarted = true;
164d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
165d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    return OK;
166d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
167d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
168d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dongvoid AudioPlayerBase::pause(bool playPendingSamples) {
169d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    CHECK(mStarted);
170d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
171d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    if (playPendingSamples) {
172d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        if (mAudioSink.get() != NULL) {
173d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            mAudioSink->stop();
174d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        } else {
175d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            mAudioTrack->stop();
176d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        }
177d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    } else {
178d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        if (mAudioSink.get() != NULL) {
179d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            mAudioSink->pause();
180d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        } else {
181d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            mAudioTrack->pause();
182d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        }
183d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
184d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
185d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
186d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dongvoid AudioPlayerBase::resume() {
187d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    CHECK(mStarted);
188d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
189d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    if (mAudioSink.get() != NULL) {
190d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mAudioSink->start();
191d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    } else {
192d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mAudioTrack->start();
193d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
194d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
195d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
196d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dongvoid AudioPlayerBase::reset() {
197d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    CHECK(mStarted);
198d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
199d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    if (mAudioSink.get() != NULL) {
200d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mAudioSink->stop();
201d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mAudioSink->close();
202d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    } else {
203d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mAudioTrack->stop();
204d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
205d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        delete mAudioTrack;
206d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mAudioTrack = NULL;
207d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
208d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
209d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    // Make sure to release any buffer we hold onto so that the
210d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    // source is able to stop().
211d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
212d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    if (mFirstBuffer != NULL) {
213d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mFirstBuffer->release();
214d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mFirstBuffer = NULL;
215d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
216d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
217d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    if (mInputBuffer != NULL) {
218d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        LOGV("AudioPlayerBase releasing input buffer.");
219d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
220d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mInputBuffer->release();
221d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mInputBuffer = NULL;
222d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
223d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
224d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    mSource->stop();
225d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
226d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    // The following hack is necessary to ensure that the OMX
227d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    // component is completely released by the time we may try
228d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    // to instantiate it again.
229d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    wp<MediaSource> tmp = mSource;
230d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    mSource.clear();
231d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    while (tmp.promote() != NULL) {
232d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        usleep(1000);
233d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
234d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    IPCThreadState::self()->flushCommands();
235d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
236d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    mNumFramesPlayed = 0;
237d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    mPositionTimeMediaUs = -1;
238d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    mPositionTimeRealUs = -1;
239d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    mSeeking = false;
240d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    mReachedEOS = false;
241d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    mFinalStatus = OK;
242d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    mStarted = false;
243d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
244d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
245d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong// static
24671e5d0e1c62a5a619d2e4b910c05052c461075feGlenn Kastenvoid AudioPlayerBase::AudioCallback(int event, void *user, void *info) {
247d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    static_cast<AudioPlayerBase *>(user)->AudioCallback(event, info);
248d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
249d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
250d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dongbool AudioPlayerBase::isSeeking() {
251d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    Mutex::Autolock autoLock(mLock);
252d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    return mSeeking;
253d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
254d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
255d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dongbool AudioPlayerBase::reachedEOS(status_t *finalStatus) {
256d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    *finalStatus = OK;
257d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
258d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    Mutex::Autolock autoLock(mLock);
259d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    *finalStatus = mFinalStatus;
260d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    return mReachedEOS;
261d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
262d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
263d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong// static
264d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dongsize_t AudioPlayerBase::AudioSinkCallback(
265d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        MediaPlayerBase::AudioSink *audioSink,
266d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        void *buffer, size_t size, void *cookie) {
267d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    AudioPlayerBase *me = (AudioPlayerBase *)cookie;
268d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
269d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    return me->fillBuffer(buffer, size);
270d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
271d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
27271e5d0e1c62a5a619d2e4b910c05052c461075feGlenn Kastenvoid AudioPlayerBase::AudioCallback(int event, void *info) {
273d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    if (event != AudioTrack::EVENT_MORE_DATA) {
274d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        return;
275d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
276d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
277d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
278d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
279d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
280d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    buffer->size = numBytesWritten;
281d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
282d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
283d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Donguint32_t AudioPlayerBase::getNumFramesPendingPlayout() const {
284d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    uint32_t numFramesPlayedOut;
285d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    status_t err;
286d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
287d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    if (mAudioSink != NULL) {
288d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        err = mAudioSink->getPosition(&numFramesPlayedOut);
289d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    } else {
290d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        err = mAudioTrack->getPosition(&numFramesPlayedOut);
291d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
292d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
293d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    if (err != OK || mNumFramesPlayed < numFramesPlayedOut) {
294d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        return 0;
295d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
296d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
297d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    // mNumFramesPlayed is the number of frames submitted
298d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    // to the audio sink for playback, but not all of them
299d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    // may have played out by now.
300d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    return mNumFramesPlayed - numFramesPlayedOut;
301d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
302d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
303d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dongsize_t AudioPlayerBase::fillBuffer(void *data, size_t size) {
304d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    if (mNumFramesPlayed == 0) {
305d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        LOGV("AudioCallback");
306d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
307d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
308d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    if (mReachedEOS) {
309d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        return 0;
310d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
311d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
312d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    bool postSeekComplete = false;
313d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    bool postEOS = false;
314d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    int64_t postEOSDelayUs = 0;
315d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
316d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    size_t size_done = 0;
317d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    size_t size_remaining = size;
318d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    while (size_remaining > 0) {
319d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        MediaSource::ReadOptions options;
320d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
321d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        {
322d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            Mutex::Autolock autoLock(mLock);
323d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
324d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            if (mSeeking) {
325d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                if (mIsFirstBuffer) {
326d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    if (mFirstBuffer != NULL) {
327d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                        mFirstBuffer->release();
328d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                        mFirstBuffer = NULL;
329d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    }
330d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    mIsFirstBuffer = false;
331d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                }
332d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
333d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                options.setSeekTo(mSeekTimeUs);
334d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
335d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                if (mInputBuffer != NULL) {
336d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    mInputBuffer->release();
337d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    mInputBuffer = NULL;
338d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                }
339d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
340d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                mSeeking = false;
341d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                if (mObserver) {
342d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    postSeekComplete = true;
343d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                }
344d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            }
345d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        }
346d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
347d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        if (mInputBuffer == NULL) {
348d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            status_t err;
349d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
350d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            if (mIsFirstBuffer) {
351d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                mInputBuffer = mFirstBuffer;
352d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                mFirstBuffer = NULL;
353d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                err = mFirstBufferResult;
354d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
355d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                mIsFirstBuffer = false;
356d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            } else {
357d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                err = mSource->read(&mInputBuffer, &options);
358d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            }
359d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
360d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            CHECK((err == OK && mInputBuffer != NULL)
361d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                   || (err != OK && mInputBuffer == NULL));
362d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
363d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            Mutex::Autolock autoLock(mLock);
364d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
365d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            if (err != OK) {
366d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                if (mObserver && !mReachedEOS) {
367d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    // We don't want to post EOS right away but only
368d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    // after all frames have actually been played out.
369d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
370d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    // These are the number of frames submitted to the
371d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    // AudioTrack that you haven't heard yet.
372d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    uint32_t numFramesPendingPlayout =
373d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                        getNumFramesPendingPlayout();
374d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
375d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    // These are the number of frames we're going to
376d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    // submit to the AudioTrack by returning from this
377d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    // callback.
378d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    uint32_t numAdditionalFrames = size_done / mFrameSize;
379d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
380d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    numFramesPendingPlayout += numAdditionalFrames;
381d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
382d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    int64_t timeToCompletionUs =
383d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                        (1000000ll * numFramesPendingPlayout) / mSampleRate;
384d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
385d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    LOGV("total number of frames played: %lld (%lld us)",
386d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                            (mNumFramesPlayed + numAdditionalFrames),
387d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                            1000000ll * (mNumFramesPlayed + numAdditionalFrames)
388d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                                / mSampleRate);
389d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
390d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    LOGV("%d frames left to play, %lld us (%.2f secs)",
391d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                         numFramesPendingPlayout,
392d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                         timeToCompletionUs, timeToCompletionUs / 1E6);
393d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
394d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    postEOS = true;
395d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    postEOSDelayUs = timeToCompletionUs + mLatencyUs;
396d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                }
397d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
398d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                mReachedEOS = true;
399d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                mFinalStatus = err;
400d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                break;
401d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            }
402d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
403d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            CHECK(mInputBuffer->meta_data()->findInt64(
404d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                        kKeyTime, &mPositionTimeMediaUs));
405d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
406d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            mPositionTimeRealUs =
407d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
408d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                    / mSampleRate;
409d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
410d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            LOGV("buffer->size() = %d, "
411d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
412d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                 mInputBuffer->range_length(),
413d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
414d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        }
415d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
416d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        if (mInputBuffer->range_length() == 0) {
417d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            mInputBuffer->release();
418d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            mInputBuffer = NULL;
419d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
420d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            continue;
421d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        }
422d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
423d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        size_t copy = size_remaining;
424d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        if (copy > mInputBuffer->range_length()) {
425d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            copy = mInputBuffer->range_length();
426d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        }
427d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
428d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        memcpy((char *)data + size_done,
429d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong               (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
430d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong               copy);
431d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
432d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
433d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong                                mInputBuffer->range_length() - copy);
434d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
435d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        size_done += copy;
436d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        size_remaining -= copy;
437d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
438d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
439d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    {
440d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        Mutex::Autolock autoLock(mLock);
441d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mNumFramesPlayed += size_done / mFrameSize;
442d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
443d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
444d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    if (postEOS) {
445d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mObserver->postAudioEOS(postEOSDelayUs);
446d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
447d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
448d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    if (postSeekComplete) {
449d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mObserver->postAudioSeekComplete();
450d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
451d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
452d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    return size_done;
453d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
454d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
455d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dongint64_t AudioPlayerBase::getRealTimeUs() {
456d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    Mutex::Autolock autoLock(mLock);
457d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    return getRealTimeUsLocked();
458d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
459d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
460d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dongint64_t AudioPlayerBase::getRealTimeUsLocked() const {
461d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
462d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
463d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
464d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dongint64_t AudioPlayerBase::getMediaTimeUs() {
465d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    Mutex::Autolock autoLock(mLock);
466d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
467d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
468d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        if (mSeeking) {
469d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong            return mSeekTimeUs;
470d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        }
471d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
472d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        return 0;
473d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
474d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
475d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs;
476d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    if (realTimeOffset < 0) {
477d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        realTimeOffset = 0;
478d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
479d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
480d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    return mPositionTimeMediaUs + realTimeOffset;
481d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
482d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
483d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dongbool AudioPlayerBase::getMediaTimeMapping(
484d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        int64_t *realtime_us, int64_t *mediatime_us) {
485d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    Mutex::Autolock autoLock(mLock);
486d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
487d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    *realtime_us = mPositionTimeRealUs;
488d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    *mediatime_us = mPositionTimeMediaUs;
489d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
490d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
491d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
492d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
493d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dongstatus_t AudioPlayerBase::seekTo(int64_t time_us) {
494d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    Mutex::Autolock autoLock(mLock);
495d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
496d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    mSeeking = true;
497d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    mPositionTimeRealUs = mPositionTimeMediaUs = -1;
498d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    mReachedEOS = false;
499d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    mSeekTimeUs = time_us;
500d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
501d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    if (mAudioSink != NULL) {
502d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mAudioSink->flush();
503d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    } else {
504d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong        mAudioTrack->flush();
505d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    }
506d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
507d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong    return OK;
508d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
509d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong
510d30f1bcd661eb469c92ceddaea15ae6fb07e7a92James Dong}
511