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