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