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