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