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::setVideoSurface(const sp<Surface>& surface) 223 { 224 LOGV("setVideoSurface"); 225 Mutex::Autolock _l(mLock); 226 if (mPlayer == 0) return NO_INIT; 227 return mPlayer->setVideoSurface(surface); 228 } 229 230 status_t MediaPlayer::setVideoSurfaceTexture( 231 const sp<ISurfaceTexture>& surfaceTexture) 232 { 233 LOGV("setVideoSurfaceTexture"); 234 Mutex::Autolock _l(mLock); 235 if (mPlayer == 0) return NO_INIT; 236 return mPlayer->setVideoSurfaceTexture(surfaceTexture); 237 } 238 239 // must call with lock held 240 status_t MediaPlayer::prepareAsync_l() 241 { 242 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) { 243 mPlayer->setAudioStreamType(mStreamType); 244 mCurrentState = MEDIA_PLAYER_PREPARING; 245 return mPlayer->prepareAsync(); 246 } 247 LOGE("prepareAsync called in state %d", mCurrentState); 248 return INVALID_OPERATION; 249 } 250 251 // TODO: In case of error, prepareAsync provides the caller with 2 error codes, 252 // one defined in the Android framework and one provided by the implementation 253 // that generated the error. The sync version of prepare returns only 1 error 254 // code. 255 status_t MediaPlayer::prepare() 256 { 257 LOGV("prepare"); 258 Mutex::Autolock _l(mLock); 259 mLockThreadId = getThreadId(); 260 if (mPrepareSync) { 261 mLockThreadId = 0; 262 return -EALREADY; 263 } 264 mPrepareSync = true; 265 status_t ret = prepareAsync_l(); 266 if (ret != NO_ERROR) { 267 mLockThreadId = 0; 268 return ret; 269 } 270 271 if (mPrepareSync) { 272 mSignal.wait(mLock); // wait for prepare done 273 mPrepareSync = false; 274 } 275 LOGV("prepare complete - status=%d", mPrepareStatus); 276 mLockThreadId = 0; 277 return mPrepareStatus; 278 } 279 280 status_t MediaPlayer::prepareAsync() 281 { 282 LOGV("prepareAsync"); 283 Mutex::Autolock _l(mLock); 284 return prepareAsync_l(); 285 } 286 287 status_t MediaPlayer::start() 288 { 289 LOGV("start"); 290 Mutex::Autolock _l(mLock); 291 if (mCurrentState & MEDIA_PLAYER_STARTED) 292 return NO_ERROR; 293 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED | 294 MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) { 295 mPlayer->setLooping(mLoop); 296 mPlayer->setVolume(mLeftVolume, mRightVolume); 297 mPlayer->setAuxEffectSendLevel(mSendLevel); 298 mCurrentState = MEDIA_PLAYER_STARTED; 299 status_t ret = mPlayer->start(); 300 if (ret != NO_ERROR) { 301 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 302 } else { 303 if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) { 304 LOGV("playback completed immediately following start()"); 305 } 306 } 307 return ret; 308 } 309 LOGE("start called in state %d", mCurrentState); 310 return INVALID_OPERATION; 311 } 312 313 status_t MediaPlayer::stop() 314 { 315 LOGV("stop"); 316 Mutex::Autolock _l(mLock); 317 if (mCurrentState & MEDIA_PLAYER_STOPPED) return NO_ERROR; 318 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | 319 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) ) { 320 status_t ret = mPlayer->stop(); 321 if (ret != NO_ERROR) { 322 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 323 } else { 324 mCurrentState = MEDIA_PLAYER_STOPPED; 325 } 326 return ret; 327 } 328 LOGE("stop called in state %d", mCurrentState); 329 return INVALID_OPERATION; 330 } 331 332 status_t MediaPlayer::pause() 333 { 334 LOGV("pause"); 335 Mutex::Autolock _l(mLock); 336 if (mCurrentState & (MEDIA_PLAYER_PAUSED|MEDIA_PLAYER_PLAYBACK_COMPLETE)) 337 return NO_ERROR; 338 if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER_STARTED)) { 339 status_t ret = mPlayer->pause(); 340 if (ret != NO_ERROR) { 341 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 342 } else { 343 mCurrentState = MEDIA_PLAYER_PAUSED; 344 } 345 return ret; 346 } 347 LOGE("pause called in state %d", mCurrentState); 348 return INVALID_OPERATION; 349 } 350 351 bool MediaPlayer::isPlaying() 352 { 353 Mutex::Autolock _l(mLock); 354 if (mPlayer != 0) { 355 bool temp = false; 356 mPlayer->isPlaying(&temp); 357 LOGV("isPlaying: %d", temp); 358 if ((mCurrentState & MEDIA_PLAYER_STARTED) && ! temp) { 359 LOGE("internal/external state mismatch corrected"); 360 mCurrentState = MEDIA_PLAYER_PAUSED; 361 } 362 return temp; 363 } 364 LOGV("isPlaying: no active player"); 365 return false; 366 } 367 368 status_t MediaPlayer::getVideoWidth(int *w) 369 { 370 LOGV("getVideoWidth"); 371 Mutex::Autolock _l(mLock); 372 if (mPlayer == 0) return INVALID_OPERATION; 373 *w = mVideoWidth; 374 return NO_ERROR; 375 } 376 377 status_t MediaPlayer::getVideoHeight(int *h) 378 { 379 LOGV("getVideoHeight"); 380 Mutex::Autolock _l(mLock); 381 if (mPlayer == 0) return INVALID_OPERATION; 382 *h = mVideoHeight; 383 return NO_ERROR; 384 } 385 386 status_t MediaPlayer::getCurrentPosition(int *msec) 387 { 388 LOGV("getCurrentPosition"); 389 Mutex::Autolock _l(mLock); 390 if (mPlayer != 0) { 391 if (mCurrentPosition >= 0) { 392 LOGV("Using cached seek position: %d", mCurrentPosition); 393 *msec = mCurrentPosition; 394 return NO_ERROR; 395 } 396 return mPlayer->getCurrentPosition(msec); 397 } 398 return INVALID_OPERATION; 399 } 400 401 status_t MediaPlayer::getDuration_l(int *msec) 402 { 403 LOGV("getDuration"); 404 bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE)); 405 if (mPlayer != 0 && isValidState) { 406 status_t ret = NO_ERROR; 407 if (mDuration <= 0) 408 ret = mPlayer->getDuration(&mDuration); 409 if (msec) 410 *msec = mDuration; 411 return ret; 412 } 413 LOGE("Attempt to call getDuration without a valid mediaplayer"); 414 return INVALID_OPERATION; 415 } 416 417 status_t MediaPlayer::getDuration(int *msec) 418 { 419 Mutex::Autolock _l(mLock); 420 return getDuration_l(msec); 421 } 422 423 status_t MediaPlayer::seekTo_l(int msec) 424 { 425 LOGV("seekTo %d", msec); 426 if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) { 427 if ( msec < 0 ) { 428 LOGW("Attempt to seek to invalid position: %d", msec); 429 msec = 0; 430 } else if ((mDuration > 0) && (msec > mDuration)) { 431 LOGW("Attempt to seek to past end of file: request = %d, EOF = %d", msec, mDuration); 432 msec = mDuration; 433 } 434 // cache duration 435 mCurrentPosition = msec; 436 if (mSeekPosition < 0) { 437 getDuration_l(NULL); 438 mSeekPosition = msec; 439 return mPlayer->seekTo(msec); 440 } 441 else { 442 LOGV("Seek in progress - queue up seekTo[%d]", msec); 443 return NO_ERROR; 444 } 445 } 446 LOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(), mCurrentState); 447 return INVALID_OPERATION; 448 } 449 450 status_t MediaPlayer::seekTo(int msec) 451 { 452 mLockThreadId = getThreadId(); 453 Mutex::Autolock _l(mLock); 454 status_t result = seekTo_l(msec); 455 mLockThreadId = 0; 456 457 return result; 458 } 459 460 status_t MediaPlayer::reset_l() 461 { 462 mLoop = false; 463 if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR; 464 mPrepareSync = false; 465 if (mPlayer != 0) { 466 status_t ret = mPlayer->reset(); 467 if (ret != NO_ERROR) { 468 LOGE("reset() failed with return code (%d)", ret); 469 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 470 } else { 471 mCurrentState = MEDIA_PLAYER_IDLE; 472 } 473 // setDataSource has to be called again to create a 474 // new mediaplayer. 475 mPlayer = 0; 476 return ret; 477 } 478 clear_l(); 479 return NO_ERROR; 480 } 481 482 status_t MediaPlayer::reset() 483 { 484 LOGV("reset"); 485 Mutex::Autolock _l(mLock); 486 return reset_l(); 487 } 488 489 status_t MediaPlayer::setAudioStreamType(int type) 490 { 491 LOGV("MediaPlayer::setAudioStreamType"); 492 Mutex::Autolock _l(mLock); 493 if (mStreamType == type) return NO_ERROR; 494 if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | 495 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) { 496 // Can't change the stream type after prepare 497 LOGE("setAudioStream called in state %d", mCurrentState); 498 return INVALID_OPERATION; 499 } 500 // cache 501 mStreamType = type; 502 return OK; 503 } 504 505 status_t MediaPlayer::setLooping(int loop) 506 { 507 LOGV("MediaPlayer::setLooping"); 508 Mutex::Autolock _l(mLock); 509 mLoop = (loop != 0); 510 if (mPlayer != 0) { 511 return mPlayer->setLooping(loop); 512 } 513 return OK; 514 } 515 516 bool MediaPlayer::isLooping() { 517 LOGV("isLooping"); 518 Mutex::Autolock _l(mLock); 519 if (mPlayer != 0) { 520 return mLoop; 521 } 522 LOGV("isLooping: no active player"); 523 return false; 524 } 525 526 status_t MediaPlayer::setVolume(float leftVolume, float rightVolume) 527 { 528 LOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume); 529 Mutex::Autolock _l(mLock); 530 mLeftVolume = leftVolume; 531 mRightVolume = rightVolume; 532 if (mPlayer != 0) { 533 return mPlayer->setVolume(leftVolume, rightVolume); 534 } 535 return OK; 536 } 537 538 status_t MediaPlayer::setAudioSessionId(int sessionId) 539 { 540 LOGV("MediaPlayer::setAudioSessionId(%d)", sessionId); 541 Mutex::Autolock _l(mLock); 542 if (!(mCurrentState & MEDIA_PLAYER_IDLE)) { 543 LOGE("setAudioSessionId called in state %d", mCurrentState); 544 return INVALID_OPERATION; 545 } 546 if (sessionId < 0) { 547 return BAD_VALUE; 548 } 549 if (sessionId != mAudioSessionId) { 550 AudioSystem::releaseAudioSessionId(mAudioSessionId); 551 AudioSystem::acquireAudioSessionId(sessionId); 552 mAudioSessionId = sessionId; 553 } 554 return NO_ERROR; 555 } 556 557 int MediaPlayer::getAudioSessionId() 558 { 559 Mutex::Autolock _l(mLock); 560 return mAudioSessionId; 561 } 562 563 status_t MediaPlayer::setAuxEffectSendLevel(float level) 564 { 565 LOGV("MediaPlayer::setAuxEffectSendLevel(%f)", level); 566 Mutex::Autolock _l(mLock); 567 mSendLevel = level; 568 if (mPlayer != 0) { 569 return mPlayer->setAuxEffectSendLevel(level); 570 } 571 return OK; 572 } 573 574 status_t MediaPlayer::attachAuxEffect(int effectId) 575 { 576 LOGV("MediaPlayer::attachAuxEffect(%d)", effectId); 577 Mutex::Autolock _l(mLock); 578 if (mPlayer == 0 || 579 (mCurrentState & MEDIA_PLAYER_IDLE) || 580 (mCurrentState == MEDIA_PLAYER_STATE_ERROR )) { 581 LOGE("attachAuxEffect called in state %d", mCurrentState); 582 return INVALID_OPERATION; 583 } 584 585 return mPlayer->attachAuxEffect(effectId); 586 } 587 588 status_t MediaPlayer::setParameter(int key, const Parcel& request) 589 { 590 LOGV("MediaPlayer::setParameter(%d)", key); 591 Mutex::Autolock _l(mLock); 592 if (mPlayer != NULL) { 593 return mPlayer->setParameter(key, request); 594 } 595 LOGV("setParameter: no active player"); 596 return INVALID_OPERATION; 597 } 598 599 status_t MediaPlayer::getParameter(int key, Parcel *reply) 600 { 601 LOGV("MediaPlayer::getParameter(%d)", key); 602 Mutex::Autolock _l(mLock); 603 if (mPlayer != NULL) { 604 return mPlayer->getParameter(key, reply); 605 } 606 LOGV("getParameter: no active player"); 607 return INVALID_OPERATION; 608 } 609 610 void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj) 611 { 612 LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2); 613 bool send = true; 614 bool locked = false; 615 616 // TODO: In the future, we might be on the same thread if the app is 617 // running in the same process as the media server. In that case, 618 // this will deadlock. 619 // 620 // The threadId hack below works around this for the care of prepare 621 // and seekTo within the same process. 622 // FIXME: Remember, this is a hack, it's not even a hack that is applied 623 // consistently for all use-cases, this needs to be revisited. 624 if (mLockThreadId != getThreadId()) { 625 mLock.lock(); 626 locked = true; 627 } 628 629 // Allows calls from JNI in idle state to notify errors 630 if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == 0) { 631 LOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2); 632 if (locked) mLock.unlock(); // release the lock when done. 633 return; 634 } 635 636 switch (msg) { 637 case MEDIA_NOP: // interface test message 638 break; 639 case MEDIA_PREPARED: 640 LOGV("prepared"); 641 mCurrentState = MEDIA_PLAYER_PREPARED; 642 if (mPrepareSync) { 643 LOGV("signal application thread"); 644 mPrepareSync = false; 645 mPrepareStatus = NO_ERROR; 646 mSignal.signal(); 647 } 648 break; 649 case MEDIA_PLAYBACK_COMPLETE: 650 LOGV("playback complete"); 651 if (mCurrentState == MEDIA_PLAYER_IDLE) { 652 LOGE("playback complete in idle state"); 653 } 654 if (!mLoop) { 655 mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE; 656 } 657 break; 658 case MEDIA_ERROR: 659 // Always log errors. 660 // ext1: Media framework error code. 661 // ext2: Implementation dependant error code. 662 LOGE("error (%d, %d)", ext1, ext2); 663 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 664 if (mPrepareSync) 665 { 666 LOGV("signal application thread"); 667 mPrepareSync = false; 668 mPrepareStatus = ext1; 669 mSignal.signal(); 670 send = false; 671 } 672 break; 673 case MEDIA_INFO: 674 // ext1: Media framework error code. 675 // ext2: Implementation dependant error code. 676 if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) { 677 LOGW("info/warning (%d, %d)", ext1, ext2); 678 } 679 break; 680 case MEDIA_SEEK_COMPLETE: 681 LOGV("Received seek complete"); 682 if (mSeekPosition != mCurrentPosition) { 683 LOGV("Executing queued seekTo(%d)", mSeekPosition); 684 mSeekPosition = -1; 685 seekTo_l(mCurrentPosition); 686 } 687 else { 688 LOGV("All seeks complete - return to regularly scheduled program"); 689 mCurrentPosition = mSeekPosition = -1; 690 } 691 break; 692 case MEDIA_BUFFERING_UPDATE: 693 LOGV("buffering %d", ext1); 694 break; 695 case MEDIA_SET_VIDEO_SIZE: 696 LOGV("New video size %d x %d", ext1, ext2); 697 mVideoWidth = ext1; 698 mVideoHeight = ext2; 699 break; 700 case MEDIA_TIMED_TEXT: 701 LOGV("Received timed text message"); 702 break; 703 default: 704 LOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2); 705 break; 706 } 707 708 sp<MediaPlayerListener> listener = mListener; 709 if (locked) mLock.unlock(); 710 711 // this prevents re-entrant calls into client code 712 if ((listener != 0) && send) { 713 Mutex::Autolock _l(mNotifyLock); 714 LOGV("callback application"); 715 listener->notify(msg, ext1, ext2, obj); 716 LOGV("back from callback"); 717 } 718 } 719 720 /*static*/ sp<IMemory> MediaPlayer::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) 721 { 722 LOGV("decode(%s)", url); 723 sp<IMemory> p; 724 const sp<IMediaPlayerService>& service = getMediaPlayerService(); 725 if (service != 0) { 726 p = service->decode(url, pSampleRate, pNumChannels, pFormat); 727 } else { 728 LOGE("Unable to locate media service"); 729 } 730 return p; 731 732 } 733 734 void MediaPlayer::died() 735 { 736 LOGV("died"); 737 notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0); 738 } 739 740 /*static*/ sp<IMemory> MediaPlayer::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) 741 { 742 LOGV("decode(%d, %lld, %lld)", fd, offset, length); 743 sp<IMemory> p; 744 const sp<IMediaPlayerService>& service = getMediaPlayerService(); 745 if (service != 0) { 746 p = service->decode(fd, offset, length, pSampleRate, pNumChannels, pFormat); 747 } else { 748 LOGE("Unable to locate media service"); 749 } 750 return p; 751 752 } 753 754 }; // namespace android 755