mediaplayer.cpp revision 7dae00baa6e8957be15523c46bb948bd1dde64c3
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 45namespace android { 46 47MediaPlayer::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 68MediaPlayer::~MediaPlayer() 69{ 70 LOGV("destructor"); 71 AudioSystem::releaseAudioSessionId(mAudioSessionId); 72 disconnect(); 73 IPCThreadState::self()->flushCommands(); 74} 75 76void 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 92void MediaPlayer::clear_l() 93{ 94 mDuration = -1; 95 mCurrentPosition = -1; 96 mSeekPosition = -1; 97 mVideoWidth = mVideoHeight = 0; 98} 99 100status_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 109status_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 140status_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 158status_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 173status_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 188status_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 202status_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 212status_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 222status_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 230status_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 240status_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. 255status_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 280status_t MediaPlayer::prepareAsync() 281{ 282 LOGV("prepareAsync"); 283 Mutex::Autolock _l(mLock); 284 return prepareAsync_l(); 285} 286 287status_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 313status_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 332status_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 351bool 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 368status_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 377status_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 386status_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 401status_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 417status_t MediaPlayer::getDuration(int *msec) 418{ 419 Mutex::Autolock _l(mLock); 420 return getDuration_l(msec); 421} 422 423status_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 450status_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 460status_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 482status_t MediaPlayer::reset() 483{ 484 LOGV("reset"); 485 Mutex::Autolock _l(mLock); 486 return reset_l(); 487} 488 489status_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 505status_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 516bool 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 526status_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 538status_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 557int MediaPlayer::getAudioSessionId() 558{ 559 Mutex::Autolock _l(mLock); 560 return mAudioSessionId; 561} 562 563status_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 574status_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 588status_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 599status_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 610void 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 734void 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