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