xref: /aosp_15_r20/frameworks/wilhelm/src/android/android_GenericPlayer.cpp (revision bebae9c0e76121f8312ccb50385c080b3a0b023c)
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