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