AudioPlayer.cpp revision a5750e0dad9e90f2195ce36f2c4457fa04b2b83e
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#include <inttypes.h> 18 19//#define LOG_NDEBUG 0 20#define LOG_TAG "AudioPlayer" 21#include <utils/Log.h> 22#include <cutils/compiler.h> 23 24#include <binder/IPCThreadState.h> 25#include <media/AudioTrack.h> 26#include <media/stagefright/foundation/ADebug.h> 27#include <media/stagefright/foundation/ALooper.h> 28#include <media/stagefright/AudioPlayer.h> 29#include <media/stagefright/MediaDefs.h> 30#include <media/stagefright/MediaErrors.h> 31#include <media/stagefright/MediaSource.h> 32#include <media/stagefright/MetaData.h> 33#include <media/stagefright/Utils.h> 34 35#include "include/AwesomePlayer.h" 36 37namespace android { 38 39AudioPlayer::AudioPlayer( 40 const sp<MediaPlayerBase::AudioSink> &audioSink, 41 uint32_t flags, 42 AwesomePlayer *observer) 43 : mInputBuffer(NULL), 44 mSampleRate(0), 45 mLatencyUs(0), 46 mFrameSize(0), 47 mNumFramesPlayed(0), 48 mNumFramesPlayedSysTimeUs(ALooper::GetNowUs()), 49 mPositionTimeMediaUs(-1), 50 mPositionTimeRealUs(-1), 51 mSeeking(false), 52 mReachedEOS(false), 53 mFinalStatus(OK), 54 mSeekTimeUs(0), 55 mStarted(false), 56 mIsFirstBuffer(false), 57 mFirstBufferResult(OK), 58 mFirstBuffer(NULL), 59 mAudioSink(audioSink), 60 mObserver(observer), 61 mPinnedTimeUs(-1ll), 62 mPlaying(false), 63 mStartPosUs(0), 64 mCreateFlags(flags) { 65} 66 67AudioPlayer::~AudioPlayer() { 68 if (mStarted) { 69 reset(); 70 } 71} 72 73void AudioPlayer::setSource(const sp<MediaSource> &source) { 74 CHECK(mSource == NULL); 75 mSource = source; 76} 77 78status_t AudioPlayer::start(bool sourceAlreadyStarted) { 79 CHECK(!mStarted); 80 CHECK(mSource != NULL); 81 82 status_t err; 83 if (!sourceAlreadyStarted) { 84 err = mSource->start(); 85 86 if (err != OK) { 87 return err; 88 } 89 } 90 91 // We allow an optional INFO_FORMAT_CHANGED at the very beginning 92 // of playback, if there is one, getFormat below will retrieve the 93 // updated format, if there isn't, we'll stash away the valid buffer 94 // of data to be used on the first audio callback. 95 96 CHECK(mFirstBuffer == NULL); 97 98 MediaSource::ReadOptions options; 99 if (mSeeking) { 100 options.setSeekTo(mSeekTimeUs); 101 mSeeking = false; 102 } 103 104 mFirstBufferResult = mSource->read(&mFirstBuffer, &options); 105 if (mFirstBufferResult == INFO_FORMAT_CHANGED) { 106 ALOGV("INFO_FORMAT_CHANGED!!!"); 107 108 CHECK(mFirstBuffer == NULL); 109 mFirstBufferResult = OK; 110 mIsFirstBuffer = false; 111 } else { 112 mIsFirstBuffer = true; 113 } 114 115 sp<MetaData> format = mSource->getFormat(); 116 const char *mime; 117 bool success = format->findCString(kKeyMIMEType, &mime); 118 CHECK(success); 119 CHECK(useOffload() || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)); 120 121 success = format->findInt32(kKeySampleRate, &mSampleRate); 122 CHECK(success); 123 124 int32_t numChannels, channelMask; 125 success = format->findInt32(kKeyChannelCount, &numChannels); 126 CHECK(success); 127 128 if(!format->findInt32(kKeyChannelMask, &channelMask)) { 129 // log only when there's a risk of ambiguity of channel mask selection 130 ALOGI_IF(numChannels > 2, 131 "source format didn't specify channel mask, using (%d) channel order", numChannels); 132 channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER; 133 } 134 135 audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT; 136 137 if (useOffload()) { 138 if (mapMimeToAudioFormat(audioFormat, mime) != OK) { 139 ALOGE("Couldn't map mime type \"%s\" to a valid AudioSystem::audio_format", mime); 140 audioFormat = AUDIO_FORMAT_INVALID; 141 } else { 142 ALOGV("Mime type \"%s\" mapped to audio_format 0x%x", mime, audioFormat); 143 } 144 } 145 146 int avgBitRate = -1; 147 format->findInt32(kKeyBitRate, &avgBitRate); 148 149 if (mAudioSink.get() != NULL) { 150 151 uint32_t flags = AUDIO_OUTPUT_FLAG_NONE; 152 audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER; 153 154 if (allowDeepBuffering()) { 155 flags |= AUDIO_OUTPUT_FLAG_DEEP_BUFFER; 156 } 157 if (useOffload()) { 158 flags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD; 159 160 int64_t durationUs; 161 if (format->findInt64(kKeyDuration, &durationUs)) { 162 offloadInfo.duration_us = durationUs; 163 } else { 164 offloadInfo.duration_us = -1; 165 } 166 167 offloadInfo.sample_rate = mSampleRate; 168 offloadInfo.channel_mask = channelMask; 169 offloadInfo.format = audioFormat; 170 offloadInfo.stream_type = AUDIO_STREAM_MUSIC; 171 offloadInfo.bit_rate = avgBitRate; 172 offloadInfo.has_video = ((mCreateFlags & HAS_VIDEO) != 0); 173 offloadInfo.is_streaming = ((mCreateFlags & IS_STREAMING) != 0); 174 } 175 176 status_t err = mAudioSink->open( 177 mSampleRate, numChannels, channelMask, audioFormat, 178 DEFAULT_AUDIOSINK_BUFFERCOUNT, 179 &AudioPlayer::AudioSinkCallback, 180 this, 181 (audio_output_flags_t)flags, 182 useOffload() ? &offloadInfo : NULL); 183 184 if (err == OK) { 185 mLatencyUs = (int64_t)mAudioSink->latency() * 1000; 186 mFrameSize = mAudioSink->frameSize(); 187 188 if (useOffload()) { 189 // If the playback is offloaded to h/w we pass the 190 // HAL some metadata information 191 // We don't want to do this for PCM because it will be going 192 // through the AudioFlinger mixer before reaching the hardware 193 sendMetaDataToHal(mAudioSink, format); 194 } 195 196 err = mAudioSink->start(); 197 // do not alter behavior for non offloaded tracks: ignore start status. 198 if (!useOffload()) { 199 err = OK; 200 } 201 } 202 203 if (err != OK) { 204 if (mFirstBuffer != NULL) { 205 mFirstBuffer->release(); 206 mFirstBuffer = NULL; 207 } 208 209 if (!sourceAlreadyStarted) { 210 mSource->stop(); 211 } 212 213 return err; 214 } 215 216 } else { 217 // playing to an AudioTrack, set up mask if necessary 218 audio_channel_mask_t audioMask = channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER ? 219 audio_channel_out_mask_from_count(numChannels) : channelMask; 220 if (0 == audioMask) { 221 return BAD_VALUE; 222 } 223 224 mAudioTrack = new AudioTrack( 225 AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT, audioMask, 226 0 /*frameCount*/, AUDIO_OUTPUT_FLAG_NONE, &AudioCallback, this, 227 0 /*notificationFrames*/); 228 229 if ((err = mAudioTrack->initCheck()) != OK) { 230 mAudioTrack.clear(); 231 232 if (mFirstBuffer != NULL) { 233 mFirstBuffer->release(); 234 mFirstBuffer = NULL; 235 } 236 237 if (!sourceAlreadyStarted) { 238 mSource->stop(); 239 } 240 241 return err; 242 } 243 244 mLatencyUs = (int64_t)mAudioTrack->latency() * 1000; 245 mFrameSize = mAudioTrack->frameSize(); 246 247 mAudioTrack->start(); 248 } 249 250 mStarted = true; 251 mPlaying = true; 252 mPinnedTimeUs = -1ll; 253 254 return OK; 255} 256 257void AudioPlayer::pause(bool playPendingSamples) { 258 CHECK(mStarted); 259 260 if (playPendingSamples) { 261 if (mAudioSink.get() != NULL) { 262 mAudioSink->stop(); 263 } else { 264 mAudioTrack->stop(); 265 } 266 267 mNumFramesPlayed = 0; 268 mNumFramesPlayedSysTimeUs = ALooper::GetNowUs(); 269 } else { 270 if (mAudioSink.get() != NULL) { 271 mAudioSink->pause(); 272 } else { 273 mAudioTrack->pause(); 274 } 275 276 mPinnedTimeUs = ALooper::GetNowUs(); 277 } 278 279 mPlaying = false; 280} 281 282status_t AudioPlayer::resume() { 283 CHECK(mStarted); 284 status_t err; 285 286 if (mAudioSink.get() != NULL) { 287 err = mAudioSink->start(); 288 } else { 289 err = mAudioTrack->start(); 290 } 291 292 if (err == OK) { 293 mPlaying = true; 294 } 295 296 return err; 297} 298 299void AudioPlayer::reset() { 300 CHECK(mStarted); 301 302 ALOGV("reset: mPlaying=%d mReachedEOS=%d useOffload=%d", 303 mPlaying, mReachedEOS, useOffload() ); 304 305 if (mAudioSink.get() != NULL) { 306 mAudioSink->stop(); 307 // If we're closing and have reached EOS, we don't want to flush 308 // the track because if it is offloaded there could be a small 309 // amount of residual data in the hardware buffer which we must 310 // play to give gapless playback. 311 // But if we're resetting when paused or before we've reached EOS 312 // we can't be doing a gapless playback and there could be a large 313 // amount of data queued in the hardware if the track is offloaded, 314 // so we must flush to prevent a track switch being delayed playing 315 // the buffered data that we don't want now 316 if (!mPlaying || !mReachedEOS) { 317 mAudioSink->flush(); 318 } 319 320 mAudioSink->close(); 321 } else { 322 mAudioTrack->stop(); 323 324 if (!mPlaying || !mReachedEOS) { 325 mAudioTrack->flush(); 326 } 327 328 mAudioTrack.clear(); 329 } 330 331 // Make sure to release any buffer we hold onto so that the 332 // source is able to stop(). 333 334 if (mFirstBuffer != NULL) { 335 mFirstBuffer->release(); 336 mFirstBuffer = NULL; 337 } 338 339 if (mInputBuffer != NULL) { 340 ALOGV("AudioPlayer releasing input buffer."); 341 342 mInputBuffer->release(); 343 mInputBuffer = NULL; 344 } 345 346 mSource->stop(); 347 348 // The following hack is necessary to ensure that the OMX 349 // component is completely released by the time we may try 350 // to instantiate it again. 351 // When offloading, the OMX component is not used so this hack 352 // is not needed 353 if (!useOffload()) { 354 wp<MediaSource> tmp = mSource; 355 mSource.clear(); 356 while (tmp.promote() != NULL) { 357 usleep(1000); 358 } 359 } else { 360 mSource.clear(); 361 } 362 IPCThreadState::self()->flushCommands(); 363 364 mNumFramesPlayed = 0; 365 mNumFramesPlayedSysTimeUs = ALooper::GetNowUs(); 366 mPositionTimeMediaUs = -1; 367 mPositionTimeRealUs = -1; 368 mSeeking = false; 369 mSeekTimeUs = 0; 370 mReachedEOS = false; 371 mFinalStatus = OK; 372 mStarted = false; 373 mPlaying = false; 374 mStartPosUs = 0; 375} 376 377// static 378void AudioPlayer::AudioCallback(int event, void *user, void *info) { 379 static_cast<AudioPlayer *>(user)->AudioCallback(event, info); 380} 381 382bool AudioPlayer::isSeeking() { 383 Mutex::Autolock autoLock(mLock); 384 return mSeeking; 385} 386 387bool AudioPlayer::reachedEOS(status_t *finalStatus) { 388 *finalStatus = OK; 389 390 Mutex::Autolock autoLock(mLock); 391 *finalStatus = mFinalStatus; 392 return mReachedEOS; 393} 394 395void AudioPlayer::notifyAudioEOS() { 396 ALOGV("AudioPlayer@0x%p notifyAudioEOS", this); 397 398 if (mObserver != NULL) { 399 mObserver->postAudioEOS(0); 400 ALOGV("Notified observer of EOS!"); 401 } 402} 403 404status_t AudioPlayer::setPlaybackRatePermille(int32_t ratePermille) { 405 if (mAudioSink.get() != NULL) { 406 return mAudioSink->setPlaybackRatePermille(ratePermille); 407 } else if (mAudioTrack != 0){ 408 return mAudioTrack->setSampleRate(ratePermille * mSampleRate / 1000); 409 } else { 410 return NO_INIT; 411 } 412} 413 414// static 415size_t AudioPlayer::AudioSinkCallback( 416 MediaPlayerBase::AudioSink * /* audioSink */, 417 void *buffer, size_t size, void *cookie, 418 MediaPlayerBase::AudioSink::cb_event_t event) { 419 AudioPlayer *me = (AudioPlayer *)cookie; 420 421 switch(event) { 422 case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER: 423 return me->fillBuffer(buffer, size); 424 425 case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END: 426 ALOGV("AudioSinkCallback: stream end"); 427 me->mReachedEOS = true; 428 me->notifyAudioEOS(); 429 break; 430 431 case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN: 432 ALOGV("AudioSinkCallback: Tear down event"); 433 me->mObserver->postAudioTearDown(); 434 break; 435 } 436 437 return 0; 438} 439 440void AudioPlayer::AudioCallback(int event, void *info) { 441 switch (event) { 442 case AudioTrack::EVENT_MORE_DATA: 443 { 444 AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info; 445 size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size); 446 buffer->size = numBytesWritten; 447 } 448 break; 449 450 case AudioTrack::EVENT_STREAM_END: 451 mReachedEOS = true; 452 notifyAudioEOS(); 453 break; 454 } 455} 456 457uint32_t AudioPlayer::getNumFramesPendingPlayout() const { 458 uint32_t numFramesPlayedOut; 459 status_t err; 460 461 if (mAudioSink != NULL) { 462 err = mAudioSink->getPosition(&numFramesPlayedOut); 463 } else { 464 err = mAudioTrack->getPosition(&numFramesPlayedOut); 465 } 466 467 if (err != OK || mNumFramesPlayed < numFramesPlayedOut) { 468 return 0; 469 } 470 471 // mNumFramesPlayed is the number of frames submitted 472 // to the audio sink for playback, but not all of them 473 // may have played out by now. 474 return mNumFramesPlayed - numFramesPlayedOut; 475} 476 477size_t AudioPlayer::fillBuffer(void *data, size_t size) { 478 if (mNumFramesPlayed == 0) { 479 ALOGV("AudioCallback"); 480 } 481 482 if (mReachedEOS) { 483 return 0; 484 } 485 486 bool postSeekComplete = false; 487 bool postEOS = false; 488 int64_t postEOSDelayUs = 0; 489 490 size_t size_done = 0; 491 size_t size_remaining = size; 492 while (size_remaining > 0) { 493 MediaSource::ReadOptions options; 494 bool refreshSeekTime = false; 495 496 { 497 Mutex::Autolock autoLock(mLock); 498 499 if (mSeeking) { 500 if (mIsFirstBuffer) { 501 if (mFirstBuffer != NULL) { 502 mFirstBuffer->release(); 503 mFirstBuffer = NULL; 504 } 505 mIsFirstBuffer = false; 506 } 507 508 options.setSeekTo(mSeekTimeUs); 509 refreshSeekTime = true; 510 511 if (mInputBuffer != NULL) { 512 mInputBuffer->release(); 513 mInputBuffer = NULL; 514 } 515 516 mSeeking = false; 517 if (mObserver) { 518 postSeekComplete = true; 519 } 520 } 521 } 522 523 if (mInputBuffer == NULL) { 524 status_t err; 525 526 if (mIsFirstBuffer) { 527 mInputBuffer = mFirstBuffer; 528 mFirstBuffer = NULL; 529 err = mFirstBufferResult; 530 531 mIsFirstBuffer = false; 532 } else { 533 err = mSource->read(&mInputBuffer, &options); 534 } 535 536 CHECK((err == OK && mInputBuffer != NULL) 537 || (err != OK && mInputBuffer == NULL)); 538 539 Mutex::Autolock autoLock(mLock); 540 541 if (err != OK) { 542 if (!mReachedEOS) { 543 if (useOffload()) { 544 // no more buffers to push - stop() and wait for STREAM_END 545 // don't set mReachedEOS until stream end received 546 if (mAudioSink != NULL) { 547 mAudioSink->stop(); 548 } else { 549 mAudioTrack->stop(); 550 } 551 } else { 552 if (mObserver) { 553 // We don't want to post EOS right away but only 554 // after all frames have actually been played out. 555 556 // These are the number of frames submitted to the 557 // AudioTrack that you haven't heard yet. 558 uint32_t numFramesPendingPlayout = 559 getNumFramesPendingPlayout(); 560 561 // These are the number of frames we're going to 562 // submit to the AudioTrack by returning from this 563 // callback. 564 uint32_t numAdditionalFrames = size_done / mFrameSize; 565 566 numFramesPendingPlayout += numAdditionalFrames; 567 568 int64_t timeToCompletionUs = 569 (1000000ll * numFramesPendingPlayout) / mSampleRate; 570 571 ALOGV("total number of frames played: %" PRId64 " (%lld us)", 572 (mNumFramesPlayed + numAdditionalFrames), 573 1000000ll * (mNumFramesPlayed + numAdditionalFrames) 574 / mSampleRate); 575 576 ALOGV("%d frames left to play, %" PRId64 " us (%.2f secs)", 577 numFramesPendingPlayout, 578 timeToCompletionUs, timeToCompletionUs / 1E6); 579 580 postEOS = true; 581 if (mAudioSink->needsTrailingPadding()) { 582 postEOSDelayUs = timeToCompletionUs + mLatencyUs; 583 } else { 584 postEOSDelayUs = 0; 585 } 586 } 587 588 mReachedEOS = true; 589 } 590 } 591 592 mFinalStatus = err; 593 break; 594 } 595 596 if (mAudioSink != NULL) { 597 mLatencyUs = (int64_t)mAudioSink->latency() * 1000; 598 } else { 599 mLatencyUs = (int64_t)mAudioTrack->latency() * 1000; 600 } 601 602 if(mInputBuffer->range_length() != 0) { 603 CHECK(mInputBuffer->meta_data()->findInt64( 604 kKeyTime, &mPositionTimeMediaUs)); 605 } 606 607 // need to adjust the mStartPosUs for offload decoding since parser 608 // might not be able to get the exact seek time requested. 609 if (refreshSeekTime) { 610 if (useOffload()) { 611 if (postSeekComplete) { 612 ALOGV("fillBuffer is going to post SEEK_COMPLETE"); 613 mObserver->postAudioSeekComplete(); 614 postSeekComplete = false; 615 } 616 617 mStartPosUs = mPositionTimeMediaUs; 618 ALOGV("adjust seek time to: %.2f", mStartPosUs/ 1E6); 619 } 620 // clear seek time with mLock locked and once we have valid mPositionTimeMediaUs 621 // and mPositionTimeRealUs 622 // before clearing mSeekTimeUs check if a new seek request has been received while 623 // we were reading from the source with mLock released. 624 if (!mSeeking) { 625 mSeekTimeUs = 0; 626 } 627 } 628 629 if (!useOffload()) { 630 mPositionTimeRealUs = 631 ((mNumFramesPlayed + size_done / mFrameSize) * 1000000) 632 / mSampleRate; 633 ALOGV("buffer->size() = %zu, " 634 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f", 635 mInputBuffer->range_length(), 636 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6); 637 } 638 639 } 640 641 if (mInputBuffer->range_length() == 0) { 642 mInputBuffer->release(); 643 mInputBuffer = NULL; 644 645 continue; 646 } 647 648 size_t copy = size_remaining; 649 if (copy > mInputBuffer->range_length()) { 650 copy = mInputBuffer->range_length(); 651 } 652 653 memcpy((char *)data + size_done, 654 (const char *)mInputBuffer->data() + mInputBuffer->range_offset(), 655 copy); 656 657 mInputBuffer->set_range(mInputBuffer->range_offset() + copy, 658 mInputBuffer->range_length() - copy); 659 660 size_done += copy; 661 size_remaining -= copy; 662 } 663 664 if (useOffload()) { 665 // We must ask the hardware what it has played 666 mPositionTimeRealUs = getOutputPlayPositionUs_l(); 667 ALOGV("mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f", 668 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6); 669 } 670 671 { 672 Mutex::Autolock autoLock(mLock); 673 mNumFramesPlayed += size_done / mFrameSize; 674 mNumFramesPlayedSysTimeUs = ALooper::GetNowUs(); 675 676 if (mReachedEOS) { 677 mPinnedTimeUs = mNumFramesPlayedSysTimeUs; 678 } else { 679 mPinnedTimeUs = -1ll; 680 } 681 } 682 683 if (postEOS) { 684 mObserver->postAudioEOS(postEOSDelayUs); 685 } 686 687 if (postSeekComplete) { 688 mObserver->postAudioSeekComplete(); 689 } 690 691 return size_done; 692} 693 694int64_t AudioPlayer::getRealTimeUs() { 695 Mutex::Autolock autoLock(mLock); 696 if (useOffload()) { 697 if (mSeeking) { 698 return mSeekTimeUs; 699 } 700 mPositionTimeRealUs = getOutputPlayPositionUs_l(); 701 return mPositionTimeRealUs; 702 } 703 704 return getRealTimeUsLocked(); 705} 706 707int64_t AudioPlayer::getRealTimeUsLocked() const { 708 CHECK(mStarted); 709 CHECK_NE(mSampleRate, 0); 710 int64_t result = -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate; 711 712 // Compensate for large audio buffers, updates of mNumFramesPlayed 713 // are less frequent, therefore to get a "smoother" notion of time we 714 // compensate using system time. 715 int64_t diffUs; 716 if (mPinnedTimeUs >= 0ll) { 717 diffUs = mPinnedTimeUs; 718 } else { 719 diffUs = ALooper::GetNowUs(); 720 } 721 722 diffUs -= mNumFramesPlayedSysTimeUs; 723 724 return result + diffUs; 725} 726 727int64_t AudioPlayer::getOutputPlayPositionUs_l() 728{ 729 uint32_t playedSamples = 0; 730 uint32_t sampleRate; 731 if (mAudioSink != NULL) { 732 mAudioSink->getPosition(&playedSamples); 733 sampleRate = mAudioSink->getSampleRate(); 734 } else { 735 mAudioTrack->getPosition(&playedSamples); 736 sampleRate = mAudioTrack->getSampleRate(); 737 } 738 if (sampleRate != 0) { 739 mSampleRate = sampleRate; 740 } 741 742 int64_t playedUs; 743 if (mSampleRate != 0) { 744 playedUs = (static_cast<int64_t>(playedSamples) * 1000000 ) / mSampleRate; 745 } else { 746 playedUs = 0; 747 } 748 749 // HAL position is relative to the first buffer we sent at mStartPosUs 750 const int64_t renderedDuration = mStartPosUs + playedUs; 751 ALOGV("getOutputPlayPositionUs_l %" PRId64, renderedDuration); 752 return renderedDuration; 753} 754 755int64_t AudioPlayer::getMediaTimeUs() { 756 Mutex::Autolock autoLock(mLock); 757 758 if (useOffload()) { 759 if (mSeeking) { 760 return mSeekTimeUs; 761 } 762 mPositionTimeRealUs = getOutputPlayPositionUs_l(); 763 ALOGV("getMediaTimeUs getOutputPlayPositionUs_l() mPositionTimeRealUs %" PRId64, 764 mPositionTimeRealUs); 765 return mPositionTimeRealUs; 766 } 767 768 769 if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) { 770 // mSeekTimeUs is either seek time while seeking or 0 if playback did not start. 771 return mSeekTimeUs; 772 } 773 774 int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs; 775 if (realTimeOffset < 0) { 776 realTimeOffset = 0; 777 } 778 779 return mPositionTimeMediaUs + realTimeOffset; 780} 781 782bool AudioPlayer::getMediaTimeMapping( 783 int64_t *realtime_us, int64_t *mediatime_us) { 784 Mutex::Autolock autoLock(mLock); 785 786 if (useOffload()) { 787 mPositionTimeRealUs = getOutputPlayPositionUs_l(); 788 *realtime_us = mPositionTimeRealUs; 789 *mediatime_us = mPositionTimeRealUs; 790 } else { 791 *realtime_us = mPositionTimeRealUs; 792 *mediatime_us = mPositionTimeMediaUs; 793 } 794 795 return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1; 796} 797 798status_t AudioPlayer::seekTo(int64_t time_us) { 799 Mutex::Autolock autoLock(mLock); 800 801 ALOGV("seekTo( %" PRId64 " )", time_us); 802 803 mSeeking = true; 804 mPositionTimeRealUs = mPositionTimeMediaUs = -1; 805 mReachedEOS = false; 806 mSeekTimeUs = time_us; 807 mStartPosUs = time_us; 808 809 // Flush resets the number of played frames 810 mNumFramesPlayed = 0; 811 mNumFramesPlayedSysTimeUs = ALooper::GetNowUs(); 812 813 if (mAudioSink != NULL) { 814 if (mPlaying) { 815 mAudioSink->pause(); 816 } 817 mAudioSink->flush(); 818 if (mPlaying) { 819 mAudioSink->start(); 820 } 821 } else { 822 if (mPlaying) { 823 mAudioTrack->pause(); 824 } 825 mAudioTrack->flush(); 826 if (mPlaying) { 827 mAudioTrack->start(); 828 } 829 } 830 831 return OK; 832} 833 834} 835