mediaplayer.cpp revision fc908d010b32bbb850a6306893ce7db166a932f6
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 21#include <fcntl.h> 22#include <inttypes.h> 23#include <sys/stat.h> 24#include <sys/types.h> 25#include <unistd.h> 26 27#include <utils/Log.h> 28 29#include <binder/IServiceManager.h> 30#include <binder/IPCThreadState.h> 31 32#include <gui/Surface.h> 33 34#include <media/mediaplayer.h> 35#include <media/AudioResamplerPublic.h> 36#include <media/AudioSystem.h> 37#include <media/AVSyncSettings.h> 38#include <media/IDataSource.h> 39 40#include <binder/MemoryBase.h> 41 42#include <utils/KeyedVector.h> 43#include <utils/String8.h> 44 45#include <system/audio.h> 46#include <system/window.h> 47 48namespace android { 49 50MediaPlayer::MediaPlayer() 51{ 52 ALOGV("constructor"); 53 mListener = NULL; 54 mCookie = NULL; 55 mStreamType = AUDIO_STREAM_MUSIC; 56 mAudioAttributesParcel = NULL; 57 mCurrentPosition = -1; 58 mSeekPosition = -1; 59 mCurrentState = MEDIA_PLAYER_IDLE; 60 mPrepareSync = false; 61 mPrepareStatus = NO_ERROR; 62 mLoop = false; 63 mLeftVolume = mRightVolume = 1.0; 64 mVideoWidth = mVideoHeight = 0; 65 mLockThreadId = 0; 66 mAudioSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION); 67 AudioSystem::acquireAudioSessionId(mAudioSessionId, -1); 68 mSendLevel = 0; 69 mRetransmitEndpointValid = false; 70} 71 72MediaPlayer::~MediaPlayer() 73{ 74 ALOGV("destructor"); 75 if (mAudioAttributesParcel != NULL) { 76 delete mAudioAttributesParcel; 77 mAudioAttributesParcel = NULL; 78 } 79 AudioSystem::releaseAudioSessionId(mAudioSessionId, -1); 80 disconnect(); 81 IPCThreadState::self()->flushCommands(); 82} 83 84void MediaPlayer::disconnect() 85{ 86 ALOGV("disconnect"); 87 sp<IMediaPlayer> p; 88 { 89 Mutex::Autolock _l(mLock); 90 p = mPlayer; 91 mPlayer.clear(); 92 } 93 94 if (p != 0) { 95 p->disconnect(); 96 } 97} 98 99// always call with lock held 100void MediaPlayer::clear_l() 101{ 102 mCurrentPosition = -1; 103 mSeekPosition = -1; 104 mVideoWidth = mVideoHeight = 0; 105 mRetransmitEndpointValid = false; 106} 107 108status_t MediaPlayer::setListener(const sp<MediaPlayerListener>& listener) 109{ 110 ALOGV("setListener"); 111 Mutex::Autolock _l(mLock); 112 mListener = listener; 113 return NO_ERROR; 114} 115 116 117status_t MediaPlayer::attachNewPlayer(const sp<IMediaPlayer>& player) 118{ 119 status_t err = UNKNOWN_ERROR; 120 sp<IMediaPlayer> p; 121 { // scope for the lock 122 Mutex::Autolock _l(mLock); 123 124 if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) || 125 (mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) { 126 ALOGE("attachNewPlayer called in state %d", mCurrentState); 127 return INVALID_OPERATION; 128 } 129 130 clear_l(); 131 p = mPlayer; 132 mPlayer = player; 133 if (player != 0) { 134 mCurrentState = MEDIA_PLAYER_INITIALIZED; 135 err = NO_ERROR; 136 } else { 137 ALOGE("Unable to create media player"); 138 } 139 } 140 141 if (p != 0) { 142 p->disconnect(); 143 } 144 145 return err; 146} 147 148status_t MediaPlayer::setDataSource( 149 const sp<IMediaHTTPService> &httpService, 150 const char *url, const KeyedVector<String8, String8> *headers) 151{ 152 ALOGV("setDataSource(%s)", url); 153 status_t err = BAD_VALUE; 154 if (url != NULL) { 155 const sp<IMediaPlayerService> service(getMediaPlayerService()); 156 if (service != 0) { 157 sp<IMediaPlayer> player(service->create(this, mAudioSessionId)); 158 if ((NO_ERROR != doSetRetransmitEndpoint(player)) || 159 (NO_ERROR != player->setDataSource(httpService, url, headers))) { 160 player.clear(); 161 } 162 err = attachNewPlayer(player); 163 } 164 } 165 return err; 166} 167 168status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length) 169{ 170 ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length); 171 status_t err = UNKNOWN_ERROR; 172 const sp<IMediaPlayerService> service(getMediaPlayerService()); 173 if (service != 0) { 174 sp<IMediaPlayer> player(service->create(this, mAudioSessionId)); 175 if ((NO_ERROR != doSetRetransmitEndpoint(player)) || 176 (NO_ERROR != player->setDataSource(fd, offset, length))) { 177 player.clear(); 178 } 179 err = attachNewPlayer(player); 180 } 181 return err; 182} 183 184status_t MediaPlayer::setDataSource(const sp<IDataSource> &source) 185{ 186 ALOGV("setDataSource(IDataSource)"); 187 status_t err = UNKNOWN_ERROR; 188 const sp<IMediaPlayerService> service(getMediaPlayerService()); 189 if (service != 0) { 190 sp<IMediaPlayer> player(service->create(this, mAudioSessionId)); 191 if ((NO_ERROR != doSetRetransmitEndpoint(player)) || 192 (NO_ERROR != player->setDataSource(source))) { 193 player.clear(); 194 } 195 err = attachNewPlayer(player); 196 } 197 return err; 198} 199 200status_t MediaPlayer::invoke(const Parcel& request, Parcel *reply) 201{ 202 Mutex::Autolock _l(mLock); 203 const bool hasBeenInitialized = 204 (mCurrentState != MEDIA_PLAYER_STATE_ERROR) && 205 ((mCurrentState & MEDIA_PLAYER_IDLE) != MEDIA_PLAYER_IDLE); 206 if ((mPlayer != NULL) && hasBeenInitialized) { 207 ALOGV("invoke %zu", request.dataSize()); 208 return mPlayer->invoke(request, reply); 209 } 210 ALOGE("invoke failed: wrong state %X, mPlayer(%p)", mCurrentState, mPlayer.get()); 211 return INVALID_OPERATION; 212} 213 214status_t MediaPlayer::setMetadataFilter(const Parcel& filter) 215{ 216 ALOGD("setMetadataFilter"); 217 Mutex::Autolock lock(mLock); 218 if (mPlayer == NULL) { 219 return NO_INIT; 220 } 221 return mPlayer->setMetadataFilter(filter); 222} 223 224status_t MediaPlayer::getMetadata(bool update_only, bool apply_filter, Parcel *metadata) 225{ 226 ALOGD("getMetadata"); 227 Mutex::Autolock lock(mLock); 228 if (mPlayer == NULL) { 229 return NO_INIT; 230 } 231 return mPlayer->getMetadata(update_only, apply_filter, metadata); 232} 233 234status_t MediaPlayer::setVideoSurfaceTexture( 235 const sp<IGraphicBufferProducer>& bufferProducer) 236{ 237 ALOGV("setVideoSurfaceTexture"); 238 Mutex::Autolock _l(mLock); 239 if (mPlayer == 0) return NO_INIT; 240 return mPlayer->setVideoSurfaceTexture(bufferProducer); 241} 242 243// must call with lock held 244status_t MediaPlayer::prepareAsync_l() 245{ 246 if ( (mPlayer != 0) && ( mCurrentState & (MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) { 247 if (mAudioAttributesParcel != NULL) { 248 mPlayer->setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, *mAudioAttributesParcel); 249 } else { 250 mPlayer->setAudioStreamType(mStreamType); 251 } 252 mCurrentState = MEDIA_PLAYER_PREPARING; 253 return mPlayer->prepareAsync(); 254 } 255 ALOGE("prepareAsync called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get()); 256 return INVALID_OPERATION; 257} 258 259// TODO: In case of error, prepareAsync provides the caller with 2 error codes, 260// one defined in the Android framework and one provided by the implementation 261// that generated the error. The sync version of prepare returns only 1 error 262// code. 263status_t MediaPlayer::prepare() 264{ 265 ALOGV("prepare"); 266 Mutex::Autolock _l(mLock); 267 mLockThreadId = getThreadId(); 268 if (mPrepareSync) { 269 mLockThreadId = 0; 270 return -EALREADY; 271 } 272 mPrepareSync = true; 273 status_t ret = prepareAsync_l(); 274 if (ret != NO_ERROR) { 275 mLockThreadId = 0; 276 return ret; 277 } 278 279 if (mPrepareSync) { 280 mSignal.wait(mLock); // wait for prepare done 281 mPrepareSync = false; 282 } 283 ALOGV("prepare complete - status=%d", mPrepareStatus); 284 mLockThreadId = 0; 285 return mPrepareStatus; 286} 287 288status_t MediaPlayer::prepareAsync() 289{ 290 ALOGV("prepareAsync"); 291 Mutex::Autolock _l(mLock); 292 return prepareAsync_l(); 293} 294 295status_t MediaPlayer::start() 296{ 297 ALOGV("start"); 298 299 status_t ret = NO_ERROR; 300 Mutex::Autolock _l(mLock); 301 302 mLockThreadId = getThreadId(); 303 304 if (mCurrentState & MEDIA_PLAYER_STARTED) { 305 ret = NO_ERROR; 306 } else if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED | 307 MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) { 308 mPlayer->setLooping(mLoop); 309 mPlayer->setVolume(mLeftVolume, mRightVolume); 310 mPlayer->setAuxEffectSendLevel(mSendLevel); 311 mCurrentState = MEDIA_PLAYER_STARTED; 312 ret = mPlayer->start(); 313 if (ret != NO_ERROR) { 314 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 315 } else { 316 if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) { 317 ALOGV("playback completed immediately following start()"); 318 } 319 } 320 } else { 321 ALOGE("start called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get()); 322 ret = INVALID_OPERATION; 323 } 324 325 mLockThreadId = 0; 326 327 return ret; 328} 329 330status_t MediaPlayer::stop() 331{ 332 ALOGV("stop"); 333 Mutex::Autolock _l(mLock); 334 if (mCurrentState & MEDIA_PLAYER_STOPPED) return NO_ERROR; 335 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | 336 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) ) { 337 status_t ret = mPlayer->stop(); 338 if (ret != NO_ERROR) { 339 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 340 } else { 341 mCurrentState = MEDIA_PLAYER_STOPPED; 342 } 343 return ret; 344 } 345 ALOGE("stop called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get()); 346 return INVALID_OPERATION; 347} 348 349status_t MediaPlayer::pause() 350{ 351 ALOGV("pause"); 352 Mutex::Autolock _l(mLock); 353 if (mCurrentState & (MEDIA_PLAYER_PAUSED|MEDIA_PLAYER_PLAYBACK_COMPLETE)) 354 return NO_ERROR; 355 if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER_STARTED)) { 356 status_t ret = mPlayer->pause(); 357 if (ret != NO_ERROR) { 358 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 359 } else { 360 mCurrentState = MEDIA_PLAYER_PAUSED; 361 } 362 return ret; 363 } 364 ALOGE("pause called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get()); 365 return INVALID_OPERATION; 366} 367 368bool MediaPlayer::isPlaying() 369{ 370 Mutex::Autolock _l(mLock); 371 if (mPlayer != 0) { 372 bool temp = false; 373 mPlayer->isPlaying(&temp); 374 ALOGV("isPlaying: %d", temp); 375 if ((mCurrentState & MEDIA_PLAYER_STARTED) && ! temp) { 376 ALOGE("internal/external state mismatch corrected"); 377 mCurrentState = MEDIA_PLAYER_PAUSED; 378 } else if ((mCurrentState & MEDIA_PLAYER_PAUSED) && temp) { 379 ALOGE("internal/external state mismatch corrected"); 380 mCurrentState = MEDIA_PLAYER_STARTED; 381 } 382 return temp; 383 } 384 ALOGV("isPlaying: no active player"); 385 return false; 386} 387 388status_t MediaPlayer::setPlaybackSettings(const AudioPlaybackRate& rate) 389{ 390 ALOGV("setPlaybackSettings: %f %f %d %d", 391 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode); 392 // Negative speed and pitch does not make sense. Further validation will 393 // be done by the respective mediaplayers. 394 if (rate.mSpeed < 0.f || rate.mPitch < 0.f) { 395 return BAD_VALUE; 396 } 397 Mutex::Autolock _l(mLock); 398 if (mPlayer == 0) return INVALID_OPERATION; 399 status_t err = mPlayer->setPlaybackSettings(rate); 400 if (err == OK) { 401 if (rate.mSpeed == 0.f && mCurrentState == MEDIA_PLAYER_STARTED) { 402 mCurrentState = MEDIA_PLAYER_PAUSED; 403 } else if (rate.mSpeed != 0.f && mCurrentState == MEDIA_PLAYER_PAUSED) { 404 mCurrentState = MEDIA_PLAYER_STARTED; 405 } 406 } 407 return err; 408} 409 410status_t MediaPlayer::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) 411{ 412 Mutex::Autolock _l(mLock); 413 if (mPlayer == 0) return INVALID_OPERATION; 414 return mPlayer->getPlaybackSettings(rate); 415} 416 417status_t MediaPlayer::setSyncSettings(const AVSyncSettings& sync, float videoFpsHint) 418{ 419 ALOGV("setSyncSettings: %u %u %f %f", 420 sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint); 421 Mutex::Autolock _l(mLock); 422 if (mPlayer == 0) return INVALID_OPERATION; 423 return mPlayer->setSyncSettings(sync, videoFpsHint); 424} 425 426status_t MediaPlayer::getSyncSettings( 427 AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */) 428{ 429 Mutex::Autolock _l(mLock); 430 if (mPlayer == 0) return INVALID_OPERATION; 431 return mPlayer->getSyncSettings(sync, videoFps); 432} 433 434status_t MediaPlayer::getVideoWidth(int *w) 435{ 436 ALOGV("getVideoWidth"); 437 Mutex::Autolock _l(mLock); 438 if (mPlayer == 0) return INVALID_OPERATION; 439 *w = mVideoWidth; 440 return NO_ERROR; 441} 442 443status_t MediaPlayer::getVideoHeight(int *h) 444{ 445 ALOGV("getVideoHeight"); 446 Mutex::Autolock _l(mLock); 447 if (mPlayer == 0) return INVALID_OPERATION; 448 *h = mVideoHeight; 449 return NO_ERROR; 450} 451 452status_t MediaPlayer::getCurrentPosition(int *msec) 453{ 454 ALOGV("getCurrentPosition"); 455 Mutex::Autolock _l(mLock); 456 if (mPlayer != 0) { 457 if (mCurrentPosition >= 0) { 458 ALOGV("Using cached seek position: %d", mCurrentPosition); 459 *msec = mCurrentPosition; 460 return NO_ERROR; 461 } 462 return mPlayer->getCurrentPosition(msec); 463 } 464 return INVALID_OPERATION; 465} 466 467status_t MediaPlayer::getDuration_l(int *msec) 468{ 469 ALOGV("getDuration_l"); 470 bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | 471 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE)); 472 if (mPlayer != 0 && isValidState) { 473 int durationMs; 474 status_t ret = mPlayer->getDuration(&durationMs); 475 476 if (ret != OK) { 477 // Do not enter error state just because no duration was available. 478 durationMs = -1; 479 ret = OK; 480 } 481 482 if (msec) { 483 *msec = durationMs; 484 } 485 return ret; 486 } 487 ALOGE("Attempt to call getDuration in wrong state: mPlayer=%p, mCurrentState=%u", 488 mPlayer.get(), mCurrentState); 489 return INVALID_OPERATION; 490} 491 492status_t MediaPlayer::getDuration(int *msec) 493{ 494 Mutex::Autolock _l(mLock); 495 return getDuration_l(msec); 496} 497 498status_t MediaPlayer::seekTo_l(int msec) 499{ 500 ALOGV("seekTo %d", msec); 501 if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | 502 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) { 503 if ( msec < 0 ) { 504 ALOGW("Attempt to seek to invalid position: %d", msec); 505 msec = 0; 506 } 507 508 int durationMs; 509 status_t err = mPlayer->getDuration(&durationMs); 510 511 if (err != OK) { 512 ALOGW("Stream has no duration and is therefore not seekable."); 513 return err; 514 } 515 516 if (msec > durationMs) { 517 ALOGW("Attempt to seek to past end of file: request = %d, " 518 "durationMs = %d", 519 msec, 520 durationMs); 521 522 msec = durationMs; 523 } 524 525 // cache duration 526 mCurrentPosition = msec; 527 if (mSeekPosition < 0) { 528 mSeekPosition = msec; 529 return mPlayer->seekTo(msec); 530 } 531 else { 532 ALOGV("Seek in progress - queue up seekTo[%d]", msec); 533 return NO_ERROR; 534 } 535 } 536 ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(), 537 mCurrentState); 538 return INVALID_OPERATION; 539} 540 541status_t MediaPlayer::seekTo(int msec) 542{ 543 mLockThreadId = getThreadId(); 544 Mutex::Autolock _l(mLock); 545 status_t result = seekTo_l(msec); 546 mLockThreadId = 0; 547 548 return result; 549} 550 551status_t MediaPlayer::reset_l() 552{ 553 mLoop = false; 554 if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR; 555 mPrepareSync = false; 556 if (mPlayer != 0) { 557 status_t ret = mPlayer->reset(); 558 if (ret != NO_ERROR) { 559 ALOGE("reset() failed with return code (%d)", ret); 560 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 561 } else { 562 mPlayer->disconnect(); 563 mCurrentState = MEDIA_PLAYER_IDLE; 564 } 565 // setDataSource has to be called again to create a 566 // new mediaplayer. 567 mPlayer = 0; 568 return ret; 569 } 570 clear_l(); 571 return NO_ERROR; 572} 573 574status_t MediaPlayer::doSetRetransmitEndpoint(const sp<IMediaPlayer>& player) { 575 Mutex::Autolock _l(mLock); 576 577 if (player == NULL) { 578 return UNKNOWN_ERROR; 579 } 580 581 if (mRetransmitEndpointValid) { 582 return player->setRetransmitEndpoint(&mRetransmitEndpoint); 583 } 584 585 return OK; 586} 587 588status_t MediaPlayer::reset() 589{ 590 ALOGV("reset"); 591 Mutex::Autolock _l(mLock); 592 return reset_l(); 593} 594 595status_t MediaPlayer::setAudioStreamType(audio_stream_type_t type) 596{ 597 ALOGV("MediaPlayer::setAudioStreamType"); 598 Mutex::Autolock _l(mLock); 599 if (mStreamType == type) return NO_ERROR; 600 if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | 601 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) { 602 // Can't change the stream type after prepare 603 ALOGE("setAudioStream called in state %d", mCurrentState); 604 return INVALID_OPERATION; 605 } 606 // cache 607 mStreamType = type; 608 return OK; 609} 610 611status_t MediaPlayer::getAudioStreamType(audio_stream_type_t *type) 612{ 613 ALOGV("getAudioStreamType"); 614 Mutex::Autolock _l(mLock); 615 *type = mStreamType; 616 return OK; 617} 618 619status_t MediaPlayer::setLooping(int loop) 620{ 621 ALOGV("MediaPlayer::setLooping"); 622 Mutex::Autolock _l(mLock); 623 mLoop = (loop != 0); 624 if (mPlayer != 0) { 625 return mPlayer->setLooping(loop); 626 } 627 return OK; 628} 629 630bool MediaPlayer::isLooping() { 631 ALOGV("isLooping"); 632 Mutex::Autolock _l(mLock); 633 if (mPlayer != 0) { 634 return mLoop; 635 } 636 ALOGV("isLooping: no active player"); 637 return false; 638} 639 640status_t MediaPlayer::setVolume(float leftVolume, float rightVolume) 641{ 642 ALOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume); 643 Mutex::Autolock _l(mLock); 644 mLeftVolume = leftVolume; 645 mRightVolume = rightVolume; 646 if (mPlayer != 0) { 647 return mPlayer->setVolume(leftVolume, rightVolume); 648 } 649 return OK; 650} 651 652status_t MediaPlayer::setAudioSessionId(audio_session_t sessionId) 653{ 654 ALOGV("MediaPlayer::setAudioSessionId(%d)", sessionId); 655 Mutex::Autolock _l(mLock); 656 if (!(mCurrentState & MEDIA_PLAYER_IDLE)) { 657 ALOGE("setAudioSessionId called in state %d", mCurrentState); 658 return INVALID_OPERATION; 659 } 660 if (sessionId < 0) { 661 return BAD_VALUE; 662 } 663 if (sessionId != mAudioSessionId) { 664 AudioSystem::acquireAudioSessionId(sessionId, -1); 665 AudioSystem::releaseAudioSessionId(mAudioSessionId, -1); 666 mAudioSessionId = sessionId; 667 } 668 return NO_ERROR; 669} 670 671audio_session_t MediaPlayer::getAudioSessionId() 672{ 673 Mutex::Autolock _l(mLock); 674 return mAudioSessionId; 675} 676 677status_t MediaPlayer::setAuxEffectSendLevel(float level) 678{ 679 ALOGV("MediaPlayer::setAuxEffectSendLevel(%f)", level); 680 Mutex::Autolock _l(mLock); 681 mSendLevel = level; 682 if (mPlayer != 0) { 683 return mPlayer->setAuxEffectSendLevel(level); 684 } 685 return OK; 686} 687 688status_t MediaPlayer::attachAuxEffect(int effectId) 689{ 690 ALOGV("MediaPlayer::attachAuxEffect(%d)", effectId); 691 Mutex::Autolock _l(mLock); 692 if (mPlayer == 0 || 693 (mCurrentState & MEDIA_PLAYER_IDLE) || 694 (mCurrentState == MEDIA_PLAYER_STATE_ERROR )) { 695 ALOGE("attachAuxEffect called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get()); 696 return INVALID_OPERATION; 697 } 698 699 return mPlayer->attachAuxEffect(effectId); 700} 701 702// always call with lock held 703status_t MediaPlayer::checkStateForKeySet_l(int key) 704{ 705 switch(key) { 706 case KEY_PARAMETER_AUDIO_ATTRIBUTES: 707 if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | 708 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) { 709 // Can't change the audio attributes after prepare 710 ALOGE("trying to set audio attributes called in state %d", mCurrentState); 711 return INVALID_OPERATION; 712 } 713 break; 714 default: 715 // parameter doesn't require player state check 716 break; 717 } 718 return OK; 719} 720 721status_t MediaPlayer::setParameter(int key, const Parcel& request) 722{ 723 ALOGV("MediaPlayer::setParameter(%d)", key); 724 status_t status = INVALID_OPERATION; 725 Mutex::Autolock _l(mLock); 726 if (checkStateForKeySet_l(key) != OK) { 727 return status; 728 } 729 switch (key) { 730 case KEY_PARAMETER_AUDIO_ATTRIBUTES: 731 // save the marshalled audio attributes 732 if (mAudioAttributesParcel != NULL) { delete mAudioAttributesParcel; }; 733 mAudioAttributesParcel = new Parcel(); 734 mAudioAttributesParcel->appendFrom(&request, 0, request.dataSize()); 735 status = OK; 736 break; 737 default: 738 ALOGV_IF(mPlayer == NULL, "setParameter: no active player"); 739 break; 740 } 741 742 if (mPlayer != NULL) { 743 status = mPlayer->setParameter(key, request); 744 } 745 return status; 746} 747 748status_t MediaPlayer::getParameter(int key, Parcel *reply) 749{ 750 ALOGV("MediaPlayer::getParameter(%d)", key); 751 Mutex::Autolock _l(mLock); 752 if (mPlayer != NULL) { 753 return mPlayer->getParameter(key, reply); 754 } 755 ALOGV("getParameter: no active player"); 756 return INVALID_OPERATION; 757} 758 759status_t MediaPlayer::setRetransmitEndpoint(const char* addrString, 760 uint16_t port) { 761 ALOGV("MediaPlayer::setRetransmitEndpoint(%s:%hu)", 762 addrString ? addrString : "(null)", port); 763 764 Mutex::Autolock _l(mLock); 765 if ((mPlayer != NULL) || (mCurrentState != MEDIA_PLAYER_IDLE)) 766 return INVALID_OPERATION; 767 768 if (NULL == addrString) { 769 mRetransmitEndpointValid = false; 770 return OK; 771 } 772 773 struct in_addr saddr; 774 if(!inet_aton(addrString, &saddr)) { 775 return BAD_VALUE; 776 } 777 778 memset(&mRetransmitEndpoint, 0, sizeof(mRetransmitEndpoint)); 779 mRetransmitEndpoint.sin_family = AF_INET; 780 mRetransmitEndpoint.sin_addr = saddr; 781 mRetransmitEndpoint.sin_port = htons(port); 782 mRetransmitEndpointValid = true; 783 784 return OK; 785} 786 787void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj) 788{ 789 ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2); 790 bool send = true; 791 bool locked = false; 792 793 // TODO: In the future, we might be on the same thread if the app is 794 // running in the same process as the media server. In that case, 795 // this will deadlock. 796 // 797 // The threadId hack below works around this for the care of prepare, 798 // seekTo and start within the same process. 799 // FIXME: Remember, this is a hack, it's not even a hack that is applied 800 // consistently for all use-cases, this needs to be revisited. 801 if (mLockThreadId != getThreadId()) { 802 mLock.lock(); 803 locked = true; 804 } 805 806 // Allows calls from JNI in idle state to notify errors 807 if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == 0) { 808 ALOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2); 809 if (locked) mLock.unlock(); // release the lock when done. 810 return; 811 } 812 813 switch (msg) { 814 case MEDIA_NOP: // interface test message 815 break; 816 case MEDIA_PREPARED: 817 ALOGV("prepared"); 818 mCurrentState = MEDIA_PLAYER_PREPARED; 819 if (mPrepareSync) { 820 ALOGV("signal application thread"); 821 mPrepareSync = false; 822 mPrepareStatus = NO_ERROR; 823 mSignal.signal(); 824 } 825 break; 826 case MEDIA_PLAYBACK_COMPLETE: 827 ALOGV("playback complete"); 828 if (mCurrentState == MEDIA_PLAYER_IDLE) { 829 ALOGE("playback complete in idle state"); 830 } 831 if (!mLoop) { 832 mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE; 833 } 834 break; 835 case MEDIA_ERROR: 836 // Always log errors. 837 // ext1: Media framework error code. 838 // ext2: Implementation dependant error code. 839 ALOGE("error (%d, %d)", ext1, ext2); 840 mCurrentState = MEDIA_PLAYER_STATE_ERROR; 841 if (mPrepareSync) 842 { 843 ALOGV("signal application thread"); 844 mPrepareSync = false; 845 mPrepareStatus = ext1; 846 mSignal.signal(); 847 send = false; 848 } 849 break; 850 case MEDIA_INFO: 851 // ext1: Media framework error code. 852 // ext2: Implementation dependant error code. 853 if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) { 854 ALOGW("info/warning (%d, %d)", ext1, ext2); 855 } 856 break; 857 case MEDIA_SEEK_COMPLETE: 858 ALOGV("Received seek complete"); 859 if (mSeekPosition != mCurrentPosition) { 860 ALOGV("Executing queued seekTo(%d)", mSeekPosition); 861 mSeekPosition = -1; 862 seekTo_l(mCurrentPosition); 863 } 864 else { 865 ALOGV("All seeks complete - return to regularly scheduled program"); 866 mCurrentPosition = mSeekPosition = -1; 867 } 868 break; 869 case MEDIA_BUFFERING_UPDATE: 870 ALOGV("buffering %d", ext1); 871 break; 872 case MEDIA_SET_VIDEO_SIZE: 873 ALOGV("New video size %d x %d", ext1, ext2); 874 mVideoWidth = ext1; 875 mVideoHeight = ext2; 876 break; 877 case MEDIA_TIMED_TEXT: 878 ALOGV("Received timed text message"); 879 break; 880 case MEDIA_SUBTITLE_DATA: 881 ALOGV("Received subtitle data message"); 882 break; 883 case MEDIA_META_DATA: 884 ALOGV("Received timed metadata message"); 885 break; 886 default: 887 ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2); 888 break; 889 } 890 891 sp<MediaPlayerListener> listener = mListener; 892 if (locked) mLock.unlock(); 893 894 // this prevents re-entrant calls into client code 895 if ((listener != 0) && send) { 896 Mutex::Autolock _l(mNotifyLock); 897 ALOGV("callback application"); 898 listener->notify(msg, ext1, ext2, obj); 899 ALOGV("back from callback"); 900 } 901} 902 903void MediaPlayer::died() 904{ 905 ALOGV("died"); 906 notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0); 907} 908 909status_t MediaPlayer::setNextMediaPlayer(const sp<MediaPlayer>& next) { 910 Mutex::Autolock _l(mLock); 911 if (mPlayer == NULL) { 912 return NO_INIT; 913 } 914 915 if (next != NULL && !(next->mCurrentState & 916 (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE))) { 917 ALOGE("next player is not prepared"); 918 return INVALID_OPERATION; 919 } 920 921 return mPlayer->setNextPlayer(next == NULL ? NULL : next->mPlayer); 922} 923 924} // namespace android 925