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