AudioPlayer.cpp revision 5295c0c55d41a2906ea7f65a3f22e6278cb17d4b
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 mFinalStatus(OK), 42 mStarted(false), 43 mAudioSink(audioSink) { 44} 45 46AudioPlayer::~AudioPlayer() { 47 if (mStarted) { 48 stop(); 49 } 50} 51 52void AudioPlayer::setSource(const sp<MediaSource> &source) { 53 CHECK_EQ(mSource, NULL); 54 mSource = source; 55} 56 57status_t AudioPlayer::start() { 58 CHECK(!mStarted); 59 CHECK(mSource != NULL); 60 61 status_t err = mSource->start(); 62 63 if (err != OK) { 64 return err; 65 } 66 67 sp<MetaData> format = mSource->getFormat(); 68 const char *mime; 69 bool success = format->findCString(kKeyMIMEType, &mime); 70 CHECK(success); 71 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)); 72 73 success = format->findInt32(kKeySampleRate, &mSampleRate); 74 CHECK(success); 75 76 int32_t numChannels; 77 success = format->findInt32(kKeyChannelCount, &numChannels); 78 CHECK(success); 79 80 if (mAudioSink.get() != NULL) { 81 status_t err = mAudioSink->open( 82 mSampleRate, numChannels, AudioSystem::PCM_16_BIT, 83 DEFAULT_AUDIOSINK_BUFFERCOUNT, 84 &AudioPlayer::AudioSinkCallback, this); 85 if (err != OK) { 86 mSource->stop(); 87 88 return err; 89 } 90 91 mLatencyUs = (int64_t)mAudioSink->latency() * 1000; 92 mFrameSize = mAudioSink->frameSize(); 93 94 mAudioSink->start(); 95 } else { 96 mAudioTrack = new AudioTrack( 97 AudioSystem::MUSIC, mSampleRate, AudioSystem::PCM_16_BIT, 98 (numChannels == 2) 99 ? AudioSystem::CHANNEL_OUT_STEREO 100 : AudioSystem::CHANNEL_OUT_MONO, 101 8192, 0, &AudioCallback, this, 0); 102 103 if ((err = mAudioTrack->initCheck()) != OK) { 104 delete mAudioTrack; 105 mAudioTrack = NULL; 106 107 mSource->stop(); 108 109 return err; 110 } 111 112 mLatencyUs = (int64_t)mAudioTrack->latency() * 1000; 113 mFrameSize = mAudioTrack->frameSize(); 114 115 mAudioTrack->start(); 116 } 117 118 mStarted = true; 119 120 return OK; 121} 122 123void AudioPlayer::pause() { 124 CHECK(mStarted); 125 126 if (mAudioSink.get() != NULL) { 127 mAudioSink->pause(); 128 } else { 129 mAudioTrack->stop(); 130 } 131} 132 133void AudioPlayer::resume() { 134 CHECK(mStarted); 135 136 if (mAudioSink.get() != NULL) { 137 mAudioSink->start(); 138 } else { 139 mAudioTrack->start(); 140 } 141} 142 143void AudioPlayer::stop() { 144 CHECK(mStarted); 145 146 if (mAudioSink.get() != NULL) { 147 mAudioSink->stop(); 148 mAudioSink->close(); 149 } else { 150 mAudioTrack->stop(); 151 152 delete mAudioTrack; 153 mAudioTrack = NULL; 154 } 155 156 // Make sure to release any buffer we hold onto so that the 157 // source is able to stop(). 158 if (mInputBuffer != NULL) { 159 LOGV("AudioPlayer releasing input buffer."); 160 161 mInputBuffer->release(); 162 mInputBuffer = NULL; 163 } 164 165 mSource->stop(); 166 167 mNumFramesPlayed = 0; 168 mPositionTimeMediaUs = -1; 169 mPositionTimeRealUs = -1; 170 mSeeking = false; 171 mReachedEOS = false; 172 mFinalStatus = OK; 173 mStarted = false; 174} 175 176// static 177void AudioPlayer::AudioCallback(int event, void *user, void *info) { 178 static_cast<AudioPlayer *>(user)->AudioCallback(event, info); 179} 180 181bool AudioPlayer::isSeeking() { 182 Mutex::Autolock autoLock(mLock); 183 return mSeeking; 184} 185 186bool AudioPlayer::reachedEOS(status_t *finalStatus) { 187 *finalStatus = OK; 188 189 Mutex::Autolock autoLock(mLock); 190 *finalStatus = mFinalStatus; 191 return mReachedEOS; 192} 193 194// static 195size_t AudioPlayer::AudioSinkCallback( 196 MediaPlayerBase::AudioSink *audioSink, 197 void *buffer, size_t size, void *cookie) { 198 AudioPlayer *me = (AudioPlayer *)cookie; 199 200 return me->fillBuffer(buffer, size); 201} 202 203void AudioPlayer::AudioCallback(int event, void *info) { 204 if (event != AudioTrack::EVENT_MORE_DATA) { 205 return; 206 } 207 208 AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info; 209 size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size); 210 211 buffer->size = numBytesWritten; 212} 213 214size_t AudioPlayer::fillBuffer(void *data, size_t size) { 215 if (mNumFramesPlayed == 0) { 216 LOGV("AudioCallback"); 217 } 218 219 if (mReachedEOS) { 220 return 0; 221 } 222 223 size_t size_done = 0; 224 size_t size_remaining = size; 225 while (size_remaining > 0) { 226 MediaSource::ReadOptions options; 227 228 { 229 Mutex::Autolock autoLock(mLock); 230 231 if (mSeeking) { 232 options.setSeekTo(mSeekTimeUs); 233 234 if (mInputBuffer != NULL) { 235 mInputBuffer->release(); 236 mInputBuffer = NULL; 237 } 238 239 mSeeking = false; 240 } 241 } 242 243 if (mInputBuffer == NULL) { 244 status_t err = mSource->read(&mInputBuffer, &options); 245 246 CHECK((err == OK && mInputBuffer != NULL) 247 || (err != OK && mInputBuffer == NULL)); 248 249 Mutex::Autolock autoLock(mLock); 250 251 if (err != OK) { 252 mReachedEOS = true; 253 mFinalStatus = err; 254 break; 255 } 256 257 CHECK(mInputBuffer->meta_data()->findInt64( 258 kKeyTime, &mPositionTimeMediaUs)); 259 260 mPositionTimeRealUs = 261 ((mNumFramesPlayed + size_done / mFrameSize) * 1000000) 262 / mSampleRate; 263 264 LOGV("buffer->size() = %d, " 265 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f", 266 mInputBuffer->range_length(), 267 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6); 268 } 269 270 if (mInputBuffer->range_length() == 0) { 271 mInputBuffer->release(); 272 mInputBuffer = NULL; 273 274 continue; 275 } 276 277 size_t copy = size_remaining; 278 if (copy > mInputBuffer->range_length()) { 279 copy = mInputBuffer->range_length(); 280 } 281 282 memcpy((char *)data + size_done, 283 (const char *)mInputBuffer->data() + mInputBuffer->range_offset(), 284 copy); 285 286 mInputBuffer->set_range(mInputBuffer->range_offset() + copy, 287 mInputBuffer->range_length() - copy); 288 289 size_done += copy; 290 size_remaining -= copy; 291 } 292 293 Mutex::Autolock autoLock(mLock); 294 mNumFramesPlayed += size_done / mFrameSize; 295 296 return size_done; 297} 298 299int64_t AudioPlayer::getRealTimeUs() { 300 Mutex::Autolock autoLock(mLock); 301 return getRealTimeUsLocked(); 302} 303 304int64_t AudioPlayer::getRealTimeUsLocked() const { 305 return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate; 306} 307 308int64_t AudioPlayer::getMediaTimeUs() { 309 Mutex::Autolock autoLock(mLock); 310 311 if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) { 312 return 0; 313 } 314 315 int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs; 316 if (realTimeOffset < 0) { 317 realTimeOffset = 0; 318 } 319 320 return mPositionTimeMediaUs + realTimeOffset; 321} 322 323bool AudioPlayer::getMediaTimeMapping( 324 int64_t *realtime_us, int64_t *mediatime_us) { 325 Mutex::Autolock autoLock(mLock); 326 327 *realtime_us = mPositionTimeRealUs; 328 *mediatime_us = mPositionTimeMediaUs; 329 330 return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1; 331} 332 333status_t AudioPlayer::seekTo(int64_t time_us) { 334 Mutex::Autolock autoLock(mLock); 335 336 mSeeking = true; 337 mReachedEOS = false; 338 mSeekTimeUs = time_us; 339 340 return OK; 341} 342 343} 344