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