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