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