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