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