mediaplayer.cpp revision 2729ea9262ca60d93047e984739887cfc89e82eb
1/* mediaplayer.cpp 2** 3** Copyright 2006, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18//#define LOG_NDEBUG 0 19#define LOG_TAG "MediaPlayer" 20#include <utils/Log.h> 21 22#include <sys/types.h> 23#include <sys/stat.h> 24#include <unistd.h> 25#include <fcntl.h> 26 27#include <utils/IServiceManager.h> 28#include <utils/IPCThreadState.h> 29 30#include <media/mediaplayer.h> 31#include <libsonivox/eas.h> 32 33#include <utils/MemoryBase.h> 34 35namespace android { 36 37// client singleton for binder interface to service 38Mutex MediaPlayer::mServiceLock; 39sp<IMediaPlayerService> MediaPlayer::mMediaPlayerService; 40sp<MediaPlayer::DeathNotifier> MediaPlayer::mDeathNotifier; 41 42// establish binder interface to service 43const sp<IMediaPlayerService>& MediaPlayer::getMediaPlayerService() 44{ 45 Mutex::Autolock _l(mServiceLock); 46 if (mMediaPlayerService.get() == 0) { 47 sp<IServiceManager> sm = defaultServiceManager(); 48 sp<IBinder> binder; 49 do { 50 binder = sm->getService(String16("media.player")); 51 if (binder != 0) 52 break; 53 LOGW("MediaPlayerService not published, waiting..."); 54 usleep(500000); // 0.5 s 55 } while(true); 56 if (mDeathNotifier == NULL) { 57 mDeathNotifier = new DeathNotifier(); 58 } 59 binder->linkToDeath(mDeathNotifier); 60 mMediaPlayerService = interface_cast<IMediaPlayerService>(binder); 61 } 62 LOGE_IF(mMediaPlayerService==0, "no MediaPlayerService!?"); 63 return mMediaPlayerService; 64} 65 66MediaPlayer::MediaPlayer() 67{ 68 LOGV("constructor"); 69 mListener = NULL; 70 mCookie = NULL; 71 mDuration = -1; 72 mStreamType = AudioTrack::MUSIC; 73 mCurrentPosition = -1; 74 mSeekPosition = -1; 75 mCurrentState = MEDIA_PLAYER_IDLE; 76 mPrepareSync = false; 77 mPrepareStatus = NO_ERROR; 78 mLoop = false; 79 mLeftVolume = mRightVolume = 1.0; 80} 81 82MediaPlayer::~MediaPlayer() 83{ 84 LOGV("destructor"); 85 disconnect(); 86 IPCThreadState::self()->flushCommands(); 87} 88 89void MediaPlayer::disconnect() 90{ 91 LOGV("disconnect"); 92 sp<IMediaPlayer> p; 93 { 94 Mutex::Autolock _l(mLock); 95 p = mPlayer; 96 mPlayer.clear(); 97 } 98 99 if (p != 0) { 100 p->disconnect(); 101 p->asBinder()->unlinkToDeath(this); 102 } 103} 104 105// always call with lock held 106void MediaPlayer::clear_l() 107{ 108 mDuration = -1; 109 mCurrentPosition = -1; 110 mSeekPosition = -1; 111} 112 113status_t MediaPlayer::setListener(const sp<MediaPlayerListener>& listener) 114{ 115 LOGV("setListener"); 116 Mutex::Autolock _l(mLock); 117 mListener = listener; 118 return NO_ERROR; 119} 120 121 122status_t MediaPlayer::setDataSource(const sp<IMediaPlayer>& player) 123{ 124 status_t err = UNKNOWN_ERROR; 125 sp<IMediaPlayer> p; 126 { // scope for the lock 127 Mutex::Autolock _l(mLock); 128 129 if ( !( mCurrentState & ( MEDIA_PLAYER_IDLE | MEDIA_PLAYER_STATE_ERROR ) ) ) { 130 LOGE("setDataSource called in state %d", mCurrentState); 131 return INVALID_OPERATION; 132 } 133 134 clear_l(); 135 p = mPlayer; 136 mPlayer = player; 137 if (player != 0) { 138 mCurrentState = MEDIA_PLAYER_INITIALIZED; 139 player->asBinder()->linkToDeath(this); 140 err = NO_ERROR; 141 } else { 142 LOGE("Unable to to create media player"); 143 } 144 } 145 146 if (p != 0) { 147 p->disconnect(); 148 p->asBinder()->unlinkToDeath(this); 149 } 150 return err; 151} 152 153status_t MediaPlayer::setDataSource(const char *url) 154{ 155 LOGV("setDataSource(%s)", url); 156 status_t err = UNKNOWN_ERROR; 157 if (url != NULL) { 158 const sp<IMediaPlayerService>& service(getMediaPlayerService()); 159 if (service != 0) { 160 sp<IMediaPlayer> player(service->create(getpid(), this, url)); 161 err = setDataSource(player); 162 } 163 } 164 return err; 165} 166 167status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length) 168{ 169 LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length); 170 status_t err = UNKNOWN_ERROR; 171 const sp<IMediaPlayerService>& service(getMediaPlayerService()); 172 if (service != 0) { 173 sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length)); 174 err = setDataSource(player); 175 } 176 return err; 177} 178 179status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface) 180{ 181 LOGV("setVideoSurface"); 182 Mutex::Autolock _l(mLock); 183 if (mPlayer == 0) return UNKNOWN_ERROR; 184 return mPlayer->setVideoSurface(surface->getISurface()); 185} 186 187// must call with lock held 188status_t MediaPlayer::prepareAsync_l() 189{ 190 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) { 191 mPlayer->setAudioStreamType(mStreamType); 192 mCurrentState = MEDIA_PLAYER_PREPARING; 193 return mPlayer->prepareAsync(); 194 } 195 LOGE("prepareAsync called in state %d", mCurrentState); 196 return INVALID_OPERATION; 197} 198 199status_t MediaPlayer::prepare() 200{ 201 LOGV("prepare"); 202 Mutex::Autolock _l(mLock); 203 if (mPrepareSync) return UNKNOWN_ERROR; 204 mPrepareSync = true; 205 status_t ret = prepareAsync_l(); 206 if (ret != NO_ERROR) return ret; 207 208 if (mPrepareSync) { 209 mSignal.wait(mLock); // wait for prepare done 210 mPrepareSync = false; 211 } 212 LOGV("prepare complete - status=%d", mPrepareStatus); 213 return mPrepareStatus; 214} 215 216status_t MediaPlayer::prepareAsync() 217{ 218 LOGV("prepareAsync"); 219 Mutex::Autolock _l(mLock); 220 return prepareAsync_l(); 221} 222 223status_t MediaPlayer::start() 224{ 225 LOGV("start"); 226 Mutex::Autolock _l(mLock); 227 if (mCurrentState & MEDIA_PLAYER_STARTED) 228 return NO_ERROR; 229 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED | 230 MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) { 231 mPlayer->setLooping(mLoop); 232 mPlayer->setVolume(mLeftVolume, mRightVolume); 233 mCurrentState = MEDIA_PLAYER_STARTED; 234 status_t ret = mPlayer->start(); 235 if (ret != NO_ERROR) { 236 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 237 ret = UNKNOWN_ERROR; 238 } else { 239 if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) { 240 LOGV("playback completed immediately following start()"); 241 } 242 } 243 return ret; 244 } 245 LOGE("start called in state %d", mCurrentState); 246 return INVALID_OPERATION; 247} 248 249status_t MediaPlayer::stop() 250{ 251 LOGV("stop"); 252 Mutex::Autolock _l(mLock); 253 if (mCurrentState & MEDIA_PLAYER_STOPPED) return NO_ERROR; 254 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | 255 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) ) { 256 status_t ret = mPlayer->stop(); 257 if (ret != NO_ERROR) { 258 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 259 ret = UNKNOWN_ERROR; 260 } else { 261 mCurrentState = MEDIA_PLAYER_STOPPED; 262 } 263 return ret; 264 } 265 LOGE("stop called in state %d", mCurrentState); 266 return INVALID_OPERATION; 267} 268 269status_t MediaPlayer::pause() 270{ 271 LOGV("pause"); 272 Mutex::Autolock _l(mLock); 273 if (mCurrentState & MEDIA_PLAYER_PAUSED) 274 return NO_ERROR; 275 if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER_STARTED)) { 276 status_t ret = mPlayer->pause(); 277 if (ret != NO_ERROR) { 278 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 279 ret = UNKNOWN_ERROR; 280 } else { 281 mCurrentState = MEDIA_PLAYER_PAUSED; 282 } 283 return ret; 284 } 285 LOGE("pause called in state %d", mCurrentState); 286 return INVALID_OPERATION; 287} 288 289bool MediaPlayer::isPlaying() 290{ 291 Mutex::Autolock _l(mLock); 292 if (mPlayer != 0) { 293 bool temp = false; 294 mPlayer->isPlaying(&temp); 295 LOGV("isPlaying: %d", temp); 296 if ((mCurrentState & MEDIA_PLAYER_STARTED) && ! temp) { 297 LOGE("internal/external state mismatch corrected"); 298 mCurrentState = MEDIA_PLAYER_PAUSED; 299 } 300 return temp; 301 } 302 LOGV("isPlaying: no active player"); 303 return false; 304} 305 306status_t MediaPlayer::getVideoWidth(int *w) 307{ 308 LOGV("getVideoWidth"); 309 Mutex::Autolock _l(mLock); 310 if (mPlayer != 0) { 311 int h; 312 return mPlayer->getVideoSize(w, &h); 313 } 314 return INVALID_OPERATION; 315} 316 317status_t MediaPlayer::getVideoHeight(int *h) 318{ 319 LOGV("getVideoHeight"); 320 Mutex::Autolock _l(mLock); 321 if (mPlayer != 0) { 322 int w; 323 return mPlayer->getVideoSize(&w, h); 324 } 325 return INVALID_OPERATION; 326} 327 328status_t MediaPlayer::getCurrentPosition(int *msec) 329{ 330 LOGV("getCurrentPosition"); 331 Mutex::Autolock _l(mLock); 332 if (mPlayer != 0) { 333 if (mCurrentPosition >= 0) { 334 LOGV("Using cached seek position: %d", mCurrentPosition); 335 *msec = mCurrentPosition; 336 return NO_ERROR; 337 } 338 return mPlayer->getCurrentPosition(msec); 339 } 340 return INVALID_OPERATION; 341} 342 343status_t MediaPlayer::getDuration_l(int *msec) 344{ 345 LOGV("getDuration"); 346 bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE)); 347 if (mPlayer != 0 && isValidState) { 348 status_t ret = NO_ERROR; 349 if (mDuration <= 0) 350 ret = mPlayer->getDuration(&mDuration); 351 if (msec) 352 *msec = mDuration; 353 return ret; 354 } 355 LOGE("Attempt to call getDuration without a valid mediaplayer"); 356 return INVALID_OPERATION; 357} 358 359status_t MediaPlayer::getDuration(int *msec) 360{ 361 Mutex::Autolock _l(mLock); 362 return getDuration_l(msec); 363} 364 365status_t MediaPlayer::seekTo_l(int msec) 366{ 367 LOGV("seekTo %d", msec); 368 if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) { 369 if ( msec < 0 ) { 370 LOGW("Attempt to seek to invalid position: %d", msec); 371 msec = 0; 372 } else if ((mDuration > 0) && (msec > mDuration)) { 373 LOGW("Attempt to seek to past end of file: request = %d, EOF = %d", msec, mDuration); 374 msec = mDuration; 375 } 376 // cache duration 377 mCurrentPosition = msec; 378 if (mSeekPosition < 0) { 379 getDuration_l(NULL); 380 mSeekPosition = msec; 381 return mPlayer->seekTo(msec); 382 } 383 else { 384 LOGV("Seek in progress - queue up seekTo[%d]", msec); 385 return NO_ERROR; 386 } 387 } 388 LOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(), mCurrentState); 389 return INVALID_OPERATION; 390} 391 392status_t MediaPlayer::seekTo(int msec) 393{ 394 Mutex::Autolock _l(mLock); 395 return seekTo_l(msec); 396} 397 398status_t MediaPlayer::reset() 399{ 400 LOGV("reset"); 401 Mutex::Autolock _l(mLock); 402 mLoop = false; 403 if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR; 404 mPrepareSync = false; 405 if (mPlayer != 0) { 406 status_t ret = mPlayer->reset(); 407 if (ret != NO_ERROR) { 408 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 409 ret = UNKNOWN_ERROR; 410 } else { 411 mCurrentState = MEDIA_PLAYER_IDLE; 412 } 413 return ret; 414 } 415 clear_l(); 416 return NO_ERROR; 417} 418 419status_t MediaPlayer::setAudioStreamType(int type) 420{ 421 LOGV("MediaPlayer::setAudioStreamType"); 422 Mutex::Autolock _l(mLock); 423 if (mStreamType == type) return NO_ERROR; 424 if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | 425 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) { 426 // Can't change the stream type after prepare 427 LOGE("setAudioStream called in state %d", mCurrentState); 428 return INVALID_OPERATION; 429 } 430 // cache 431 mStreamType = type; 432 return OK; 433} 434 435status_t MediaPlayer::setLooping(int loop) 436{ 437 LOGV("MediaPlayer::setLooping"); 438 Mutex::Autolock _l(mLock); 439 mLoop = (loop != 0); 440 if (mPlayer != 0) { 441 return mPlayer->setLooping(loop); 442 } 443 return OK; 444} 445 446status_t MediaPlayer::setVolume(float leftVolume, float rightVolume) 447{ 448 LOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume); 449 Mutex::Autolock _l(mLock); 450 mLeftVolume = leftVolume; 451 mRightVolume = rightVolume; 452 if (mPlayer != 0) { 453 return mPlayer->setVolume(leftVolume, rightVolume); 454 } 455 return OK; 456} 457 458void MediaPlayer::notify(int msg, int ext1, int ext2) 459{ 460 LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2); 461 bool send = true; 462 463 // TODO: In the future, we might be on the same thread if the app is 464 // running in the same process as the media server. In that case, 465 // this will deadlock. 466 mLock.lock(); 467 if (mPlayer == 0) { 468 LOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2); 469 return; 470 } 471 472 switch (msg) { 473 case MEDIA_NOP: // interface test message 474 break; 475 case MEDIA_PREPARED: 476 LOGV("prepared"); 477 mCurrentState = MEDIA_PLAYER_PREPARED; 478 if (mPrepareSync) { 479 LOGV("signal application thread"); 480 mPrepareSync = false; 481 mPrepareStatus = NO_ERROR; 482 mSignal.signal(); 483 } 484 break; 485 case MEDIA_PLAYBACK_COMPLETE: 486 LOGV("playback complete"); 487 if (!mLoop) { 488 mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE; 489 } 490 break; 491 case MEDIA_ERROR: 492 LOGV("error (%d, %d)", ext1, ext2); 493 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 494 if (mPrepareSync) 495 { 496 LOGV("signal application thread"); 497 mPrepareSync = false; 498 mPrepareStatus = ext1; 499 mSignal.signal(); 500 send = false; 501 } 502 break; 503 case MEDIA_SEEK_COMPLETE: 504 LOGV("Received seek complete"); 505 if (mSeekPosition != mCurrentPosition) { 506 LOGV("Executing queued seekTo(%d)", mSeekPosition); 507 mSeekPosition = -1; 508 seekTo_l(mCurrentPosition); 509 } 510 else { 511 LOGV("All seeks complete - return to regularly scheduled program"); 512 mCurrentPosition = mSeekPosition = -1; 513 } 514 break; 515 case MEDIA_BUFFERING_UPDATE: 516 LOGV("buffering %d", ext1); 517 break; 518 default: 519 LOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2); 520 break; 521 } 522 523 sp<MediaPlayerListener> listener = mListener; 524 mLock.unlock(); 525 526 // this prevents re-entrant calls into client code 527 if ((listener != 0) && send) { 528 Mutex::Autolock _l(mNotifyLock); 529 LOGV("callback application"); 530 listener->notify(msg, ext1, ext2); 531 LOGV("back from callback"); 532 } 533} 534 535void MediaPlayer::binderDied(const wp<IBinder>& who) { 536 LOGW("IMediaplayer died"); 537 notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0); 538} 539 540void MediaPlayer::DeathNotifier::binderDied(const wp<IBinder>& who) { 541 Mutex::Autolock _l(MediaPlayer::mServiceLock); 542 MediaPlayer::mMediaPlayerService.clear(); 543 LOGW("MediaPlayer server died!"); 544} 545 546MediaPlayer::DeathNotifier::~DeathNotifier() 547{ 548 Mutex::Autolock _l(mServiceLock); 549 if (mMediaPlayerService != 0) { 550 mMediaPlayerService->asBinder()->unlinkToDeath(this); 551 } 552} 553 554/*static*/ sp<IMemory> MediaPlayer::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels) 555{ 556 LOGV("decode(%s)", url); 557 sp<IMemory> p; 558 const sp<IMediaPlayerService>& service = getMediaPlayerService(); 559 if (service != 0) { 560 p = mMediaPlayerService->decode(url, pSampleRate, pNumChannels); 561 } else { 562 LOGE("Unable to locate media service"); 563 } 564 return p; 565 566} 567 568/*static*/ sp<IMemory> MediaPlayer::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels) 569{ 570 LOGV("decode(%d, %lld, %lld)", fd, offset, length); 571 sp<IMemory> p; 572 const sp<IMediaPlayerService>& service = getMediaPlayerService(); 573 if (service != 0) { 574 p = mMediaPlayerService->decode(fd, offset, length, pSampleRate, pNumChannels); 575 } else { 576 LOGE("Unable to locate media service"); 577 } 578 return p; 579 580} 581 582}; // namespace android 583