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