Home | History | Annotate | Download | only in libstagefright
      1 /*
      2  * Copyright (C) 2009 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 #undef DEBUG_HDCP
     18 
     19 //#define LOG_NDEBUG 0
     20 #define LOG_TAG "AwesomePlayer"
     21 #include <utils/Log.h>
     22 
     23 #include <dlfcn.h>
     24 
     25 #include "include/ARTSPController.h"
     26 #include "include/AwesomePlayer.h"
     27 #include "include/DRMExtractor.h"
     28 #include "include/SoftwareRenderer.h"
     29 #include "include/NuCachedSource2.h"
     30 #include "include/ThrottledSource.h"
     31 #include "include/MPEG2TSExtractor.h"
     32 #include "include/WVMExtractor.h"
     33 
     34 #include "timedtext/TimedTextPlayer.h"
     35 
     36 #include <binder/IPCThreadState.h>
     37 #include <binder/IServiceManager.h>
     38 #include <media/IMediaPlayerService.h>
     39 #include <media/stagefright/foundation/hexdump.h>
     40 #include <media/stagefright/foundation/ADebug.h>
     41 #include <media/stagefright/AudioPlayer.h>
     42 #include <media/stagefright/DataSource.h>
     43 #include <media/stagefright/FileSource.h>
     44 #include <media/stagefright/MediaBuffer.h>
     45 #include <media/stagefright/MediaDefs.h>
     46 #include <media/stagefright/MediaExtractor.h>
     47 #include <media/stagefright/MediaSource.h>
     48 #include <media/stagefright/MetaData.h>
     49 #include <media/stagefright/OMXCodec.h>
     50 
     51 #include <surfaceflinger/Surface.h>
     52 #include <gui/ISurfaceTexture.h>
     53 #include <gui/SurfaceTextureClient.h>
     54 #include <surfaceflinger/ISurfaceComposer.h>
     55 
     56 #include <media/stagefright/foundation/ALooper.h>
     57 #include <media/stagefright/foundation/AMessage.h>
     58 
     59 #include <cutils/properties.h>
     60 
     61 #define USE_SURFACE_ALLOC 1
     62 #define FRAME_DROP_FREQ 0
     63 
     64 namespace android {
     65 
     66 static int64_t kLowWaterMarkUs = 2000000ll;  // 2secs
     67 static int64_t kHighWaterMarkUs = 5000000ll;  // 5secs
     68 static int64_t kHighWaterMarkRTSPUs = 4000000ll;  // 4secs
     69 static const size_t kLowWaterMarkBytes = 40000;
     70 static const size_t kHighWaterMarkBytes = 200000;
     71 
     72 struct AwesomeEvent : public TimedEventQueue::Event {
     73     AwesomeEvent(
     74             AwesomePlayer *player,
     75             void (AwesomePlayer::*method)())
     76         : mPlayer(player),
     77           mMethod(method) {
     78     }
     79 
     80 protected:
     81     virtual ~AwesomeEvent() {}
     82 
     83     virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
     84         (mPlayer->*mMethod)();
     85     }
     86 
     87 private:
     88     AwesomePlayer *mPlayer;
     89     void (AwesomePlayer::*mMethod)();
     90 
     91     AwesomeEvent(const AwesomeEvent &);
     92     AwesomeEvent &operator=(const AwesomeEvent &);
     93 };
     94 
     95 struct AwesomeLocalRenderer : public AwesomeRenderer {
     96     AwesomeLocalRenderer(
     97             const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta)
     98         : mTarget(new SoftwareRenderer(nativeWindow, meta)) {
     99     }
    100 
    101     virtual void render(MediaBuffer *buffer) {
    102         render((const uint8_t *)buffer->data() + buffer->range_offset(),
    103                buffer->range_length());
    104     }
    105 
    106     void render(const void *data, size_t size) {
    107         mTarget->render(data, size, NULL);
    108     }
    109 
    110 protected:
    111     virtual ~AwesomeLocalRenderer() {
    112         delete mTarget;
    113         mTarget = NULL;
    114     }
    115 
    116 private:
    117     SoftwareRenderer *mTarget;
    118 
    119     AwesomeLocalRenderer(const AwesomeLocalRenderer &);
    120     AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
    121 };
    122 
    123 struct AwesomeNativeWindowRenderer : public AwesomeRenderer {
    124     AwesomeNativeWindowRenderer(
    125             const sp<ANativeWindow> &nativeWindow,
    126             int32_t rotationDegrees)
    127         : mNativeWindow(nativeWindow) {
    128         applyRotation(rotationDegrees);
    129     }
    130 
    131     virtual void render(MediaBuffer *buffer) {
    132         int64_t timeUs;
    133         CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
    134         native_window_set_buffers_timestamp(mNativeWindow.get(), timeUs * 1000);
    135         status_t err = mNativeWindow->queueBuffer(
    136                 mNativeWindow.get(), buffer->graphicBuffer().get());
    137         if (err != 0) {
    138             LOGE("queueBuffer failed with error %s (%d)", strerror(-err),
    139                     -err);
    140             return;
    141         }
    142 
    143         sp<MetaData> metaData = buffer->meta_data();
    144         metaData->setInt32(kKeyRendered, 1);
    145     }
    146 
    147 protected:
    148     virtual ~AwesomeNativeWindowRenderer() {}
    149 
    150 private:
    151     sp<ANativeWindow> mNativeWindow;
    152 
    153     void applyRotation(int32_t rotationDegrees) {
    154         uint32_t transform;
    155         switch (rotationDegrees) {
    156             case 0: transform = 0; break;
    157             case 90: transform = HAL_TRANSFORM_ROT_90; break;
    158             case 180: transform = HAL_TRANSFORM_ROT_180; break;
    159             case 270: transform = HAL_TRANSFORM_ROT_270; break;
    160             default: transform = 0; break;
    161         }
    162 
    163         if (transform) {
    164             CHECK_EQ(0, native_window_set_buffers_transform(
    165                         mNativeWindow.get(), transform));
    166         }
    167     }
    168 
    169     AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &);
    170     AwesomeNativeWindowRenderer &operator=(
    171             const AwesomeNativeWindowRenderer &);
    172 };
    173 
    174 // To collect the decoder usage
    175 void addBatteryData(uint32_t params) {
    176     sp<IBinder> binder =
    177         defaultServiceManager()->getService(String16("media.player"));
    178     sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
    179     CHECK(service.get() != NULL);
    180 
    181     service->addBatteryData(params);
    182 }
    183 
    184 ////////////////////////////////////////////////////////////////////////////////
    185 AwesomePlayer::AwesomePlayer()
    186     : mQueueStarted(false),
    187       mUIDValid(false),
    188       mTimeSource(NULL),
    189       mVideoRendererIsPreview(false),
    190       mAudioPlayer(NULL),
    191       mDisplayWidth(0),
    192       mDisplayHeight(0),
    193       mFlags(0),
    194       mExtractorFlags(0),
    195       mVideoBuffer(NULL),
    196       mDecryptHandle(NULL),
    197       mLastVideoTimeUs(-1),
    198       mTextPlayer(NULL) {
    199     CHECK_EQ(mClient.connect(), (status_t)OK);
    200 
    201     DataSource::RegisterDefaultSniffers();
    202 
    203     mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
    204     mVideoEventPending = false;
    205     mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
    206     mStreamDoneEventPending = false;
    207     mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
    208     mBufferingEventPending = false;
    209     mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate);
    210     mVideoEventPending = false;
    211 
    212     mCheckAudioStatusEvent = new AwesomeEvent(
    213             this, &AwesomePlayer::onCheckAudioStatus);
    214 
    215     mAudioStatusEventPending = false;
    216 
    217     reset();
    218 }
    219 
    220 AwesomePlayer::~AwesomePlayer() {
    221     if (mQueueStarted) {
    222         mQueue.stop();
    223     }
    224 
    225     reset();
    226 
    227     mClient.disconnect();
    228 }
    229 
    230 void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
    231     mQueue.cancelEvent(mVideoEvent->eventID());
    232     mVideoEventPending = false;
    233     mQueue.cancelEvent(mStreamDoneEvent->eventID());
    234     mStreamDoneEventPending = false;
    235     mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
    236     mAudioStatusEventPending = false;
    237     mQueue.cancelEvent(mVideoLagEvent->eventID());
    238     mVideoLagEventPending = false;
    239 
    240     if (!keepBufferingGoing) {
    241         mQueue.cancelEvent(mBufferingEvent->eventID());
    242         mBufferingEventPending = false;
    243     }
    244 }
    245 
    246 void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
    247     Mutex::Autolock autoLock(mLock);
    248     mListener = listener;
    249 }
    250 
    251 void AwesomePlayer::setUID(uid_t uid) {
    252     LOGV("AwesomePlayer running on behalf of uid %d", uid);
    253 
    254     mUID = uid;
    255     mUIDValid = true;
    256 }
    257 
    258 status_t AwesomePlayer::setDataSource(
    259         const char *uri, const KeyedVector<String8, String8> *headers) {
    260     Mutex::Autolock autoLock(mLock);
    261     return setDataSource_l(uri, headers);
    262 }
    263 
    264 status_t AwesomePlayer::setDataSource_l(
    265         const char *uri, const KeyedVector<String8, String8> *headers) {
    266     reset_l();
    267 
    268     mUri = uri;
    269 
    270     if (headers) {
    271         mUriHeaders = *headers;
    272 
    273         ssize_t index = mUriHeaders.indexOfKey(String8("x-hide-urls-from-log"));
    274         if (index >= 0) {
    275             // Browser is in "incognito" mode, suppress logging URLs.
    276 
    277             // This isn't something that should be passed to the server.
    278             mUriHeaders.removeItemsAt(index);
    279 
    280             modifyFlags(INCOGNITO, SET);
    281         }
    282     }
    283 
    284     if (!(mFlags & INCOGNITO)) {
    285         LOGI("setDataSource_l('%s')", mUri.string());
    286     } else {
    287         LOGI("setDataSource_l(URL suppressed)");
    288     }
    289 
    290     // The actual work will be done during preparation in the call to
    291     // ::finishSetDataSource_l to avoid blocking the calling thread in
    292     // setDataSource for any significant time.
    293 
    294     {
    295         Mutex::Autolock autoLock(mStatsLock);
    296         mStats.mFd = -1;
    297         mStats.mURI = mUri;
    298     }
    299 
    300     return OK;
    301 }
    302 
    303 status_t AwesomePlayer::setDataSource(
    304         int fd, int64_t offset, int64_t length) {
    305     Mutex::Autolock autoLock(mLock);
    306 
    307     reset_l();
    308 
    309     sp<DataSource> dataSource = new FileSource(fd, offset, length);
    310 
    311     status_t err = dataSource->initCheck();
    312 
    313     if (err != OK) {
    314         return err;
    315     }
    316 
    317     mFileSource = dataSource;
    318 
    319     {
    320         Mutex::Autolock autoLock(mStatsLock);
    321         mStats.mFd = fd;
    322         mStats.mURI = String8();
    323     }
    324 
    325     return setDataSource_l(dataSource);
    326 }
    327 
    328 status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) {
    329     return INVALID_OPERATION;
    330 }
    331 
    332 status_t AwesomePlayer::setDataSource_l(
    333         const sp<DataSource> &dataSource) {
    334     sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
    335 
    336     if (extractor == NULL) {
    337         return UNKNOWN_ERROR;
    338     }
    339 
    340     dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
    341     if (mDecryptHandle != NULL) {
    342         CHECK(mDrmManagerClient);
    343         if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
    344             notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
    345         }
    346     }
    347 
    348     return setDataSource_l(extractor);
    349 }
    350 
    351 status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
    352     // Attempt to approximate overall stream bitrate by summing all
    353     // tracks' individual bitrates, if not all of them advertise bitrate,
    354     // we have to fail.
    355 
    356     int64_t totalBitRate = 0;
    357 
    358     for (size_t i = 0; i < extractor->countTracks(); ++i) {
    359         sp<MetaData> meta = extractor->getTrackMetaData(i);
    360 
    361         int32_t bitrate;
    362         if (!meta->findInt32(kKeyBitRate, &bitrate)) {
    363             const char *mime;
    364             CHECK(meta->findCString(kKeyMIMEType, &mime));
    365             LOGV("track of type '%s' does not publish bitrate", mime);
    366 
    367             totalBitRate = -1;
    368             break;
    369         }
    370 
    371         totalBitRate += bitrate;
    372     }
    373 
    374     mBitrate = totalBitRate;
    375 
    376     LOGV("mBitrate = %lld bits/sec", mBitrate);
    377 
    378     {
    379         Mutex::Autolock autoLock(mStatsLock);
    380         mStats.mBitrate = mBitrate;
    381         mStats.mTracks.clear();
    382         mStats.mAudioTrackIndex = -1;
    383         mStats.mVideoTrackIndex = -1;
    384     }
    385 
    386     bool haveAudio = false;
    387     bool haveVideo = false;
    388     for (size_t i = 0; i < extractor->countTracks(); ++i) {
    389         sp<MetaData> meta = extractor->getTrackMetaData(i);
    390 
    391         const char *mime;
    392         CHECK(meta->findCString(kKeyMIMEType, &mime));
    393 
    394         if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
    395             setVideoSource(extractor->getTrack(i));
    396             haveVideo = true;
    397 
    398             // Set the presentation/display size
    399             int32_t displayWidth, displayHeight;
    400             bool success = meta->findInt32(kKeyDisplayWidth, &displayWidth);
    401             if (success) {
    402                 success = meta->findInt32(kKeyDisplayHeight, &displayHeight);
    403             }
    404             if (success) {
    405                 mDisplayWidth = displayWidth;
    406                 mDisplayHeight = displayHeight;
    407             }
    408 
    409             {
    410                 Mutex::Autolock autoLock(mStatsLock);
    411                 mStats.mVideoTrackIndex = mStats.mTracks.size();
    412                 mStats.mTracks.push();
    413                 TrackStat *stat =
    414                     &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
    415                 stat->mMIME = mime;
    416             }
    417         } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
    418             setAudioSource(extractor->getTrack(i));
    419             haveAudio = true;
    420 
    421             {
    422                 Mutex::Autolock autoLock(mStatsLock);
    423                 mStats.mAudioTrackIndex = mStats.mTracks.size();
    424                 mStats.mTracks.push();
    425                 TrackStat *stat =
    426                     &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
    427                 stat->mMIME = mime;
    428             }
    429 
    430             if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
    431                 // Only do this for vorbis audio, none of the other audio
    432                 // formats even support this ringtone specific hack and
    433                 // retrieving the metadata on some extractors may turn out
    434                 // to be very expensive.
    435                 sp<MetaData> fileMeta = extractor->getMetaData();
    436                 int32_t loop;
    437                 if (fileMeta != NULL
    438                         && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
    439                     modifyFlags(AUTO_LOOPING, SET);
    440                 }
    441             }
    442         } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
    443             addTextSource(extractor->getTrack(i));
    444         }
    445     }
    446 
    447     if (!haveAudio && !haveVideo) {
    448         return UNKNOWN_ERROR;
    449     }
    450 
    451     mExtractorFlags = extractor->flags();
    452 
    453     return OK;
    454 }
    455 
    456 void AwesomePlayer::reset() {
    457     Mutex::Autolock autoLock(mLock);
    458     reset_l();
    459 }
    460 
    461 void AwesomePlayer::reset_l() {
    462     mDisplayWidth = 0;
    463     mDisplayHeight = 0;
    464 
    465     if (mDecryptHandle != NULL) {
    466             mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
    467                     Playback::STOP, 0);
    468             mDecryptHandle = NULL;
    469             mDrmManagerClient = NULL;
    470     }
    471 
    472     if (mFlags & PLAYING) {
    473         uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
    474         if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
    475             params |= IMediaPlayerService::kBatteryDataTrackAudio;
    476         }
    477         if (mVideoSource != NULL) {
    478             params |= IMediaPlayerService::kBatteryDataTrackVideo;
    479         }
    480         addBatteryData(params);
    481     }
    482 
    483     if (mFlags & PREPARING) {
    484         modifyFlags(PREPARE_CANCELLED, SET);
    485         if (mConnectingDataSource != NULL) {
    486             LOGI("interrupting the connection process");
    487             mConnectingDataSource->disconnect();
    488         } else if (mConnectingRTSPController != NULL) {
    489             LOGI("interrupting the connection process");
    490             mConnectingRTSPController->disconnect();
    491         }
    492 
    493         if (mFlags & PREPARING_CONNECTED) {
    494             // We are basically done preparing, we're just buffering
    495             // enough data to start playback, we can safely interrupt that.
    496             finishAsyncPrepare_l();
    497         }
    498     }
    499 
    500     while (mFlags & PREPARING) {
    501         mPreparedCondition.wait(mLock);
    502     }
    503 
    504     cancelPlayerEvents();
    505 
    506     mWVMExtractor.clear();
    507     mCachedSource.clear();
    508     mAudioTrack.clear();
    509     mVideoTrack.clear();
    510 
    511     // Shutdown audio first, so that the respone to the reset request
    512     // appears to happen instantaneously as far as the user is concerned
    513     // If we did this later, audio would continue playing while we
    514     // shutdown the video-related resources and the player appear to
    515     // not be as responsive to a reset request.
    516     if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED))
    517             && mAudioSource != NULL) {
    518         // If we had an audio player, it would have effectively
    519         // taken possession of the audio source and stopped it when
    520         // _it_ is stopped. Otherwise this is still our responsibility.
    521         mAudioSource->stop();
    522     }
    523     mAudioSource.clear();
    524 
    525     mTimeSource = NULL;
    526 
    527     delete mAudioPlayer;
    528     mAudioPlayer = NULL;
    529 
    530     if (mTextPlayer != NULL) {
    531         delete mTextPlayer;
    532         mTextPlayer = NULL;
    533     }
    534 
    535     mVideoRenderer.clear();
    536 
    537     if (mRTSPController != NULL) {
    538         mRTSPController->disconnect();
    539         mRTSPController.clear();
    540     }
    541 
    542     if (mVideoSource != NULL) {
    543         shutdownVideoDecoder_l();
    544     }
    545 
    546     mDurationUs = -1;
    547     modifyFlags(0, ASSIGN);
    548     mExtractorFlags = 0;
    549     mTimeSourceDeltaUs = 0;
    550     mVideoTimeUs = 0;
    551 
    552     mSeeking = NO_SEEK;
    553     mSeekNotificationSent = true;
    554     mSeekTimeUs = 0;
    555 
    556     mUri.setTo("");
    557     mUriHeaders.clear();
    558 
    559     mFileSource.clear();
    560 
    561     mBitrate = -1;
    562     mLastVideoTimeUs = -1;
    563 
    564     {
    565         Mutex::Autolock autoLock(mStatsLock);
    566         mStats.mFd = -1;
    567         mStats.mURI = String8();
    568         mStats.mBitrate = -1;
    569         mStats.mAudioTrackIndex = -1;
    570         mStats.mVideoTrackIndex = -1;
    571         mStats.mNumVideoFramesDecoded = 0;
    572         mStats.mNumVideoFramesDropped = 0;
    573         mStats.mVideoWidth = -1;
    574         mStats.mVideoHeight = -1;
    575         mStats.mFlags = 0;
    576         mStats.mTracks.clear();
    577     }
    578 
    579     mWatchForAudioSeekComplete = false;
    580     mWatchForAudioEOS = false;
    581 }
    582 
    583 void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
    584     if (mListener != NULL) {
    585         sp<MediaPlayerBase> listener = mListener.promote();
    586 
    587         if (listener != NULL) {
    588             listener->sendEvent(msg, ext1, ext2);
    589         }
    590     }
    591 }
    592 
    593 bool AwesomePlayer::getBitrate(int64_t *bitrate) {
    594     off64_t size;
    595     if (mDurationUs >= 0 && mCachedSource != NULL
    596             && mCachedSource->getSize(&size) == OK) {
    597         *bitrate = size * 8000000ll / mDurationUs;  // in bits/sec
    598         return true;
    599     }
    600 
    601     if (mBitrate >= 0) {
    602         *bitrate = mBitrate;
    603         return true;
    604     }
    605 
    606     *bitrate = 0;
    607 
    608     return false;
    609 }
    610 
    611 // Returns true iff cached duration is available/applicable.
    612 bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
    613     int64_t bitrate;
    614 
    615     if (mRTSPController != NULL) {
    616         *durationUs = mRTSPController->getQueueDurationUs(eos);
    617         return true;
    618     } else if (mCachedSource != NULL && getBitrate(&bitrate)) {
    619         status_t finalStatus;
    620         size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
    621         *durationUs = cachedDataRemaining * 8000000ll / bitrate;
    622         *eos = (finalStatus != OK);
    623         return true;
    624     } else if (mWVMExtractor != NULL) {
    625         status_t finalStatus;
    626         *durationUs = mWVMExtractor->getCachedDurationUs(&finalStatus);
    627         *eos = (finalStatus != OK);
    628         return true;
    629     }
    630 
    631     return false;
    632 }
    633 
    634 void AwesomePlayer::ensureCacheIsFetching_l() {
    635     if (mCachedSource != NULL) {
    636         mCachedSource->resumeFetchingIfNecessary();
    637     }
    638 }
    639 
    640 void AwesomePlayer::onVideoLagUpdate() {
    641     Mutex::Autolock autoLock(mLock);
    642     if (!mVideoLagEventPending) {
    643         return;
    644     }
    645     mVideoLagEventPending = false;
    646 
    647     int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs();
    648     int64_t videoLateByUs = audioTimeUs - mVideoTimeUs;
    649 
    650     if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) {
    651         LOGV("video late by %lld ms.", videoLateByUs / 1000ll);
    652 
    653         notifyListener_l(
    654                 MEDIA_INFO,
    655                 MEDIA_INFO_VIDEO_TRACK_LAGGING,
    656                 videoLateByUs / 1000ll);
    657     }
    658 
    659     postVideoLagEvent_l();
    660 }
    661 
    662 void AwesomePlayer::onBufferingUpdate() {
    663     Mutex::Autolock autoLock(mLock);
    664     if (!mBufferingEventPending) {
    665         return;
    666     }
    667     mBufferingEventPending = false;
    668 
    669     if (mCachedSource != NULL) {
    670         status_t finalStatus;
    671         size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
    672         bool eos = (finalStatus != OK);
    673 
    674         if (eos) {
    675             if (finalStatus == ERROR_END_OF_STREAM) {
    676                 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
    677             }
    678             if (mFlags & PREPARING) {
    679                 LOGV("cache has reached EOS, prepare is done.");
    680                 finishAsyncPrepare_l();
    681             }
    682         } else {
    683             int64_t bitrate;
    684             if (getBitrate(&bitrate)) {
    685                 size_t cachedSize = mCachedSource->cachedSize();
    686                 int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
    687 
    688                 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
    689                 if (percentage > 100) {
    690                     percentage = 100;
    691                 }
    692 
    693                 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
    694             } else {
    695                 // We don't know the bitrate of the stream, use absolute size
    696                 // limits to maintain the cache.
    697 
    698                 if ((mFlags & PLAYING) && !eos
    699                         && (cachedDataRemaining < kLowWaterMarkBytes)) {
    700                     LOGI("cache is running low (< %d) , pausing.",
    701                          kLowWaterMarkBytes);
    702                     modifyFlags(CACHE_UNDERRUN, SET);
    703                     pause_l();
    704                     ensureCacheIsFetching_l();
    705                     sendCacheStats();
    706                     notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
    707                 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
    708                     if (mFlags & CACHE_UNDERRUN) {
    709                         LOGI("cache has filled up (> %d), resuming.",
    710                              kHighWaterMarkBytes);
    711                         modifyFlags(CACHE_UNDERRUN, CLEAR);
    712                         play_l();
    713                         notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
    714                     } else if (mFlags & PREPARING) {
    715                         LOGV("cache has filled up (> %d), prepare is done",
    716                              kHighWaterMarkBytes);
    717                         finishAsyncPrepare_l();
    718                     }
    719                 }
    720             }
    721         }
    722     } else if (mWVMExtractor != NULL) {
    723         status_t finalStatus;
    724 
    725         int64_t cachedDurationUs
    726             = mWVMExtractor->getCachedDurationUs(&finalStatus);
    727 
    728         bool eos = (finalStatus != OK);
    729 
    730         if (eos) {
    731             if (finalStatus == ERROR_END_OF_STREAM) {
    732                 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
    733             }
    734             if (mFlags & PREPARING) {
    735                 LOGV("cache has reached EOS, prepare is done.");
    736                 finishAsyncPrepare_l();
    737             }
    738         } else {
    739             int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
    740             if (percentage > 100) {
    741                 percentage = 100;
    742             }
    743 
    744             notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
    745         }
    746     }
    747 
    748     int64_t cachedDurationUs;
    749     bool eos;
    750     if (getCachedDuration_l(&cachedDurationUs, &eos)) {
    751         LOGV("cachedDurationUs = %.2f secs, eos=%d",
    752              cachedDurationUs / 1E6, eos);
    753 
    754         int64_t highWaterMarkUs =
    755             (mRTSPController != NULL) ? kHighWaterMarkRTSPUs : kHighWaterMarkUs;
    756 
    757         if ((mFlags & PLAYING) && !eos
    758                 && (cachedDurationUs < kLowWaterMarkUs)) {
    759             LOGI("cache is running low (%.2f secs) , pausing.",
    760                  cachedDurationUs / 1E6);
    761             modifyFlags(CACHE_UNDERRUN, SET);
    762             pause_l();
    763             ensureCacheIsFetching_l();
    764             sendCacheStats();
    765             notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
    766         } else if (eos || cachedDurationUs > highWaterMarkUs) {
    767             if (mFlags & CACHE_UNDERRUN) {
    768                 LOGI("cache has filled up (%.2f secs), resuming.",
    769                      cachedDurationUs / 1E6);
    770                 modifyFlags(CACHE_UNDERRUN, CLEAR);
    771                 play_l();
    772                 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
    773             } else if (mFlags & PREPARING) {
    774                 LOGV("cache has filled up (%.2f secs), prepare is done",
    775                      cachedDurationUs / 1E6);
    776                 finishAsyncPrepare_l();
    777             }
    778         }
    779     }
    780 
    781     postBufferingEvent_l();
    782 }
    783 
    784 void AwesomePlayer::sendCacheStats() {
    785     sp<MediaPlayerBase> listener = mListener.promote();
    786     if (listener != NULL && mCachedSource != NULL) {
    787         int32_t kbps = 0;
    788         status_t err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
    789         if (err == OK) {
    790             listener->sendEvent(
    791                 MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps);
    792         }
    793     }
    794 }
    795 
    796 void AwesomePlayer::onStreamDone() {
    797     // Posted whenever any stream finishes playing.
    798 
    799     Mutex::Autolock autoLock(mLock);
    800     if (!mStreamDoneEventPending) {
    801         return;
    802     }
    803     mStreamDoneEventPending = false;
    804 
    805     if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
    806         LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
    807 
    808         notifyListener_l(
    809                 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
    810 
    811         pause_l(true /* at eos */);
    812 
    813         modifyFlags(AT_EOS, SET);
    814         return;
    815     }
    816 
    817     const bool allDone =
    818         (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
    819             && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
    820 
    821     if (!allDone) {
    822         return;
    823     }
    824 
    825     if ((mFlags & LOOPING)
    826             || ((mFlags & AUTO_LOOPING)
    827                 && (mAudioSink == NULL || mAudioSink->realtime()))) {
    828         // Don't AUTO_LOOP if we're being recorded, since that cannot be
    829         // turned off and recording would go on indefinitely.
    830 
    831         seekTo_l(0);
    832 
    833         if (mVideoSource != NULL) {
    834             postVideoEvent_l();
    835         }
    836     } else {
    837         LOGV("MEDIA_PLAYBACK_COMPLETE");
    838         notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
    839 
    840         pause_l(true /* at eos */);
    841 
    842         modifyFlags(AT_EOS, SET);
    843     }
    844 }
    845 
    846 status_t AwesomePlayer::play() {
    847     Mutex::Autolock autoLock(mLock);
    848 
    849     modifyFlags(CACHE_UNDERRUN, CLEAR);
    850 
    851     return play_l();
    852 }
    853 
    854 status_t AwesomePlayer::play_l() {
    855     modifyFlags(SEEK_PREVIEW, CLEAR);
    856 
    857     if (mFlags & PLAYING) {
    858         return OK;
    859     }
    860 
    861     if (!(mFlags & PREPARED)) {
    862         status_t err = prepare_l();
    863 
    864         if (err != OK) {
    865             return err;
    866         }
    867     }
    868 
    869     modifyFlags(PLAYING, SET);
    870     modifyFlags(FIRST_FRAME, SET);
    871 
    872     if (mDecryptHandle != NULL) {
    873         int64_t position;
    874         getPosition(&position);
    875         mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
    876                 Playback::START, position / 1000);
    877     }
    878 
    879     if (mAudioSource != NULL) {
    880         if (mAudioPlayer == NULL) {
    881             if (mAudioSink != NULL) {
    882                 mAudioPlayer = new AudioPlayer(mAudioSink, this);
    883                 mAudioPlayer->setSource(mAudioSource);
    884 
    885                 mTimeSource = mAudioPlayer;
    886 
    887                 // If there was a seek request before we ever started,
    888                 // honor the request now.
    889                 // Make sure to do this before starting the audio player
    890                 // to avoid a race condition.
    891                 seekAudioIfNecessary_l();
    892             }
    893         }
    894 
    895         CHECK(!(mFlags & AUDIO_RUNNING));
    896 
    897         if (mVideoSource == NULL) {
    898             // We don't want to post an error notification at this point,
    899             // the error returned from MediaPlayer::start() will suffice.
    900 
    901             status_t err = startAudioPlayer_l(
    902                     false /* sendErrorNotification */);
    903 
    904             if (err != OK) {
    905                 delete mAudioPlayer;
    906                 mAudioPlayer = NULL;
    907 
    908                 modifyFlags((PLAYING | FIRST_FRAME), CLEAR);
    909 
    910                 if (mDecryptHandle != NULL) {
    911                     mDrmManagerClient->setPlaybackStatus(
    912                             mDecryptHandle, Playback::STOP, 0);
    913                 }
    914 
    915                 return err;
    916             }
    917         }
    918     }
    919 
    920     if (mTimeSource == NULL && mAudioPlayer == NULL) {
    921         mTimeSource = &mSystemTimeSource;
    922     }
    923 
    924     if (mVideoSource != NULL) {
    925         // Kick off video playback
    926         postVideoEvent_l();
    927 
    928         if (mAudioSource != NULL && mVideoSource != NULL) {
    929             postVideoLagEvent_l();
    930         }
    931     }
    932 
    933     if (mFlags & AT_EOS) {
    934         // Legacy behaviour, if a stream finishes playing and then
    935         // is started again, we play from the start...
    936         seekTo_l(0);
    937     }
    938 
    939     uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted
    940         | IMediaPlayerService::kBatteryDataTrackDecoder;
    941     if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
    942         params |= IMediaPlayerService::kBatteryDataTrackAudio;
    943     }
    944     if (mVideoSource != NULL) {
    945         params |= IMediaPlayerService::kBatteryDataTrackVideo;
    946     }
    947     addBatteryData(params);
    948 
    949     return OK;
    950 }
    951 
    952 status_t AwesomePlayer::startAudioPlayer_l(bool sendErrorNotification) {
    953     CHECK(!(mFlags & AUDIO_RUNNING));
    954 
    955     if (mAudioSource == NULL || mAudioPlayer == NULL) {
    956         return OK;
    957     }
    958 
    959     if (!(mFlags & AUDIOPLAYER_STARTED)) {
    960         modifyFlags(AUDIOPLAYER_STARTED, SET);
    961 
    962         bool wasSeeking = mAudioPlayer->isSeeking();
    963 
    964         // We've already started the MediaSource in order to enable
    965         // the prefetcher to read its data.
    966         status_t err = mAudioPlayer->start(
    967                 true /* sourceAlreadyStarted */);
    968 
    969         if (err != OK) {
    970             if (sendErrorNotification) {
    971                 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
    972             }
    973 
    974             return err;
    975         }
    976 
    977         if (wasSeeking) {
    978             CHECK(!mAudioPlayer->isSeeking());
    979 
    980             // We will have finished the seek while starting the audio player.
    981             postAudioSeekComplete();
    982         }
    983     } else {
    984         mAudioPlayer->resume();
    985     }
    986 
    987     modifyFlags(AUDIO_RUNNING, SET);
    988 
    989     mWatchForAudioEOS = true;
    990 
    991     return OK;
    992 }
    993 
    994 void AwesomePlayer::notifyVideoSize_l() {
    995     sp<MetaData> meta = mVideoSource->getFormat();
    996 
    997     int32_t cropLeft, cropTop, cropRight, cropBottom;
    998     if (!meta->findRect(
    999                 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
   1000         int32_t width, height;
   1001         CHECK(meta->findInt32(kKeyWidth, &width));
   1002         CHECK(meta->findInt32(kKeyHeight, &height));
   1003 
   1004         cropLeft = cropTop = 0;
   1005         cropRight = width - 1;
   1006         cropBottom = height - 1;
   1007 
   1008         LOGV("got dimensions only %d x %d", width, height);
   1009     } else {
   1010         LOGV("got crop rect %d, %d, %d, %d",
   1011              cropLeft, cropTop, cropRight, cropBottom);
   1012     }
   1013 
   1014     int32_t displayWidth;
   1015     if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
   1016         LOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
   1017         mDisplayWidth = displayWidth;
   1018     }
   1019     int32_t displayHeight;
   1020     if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
   1021         LOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
   1022         mDisplayHeight = displayHeight;
   1023     }
   1024 
   1025     int32_t usableWidth = cropRight - cropLeft + 1;
   1026     int32_t usableHeight = cropBottom - cropTop + 1;
   1027     if (mDisplayWidth != 0) {
   1028         usableWidth = mDisplayWidth;
   1029     }
   1030     if (mDisplayHeight != 0) {
   1031         usableHeight = mDisplayHeight;
   1032     }
   1033 
   1034     {
   1035         Mutex::Autolock autoLock(mStatsLock);
   1036         mStats.mVideoWidth = usableWidth;
   1037         mStats.mVideoHeight = usableHeight;
   1038     }
   1039 
   1040     int32_t rotationDegrees;
   1041     if (!mVideoTrack->getFormat()->findInt32(
   1042                 kKeyRotation, &rotationDegrees)) {
   1043         rotationDegrees = 0;
   1044     }
   1045 
   1046     if (rotationDegrees == 90 || rotationDegrees == 270) {
   1047         notifyListener_l(
   1048                 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
   1049     } else {
   1050         notifyListener_l(
   1051                 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
   1052     }
   1053 }
   1054 
   1055 void AwesomePlayer::initRenderer_l() {
   1056     if (mNativeWindow == NULL) {
   1057         return;
   1058     }
   1059 
   1060     sp<MetaData> meta = mVideoSource->getFormat();
   1061 
   1062     int32_t format;
   1063     const char *component;
   1064     int32_t decodedWidth, decodedHeight;
   1065     CHECK(meta->findInt32(kKeyColorFormat, &format));
   1066     CHECK(meta->findCString(kKeyDecoderComponent, &component));
   1067     CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
   1068     CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
   1069 
   1070     int32_t rotationDegrees;
   1071     if (!mVideoTrack->getFormat()->findInt32(
   1072                 kKeyRotation, &rotationDegrees)) {
   1073         rotationDegrees = 0;
   1074     }
   1075 
   1076     mVideoRenderer.clear();
   1077 
   1078     // Must ensure that mVideoRenderer's destructor is actually executed
   1079     // before creating a new one.
   1080     IPCThreadState::self()->flushCommands();
   1081 
   1082     if (USE_SURFACE_ALLOC
   1083             && !strncmp(component, "OMX.", 4)
   1084             && strncmp(component, "OMX.google.", 11)) {
   1085         // Hardware decoders avoid the CPU color conversion by decoding
   1086         // directly to ANativeBuffers, so we must use a renderer that
   1087         // just pushes those buffers to the ANativeWindow.
   1088         mVideoRenderer =
   1089             new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);
   1090     } else {
   1091         // Other decoders are instantiated locally and as a consequence
   1092         // allocate their buffers in local address space.  This renderer
   1093         // then performs a color conversion and copy to get the data
   1094         // into the ANativeBuffer.
   1095         mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta);
   1096     }
   1097 }
   1098 
   1099 status_t AwesomePlayer::pause() {
   1100     Mutex::Autolock autoLock(mLock);
   1101 
   1102     modifyFlags(CACHE_UNDERRUN, CLEAR);
   1103 
   1104     return pause_l();
   1105 }
   1106 
   1107 status_t AwesomePlayer::pause_l(bool at_eos) {
   1108     if (!(mFlags & PLAYING)) {
   1109         return OK;
   1110     }
   1111 
   1112     cancelPlayerEvents(true /* keepBufferingGoing */);
   1113 
   1114     if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
   1115         if (at_eos) {
   1116             // If we played the audio stream to completion we
   1117             // want to make sure that all samples remaining in the audio
   1118             // track's queue are played out.
   1119             mAudioPlayer->pause(true /* playPendingSamples */);
   1120         } else {
   1121             mAudioPlayer->pause();
   1122         }
   1123 
   1124         modifyFlags(AUDIO_RUNNING, CLEAR);
   1125     }
   1126 
   1127     if (mFlags & TEXTPLAYER_STARTED) {
   1128         mTextPlayer->pause();
   1129         modifyFlags(TEXT_RUNNING, CLEAR);
   1130     }
   1131 
   1132     modifyFlags(PLAYING, CLEAR);
   1133 
   1134     if (mDecryptHandle != NULL) {
   1135         mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
   1136                 Playback::PAUSE, 0);
   1137     }
   1138 
   1139     uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
   1140     if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
   1141         params |= IMediaPlayerService::kBatteryDataTrackAudio;
   1142     }
   1143     if (mVideoSource != NULL) {
   1144         params |= IMediaPlayerService::kBatteryDataTrackVideo;
   1145     }
   1146 
   1147     addBatteryData(params);
   1148 
   1149     return OK;
   1150 }
   1151 
   1152 bool AwesomePlayer::isPlaying() const {
   1153     return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
   1154 }
   1155 
   1156 status_t AwesomePlayer::setSurface(const sp<Surface> &surface) {
   1157     Mutex::Autolock autoLock(mLock);
   1158 
   1159     mSurface = surface;
   1160     return setNativeWindow_l(surface);
   1161 }
   1162 
   1163 status_t AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
   1164     Mutex::Autolock autoLock(mLock);
   1165 
   1166     mSurface.clear();
   1167 
   1168     status_t err;
   1169     if (surfaceTexture != NULL) {
   1170         err = setNativeWindow_l(new SurfaceTextureClient(surfaceTexture));
   1171     } else {
   1172         err = setNativeWindow_l(NULL);
   1173     }
   1174 
   1175     return err;
   1176 }
   1177 
   1178 void AwesomePlayer::shutdownVideoDecoder_l() {
   1179     if (mVideoBuffer) {
   1180         mVideoBuffer->release();
   1181         mVideoBuffer = NULL;
   1182     }
   1183 
   1184     mVideoSource->stop();
   1185 
   1186     // The following hack is necessary to ensure that the OMX
   1187     // component is completely released by the time we may try
   1188     // to instantiate it again.
   1189     wp<MediaSource> tmp = mVideoSource;
   1190     mVideoSource.clear();
   1191     while (tmp.promote() != NULL) {
   1192         usleep(1000);
   1193     }
   1194     IPCThreadState::self()->flushCommands();
   1195     LOGV("video decoder shutdown completed");
   1196 }
   1197 
   1198 status_t AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
   1199     mNativeWindow = native;
   1200 
   1201     if (mVideoSource == NULL) {
   1202         return OK;
   1203     }
   1204 
   1205     LOGV("attempting to reconfigure to use new surface");
   1206 
   1207     bool wasPlaying = (mFlags & PLAYING) != 0;
   1208 
   1209     pause_l();
   1210     mVideoRenderer.clear();
   1211 
   1212     shutdownVideoDecoder_l();
   1213 
   1214     status_t err = initVideoDecoder();
   1215 
   1216     if (err != OK) {
   1217         LOGE("failed to reinstantiate video decoder after surface change.");
   1218         return err;
   1219     }
   1220 
   1221     if (mLastVideoTimeUs >= 0) {
   1222         mSeeking = SEEK;
   1223         mSeekTimeUs = mLastVideoTimeUs;
   1224         modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
   1225     }
   1226 
   1227     if (wasPlaying) {
   1228         play_l();
   1229     }
   1230 
   1231     return OK;
   1232 }
   1233 
   1234 void AwesomePlayer::setAudioSink(
   1235         const sp<MediaPlayerBase::AudioSink> &audioSink) {
   1236     Mutex::Autolock autoLock(mLock);
   1237 
   1238     mAudioSink = audioSink;
   1239 }
   1240 
   1241 status_t AwesomePlayer::setLooping(bool shouldLoop) {
   1242     Mutex::Autolock autoLock(mLock);
   1243 
   1244     modifyFlags(LOOPING, CLEAR);
   1245 
   1246     if (shouldLoop) {
   1247         modifyFlags(LOOPING, SET);
   1248     }
   1249 
   1250     return OK;
   1251 }
   1252 
   1253 status_t AwesomePlayer::getDuration(int64_t *durationUs) {
   1254     Mutex::Autolock autoLock(mMiscStateLock);
   1255 
   1256     if (mDurationUs < 0) {
   1257         return UNKNOWN_ERROR;
   1258     }
   1259 
   1260     *durationUs = mDurationUs;
   1261 
   1262     return OK;
   1263 }
   1264 
   1265 status_t AwesomePlayer::getPosition(int64_t *positionUs) {
   1266     if (mRTSPController != NULL) {
   1267         *positionUs = mRTSPController->getNormalPlayTimeUs();
   1268     }
   1269     else if (mSeeking != NO_SEEK) {
   1270         *positionUs = mSeekTimeUs;
   1271     } else if (mVideoSource != NULL
   1272             && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) {
   1273         Mutex::Autolock autoLock(mMiscStateLock);
   1274         *positionUs = mVideoTimeUs;
   1275     } else if (mAudioPlayer != NULL) {
   1276         *positionUs = mAudioPlayer->getMediaTimeUs();
   1277     } else {
   1278         *positionUs = 0;
   1279     }
   1280 
   1281     return OK;
   1282 }
   1283 
   1284 status_t AwesomePlayer::seekTo(int64_t timeUs) {
   1285     if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
   1286         Mutex::Autolock autoLock(mLock);
   1287         return seekTo_l(timeUs);
   1288     }
   1289 
   1290     return OK;
   1291 }
   1292 
   1293 status_t AwesomePlayer::setTimedTextTrackIndex(int32_t index) {
   1294     if (mTextPlayer != NULL) {
   1295         if (index >= 0) { // to turn on a text track
   1296             status_t err = mTextPlayer->setTimedTextTrackIndex(index);
   1297             if (err != OK) {
   1298                 return err;
   1299             }
   1300 
   1301             modifyFlags(TEXT_RUNNING, SET);
   1302             modifyFlags(TEXTPLAYER_STARTED, SET);
   1303             return OK;
   1304         } else { // to turn off the text track display
   1305             if (mFlags  & TEXT_RUNNING) {
   1306                 modifyFlags(TEXT_RUNNING, CLEAR);
   1307             }
   1308             if (mFlags  & TEXTPLAYER_STARTED) {
   1309                 modifyFlags(TEXTPLAYER_STARTED, CLEAR);
   1310             }
   1311 
   1312             return mTextPlayer->setTimedTextTrackIndex(index);
   1313         }
   1314     } else {
   1315         return INVALID_OPERATION;
   1316     }
   1317 }
   1318 
   1319 // static
   1320 void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) {
   1321     static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone();
   1322 }
   1323 
   1324 void AwesomePlayer::onRTSPSeekDone() {
   1325     if (!mSeekNotificationSent) {
   1326         notifyListener_l(MEDIA_SEEK_COMPLETE);
   1327         mSeekNotificationSent = true;
   1328     }
   1329 }
   1330 
   1331 status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
   1332     if (mRTSPController != NULL) {
   1333         mSeekNotificationSent = false;
   1334         mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this);
   1335         return OK;
   1336     }
   1337 
   1338     if (mFlags & CACHE_UNDERRUN) {
   1339         modifyFlags(CACHE_UNDERRUN, CLEAR);
   1340         play_l();
   1341     }
   1342 
   1343     if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) {
   1344         // Video playback completed before, there's no pending
   1345         // video event right now. In order for this new seek
   1346         // to be honored, we need to post one.
   1347 
   1348         postVideoEvent_l();
   1349     }
   1350 
   1351     mSeeking = SEEK;
   1352     mSeekNotificationSent = false;
   1353     mSeekTimeUs = timeUs;
   1354     modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
   1355 
   1356     seekAudioIfNecessary_l();
   1357 
   1358     if (mFlags & TEXTPLAYER_STARTED) {
   1359         mTextPlayer->seekTo(mSeekTimeUs);
   1360     }
   1361 
   1362     if (!(mFlags & PLAYING)) {
   1363         LOGV("seeking while paused, sending SEEK_COMPLETE notification"
   1364              " immediately.");
   1365 
   1366         notifyListener_l(MEDIA_SEEK_COMPLETE);
   1367         mSeekNotificationSent = true;
   1368 
   1369         if ((mFlags & PREPARED) && mVideoSource != NULL) {
   1370             modifyFlags(SEEK_PREVIEW, SET);
   1371             postVideoEvent_l();
   1372         }
   1373     }
   1374 
   1375     return OK;
   1376 }
   1377 
   1378 void AwesomePlayer::seekAudioIfNecessary_l() {
   1379     if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
   1380         mAudioPlayer->seekTo(mSeekTimeUs);
   1381 
   1382         mWatchForAudioSeekComplete = true;
   1383         mWatchForAudioEOS = true;
   1384 
   1385         if (mDecryptHandle != NULL) {
   1386             mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
   1387                     Playback::PAUSE, 0);
   1388             mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
   1389                     Playback::START, mSeekTimeUs / 1000);
   1390         }
   1391     }
   1392 }
   1393 
   1394 void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
   1395     CHECK(source != NULL);
   1396 
   1397     mAudioTrack = source;
   1398 }
   1399 
   1400 void AwesomePlayer::addTextSource(sp<MediaSource> source) {
   1401     Mutex::Autolock autoLock(mTimedTextLock);
   1402     CHECK(source != NULL);
   1403 
   1404     if (mTextPlayer == NULL) {
   1405         mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue);
   1406     }
   1407 
   1408     mTextPlayer->addTextSource(source);
   1409 }
   1410 
   1411 status_t AwesomePlayer::initAudioDecoder() {
   1412     sp<MetaData> meta = mAudioTrack->getFormat();
   1413 
   1414     const char *mime;
   1415     CHECK(meta->findCString(kKeyMIMEType, &mime));
   1416 
   1417     if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
   1418         mAudioSource = mAudioTrack;
   1419     } else {
   1420         mAudioSource = OMXCodec::Create(
   1421                 mClient.interface(), mAudioTrack->getFormat(),
   1422                 false, // createEncoder
   1423                 mAudioTrack);
   1424     }
   1425 
   1426     if (mAudioSource != NULL) {
   1427         int64_t durationUs;
   1428         if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
   1429             Mutex::Autolock autoLock(mMiscStateLock);
   1430             if (mDurationUs < 0 || durationUs > mDurationUs) {
   1431                 mDurationUs = durationUs;
   1432             }
   1433         }
   1434 
   1435         status_t err = mAudioSource->start();
   1436 
   1437         if (err != OK) {
   1438             mAudioSource.clear();
   1439             return err;
   1440         }
   1441     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
   1442         // For legacy reasons we're simply going to ignore the absence
   1443         // of an audio decoder for QCELP instead of aborting playback
   1444         // altogether.
   1445         return OK;
   1446     }
   1447 
   1448     if (mAudioSource != NULL) {
   1449         Mutex::Autolock autoLock(mStatsLock);
   1450         TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
   1451 
   1452         const char *component;
   1453         if (!mAudioSource->getFormat()
   1454                 ->findCString(kKeyDecoderComponent, &component)) {
   1455             component = "none";
   1456         }
   1457 
   1458         stat->mDecoderName = component;
   1459     }
   1460 
   1461     return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
   1462 }
   1463 
   1464 void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
   1465     CHECK(source != NULL);
   1466 
   1467     mVideoTrack = source;
   1468 }
   1469 
   1470 status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
   1471 
   1472     // Either the application or the DRM system can independently say
   1473     // that there must be a hardware-protected path to an external video sink.
   1474     // For now we always require a hardware-protected path to external video sink
   1475     // if content is DRMed, but eventually this could be optional per DRM agent.
   1476     // When the application wants protection, then
   1477     //   (USE_SURFACE_ALLOC && (mSurface != 0) &&
   1478     //   (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp))
   1479     // will be true, but that part is already handled by SurfaceFlinger.
   1480 
   1481 #ifdef DEBUG_HDCP
   1482     // For debugging, we allow a system property to control the protected usage.
   1483     // In case of uninitialized or unexpected property, we default to "DRM only".
   1484     bool setProtectionBit = false;
   1485     char value[PROPERTY_VALUE_MAX];
   1486     if (property_get("persist.sys.hdcp_checking", value, NULL)) {
   1487         if (!strcmp(value, "never")) {
   1488             // nop
   1489         } else if (!strcmp(value, "always")) {
   1490             setProtectionBit = true;
   1491         } else if (!strcmp(value, "drm-only")) {
   1492             if (mDecryptHandle != NULL) {
   1493                 setProtectionBit = true;
   1494             }
   1495         // property value is empty, or unexpected value
   1496         } else {
   1497             if (mDecryptHandle != NULL) {
   1498                 setProtectionBit = true;
   1499             }
   1500         }
   1501     // can' read property value
   1502     } else {
   1503         if (mDecryptHandle != NULL) {
   1504             setProtectionBit = true;
   1505         }
   1506     }
   1507     // note that usage bit is already cleared, so no need to clear it in the "else" case
   1508     if (setProtectionBit) {
   1509         flags |= OMXCodec::kEnableGrallocUsageProtected;
   1510     }
   1511 #else
   1512     if (mDecryptHandle != NULL) {
   1513         flags |= OMXCodec::kEnableGrallocUsageProtected;
   1514     }
   1515 #endif
   1516     LOGV("initVideoDecoder flags=0x%x", flags);
   1517     mVideoSource = OMXCodec::Create(
   1518             mClient.interface(), mVideoTrack->getFormat(),
   1519             false, // createEncoder
   1520             mVideoTrack,
   1521             NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
   1522 
   1523     if (mVideoSource != NULL) {
   1524         int64_t durationUs;
   1525         if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
   1526             Mutex::Autolock autoLock(mMiscStateLock);
   1527             if (mDurationUs < 0 || durationUs > mDurationUs) {
   1528                 mDurationUs = durationUs;
   1529             }
   1530         }
   1531 
   1532         status_t err = mVideoSource->start();
   1533 
   1534         if (err != OK) {
   1535             mVideoSource.clear();
   1536             return err;
   1537         }
   1538     }
   1539 
   1540     if (mVideoSource != NULL) {
   1541         const char *componentName;
   1542         CHECK(mVideoSource->getFormat()
   1543                 ->findCString(kKeyDecoderComponent, &componentName));
   1544 
   1545         {
   1546             Mutex::Autolock autoLock(mStatsLock);
   1547             TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
   1548 
   1549             stat->mDecoderName = componentName;
   1550         }
   1551 
   1552         static const char *kPrefix = "OMX.Nvidia.";
   1553         static const char *kSuffix = ".decode";
   1554         static const size_t kSuffixLength = strlen(kSuffix);
   1555 
   1556         size_t componentNameLength = strlen(componentName);
   1557 
   1558         if (!strncmp(componentName, kPrefix, strlen(kPrefix))
   1559                 && componentNameLength >= kSuffixLength
   1560                 && !strcmp(&componentName[
   1561                     componentNameLength - kSuffixLength], kSuffix)) {
   1562             modifyFlags(SLOW_DECODER_HACK, SET);
   1563         }
   1564     }
   1565 
   1566     return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
   1567 }
   1568 
   1569 void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
   1570     if (mSeeking == SEEK_VIDEO_ONLY) {
   1571         mSeeking = NO_SEEK;
   1572         return;
   1573     }
   1574 
   1575     if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
   1576         return;
   1577     }
   1578 
   1579     if (mAudioPlayer != NULL) {
   1580         LOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
   1581 
   1582         // If we don't have a video time, seek audio to the originally
   1583         // requested seek time instead.
   1584 
   1585         mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
   1586         mWatchForAudioSeekComplete = true;
   1587         mWatchForAudioEOS = true;
   1588     } else if (!mSeekNotificationSent) {
   1589         // If we're playing video only, report seek complete now,
   1590         // otherwise audio player will notify us later.
   1591         notifyListener_l(MEDIA_SEEK_COMPLETE);
   1592         mSeekNotificationSent = true;
   1593     }
   1594 
   1595     modifyFlags(FIRST_FRAME, SET);
   1596     mSeeking = NO_SEEK;
   1597 
   1598     if (mDecryptHandle != NULL) {
   1599         mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
   1600                 Playback::PAUSE, 0);
   1601         mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
   1602                 Playback::START, videoTimeUs / 1000);
   1603     }
   1604 }
   1605 
   1606 void AwesomePlayer::onVideoEvent() {
   1607     Mutex::Autolock autoLock(mLock);
   1608     if (!mVideoEventPending) {
   1609         // The event has been cancelled in reset_l() but had already
   1610         // been scheduled for execution at that time.
   1611         return;
   1612     }
   1613     mVideoEventPending = false;
   1614 
   1615     if (mSeeking != NO_SEEK) {
   1616         if (mVideoBuffer) {
   1617             mVideoBuffer->release();
   1618             mVideoBuffer = NULL;
   1619         }
   1620 
   1621         if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL
   1622                 && !(mFlags & SEEK_PREVIEW)) {
   1623             // We're going to seek the video source first, followed by
   1624             // the audio source.
   1625             // In order to avoid jumps in the DataSource offset caused by
   1626             // the audio codec prefetching data from the old locations
   1627             // while the video codec is already reading data from the new
   1628             // locations, we'll "pause" the audio source, causing it to
   1629             // stop reading input data until a subsequent seek.
   1630 
   1631             if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
   1632                 mAudioPlayer->pause();
   1633 
   1634                 modifyFlags(AUDIO_RUNNING, CLEAR);
   1635             }
   1636             mAudioSource->pause();
   1637         }
   1638     }
   1639 
   1640     if (!mVideoBuffer) {
   1641         MediaSource::ReadOptions options;
   1642         if (mSeeking != NO_SEEK) {
   1643             LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
   1644 
   1645             options.setSeekTo(
   1646                     mSeekTimeUs,
   1647                     mSeeking == SEEK_VIDEO_ONLY
   1648                         ? MediaSource::ReadOptions::SEEK_NEXT_SYNC
   1649                         : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
   1650         }
   1651         for (;;) {
   1652             status_t err = mVideoSource->read(&mVideoBuffer, &options);
   1653             options.clearSeekTo();
   1654 
   1655             if (err != OK) {
   1656                 CHECK(mVideoBuffer == NULL);
   1657 
   1658                 if (err == INFO_FORMAT_CHANGED) {
   1659                     LOGV("VideoSource signalled format change.");
   1660 
   1661                     notifyVideoSize_l();
   1662 
   1663                     if (mVideoRenderer != NULL) {
   1664                         mVideoRendererIsPreview = false;
   1665                         initRenderer_l();
   1666                     }
   1667                     continue;
   1668                 }
   1669 
   1670                 // So video playback is complete, but we may still have
   1671                 // a seek request pending that needs to be applied
   1672                 // to the audio track.
   1673                 if (mSeeking != NO_SEEK) {
   1674                     LOGV("video stream ended while seeking!");
   1675                 }
   1676                 finishSeekIfNecessary(-1);
   1677 
   1678                 if (mAudioPlayer != NULL
   1679                         && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
   1680                     startAudioPlayer_l();
   1681                 }
   1682 
   1683                 modifyFlags(VIDEO_AT_EOS, SET);
   1684                 postStreamDoneEvent_l(err);
   1685                 return;
   1686             }
   1687 
   1688             if (mVideoBuffer->range_length() == 0) {
   1689                 // Some decoders, notably the PV AVC software decoder
   1690                 // return spurious empty buffers that we just want to ignore.
   1691 
   1692                 mVideoBuffer->release();
   1693                 mVideoBuffer = NULL;
   1694                 continue;
   1695             }
   1696 
   1697             break;
   1698         }
   1699 
   1700         {
   1701             Mutex::Autolock autoLock(mStatsLock);
   1702             ++mStats.mNumVideoFramesDecoded;
   1703         }
   1704     }
   1705 
   1706     int64_t timeUs;
   1707     CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
   1708 
   1709     mLastVideoTimeUs = timeUs;
   1710 
   1711     if (mSeeking == SEEK_VIDEO_ONLY) {
   1712         if (mSeekTimeUs > timeUs) {
   1713             LOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us",
   1714                  mSeekTimeUs, timeUs);
   1715         }
   1716     }
   1717 
   1718     {
   1719         Mutex::Autolock autoLock(mMiscStateLock);
   1720         mVideoTimeUs = timeUs;
   1721     }
   1722 
   1723     SeekType wasSeeking = mSeeking;
   1724     finishSeekIfNecessary(timeUs);
   1725 
   1726     if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
   1727         status_t err = startAudioPlayer_l();
   1728         if (err != OK) {
   1729             LOGE("Starting the audio player failed w/ err %d", err);
   1730             return;
   1731         }
   1732     }
   1733 
   1734     if ((mFlags & TEXTPLAYER_STARTED) && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) {
   1735         mTextPlayer->resume();
   1736         modifyFlags(TEXT_RUNNING, SET);
   1737     }
   1738 
   1739     TimeSource *ts =
   1740         ((mFlags & AUDIO_AT_EOS) || !(mFlags & AUDIOPLAYER_STARTED))
   1741             ? &mSystemTimeSource : mTimeSource;
   1742 
   1743     if (mFlags & FIRST_FRAME) {
   1744         modifyFlags(FIRST_FRAME, CLEAR);
   1745         mSinceLastDropped = 0;
   1746         mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
   1747     }
   1748 
   1749     int64_t realTimeUs, mediaTimeUs;
   1750     if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
   1751         && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
   1752         mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
   1753     }
   1754 
   1755     if (wasSeeking == SEEK_VIDEO_ONLY) {
   1756         int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
   1757 
   1758         int64_t latenessUs = nowUs - timeUs;
   1759 
   1760         if (latenessUs > 0) {
   1761             LOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6);
   1762         }
   1763     }
   1764 
   1765     if (wasSeeking == NO_SEEK) {
   1766         // Let's display the first frame after seeking right away.
   1767 
   1768         int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
   1769 
   1770         int64_t latenessUs = nowUs - timeUs;
   1771 
   1772         if (latenessUs > 500000ll
   1773                 && mRTSPController == NULL
   1774                 && mAudioPlayer != NULL
   1775                 && mAudioPlayer->getMediaTimeMapping(
   1776                     &realTimeUs, &mediaTimeUs)) {
   1777             LOGI("we're much too late (%.2f secs), video skipping ahead",
   1778                  latenessUs / 1E6);
   1779 
   1780             mVideoBuffer->release();
   1781             mVideoBuffer = NULL;
   1782 
   1783             mSeeking = SEEK_VIDEO_ONLY;
   1784             mSeekTimeUs = mediaTimeUs;
   1785 
   1786             postVideoEvent_l();
   1787             return;
   1788         }
   1789 
   1790         if (latenessUs > 40000) {
   1791             // We're more than 40ms late.
   1792             LOGV("we're late by %lld us (%.2f secs)",
   1793                  latenessUs, latenessUs / 1E6);
   1794 
   1795             if (!(mFlags & SLOW_DECODER_HACK)
   1796                     || mSinceLastDropped > FRAME_DROP_FREQ)
   1797             {
   1798                 LOGV("we're late by %lld us (%.2f secs) dropping "
   1799                      "one after %d frames",
   1800                      latenessUs, latenessUs / 1E6, mSinceLastDropped);
   1801 
   1802                 mSinceLastDropped = 0;
   1803                 mVideoBuffer->release();
   1804                 mVideoBuffer = NULL;
   1805 
   1806                 {
   1807                     Mutex::Autolock autoLock(mStatsLock);
   1808                     ++mStats.mNumVideoFramesDropped;
   1809                 }
   1810 
   1811                 postVideoEvent_l();
   1812                 return;
   1813             }
   1814         }
   1815 
   1816         if (latenessUs < -10000) {
   1817             // We're more than 10ms early.
   1818 
   1819             postVideoEvent_l(10000);
   1820             return;
   1821         }
   1822     }
   1823 
   1824     if ((mNativeWindow != NULL)
   1825             && (mVideoRendererIsPreview || mVideoRenderer == NULL)) {
   1826         mVideoRendererIsPreview = false;
   1827 
   1828         initRenderer_l();
   1829     }
   1830 
   1831     if (mVideoRenderer != NULL) {
   1832         mSinceLastDropped++;
   1833         mVideoRenderer->render(mVideoBuffer);
   1834     }
   1835 
   1836     mVideoBuffer->release();
   1837     mVideoBuffer = NULL;
   1838 
   1839     if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) {
   1840         modifyFlags(SEEK_PREVIEW, CLEAR);
   1841         return;
   1842     }
   1843 
   1844     postVideoEvent_l();
   1845 }
   1846 
   1847 void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
   1848     if (mVideoEventPending) {
   1849         return;
   1850     }
   1851 
   1852     mVideoEventPending = true;
   1853     mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
   1854 }
   1855 
   1856 void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
   1857     if (mStreamDoneEventPending) {
   1858         return;
   1859     }
   1860     mStreamDoneEventPending = true;
   1861 
   1862     mStreamDoneStatus = status;
   1863     mQueue.postEvent(mStreamDoneEvent);
   1864 }
   1865 
   1866 void AwesomePlayer::postBufferingEvent_l() {
   1867     if (mBufferingEventPending) {
   1868         return;
   1869     }
   1870     mBufferingEventPending = true;
   1871     mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
   1872 }
   1873 
   1874 void AwesomePlayer::postVideoLagEvent_l() {
   1875     if (mVideoLagEventPending) {
   1876         return;
   1877     }
   1878     mVideoLagEventPending = true;
   1879     mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
   1880 }
   1881 
   1882 void AwesomePlayer::postCheckAudioStatusEvent(int64_t delayUs) {
   1883     Mutex::Autolock autoLock(mAudioLock);
   1884     if (mAudioStatusEventPending) {
   1885         return;
   1886     }
   1887     mAudioStatusEventPending = true;
   1888     mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
   1889 }
   1890 
   1891 void AwesomePlayer::onCheckAudioStatus() {
   1892     {
   1893         Mutex::Autolock autoLock(mAudioLock);
   1894         if (!mAudioStatusEventPending) {
   1895             // Event was dispatched and while we were blocking on the mutex,
   1896             // has already been cancelled.
   1897             return;
   1898         }
   1899 
   1900         mAudioStatusEventPending = false;
   1901     }
   1902 
   1903     Mutex::Autolock autoLock(mLock);
   1904 
   1905     if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
   1906         mWatchForAudioSeekComplete = false;
   1907 
   1908         if (!mSeekNotificationSent) {
   1909             notifyListener_l(MEDIA_SEEK_COMPLETE);
   1910             mSeekNotificationSent = true;
   1911         }
   1912 
   1913         mSeeking = NO_SEEK;
   1914     }
   1915 
   1916     status_t finalStatus;
   1917     if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
   1918         mWatchForAudioEOS = false;
   1919         modifyFlags(AUDIO_AT_EOS, SET);
   1920         modifyFlags(FIRST_FRAME, SET);
   1921         postStreamDoneEvent_l(finalStatus);
   1922     }
   1923 }
   1924 
   1925 status_t AwesomePlayer::prepare() {
   1926     Mutex::Autolock autoLock(mLock);
   1927     return prepare_l();
   1928 }
   1929 
   1930 status_t AwesomePlayer::prepare_l() {
   1931     if (mFlags & PREPARED) {
   1932         return OK;
   1933     }
   1934 
   1935     if (mFlags & PREPARING) {
   1936         return UNKNOWN_ERROR;
   1937     }
   1938 
   1939     mIsAsyncPrepare = false;
   1940     status_t err = prepareAsync_l();
   1941 
   1942     if (err != OK) {
   1943         return err;
   1944     }
   1945 
   1946     while (mFlags & PREPARING) {
   1947         mPreparedCondition.wait(mLock);
   1948     }
   1949 
   1950     return mPrepareResult;
   1951 }
   1952 
   1953 status_t AwesomePlayer::prepareAsync() {
   1954     Mutex::Autolock autoLock(mLock);
   1955 
   1956     if (mFlags & PREPARING) {
   1957         return UNKNOWN_ERROR;  // async prepare already pending
   1958     }
   1959 
   1960     mIsAsyncPrepare = true;
   1961     return prepareAsync_l();
   1962 }
   1963 
   1964 status_t AwesomePlayer::prepareAsync_l() {
   1965     if (mFlags & PREPARING) {
   1966         return UNKNOWN_ERROR;  // async prepare already pending
   1967     }
   1968 
   1969     if (!mQueueStarted) {
   1970         mQueue.start();
   1971         mQueueStarted = true;
   1972     }
   1973 
   1974     modifyFlags(PREPARING, SET);
   1975     mAsyncPrepareEvent = new AwesomeEvent(
   1976             this, &AwesomePlayer::onPrepareAsyncEvent);
   1977 
   1978     mQueue.postEvent(mAsyncPrepareEvent);
   1979 
   1980     return OK;
   1981 }
   1982 
   1983 status_t AwesomePlayer::finishSetDataSource_l() {
   1984     sp<DataSource> dataSource;
   1985 
   1986     bool isWidevineStreaming = false;
   1987     if (!strncasecmp("widevine://", mUri.string(), 11)) {
   1988         isWidevineStreaming = true;
   1989 
   1990         String8 newURI = String8("http://");
   1991         newURI.append(mUri.string() + 11);
   1992 
   1993         mUri = newURI;
   1994     }
   1995 
   1996     if (!strncasecmp("http://", mUri.string(), 7)
   1997             || !strncasecmp("https://", mUri.string(), 8)
   1998             || isWidevineStreaming) {
   1999         mConnectingDataSource = HTTPBase::Create(
   2000                 (mFlags & INCOGNITO)
   2001                     ? HTTPBase::kFlagIncognito
   2002                     : 0);
   2003 
   2004         if (mUIDValid) {
   2005             mConnectingDataSource->setUID(mUID);
   2006         }
   2007 
   2008         String8 cacheConfig;
   2009         bool disconnectAtHighwatermark;
   2010         NuCachedSource2::RemoveCacheSpecificHeaders(
   2011                 &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark);
   2012 
   2013         mLock.unlock();
   2014         status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
   2015         mLock.lock();
   2016 
   2017         if (err != OK) {
   2018             mConnectingDataSource.clear();
   2019 
   2020             LOGI("mConnectingDataSource->connect() returned %d", err);
   2021             return err;
   2022         }
   2023 
   2024         if (!isWidevineStreaming) {
   2025             // The widevine extractor does its own caching.
   2026 
   2027 #if 0
   2028             mCachedSource = new NuCachedSource2(
   2029                     new ThrottledSource(
   2030                         mConnectingDataSource, 50 * 1024 /* bytes/sec */));
   2031 #else
   2032             mCachedSource = new NuCachedSource2(
   2033                     mConnectingDataSource,
   2034                     cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
   2035                     disconnectAtHighwatermark);
   2036 #endif
   2037 
   2038             dataSource = mCachedSource;
   2039         } else {
   2040             dataSource = mConnectingDataSource;
   2041         }
   2042 
   2043         mConnectingDataSource.clear();
   2044 
   2045 
   2046         String8 contentType = dataSource->getMIMEType();
   2047 
   2048         if (strncasecmp(contentType.string(), "audio/", 6)) {
   2049             // We're not doing this for streams that appear to be audio-only
   2050             // streams to ensure that even low bandwidth streams start
   2051             // playing back fairly instantly.
   2052 
   2053             // We're going to prefill the cache before trying to instantiate
   2054             // the extractor below, as the latter is an operation that otherwise
   2055             // could block on the datasource for a significant amount of time.
   2056             // During that time we'd be unable to abort the preparation phase
   2057             // without this prefill.
   2058             if (mCachedSource != NULL) {
   2059                 // We're going to prefill the cache before trying to instantiate
   2060                 // the extractor below, as the latter is an operation that otherwise
   2061                 // could block on the datasource for a significant amount of time.
   2062                 // During that time we'd be unable to abort the preparation phase
   2063                 // without this prefill.
   2064 
   2065                 mLock.unlock();
   2066 
   2067                 for (;;) {
   2068                     status_t finalStatus;
   2069                     size_t cachedDataRemaining =
   2070                         mCachedSource->approxDataRemaining(&finalStatus);
   2071 
   2072                     if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
   2073                             || (mFlags & PREPARE_CANCELLED)) {
   2074                         break;
   2075                     }
   2076 
   2077                     usleep(200000);
   2078                 }
   2079 
   2080                 mLock.lock();
   2081             }
   2082 
   2083             if (mFlags & PREPARE_CANCELLED) {
   2084                 LOGI("Prepare cancelled while waiting for initial cache fill.");
   2085                 return UNKNOWN_ERROR;
   2086             }
   2087         }
   2088     } else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
   2089         if (mLooper == NULL) {
   2090             mLooper = new ALooper;
   2091             mLooper->setName("rtsp");
   2092             mLooper->start();
   2093         }
   2094         mRTSPController = new ARTSPController(mLooper);
   2095         mConnectingRTSPController = mRTSPController;
   2096 
   2097         if (mUIDValid) {
   2098             mConnectingRTSPController->setUID(mUID);
   2099         }
   2100 
   2101         mLock.unlock();
   2102         status_t err = mRTSPController->connect(mUri.string());
   2103         mLock.lock();
   2104 
   2105         mConnectingRTSPController.clear();
   2106 
   2107         LOGI("ARTSPController::connect returned %d", err);
   2108 
   2109         if (err != OK) {
   2110             mRTSPController.clear();
   2111             return err;
   2112         }
   2113 
   2114         sp<MediaExtractor> extractor = mRTSPController.get();
   2115         return setDataSource_l(extractor);
   2116     } else {
   2117         dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
   2118     }
   2119 
   2120     if (dataSource == NULL) {
   2121         return UNKNOWN_ERROR;
   2122     }
   2123 
   2124     sp<MediaExtractor> extractor;
   2125 
   2126     if (isWidevineStreaming) {
   2127         String8 mimeType;
   2128         float confidence;
   2129         sp<AMessage> dummy;
   2130         bool success = SniffDRM(dataSource, &mimeType, &confidence, &dummy);
   2131 
   2132         if (!success
   2133                 || strcasecmp(
   2134                     mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
   2135             return ERROR_UNSUPPORTED;
   2136         }
   2137 
   2138         mWVMExtractor = new WVMExtractor(dataSource);
   2139         mWVMExtractor->setAdaptiveStreamingMode(true);
   2140         extractor = mWVMExtractor;
   2141     } else {
   2142         extractor = MediaExtractor::Create(dataSource);
   2143 
   2144         if (extractor == NULL) {
   2145             return UNKNOWN_ERROR;
   2146         }
   2147     }
   2148 
   2149     dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
   2150 
   2151     if (mDecryptHandle != NULL) {
   2152         CHECK(mDrmManagerClient);
   2153         if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
   2154             notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
   2155         }
   2156     }
   2157 
   2158     status_t err = setDataSource_l(extractor);
   2159 
   2160     if (err != OK) {
   2161         mWVMExtractor.clear();
   2162 
   2163         return err;
   2164     }
   2165 
   2166     return OK;
   2167 }
   2168 
   2169 void AwesomePlayer::abortPrepare(status_t err) {
   2170     CHECK(err != OK);
   2171 
   2172     if (mIsAsyncPrepare) {
   2173         notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
   2174     }
   2175 
   2176     mPrepareResult = err;
   2177     modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
   2178     mAsyncPrepareEvent = NULL;
   2179     mPreparedCondition.broadcast();
   2180 }
   2181 
   2182 // static
   2183 bool AwesomePlayer::ContinuePreparation(void *cookie) {
   2184     AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
   2185 
   2186     return (me->mFlags & PREPARE_CANCELLED) == 0;
   2187 }
   2188 
   2189 void AwesomePlayer::onPrepareAsyncEvent() {
   2190     Mutex::Autolock autoLock(mLock);
   2191 
   2192     if (mFlags & PREPARE_CANCELLED) {
   2193         LOGI("prepare was cancelled before doing anything");
   2194         abortPrepare(UNKNOWN_ERROR);
   2195         return;
   2196     }
   2197 
   2198     if (mUri.size() > 0) {
   2199         status_t err = finishSetDataSource_l();
   2200 
   2201         if (err != OK) {
   2202             abortPrepare(err);
   2203             return;
   2204         }
   2205     }
   2206 
   2207     if (mVideoTrack != NULL && mVideoSource == NULL) {
   2208         status_t err = initVideoDecoder();
   2209 
   2210         if (err != OK) {
   2211             abortPrepare(err);
   2212             return;
   2213         }
   2214     }
   2215 
   2216     if (mAudioTrack != NULL && mAudioSource == NULL) {
   2217         status_t err = initAudioDecoder();
   2218 
   2219         if (err != OK) {
   2220             abortPrepare(err);
   2221             return;
   2222         }
   2223     }
   2224 
   2225     modifyFlags(PREPARING_CONNECTED, SET);
   2226 
   2227     if (isStreamingHTTP() || mRTSPController != NULL) {
   2228         postBufferingEvent_l();
   2229     } else {
   2230         finishAsyncPrepare_l();
   2231     }
   2232 }
   2233 
   2234 void AwesomePlayer::finishAsyncPrepare_l() {
   2235     if (mIsAsyncPrepare) {
   2236         if (mVideoSource == NULL) {
   2237             notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
   2238         } else {
   2239             notifyVideoSize_l();
   2240         }
   2241 
   2242         notifyListener_l(MEDIA_PREPARED);
   2243     }
   2244 
   2245     mPrepareResult = OK;
   2246     modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
   2247     modifyFlags(PREPARED, SET);
   2248     mAsyncPrepareEvent = NULL;
   2249     mPreparedCondition.broadcast();
   2250 }
   2251 
   2252 uint32_t AwesomePlayer::flags() const {
   2253     return mExtractorFlags;
   2254 }
   2255 
   2256 void AwesomePlayer::postAudioEOS(int64_t delayUs) {
   2257     postCheckAudioStatusEvent(delayUs);
   2258 }
   2259 
   2260 void AwesomePlayer::postAudioSeekComplete() {
   2261     postCheckAudioStatusEvent(0);
   2262 }
   2263 
   2264 status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
   2265     switch (key) {
   2266         case KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX:
   2267         {
   2268             Mutex::Autolock autoLock(mTimedTextLock);
   2269             return setTimedTextTrackIndex(request.readInt32());
   2270         }
   2271         case KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE:
   2272         {
   2273             Mutex::Autolock autoLock(mTimedTextLock);
   2274             if (mTextPlayer == NULL) {
   2275                 mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue);
   2276             }
   2277 
   2278             return mTextPlayer->setParameter(key, request);
   2279         }
   2280         case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS:
   2281         {
   2282             return setCacheStatCollectFreq(request);
   2283         }
   2284         default:
   2285         {
   2286             return ERROR_UNSUPPORTED;
   2287         }
   2288     }
   2289 }
   2290 
   2291 status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) {
   2292     if (mCachedSource != NULL) {
   2293         int32_t freqMs = request.readInt32();
   2294         LOGD("Request to keep cache stats in the past %d ms",
   2295             freqMs);
   2296         return mCachedSource->setCacheStatCollectFreq(freqMs);
   2297     }
   2298     return ERROR_UNSUPPORTED;
   2299 }
   2300 
   2301 status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
   2302     switch (key) {
   2303     case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
   2304         {
   2305             int32_t channelCount;
   2306             if (mAudioTrack == 0 ||
   2307                     !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) {
   2308                 channelCount = 0;
   2309             }
   2310             reply->writeInt32(channelCount);
   2311         }
   2312         return OK;
   2313     default:
   2314         {
   2315             return ERROR_UNSUPPORTED;
   2316         }
   2317     }
   2318 }
   2319 
   2320 bool AwesomePlayer::isStreamingHTTP() const {
   2321     return mCachedSource != NULL || mWVMExtractor != NULL;
   2322 }
   2323 
   2324 status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const {
   2325     Mutex::Autolock autoLock(mStatsLock);
   2326 
   2327     FILE *out = fdopen(dup(fd), "w");
   2328 
   2329     fprintf(out, " AwesomePlayer\n");
   2330     if (mStats.mFd < 0) {
   2331         fprintf(out, "  URI(%s)", mStats.mURI.string());
   2332     } else {
   2333         fprintf(out, "  fd(%d)", mStats.mFd);
   2334     }
   2335 
   2336     fprintf(out, ", flags(0x%08x)", mStats.mFlags);
   2337 
   2338     if (mStats.mBitrate >= 0) {
   2339         fprintf(out, ", bitrate(%lld bps)", mStats.mBitrate);
   2340     }
   2341 
   2342     fprintf(out, "\n");
   2343 
   2344     for (size_t i = 0; i < mStats.mTracks.size(); ++i) {
   2345         const TrackStat &stat = mStats.mTracks.itemAt(i);
   2346 
   2347         fprintf(out, "  Track %d\n", i + 1);
   2348         fprintf(out, "   MIME(%s)", stat.mMIME.string());
   2349 
   2350         if (!stat.mDecoderName.isEmpty()) {
   2351             fprintf(out, ", decoder(%s)", stat.mDecoderName.string());
   2352         }
   2353 
   2354         fprintf(out, "\n");
   2355 
   2356         if ((ssize_t)i == mStats.mVideoTrackIndex) {
   2357             fprintf(out,
   2358                     "   videoDimensions(%d x %d), "
   2359                     "numVideoFramesDecoded(%lld), "
   2360                     "numVideoFramesDropped(%lld)\n",
   2361                     mStats.mVideoWidth,
   2362                     mStats.mVideoHeight,
   2363                     mStats.mNumVideoFramesDecoded,
   2364                     mStats.mNumVideoFramesDropped);
   2365         }
   2366     }
   2367 
   2368     fclose(out);
   2369     out = NULL;
   2370 
   2371     return OK;
   2372 }
   2373 
   2374 void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) {
   2375     switch (mode) {
   2376         case SET:
   2377             mFlags |= value;
   2378             break;
   2379         case CLEAR:
   2380             mFlags &= ~value;
   2381             break;
   2382         case ASSIGN:
   2383             mFlags = value;
   2384             break;
   2385         default:
   2386             TRESPASS();
   2387     }
   2388 
   2389     {
   2390         Mutex::Autolock autoLock(mStatsLock);
   2391         mStats.mFlags = mFlags;
   2392     }
   2393 }
   2394 
   2395 }  // namespace android
   2396