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