mediaplayer.cpp revision a7e0e8b4c429fc68eb1bd5b5a30f5b91352288f9
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 <binder/IServiceManager.h> 28#include <binder/IPCThreadState.h> 29 30#include <media/mediaplayer.h> 31#include <media/AudioTrack.h> 32 33#include <binder/MemoryBase.h> 34 35namespace android { 36 37// client singleton for binder interface to service 38Mutex MediaPlayer::sServiceLock; 39sp<IMediaPlayerService> MediaPlayer::sMediaPlayerService; 40sp<MediaPlayer::DeathNotifier> MediaPlayer::sDeathNotifier; 41SortedVector< wp<MediaPlayer> > MediaPlayer::sObitRecipients; 42 43// establish binder interface to service 44const sp<IMediaPlayerService>& MediaPlayer::getMediaPlayerService() 45{ 46 Mutex::Autolock _l(sServiceLock); 47 if (sMediaPlayerService.get() == 0) { 48 sp<IServiceManager> sm = defaultServiceManager(); 49 sp<IBinder> binder; 50 do { 51 binder = sm->getService(String16("media.player")); 52 if (binder != 0) 53 break; 54 LOGW("MediaPlayerService not published, waiting..."); 55 usleep(500000); // 0.5 s 56 } while(true); 57 if (sDeathNotifier == NULL) { 58 sDeathNotifier = new DeathNotifier(); 59 } 60 binder->linkToDeath(sDeathNotifier); 61 sMediaPlayerService = interface_cast<IMediaPlayerService>(binder); 62 } 63 LOGE_IF(sMediaPlayerService==0, "no MediaPlayerService!?"); 64 return sMediaPlayerService; 65} 66 67void MediaPlayer::addObitRecipient(const wp<MediaPlayer>& recipient) 68{ 69 Mutex::Autolock _l(sServiceLock); 70 sObitRecipients.add(recipient); 71} 72 73void MediaPlayer::removeObitRecipient(const wp<MediaPlayer>& recipient) 74{ 75 Mutex::Autolock _l(sServiceLock); 76 sObitRecipients.remove(recipient); 77} 78 79MediaPlayer::MediaPlayer() 80{ 81 LOGV("constructor"); 82 mListener = NULL; 83 mCookie = NULL; 84 mDuration = -1; 85 mStreamType = AudioSystem::MUSIC; 86 mCurrentPosition = -1; 87 mSeekPosition = -1; 88 mCurrentState = MEDIA_PLAYER_IDLE; 89 mPrepareSync = false; 90 mPrepareStatus = NO_ERROR; 91 mLoop = false; 92 mLeftVolume = mRightVolume = 1.0; 93 mVideoWidth = mVideoHeight = 0; 94 mLockThreadId = 0; 95} 96 97void MediaPlayer::onFirstRef() 98{ 99 addObitRecipient(this); 100} 101 102MediaPlayer::~MediaPlayer() 103{ 104 LOGV("destructor"); 105 removeObitRecipient(this); 106 disconnect(); 107 IPCThreadState::self()->flushCommands(); 108} 109 110void MediaPlayer::disconnect() 111{ 112 LOGV("disconnect"); 113 sp<IMediaPlayer> p; 114 { 115 Mutex::Autolock _l(mLock); 116 p = mPlayer; 117 mPlayer.clear(); 118 } 119 120 if (p != 0) { 121 p->disconnect(); 122 } 123} 124 125// always call with lock held 126void MediaPlayer::clear_l() 127{ 128 mDuration = -1; 129 mCurrentPosition = -1; 130 mSeekPosition = -1; 131 mVideoWidth = mVideoHeight = 0; 132} 133 134status_t MediaPlayer::setListener(const sp<MediaPlayerListener>& listener) 135{ 136 LOGV("setListener"); 137 Mutex::Autolock _l(mLock); 138 mListener = listener; 139 return NO_ERROR; 140} 141 142 143status_t MediaPlayer::setDataSource(const sp<IMediaPlayer>& player) 144{ 145 status_t err = UNKNOWN_ERROR; 146 sp<IMediaPlayer> p; 147 { // scope for the lock 148 Mutex::Autolock _l(mLock); 149 150 if ( !( mCurrentState & ( MEDIA_PLAYER_IDLE | MEDIA_PLAYER_STATE_ERROR ) ) ) { 151 LOGE("setDataSource called in state %d", mCurrentState); 152 return INVALID_OPERATION; 153 } 154 155 clear_l(); 156 p = mPlayer; 157 mPlayer = player; 158 if (player != 0) { 159 mCurrentState = MEDIA_PLAYER_INITIALIZED; 160 err = NO_ERROR; 161 } else { 162 LOGE("Unable to to create media player"); 163 } 164 } 165 166 if (p != 0) { 167 p->disconnect(); 168 } 169 170 return err; 171} 172 173status_t MediaPlayer::setDataSource(const char *url) 174{ 175 LOGV("setDataSource(%s)", url); 176 status_t err = BAD_VALUE; 177 if (url != NULL) { 178 const sp<IMediaPlayerService>& service(getMediaPlayerService()); 179 if (service != 0) { 180 sp<IMediaPlayer> player(service->create(getpid(), this, url)); 181 err = setDataSource(player); 182 } 183 } 184 return err; 185} 186 187status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length) 188{ 189 LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length); 190 status_t err = UNKNOWN_ERROR; 191 const sp<IMediaPlayerService>& service(getMediaPlayerService()); 192 if (service != 0) { 193 sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length)); 194 err = setDataSource(player); 195 } 196 return err; 197} 198 199status_t MediaPlayer::invoke(const Parcel& request, Parcel *reply) 200{ 201 Mutex::Autolock _l(mLock); 202 if ((mPlayer != NULL) && ( mCurrentState & MEDIA_PLAYER_INITIALIZED )) 203 { 204 LOGV("invoke %d", request.dataSize()); 205 return mPlayer->invoke(request, reply); 206 } 207 LOGE("invoke failed: wrong state %X", mCurrentState); 208 return INVALID_OPERATION; 209} 210 211status_t MediaPlayer::setMetadataFilter(const Parcel& filter) 212{ 213 LOGD("setMetadataFilter"); 214 Mutex::Autolock _l(mLock); 215 if (mPlayer == NULL) 216 { 217 return NO_INIT; 218 } 219 return mPlayer->setMetadataFilter(filter); 220} 221 222status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface) 223{ 224 LOGV("setVideoSurface"); 225 Mutex::Autolock _l(mLock); 226 if (mPlayer == 0) return NO_INIT; 227 return mPlayer->setVideoSurface(surface->getISurface()); 228} 229 230// must call with lock held 231status_t MediaPlayer::prepareAsync_l() 232{ 233 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) { 234 mPlayer->setAudioStreamType(mStreamType); 235 mCurrentState = MEDIA_PLAYER_PREPARING; 236 return mPlayer->prepareAsync(); 237 } 238 LOGE("prepareAsync called in state %d", mCurrentState); 239 return INVALID_OPERATION; 240} 241 242// TODO: In case of error, prepareAsync provides the caller with 2 error codes, 243// one defined in the Android framework and one provided by the implementation 244// that generated the error. The sync version of prepare returns only 1 error 245// code. 246status_t MediaPlayer::prepare() 247{ 248 LOGV("prepare"); 249 Mutex::Autolock _l(mLock); 250 mLockThreadId = getThreadId(); 251 if (mPrepareSync) { 252 mLockThreadId = 0; 253 return -EALREADY; 254 } 255 mPrepareSync = true; 256 status_t ret = prepareAsync_l(); 257 if (ret != NO_ERROR) { 258 mLockThreadId = 0; 259 return ret; 260 } 261 262 if (mPrepareSync) { 263 mSignal.wait(mLock); // wait for prepare done 264 mPrepareSync = false; 265 } 266 LOGV("prepare complete - status=%d", mPrepareStatus); 267 mLockThreadId = 0; 268 return mPrepareStatus; 269} 270 271status_t MediaPlayer::prepareAsync() 272{ 273 LOGV("prepareAsync"); 274 Mutex::Autolock _l(mLock); 275 return prepareAsync_l(); 276} 277 278status_t MediaPlayer::start() 279{ 280 LOGV("start"); 281 Mutex::Autolock _l(mLock); 282 if (mCurrentState & MEDIA_PLAYER_STARTED) 283 return NO_ERROR; 284 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED | 285 MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) { 286 mPlayer->setLooping(mLoop); 287 mPlayer->setVolume(mLeftVolume, mRightVolume); 288 mCurrentState = MEDIA_PLAYER_STARTED; 289 status_t ret = mPlayer->start(); 290 if (ret != NO_ERROR) { 291 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 292 } else { 293 if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) { 294 LOGV("playback completed immediately following start()"); 295 } 296 } 297 return ret; 298 } 299 LOGE("start called in state %d", mCurrentState); 300 return INVALID_OPERATION; 301} 302 303status_t MediaPlayer::stop() 304{ 305 LOGV("stop"); 306 Mutex::Autolock _l(mLock); 307 if (mCurrentState & MEDIA_PLAYER_STOPPED) return NO_ERROR; 308 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | 309 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) ) { 310 status_t ret = mPlayer->stop(); 311 if (ret != NO_ERROR) { 312 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 313 } else { 314 mCurrentState = MEDIA_PLAYER_STOPPED; 315 } 316 return ret; 317 } 318 LOGE("stop called in state %d", mCurrentState); 319 return INVALID_OPERATION; 320} 321 322status_t MediaPlayer::pause() 323{ 324 LOGV("pause"); 325 Mutex::Autolock _l(mLock); 326 if (mCurrentState & MEDIA_PLAYER_PAUSED) 327 return NO_ERROR; 328 if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER_STARTED)) { 329 status_t ret = mPlayer->pause(); 330 if (ret != NO_ERROR) { 331 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 332 } else { 333 mCurrentState = MEDIA_PLAYER_PAUSED; 334 } 335 return ret; 336 } 337 LOGE("pause called in state %d", mCurrentState); 338 return INVALID_OPERATION; 339} 340 341bool MediaPlayer::isPlaying() 342{ 343 Mutex::Autolock _l(mLock); 344 if (mPlayer != 0) { 345 bool temp = false; 346 mPlayer->isPlaying(&temp); 347 LOGV("isPlaying: %d", temp); 348 if ((mCurrentState & MEDIA_PLAYER_STARTED) && ! temp) { 349 LOGE("internal/external state mismatch corrected"); 350 mCurrentState = MEDIA_PLAYER_PAUSED; 351 } 352 return temp; 353 } 354 LOGV("isPlaying: no active player"); 355 return false; 356} 357 358status_t MediaPlayer::getVideoWidth(int *w) 359{ 360 LOGV("getVideoWidth"); 361 Mutex::Autolock _l(mLock); 362 if (mPlayer == 0) return INVALID_OPERATION; 363 *w = mVideoWidth; 364 return NO_ERROR; 365} 366 367status_t MediaPlayer::getVideoHeight(int *h) 368{ 369 LOGV("getVideoHeight"); 370 Mutex::Autolock _l(mLock); 371 if (mPlayer == 0) return INVALID_OPERATION; 372 *h = mVideoHeight; 373 return NO_ERROR; 374} 375 376status_t MediaPlayer::getCurrentPosition(int *msec) 377{ 378 LOGV("getCurrentPosition"); 379 Mutex::Autolock _l(mLock); 380 if (mPlayer != 0) { 381 if (mCurrentPosition >= 0) { 382 LOGV("Using cached seek position: %d", mCurrentPosition); 383 *msec = mCurrentPosition; 384 return NO_ERROR; 385 } 386 return mPlayer->getCurrentPosition(msec); 387 } 388 return INVALID_OPERATION; 389} 390 391status_t MediaPlayer::getDuration_l(int *msec) 392{ 393 LOGV("getDuration"); 394 bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE)); 395 if (mPlayer != 0 && isValidState) { 396 status_t ret = NO_ERROR; 397 if (mDuration <= 0) 398 ret = mPlayer->getDuration(&mDuration); 399 if (msec) 400 *msec = mDuration; 401 return ret; 402 } 403 LOGE("Attempt to call getDuration without a valid mediaplayer"); 404 return INVALID_OPERATION; 405} 406 407status_t MediaPlayer::getDuration(int *msec) 408{ 409 Mutex::Autolock _l(mLock); 410 return getDuration_l(msec); 411} 412 413status_t MediaPlayer::seekTo_l(int msec) 414{ 415 LOGV("seekTo %d", msec); 416 if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) { 417 if ( msec < 0 ) { 418 LOGW("Attempt to seek to invalid position: %d", msec); 419 msec = 0; 420 } else if ((mDuration > 0) && (msec > mDuration)) { 421 LOGW("Attempt to seek to past end of file: request = %d, EOF = %d", msec, mDuration); 422 msec = mDuration; 423 } 424 // cache duration 425 mCurrentPosition = msec; 426 if (mSeekPosition < 0) { 427 getDuration_l(NULL); 428 mSeekPosition = msec; 429 return mPlayer->seekTo(msec); 430 } 431 else { 432 LOGV("Seek in progress - queue up seekTo[%d]", msec); 433 return NO_ERROR; 434 } 435 } 436 LOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(), mCurrentState); 437 return INVALID_OPERATION; 438} 439 440status_t MediaPlayer::seekTo(int msec) 441{ 442 mLockThreadId = getThreadId(); 443 Mutex::Autolock _l(mLock); 444 status_t result = seekTo_l(msec); 445 mLockThreadId = 0; 446 447 return result; 448} 449 450status_t MediaPlayer::reset() 451{ 452 LOGV("reset"); 453 Mutex::Autolock _l(mLock); 454 mLoop = false; 455 if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR; 456 mPrepareSync = false; 457 if (mPlayer != 0) { 458 status_t ret = mPlayer->reset(); 459 if (ret != NO_ERROR) { 460 LOGE("reset() failed with return code (%d)", ret); 461 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 462 } else { 463 mCurrentState = MEDIA_PLAYER_IDLE; 464 } 465 return ret; 466 } 467 clear_l(); 468 return NO_ERROR; 469} 470 471status_t MediaPlayer::setAudioStreamType(int type) 472{ 473 LOGV("MediaPlayer::setAudioStreamType"); 474 Mutex::Autolock _l(mLock); 475 if (mStreamType == type) return NO_ERROR; 476 if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | 477 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) { 478 // Can't change the stream type after prepare 479 LOGE("setAudioStream called in state %d", mCurrentState); 480 return INVALID_OPERATION; 481 } 482 // cache 483 mStreamType = type; 484 return OK; 485} 486 487status_t MediaPlayer::setLooping(int loop) 488{ 489 LOGV("MediaPlayer::setLooping"); 490 Mutex::Autolock _l(mLock); 491 mLoop = (loop != 0); 492 if (mPlayer != 0) { 493 return mPlayer->setLooping(loop); 494 } 495 return OK; 496} 497 498bool MediaPlayer::isLooping() { 499 LOGV("isLooping"); 500 Mutex::Autolock _l(mLock); 501 if (mPlayer != 0) { 502 return mLoop; 503 } 504 LOGV("isLooping: no active player"); 505 return false; 506} 507 508status_t MediaPlayer::setVolume(float leftVolume, float rightVolume) 509{ 510 LOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume); 511 Mutex::Autolock _l(mLock); 512 mLeftVolume = leftVolume; 513 mRightVolume = rightVolume; 514 if (mPlayer != 0) { 515 return mPlayer->setVolume(leftVolume, rightVolume); 516 } 517 return OK; 518} 519 520void MediaPlayer::notify(int msg, int ext1, int ext2) 521{ 522 LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2); 523 bool send = true; 524 bool locked = false; 525 526 // TODO: In the future, we might be on the same thread if the app is 527 // running in the same process as the media server. In that case, 528 // this will deadlock. 529 // 530 // The threadId hack below works around this for the care of prepare 531 // and seekTo within the same process. 532 // FIXME: Remember, this is a hack, it's not even a hack that is applied 533 // consistently for all use-cases, this needs to be revisited. 534 if (mLockThreadId != getThreadId()) { 535 mLock.lock(); 536 locked = true; 537 } 538 539 if (mPlayer == 0) { 540 LOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2); 541 if (locked) mLock.unlock(); // release the lock when done. 542 return; 543 } 544 545 switch (msg) { 546 case MEDIA_NOP: // interface test message 547 break; 548 case MEDIA_PREPARED: 549 LOGV("prepared"); 550 mCurrentState = MEDIA_PLAYER_PREPARED; 551 if (mPrepareSync) { 552 LOGV("signal application thread"); 553 mPrepareSync = false; 554 mPrepareStatus = NO_ERROR; 555 mSignal.signal(); 556 } 557 break; 558 case MEDIA_PLAYBACK_COMPLETE: 559 LOGV("playback complete"); 560 if (!mLoop) { 561 mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE; 562 } 563 break; 564 case MEDIA_ERROR: 565 // Always log errors. 566 // ext1: Media framework error code. 567 // ext2: Implementation dependant error code. 568 LOGE("error (%d, %d)", ext1, ext2); 569 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 570 if (mPrepareSync) 571 { 572 LOGV("signal application thread"); 573 mPrepareSync = false; 574 mPrepareStatus = ext1; 575 mSignal.signal(); 576 send = false; 577 } 578 break; 579 case MEDIA_INFO: 580 // ext1: Media framework error code. 581 // ext2: Implementation dependant error code. 582 LOGW("info/warning (%d, %d)", ext1, ext2); 583 break; 584 case MEDIA_SEEK_COMPLETE: 585 LOGV("Received seek complete"); 586 if (mSeekPosition != mCurrentPosition) { 587 LOGV("Executing queued seekTo(%d)", mSeekPosition); 588 mSeekPosition = -1; 589 seekTo_l(mCurrentPosition); 590 } 591 else { 592 LOGV("All seeks complete - return to regularly scheduled program"); 593 mCurrentPosition = mSeekPosition = -1; 594 } 595 break; 596 case MEDIA_BUFFERING_UPDATE: 597 LOGV("buffering %d", ext1); 598 break; 599 case MEDIA_SET_VIDEO_SIZE: 600 LOGV("New video size %d x %d", ext1, ext2); 601 mVideoWidth = ext1; 602 mVideoHeight = ext2; 603 break; 604 default: 605 LOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2); 606 break; 607 } 608 609 sp<MediaPlayerListener> listener = mListener; 610 if (locked) mLock.unlock(); 611 612 // this prevents re-entrant calls into client code 613 if ((listener != 0) && send) { 614 Mutex::Autolock _l(mNotifyLock); 615 LOGV("callback application"); 616 listener->notify(msg, ext1, ext2); 617 LOGV("back from callback"); 618 } 619} 620 621void MediaPlayer::DeathNotifier::binderDied(const wp<IBinder>& who) { 622 LOGW("MediaPlayer server died!"); 623 624 // Need to do this with the lock held 625 SortedVector< wp<MediaPlayer> > list; 626 { 627 Mutex::Autolock _l(MediaPlayer::sServiceLock); 628 MediaPlayer::sMediaPlayerService.clear(); 629 list = sObitRecipients; 630 } 631 632 // Notify application when media server dies. 633 // Don't hold the static lock during callback in case app 634 // makes a call that needs the lock. 635 size_t count = list.size(); 636 for (size_t iter = 0; iter < count; ++iter) { 637 sp<MediaPlayer> player = list[iter].promote(); 638 if ((player != 0) && (player->mPlayer != 0)) { 639 player->notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0); 640 } 641 } 642} 643 644MediaPlayer::DeathNotifier::~DeathNotifier() 645{ 646 Mutex::Autolock _l(sServiceLock); 647 sObitRecipients.clear(); 648 if (sMediaPlayerService != 0) { 649 sMediaPlayerService->asBinder()->unlinkToDeath(this); 650 } 651} 652 653/*static*/ sp<IMemory> MediaPlayer::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) 654{ 655 LOGV("decode(%s)", url); 656 sp<IMemory> p; 657 const sp<IMediaPlayerService>& service = getMediaPlayerService(); 658 if (service != 0) { 659 p = sMediaPlayerService->decode(url, pSampleRate, pNumChannels, pFormat); 660 } else { 661 LOGE("Unable to locate media service"); 662 } 663 return p; 664 665} 666 667/*static*/ sp<IMemory> MediaPlayer::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) 668{ 669 LOGV("decode(%d, %lld, %lld)", fd, offset, length); 670 sp<IMemory> p; 671 const sp<IMediaPlayerService>& service = getMediaPlayerService(); 672 if (service != 0) { 673 p = sMediaPlayerService->decode(fd, offset, length, pSampleRate, pNumChannels, pFormat); 674 } else { 675 LOGE("Unable to locate media service"); 676 } 677 return p; 678 679} 680 681}; // namespace android 682