android_GenericPlayer.cpp revision 85edd878a30caa535b0267d8d6e61b4ccc0d5fd0
1/* 2 * Copyright (C) 2011 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 USE_LOG SLAndroidLogLevel_Verbose 18 19#include "sles_allinclusive.h" 20 21#include <media/stagefright/foundation/ADebug.h> 22#include <sys/stat.h> 23 24namespace android { 25 26//-------------------------------------------------------------------------------------------------- 27GenericPlayer::GenericPlayer(const AudioPlayback_Parameters* params) : 28 mDataLocatorType(kDataLocatorNone), 29 mNotifyClient(NULL), 30 mNotifyUser(NULL), 31 mStateFlags(0), 32 mLooperPriority(PRIORITY_DEFAULT), 33 mPlaybackParams(*params), 34 mChannelCount(UNKNOWN_NUMCHANNELS), 35 mDurationMsec(ANDROID_UNKNOWN_TIME), 36 mSampleRateHz(UNKNOWN_SAMPLERATE), 37 mCacheStatus(kStatusEmpty), 38 mCacheFill(0), 39 mLastNotifiedCacheFill(0), 40 mCacheFillNotifThreshold(100), 41 mEventFlags(0), 42 mMarkerPositionMs(ANDROID_UNKNOWN_TIME), 43 mPositionUpdatePeriodMs(1000), // per spec 44 mOneShotGeneration(0), 45 mDeliveredNewPosMs(ANDROID_UNKNOWN_TIME), 46 mObservedPositionMs(ANDROID_UNKNOWN_TIME) 47{ 48 SL_LOGD("GenericPlayer::GenericPlayer()"); 49 50 mLooper = new android::ALooper(); 51 52 mAndroidAudioLevels.mFinalVolume[0] = 1.0f; 53 mAndroidAudioLevels.mFinalVolume[1] = 1.0f; 54} 55 56 57GenericPlayer::~GenericPlayer() { 58 SL_LOGV("GenericPlayer::~GenericPlayer()"); 59 60} 61 62 63void GenericPlayer::init(const notif_cbf_t cbf, void* notifUser) { 64 SL_LOGD("GenericPlayer::init()"); 65 66 { 67 android::Mutex::Autolock autoLock(mNotifyClientLock); 68 mNotifyClient = cbf; 69 mNotifyUser = notifUser; 70 } 71 72 mLooper->registerHandler(this); 73 mLooper->start(false /*runOnCallingThread*/, false /*canCallJava*/, mLooperPriority); 74} 75 76 77void GenericPlayer::preDestroy() { 78 SL_LOGD("GenericPlayer::preDestroy()"); 79 { 80 android::Mutex::Autolock autoLock(mNotifyClientLock); 81 mNotifyClient = NULL; 82 mNotifyUser = NULL; 83 } 84 85 mLooper->stop(); 86 mLooper->unregisterHandler(id()); 87} 88 89 90void GenericPlayer::setDataSource(const char *uri) { 91 SL_LOGV("GenericPlayer::setDataSource(uri=%s)", uri); 92 resetDataLocator(); 93 94 mDataLocator.uriRef = uri; 95 96 mDataLocatorType = kDataLocatorUri; 97} 98 99 100void GenericPlayer::setDataSource(int fd, int64_t offset, int64_t length) { 101 SL_LOGV("GenericPlayer::setDataSource(fd=%d, offset=%lld, length=%lld)", fd, offset, length); 102 resetDataLocator(); 103 104 mDataLocator.fdi.fd = fd; 105 106 struct stat sb; 107 int ret = fstat(fd, &sb); 108 if (ret != 0) { 109 SL_LOGE("GenericPlayer::setDataSource: fstat(%d) failed: %d, %s", fd, ret, strerror(errno)); 110 return; 111 } 112 113 if (offset >= sb.st_size) { 114 SL_LOGE("SfPlayer::setDataSource: invalid offset"); 115 return; 116 } 117 mDataLocator.fdi.offset = offset; 118 119 if (PLAYER_FD_FIND_FILE_SIZE == length) { 120 mDataLocator.fdi.length = sb.st_size; 121 } else if (offset + length > sb.st_size) { 122 mDataLocator.fdi.length = sb.st_size - offset; 123 } else { 124 mDataLocator.fdi.length = length; 125 } 126 127 mDataLocatorType = kDataLocatorFd; 128} 129 130 131void GenericPlayer::prepare() { 132 SL_LOGD("GenericPlayer::prepare()"); 133 // do not attempt prepare more than once 134 if (!(mStateFlags & (kFlagPrepared | kFlagPreparedUnsuccessfully))) { 135 sp<AMessage> msg = new AMessage(kWhatPrepare, id()); 136 msg->post(); 137 } 138} 139 140 141void GenericPlayer::play() { 142 SL_LOGD("GenericPlayer::play()"); 143 sp<AMessage> msg = new AMessage(kWhatPlay, id()); 144 msg->post(); 145} 146 147 148void GenericPlayer::pause() { 149 SL_LOGD("GenericPlayer::pause()"); 150 sp<AMessage> msg = new AMessage(kWhatPause, id()); 151 msg->post(); 152} 153 154 155void GenericPlayer::stop() { 156 SL_LOGD("GenericPlayer::stop()"); 157 (new AMessage(kWhatPause, id()))->post(); 158 159 // after a stop, playback should resume from the start. 160 seek(0); 161} 162 163 164void GenericPlayer::seek(int64_t timeMsec) { 165 SL_LOGV("GenericPlayer::seek %lld", timeMsec); 166 if (timeMsec < 0) { 167 SL_LOGE("GenericPlayer::seek error, can't seek to negative time %lldms", timeMsec); 168 return; 169 } 170 sp<AMessage> msg = new AMessage(kWhatSeek, id()); 171 msg->setInt64(WHATPARAM_SEEK_SEEKTIME_MS, timeMsec); 172 msg->post(); 173} 174 175 176void GenericPlayer::loop(bool loop) { 177 SL_LOGV("GenericPlayer::loop %s", loop ? "true" : "false"); 178 sp<AMessage> msg = new AMessage(kWhatLoop, id()); 179 msg->setInt32(WHATPARAM_LOOP_LOOPING, (int32_t)loop); 180 msg->post(); 181} 182 183 184void GenericPlayer::setBufferingUpdateThreshold(int16_t thresholdPercent) { 185 SL_LOGV("GenericPlayer::setBufferingUpdateThreshold %d", thresholdPercent); 186 sp<AMessage> msg = new AMessage(kWhatBuffUpdateThres, id()); 187 msg->setInt32(WHATPARAM_BUFFERING_UPDATETHRESHOLD_PERCENT, (int32_t)thresholdPercent); 188 msg->post(); 189} 190 191 192//-------------------------------------------------- 193void GenericPlayer::getDurationMsec(int* msec) { 194 *msec = mDurationMsec; 195} 196 197void GenericPlayer::getSampleRate(uint* hz) { 198 *hz = mSampleRateHz; 199} 200 201//-------------------------------------------------- 202void GenericPlayer::setVolume(float leftVol, float rightVol) 203{ 204 { 205 Mutex::Autolock _l(mSettingsLock); 206 mAndroidAudioLevels.mFinalVolume[0] = leftVol; 207 mAndroidAudioLevels.mFinalVolume[1] = rightVol; 208 } 209 // send a message for the volume to be updated by the object which implements the volume 210 (new AMessage(kWhatVolumeUpdate, id()))->post(); 211} 212 213 214//-------------------------------------------------- 215void GenericPlayer::attachAuxEffect(int32_t effectId) 216{ 217 SL_LOGV("GenericPlayer::attachAuxEffect(id=%d)", effectId); 218 sp<AMessage> msg = new AMessage(kWhatAttachAuxEffect, id()); 219 msg->setInt32(WHATPARAM_ATTACHAUXEFFECT, effectId); 220 msg->post(); 221} 222 223 224//-------------------------------------------------- 225void GenericPlayer::setAuxEffectSendLevel(float level) 226{ 227 SL_LOGV("GenericPlayer::setAuxEffectSendLevel(level=%g)", level); 228 sp<AMessage> msg = new AMessage(kWhatSetAuxEffectSendLevel, id()); 229 msg->setFloat(WHATPARAM_SETAUXEFFECTSENDLEVEL, level); 230 msg->post(); 231} 232 233 234//-------------------------------------------------- 235// Call after changing any of the IPlay settings related to SL_PLAYEVENT_* 236void GenericPlayer::setPlayEvents(int32_t eventFlags, int32_t markerPositionMs, 237 int32_t positionUpdatePeriodMs) 238{ 239 // Normalize ms that are within the valid unsigned range, but not in the int32_t range 240 if (markerPositionMs < 0) { 241 markerPositionMs = ANDROID_UNKNOWN_TIME; 242 } 243 if (positionUpdatePeriodMs < 0) { 244 positionUpdatePeriodMs = ANDROID_UNKNOWN_TIME; 245 } 246 // markers are delivered accurately, but new position updates are limited to every 100 ms 247 if (positionUpdatePeriodMs < 100) { 248 positionUpdatePeriodMs = 100; 249 } 250 sp<AMessage> msg = new AMessage(kWhatSetPlayEvents, id()); 251 msg->setInt32(WHATPARAM_SETPLAYEVENTS_FLAGS, eventFlags); 252 msg->setInt32(WHATPARAM_SETPLAYEVENTS_MARKER, markerPositionMs); 253 msg->setInt32(WHATPARAM_SETPLAYEVENTS_UPDATE, positionUpdatePeriodMs); 254 msg->post(); 255} 256 257 258//-------------------------------------------------- 259/* 260 * post-condition: mDataLocatorType == kDataLocatorNone 261 * 262 */ 263void GenericPlayer::resetDataLocator() { 264 SL_LOGV("GenericPlayer::resetDataLocator()"); 265 mDataLocatorType = kDataLocatorNone; 266} 267 268 269void GenericPlayer::notify(const char* event, int data, bool async) { 270 SL_LOGV("GenericPlayer::notify(event=%s, data=%d, async=%s)", event, data, 271 async ? "true" : "false"); 272 sp<AMessage> msg = new AMessage(kWhatNotif, id()); 273 msg->setInt32(event, (int32_t)data); 274 if (async) { 275 msg->post(); 276 } else { 277 this->onNotify(msg); 278 } 279} 280 281 282void GenericPlayer::notify(const char* event, int data1, int data2, bool async) { 283 SL_LOGV("GenericPlayer::notify(event=%s, data1=%d, data2=%d, async=%s)", event, data1, data2, 284 async ? "true" : "false"); 285 sp<AMessage> msg = new AMessage(kWhatNotif, id()); 286 msg->setRect(event, 0, 0, (int32_t)data1, (int32_t)data2); 287 if (async) { 288 msg->post(); 289 } else { 290 this->onNotify(msg); 291 } 292} 293 294 295//-------------------------------------------------- 296// AHandler implementation 297void GenericPlayer::onMessageReceived(const sp<AMessage> &msg) { 298 SL_LOGV("GenericPlayer::onMessageReceived()"); 299 switch (msg->what()) { 300 case kWhatPrepare: 301 SL_LOGV("kWhatPrepare"); 302 onPrepare(); 303 break; 304 305 case kWhatNotif: 306 SL_LOGV("kWhatNotif"); 307 onNotify(msg); 308 break; 309 310 case kWhatPlay: 311 SL_LOGV("kWhatPlay"); 312 onPlay(); 313 break; 314 315 case kWhatPause: 316 SL_LOGV("kWhatPause"); 317 onPause(); 318 break; 319 320 case kWhatSeek: 321 SL_LOGV("kWhatSeek"); 322 onSeek(msg); 323 break; 324 325 case kWhatLoop: 326 SL_LOGV("kWhatLoop"); 327 onLoop(msg); 328 break; 329 330 case kWhatVolumeUpdate: 331 SL_LOGV("kWhatVolumeUpdate"); 332 onVolumeUpdate(); 333 break; 334 335 case kWhatSeekComplete: 336 SL_LOGV("kWhatSeekComplete"); 337 onSeekComplete(); 338 break; 339 340 case kWhatBufferingUpdate: 341 SL_LOGV("kWhatBufferingUpdate"); 342 onBufferingUpdate(msg); 343 break; 344 345 case kWhatBuffUpdateThres: 346 SL_LOGV("kWhatBuffUpdateThres"); 347 onSetBufferingUpdateThreshold(msg); 348 break; 349 350 case kWhatAttachAuxEffect: 351 SL_LOGV("kWhatAttachAuxEffect"); 352 onAttachAuxEffect(msg); 353 break; 354 355 case kWhatSetAuxEffectSendLevel: 356 SL_LOGV("kWhatSetAuxEffectSendLevel"); 357 onSetAuxEffectSendLevel(msg); 358 break; 359 360 case kWhatSetPlayEvents: 361 SL_LOGV("kWhatSetPlayEvents"); 362 onSetPlayEvents(msg); 363 break; 364 365 case kWhatOneShot: 366 SL_LOGV("kWhatOneShot"); 367 onOneShot(msg); 368 break; 369 370 default: 371 SL_LOGE("GenericPlayer::onMessageReceived unknown message %d", msg->what()); 372 TRESPASS(); 373 } 374} 375 376 377//-------------------------------------------------- 378// Event handlers 379// it is strictly verboten to call those methods outside of the event loop 380 381void GenericPlayer::onPrepare() { 382 SL_LOGV("GenericPlayer::onPrepare()"); 383 // Subclass is responsible for indicating whether prepare was successful or unsuccessful 384 // by updating mStateFlags accordingly. It must set exactly one of these two flags. 385 assert(!(mStateFlags & kFlagPrepared) != !(mStateFlags & kFlagPreparedUnsuccessfully)); 386 notify(PLAYEREVENT_PREPARED, mStateFlags & kFlagPrepared ? PLAYER_SUCCESS : PLAYER_FAILURE, 387 false /*async*/); 388 SL_LOGD("GenericPlayer::onPrepare() done, mStateFlags=0x%x", mStateFlags); 389} 390 391 392void GenericPlayer::onNotify(const sp<AMessage> &msg) { 393 SL_LOGV("GenericPlayer::onNotify()"); 394 notif_cbf_t notifClient; 395 void* notifUser; 396 { 397 android::Mutex::Autolock autoLock(mNotifyClientLock); 398 if (NULL == mNotifyClient) { 399 return; 400 } else { 401 notifClient = mNotifyClient; 402 notifUser = mNotifyUser; 403 } 404 } 405 406 int32_t val1, val2; 407 if (msg->findInt32(PLAYEREVENT_PREFETCHSTATUSCHANGE, &val1)) { 408 SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_PREFETCHSTATUSCHANGE, val1); 409 notifClient(kEventPrefetchStatusChange, val1, 0, notifUser); 410 } else if (msg->findInt32(PLAYEREVENT_PREFETCHFILLLEVELUPDATE, &val1)) { 411 SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_PREFETCHFILLLEVELUPDATE, val1); 412 notifClient(kEventPrefetchFillLevelUpdate, val1, 0, notifUser); 413 } else if (msg->findInt32(PLAYEREVENT_ENDOFSTREAM, &val1)) { 414 SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_ENDOFSTREAM, val1); 415 notifClient(kEventEndOfStream, val1, 0, notifUser); 416 } else if (msg->findInt32(PLAYEREVENT_PREPARED, &val1)) { 417 SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_PREPARED, val1); 418 notifClient(kEventPrepared, val1, 0, notifUser); 419 } else if (msg->findInt32(PLAYEREVENT_CHANNEL_COUNT, &val1)) { 420 SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_CHANNEL_COUNT, val1); 421 notifClient(kEventChannelCount, val1, 0, notifUser); 422 } else if (msg->findRect(PLAYEREVENT_VIDEO_SIZE_UPDATE, &val1, &val2, &val1, &val2)) { 423 SL_LOGV("GenericPlayer notifying %s = %d, %d", PLAYEREVENT_VIDEO_SIZE_UPDATE, val1, val2); 424 notifClient(kEventHasVideoSize, val1, val2, notifUser); 425 } else if (msg->findInt32(PLAYEREVENT_PLAY, &val1)) { 426 SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_PLAY, val1); 427 notifClient(kEventPlay, val1, 0, notifUser); 428 } else { 429 SL_LOGV("GenericPlayer notifying unknown"); 430 } 431} 432 433 434void GenericPlayer::onPlay() { 435 SL_LOGD("GenericPlayer::onPlay()"); 436 if ((mStateFlags & (kFlagPrepared | kFlagPlaying)) == kFlagPrepared) { 437 SL_LOGD("starting player"); 438 mStateFlags |= kFlagPlaying; 439 updateOneShot(); 440 } 441} 442 443 444void GenericPlayer::onPause() { 445 SL_LOGD("GenericPlayer::onPause()"); 446 if (!(~mStateFlags & (kFlagPrepared | kFlagPlaying))) { 447 SL_LOGV("pausing player"); 448 mStateFlags &= ~kFlagPlaying; 449 updateOneShot(); 450 } 451} 452 453 454void GenericPlayer::onSeek(const sp<AMessage> &msg) { 455 SL_LOGV("GenericPlayer::onSeek"); 456} 457 458 459void GenericPlayer::onLoop(const sp<AMessage> &msg) { 460 SL_LOGV("GenericPlayer::onLoop"); 461} 462 463 464void GenericPlayer::onVolumeUpdate() { 465 SL_LOGV("GenericPlayer::onVolumeUpdate"); 466} 467 468 469void GenericPlayer::onSeekComplete() { 470 SL_LOGD("GenericPlayer::onSeekComplete()"); 471 mStateFlags &= ~kFlagSeeking; 472 // avoid spurious or lost events caused by seeking past a marker 473 mDeliveredNewPosMs = ANDROID_UNKNOWN_TIME; 474 mObservedPositionMs = ANDROID_UNKNOWN_TIME; 475 updateOneShot(); 476} 477 478 479void GenericPlayer::onBufferingUpdate(const sp<AMessage> &msg) { 480 SL_LOGV("GenericPlayer::onBufferingUpdate"); 481} 482 483 484void GenericPlayer::onSetBufferingUpdateThreshold(const sp<AMessage> &msg) { 485 SL_LOGV("GenericPlayer::onSetBufferingUpdateThreshold"); 486 int32_t thresholdPercent = 0; 487 if (msg->findInt32(WHATPARAM_BUFFERING_UPDATETHRESHOLD_PERCENT, &thresholdPercent)) { 488 Mutex::Autolock _l(mSettingsLock); 489 mCacheFillNotifThreshold = (int16_t)thresholdPercent; 490 } 491} 492 493 494void GenericPlayer::onAttachAuxEffect(const sp<AMessage> &msg) { 495 SL_LOGV("GenericPlayer::onAttachAuxEffect()"); 496} 497 498 499void GenericPlayer::onSetAuxEffectSendLevel(const sp<AMessage> &msg) { 500 SL_LOGV("GenericPlayer::onSetAuxEffectSendLevel()"); 501} 502 503 504void GenericPlayer::onSetPlayEvents(const sp<AMessage> &msg) { 505 SL_LOGV("GenericPlayer::onSetPlayEvents()"); 506 int32_t eventFlags, markerPositionMs, positionUpdatePeriodMs; 507 if (msg->findInt32(WHATPARAM_SETPLAYEVENTS_FLAGS, &eventFlags) && 508 msg->findInt32(WHATPARAM_SETPLAYEVENTS_MARKER, &markerPositionMs) && 509 msg->findInt32(WHATPARAM_SETPLAYEVENTS_UPDATE, &positionUpdatePeriodMs)) { 510 mEventFlags = eventFlags; 511 mMarkerPositionMs = markerPositionMs; 512 mPositionUpdatePeriodMs = positionUpdatePeriodMs; 513 updateOneShot(); 514 } 515} 516 517 518void GenericPlayer::onOneShot(const sp<AMessage> &msg) { 519 SL_LOGV("GenericPlayer::onOneShot()"); 520 int32_t generation; 521 if (msg->findInt32(WHATPARAM_ONESHOT_GENERATION, &generation)) { 522 if (generation != mOneShotGeneration) { 523 SL_LOGV("GenericPlayer::onOneShot() generation %d cancelled; latest is %d", 524 generation, mOneShotGeneration); 525 return; 526 } 527 updateOneShot(); 528 } 529} 530 531 532//------------------------------------------------- 533void GenericPlayer::notifyStatus() { 534 SL_LOGV("GenericPlayer::notifyStatus"); 535 notify(PLAYEREVENT_PREFETCHSTATUSCHANGE, (int32_t)mCacheStatus, true /*async*/); 536} 537 538 539void GenericPlayer::notifyCacheFill() { 540 SL_LOGV("GenericPlayer::notifyCacheFill"); 541 mLastNotifiedCacheFill = mCacheFill; 542 notify(PLAYEREVENT_PREFETCHFILLLEVELUPDATE, (int32_t)mLastNotifiedCacheFill, true/*async*/); 543} 544 545 546void GenericPlayer::seekComplete() { 547 SL_LOGV("GenericPlayer::seekComplete"); 548 sp<AMessage> msg = new AMessage(kWhatSeekComplete, id()); 549 msg->post(); 550} 551 552 553void GenericPlayer::bufferingUpdate(int16_t fillLevelPerMille) { 554 SL_LOGV("GenericPlayer::bufferingUpdate"); 555 sp<AMessage> msg = new AMessage(kWhatBufferingUpdate, id()); 556 msg->setInt32(WHATPARAM_BUFFERING_UPDATE, fillLevelPerMille); 557 msg->post(); 558} 559 560 561// For the meaning of positionMs, see comment in declaration at android_GenericPlayer.h 562void GenericPlayer::updateOneShot(int positionMs) 563{ 564 SL_LOGV("GenericPlayer::updateOneShot"); 565 566 // nop until prepared 567 if (!(mStateFlags & kFlagPrepared)) { 568 return; 569 } 570 571 // cancel any pending one-shot(s) 572 ++mOneShotGeneration; 573 574 // don't restart one-shot if player is paused or stopped 575 if (!(mStateFlags & kFlagPlaying)) { 576 return; 577 } 578 579 // get current player position in milliseconds 580 if (positionMs < 0) { 581 positionMs = ANDROID_UNKNOWN_TIME; 582 } 583 if (positionMs == ANDROID_UNKNOWN_TIME) { 584 getPositionMsec(&positionMs); 585 // normalize it 586 if (positionMs < 0) { 587 positionMs = ANDROID_UNKNOWN_TIME; 588 } 589 if (ANDROID_UNKNOWN_TIME == positionMs) { 590 // we can't proceed if we don't know where we are now 591 return; 592 } 593 } 594 595 // default one-shot delay is infinity 596 int64_t delayUs = -1; 597 // is there a marker? 598 if ((mEventFlags & SL_PLAYEVENT_HEADATMARKER) && (mMarkerPositionMs != ANDROID_UNKNOWN_TIME)) { 599 // check to see if we have observed the position passing through the marker 600 if (mObservedPositionMs <= mMarkerPositionMs && mMarkerPositionMs <= positionMs) { 601 notify(PLAYEREVENT_PLAY, (int32_t) SL_PLAYEVENT_HEADATMARKER, true /*async*/); 602 } else if (positionMs < mMarkerPositionMs) { 603 delayUs = (mMarkerPositionMs - positionMs) * 1000LL; 604 } 605 } 606 // are periodic position updates needed? 607 if ((mEventFlags & SL_PLAYEVENT_HEADATNEWPOS) && 608 (mPositionUpdatePeriodMs != ANDROID_UNKNOWN_TIME)) { 609 // check to see if we have observed the position passing through a virtual marker, where the 610 // virtual marker is at the previously delivered new position plus position update period 611 int32_t virtualMarkerMs; 612 if (mDeliveredNewPosMs != ANDROID_UNKNOWN_TIME) { 613 virtualMarkerMs = mDeliveredNewPosMs + mPositionUpdatePeriodMs; 614 } else if (mObservedPositionMs != ANDROID_UNKNOWN_TIME) { 615 virtualMarkerMs = mObservedPositionMs + mPositionUpdatePeriodMs; 616 } else { 617 virtualMarkerMs = positionMs + mPositionUpdatePeriodMs; 618 } 619 if (mObservedPositionMs <= virtualMarkerMs && virtualMarkerMs <= positionMs) { 620 mDeliveredNewPosMs = virtualMarkerMs; 621 virtualMarkerMs += mPositionUpdatePeriodMs; 622 // re-synchronize if we missed an update 623 if (virtualMarkerMs <= positionMs) { 624 virtualMarkerMs = positionMs + mPositionUpdatePeriodMs; 625 } 626 notify(PLAYEREVENT_PLAY, (int32_t) SL_PLAYEVENT_HEADATNEWPOS, true /*async*/); 627 } 628 // note that if arithmetic overflow occurred, virtualMarkerMs will be negative 629 if (positionMs < virtualMarkerMs) { 630 int64_t trialDelayUs; 631 trialDelayUs = (virtualMarkerMs - positionMs) * 1000LL; 632 if (trialDelayUs > 0 && (delayUs == -1 || trialDelayUs < delayUs)) { 633 delayUs = trialDelayUs; 634 } 635 } 636 } 637 638 // we have a new observed position 639 mObservedPositionMs = positionMs; 640 641 // post the new one-shot message if needed 642 if (delayUs >= 0) { 643 // 20 ms min delay to avoid near busy waiting 644 if (delayUs < 20000LL) { 645 delayUs = 20000LL; 646 } 647 // 1 minute max delay avoids indefinite memory leaks caused by cancelled one-shots 648 if (delayUs > 60000000LL) { 649 delayUs = 60000000LL; 650 } 651 //SL_LOGI("delayUs = %lld", delayUs); 652 sp<AMessage> msg = new AMessage(kWhatOneShot, id()); 653 msg->setInt32(WHATPARAM_ONESHOT_GENERATION, mOneShotGeneration); 654 msg->post(delayUs); 655 } 656 657} 658 659} // namespace android 660