Home | History | Annotate | Download | only in libmedia
      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 
     45 namespace android {
     46 
     47 MediaPlayer::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 
     68 MediaPlayer::~MediaPlayer()
     69 {
     70     LOGV("destructor");
     71     AudioSystem::releaseAudioSessionId(mAudioSessionId);
     72     disconnect();
     73     IPCThreadState::self()->flushCommands();
     74 }
     75 
     76 void 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
     92 void MediaPlayer::clear_l()
     93 {
     94     mDuration = -1;
     95     mCurrentPosition = -1;
     96     mSeekPosition = -1;
     97     mVideoWidth = mVideoHeight = 0;
     98 }
     99 
    100 status_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 
    109 status_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 
    140 status_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 
    158 status_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 
    173 status_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 
    188 status_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 
    202 status_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 
    212 status_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 
    222 status_t MediaPlayer::setVideoSurfaceTexture(
    223         const sp<ISurfaceTexture>& surfaceTexture)
    224 {
    225     LOGV("setVideoSurfaceTexture");
    226     Mutex::Autolock _l(mLock);
    227     if (mPlayer == 0) return NO_INIT;
    228     return mPlayer->setVideoSurfaceTexture(surfaceTexture);
    229 }
    230 
    231 // must call with lock held
    232 status_t MediaPlayer::prepareAsync_l()
    233 {
    234     if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {
    235         mPlayer->setAudioStreamType(mStreamType);
    236         mCurrentState = MEDIA_PLAYER_PREPARING;
    237         return mPlayer->prepareAsync();
    238     }
    239     LOGE("prepareAsync called in state %d", mCurrentState);
    240     return INVALID_OPERATION;
    241 }
    242 
    243 // TODO: In case of error, prepareAsync provides the caller with 2 error codes,
    244 // one defined in the Android framework and one provided by the implementation
    245 // that generated the error. The sync version of prepare returns only 1 error
    246 // code.
    247 status_t MediaPlayer::prepare()
    248 {
    249     LOGV("prepare");
    250     Mutex::Autolock _l(mLock);
    251     mLockThreadId = getThreadId();
    252     if (mPrepareSync) {
    253         mLockThreadId = 0;
    254         return -EALREADY;
    255     }
    256     mPrepareSync = true;
    257     status_t ret = prepareAsync_l();
    258     if (ret != NO_ERROR) {
    259         mLockThreadId = 0;
    260         return ret;
    261     }
    262 
    263     if (mPrepareSync) {
    264         mSignal.wait(mLock);  // wait for prepare done
    265         mPrepareSync = false;
    266     }
    267     LOGV("prepare complete - status=%d", mPrepareStatus);
    268     mLockThreadId = 0;
    269     return mPrepareStatus;
    270 }
    271 
    272 status_t MediaPlayer::prepareAsync()
    273 {
    274     LOGV("prepareAsync");
    275     Mutex::Autolock _l(mLock);
    276     return prepareAsync_l();
    277 }
    278 
    279 status_t MediaPlayer::start()
    280 {
    281     LOGV("start");
    282     Mutex::Autolock _l(mLock);
    283     if (mCurrentState & MEDIA_PLAYER_STARTED)
    284         return NO_ERROR;
    285     if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED |
    286                     MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) {
    287         mPlayer->setLooping(mLoop);
    288         mPlayer->setVolume(mLeftVolume, mRightVolume);
    289         mPlayer->setAuxEffectSendLevel(mSendLevel);
    290         mCurrentState = MEDIA_PLAYER_STARTED;
    291         status_t ret = mPlayer->start();
    292         if (ret != NO_ERROR) {
    293             mCurrentState = MEDIA_PLAYER_STATE_ERROR;
    294         } else {
    295             if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) {
    296                 LOGV("playback completed immediately following start()");
    297             }
    298         }
    299         return ret;
    300     }
    301     LOGE("start called in state %d", mCurrentState);
    302     return INVALID_OPERATION;
    303 }
    304 
    305 status_t MediaPlayer::stop()
    306 {
    307     LOGV("stop");
    308     Mutex::Autolock _l(mLock);
    309     if (mCurrentState & MEDIA_PLAYER_STOPPED) return NO_ERROR;
    310     if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED |
    311                     MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) ) {
    312         status_t ret = mPlayer->stop();
    313         if (ret != NO_ERROR) {
    314             mCurrentState = MEDIA_PLAYER_STATE_ERROR;
    315         } else {
    316             mCurrentState = MEDIA_PLAYER_STOPPED;
    317         }
    318         return ret;
    319     }
    320     LOGE("stop called in state %d", mCurrentState);
    321     return INVALID_OPERATION;
    322 }
    323 
    324 status_t MediaPlayer::pause()
    325 {
    326     LOGV("pause");
    327     Mutex::Autolock _l(mLock);
    328     if (mCurrentState & (MEDIA_PLAYER_PAUSED|MEDIA_PLAYER_PLAYBACK_COMPLETE))
    329         return NO_ERROR;
    330     if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER_STARTED)) {
    331         status_t ret = mPlayer->pause();
    332         if (ret != NO_ERROR) {
    333             mCurrentState = MEDIA_PLAYER_STATE_ERROR;
    334         } else {
    335             mCurrentState = MEDIA_PLAYER_PAUSED;
    336         }
    337         return ret;
    338     }
    339     LOGE("pause called in state %d", mCurrentState);
    340     return INVALID_OPERATION;
    341 }
    342 
    343 bool MediaPlayer::isPlaying()
    344 {
    345     Mutex::Autolock _l(mLock);
    346     if (mPlayer != 0) {
    347         bool temp = false;
    348         mPlayer->isPlaying(&temp);
    349         LOGV("isPlaying: %d", temp);
    350         if ((mCurrentState & MEDIA_PLAYER_STARTED) && ! temp) {
    351             LOGE("internal/external state mismatch corrected");
    352             mCurrentState = MEDIA_PLAYER_PAUSED;
    353         }
    354         return temp;
    355     }
    356     LOGV("isPlaying: no active player");
    357     return false;
    358 }
    359 
    360 status_t MediaPlayer::getVideoWidth(int *w)
    361 {
    362     LOGV("getVideoWidth");
    363     Mutex::Autolock _l(mLock);
    364     if (mPlayer == 0) return INVALID_OPERATION;
    365     *w = mVideoWidth;
    366     return NO_ERROR;
    367 }
    368 
    369 status_t MediaPlayer::getVideoHeight(int *h)
    370 {
    371     LOGV("getVideoHeight");
    372     Mutex::Autolock _l(mLock);
    373     if (mPlayer == 0) return INVALID_OPERATION;
    374     *h = mVideoHeight;
    375     return NO_ERROR;
    376 }
    377 
    378 status_t MediaPlayer::getCurrentPosition(int *msec)
    379 {
    380     LOGV("getCurrentPosition");
    381     Mutex::Autolock _l(mLock);
    382     if (mPlayer != 0) {
    383         if (mCurrentPosition >= 0) {
    384             LOGV("Using cached seek position: %d", mCurrentPosition);
    385             *msec = mCurrentPosition;
    386             return NO_ERROR;
    387         }
    388         return mPlayer->getCurrentPosition(msec);
    389     }
    390     return INVALID_OPERATION;
    391 }
    392 
    393 status_t MediaPlayer::getDuration_l(int *msec)
    394 {
    395     LOGV("getDuration");
    396     bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE));
    397     if (mPlayer != 0 && isValidState) {
    398         status_t ret = NO_ERROR;
    399         if (mDuration <= 0)
    400             ret = mPlayer->getDuration(&mDuration);
    401         if (msec)
    402             *msec = mDuration;
    403         return ret;
    404     }
    405     LOGE("Attempt to call getDuration without a valid mediaplayer");
    406     return INVALID_OPERATION;
    407 }
    408 
    409 status_t MediaPlayer::getDuration(int *msec)
    410 {
    411     Mutex::Autolock _l(mLock);
    412     return getDuration_l(msec);
    413 }
    414 
    415 status_t MediaPlayer::seekTo_l(int msec)
    416 {
    417     LOGV("seekTo %d", msec);
    418     if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED |  MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) {
    419         if ( msec < 0 ) {
    420             LOGW("Attempt to seek to invalid position: %d", msec);
    421             msec = 0;
    422         } else if ((mDuration > 0) && (msec > mDuration)) {
    423             LOGW("Attempt to seek to past end of file: request = %d, EOF = %d", msec, mDuration);
    424             msec = mDuration;
    425         }
    426         // cache duration
    427         mCurrentPosition = msec;
    428         if (mSeekPosition < 0) {
    429             getDuration_l(NULL);
    430             mSeekPosition = msec;
    431             return mPlayer->seekTo(msec);
    432         }
    433         else {
    434             LOGV("Seek in progress - queue up seekTo[%d]", msec);
    435             return NO_ERROR;
    436         }
    437     }
    438     LOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(), mCurrentState);
    439     return INVALID_OPERATION;
    440 }
    441 
    442 status_t MediaPlayer::seekTo(int msec)
    443 {
    444     mLockThreadId = getThreadId();
    445     Mutex::Autolock _l(mLock);
    446     status_t result = seekTo_l(msec);
    447     mLockThreadId = 0;
    448 
    449     return result;
    450 }
    451 
    452 status_t MediaPlayer::reset_l()
    453 {
    454     mLoop = false;
    455     if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR;
    456     mPrepareSync = false;
    457     if (mPlayer != 0) {
    458         status_t ret = mPlayer->reset();
    459         if (ret != NO_ERROR) {
    460             LOGE("reset() failed with return code (%d)", ret);
    461             mCurrentState = MEDIA_PLAYER_STATE_ERROR;
    462         } else {
    463             mCurrentState = MEDIA_PLAYER_IDLE;
    464         }
    465         // setDataSource has to be called again to create a
    466         // new mediaplayer.
    467         mPlayer = 0;
    468         return ret;
    469     }
    470     clear_l();
    471     return NO_ERROR;
    472 }
    473 
    474 status_t MediaPlayer::reset()
    475 {
    476     LOGV("reset");
    477     Mutex::Autolock _l(mLock);
    478     return reset_l();
    479 }
    480 
    481 status_t MediaPlayer::setAudioStreamType(int type)
    482 {
    483     LOGV("MediaPlayer::setAudioStreamType");
    484     Mutex::Autolock _l(mLock);
    485     if (mStreamType == type) return NO_ERROR;
    486     if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
    487                 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) {
    488         // Can't change the stream type after prepare
    489         LOGE("setAudioStream called in state %d", mCurrentState);
    490         return INVALID_OPERATION;
    491     }
    492     // cache
    493     mStreamType = type;
    494     return OK;
    495 }
    496 
    497 status_t MediaPlayer::setLooping(int loop)
    498 {
    499     LOGV("MediaPlayer::setLooping");
    500     Mutex::Autolock _l(mLock);
    501     mLoop = (loop != 0);
    502     if (mPlayer != 0) {
    503         return mPlayer->setLooping(loop);
    504     }
    505     return OK;
    506 }
    507 
    508 bool MediaPlayer::isLooping() {
    509     LOGV("isLooping");
    510     Mutex::Autolock _l(mLock);
    511     if (mPlayer != 0) {
    512         return mLoop;
    513     }
    514     LOGV("isLooping: no active player");
    515     return false;
    516 }
    517 
    518 status_t MediaPlayer::setVolume(float leftVolume, float rightVolume)
    519 {
    520     LOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume);
    521     Mutex::Autolock _l(mLock);
    522     mLeftVolume = leftVolume;
    523     mRightVolume = rightVolume;
    524     if (mPlayer != 0) {
    525         return mPlayer->setVolume(leftVolume, rightVolume);
    526     }
    527     return OK;
    528 }
    529 
    530 status_t MediaPlayer::setAudioSessionId(int sessionId)
    531 {
    532     LOGV("MediaPlayer::setAudioSessionId(%d)", sessionId);
    533     Mutex::Autolock _l(mLock);
    534     if (!(mCurrentState & MEDIA_PLAYER_IDLE)) {
    535         LOGE("setAudioSessionId called in state %d", mCurrentState);
    536         return INVALID_OPERATION;
    537     }
    538     if (sessionId < 0) {
    539         return BAD_VALUE;
    540     }
    541     if (sessionId != mAudioSessionId) {
    542       AudioSystem::releaseAudioSessionId(mAudioSessionId);
    543       AudioSystem::acquireAudioSessionId(sessionId);
    544       mAudioSessionId = sessionId;
    545     }
    546     return NO_ERROR;
    547 }
    548 
    549 int MediaPlayer::getAudioSessionId()
    550 {
    551     Mutex::Autolock _l(mLock);
    552     return mAudioSessionId;
    553 }
    554 
    555 status_t MediaPlayer::setAuxEffectSendLevel(float level)
    556 {
    557     LOGV("MediaPlayer::setAuxEffectSendLevel(%f)", level);
    558     Mutex::Autolock _l(mLock);
    559     mSendLevel = level;
    560     if (mPlayer != 0) {
    561         return mPlayer->setAuxEffectSendLevel(level);
    562     }
    563     return OK;
    564 }
    565 
    566 status_t MediaPlayer::attachAuxEffect(int effectId)
    567 {
    568     LOGV("MediaPlayer::attachAuxEffect(%d)", effectId);
    569     Mutex::Autolock _l(mLock);
    570     if (mPlayer == 0 ||
    571         (mCurrentState & MEDIA_PLAYER_IDLE) ||
    572         (mCurrentState == MEDIA_PLAYER_STATE_ERROR )) {
    573         LOGE("attachAuxEffect called in state %d", mCurrentState);
    574         return INVALID_OPERATION;
    575     }
    576 
    577     return mPlayer->attachAuxEffect(effectId);
    578 }
    579 
    580 status_t MediaPlayer::setParameter(int key, const Parcel& request)
    581 {
    582     LOGV("MediaPlayer::setParameter(%d)", key);
    583     Mutex::Autolock _l(mLock);
    584     if (mPlayer != NULL) {
    585         return  mPlayer->setParameter(key, request);
    586     }
    587     LOGV("setParameter: no active player");
    588     return INVALID_OPERATION;
    589 }
    590 
    591 status_t MediaPlayer::getParameter(int key, Parcel *reply)
    592 {
    593     LOGV("MediaPlayer::getParameter(%d)", key);
    594     Mutex::Autolock _l(mLock);
    595     if (mPlayer != NULL) {
    596          return  mPlayer->getParameter(key, reply);
    597     }
    598     LOGV("getParameter: no active player");
    599     return INVALID_OPERATION;
    600 }
    601 
    602 void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
    603 {
    604     LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
    605     bool send = true;
    606     bool locked = false;
    607 
    608     // TODO: In the future, we might be on the same thread if the app is
    609     // running in the same process as the media server. In that case,
    610     // this will deadlock.
    611     //
    612     // The threadId hack below works around this for the care of prepare
    613     // and seekTo within the same process.
    614     // FIXME: Remember, this is a hack, it's not even a hack that is applied
    615     // consistently for all use-cases, this needs to be revisited.
    616      if (mLockThreadId != getThreadId()) {
    617         mLock.lock();
    618         locked = true;
    619     }
    620 
    621     // Allows calls from JNI in idle state to notify errors
    622     if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == 0) {
    623         LOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2);
    624         if (locked) mLock.unlock();   // release the lock when done.
    625         return;
    626     }
    627 
    628     switch (msg) {
    629     case MEDIA_NOP: // interface test message
    630         break;
    631     case MEDIA_PREPARED:
    632         LOGV("prepared");
    633         mCurrentState = MEDIA_PLAYER_PREPARED;
    634         if (mPrepareSync) {
    635             LOGV("signal application thread");
    636             mPrepareSync = false;
    637             mPrepareStatus = NO_ERROR;
    638             mSignal.signal();
    639         }
    640         break;
    641     case MEDIA_PLAYBACK_COMPLETE:
    642         LOGV("playback complete");
    643         if (mCurrentState == MEDIA_PLAYER_IDLE) {
    644             LOGE("playback complete in idle state");
    645         }
    646         if (!mLoop) {
    647             mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;
    648         }
    649         break;
    650     case MEDIA_ERROR:
    651         // Always log errors.
    652         // ext1: Media framework error code.
    653         // ext2: Implementation dependant error code.
    654         LOGE("error (%d, %d)", ext1, ext2);
    655         mCurrentState = MEDIA_PLAYER_STATE_ERROR;
    656         if (mPrepareSync)
    657         {
    658             LOGV("signal application thread");
    659             mPrepareSync = false;
    660             mPrepareStatus = ext1;
    661             mSignal.signal();
    662             send = false;
    663         }
    664         break;
    665     case MEDIA_INFO:
    666         // ext1: Media framework error code.
    667         // ext2: Implementation dependant error code.
    668         if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) {
    669             LOGW("info/warning (%d, %d)", ext1, ext2);
    670         }
    671         break;
    672     case MEDIA_SEEK_COMPLETE:
    673         LOGV("Received seek complete");
    674         if (mSeekPosition != mCurrentPosition) {
    675             LOGV("Executing queued seekTo(%d)", mSeekPosition);
    676             mSeekPosition = -1;
    677             seekTo_l(mCurrentPosition);
    678         }
    679         else {
    680             LOGV("All seeks complete - return to regularly scheduled program");
    681             mCurrentPosition = mSeekPosition = -1;
    682         }
    683         break;
    684     case MEDIA_BUFFERING_UPDATE:
    685         LOGV("buffering %d", ext1);
    686         break;
    687     case MEDIA_SET_VIDEO_SIZE:
    688         LOGV("New video size %d x %d", ext1, ext2);
    689         mVideoWidth = ext1;
    690         mVideoHeight = ext2;
    691         break;
    692     case MEDIA_TIMED_TEXT:
    693         LOGV("Received timed text message");
    694         break;
    695     default:
    696         LOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
    697         break;
    698     }
    699 
    700     sp<MediaPlayerListener> listener = mListener;
    701     if (locked) mLock.unlock();
    702 
    703     // this prevents re-entrant calls into client code
    704     if ((listener != 0) && send) {
    705         Mutex::Autolock _l(mNotifyLock);
    706         LOGV("callback application");
    707         listener->notify(msg, ext1, ext2, obj);
    708         LOGV("back from callback");
    709     }
    710 }
    711 
    712 /*static*/ sp<IMemory> MediaPlayer::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
    713 {
    714     LOGV("decode(%s)", url);
    715     sp<IMemory> p;
    716     const sp<IMediaPlayerService>& service = getMediaPlayerService();
    717     if (service != 0) {
    718         p = service->decode(url, pSampleRate, pNumChannels, pFormat);
    719     } else {
    720         LOGE("Unable to locate media service");
    721     }
    722     return p;
    723 
    724 }
    725 
    726 void MediaPlayer::died()
    727 {
    728     LOGV("died");
    729     notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
    730 }
    731 
    732 /*static*/ sp<IMemory> MediaPlayer::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
    733 {
    734     LOGV("decode(%d, %lld, %lld)", fd, offset, length);
    735     sp<IMemory> p;
    736     const sp<IMediaPlayerService>& service = getMediaPlayerService();
    737     if (service != 0) {
    738         p = service->decode(fd, offset, length, pSampleRate, pNumChannels, pFormat);
    739     } else {
    740         LOGE("Unable to locate media service");
    741     }
    742     return p;
    743 
    744 }
    745 
    746 }; // namespace android
    747