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