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