AudioPlayer.cpp revision bd7b7177f88ae6e83bd7bb8bfd9b7018be923931
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 memset(data, 0, size); 310 311 return size; 312 } 313 314 bool postSeekComplete = false; 315 bool postEOS = false; 316 int64_t postEOSDelayUs = 0; 317 318 size_t size_done = 0; 319 size_t size_remaining = size; 320 while (size_remaining > 0) { 321 MediaSource::ReadOptions options; 322 323 { 324 Mutex::Autolock autoLock(mLock); 325 326 if (mSeeking) { 327 if (mIsFirstBuffer) { 328 if (mFirstBuffer != NULL) { 329 mFirstBuffer->release(); 330 mFirstBuffer = NULL; 331 } 332 mIsFirstBuffer = false; 333 } 334 335 options.setSeekTo(mSeekTimeUs); 336 337 if (mInputBuffer != NULL) { 338 mInputBuffer->release(); 339 mInputBuffer = NULL; 340 } 341 342 mSeeking = false; 343 if (mObserver) { 344 postSeekComplete = true; 345 } 346 } 347 } 348 349 if (mInputBuffer == NULL) { 350 status_t err; 351 352 if (mIsFirstBuffer) { 353 mInputBuffer = mFirstBuffer; 354 mFirstBuffer = NULL; 355 err = mFirstBufferResult; 356 357 mIsFirstBuffer = false; 358 } else { 359 err = mSource->read(&mInputBuffer, &options); 360 } 361 362 CHECK((err == OK && mInputBuffer != NULL) 363 || (err != OK && mInputBuffer == NULL)); 364 365 Mutex::Autolock autoLock(mLock); 366 367 if (err != OK) { 368 if (mObserver && !mReachedEOS) { 369 // We don't want to post EOS right away but only 370 // after all frames have actually been played out. 371 372 // These are the number of frames submitted to the 373 // AudioTrack that you haven't heard yet. 374 uint32_t numFramesPendingPlayout = 375 getNumFramesPendingPlayout(); 376 377 // These are the number of frames we're going to 378 // submit to the AudioTrack by returning from this 379 // callback. 380 uint32_t numAdditionalFrames = size_done / mFrameSize; 381 382 numFramesPendingPlayout += numAdditionalFrames; 383 384 int64_t timeToCompletionUs = 385 (1000000ll * numFramesPendingPlayout) / mSampleRate; 386 387 LOGV("total number of frames played: %lld (%lld us)", 388 (mNumFramesPlayed + numAdditionalFrames), 389 1000000ll * (mNumFramesPlayed + numAdditionalFrames) 390 / mSampleRate); 391 392 LOGV("%d frames left to play, %lld us (%.2f secs)", 393 numFramesPendingPlayout, 394 timeToCompletionUs, timeToCompletionUs / 1E6); 395 396 postEOS = true; 397 postEOSDelayUs = timeToCompletionUs + mLatencyUs; 398 } 399 400 mReachedEOS = true; 401 mFinalStatus = err; 402 break; 403 } 404 405 CHECK(mInputBuffer->meta_data()->findInt64( 406 kKeyTime, &mPositionTimeMediaUs)); 407 408 mPositionTimeRealUs = 409 ((mNumFramesPlayed + size_done / mFrameSize) * 1000000) 410 / mSampleRate; 411 412 LOGV("buffer->size() = %d, " 413 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f", 414 mInputBuffer->range_length(), 415 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6); 416 } 417 418 if (mInputBuffer->range_length() == 0) { 419 mInputBuffer->release(); 420 mInputBuffer = NULL; 421 422 continue; 423 } 424 425 size_t copy = size_remaining; 426 if (copy > mInputBuffer->range_length()) { 427 copy = mInputBuffer->range_length(); 428 } 429 430 memcpy((char *)data + size_done, 431 (const char *)mInputBuffer->data() + mInputBuffer->range_offset(), 432 copy); 433 434 mInputBuffer->set_range(mInputBuffer->range_offset() + copy, 435 mInputBuffer->range_length() - copy); 436 437 size_done += copy; 438 size_remaining -= copy; 439 } 440 441 { 442 Mutex::Autolock autoLock(mLock); 443 mNumFramesPlayed += size_done / mFrameSize; 444 } 445 446 if (postEOS) { 447 mObserver->postAudioEOS(postEOSDelayUs); 448 } 449 450 if (postSeekComplete) { 451 mObserver->postAudioSeekComplete(); 452 } 453 454 return size_done; 455} 456 457int64_t AudioPlayer::getRealTimeUs() { 458 Mutex::Autolock autoLock(mLock); 459 return getRealTimeUsLocked(); 460} 461 462int64_t AudioPlayer::getRealTimeUsLocked() const { 463 return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate; 464} 465 466int64_t AudioPlayer::getMediaTimeUs() { 467 Mutex::Autolock autoLock(mLock); 468 469 if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) { 470 if (mSeeking) { 471 return mSeekTimeUs; 472 } 473 474 return 0; 475 } 476 477 int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs; 478 if (realTimeOffset < 0) { 479 realTimeOffset = 0; 480 } 481 482 return mPositionTimeMediaUs + realTimeOffset; 483} 484 485bool AudioPlayer::getMediaTimeMapping( 486 int64_t *realtime_us, int64_t *mediatime_us) { 487 Mutex::Autolock autoLock(mLock); 488 489 *realtime_us = mPositionTimeRealUs; 490 *mediatime_us = mPositionTimeMediaUs; 491 492 return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1; 493} 494 495status_t AudioPlayer::seekTo(int64_t time_us) { 496 Mutex::Autolock autoLock(mLock); 497 498 mSeeking = true; 499 mPositionTimeRealUs = mPositionTimeMediaUs = -1; 500 mReachedEOS = false; 501 mSeekTimeUs = time_us; 502 503 if (mAudioSink != NULL) { 504 mAudioSink->flush(); 505 } else { 506 mAudioTrack->flush(); 507 } 508 509 return OK; 510} 511 512} 513