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