android_GenericPlayer.cpp revision e6ded5c61944a87fa9e472dec3a6929855d42aeb
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define USE_LOG SLAndroidLogLevel_Verbose 18 19#include "sles_allinclusive.h" 20 21#include <media/stagefright/foundation/ADebug.h> 22#include <sys/stat.h> 23 24namespace android { 25 26//-------------------------------------------------------------------------------------------------- 27GenericPlayer::GenericPlayer(const AudioPlayback_Parameters* params) : 28 mDataLocatorType(kDataLocatorNone), 29 mNotifyClient(NULL), 30 mNotifyUser(NULL), 31 mStateFlags(0), 32 mLooperPriority(PRIORITY_DEFAULT), 33 mPlaybackParams(*params), 34 mChannelCount(ANDROID_UNKNOWN_NUMCHANNELS), 35 mDurationMsec(ANDROID_UNKNOWN_TIME), 36 mPositionMsec(ANDROID_UNKNOWN_TIME), 37 mSampleRateHz(ANDROID_UNKNOWN_SAMPLERATE), 38 mCacheStatus(kStatusEmpty), 39 mCacheFill(0), 40 mLastNotifiedCacheFill(0), 41 mCacheFillNotifThreshold(100) 42{ 43 SL_LOGD("GenericPlayer::GenericPlayer()"); 44 45 mLooper = new android::ALooper(); 46 47 mAndroidAudioLevels.mMute = false; 48 mAndroidAudioLevels.mFinalVolume[0] = 1.0f; 49 mAndroidAudioLevels.mFinalVolume[1] = 1.0f; 50} 51 52 53GenericPlayer::~GenericPlayer() { 54 SL_LOGV("GenericPlayer::~GenericPlayer()"); 55 56} 57 58 59void GenericPlayer::init(const notif_cbf_t cbf, void* notifUser) { 60 SL_LOGD("GenericPlayer::init()"); 61 62 { 63 android::Mutex::Autolock autoLock(mNotifyClientLock); 64 mNotifyClient = cbf; 65 mNotifyUser = notifUser; 66 } 67 68 mLooper->registerHandler(this); 69 mLooper->start(false /*runOnCallingThread*/, false /*canCallJava*/, mLooperPriority); 70} 71 72 73void GenericPlayer::preDestroy() { 74 SL_LOGD("GenericPlayer::preDestroy()"); 75 { 76 android::Mutex::Autolock autoLock(mNotifyClientLock); 77 mNotifyClient = NULL; 78 mNotifyUser = NULL; 79 } 80 81 mLooper->stop(); 82 mLooper->unregisterHandler(id()); 83} 84 85 86void GenericPlayer::setDataSource(const char *uri) { 87 resetDataLocator(); 88 89 mDataLocator.uriRef = uri; 90 91 mDataLocatorType = kDataLocatorUri; 92} 93 94 95void GenericPlayer::setDataSource(int fd, int64_t offset, int64_t length) { 96 resetDataLocator(); 97 98 mDataLocator.fdi.fd = fd; 99 100 struct stat sb; 101 int ret = fstat(fd, &sb); 102 if (ret != 0) { 103 SL_LOGE("GenericPlayer::setDataSource: fstat(%d) failed: %d, %s", fd, ret, strerror(errno)); 104 return; 105 } 106 107 if (offset >= sb.st_size) { 108 SL_LOGE("SfPlayer::setDataSource: invalid offset"); 109 return; 110 } 111 mDataLocator.fdi.offset = offset; 112 113 if (PLAYER_FD_FIND_FILE_SIZE == length) { 114 mDataLocator.fdi.length = sb.st_size; 115 } else if (offset + length > sb.st_size) { 116 mDataLocator.fdi.length = sb.st_size - offset; 117 } else { 118 mDataLocator.fdi.length = length; 119 } 120 121 mDataLocatorType = kDataLocatorFd; 122} 123 124 125void GenericPlayer::prepare() { 126 SL_LOGD("GenericPlayer::prepare()"); 127 sp<AMessage> msg = new AMessage(kWhatPrepare, id()); 128 msg->post(); 129} 130 131 132void GenericPlayer::play() { 133 SL_LOGD("GenericPlayer::play()"); 134 sp<AMessage> msg = new AMessage(kWhatPlay, id()); 135 msg->post(); 136} 137 138 139void GenericPlayer::pause() { 140 SL_LOGD("GenericPlayer::pause()"); 141 sp<AMessage> msg = new AMessage(kWhatPause, id()); 142 msg->post(); 143} 144 145 146void GenericPlayer::stop() { 147 SL_LOGD("GenericPlayer::stop()"); 148 (new AMessage(kWhatPause, id()))->post(); 149 150 // after a stop, playback should resume from the start. 151 seek(0); 152} 153 154 155void GenericPlayer::seek(int64_t timeMsec) { 156 SL_LOGV("GenericPlayer::seek %lld", timeMsec); 157 if (timeMsec < 0) { 158 SL_LOGE("GenericPlayer::seek error, can't seek to negative time %lldms", timeMsec); 159 return; 160 } 161 sp<AMessage> msg = new AMessage(kWhatSeek, id()); 162 msg->setInt64(WHATPARAM_SEEK_SEEKTIME_MS, timeMsec); 163 msg->post(); 164} 165 166 167void GenericPlayer::loop(bool loop) { 168 sp<AMessage> msg = new AMessage(kWhatLoop, id()); 169 msg->setInt32(WHATPARAM_LOOP_LOOPING, (int32_t)loop); 170 msg->post(); 171} 172 173 174void GenericPlayer::setBufferingUpdateThreshold(int16_t thresholdPercent) { 175 sp<AMessage> msg = new AMessage(kWhatBuffUpdateThres, id()); 176 msg->setInt32(WHATPARAM_BUFFERING_UPDATETHRESHOLD_PERCENT, (int32_t)thresholdPercent); 177 msg->post(); 178} 179 180 181//-------------------------------------------------- 182void GenericPlayer::getDurationMsec(int* msec) { 183 *msec = mDurationMsec; 184} 185 186void GenericPlayer::getPositionMsec(int* msec) { 187 *msec = mPositionMsec; 188} 189 190void GenericPlayer::getSampleRate(uint* hz) { 191 *hz = mSampleRateHz; 192} 193 194//-------------------------------------------------- 195void GenericPlayer::setVolume(bool mute, bool useStereoPos, 196 XApermille stereoPos, XAmillibel volume) { 197 198 // compute amplification as the combination of volume level and stereo position 199 float leftVol = 1.0f, rightVol = 1.0f; 200 // amplification from volume level 201 leftVol *= sles_to_android_amplification(volume); 202 rightVol = leftVol; 203 204 // amplification from direct level (changed in SLEffectSendtItf and SLAndroidEffectSendItf) 205 // FIXME use calculation below when supporting effects 206 //leftVol *= mAndroidAudioLevels.mAmplFromDirectLevel; 207 //rightVol *= mAndroidAudioLevels.mAmplFromDirectLevel; 208 209 // amplification from stereo position 210 if (useStereoPos) { 211 // panning law depends on number of channels of content: stereo panning vs 2ch. balance 212 if (1 == mChannelCount) { 213 // stereo panning 214 double theta = (1000 + stereoPos) * M_PI_4 / 1000.0f; // 0 <= theta <= Pi/2 215 leftVol *= cos(theta); 216 rightVol *= sin(theta); 217 } else { 218 // stereo balance 219 if (stereoPos > 0) { 220 leftVol *= (1000 - stereoPos) / 1000.0f; 221 rightVol *= 1.0f; 222 } else { 223 leftVol *= 1.0f; 224 rightVol *= (1000 + stereoPos) / 1000.0f; 225 } 226 } 227 } 228 229 { 230 Mutex::Autolock _l(mSettingsLock); 231 mAndroidAudioLevels.mMute = mute; 232 mAndroidAudioLevels.mFinalVolume[0] = leftVol; 233 mAndroidAudioLevels.mFinalVolume[1] = rightVol; 234 } 235 236 // send a message for the volume to be updated by the object which implements the volume 237 (new AMessage(kWhatVolumeUpdate, id()))->post(); 238} 239 240 241//-------------------------------------------------- 242/* 243 * post-condition: mDataLocatorType == kDataLocatorNone 244 * 245 */ 246void GenericPlayer::resetDataLocator() { 247 mDataLocatorType = kDataLocatorNone; 248} 249 250 251void GenericPlayer::notify(const char* event, int data, bool async) { 252 sp<AMessage> msg = new AMessage(kWhatNotif, id()); 253 msg->setInt32(event, (int32_t)data); 254 if (async) { 255 msg->post(); 256 } else { 257 this->onNotify(msg); 258 } 259} 260 261 262void GenericPlayer::notify(const char* event, int data1, int data2, bool async) { 263 sp<AMessage> msg = new AMessage(kWhatNotif, id()); 264 msg->setRect(event, 0, 0, (int32_t)data1, (int32_t)data2); 265 if (async) { 266 msg->post(); 267 } else { 268 this->onNotify(msg); 269 } 270} 271 272 273//-------------------------------------------------- 274// AHandler implementation 275void GenericPlayer::onMessageReceived(const sp<AMessage> &msg) { 276 switch (msg->what()) { 277 case kWhatPrepare: 278 onPrepare(); 279 break; 280 281 case kWhatNotif: 282 onNotify(msg); 283 break; 284 285 case kWhatPlay: 286 onPlay(); 287 break; 288 289 case kWhatPause: 290 onPause(); 291 break; 292 293 case kWhatSeek: 294 onSeek(msg); 295 break; 296 297 case kWhatLoop: 298 onLoop(msg); 299 break; 300 301 case kWhatVolumeUpdate: 302 onVolumeUpdate(); 303 break; 304 305 case kWhatSeekComplete: 306 onSeekComplete(); 307 break; 308 309 case kWhatBufferingUpdate: 310 onBufferingUpdate(msg); 311 break; 312 313 case kWhatBuffUpdateThres: 314 onSetBufferingUpdateThreshold(msg); 315 break; 316 317 default: 318 TRESPASS(); 319 } 320} 321 322 323//-------------------------------------------------- 324// Event handlers 325// it is strictly verboten to call those methods outside of the event loop 326 327void GenericPlayer::onPrepare() { 328 SL_LOGD("GenericPlayer::onPrepare()"); 329 if (!(mStateFlags & kFlagPrepared)) { 330 mStateFlags |= kFlagPrepared; 331 notify(PLAYEREVENT_PREPARED, PLAYER_SUCCESS, false /*async*/); 332 } 333 SL_LOGD("GenericPlayer::onPrepare() done, mStateFlags=0x%x", mStateFlags); 334} 335 336 337void GenericPlayer::onNotify(const sp<AMessage> &msg) { 338 notif_cbf_t notifClient; 339 void* notifUser; 340 { 341 android::Mutex::Autolock autoLock(mNotifyClientLock); 342 if (NULL == mNotifyClient) { 343 return; 344 } else { 345 notifClient = mNotifyClient; 346 notifUser = mNotifyUser; 347 } 348 } 349 350 int32_t val1, val2; 351 if (msg->findInt32(PLAYEREVENT_PREFETCHSTATUSCHANGE, &val1)) { 352 SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_PREFETCHSTATUSCHANGE, val1); 353 notifClient(kEventPrefetchStatusChange, val1, 0, notifUser); 354 } else if (msg->findInt32(PLAYEREVENT_PREFETCHFILLLEVELUPDATE, &val1)) { 355 SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_PREFETCHFILLLEVELUPDATE, val1); 356 notifClient(kEventPrefetchFillLevelUpdate, val1, 0, notifUser); 357 } else if (msg->findInt32(PLAYEREVENT_ENDOFSTREAM, &val1)) { 358 SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_ENDOFSTREAM, val1); 359 notifClient(kEventEndOfStream, val1, 0, notifUser); 360 } else if (msg->findInt32(PLAYEREVENT_PREPARED, &val1)) { 361 SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_PREPARED, val1); 362 notifClient(kEventPrepared, val1, 0, notifUser); 363 } else if (msg->findRect(PLAYEREVENT_VIDEO_SIZE_UPDATE, &val1, &val2, &val1, &val2)) { 364 SL_LOGV("GenericPlayer notifying %s = %d, %d", PLAYEREVENT_VIDEO_SIZE_UPDATE, val1, val2); 365 notifClient(kEventHasVideoSize, val1, val2, notifUser); 366 } 367} 368 369 370void GenericPlayer::onPlay() { 371 SL_LOGD("GenericPlayer::onPlay()"); 372 if ((mStateFlags & kFlagPrepared)) { 373 SL_LOGD("starting player"); 374 mStateFlags |= kFlagPlaying; 375 } else { 376 SL_LOGV("NOT starting player mStateFlags=0x%x", mStateFlags); 377 } 378} 379 380 381void GenericPlayer::onPause() { 382 SL_LOGD("GenericPlayer::onPause()"); 383 if ((mStateFlags & kFlagPrepared)) { 384 mStateFlags &= ~kFlagPlaying; 385 } 386} 387 388 389void GenericPlayer::onSeek(const sp<AMessage> &msg) { 390 SL_LOGV("GenericPlayer::onSeek"); 391} 392 393 394void GenericPlayer::onLoop(const sp<AMessage> &msg) { 395 SL_LOGV("GenericPlayer::onLoop"); 396} 397 398 399void GenericPlayer::onVolumeUpdate() { 400 401} 402 403 404void GenericPlayer::onSeekComplete() { 405 SL_LOGD("GenericPlayer::onSeekComplete()"); 406 mStateFlags &= ~kFlagSeeking; 407} 408 409 410void GenericPlayer::onBufferingUpdate(const sp<AMessage> &msg) { 411 412} 413 414 415void GenericPlayer::onSetBufferingUpdateThreshold(const sp<AMessage> &msg) { 416 int32_t thresholdPercent = 0; 417 if (msg->findInt32(WHATPARAM_BUFFERING_UPDATETHRESHOLD_PERCENT, &thresholdPercent)) { 418 Mutex::Autolock _l(mSettingsLock); 419 mCacheFillNotifThreshold = (int16_t)thresholdPercent; 420 } 421} 422 423 424//------------------------------------------------- 425void GenericPlayer::notifyStatus() { 426 notify(PLAYEREVENT_PREFETCHSTATUSCHANGE, (int32_t)mCacheStatus, true /*async*/); 427} 428 429 430void GenericPlayer::notifyCacheFill() { 431 mLastNotifiedCacheFill = mCacheFill; 432 notify(PLAYEREVENT_PREFETCHFILLLEVELUPDATE, (int32_t)mLastNotifiedCacheFill, true/*async*/); 433} 434 435 436void GenericPlayer::seekComplete() { 437 sp<AMessage> msg = new AMessage(kWhatSeekComplete, id()); 438 msg->post(); 439} 440 441 442void GenericPlayer::bufferingUpdate(int16_t fillLevelPerMille) { 443 sp<AMessage> msg = new AMessage(kWhatBufferingUpdate, id()); 444 msg->setInt32(WHATPARAM_BUFFERING_UPDATE, fillLevelPerMille); 445 msg->post(); 446} 447 448} // namespace android 449