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