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