AudioPlayer.cpp revision 80a68deec52c9a1b47215ed68526206ec88197f8
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "AudioPlayer" 19#include <utils/Log.h> 20 21#include <media/AudioTrack.h> 22#include <media/stagefright/AudioPlayer.h> 23#include <media/stagefright/MediaDebug.h> 24#include <media/stagefright/MediaDefs.h> 25#include <media/stagefright/MediaSource.h> 26#include <media/stagefright/MetaData.h> 27 28namespace android { 29 30AudioPlayer::AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink) 31 : mAudioTrack(NULL), 32 mInputBuffer(NULL), 33 mSampleRate(0), 34 mLatencyUs(0), 35 mFrameSize(0), 36 mNumFramesPlayed(0), 37 mPositionTimeMediaUs(-1), 38 mPositionTimeRealUs(-1), 39 mSeeking(false), 40 mReachedEOS(false), 41 mStarted(false), 42 mAudioSink(audioSink) { 43} 44 45AudioPlayer::~AudioPlayer() { 46 if (mStarted) { 47 stop(); 48 } 49} 50 51void AudioPlayer::setSource(const sp<MediaSource> &source) { 52 CHECK_EQ(mSource, NULL); 53 mSource = source; 54} 55 56status_t AudioPlayer::start() { 57 CHECK(!mStarted); 58 CHECK(mSource != NULL); 59 60 status_t err = mSource->start(); 61 62 if (err != OK) { 63 return err; 64 } 65 66 sp<MetaData> format = mSource->getFormat(); 67 const char *mime; 68 bool success = format->findCString(kKeyMIMEType, &mime); 69 CHECK(success); 70 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)); 71 72 success = format->findInt32(kKeySampleRate, &mSampleRate); 73 CHECK(success); 74 75 int32_t numChannels; 76 success = format->findInt32(kKeyChannelCount, &numChannels); 77 CHECK(success); 78 79 if (mAudioSink.get() != NULL) { 80 status_t err = mAudioSink->open( 81 mSampleRate, numChannels, AudioSystem::PCM_16_BIT, 82 DEFAULT_AUDIOSINK_BUFFERCOUNT, 83 &AudioPlayer::AudioSinkCallback, this); 84 if (err != OK) { 85 mSource->stop(); 86 87 return err; 88 } 89 90 mLatencyUs = (int64_t)mAudioSink->latency() * 1000; 91 mFrameSize = mAudioSink->frameSize(); 92 93 mAudioSink->start(); 94 } else { 95 mAudioTrack = new AudioTrack( 96 AudioSystem::MUSIC, mSampleRate, AudioSystem::PCM_16_BIT, 97 (numChannels == 2) 98 ? AudioSystem::CHANNEL_OUT_STEREO 99 : AudioSystem::CHANNEL_OUT_MONO, 100 8192, 0, &AudioCallback, this, 0); 101 102 if (mAudioTrack->initCheck() != OK) { 103 delete mAudioTrack; 104 mAudioTrack = NULL; 105 106 mSource->stop(); 107 108 return mAudioTrack->initCheck(); 109 } 110 111 mLatencyUs = (int64_t)mAudioTrack->latency() * 1000; 112 mFrameSize = mAudioTrack->frameSize(); 113 114 mAudioTrack->start(); 115 } 116 117 mStarted = true; 118 119 return OK; 120} 121 122void AudioPlayer::pause() { 123 CHECK(mStarted); 124 125 if (mAudioSink.get() != NULL) { 126 mAudioSink->pause(); 127 } else { 128 mAudioTrack->stop(); 129 } 130} 131 132void AudioPlayer::resume() { 133 CHECK(mStarted); 134 135 if (mAudioSink.get() != NULL) { 136 mAudioSink->start(); 137 } else { 138 mAudioTrack->start(); 139 } 140} 141 142void AudioPlayer::stop() { 143 CHECK(mStarted); 144 145 if (mAudioSink.get() != NULL) { 146 mAudioSink->stop(); 147 mAudioSink->close(); 148 } else { 149 mAudioTrack->stop(); 150 151 delete mAudioTrack; 152 mAudioTrack = NULL; 153 } 154 155 // Make sure to release any buffer we hold onto so that the 156 // source is able to stop(). 157 if (mInputBuffer != NULL) { 158 LOGV("AudioPlayer releasing input buffer."); 159 160 mInputBuffer->release(); 161 mInputBuffer = NULL; 162 } 163 164 mSource->stop(); 165 166 mNumFramesPlayed = 0; 167 mPositionTimeMediaUs = -1; 168 mPositionTimeRealUs = -1; 169 mSeeking = false; 170 mReachedEOS = false; 171 mStarted = false; 172} 173 174// static 175void AudioPlayer::AudioCallback(int event, void *user, void *info) { 176 static_cast<AudioPlayer *>(user)->AudioCallback(event, info); 177} 178 179bool AudioPlayer::isSeeking() { 180 Mutex::Autolock autoLock(mLock); 181 return mSeeking; 182} 183 184bool AudioPlayer::reachedEOS() { 185 Mutex::Autolock autoLock(mLock); 186 return mReachedEOS; 187} 188 189// static 190void AudioPlayer::AudioSinkCallback( 191 MediaPlayerBase::AudioSink *audioSink, 192 void *buffer, size_t size, void *cookie) { 193 AudioPlayer *me = (AudioPlayer *)cookie; 194 195 me->fillBuffer(buffer, size); 196} 197 198void AudioPlayer::AudioCallback(int event, void *info) { 199 if (event != AudioTrack::EVENT_MORE_DATA) { 200 return; 201 } 202 203 AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info; 204 fillBuffer(buffer->raw, buffer->size); 205} 206 207void AudioPlayer::fillBuffer(void *data, size_t size) { 208 if (mNumFramesPlayed == 0) { 209 LOGV("AudioCallback"); 210 } 211 212 if (mReachedEOS) { 213 memset(data, 0, size); 214 return; 215 } 216 217 size_t size_done = 0; 218 size_t size_remaining = size; 219 while (size_remaining > 0) { 220 MediaSource::ReadOptions options; 221 222 { 223 Mutex::Autolock autoLock(mLock); 224 225 if (mSeeking) { 226 options.setSeekTo(mSeekTimeUs); 227 228 if (mInputBuffer != NULL) { 229 mInputBuffer->release(); 230 mInputBuffer = NULL; 231 } 232 } 233 } 234 235 if (mInputBuffer == NULL) { 236 status_t err = mSource->read(&mInputBuffer, &options); 237 238 CHECK((err == OK && mInputBuffer != NULL) 239 || (err != OK && mInputBuffer == NULL)); 240 241 Mutex::Autolock autoLock(mLock); 242 243 mSeeking = false; 244 245 if (err != OK) { 246 mReachedEOS = true; 247 memset((char *)data + size_done, 0, size_remaining); 248 break; 249 } 250 251 CHECK(mInputBuffer->meta_data()->findInt64( 252 kKeyTime, &mPositionTimeMediaUs)); 253 254 mPositionTimeRealUs = 255 ((mNumFramesPlayed + size_done / mFrameSize) * 1000000) 256 / mSampleRate; 257 258 LOGV("buffer->size() = %d, " 259 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f", 260 mInputBuffer->range_length(), 261 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6); 262 } 263 264 if (mInputBuffer->range_length() == 0) { 265 mInputBuffer->release(); 266 mInputBuffer = NULL; 267 268 continue; 269 } 270 271 size_t copy = size_remaining; 272 if (copy > mInputBuffer->range_length()) { 273 copy = mInputBuffer->range_length(); 274 } 275 276 memcpy((char *)data + size_done, 277 (const char *)mInputBuffer->data() + mInputBuffer->range_offset(), 278 copy); 279 280 mInputBuffer->set_range(mInputBuffer->range_offset() + copy, 281 mInputBuffer->range_length() - copy); 282 283 size_done += copy; 284 size_remaining -= copy; 285 } 286 287 Mutex::Autolock autoLock(mLock); 288 mNumFramesPlayed += size / mFrameSize; 289} 290 291int64_t AudioPlayer::getRealTimeUs() { 292 Mutex::Autolock autoLock(mLock); 293 return getRealTimeUsLocked(); 294} 295 296int64_t AudioPlayer::getRealTimeUsLocked() const { 297 return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate; 298} 299 300int64_t AudioPlayer::getMediaTimeUs() { 301 Mutex::Autolock autoLock(mLock); 302 303 if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) { 304 return 0; 305 } 306 307 int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs; 308 if (realTimeOffset < 0) { 309 realTimeOffset = 0; 310 } 311 312 return mPositionTimeMediaUs + realTimeOffset; 313} 314 315bool AudioPlayer::getMediaTimeMapping( 316 int64_t *realtime_us, int64_t *mediatime_us) { 317 Mutex::Autolock autoLock(mLock); 318 319 *realtime_us = mPositionTimeRealUs; 320 *mediatime_us = mPositionTimeMediaUs; 321 322 return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1; 323} 324 325status_t AudioPlayer::seekTo(int64_t time_us) { 326 Mutex::Autolock autoLock(mLock); 327 328 mSeeking = true; 329 mReachedEOS = false; 330 mSeekTimeUs = time_us; 331 332 return OK; 333} 334 335} 336