mediaplayer.cpp revision d681bbb1767bed09415e050ba78975df214bcd68
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 <gui/SurfaceTextureClient.h> 31 32#include <media/mediaplayer.h> 33#include <media/AudioTrack.h> 34 35#include <surfaceflinger/Surface.h> 36 37#include <binder/MemoryBase.h> 38 39#include <utils/KeyedVector.h> 40#include <utils/String8.h> 41 42#include <system/audio.h> 43#include <system/window.h> 44 45namespace android { 46 47MediaPlayer::MediaPlayer() 48{ 49 LOGV("constructor"); 50 mListener = NULL; 51 mCookie = NULL; 52 mDuration = -1; 53 mStreamType = AUDIO_STREAM_MUSIC; 54 mCurrentPosition = -1; 55 mSeekPosition = -1; 56 mCurrentState = MEDIA_PLAYER_IDLE; 57 mPrepareSync = false; 58 mPrepareStatus = NO_ERROR; 59 mLoop = false; 60 mLeftVolume = mRightVolume = 1.0; 61 mVideoWidth = mVideoHeight = 0; 62 mLockThreadId = 0; 63 mAudioSessionId = AudioSystem::newAudioSessionId(); 64 AudioSystem::acquireAudioSessionId(mAudioSessionId); 65 mSendLevel = 0; 66} 67 68MediaPlayer::~MediaPlayer() 69{ 70 LOGV("destructor"); 71 AudioSystem::releaseAudioSessionId(mAudioSessionId); 72 disconnect(); 73 IPCThreadState::self()->flushCommands(); 74} 75 76void MediaPlayer::disconnect() 77{ 78 LOGV("disconnect"); 79 sp<IMediaPlayer> p; 80 { 81 Mutex::Autolock _l(mLock); 82 p = mPlayer; 83 mPlayer.clear(); 84 } 85 86 if (p != 0) { 87 p->disconnect(); 88 } 89 90 disconnectNativeWindow(); 91} 92 93// always call with lock held 94void MediaPlayer::clear_l() 95{ 96 mDuration = -1; 97 mCurrentPosition = -1; 98 mSeekPosition = -1; 99 mVideoWidth = mVideoHeight = 0; 100} 101 102status_t MediaPlayer::setListener(const sp<MediaPlayerListener>& listener) 103{ 104 LOGV("setListener"); 105 Mutex::Autolock _l(mLock); 106 mListener = listener; 107 return NO_ERROR; 108} 109 110 111status_t MediaPlayer::attachNewPlayer(const sp<IMediaPlayer>& player) 112{ 113 status_t err = UNKNOWN_ERROR; 114 sp<IMediaPlayer> p; 115 { // scope for the lock 116 Mutex::Autolock _l(mLock); 117 118 if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) || 119 (mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) { 120 LOGE("attachNewPlayer called in state %d", mCurrentState); 121 return INVALID_OPERATION; 122 } 123 124 clear_l(); 125 p = mPlayer; 126 mPlayer = player; 127 if (player != 0) { 128 mCurrentState = MEDIA_PLAYER_INITIALIZED; 129 err = NO_ERROR; 130 } else { 131 LOGE("Unable to to create media player"); 132 } 133 } 134 135 if (p != 0) { 136 p->disconnect(); 137 } 138 139 return err; 140} 141 142status_t MediaPlayer::setDataSource( 143 const char *url, const KeyedVector<String8, String8> *headers) 144{ 145 LOGV("setDataSource(%s)", url); 146 status_t err = BAD_VALUE; 147 if (url != NULL) { 148 const sp<IMediaPlayerService>& service(getMediaPlayerService()); 149 if (service != 0) { 150 sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId)); 151 err = attachNewPlayer(player); 152 if (err == NO_ERROR) { 153 err = mPlayer->setDataSource(url, headers); 154 } 155 } 156 } 157 return err; 158} 159 160status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length) 161{ 162 LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length); 163 status_t err = UNKNOWN_ERROR; 164 const sp<IMediaPlayerService>& service(getMediaPlayerService()); 165 if (service != 0) { 166 sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId)); 167 err = attachNewPlayer(player); 168 if (err == NO_ERROR) { 169 err = mPlayer->setDataSource(fd, offset, length); 170 } 171 } 172 return err; 173} 174 175status_t MediaPlayer::setDataSource(const sp<IStreamSource> &source) 176{ 177 LOGV("setDataSource"); 178 status_t err = UNKNOWN_ERROR; 179 const sp<IMediaPlayerService>& service(getMediaPlayerService()); 180 if (service != 0) { 181 sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId)); 182 err = attachNewPlayer(player); 183 if (err == NO_ERROR) { 184 err = mPlayer->setDataSource(source); 185 } 186 } 187 return err; 188} 189 190status_t MediaPlayer::invoke(const Parcel& request, Parcel *reply) 191{ 192 Mutex::Autolock _l(mLock); 193 const bool hasBeenInitialized = 194 (mCurrentState != MEDIA_PLAYER_STATE_ERROR) && 195 ((mCurrentState & MEDIA_PLAYER_IDLE) != MEDIA_PLAYER_IDLE); 196 if ((mPlayer != NULL) && hasBeenInitialized) { 197 LOGV("invoke %d", request.dataSize()); 198 return mPlayer->invoke(request, reply); 199 } 200 LOGE("invoke failed: wrong state %X", mCurrentState); 201 return INVALID_OPERATION; 202} 203 204status_t MediaPlayer::setMetadataFilter(const Parcel& filter) 205{ 206 LOGD("setMetadataFilter"); 207 Mutex::Autolock lock(mLock); 208 if (mPlayer == NULL) { 209 return NO_INIT; 210 } 211 return mPlayer->setMetadataFilter(filter); 212} 213 214status_t MediaPlayer::getMetadata(bool update_only, bool apply_filter, Parcel *metadata) 215{ 216 LOGD("getMetadata"); 217 Mutex::Autolock lock(mLock); 218 if (mPlayer == NULL) { 219 return NO_INIT; 220 } 221 return mPlayer->getMetadata(update_only, apply_filter, metadata); 222} 223 224void MediaPlayer::disconnectNativeWindow() { 225 if (mConnectedWindow != NULL) { 226 status_t err = native_window_api_disconnect(mConnectedWindow.get(), 227 NATIVE_WINDOW_API_MEDIA); 228 229 if (err != OK) { 230 LOGW("native_window_api_disconnect returned an error: %s (%d)", 231 strerror(-err), err); 232 } 233 } 234 mConnectedWindow.clear(); 235} 236 237status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface) 238{ 239 LOGV("setVideoSurface"); 240 Mutex::Autolock _l(mLock); 241 if (mPlayer == 0) return NO_INIT; 242 243 sp<IBinder> binder(surface == NULL ? NULL : surface->asBinder()); 244 if (mConnectedWindowBinder == binder) { 245 return OK; 246 } 247 248 if (surface != NULL) { 249 status_t err = native_window_api_connect(surface.get(), 250 NATIVE_WINDOW_API_MEDIA); 251 252 if (err != OK) { 253 LOGE("setVideoSurface failed: %d", err); 254 // Note that we must do the reset before disconnecting from the ANW. 255 // Otherwise queue/dequeue calls could be made on the disconnected 256 // ANW, which may result in errors. 257 reset_l(); 258 259 disconnectNativeWindow(); 260 261 return err; 262 } 263 } 264 265 // Note that we must set the player's new surface before disconnecting the 266 // old one. Otherwise queue/dequeue calls could be made on the disconnected 267 // ANW, which may result in errors. 268 status_t err = mPlayer->setVideoSurface(surface); 269 270 disconnectNativeWindow(); 271 272 mConnectedWindow = surface; 273 274 if (err == OK) { 275 mConnectedWindowBinder = binder; 276 } else { 277 disconnectNativeWindow(); 278 } 279 280 return err; 281} 282 283status_t MediaPlayer::setVideoSurfaceTexture( 284 const sp<ISurfaceTexture>& surfaceTexture) 285{ 286 LOGV("setVideoSurfaceTexture"); 287 Mutex::Autolock _l(mLock); 288 if (mPlayer == 0) return NO_INIT; 289 290 sp<IBinder> binder(surfaceTexture == NULL ? NULL : 291 surfaceTexture->asBinder()); 292 if (mConnectedWindowBinder == binder) { 293 return OK; 294 } 295 296 sp<ANativeWindow> anw; 297 if (surfaceTexture != NULL) { 298 anw = new SurfaceTextureClient(surfaceTexture); 299 status_t err = native_window_api_connect(anw.get(), 300 NATIVE_WINDOW_API_MEDIA); 301 302 if (err != OK) { 303 LOGE("setVideoSurfaceTexture failed: %d", err); 304 // Note that we must do the reset before disconnecting from the ANW. 305 // Otherwise queue/dequeue calls could be made on the disconnected 306 // ANW, which may result in errors. 307 reset_l(); 308 309 disconnectNativeWindow(); 310 311 return err; 312 } 313 } 314 315 // Note that we must set the player's new SurfaceTexture before 316 // disconnecting the old one. Otherwise queue/dequeue calls could be made 317 // on the disconnected ANW, which may result in errors. 318 status_t err = mPlayer->setVideoSurfaceTexture(surfaceTexture); 319 320 disconnectNativeWindow(); 321 322 mConnectedWindow = anw; 323 324 if (err == OK) { 325 mConnectedWindowBinder = binder; 326 } else { 327 disconnectNativeWindow(); 328 } 329 330 return err; 331} 332 333// must call with lock held 334status_t MediaPlayer::prepareAsync_l() 335{ 336 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) { 337 mPlayer->setAudioStreamType(mStreamType); 338 mCurrentState = MEDIA_PLAYER_PREPARING; 339 return mPlayer->prepareAsync(); 340 } 341 LOGE("prepareAsync called in state %d", mCurrentState); 342 return INVALID_OPERATION; 343} 344 345// TODO: In case of error, prepareAsync provides the caller with 2 error codes, 346// one defined in the Android framework and one provided by the implementation 347// that generated the error. The sync version of prepare returns only 1 error 348// code. 349status_t MediaPlayer::prepare() 350{ 351 LOGV("prepare"); 352 Mutex::Autolock _l(mLock); 353 mLockThreadId = getThreadId(); 354 if (mPrepareSync) { 355 mLockThreadId = 0; 356 return -EALREADY; 357 } 358 mPrepareSync = true; 359 status_t ret = prepareAsync_l(); 360 if (ret != NO_ERROR) { 361 mLockThreadId = 0; 362 return ret; 363 } 364 365 if (mPrepareSync) { 366 mSignal.wait(mLock); // wait for prepare done 367 mPrepareSync = false; 368 } 369 LOGV("prepare complete - status=%d", mPrepareStatus); 370 mLockThreadId = 0; 371 return mPrepareStatus; 372} 373 374status_t MediaPlayer::prepareAsync() 375{ 376 LOGV("prepareAsync"); 377 Mutex::Autolock _l(mLock); 378 return prepareAsync_l(); 379} 380 381status_t MediaPlayer::start() 382{ 383 LOGV("start"); 384 Mutex::Autolock _l(mLock); 385 if (mCurrentState & MEDIA_PLAYER_STARTED) 386 return NO_ERROR; 387 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED | 388 MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) { 389 mPlayer->setLooping(mLoop); 390 mPlayer->setVolume(mLeftVolume, mRightVolume); 391 mPlayer->setAuxEffectSendLevel(mSendLevel); 392 mCurrentState = MEDIA_PLAYER_STARTED; 393 status_t ret = mPlayer->start(); 394 if (ret != NO_ERROR) { 395 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 396 } else { 397 if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) { 398 LOGV("playback completed immediately following start()"); 399 } 400 } 401 return ret; 402 } 403 LOGE("start called in state %d", mCurrentState); 404 return INVALID_OPERATION; 405} 406 407status_t MediaPlayer::stop() 408{ 409 LOGV("stop"); 410 Mutex::Autolock _l(mLock); 411 if (mCurrentState & MEDIA_PLAYER_STOPPED) return NO_ERROR; 412 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | 413 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) ) { 414 status_t ret = mPlayer->stop(); 415 if (ret != NO_ERROR) { 416 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 417 } else { 418 mCurrentState = MEDIA_PLAYER_STOPPED; 419 } 420 return ret; 421 } 422 LOGE("stop called in state %d", mCurrentState); 423 return INVALID_OPERATION; 424} 425 426status_t MediaPlayer::pause() 427{ 428 LOGV("pause"); 429 Mutex::Autolock _l(mLock); 430 if (mCurrentState & (MEDIA_PLAYER_PAUSED|MEDIA_PLAYER_PLAYBACK_COMPLETE)) 431 return NO_ERROR; 432 if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER_STARTED)) { 433 status_t ret = mPlayer->pause(); 434 if (ret != NO_ERROR) { 435 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 436 } else { 437 mCurrentState = MEDIA_PLAYER_PAUSED; 438 } 439 return ret; 440 } 441 LOGE("pause called in state %d", mCurrentState); 442 return INVALID_OPERATION; 443} 444 445bool MediaPlayer::isPlaying() 446{ 447 Mutex::Autolock _l(mLock); 448 if (mPlayer != 0) { 449 bool temp = false; 450 mPlayer->isPlaying(&temp); 451 LOGV("isPlaying: %d", temp); 452 if ((mCurrentState & MEDIA_PLAYER_STARTED) && ! temp) { 453 LOGE("internal/external state mismatch corrected"); 454 mCurrentState = MEDIA_PLAYER_PAUSED; 455 } 456 return temp; 457 } 458 LOGV("isPlaying: no active player"); 459 return false; 460} 461 462status_t MediaPlayer::getVideoWidth(int *w) 463{ 464 LOGV("getVideoWidth"); 465 Mutex::Autolock _l(mLock); 466 if (mPlayer == 0) return INVALID_OPERATION; 467 *w = mVideoWidth; 468 return NO_ERROR; 469} 470 471status_t MediaPlayer::getVideoHeight(int *h) 472{ 473 LOGV("getVideoHeight"); 474 Mutex::Autolock _l(mLock); 475 if (mPlayer == 0) return INVALID_OPERATION; 476 *h = mVideoHeight; 477 return NO_ERROR; 478} 479 480status_t MediaPlayer::getCurrentPosition(int *msec) 481{ 482 LOGV("getCurrentPosition"); 483 Mutex::Autolock _l(mLock); 484 if (mPlayer != 0) { 485 if (mCurrentPosition >= 0) { 486 LOGV("Using cached seek position: %d", mCurrentPosition); 487 *msec = mCurrentPosition; 488 return NO_ERROR; 489 } 490 return mPlayer->getCurrentPosition(msec); 491 } 492 return INVALID_OPERATION; 493} 494 495status_t MediaPlayer::getDuration_l(int *msec) 496{ 497 LOGV("getDuration"); 498 bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE)); 499 if (mPlayer != 0 && isValidState) { 500 status_t ret = NO_ERROR; 501 if (mDuration <= 0) 502 ret = mPlayer->getDuration(&mDuration); 503 if (msec) 504 *msec = mDuration; 505 return ret; 506 } 507 LOGE("Attempt to call getDuration without a valid mediaplayer"); 508 return INVALID_OPERATION; 509} 510 511status_t MediaPlayer::getDuration(int *msec) 512{ 513 Mutex::Autolock _l(mLock); 514 return getDuration_l(msec); 515} 516 517status_t MediaPlayer::seekTo_l(int msec) 518{ 519 LOGV("seekTo %d", msec); 520 if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) { 521 if ( msec < 0 ) { 522 LOGW("Attempt to seek to invalid position: %d", msec); 523 msec = 0; 524 } else if ((mDuration > 0) && (msec > mDuration)) { 525 LOGW("Attempt to seek to past end of file: request = %d, EOF = %d", msec, mDuration); 526 msec = mDuration; 527 } 528 // cache duration 529 mCurrentPosition = msec; 530 if (mSeekPosition < 0) { 531 getDuration_l(NULL); 532 mSeekPosition = msec; 533 return mPlayer->seekTo(msec); 534 } 535 else { 536 LOGV("Seek in progress - queue up seekTo[%d]", msec); 537 return NO_ERROR; 538 } 539 } 540 LOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(), mCurrentState); 541 return INVALID_OPERATION; 542} 543 544status_t MediaPlayer::seekTo(int msec) 545{ 546 mLockThreadId = getThreadId(); 547 Mutex::Autolock _l(mLock); 548 status_t result = seekTo_l(msec); 549 mLockThreadId = 0; 550 551 return result; 552} 553 554status_t MediaPlayer::reset_l() 555{ 556 mLoop = false; 557 if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR; 558 mPrepareSync = false; 559 if (mPlayer != 0) { 560 status_t ret = mPlayer->reset(); 561 if (ret != NO_ERROR) { 562 LOGE("reset() failed with return code (%d)", ret); 563 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 564 } else { 565 mCurrentState = MEDIA_PLAYER_IDLE; 566 } 567 // setDataSource has to be called again to create a 568 // new mediaplayer. 569 mPlayer = 0; 570 return ret; 571 } 572 clear_l(); 573 return NO_ERROR; 574} 575 576status_t MediaPlayer::reset() 577{ 578 LOGV("reset"); 579 Mutex::Autolock _l(mLock); 580 return reset_l(); 581} 582 583status_t MediaPlayer::setAudioStreamType(int type) 584{ 585 LOGV("MediaPlayer::setAudioStreamType"); 586 Mutex::Autolock _l(mLock); 587 if (mStreamType == type) return NO_ERROR; 588 if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | 589 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) { 590 // Can't change the stream type after prepare 591 LOGE("setAudioStream called in state %d", mCurrentState); 592 return INVALID_OPERATION; 593 } 594 // cache 595 mStreamType = type; 596 return OK; 597} 598 599status_t MediaPlayer::setLooping(int loop) 600{ 601 LOGV("MediaPlayer::setLooping"); 602 Mutex::Autolock _l(mLock); 603 mLoop = (loop != 0); 604 if (mPlayer != 0) { 605 return mPlayer->setLooping(loop); 606 } 607 return OK; 608} 609 610bool MediaPlayer::isLooping() { 611 LOGV("isLooping"); 612 Mutex::Autolock _l(mLock); 613 if (mPlayer != 0) { 614 return mLoop; 615 } 616 LOGV("isLooping: no active player"); 617 return false; 618} 619 620status_t MediaPlayer::setVolume(float leftVolume, float rightVolume) 621{ 622 LOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume); 623 Mutex::Autolock _l(mLock); 624 mLeftVolume = leftVolume; 625 mRightVolume = rightVolume; 626 if (mPlayer != 0) { 627 return mPlayer->setVolume(leftVolume, rightVolume); 628 } 629 return OK; 630} 631 632status_t MediaPlayer::setAudioSessionId(int sessionId) 633{ 634 LOGV("MediaPlayer::setAudioSessionId(%d)", sessionId); 635 Mutex::Autolock _l(mLock); 636 if (!(mCurrentState & MEDIA_PLAYER_IDLE)) { 637 LOGE("setAudioSessionId called in state %d", mCurrentState); 638 return INVALID_OPERATION; 639 } 640 if (sessionId < 0) { 641 return BAD_VALUE; 642 } 643 if (sessionId != mAudioSessionId) { 644 AudioSystem::releaseAudioSessionId(mAudioSessionId); 645 AudioSystem::acquireAudioSessionId(sessionId); 646 mAudioSessionId = sessionId; 647 } 648 return NO_ERROR; 649} 650 651int MediaPlayer::getAudioSessionId() 652{ 653 Mutex::Autolock _l(mLock); 654 return mAudioSessionId; 655} 656 657status_t MediaPlayer::setAuxEffectSendLevel(float level) 658{ 659 LOGV("MediaPlayer::setAuxEffectSendLevel(%f)", level); 660 Mutex::Autolock _l(mLock); 661 mSendLevel = level; 662 if (mPlayer != 0) { 663 return mPlayer->setAuxEffectSendLevel(level); 664 } 665 return OK; 666} 667 668status_t MediaPlayer::attachAuxEffect(int effectId) 669{ 670 LOGV("MediaPlayer::attachAuxEffect(%d)", effectId); 671 Mutex::Autolock _l(mLock); 672 if (mPlayer == 0 || 673 (mCurrentState & MEDIA_PLAYER_IDLE) || 674 (mCurrentState == MEDIA_PLAYER_STATE_ERROR )) { 675 LOGE("attachAuxEffect called in state %d", mCurrentState); 676 return INVALID_OPERATION; 677 } 678 679 return mPlayer->attachAuxEffect(effectId); 680} 681 682status_t MediaPlayer::setParameter(int key, const Parcel& request) 683{ 684 LOGV("MediaPlayer::setParameter(%d)", key); 685 Mutex::Autolock _l(mLock); 686 if (mPlayer != NULL) { 687 return mPlayer->setParameter(key, request); 688 } 689 LOGV("setParameter: no active player"); 690 return INVALID_OPERATION; 691} 692 693status_t MediaPlayer::getParameter(int key, Parcel *reply) 694{ 695 LOGV("MediaPlayer::getParameter(%d)", key); 696 Mutex::Autolock _l(mLock); 697 if (mPlayer != NULL) { 698 return mPlayer->getParameter(key, reply); 699 } 700 LOGV("getParameter: no active player"); 701 return INVALID_OPERATION; 702} 703 704void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj) 705{ 706 LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2); 707 bool send = true; 708 bool locked = false; 709 710 // TODO: In the future, we might be on the same thread if the app is 711 // running in the same process as the media server. In that case, 712 // this will deadlock. 713 // 714 // The threadId hack below works around this for the care of prepare 715 // and seekTo within the same process. 716 // FIXME: Remember, this is a hack, it's not even a hack that is applied 717 // consistently for all use-cases, this needs to be revisited. 718 if (mLockThreadId != getThreadId()) { 719 mLock.lock(); 720 locked = true; 721 } 722 723 // Allows calls from JNI in idle state to notify errors 724 if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == 0) { 725 LOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2); 726 if (locked) mLock.unlock(); // release the lock when done. 727 return; 728 } 729 730 switch (msg) { 731 case MEDIA_NOP: // interface test message 732 break; 733 case MEDIA_PREPARED: 734 LOGV("prepared"); 735 mCurrentState = MEDIA_PLAYER_PREPARED; 736 if (mPrepareSync) { 737 LOGV("signal application thread"); 738 mPrepareSync = false; 739 mPrepareStatus = NO_ERROR; 740 mSignal.signal(); 741 } 742 break; 743 case MEDIA_PLAYBACK_COMPLETE: 744 LOGV("playback complete"); 745 if (mCurrentState == MEDIA_PLAYER_IDLE) { 746 LOGE("playback complete in idle state"); 747 } 748 if (!mLoop) { 749 mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE; 750 } 751 break; 752 case MEDIA_ERROR: 753 // Always log errors. 754 // ext1: Media framework error code. 755 // ext2: Implementation dependant error code. 756 LOGE("error (%d, %d)", ext1, ext2); 757 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 758 if (mPrepareSync) 759 { 760 LOGV("signal application thread"); 761 mPrepareSync = false; 762 mPrepareStatus = ext1; 763 mSignal.signal(); 764 send = false; 765 } 766 break; 767 case MEDIA_INFO: 768 // ext1: Media framework error code. 769 // ext2: Implementation dependant error code. 770 if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) { 771 LOGW("info/warning (%d, %d)", ext1, ext2); 772 } 773 break; 774 case MEDIA_SEEK_COMPLETE: 775 LOGV("Received seek complete"); 776 if (mSeekPosition != mCurrentPosition) { 777 LOGV("Executing queued seekTo(%d)", mSeekPosition); 778 mSeekPosition = -1; 779 seekTo_l(mCurrentPosition); 780 } 781 else { 782 LOGV("All seeks complete - return to regularly scheduled program"); 783 mCurrentPosition = mSeekPosition = -1; 784 } 785 break; 786 case MEDIA_BUFFERING_UPDATE: 787 LOGV("buffering %d", ext1); 788 break; 789 case MEDIA_SET_VIDEO_SIZE: 790 LOGV("New video size %d x %d", ext1, ext2); 791 mVideoWidth = ext1; 792 mVideoHeight = ext2; 793 break; 794 case MEDIA_TIMED_TEXT: 795 LOGV("Received timed text message"); 796 break; 797 default: 798 LOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2); 799 break; 800 } 801 802 sp<MediaPlayerListener> listener = mListener; 803 if (locked) mLock.unlock(); 804 805 // this prevents re-entrant calls into client code 806 if ((listener != 0) && send) { 807 Mutex::Autolock _l(mNotifyLock); 808 LOGV("callback application"); 809 listener->notify(msg, ext1, ext2, obj); 810 LOGV("back from callback"); 811 } 812} 813 814/*static*/ sp<IMemory> MediaPlayer::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) 815{ 816 LOGV("decode(%s)", url); 817 sp<IMemory> p; 818 const sp<IMediaPlayerService>& service = getMediaPlayerService(); 819 if (service != 0) { 820 p = service->decode(url, pSampleRate, pNumChannels, pFormat); 821 } else { 822 LOGE("Unable to locate media service"); 823 } 824 return p; 825 826} 827 828void MediaPlayer::died() 829{ 830 LOGV("died"); 831 notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0); 832} 833 834/*static*/ sp<IMemory> MediaPlayer::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) 835{ 836 LOGV("decode(%d, %lld, %lld)", fd, offset, length); 837 sp<IMemory> p; 838 const sp<IMediaPlayerService>& service = getMediaPlayerService(); 839 if (service != 0) { 840 p = service->decode(fd, offset, length, pSampleRate, pNumChannels, pFormat); 841 } else { 842 LOGE("Unable to locate media service"); 843 } 844 return p; 845 846} 847 848}; // namespace android 849