Home | History | Annotate | Download | only in android
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //#define USE_LOG SLAndroidLogLevel_Verbose
     18 
     19 #include "sles_allinclusive.h"
     20 #include "android_GenericMediaPlayer.h"
     21 
     22 #include <system/window.h>
     23 
     24 #include <media/IMediaPlayerService.h>
     25 #include <media/stagefright/foundation/ADebug.h>
     26 #include <media/mediaplayer.h>  // media_event_type media_error_type media_info_type
     27 
     28 // default delay in Us used when reposting an event when the player is not ready to accept
     29 // the command yet. This is for instance used when seeking on a MediaPlayer that's still preparing
     30 #define DEFAULT_COMMAND_DELAY_FOR_REPOST_US (100*1000) // 100ms
     31 
     32 // table of prefixes for known distant protocols; these are immediately dispatched to mediaserver
     33 static const char* const kDistantProtocolPrefix[] = { "http://", "https://", "rtsp://"};
     34 #define NB_DISTANT_PROTOCOLS (sizeof(kDistantProtocolPrefix)/sizeof(kDistantProtocolPrefix[0]))
     35 
     36 // is the specified URI a known distant protocol?
     37 bool isDistantProtocol(const char *uri)
     38 {
     39     for (unsigned int i = 0; i < NB_DISTANT_PROTOCOLS; i++) {
     40         if (!strncasecmp(uri, kDistantProtocolPrefix[i], strlen(kDistantProtocolPrefix[i]))) {
     41             return true;
     42         }
     43     }
     44     return false;
     45 }
     46 
     47 namespace android {
     48 
     49 //--------------------------------------------------------------------------------------------------
     50 MediaPlayerNotificationClient::MediaPlayerNotificationClient(GenericMediaPlayer* gmp) :
     51     mGenericMediaPlayer(gmp),
     52     mPlayerPrepared(PREPARE_NOT_STARTED)
     53 {
     54     SL_LOGV("MediaPlayerNotificationClient::MediaPlayerNotificationClient()");
     55 }
     56 
     57 MediaPlayerNotificationClient::~MediaPlayerNotificationClient() {
     58     SL_LOGV("MediaPlayerNotificationClient::~MediaPlayerNotificationClient()");
     59 }
     60 
     61 // Map a media_event_type enum (the msg of an IMediaPlayerClient::notify) to a string or NULL
     62 static const char *media_event_type_to_string(media_event_type msg)
     63 {
     64     switch (msg) {
     65 #define _(code) case code: return #code;
     66     _(MEDIA_NOP)
     67     _(MEDIA_PREPARED)
     68     _(MEDIA_PLAYBACK_COMPLETE)
     69     _(MEDIA_BUFFERING_UPDATE)
     70     _(MEDIA_SEEK_COMPLETE)
     71     _(MEDIA_SET_VIDEO_SIZE)
     72     _(MEDIA_TIMED_TEXT)
     73     _(MEDIA_ERROR)
     74     _(MEDIA_INFO)
     75 #undef _
     76     default:
     77         return NULL;
     78     }
     79 }
     80 
     81 // Map a media_error_type enum (the ext1 of a MEDIA_ERROR event) to a string or NULL
     82 static const char *media_error_type_to_string(media_error_type err)
     83 {
     84     switch (err) {
     85 #define _(code, msg) case code: return msg;
     86     _(MEDIA_ERROR_UNKNOWN,                              "Unknown media error")
     87     _(MEDIA_ERROR_SERVER_DIED,                          "Server died")
     88     _(MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK,   "Not valid for progressive playback")
     89 #undef _
     90     default:
     91         return NULL;
     92     }
     93 }
     94 
     95 // Map a media_info_type enum (the ext1 of a MEDIA_INFO event) to a string or NULL
     96 static const char *media_info_type_to_string(media_info_type info)
     97 {
     98     switch (info) {
     99 #define _(code, msg) case code: return msg;
    100     _(MEDIA_INFO_UNKNOWN,             "Unknown info")
    101     _(MEDIA_INFO_VIDEO_TRACK_LAGGING, "Video track lagging")
    102     _(MEDIA_INFO_BUFFERING_START,     "Buffering start")
    103     _(MEDIA_INFO_BUFFERING_END,       "Buffering end")
    104     _(MEDIA_INFO_NETWORK_BANDWIDTH,   "Network bandwidth")
    105     _(MEDIA_INFO_BAD_INTERLEAVING,    "Bad interleaving")
    106     _(MEDIA_INFO_NOT_SEEKABLE,        "Not seekable")
    107     _(MEDIA_INFO_METADATA_UPDATE,     "Metadata update")
    108 #undef _
    109     default:
    110         return NULL;
    111     }
    112 }
    113 
    114 //--------------------------------------------------
    115 // IMediaPlayerClient implementation
    116 void MediaPlayerNotificationClient::notify(int msg, int ext1, int ext2, const Parcel *obj) {
    117     (void)media_event_type_to_string; // Suppresses -Wunused-function.
    118     SL_LOGV("MediaPlayerNotificationClient::notify(msg=%s (%d), ext1=%d, ext2=%d)",
    119             media_event_type_to_string((enum media_event_type) msg), msg, ext1, ext2);
    120 
    121     sp<GenericMediaPlayer> genericMediaPlayer(mGenericMediaPlayer.promote());
    122     if (genericMediaPlayer == NULL) {
    123         SL_LOGW("MediaPlayerNotificationClient::notify after GenericMediaPlayer destroyed");
    124         return;
    125     }
    126 
    127     switch ((media_event_type) msg) {
    128       case MEDIA_PREPARED:
    129         {
    130         Mutex::Autolock _l(mLock);
    131         if (PREPARE_IN_PROGRESS == mPlayerPrepared) {
    132             mPlayerPrepared = PREPARE_COMPLETED_SUCCESSFULLY;
    133             mPlayerPreparedCondition.signal();
    134         } else {
    135             SL_LOGE("Unexpected MEDIA_PREPARED");
    136         }
    137         }
    138         break;
    139 
    140       case MEDIA_SET_VIDEO_SIZE:
    141         // only send video size updates if the player was flagged as having video, to avoid
    142         // sending video size updates of (0,0)
    143         // We're running on a different thread than genericMediaPlayer's ALooper thread,
    144         // so it would normally be racy to access fields within genericMediaPlayer.
    145         // But in this case mHasVideo is const, so it is safe to access.
    146         // Or alternatively, we could notify unconditionally and let it decide whether to handle.
    147         if (genericMediaPlayer->mHasVideo && (ext1 != 0 || ext2 != 0)) {
    148             genericMediaPlayer->notify(PLAYEREVENT_VIDEO_SIZE_UPDATE,
    149                     (int32_t)ext1 /*width*/, (int32_t)ext2 /*height*/, true /*async*/);
    150         }
    151         break;
    152 
    153       case MEDIA_SEEK_COMPLETE:
    154         genericMediaPlayer->seekComplete();
    155         break;
    156 
    157       case MEDIA_PLAYBACK_COMPLETE:
    158         genericMediaPlayer->notify(PLAYEREVENT_ENDOFSTREAM, 1, true /*async*/);
    159         break;
    160 
    161       case MEDIA_BUFFERING_UPDATE:
    162         // if we receive any out-of-range data, then clamp it to reduce further harm
    163         if (ext1 < 0) {
    164             SL_LOGE("MEDIA_BUFFERING_UPDATE %d%% < 0", ext1);
    165             ext1 = 0;
    166         } else if (ext1 > 100) {
    167             SL_LOGE("MEDIA_BUFFERING_UPDATE %d%% > 100", ext1);
    168             ext1 = 100;
    169         }
    170         // values received from Android framework for buffer fill level use percent,
    171         //   while SL/XA use permille, so does GenericPlayer
    172         genericMediaPlayer->bufferingUpdate(ext1 * 10 /*fillLevelPerMille*/);
    173         break;
    174 
    175       case MEDIA_ERROR:
    176         {
    177         (void)media_error_type_to_string; // Suppresses -Wunused-function.
    178         SL_LOGV("MediaPlayerNotificationClient::notify(msg=MEDIA_ERROR, ext1=%s (%d), ext2=%d)",
    179                 media_error_type_to_string((media_error_type) ext1), ext1, ext2);
    180         Mutex::Autolock _l(mLock);
    181         if (PREPARE_IN_PROGRESS == mPlayerPrepared) {
    182             mPlayerPrepared = PREPARE_COMPLETED_UNSUCCESSFULLY;
    183             mPlayerPreparedCondition.signal();
    184         } else {
    185             // inform client of errors after preparation
    186             genericMediaPlayer->notify(PLAYEREVENT_ERRORAFTERPREPARE, ext1, true /*async*/);
    187         }
    188         }
    189         break;
    190 
    191       case MEDIA_NOP:
    192       case MEDIA_TIMED_TEXT:
    193         break;
    194 
    195       case MEDIA_INFO:
    196         (void)media_info_type_to_string; // Suppresses -Wunused-function.
    197         SL_LOGV("MediaPlayerNotificationClient::notify(msg=MEDIA_INFO, ext1=%s (%d), ext2=%d)",
    198                 media_info_type_to_string((media_info_type) ext1), ext1, ext2);
    199         switch (ext1) {
    200         case MEDIA_INFO_VIDEO_TRACK_LAGGING:
    201             SL_LOGV("MEDIA_INFO_VIDEO_TRACK_LAGGING by %d ms", ext1);
    202             break;
    203         case MEDIA_INFO_NETWORK_BANDWIDTH:
    204             SL_LOGV("MEDIA_INFO_NETWORK_BANDWIDTH %d kbps", ext2);
    205             break;
    206         case MEDIA_INFO_UNKNOWN:
    207         case MEDIA_INFO_BUFFERING_START:
    208         case MEDIA_INFO_BUFFERING_END:
    209         case MEDIA_INFO_BAD_INTERLEAVING:
    210         case MEDIA_INFO_NOT_SEEKABLE:
    211         case MEDIA_INFO_METADATA_UPDATE:
    212         default:
    213             break;
    214         }
    215         break;
    216 
    217       default:
    218         break;
    219     }
    220 
    221 }
    222 
    223 //--------------------------------------------------
    224 void MediaPlayerNotificationClient::beforePrepare()
    225 {
    226     Mutex::Autolock _l(mLock);
    227     assert(mPlayerPrepared == PREPARE_NOT_STARTED);
    228     mPlayerPrepared = PREPARE_IN_PROGRESS;
    229 }
    230 
    231 //--------------------------------------------------
    232 bool MediaPlayerNotificationClient::blockUntilPlayerPrepared() {
    233     Mutex::Autolock _l(mLock);
    234     assert(mPlayerPrepared != PREPARE_NOT_STARTED);
    235     while (mPlayerPrepared == PREPARE_IN_PROGRESS) {
    236         mPlayerPreparedCondition.wait(mLock);
    237     }
    238     assert(mPlayerPrepared == PREPARE_COMPLETED_SUCCESSFULLY ||
    239             mPlayerPrepared == PREPARE_COMPLETED_UNSUCCESSFULLY);
    240     return mPlayerPrepared == PREPARE_COMPLETED_SUCCESSFULLY;
    241 }
    242 
    243 //--------------------------------------------------------------------------------------------------
    244 GenericMediaPlayer::GenericMediaPlayer(const AudioPlayback_Parameters* params, bool hasVideo) :
    245     GenericPlayer(params),
    246     mHasVideo(hasVideo),
    247     mSeekTimeMsec(0),
    248     mVideoSurfaceTexture(0),
    249     mPlayer(0),
    250     mPlayerClient(new MediaPlayerNotificationClient(this)),
    251     mPlayerDeathNotifier(new MediaPlayerDeathNotifier(mPlayerClient))
    252 {
    253     SL_LOGD("GenericMediaPlayer::GenericMediaPlayer()");
    254 
    255 }
    256 
    257 GenericMediaPlayer::~GenericMediaPlayer() {
    258     SL_LOGD("GenericMediaPlayer::~GenericMediaPlayer()");
    259 }
    260 
    261 void GenericMediaPlayer::preDestroy() {
    262     // FIXME can't access mPlayer from outside the looper (no mutex!) so using mPreparedPlayer
    263     sp<IMediaPlayer> player;
    264     getPreparedPlayer(player);
    265     if (player != NULL) {
    266         player->stop();
    267         // causes CHECK failure in Nuplayer, but commented out in the subclass preDestroy
    268         // randomly causes a NPE in StagefrightPlayer, heap corruption, or app hang
    269         //player->setDataSource(NULL);
    270         player->setVideoSurfaceTexture(NULL);
    271         player->disconnect();
    272         // release all references to the IMediaPlayer
    273         // FIXME illegal if not on looper
    274         //mPlayer.clear();
    275         {
    276             Mutex::Autolock _l(mPreparedPlayerLock);
    277             mPreparedPlayer.clear();
    278         }
    279     }
    280     GenericPlayer::preDestroy();
    281 }
    282 
    283 //--------------------------------------------------
    284 // overridden from GenericPlayer
    285 // pre-condition:
    286 //   msec != NULL
    287 // post-condition
    288 //   *msec ==
    289 //                  ANDROID_UNKNOWN_TIME if position is unknown at time of query,
    290 //               or the current MediaPlayer position
    291 void GenericMediaPlayer::getPositionMsec(int* msec) {
    292     SL_LOGD("GenericMediaPlayer::getPositionMsec()");
    293     sp<IMediaPlayer> player;
    294     getPreparedPlayer(player);
    295     // To avoid deadlock, directly call the MediaPlayer object
    296     if (player == 0 || player->getCurrentPosition(msec) != NO_ERROR) {
    297         *msec = ANDROID_UNKNOWN_TIME;
    298     }
    299 }
    300 
    301 //--------------------------------------------------
    302 void GenericMediaPlayer::setVideoSurfaceTexture(const sp<IGraphicBufferProducer> &bufferProducer) {
    303     SL_LOGV("GenericMediaPlayer::setVideoSurfaceTexture()");
    304     // FIXME bug - race condition, should do in looper
    305     if (mVideoSurfaceTexture.get() == bufferProducer.get()) {
    306         return;
    307     }
    308     if ((mStateFlags & kFlagPrepared) && (mPlayer != 0)) {
    309         mPlayer->setVideoSurfaceTexture(bufferProducer);
    310     }
    311     mVideoSurfaceTexture = bufferProducer;
    312 }
    313 
    314 //--------------------------------------------------
    315 void GenericMediaPlayer::setPlaybackRate(int32_t ratePermille) {
    316     SL_LOGV("GenericMediaPlayer::setPlaybackRate(%d)", ratePermille);
    317     GenericPlayer::setPlaybackRate(ratePermille);
    318     sp<IMediaPlayer> player;
    319     getPreparedPlayer(player);
    320     if (player != 0) {
    321         Parcel rateParcel;
    322         if (rateParcel.writeInt32(ratePermille) == OK) {
    323             player->setParameter(KEY_PARAMETER_PLAYBACK_RATE_PERMILLE, rateParcel);
    324         }
    325     }
    326 }
    327 
    328 
    329 //--------------------------------------------------
    330 // Event handlers
    331 
    332 // blocks until mPlayer is prepared
    333 void GenericMediaPlayer::onPrepare() {
    334     SL_LOGD("GenericMediaPlayer::onPrepare()");
    335     // Attempt to prepare at most once, and only if there is a MediaPlayer
    336     if (!(mStateFlags & (kFlagPrepared | kFlagPreparedUnsuccessfully)) && (mPlayer != 0)) {
    337         if (mHasVideo) {
    338             if (mVideoSurfaceTexture != 0) {
    339                 mPlayer->setVideoSurfaceTexture(mVideoSurfaceTexture);
    340             }
    341         }
    342         mPlayer->setAudioStreamType(mPlaybackParams.streamType);
    343         mPlayerClient->beforePrepare();
    344         mPlayer->prepareAsync();
    345         if (mPlayerClient->blockUntilPlayerPrepared()) {
    346             mStateFlags |= kFlagPrepared;
    347             afterMediaPlayerPreparedSuccessfully();
    348         } else {
    349             mStateFlags |= kFlagPreparedUnsuccessfully;
    350         }
    351     }
    352     GenericPlayer::onPrepare();
    353     SL_LOGD("GenericMediaPlayer::onPrepare() done, mStateFlags=0x%x", mStateFlags);
    354 }
    355 
    356 
    357 void GenericMediaPlayer::onPlay() {
    358     SL_LOGD("GenericMediaPlayer::onPlay()");
    359     if (((mStateFlags & (kFlagPrepared | kFlagPlaying)) == kFlagPrepared) && (mPlayer != 0)) {
    360         mPlayer->start();
    361     }
    362     GenericPlayer::onPlay();
    363 }
    364 
    365 
    366 void GenericMediaPlayer::onPause() {
    367     SL_LOGD("GenericMediaPlayer::onPause()");
    368     if (!(~mStateFlags & (kFlagPrepared | kFlagPlaying)) && (mPlayer != 0)) {
    369         mPlayer->pause();
    370     }
    371     GenericPlayer::onPause();
    372 }
    373 
    374 
    375 void GenericMediaPlayer::onSeekComplete() {
    376     SL_LOGV("GenericMediaPlayer::onSeekComplete()");
    377     // did we initiate the seek?
    378     if (!(mStateFlags & kFlagSeeking)) {
    379         // no, are we looping?
    380         if (mStateFlags & kFlagLooping) {
    381             // yes, per OpenSL ES 1.0.1 and 1.1 do NOT report it to client
    382             // notify(PLAYEREVENT_ENDOFSTREAM, 1, true /*async*/);
    383         // no, well that's surprising, but it's probably just a benign race condition
    384         } else {
    385             SL_LOGW("Unexpected seek complete event ignored");
    386         }
    387     }
    388     GenericPlayer::onSeekComplete();
    389 }
    390 
    391 
    392 /**
    393  * pre-condition: WHATPARAM_SEEK_SEEKTIME_MS parameter value >= 0
    394  */
    395 void GenericMediaPlayer::onSeek(const sp<AMessage> &msg) {
    396     SL_LOGV("GenericMediaPlayer::onSeek");
    397     int64_t timeMsec = ANDROID_UNKNOWN_TIME;
    398     if (!msg->findInt64(WHATPARAM_SEEK_SEEKTIME_MS, &timeMsec)) {
    399         // invalid command, drop it
    400         return;
    401     }
    402     if ((mStateFlags & kFlagSeeking) && (timeMsec == mSeekTimeMsec) &&
    403             (timeMsec != ANDROID_UNKNOWN_TIME)) {
    404         // already seeking to the same non-unknown time, cancel this command
    405         return;
    406     } else if (mStateFlags & kFlagPreparedUnsuccessfully) {
    407         // discard seeks after unsuccessful prepare
    408     } else if (!(mStateFlags & kFlagPrepared)) {
    409         // we are not ready to accept a seek command at this time, retry later
    410         msg->post(DEFAULT_COMMAND_DELAY_FOR_REPOST_US);
    411     } else {
    412         if (mPlayer != 0) {
    413             mStateFlags |= kFlagSeeking;
    414             mSeekTimeMsec = (int32_t)timeMsec;
    415             // seek to unknown time is used by StreamPlayer after discontinuity
    416             if (timeMsec == ANDROID_UNKNOWN_TIME) {
    417                 // FIXME simulate a MEDIA_SEEK_COMPLETE event in 250 ms;
    418                 // this is a terrible hack to make up for mediaserver not sending one
    419                 (new AMessage(kWhatSeekComplete, this))->post(250000);
    420             } else if (OK != mPlayer->seekTo(timeMsec)) {
    421                 mStateFlags &= ~kFlagSeeking;
    422                 mSeekTimeMsec = ANDROID_UNKNOWN_TIME;
    423                 // don't call updateOneShot because seek not yet done
    424             }
    425         }
    426     }
    427 }
    428 
    429 
    430 void GenericMediaPlayer::onLoop(const sp<AMessage> &msg) {
    431     SL_LOGV("GenericMediaPlayer::onLoop");
    432     int32_t loop = 0;
    433     if (msg->findInt32(WHATPARAM_LOOP_LOOPING, &loop)) {
    434         if (loop) {
    435             mStateFlags |= kFlagLooping;
    436         } else {
    437             mStateFlags &= ~kFlagLooping;
    438         }
    439         // if we have a MediaPlayer then tell it now, otherwise we'll tell it after it's created
    440         if (mPlayer != 0) {
    441             (void) mPlayer->setLooping(loop);
    442         }
    443     }
    444 }
    445 
    446 
    447 void GenericMediaPlayer::onVolumeUpdate() {
    448     SL_LOGD("GenericMediaPlayer::onVolumeUpdate()");
    449     if (mPlayer != 0) {
    450         // use settings lock to read the volume settings
    451         Mutex::Autolock _l(mSettingsLock);
    452         mPlayer->setVolume(mAndroidAudioLevels.mFinalVolume[0],
    453                 mAndroidAudioLevels.mFinalVolume[1]);
    454     }
    455 }
    456 
    457 
    458 void GenericMediaPlayer::onAttachAuxEffect(const sp<AMessage> &msg) {
    459     SL_LOGD("GenericMediaPlayer::onAttachAuxEffect()");
    460     int32_t effectId = 0;
    461     if (msg->findInt32(WHATPARAM_ATTACHAUXEFFECT, &effectId)) {
    462         if (mPlayer != 0) {
    463             status_t status;
    464             status = mPlayer->attachAuxEffect(effectId);
    465             // attachAuxEffect returns a status but we have no way to report it back to app
    466             (void) status;
    467         }
    468     }
    469 }
    470 
    471 
    472 void GenericMediaPlayer::onSetAuxEffectSendLevel(const sp<AMessage> &msg) {
    473     SL_LOGD("GenericMediaPlayer::onSetAuxEffectSendLevel()");
    474     float level = 0.0f;
    475     if (msg->findFloat(WHATPARAM_SETAUXEFFECTSENDLEVEL, &level)) {
    476         if (mPlayer != 0) {
    477             status_t status;
    478             status = mPlayer->setAuxEffectSendLevel(level);
    479             // setAuxEffectSendLevel returns a status but we have no way to report it back to app
    480             (void) status;
    481         }
    482     }
    483 }
    484 
    485 
    486 void GenericMediaPlayer::onBufferingUpdate(const sp<AMessage> &msg) {
    487     int32_t fillLevel = 0;
    488     if (msg->findInt32(WHATPARAM_BUFFERING_UPDATE, &fillLevel)) {
    489         SL_LOGD("GenericMediaPlayer::onBufferingUpdate(fillLevel=%d)", fillLevel);
    490 
    491         Mutex::Autolock _l(mSettingsLock);
    492         mCacheFill = fillLevel;
    493         // handle cache fill update
    494         if (mCacheFill - mLastNotifiedCacheFill >= mCacheFillNotifThreshold) {
    495             notifyCacheFill();
    496         }
    497         // handle prefetch status update
    498         //   compute how much time ahead of position is buffered
    499         int durationMsec, positionMsec = -1;
    500         if ((mStateFlags & kFlagPrepared) && (mPlayer != 0)
    501                 && (OK == mPlayer->getDuration(&durationMsec))
    502                         && (OK == mPlayer->getCurrentPosition(&positionMsec))) {
    503             if ((-1 != durationMsec) && (-1 != positionMsec)) {
    504                 // evaluate prefetch status based on buffer time thresholds
    505                 int64_t bufferedDurationMsec = (durationMsec * fillLevel / 100) - positionMsec;
    506                 CacheStatus_t newCacheStatus = mCacheStatus;
    507                 if (bufferedDurationMsec > DURATION_CACHED_HIGH_MS) {
    508                     newCacheStatus = kStatusHigh;
    509                 } else if (bufferedDurationMsec > DURATION_CACHED_MED_MS) {
    510                     newCacheStatus = kStatusEnough;
    511                 } else if (bufferedDurationMsec > DURATION_CACHED_LOW_MS) {
    512                     newCacheStatus = kStatusIntermediate;
    513                 } else if (bufferedDurationMsec == 0) {
    514                     newCacheStatus = kStatusEmpty;
    515                 } else {
    516                     newCacheStatus = kStatusLow;
    517                 }
    518 
    519                 if (newCacheStatus != mCacheStatus) {
    520                     mCacheStatus = newCacheStatus;
    521                     notifyStatus();
    522                 }
    523             }
    524         }
    525     } else {
    526         SL_LOGV("GenericMediaPlayer::onBufferingUpdate(fillLevel=unknown)");
    527     }
    528 }
    529 
    530 
    531 //--------------------------------------------------
    532 /**
    533  * called from GenericMediaPlayer::onPrepare after the MediaPlayer mPlayer is prepared successfully
    534  * pre-conditions:
    535  *  mPlayer != 0
    536  *  mPlayer is prepared successfully
    537  */
    538 void GenericMediaPlayer::afterMediaPlayerPreparedSuccessfully() {
    539     SL_LOGV("GenericMediaPlayer::afterMediaPlayerPrepared()");
    540     assert(mPlayer != 0);
    541     assert(mStateFlags & kFlagPrepared);
    542     // Mark this player as prepared successfully, so safe to directly call getCurrentPosition
    543     {
    544         Mutex::Autolock _l(mPreparedPlayerLock);
    545         assert(mPreparedPlayer == 0);
    546         mPreparedPlayer = mPlayer;
    547     }
    548     // retrieve channel count
    549     int32_t channelCount;
    550     Parcel *reply = new Parcel();
    551     status_t status = mPlayer->getParameter(KEY_PARAMETER_AUDIO_CHANNEL_COUNT, reply);
    552     if (status == NO_ERROR) {
    553         channelCount = reply->readInt32();
    554     } else {
    555         // FIXME MPEG-2 TS doesn't yet implement this key, so default to stereo
    556         channelCount = 2;
    557     }
    558     if (UNKNOWN_NUMCHANNELS != channelCount) {
    559         // now that we know the channel count, re-calculate the volumes
    560         notify(PLAYEREVENT_CHANNEL_COUNT, channelCount, true /*async*/);
    561     } else {
    562         ALOGW("channel count is still unknown after prepare");
    563     }
    564     delete reply;
    565     // retrieve duration
    566     {
    567         int msec = 0;
    568         if (OK == mPlayer->getDuration(&msec)) {
    569             Mutex::Autolock _l(mSettingsLock);
    570             mDurationMsec = msec;
    571         }
    572     }
    573     // now that we have a MediaPlayer, set the looping flag
    574     if (mStateFlags & kFlagLooping) {
    575         (void) mPlayer->setLooping(1);
    576     }
    577     // when the MediaPlayer mPlayer is prepared, there is "sufficient data" in the playback buffers
    578     // if the data source was local, and the buffers are considered full so we need to notify that
    579     bool isLocalSource = true;
    580     if (kDataLocatorUri == mDataLocatorType) {
    581         isLocalSource = !isDistantProtocol(mDataLocator.uriRef);
    582     }
    583     if (isLocalSource) {
    584         SL_LOGD("media player prepared on local source");
    585         {
    586             Mutex::Autolock _l(mSettingsLock);
    587             mCacheStatus = kStatusHigh;
    588             mCacheFill = 1000;
    589             notifyStatus();
    590             notifyCacheFill();
    591         }
    592     } else {
    593         SL_LOGD("media player prepared on non-local source");
    594     }
    595     // when the MediaPlayer mPlayer is prepared, apply the playback rate
    596     Parcel rateParcel;
    597     if (rateParcel.writeInt32((int32_t)mPlaybackRatePermille) == OK) {
    598         mPlayer->setParameter(KEY_PARAMETER_PLAYBACK_RATE_PERMILLE, rateParcel);
    599     }
    600 }
    601 
    602 
    603 //--------------------------------------------------
    604 // If player is prepared successfully, set output parameter to that reference, otherwise NULL
    605 void GenericMediaPlayer::getPreparedPlayer(sp<IMediaPlayer> &preparedPlayer)
    606 {
    607     Mutex::Autolock _l(mPreparedPlayerLock);
    608     preparedPlayer = mPreparedPlayer;
    609 }
    610 
    611 } // namespace android
    612