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