mediaplayer.cpp revision de9453fb5cbc9cd69fd1ea45d577851e3aa3b8c9
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, -1); 62 mSendLevel = 0; 63 mRetransmitEndpointValid = false; 64} 65 66MediaPlayer::~MediaPlayer() 67{ 68 ALOGV("destructor"); 69 AudioSystem::releaseAudioSessionId(mAudioSessionId, -1); 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::getAudioStreamType(audio_stream_type_t *type) 535{ 536 ALOGV("getAudioStreamType"); 537 Mutex::Autolock _l(mLock); 538 *type = mStreamType; 539 return OK; 540} 541 542status_t MediaPlayer::setLooping(int loop) 543{ 544 ALOGV("MediaPlayer::setLooping"); 545 Mutex::Autolock _l(mLock); 546 mLoop = (loop != 0); 547 if (mPlayer != 0) { 548 return mPlayer->setLooping(loop); 549 } 550 return OK; 551} 552 553bool MediaPlayer::isLooping() { 554 ALOGV("isLooping"); 555 Mutex::Autolock _l(mLock); 556 if (mPlayer != 0) { 557 return mLoop; 558 } 559 ALOGV("isLooping: no active player"); 560 return false; 561} 562 563status_t MediaPlayer::setVolume(float leftVolume, float rightVolume) 564{ 565 ALOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume); 566 Mutex::Autolock _l(mLock); 567 mLeftVolume = leftVolume; 568 mRightVolume = rightVolume; 569 if (mPlayer != 0) { 570 return mPlayer->setVolume(leftVolume, rightVolume); 571 } 572 return OK; 573} 574 575status_t MediaPlayer::setAudioSessionId(int sessionId) 576{ 577 ALOGV("MediaPlayer::setAudioSessionId(%d)", sessionId); 578 Mutex::Autolock _l(mLock); 579 if (!(mCurrentState & MEDIA_PLAYER_IDLE)) { 580 ALOGE("setAudioSessionId called in state %d", mCurrentState); 581 return INVALID_OPERATION; 582 } 583 if (sessionId < 0) { 584 return BAD_VALUE; 585 } 586 if (sessionId != mAudioSessionId) { 587 AudioSystem::acquireAudioSessionId(sessionId, -1); 588 AudioSystem::releaseAudioSessionId(mAudioSessionId, -1); 589 mAudioSessionId = sessionId; 590 } 591 return NO_ERROR; 592} 593 594int MediaPlayer::getAudioSessionId() 595{ 596 Mutex::Autolock _l(mLock); 597 return mAudioSessionId; 598} 599 600status_t MediaPlayer::setAuxEffectSendLevel(float level) 601{ 602 ALOGV("MediaPlayer::setAuxEffectSendLevel(%f)", level); 603 Mutex::Autolock _l(mLock); 604 mSendLevel = level; 605 if (mPlayer != 0) { 606 return mPlayer->setAuxEffectSendLevel(level); 607 } 608 return OK; 609} 610 611status_t MediaPlayer::attachAuxEffect(int effectId) 612{ 613 ALOGV("MediaPlayer::attachAuxEffect(%d)", effectId); 614 Mutex::Autolock _l(mLock); 615 if (mPlayer == 0 || 616 (mCurrentState & MEDIA_PLAYER_IDLE) || 617 (mCurrentState == MEDIA_PLAYER_STATE_ERROR )) { 618 ALOGE("attachAuxEffect called in state %d", mCurrentState); 619 return INVALID_OPERATION; 620 } 621 622 return mPlayer->attachAuxEffect(effectId); 623} 624 625status_t MediaPlayer::setParameter(int key, const Parcel& request) 626{ 627 ALOGV("MediaPlayer::setParameter(%d)", key); 628 Mutex::Autolock _l(mLock); 629 if (mPlayer != NULL) { 630 return mPlayer->setParameter(key, request); 631 } 632 ALOGV("setParameter: no active player"); 633 return INVALID_OPERATION; 634} 635 636status_t MediaPlayer::getParameter(int key, Parcel *reply) 637{ 638 ALOGV("MediaPlayer::getParameter(%d)", key); 639 Mutex::Autolock _l(mLock); 640 if (mPlayer != NULL) { 641 return mPlayer->getParameter(key, reply); 642 } 643 ALOGV("getParameter: no active player"); 644 return INVALID_OPERATION; 645} 646 647status_t MediaPlayer::setRetransmitEndpoint(const char* addrString, 648 uint16_t port) { 649 ALOGV("MediaPlayer::setRetransmitEndpoint(%s:%hu)", 650 addrString ? addrString : "(null)", port); 651 652 Mutex::Autolock _l(mLock); 653 if ((mPlayer != NULL) || (mCurrentState != MEDIA_PLAYER_IDLE)) 654 return INVALID_OPERATION; 655 656 if (NULL == addrString) { 657 mRetransmitEndpointValid = false; 658 return OK; 659 } 660 661 struct in_addr saddr; 662 if(!inet_aton(addrString, &saddr)) { 663 return BAD_VALUE; 664 } 665 666 memset(&mRetransmitEndpoint, 0, sizeof(mRetransmitEndpoint)); 667 mRetransmitEndpoint.sin_family = AF_INET; 668 mRetransmitEndpoint.sin_addr = saddr; 669 mRetransmitEndpoint.sin_port = htons(port); 670 mRetransmitEndpointValid = true; 671 672 return OK; 673} 674 675void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj) 676{ 677 ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2); 678 bool send = true; 679 bool locked = false; 680 681 // TODO: In the future, we might be on the same thread if the app is 682 // running in the same process as the media server. In that case, 683 // this will deadlock. 684 // 685 // The threadId hack below works around this for the care of prepare 686 // and seekTo within the same process. 687 // FIXME: Remember, this is a hack, it's not even a hack that is applied 688 // consistently for all use-cases, this needs to be revisited. 689 if (mLockThreadId != getThreadId()) { 690 mLock.lock(); 691 locked = true; 692 } 693 694 // Allows calls from JNI in idle state to notify errors 695 if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == 0) { 696 ALOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2); 697 if (locked) mLock.unlock(); // release the lock when done. 698 return; 699 } 700 701 switch (msg) { 702 case MEDIA_NOP: // interface test message 703 break; 704 case MEDIA_PREPARED: 705 ALOGV("prepared"); 706 mCurrentState = MEDIA_PLAYER_PREPARED; 707 if (mPrepareSync) { 708 ALOGV("signal application thread"); 709 mPrepareSync = false; 710 mPrepareStatus = NO_ERROR; 711 mSignal.signal(); 712 } 713 break; 714 case MEDIA_PLAYBACK_COMPLETE: 715 ALOGV("playback complete"); 716 if (mCurrentState == MEDIA_PLAYER_IDLE) { 717 ALOGE("playback complete in idle state"); 718 } 719 if (!mLoop) { 720 mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE; 721 } 722 break; 723 case MEDIA_ERROR: 724 // Always log errors. 725 // ext1: Media framework error code. 726 // ext2: Implementation dependant error code. 727 ALOGE("error (%d, %d)", ext1, ext2); 728 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 729 if (mPrepareSync) 730 { 731 ALOGV("signal application thread"); 732 mPrepareSync = false; 733 mPrepareStatus = ext1; 734 mSignal.signal(); 735 send = false; 736 } 737 break; 738 case MEDIA_INFO: 739 // ext1: Media framework error code. 740 // ext2: Implementation dependant error code. 741 if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) { 742 ALOGW("info/warning (%d, %d)", ext1, ext2); 743 } 744 break; 745 case MEDIA_SEEK_COMPLETE: 746 ALOGV("Received seek complete"); 747 if (mSeekPosition != mCurrentPosition) { 748 ALOGV("Executing queued seekTo(%d)", mSeekPosition); 749 mSeekPosition = -1; 750 seekTo_l(mCurrentPosition); 751 } 752 else { 753 ALOGV("All seeks complete - return to regularly scheduled program"); 754 mCurrentPosition = mSeekPosition = -1; 755 } 756 break; 757 case MEDIA_BUFFERING_UPDATE: 758 ALOGV("buffering %d", ext1); 759 break; 760 case MEDIA_SET_VIDEO_SIZE: 761 ALOGV("New video size %d x %d", ext1, ext2); 762 mVideoWidth = ext1; 763 mVideoHeight = ext2; 764 break; 765 case MEDIA_TIMED_TEXT: 766 ALOGV("Received timed text message"); 767 break; 768 case MEDIA_SUBTITLE_DATA: 769 ALOGV("Received subtitle data message"); 770 break; 771 default: 772 ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2); 773 break; 774 } 775 776 sp<MediaPlayerListener> listener = mListener; 777 if (locked) mLock.unlock(); 778 779 // this prevents re-entrant calls into client code 780 if ((listener != 0) && send) { 781 Mutex::Autolock _l(mNotifyLock); 782 ALOGV("callback application"); 783 listener->notify(msg, ext1, ext2, obj); 784 ALOGV("back from callback"); 785 } 786} 787 788/*static*/ status_t MediaPlayer::decode( 789 const sp<IMediaHTTPService> &httpService, 790 const char* url, 791 uint32_t *pSampleRate, 792 int* pNumChannels, 793 audio_format_t* pFormat, 794 const sp<IMemoryHeap>& heap, 795 size_t *pSize) 796{ 797 ALOGV("decode(%s)", url); 798 status_t status; 799 const sp<IMediaPlayerService>& service = getMediaPlayerService(); 800 if (service != 0) { 801 status = service->decode(httpService, url, pSampleRate, pNumChannels, pFormat, heap, pSize); 802 } else { 803 ALOGE("Unable to locate media service"); 804 status = DEAD_OBJECT; 805 } 806 return status; 807 808} 809 810void MediaPlayer::died() 811{ 812 ALOGV("died"); 813 notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0); 814} 815 816/*static*/ status_t MediaPlayer::decode(int fd, int64_t offset, int64_t length, 817 uint32_t *pSampleRate, int* pNumChannels, 818 audio_format_t* pFormat, 819 const sp<IMemoryHeap>& heap, size_t *pSize) 820{ 821 ALOGV("decode(%d, %lld, %lld)", fd, offset, length); 822 status_t status; 823 const sp<IMediaPlayerService>& service = getMediaPlayerService(); 824 if (service != 0) { 825 status = service->decode(fd, offset, length, pSampleRate, 826 pNumChannels, pFormat, heap, pSize); 827 } else { 828 ALOGE("Unable to locate media service"); 829 status = DEAD_OBJECT; 830 } 831 return status; 832 833} 834 835status_t MediaPlayer::setNextMediaPlayer(const sp<MediaPlayer>& next) { 836 if (mPlayer == NULL) { 837 return NO_INIT; 838 } 839 840 if (next != NULL && !(next->mCurrentState & 841 (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE))) { 842 ALOGE("next player is not prepared"); 843 return INVALID_OPERATION; 844 } 845 846 return mPlayer->setNextPlayer(next == NULL ? NULL : next->mPlayer); 847} 848 849}; // namespace android 850