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