android_GenericPlayer.cpp revision 7349b2e742b2cedc6d149fac62ed661ad7d47dec
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 (advancesPositionInRealTime() && 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
687} // namespace android
688