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