Home | History | Annotate | Download | only in nuplayer
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "GenericSource"
     19 
     20 #include "GenericSource.h"
     21 #include "NuPlayerDrm.h"
     22 
     23 #include "AnotherPacketSource.h"
     24 #include <binder/IServiceManager.h>
     25 #include <cutils/properties.h>
     26 #include <media/IMediaExtractorService.h>
     27 #include <media/IMediaHTTPService.h>
     28 #include <media/stagefright/foundation/ABuffer.h>
     29 #include <media/stagefright/foundation/ADebug.h>
     30 #include <media/stagefright/foundation/AMessage.h>
     31 #include <media/stagefright/DataSource.h>
     32 #include <media/stagefright/FileSource.h>
     33 #include <media/stagefright/MediaBuffer.h>
     34 #include <media/stagefright/MediaDefs.h>
     35 #include <media/stagefright/MediaExtractor.h>
     36 #include <media/stagefright/MediaSource.h>
     37 #include <media/stagefright/MetaData.h>
     38 #include <media/stagefright/Utils.h>
     39 #include "../../libstagefright/include/NuCachedSource2.h"
     40 #include "../../libstagefright/include/HTTPBase.h"
     41 
     42 namespace android {
     43 
     44 static const int kLowWaterMarkMs          = 2000;  // 2secs
     45 static const int kHighWaterMarkMs         = 5000;  // 5secs
     46 static const int kHighWaterMarkRebufferMs = 15000;  // 15secs
     47 
     48 static const int kLowWaterMarkKB  = 40;
     49 static const int kHighWaterMarkKB = 200;
     50 
     51 NuPlayer::GenericSource::GenericSource(
     52         const sp<AMessage> &notify,
     53         bool uidValid,
     54         uid_t uid)
     55     : Source(notify),
     56       mAudioTimeUs(0),
     57       mAudioLastDequeueTimeUs(0),
     58       mVideoTimeUs(0),
     59       mVideoLastDequeueTimeUs(0),
     60       mFetchSubtitleDataGeneration(0),
     61       mFetchTimedTextDataGeneration(0),
     62       mDurationUs(-1ll),
     63       mAudioIsVorbis(false),
     64       mIsSecure(false),
     65       mIsStreaming(false),
     66       mUIDValid(uidValid),
     67       mUID(uid),
     68       mFd(-1),
     69       mBitrate(-1ll),
     70       mPendingReadBufferTypes(0) {
     71     ALOGV("GenericSource");
     72 
     73     mBufferingMonitor = new BufferingMonitor(notify);
     74     resetDataSource();
     75 }
     76 
     77 void NuPlayer::GenericSource::resetDataSource() {
     78     ALOGV("resetDataSource");
     79 
     80     mHTTPService.clear();
     81     mHttpSource.clear();
     82     mUri.clear();
     83     mUriHeaders.clear();
     84     if (mFd >= 0) {
     85         close(mFd);
     86         mFd = -1;
     87     }
     88     mOffset = 0;
     89     mLength = 0;
     90     mStarted = false;
     91     mStopRead = true;
     92 
     93     if (mBufferingMonitorLooper != NULL) {
     94         mBufferingMonitorLooper->unregisterHandler(mBufferingMonitor->id());
     95         mBufferingMonitorLooper->stop();
     96         mBufferingMonitorLooper = NULL;
     97     }
     98     mBufferingMonitor->stop();
     99 
    100     mIsDrmProtected = false;
    101     mIsDrmReleased = false;
    102     mIsSecure = false;
    103     mMimes.clear();
    104 }
    105 
    106 status_t NuPlayer::GenericSource::setDataSource(
    107         const sp<IMediaHTTPService> &httpService,
    108         const char *url,
    109         const KeyedVector<String8, String8> *headers) {
    110     ALOGV("setDataSource url: %s", url);
    111 
    112     resetDataSource();
    113 
    114     mHTTPService = httpService;
    115     mUri = url;
    116 
    117     if (headers) {
    118         mUriHeaders = *headers;
    119     }
    120 
    121     // delay data source creation to prepareAsync() to avoid blocking
    122     // the calling thread in setDataSource for any significant time.
    123     return OK;
    124 }
    125 
    126 status_t NuPlayer::GenericSource::setDataSource(
    127         int fd, int64_t offset, int64_t length) {
    128     ALOGV("setDataSource %d/%lld/%lld", fd, (long long)offset, (long long)length);
    129 
    130     resetDataSource();
    131 
    132     mFd = dup(fd);
    133     mOffset = offset;
    134     mLength = length;
    135 
    136     // delay data source creation to prepareAsync() to avoid blocking
    137     // the calling thread in setDataSource for any significant time.
    138     return OK;
    139 }
    140 
    141 status_t NuPlayer::GenericSource::setDataSource(const sp<DataSource>& source) {
    142     ALOGV("setDataSource (source: %p)", source.get());
    143 
    144     resetDataSource();
    145     mDataSource = source;
    146     return OK;
    147 }
    148 
    149 sp<MetaData> NuPlayer::GenericSource::getFileFormatMeta() const {
    150     return mFileMeta;
    151 }
    152 
    153 status_t NuPlayer::GenericSource::initFromDataSource() {
    154     sp<IMediaExtractor> extractor;
    155     CHECK(mDataSource != NULL);
    156 
    157     extractor = MediaExtractor::Create(mDataSource, NULL);
    158 
    159     if (extractor == NULL) {
    160         ALOGE("initFromDataSource, cannot create extractor!");
    161         return UNKNOWN_ERROR;
    162     }
    163 
    164     mFileMeta = extractor->getMetaData();
    165     if (mFileMeta != NULL) {
    166         int64_t duration;
    167         if (mFileMeta->findInt64(kKeyDuration, &duration)) {
    168             mDurationUs = duration;
    169         }
    170     }
    171 
    172     int32_t totalBitrate = 0;
    173 
    174     size_t numtracks = extractor->countTracks();
    175     if (numtracks == 0) {
    176         ALOGE("initFromDataSource, source has no track!");
    177         return UNKNOWN_ERROR;
    178     }
    179 
    180     mMimes.clear();
    181 
    182     for (size_t i = 0; i < numtracks; ++i) {
    183         sp<IMediaSource> track = extractor->getTrack(i);
    184         if (track == NULL) {
    185             continue;
    186         }
    187 
    188         sp<MetaData> meta = extractor->getTrackMetaData(i);
    189         if (meta == NULL) {
    190             ALOGE("no metadata for track %zu", i);
    191             return UNKNOWN_ERROR;
    192         }
    193 
    194         const char *mime;
    195         CHECK(meta->findCString(kKeyMIMEType, &mime));
    196 
    197         ALOGV("initFromDataSource track[%zu]: %s", i, mime);
    198 
    199         // Do the string compare immediately with "mime",
    200         // we can't assume "mime" would stay valid after another
    201         // extractor operation, some extractors might modify meta
    202         // during getTrack() and make it invalid.
    203         if (!strncasecmp(mime, "audio/", 6)) {
    204             if (mAudioTrack.mSource == NULL) {
    205                 mAudioTrack.mIndex = i;
    206                 mAudioTrack.mSource = track;
    207                 mAudioTrack.mPackets =
    208                     new AnotherPacketSource(mAudioTrack.mSource->getFormat());
    209 
    210                 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
    211                     mAudioIsVorbis = true;
    212                 } else {
    213                     mAudioIsVorbis = false;
    214                 }
    215 
    216                 mMimes.add(String8(mime));
    217             }
    218         } else if (!strncasecmp(mime, "video/", 6)) {
    219             if (mVideoTrack.mSource == NULL) {
    220                 mVideoTrack.mIndex = i;
    221                 mVideoTrack.mSource = track;
    222                 mVideoTrack.mPackets =
    223                     new AnotherPacketSource(mVideoTrack.mSource->getFormat());
    224 
    225                 // video always at the beginning
    226                 mMimes.insertAt(String8(mime), 0);
    227             }
    228         }
    229 
    230         mSources.push(track);
    231         int64_t durationUs;
    232         if (meta->findInt64(kKeyDuration, &durationUs)) {
    233             if (durationUs > mDurationUs) {
    234                 mDurationUs = durationUs;
    235             }
    236         }
    237 
    238         int32_t bitrate;
    239         if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) {
    240             totalBitrate += bitrate;
    241         } else {
    242             totalBitrate = -1;
    243         }
    244     }
    245 
    246     ALOGV("initFromDataSource mSources.size(): %zu  mIsSecure: %d  mime[0]: %s", mSources.size(),
    247             mIsSecure, (mMimes.isEmpty() ? "NONE" : mMimes[0].string()));
    248 
    249     if (mSources.size() == 0) {
    250         ALOGE("b/23705695");
    251         return UNKNOWN_ERROR;
    252     }
    253 
    254     // Modular DRM: The return value doesn't affect source initialization.
    255     (void)checkDrmInfo();
    256 
    257     mBitrate = totalBitrate;
    258 
    259     return OK;
    260 }
    261 
    262 status_t NuPlayer::GenericSource::getDefaultBufferingSettings(
    263         BufferingSettings* buffering /* nonnull */) {
    264     mBufferingMonitor->getDefaultBufferingSettings(buffering);
    265     return OK;
    266 }
    267 
    268 status_t NuPlayer::GenericSource::setBufferingSettings(const BufferingSettings& buffering) {
    269     return mBufferingMonitor->setBufferingSettings(buffering);
    270 }
    271 
    272 status_t NuPlayer::GenericSource::startSources() {
    273     // Start the selected A/V tracks now before we start buffering.
    274     // Widevine sources might re-initialize crypto when starting, if we delay
    275     // this to start(), all data buffered during prepare would be wasted.
    276     // (We don't actually start reading until start().)
    277     //
    278     // TODO: this logic may no longer be relevant after the removal of widevine
    279     // support
    280     if (mAudioTrack.mSource != NULL && mAudioTrack.mSource->start() != OK) {
    281         ALOGE("failed to start audio track!");
    282         return UNKNOWN_ERROR;
    283     }
    284 
    285     if (mVideoTrack.mSource != NULL && mVideoTrack.mSource->start() != OK) {
    286         ALOGE("failed to start video track!");
    287         return UNKNOWN_ERROR;
    288     }
    289 
    290     return OK;
    291 }
    292 
    293 int64_t NuPlayer::GenericSource::getLastReadPosition() {
    294     if (mAudioTrack.mSource != NULL) {
    295         return mAudioTimeUs;
    296     } else if (mVideoTrack.mSource != NULL) {
    297         return mVideoTimeUs;
    298     } else {
    299         return 0;
    300     }
    301 }
    302 
    303 status_t NuPlayer::GenericSource::setBuffers(
    304         bool audio, Vector<MediaBuffer *> &buffers) {
    305     if (mIsSecure && !audio && mVideoTrack.mSource != NULL) {
    306         return mVideoTrack.mSource->setBuffers(buffers);
    307     }
    308     return INVALID_OPERATION;
    309 }
    310 
    311 bool NuPlayer::GenericSource::isStreaming() const {
    312     return mIsStreaming;
    313 }
    314 
    315 void NuPlayer::GenericSource::setOffloadAudio(bool offload) {
    316     mBufferingMonitor->setOffloadAudio(offload);
    317 }
    318 
    319 NuPlayer::GenericSource::~GenericSource() {
    320     ALOGV("~GenericSource");
    321     if (mLooper != NULL) {
    322         mLooper->unregisterHandler(id());
    323         mLooper->stop();
    324     }
    325     resetDataSource();
    326 }
    327 
    328 void NuPlayer::GenericSource::prepareAsync() {
    329     ALOGV("prepareAsync: (looper: %d)", (mLooper != NULL));
    330 
    331     if (mLooper == NULL) {
    332         mLooper = new ALooper;
    333         mLooper->setName("generic");
    334         mLooper->start();
    335 
    336         mLooper->registerHandler(this);
    337     }
    338 
    339     sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this);
    340     msg->post();
    341 }
    342 
    343 void NuPlayer::GenericSource::onPrepareAsync() {
    344     ALOGV("onPrepareAsync: mDataSource: %d", (mDataSource != NULL));
    345 
    346     // delayed data source creation
    347     if (mDataSource == NULL) {
    348         // set to false first, if the extractor
    349         // comes back as secure, set it to true then.
    350         mIsSecure = false;
    351 
    352         if (!mUri.empty()) {
    353             const char* uri = mUri.c_str();
    354             String8 contentType;
    355 
    356             if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
    357                 mHttpSource = DataSource::CreateMediaHTTP(mHTTPService);
    358                 if (mHttpSource == NULL) {
    359                     ALOGE("Failed to create http source!");
    360                     notifyPreparedAndCleanup(UNKNOWN_ERROR);
    361                     return;
    362                 }
    363             }
    364 
    365             mDataSource = DataSource::CreateFromURI(
    366                    mHTTPService, uri, &mUriHeaders, &contentType,
    367                    static_cast<HTTPBase *>(mHttpSource.get()));
    368         } else {
    369             if (property_get_bool("media.stagefright.extractremote", true) &&
    370                     !FileSource::requiresDrm(mFd, mOffset, mLength, nullptr /* mime */)) {
    371                 sp<IBinder> binder =
    372                         defaultServiceManager()->getService(String16("media.extractor"));
    373                 if (binder != nullptr) {
    374                     ALOGD("FileSource remote");
    375                     sp<IMediaExtractorService> mediaExService(
    376                             interface_cast<IMediaExtractorService>(binder));
    377                     sp<IDataSource> source =
    378                             mediaExService->makeIDataSource(mFd, mOffset, mLength);
    379                     ALOGV("IDataSource(FileSource): %p %d %lld %lld",
    380                             source.get(), mFd, (long long)mOffset, (long long)mLength);
    381                     if (source.get() != nullptr) {
    382                         mDataSource = DataSource::CreateFromIDataSource(source);
    383                         if (mDataSource != nullptr) {
    384                             // Close the local file descriptor as it is not needed anymore.
    385                             close(mFd);
    386                             mFd = -1;
    387                         }
    388                     } else {
    389                         ALOGW("extractor service cannot make data source");
    390                     }
    391                 } else {
    392                     ALOGW("extractor service not running");
    393                 }
    394             }
    395             if (mDataSource == nullptr) {
    396                 ALOGD("FileSource local");
    397                 mDataSource = new FileSource(mFd, mOffset, mLength);
    398             }
    399             // TODO: close should always be done on mFd, see the lines following
    400             // DataSource::CreateFromIDataSource above,
    401             // and the FileSource constructor should dup the mFd argument as needed.
    402             mFd = -1;
    403         }
    404 
    405         if (mDataSource == NULL) {
    406             ALOGE("Failed to create data source!");
    407             notifyPreparedAndCleanup(UNKNOWN_ERROR);
    408             return;
    409         }
    410     }
    411 
    412     if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
    413         mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
    414     }
    415 
    416     // For cached streaming cases, we need to wait for enough
    417     // buffering before reporting prepared.
    418     mIsStreaming = (mCachedSource != NULL);
    419 
    420     // init extractor from data source
    421     status_t err = initFromDataSource();
    422 
    423     if (err != OK) {
    424         ALOGE("Failed to init from data source!");
    425         notifyPreparedAndCleanup(err);
    426         return;
    427     }
    428 
    429     if (mVideoTrack.mSource != NULL) {
    430         sp<MetaData> meta = doGetFormatMeta(false /* audio */);
    431         sp<AMessage> msg = new AMessage;
    432         err = convertMetaDataToMessage(meta, &msg);
    433         if(err != OK) {
    434             notifyPreparedAndCleanup(err);
    435             return;
    436         }
    437         notifyVideoSizeChanged(msg);
    438     }
    439 
    440     notifyFlagsChanged(
    441             // FLAG_SECURE will be known if/when prepareDrm is called by the app
    442             // FLAG_PROTECTED will be known if/when prepareDrm is called by the app
    443             FLAG_CAN_PAUSE |
    444             FLAG_CAN_SEEK_BACKWARD |
    445             FLAG_CAN_SEEK_FORWARD |
    446             FLAG_CAN_SEEK);
    447 
    448     finishPrepareAsync();
    449 
    450     ALOGV("onPrepareAsync: Done");
    451 }
    452 
    453 void NuPlayer::GenericSource::finishPrepareAsync() {
    454     ALOGV("finishPrepareAsync");
    455 
    456     status_t err = startSources();
    457     if (err != OK) {
    458         ALOGE("Failed to init start data source!");
    459         notifyPreparedAndCleanup(err);
    460         return;
    461     }
    462 
    463     if (mIsStreaming) {
    464         if (mBufferingMonitorLooper == NULL) {
    465             mBufferingMonitor->prepare(mCachedSource, mDurationUs, mBitrate,
    466                     mIsStreaming);
    467 
    468             mBufferingMonitorLooper = new ALooper;
    469             mBufferingMonitorLooper->setName("GSBMonitor");
    470             mBufferingMonitorLooper->start();
    471             mBufferingMonitorLooper->registerHandler(mBufferingMonitor);
    472         }
    473 
    474         mBufferingMonitor->ensureCacheIsFetching();
    475         mBufferingMonitor->restartPollBuffering();
    476     } else {
    477         notifyPrepared();
    478     }
    479 }
    480 
    481 void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) {
    482     if (err != OK) {
    483         {
    484             sp<DataSource> dataSource = mDataSource;
    485             sp<NuCachedSource2> cachedSource = mCachedSource;
    486             sp<DataSource> httpSource = mHttpSource;
    487             {
    488                 Mutex::Autolock _l(mDisconnectLock);
    489                 mDataSource.clear();
    490                 mCachedSource.clear();
    491                 mHttpSource.clear();
    492             }
    493         }
    494         mBitrate = -1;
    495 
    496         mBufferingMonitor->cancelPollBuffering();
    497     }
    498     notifyPrepared(err);
    499 }
    500 
    501 void NuPlayer::GenericSource::start() {
    502     ALOGI("start");
    503 
    504     mStopRead = false;
    505     if (mAudioTrack.mSource != NULL) {
    506         postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
    507     }
    508 
    509     if (mVideoTrack.mSource != NULL) {
    510         postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
    511     }
    512 
    513     mStarted = true;
    514 
    515     (new AMessage(kWhatStart, this))->post();
    516 }
    517 
    518 void NuPlayer::GenericSource::stop() {
    519     mStarted = false;
    520 }
    521 
    522 void NuPlayer::GenericSource::pause() {
    523     mStarted = false;
    524 }
    525 
    526 void NuPlayer::GenericSource::resume() {
    527     mStarted = true;
    528 
    529     (new AMessage(kWhatResume, this))->post();
    530 }
    531 
    532 void NuPlayer::GenericSource::disconnect() {
    533     sp<DataSource> dataSource, httpSource;
    534     {
    535         Mutex::Autolock _l(mDisconnectLock);
    536         dataSource = mDataSource;
    537         httpSource = mHttpSource;
    538     }
    539 
    540     if (dataSource != NULL) {
    541         // disconnect data source
    542         if (dataSource->flags() & DataSource::kIsCachingDataSource) {
    543             static_cast<NuCachedSource2 *>(dataSource.get())->disconnect();
    544         }
    545     } else if (httpSource != NULL) {
    546         static_cast<HTTPBase *>(httpSource.get())->disconnect();
    547     }
    548 }
    549 
    550 status_t NuPlayer::GenericSource::feedMoreTSData() {
    551     return OK;
    552 }
    553 
    554 void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
    555     switch (msg->what()) {
    556       case kWhatPrepareAsync:
    557       {
    558           onPrepareAsync();
    559           break;
    560       }
    561       case kWhatFetchSubtitleData:
    562       {
    563           fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
    564                   mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
    565           break;
    566       }
    567 
    568       case kWhatFetchTimedTextData:
    569       {
    570           fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
    571                   mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
    572           break;
    573       }
    574 
    575       case kWhatSendSubtitleData:
    576       {
    577           sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
    578                   mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
    579           break;
    580       }
    581 
    582       case kWhatSendGlobalTimedTextData:
    583       {
    584           sendGlobalTextData(kWhatTimedTextData, mFetchTimedTextDataGeneration, msg);
    585           break;
    586       }
    587       case kWhatSendTimedTextData:
    588       {
    589           sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
    590                   mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
    591           break;
    592       }
    593 
    594       case kWhatChangeAVSource:
    595       {
    596           int32_t trackIndex;
    597           CHECK(msg->findInt32("trackIndex", &trackIndex));
    598           const sp<IMediaSource> source = mSources.itemAt(trackIndex);
    599 
    600           Track* track;
    601           const char *mime;
    602           media_track_type trackType, counterpartType;
    603           sp<MetaData> meta = source->getFormat();
    604           meta->findCString(kKeyMIMEType, &mime);
    605           if (!strncasecmp(mime, "audio/", 6)) {
    606               track = &mAudioTrack;
    607               trackType = MEDIA_TRACK_TYPE_AUDIO;
    608               counterpartType = MEDIA_TRACK_TYPE_VIDEO;;
    609           } else {
    610               CHECK(!strncasecmp(mime, "video/", 6));
    611               track = &mVideoTrack;
    612               trackType = MEDIA_TRACK_TYPE_VIDEO;
    613               counterpartType = MEDIA_TRACK_TYPE_AUDIO;;
    614           }
    615 
    616 
    617           if (track->mSource != NULL) {
    618               track->mSource->stop();
    619           }
    620           track->mSource = source;
    621           track->mSource->start();
    622           track->mIndex = trackIndex;
    623 
    624           int64_t timeUs, actualTimeUs;
    625           const bool formatChange = true;
    626           if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
    627               timeUs = mAudioLastDequeueTimeUs;
    628           } else {
    629               timeUs = mVideoLastDequeueTimeUs;
    630           }
    631           readBuffer(trackType, timeUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
    632                   &actualTimeUs, formatChange);
    633           readBuffer(counterpartType, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
    634                   NULL, !formatChange);
    635           ALOGV("timeUs %lld actualTimeUs %lld", (long long)timeUs, (long long)actualTimeUs);
    636 
    637           break;
    638       }
    639 
    640       case kWhatStart:
    641       case kWhatResume:
    642       {
    643           mBufferingMonitor->restartPollBuffering();
    644           break;
    645       }
    646 
    647       case kWhatGetFormat:
    648       {
    649           onGetFormatMeta(msg);
    650           break;
    651       }
    652 
    653       case kWhatGetSelectedTrack:
    654       {
    655           onGetSelectedTrack(msg);
    656           break;
    657       }
    658 
    659       case kWhatGetTrackInfo:
    660       {
    661           onGetTrackInfo(msg);
    662           break;
    663       }
    664 
    665       case kWhatSelectTrack:
    666       {
    667           onSelectTrack(msg);
    668           break;
    669       }
    670 
    671       case kWhatSeek:
    672       {
    673           onSeek(msg);
    674           break;
    675       }
    676 
    677       case kWhatReadBuffer:
    678       {
    679           onReadBuffer(msg);
    680           break;
    681       }
    682 
    683       case kWhatPrepareDrm:
    684       {
    685           status_t status = onPrepareDrm(msg);
    686           sp<AMessage> response = new AMessage;
    687           response->setInt32("status", status);
    688           sp<AReplyToken> replyID;
    689           CHECK(msg->senderAwaitsResponse(&replyID));
    690           response->postReply(replyID);
    691           break;
    692       }
    693 
    694       case kWhatReleaseDrm:
    695       {
    696           status_t status = onReleaseDrm();
    697           sp<AMessage> response = new AMessage;
    698           response->setInt32("status", status);
    699           sp<AReplyToken> replyID;
    700           CHECK(msg->senderAwaitsResponse(&replyID));
    701           response->postReply(replyID);
    702           break;
    703       }
    704 
    705       default:
    706           Source::onMessageReceived(msg);
    707           break;
    708     }
    709 }
    710 
    711 void NuPlayer::GenericSource::fetchTextData(
    712         uint32_t sendWhat,
    713         media_track_type type,
    714         int32_t curGen,
    715         const sp<AnotherPacketSource>& packets,
    716         const sp<AMessage>& msg) {
    717     int32_t msgGeneration;
    718     CHECK(msg->findInt32("generation", &msgGeneration));
    719     if (msgGeneration != curGen) {
    720         // stale
    721         return;
    722     }
    723 
    724     int32_t avail;
    725     if (packets->hasBufferAvailable(&avail)) {
    726         return;
    727     }
    728 
    729     int64_t timeUs;
    730     CHECK(msg->findInt64("timeUs", &timeUs));
    731 
    732     int64_t subTimeUs;
    733     readBuffer(type, timeUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &subTimeUs);
    734 
    735     int64_t delayUs = subTimeUs - timeUs;
    736     if (msg->what() == kWhatFetchSubtitleData) {
    737         const int64_t oneSecUs = 1000000ll;
    738         delayUs -= oneSecUs;
    739     }
    740     sp<AMessage> msg2 = new AMessage(sendWhat, this);
    741     msg2->setInt32("generation", msgGeneration);
    742     msg2->post(delayUs < 0 ? 0 : delayUs);
    743 }
    744 
    745 void NuPlayer::GenericSource::sendTextData(
    746         uint32_t what,
    747         media_track_type type,
    748         int32_t curGen,
    749         const sp<AnotherPacketSource>& packets,
    750         const sp<AMessage>& msg) {
    751     int32_t msgGeneration;
    752     CHECK(msg->findInt32("generation", &msgGeneration));
    753     if (msgGeneration != curGen) {
    754         // stale
    755         return;
    756     }
    757 
    758     int64_t subTimeUs;
    759     if (packets->nextBufferTime(&subTimeUs) != OK) {
    760         return;
    761     }
    762 
    763     int64_t nextSubTimeUs;
    764     readBuffer(type, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &nextSubTimeUs);
    765 
    766     sp<ABuffer> buffer;
    767     status_t dequeueStatus = packets->dequeueAccessUnit(&buffer);
    768     if (dequeueStatus == OK) {
    769         sp<AMessage> notify = dupNotify();
    770         notify->setInt32("what", what);
    771         notify->setBuffer("buffer", buffer);
    772         notify->post();
    773 
    774         const int64_t delayUs = nextSubTimeUs - subTimeUs;
    775         msg->post(delayUs < 0 ? 0 : delayUs);
    776     }
    777 }
    778 
    779 void NuPlayer::GenericSource::sendGlobalTextData(
    780         uint32_t what,
    781         int32_t curGen,
    782         sp<AMessage> msg) {
    783     int32_t msgGeneration;
    784     CHECK(msg->findInt32("generation", &msgGeneration));
    785     if (msgGeneration != curGen) {
    786         // stale
    787         return;
    788     }
    789 
    790     uint32_t textType;
    791     const void *data;
    792     size_t size = 0;
    793     if (mTimedTextTrack.mSource->getFormat()->findData(
    794                     kKeyTextFormatData, &textType, &data, &size)) {
    795         mGlobalTimedText = new ABuffer(size);
    796         if (mGlobalTimedText->data()) {
    797             memcpy(mGlobalTimedText->data(), data, size);
    798             sp<AMessage> globalMeta = mGlobalTimedText->meta();
    799             globalMeta->setInt64("timeUs", 0);
    800             globalMeta->setString("mime", MEDIA_MIMETYPE_TEXT_3GPP);
    801             globalMeta->setInt32("global", 1);
    802             sp<AMessage> notify = dupNotify();
    803             notify->setInt32("what", what);
    804             notify->setBuffer("buffer", mGlobalTimedText);
    805             notify->post();
    806         }
    807     }
    808 }
    809 
    810 sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) {
    811     sp<AMessage> msg = new AMessage(kWhatGetFormat, this);
    812     msg->setInt32("audio", audio);
    813 
    814     sp<AMessage> response;
    815     sp<RefBase> format;
    816     status_t err = msg->postAndAwaitResponse(&response);
    817     if (err == OK && response != NULL) {
    818         CHECK(response->findObject("format", &format));
    819         return static_cast<MetaData*>(format.get());
    820     } else {
    821         return NULL;
    822     }
    823 }
    824 
    825 void NuPlayer::GenericSource::onGetFormatMeta(const sp<AMessage>& msg) const {
    826     int32_t audio;
    827     CHECK(msg->findInt32("audio", &audio));
    828 
    829     sp<AMessage> response = new AMessage;
    830     sp<MetaData> format = doGetFormatMeta(audio);
    831     response->setObject("format", format);
    832 
    833     sp<AReplyToken> replyID;
    834     CHECK(msg->senderAwaitsResponse(&replyID));
    835     response->postReply(replyID);
    836 }
    837 
    838 sp<MetaData> NuPlayer::GenericSource::doGetFormatMeta(bool audio) const {
    839     sp<IMediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
    840 
    841     if (source == NULL) {
    842         return NULL;
    843     }
    844 
    845     return source->getFormat();
    846 }
    847 
    848 status_t NuPlayer::GenericSource::dequeueAccessUnit(
    849         bool audio, sp<ABuffer> *accessUnit) {
    850     if (audio && !mStarted) {
    851         return -EWOULDBLOCK;
    852     }
    853 
    854     // If has gone through stop/releaseDrm sequence, we no longer send down any buffer b/c
    855     // the codec's crypto object has gone away (b/37960096).
    856     // Note: This will be unnecessary when stop() changes behavior and releases codec (b/35248283).
    857     if (!mStarted && mIsDrmReleased) {
    858         return -EWOULDBLOCK;
    859     }
    860 
    861     Track *track = audio ? &mAudioTrack : &mVideoTrack;
    862 
    863     if (track->mSource == NULL) {
    864         return -EWOULDBLOCK;
    865     }
    866 
    867     status_t finalResult;
    868     if (!track->mPackets->hasBufferAvailable(&finalResult)) {
    869         if (finalResult == OK) {
    870             postReadBuffer(
    871                     audio ? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
    872             return -EWOULDBLOCK;
    873         }
    874         return finalResult;
    875     }
    876 
    877     status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
    878 
    879     // start pulling in more buffers if we only have one (or no) buffer left
    880     // so that decoder has less chance of being starved
    881     if (track->mPackets->getAvailableBufferCount(&finalResult) < 2) {
    882         postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
    883     }
    884 
    885     if (result != OK) {
    886         if (mSubtitleTrack.mSource != NULL) {
    887             mSubtitleTrack.mPackets->clear();
    888             mFetchSubtitleDataGeneration++;
    889         }
    890         if (mTimedTextTrack.mSource != NULL) {
    891             mTimedTextTrack.mPackets->clear();
    892             mFetchTimedTextDataGeneration++;
    893         }
    894         return result;
    895     }
    896 
    897     int64_t timeUs;
    898     status_t eosResult; // ignored
    899     CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
    900     if (audio) {
    901         mAudioLastDequeueTimeUs = timeUs;
    902         mBufferingMonitor->updateDequeuedBufferTime(timeUs);
    903     } else {
    904         mVideoLastDequeueTimeUs = timeUs;
    905     }
    906 
    907     if (mSubtitleTrack.mSource != NULL
    908             && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
    909         sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
    910         msg->setInt64("timeUs", timeUs);
    911         msg->setInt32("generation", mFetchSubtitleDataGeneration);
    912         msg->post();
    913     }
    914 
    915     if (mTimedTextTrack.mSource != NULL
    916             && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
    917         sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
    918         msg->setInt64("timeUs", timeUs);
    919         msg->setInt32("generation", mFetchTimedTextDataGeneration);
    920         msg->post();
    921     }
    922 
    923     return result;
    924 }
    925 
    926 status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) {
    927     *durationUs = mDurationUs;
    928     return OK;
    929 }
    930 
    931 size_t NuPlayer::GenericSource::getTrackCount() const {
    932     return mSources.size();
    933 }
    934 
    935 sp<AMessage> NuPlayer::GenericSource::getTrackInfo(size_t trackIndex) const {
    936     sp<AMessage> msg = new AMessage(kWhatGetTrackInfo, this);
    937     msg->setSize("trackIndex", trackIndex);
    938 
    939     sp<AMessage> response;
    940     sp<RefBase> format;
    941     status_t err = msg->postAndAwaitResponse(&response);
    942     if (err == OK && response != NULL) {
    943         CHECK(response->findObject("format", &format));
    944         return static_cast<AMessage*>(format.get());
    945     } else {
    946         return NULL;
    947     }
    948 }
    949 
    950 void NuPlayer::GenericSource::onGetTrackInfo(const sp<AMessage>& msg) const {
    951     size_t trackIndex;
    952     CHECK(msg->findSize("trackIndex", &trackIndex));
    953 
    954     sp<AMessage> response = new AMessage;
    955     sp<AMessage> format = doGetTrackInfo(trackIndex);
    956     response->setObject("format", format);
    957 
    958     sp<AReplyToken> replyID;
    959     CHECK(msg->senderAwaitsResponse(&replyID));
    960     response->postReply(replyID);
    961 }
    962 
    963 sp<AMessage> NuPlayer::GenericSource::doGetTrackInfo(size_t trackIndex) const {
    964     size_t trackCount = mSources.size();
    965     if (trackIndex >= trackCount) {
    966         return NULL;
    967     }
    968 
    969     sp<AMessage> format = new AMessage();
    970     sp<MetaData> meta = mSources.itemAt(trackIndex)->getFormat();
    971     if (meta == NULL) {
    972         ALOGE("no metadata for track %zu", trackIndex);
    973         return NULL;
    974     }
    975 
    976     const char *mime;
    977     CHECK(meta->findCString(kKeyMIMEType, &mime));
    978     format->setString("mime", mime);
    979 
    980     int32_t trackType;
    981     if (!strncasecmp(mime, "video/", 6)) {
    982         trackType = MEDIA_TRACK_TYPE_VIDEO;
    983     } else if (!strncasecmp(mime, "audio/", 6)) {
    984         trackType = MEDIA_TRACK_TYPE_AUDIO;
    985     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
    986         trackType = MEDIA_TRACK_TYPE_TIMEDTEXT;
    987     } else {
    988         trackType = MEDIA_TRACK_TYPE_UNKNOWN;
    989     }
    990     format->setInt32("type", trackType);
    991 
    992     const char *lang;
    993     if (!meta->findCString(kKeyMediaLanguage, &lang)) {
    994         lang = "und";
    995     }
    996     format->setString("language", lang);
    997 
    998     if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
    999         int32_t isAutoselect = 1, isDefault = 0, isForced = 0;
   1000         meta->findInt32(kKeyTrackIsAutoselect, &isAutoselect);
   1001         meta->findInt32(kKeyTrackIsDefault, &isDefault);
   1002         meta->findInt32(kKeyTrackIsForced, &isForced);
   1003 
   1004         format->setInt32("auto", !!isAutoselect);
   1005         format->setInt32("default", !!isDefault);
   1006         format->setInt32("forced", !!isForced);
   1007     }
   1008 
   1009     return format;
   1010 }
   1011 
   1012 ssize_t NuPlayer::GenericSource::getSelectedTrack(media_track_type type) const {
   1013     sp<AMessage> msg = new AMessage(kWhatGetSelectedTrack, this);
   1014     msg->setInt32("type", type);
   1015 
   1016     sp<AMessage> response;
   1017     int32_t index;
   1018     status_t err = msg->postAndAwaitResponse(&response);
   1019     if (err == OK && response != NULL) {
   1020         CHECK(response->findInt32("index", &index));
   1021         return index;
   1022     } else {
   1023         return -1;
   1024     }
   1025 }
   1026 
   1027 void NuPlayer::GenericSource::onGetSelectedTrack(const sp<AMessage>& msg) const {
   1028     int32_t tmpType;
   1029     CHECK(msg->findInt32("type", &tmpType));
   1030     media_track_type type = (media_track_type)tmpType;
   1031 
   1032     sp<AMessage> response = new AMessage;
   1033     ssize_t index = doGetSelectedTrack(type);
   1034     response->setInt32("index", index);
   1035 
   1036     sp<AReplyToken> replyID;
   1037     CHECK(msg->senderAwaitsResponse(&replyID));
   1038     response->postReply(replyID);
   1039 }
   1040 
   1041 ssize_t NuPlayer::GenericSource::doGetSelectedTrack(media_track_type type) const {
   1042     const Track *track = NULL;
   1043     switch (type) {
   1044     case MEDIA_TRACK_TYPE_VIDEO:
   1045         track = &mVideoTrack;
   1046         break;
   1047     case MEDIA_TRACK_TYPE_AUDIO:
   1048         track = &mAudioTrack;
   1049         break;
   1050     case MEDIA_TRACK_TYPE_TIMEDTEXT:
   1051         track = &mTimedTextTrack;
   1052         break;
   1053     case MEDIA_TRACK_TYPE_SUBTITLE:
   1054         track = &mSubtitleTrack;
   1055         break;
   1056     default:
   1057         break;
   1058     }
   1059 
   1060     if (track != NULL && track->mSource != NULL) {
   1061         return track->mIndex;
   1062     }
   1063 
   1064     return -1;
   1065 }
   1066 
   1067 status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select, int64_t timeUs) {
   1068     ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex);
   1069     sp<AMessage> msg = new AMessage(kWhatSelectTrack, this);
   1070     msg->setInt32("trackIndex", trackIndex);
   1071     msg->setInt32("select", select);
   1072     msg->setInt64("timeUs", timeUs);
   1073 
   1074     sp<AMessage> response;
   1075     status_t err = msg->postAndAwaitResponse(&response);
   1076     if (err == OK && response != NULL) {
   1077         CHECK(response->findInt32("err", &err));
   1078     }
   1079 
   1080     return err;
   1081 }
   1082 
   1083 void NuPlayer::GenericSource::onSelectTrack(const sp<AMessage>& msg) {
   1084     int32_t trackIndex, select;
   1085     int64_t timeUs;
   1086     CHECK(msg->findInt32("trackIndex", &trackIndex));
   1087     CHECK(msg->findInt32("select", &select));
   1088     CHECK(msg->findInt64("timeUs", &timeUs));
   1089 
   1090     sp<AMessage> response = new AMessage;
   1091     status_t err = doSelectTrack(trackIndex, select, timeUs);
   1092     response->setInt32("err", err);
   1093 
   1094     sp<AReplyToken> replyID;
   1095     CHECK(msg->senderAwaitsResponse(&replyID));
   1096     response->postReply(replyID);
   1097 }
   1098 
   1099 status_t NuPlayer::GenericSource::doSelectTrack(size_t trackIndex, bool select, int64_t timeUs) {
   1100     if (trackIndex >= mSources.size()) {
   1101         return BAD_INDEX;
   1102     }
   1103 
   1104     if (!select) {
   1105         Track* track = NULL;
   1106         if (mSubtitleTrack.mSource != NULL && trackIndex == mSubtitleTrack.mIndex) {
   1107             track = &mSubtitleTrack;
   1108             mFetchSubtitleDataGeneration++;
   1109         } else if (mTimedTextTrack.mSource != NULL && trackIndex == mTimedTextTrack.mIndex) {
   1110             track = &mTimedTextTrack;
   1111             mFetchTimedTextDataGeneration++;
   1112         }
   1113         if (track == NULL) {
   1114             return INVALID_OPERATION;
   1115         }
   1116         track->mSource->stop();
   1117         track->mSource = NULL;
   1118         track->mPackets->clear();
   1119         return OK;
   1120     }
   1121 
   1122     const sp<IMediaSource> source = mSources.itemAt(trackIndex);
   1123     sp<MetaData> meta = source->getFormat();
   1124     const char *mime;
   1125     CHECK(meta->findCString(kKeyMIMEType, &mime));
   1126     if (!strncasecmp(mime, "text/", 5)) {
   1127         bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP);
   1128         Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack;
   1129         if (track->mSource != NULL && track->mIndex == trackIndex) {
   1130             return OK;
   1131         }
   1132         track->mIndex = trackIndex;
   1133         if (track->mSource != NULL) {
   1134             track->mSource->stop();
   1135         }
   1136         track->mSource = mSources.itemAt(trackIndex);
   1137         track->mSource->start();
   1138         if (track->mPackets == NULL) {
   1139             track->mPackets = new AnotherPacketSource(track->mSource->getFormat());
   1140         } else {
   1141             track->mPackets->clear();
   1142             track->mPackets->setFormat(track->mSource->getFormat());
   1143 
   1144         }
   1145 
   1146         if (isSubtitle) {
   1147             mFetchSubtitleDataGeneration++;
   1148         } else {
   1149             mFetchTimedTextDataGeneration++;
   1150         }
   1151 
   1152         status_t eosResult; // ignored
   1153         if (mSubtitleTrack.mSource != NULL
   1154                 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
   1155             sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
   1156             msg->setInt64("timeUs", timeUs);
   1157             msg->setInt32("generation", mFetchSubtitleDataGeneration);
   1158             msg->post();
   1159         }
   1160 
   1161         sp<AMessage> msg2 = new AMessage(kWhatSendGlobalTimedTextData, this);
   1162         msg2->setInt32("generation", mFetchTimedTextDataGeneration);
   1163         msg2->post();
   1164 
   1165         if (mTimedTextTrack.mSource != NULL
   1166                 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
   1167             sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
   1168             msg->setInt64("timeUs", timeUs);
   1169             msg->setInt32("generation", mFetchTimedTextDataGeneration);
   1170             msg->post();
   1171         }
   1172 
   1173         return OK;
   1174     } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) {
   1175         bool audio = !strncasecmp(mime, "audio/", 6);
   1176         Track *track = audio ? &mAudioTrack : &mVideoTrack;
   1177         if (track->mSource != NULL && track->mIndex == trackIndex) {
   1178             return OK;
   1179         }
   1180 
   1181         sp<AMessage> msg = new AMessage(kWhatChangeAVSource, this);
   1182         msg->setInt32("trackIndex", trackIndex);
   1183         msg->post();
   1184         return OK;
   1185     }
   1186 
   1187     return INVALID_OPERATION;
   1188 }
   1189 
   1190 status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
   1191     sp<AMessage> msg = new AMessage(kWhatSeek, this);
   1192     msg->setInt64("seekTimeUs", seekTimeUs);
   1193     msg->setInt32("mode", mode);
   1194 
   1195     sp<AMessage> response;
   1196     status_t err = msg->postAndAwaitResponse(&response);
   1197     if (err == OK && response != NULL) {
   1198         CHECK(response->findInt32("err", &err));
   1199     }
   1200 
   1201     return err;
   1202 }
   1203 
   1204 void NuPlayer::GenericSource::onSeek(const sp<AMessage>& msg) {
   1205     int64_t seekTimeUs;
   1206     int32_t mode;
   1207     CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
   1208     CHECK(msg->findInt32("mode", &mode));
   1209 
   1210     sp<AMessage> response = new AMessage;
   1211     status_t err = doSeek(seekTimeUs, (MediaPlayerSeekMode)mode);
   1212     response->setInt32("err", err);
   1213 
   1214     sp<AReplyToken> replyID;
   1215     CHECK(msg->senderAwaitsResponse(&replyID));
   1216     response->postReply(replyID);
   1217 }
   1218 
   1219 status_t NuPlayer::GenericSource::doSeek(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
   1220     mBufferingMonitor->updateDequeuedBufferTime(-1ll);
   1221 
   1222     // If the Widevine source is stopped, do not attempt to read any
   1223     // more buffers.
   1224     //
   1225     // TODO: revisit after widevine is removed.  May be able to
   1226     // combine mStopRead with mStarted.
   1227     if (mStopRead) {
   1228         return INVALID_OPERATION;
   1229     }
   1230     if (mVideoTrack.mSource != NULL) {
   1231         int64_t actualTimeUs;
   1232         readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, mode, &actualTimeUs);
   1233 
   1234         if (mode != MediaPlayerSeekMode::SEEK_CLOSEST) {
   1235             seekTimeUs = actualTimeUs;
   1236         }
   1237         mVideoLastDequeueTimeUs = actualTimeUs;
   1238     }
   1239 
   1240     if (mAudioTrack.mSource != NULL) {
   1241         readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs);
   1242         mAudioLastDequeueTimeUs = seekTimeUs;
   1243     }
   1244 
   1245     if (mSubtitleTrack.mSource != NULL) {
   1246         mSubtitleTrack.mPackets->clear();
   1247         mFetchSubtitleDataGeneration++;
   1248     }
   1249 
   1250     if (mTimedTextTrack.mSource != NULL) {
   1251         mTimedTextTrack.mPackets->clear();
   1252         mFetchTimedTextDataGeneration++;
   1253     }
   1254 
   1255     // If currently buffering, post kWhatBufferingEnd first, so that
   1256     // NuPlayer resumes. Otherwise, if cache hits high watermark
   1257     // before new polling happens, no one will resume the playback.
   1258     mBufferingMonitor->stopBufferingIfNecessary();
   1259     mBufferingMonitor->restartPollBuffering();
   1260 
   1261     return OK;
   1262 }
   1263 
   1264 sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer(
   1265         MediaBuffer* mb,
   1266         media_track_type trackType) {
   1267     bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
   1268     size_t outLength = mb->range_length();
   1269 
   1270     if (audio && mAudioIsVorbis) {
   1271         outLength += sizeof(int32_t);
   1272     }
   1273 
   1274     sp<ABuffer> ab;
   1275 
   1276     if (mIsDrmProtected)   {
   1277         // Modular DRM
   1278         // Enabled for both video/audio so 1) media buffer is reused without extra copying
   1279         // 2) meta data can be retrieved in onInputBufferFetched for calling queueSecureInputBuffer.
   1280 
   1281         // data is already provided in the buffer
   1282         ab = new ABuffer(NULL, mb->range_length());
   1283         mb->add_ref();
   1284         ab->setMediaBufferBase(mb);
   1285 
   1286         // Modular DRM: Required b/c of the above add_ref.
   1287         // If ref>0, there must be an observer, or it'll crash at release().
   1288         // TODO: MediaBuffer might need to be revised to ease such need.
   1289         mb->setObserver(this);
   1290         // setMediaBufferBase() interestingly doesn't increment the ref count on its own.
   1291         // Extra increment (since we want to keep mb alive and attached to ab beyond this function
   1292         // call. This is to counter the effect of mb->release() towards the end.
   1293         mb->add_ref();
   1294 
   1295     } else {
   1296         ab = new ABuffer(outLength);
   1297         memcpy(ab->data(),
   1298                (const uint8_t *)mb->data() + mb->range_offset(),
   1299                mb->range_length());
   1300     }
   1301 
   1302     if (audio && mAudioIsVorbis) {
   1303         int32_t numPageSamples;
   1304         if (!mb->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) {
   1305             numPageSamples = -1;
   1306         }
   1307 
   1308         uint8_t* abEnd = ab->data() + mb->range_length();
   1309         memcpy(abEnd, &numPageSamples, sizeof(numPageSamples));
   1310     }
   1311 
   1312     sp<AMessage> meta = ab->meta();
   1313 
   1314     int64_t timeUs;
   1315     CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs));
   1316     meta->setInt64("timeUs", timeUs);
   1317 
   1318     if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
   1319         int32_t layerId;
   1320         if (mb->meta_data()->findInt32(kKeyTemporalLayerId, &layerId)) {
   1321             meta->setInt32("temporal-layer-id", layerId);
   1322         }
   1323     }
   1324 
   1325     if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
   1326         const char *mime;
   1327         CHECK(mTimedTextTrack.mSource != NULL
   1328                 && mTimedTextTrack.mSource->getFormat()->findCString(kKeyMIMEType, &mime));
   1329         meta->setString("mime", mime);
   1330     }
   1331 
   1332     int64_t durationUs;
   1333     if (mb->meta_data()->findInt64(kKeyDuration, &durationUs)) {
   1334         meta->setInt64("durationUs", durationUs);
   1335     }
   1336 
   1337     if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
   1338         meta->setInt32("trackIndex", mSubtitleTrack.mIndex);
   1339     }
   1340 
   1341     uint32_t dataType; // unused
   1342     const void *seiData;
   1343     size_t seiLength;
   1344     if (mb->meta_data()->findData(kKeySEI, &dataType, &seiData, &seiLength)) {
   1345         sp<ABuffer> sei = ABuffer::CreateAsCopy(seiData, seiLength);;
   1346         meta->setBuffer("sei", sei);
   1347     }
   1348 
   1349     const void *mpegUserDataPointer;
   1350     size_t mpegUserDataLength;
   1351     if (mb->meta_data()->findData(
   1352             kKeyMpegUserData, &dataType, &mpegUserDataPointer, &mpegUserDataLength)) {
   1353         sp<ABuffer> mpegUserData = ABuffer::CreateAsCopy(mpegUserDataPointer, mpegUserDataLength);
   1354         meta->setBuffer("mpegUserData", mpegUserData);
   1355     }
   1356 
   1357     mb->release();
   1358     mb = NULL;
   1359 
   1360     return ab;
   1361 }
   1362 
   1363 void NuPlayer::GenericSource::postReadBuffer(media_track_type trackType) {
   1364     Mutex::Autolock _l(mReadBufferLock);
   1365 
   1366     if ((mPendingReadBufferTypes & (1 << trackType)) == 0) {
   1367         mPendingReadBufferTypes |= (1 << trackType);
   1368         sp<AMessage> msg = new AMessage(kWhatReadBuffer, this);
   1369         msg->setInt32("trackType", trackType);
   1370         msg->post();
   1371     }
   1372 }
   1373 
   1374 void NuPlayer::GenericSource::onReadBuffer(const sp<AMessage>& msg) {
   1375     int32_t tmpType;
   1376     CHECK(msg->findInt32("trackType", &tmpType));
   1377     media_track_type trackType = (media_track_type)tmpType;
   1378     readBuffer(trackType);
   1379     {
   1380         // only protect the variable change, as readBuffer may
   1381         // take considerable time.
   1382         Mutex::Autolock _l(mReadBufferLock);
   1383         mPendingReadBufferTypes &= ~(1 << trackType);
   1384     }
   1385 }
   1386 
   1387 void NuPlayer::GenericSource::readBuffer(
   1388         media_track_type trackType, int64_t seekTimeUs, MediaPlayerSeekMode mode,
   1389         int64_t *actualTimeUs, bool formatChange) {
   1390     // Do not read data if Widevine source is stopped
   1391     //
   1392     // TODO: revisit after widevine is removed.  May be able to
   1393     // combine mStopRead with mStarted.
   1394     if (mStopRead) {
   1395         return;
   1396     }
   1397     Track *track;
   1398     size_t maxBuffers = 1;
   1399     switch (trackType) {
   1400         case MEDIA_TRACK_TYPE_VIDEO:
   1401             track = &mVideoTrack;
   1402             maxBuffers = 8;  // too large of a number may influence seeks
   1403             break;
   1404         case MEDIA_TRACK_TYPE_AUDIO:
   1405             track = &mAudioTrack;
   1406             maxBuffers = 64;
   1407             break;
   1408         case MEDIA_TRACK_TYPE_SUBTITLE:
   1409             track = &mSubtitleTrack;
   1410             break;
   1411         case MEDIA_TRACK_TYPE_TIMEDTEXT:
   1412             track = &mTimedTextTrack;
   1413             break;
   1414         default:
   1415             TRESPASS();
   1416     }
   1417 
   1418     if (track->mSource == NULL) {
   1419         return;
   1420     }
   1421 
   1422     if (actualTimeUs) {
   1423         *actualTimeUs = seekTimeUs;
   1424     }
   1425 
   1426     MediaSource::ReadOptions options;
   1427 
   1428     bool seeking = false;
   1429     if (seekTimeUs >= 0) {
   1430         options.setSeekTo(seekTimeUs, mode);
   1431         seeking = true;
   1432     }
   1433 
   1434     const bool couldReadMultiple = (track->mSource->supportReadMultiple());
   1435 
   1436     if (couldReadMultiple) {
   1437         options.setNonBlocking();
   1438     }
   1439 
   1440     for (size_t numBuffers = 0; numBuffers < maxBuffers; ) {
   1441         Vector<MediaBuffer *> mediaBuffers;
   1442         status_t err = NO_ERROR;
   1443 
   1444         if (couldReadMultiple) {
   1445             err = track->mSource->readMultiple(
   1446                     &mediaBuffers, maxBuffers - numBuffers, &options);
   1447         } else {
   1448             MediaBuffer *mbuf = NULL;
   1449             err = track->mSource->read(&mbuf, &options);
   1450             if (err == OK && mbuf != NULL) {
   1451                 mediaBuffers.push_back(mbuf);
   1452             }
   1453         }
   1454 
   1455         options.clearNonPersistent();
   1456 
   1457         size_t id = 0;
   1458         size_t count = mediaBuffers.size();
   1459         for (; id < count; ++id) {
   1460             int64_t timeUs;
   1461             MediaBuffer *mbuf = mediaBuffers[id];
   1462             if (!mbuf->meta_data()->findInt64(kKeyTime, &timeUs)) {
   1463                 mbuf->meta_data()->dumpToLog();
   1464                 track->mPackets->signalEOS(ERROR_MALFORMED);
   1465                 break;
   1466             }
   1467             if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
   1468                 mAudioTimeUs = timeUs;
   1469                 mBufferingMonitor->updateQueuedTime(true /* isAudio */, timeUs);
   1470             } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
   1471                 mVideoTimeUs = timeUs;
   1472                 mBufferingMonitor->updateQueuedTime(false /* isAudio */, timeUs);
   1473             }
   1474 
   1475             queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
   1476 
   1477             sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType);
   1478             if (numBuffers == 0 && actualTimeUs != nullptr) {
   1479                 *actualTimeUs = timeUs;
   1480             }
   1481             if (seeking && buffer != nullptr) {
   1482                 sp<AMessage> meta = buffer->meta();
   1483                 if (meta != nullptr && mode == MediaPlayerSeekMode::SEEK_CLOSEST
   1484                         && seekTimeUs > timeUs) {
   1485                     sp<AMessage> extra = new AMessage;
   1486                     extra->setInt64("resume-at-mediaTimeUs", seekTimeUs);
   1487                     meta->setMessage("extra", extra);
   1488                 }
   1489             }
   1490 
   1491             track->mPackets->queueAccessUnit(buffer);
   1492             formatChange = false;
   1493             seeking = false;
   1494             ++numBuffers;
   1495         }
   1496         if (id < count) {
   1497             // Error, some mediaBuffer doesn't have kKeyTime.
   1498             for (; id < count; ++id) {
   1499                 mediaBuffers[id]->release();
   1500             }
   1501             break;
   1502         }
   1503 
   1504         if (err == WOULD_BLOCK) {
   1505             break;
   1506         } else if (err == INFO_FORMAT_CHANGED) {
   1507 #if 0
   1508             track->mPackets->queueDiscontinuity(
   1509                     ATSParser::DISCONTINUITY_FORMATCHANGE,
   1510                     NULL,
   1511                     false /* discard */);
   1512 #endif
   1513         } else if (err != OK) {
   1514             queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
   1515             track->mPackets->signalEOS(err);
   1516             break;
   1517         }
   1518     }
   1519 }
   1520 
   1521 void NuPlayer::GenericSource::queueDiscontinuityIfNeeded(
   1522         bool seeking, bool formatChange, media_track_type trackType, Track *track) {
   1523     // formatChange && seeking: track whose source is changed during selection
   1524     // formatChange && !seeking: track whose source is not changed during selection
   1525     // !formatChange: normal seek
   1526     if ((seeking || formatChange)
   1527             && (trackType == MEDIA_TRACK_TYPE_AUDIO
   1528             || trackType == MEDIA_TRACK_TYPE_VIDEO)) {
   1529         ATSParser::DiscontinuityType type = (formatChange && seeking)
   1530                 ? ATSParser::DISCONTINUITY_FORMATCHANGE
   1531                 : ATSParser::DISCONTINUITY_NONE;
   1532         track->mPackets->queueDiscontinuity(type, NULL /* extra */, true /* discard */);
   1533     }
   1534 }
   1535 
   1536 NuPlayer::GenericSource::BufferingMonitor::BufferingMonitor(const sp<AMessage> &notify)
   1537     : mNotify(notify),
   1538       mDurationUs(-1ll),
   1539       mBitrate(-1ll),
   1540       mIsStreaming(false),
   1541       mAudioTimeUs(0),
   1542       mVideoTimeUs(0),
   1543       mPollBufferingGeneration(0),
   1544       mPrepareBuffering(false),
   1545       mBuffering(false),
   1546       mPrevBufferPercentage(-1),
   1547       mOffloadAudio(false),
   1548       mFirstDequeuedBufferRealUs(-1ll),
   1549       mFirstDequeuedBufferMediaUs(-1ll),
   1550       mlastDequeuedBufferMediaUs(-1ll) {
   1551       getDefaultBufferingSettings(&mSettings);
   1552 }
   1553 
   1554 NuPlayer::GenericSource::BufferingMonitor::~BufferingMonitor() {
   1555 }
   1556 
   1557 void NuPlayer::GenericSource::BufferingMonitor::getDefaultBufferingSettings(
   1558         BufferingSettings *buffering /* nonnull */) {
   1559     buffering->mInitialBufferingMode = BUFFERING_MODE_TIME_ONLY;
   1560     buffering->mRebufferingMode = BUFFERING_MODE_TIME_THEN_SIZE;
   1561     buffering->mInitialWatermarkMs = kHighWaterMarkMs;
   1562     buffering->mRebufferingWatermarkLowMs = kLowWaterMarkMs;
   1563     buffering->mRebufferingWatermarkHighMs = kHighWaterMarkRebufferMs;
   1564     buffering->mRebufferingWatermarkLowKB = kLowWaterMarkKB;
   1565     buffering->mRebufferingWatermarkHighKB = kHighWaterMarkKB;
   1566 
   1567     ALOGV("BufferingMonitor::getDefaultBufferingSettings{%s}",
   1568             buffering->toString().string());
   1569 }
   1570 
   1571 status_t NuPlayer::GenericSource::BufferingMonitor::setBufferingSettings(
   1572         const BufferingSettings &buffering) {
   1573     ALOGV("BufferingMonitor::setBufferingSettings{%s}",
   1574             buffering.toString().string());
   1575 
   1576     Mutex::Autolock _l(mLock);
   1577     if (buffering.IsSizeBasedBufferingMode(buffering.mInitialBufferingMode)
   1578             || (buffering.IsTimeBasedBufferingMode(buffering.mRebufferingMode)
   1579                 && buffering.mRebufferingWatermarkLowMs > buffering.mRebufferingWatermarkHighMs)
   1580             || (buffering.IsSizeBasedBufferingMode(buffering.mRebufferingMode)
   1581                 && buffering.mRebufferingWatermarkLowKB > buffering.mRebufferingWatermarkHighKB)) {
   1582         return BAD_VALUE;
   1583     }
   1584     mSettings = buffering;
   1585     if (mSettings.mInitialBufferingMode == BUFFERING_MODE_NONE) {
   1586         mSettings.mInitialWatermarkMs = BufferingSettings::kNoWatermark;
   1587     }
   1588     if (!mSettings.IsTimeBasedBufferingMode(mSettings.mRebufferingMode)) {
   1589         mSettings.mRebufferingWatermarkLowMs = BufferingSettings::kNoWatermark;
   1590         mSettings.mRebufferingWatermarkHighMs = INT32_MAX;
   1591     }
   1592     if (!mSettings.IsSizeBasedBufferingMode(mSettings.mRebufferingMode)) {
   1593         mSettings.mRebufferingWatermarkLowKB = BufferingSettings::kNoWatermark;
   1594         mSettings.mRebufferingWatermarkHighKB = INT32_MAX;
   1595     }
   1596     return OK;
   1597 }
   1598 
   1599 void NuPlayer::GenericSource::BufferingMonitor::prepare(
   1600         const sp<NuCachedSource2> &cachedSource,
   1601         int64_t durationUs,
   1602         int64_t bitrate,
   1603         bool isStreaming) {
   1604     Mutex::Autolock _l(mLock);
   1605     prepare_l(cachedSource, durationUs, bitrate, isStreaming);
   1606 }
   1607 
   1608 void NuPlayer::GenericSource::BufferingMonitor::stop() {
   1609     Mutex::Autolock _l(mLock);
   1610     prepare_l(NULL /* cachedSource */, -1 /* durationUs */,
   1611             -1 /* bitrate */, false /* isStreaming */);
   1612 }
   1613 
   1614 void NuPlayer::GenericSource::BufferingMonitor::cancelPollBuffering() {
   1615     Mutex::Autolock _l(mLock);
   1616     cancelPollBuffering_l();
   1617 }
   1618 
   1619 void NuPlayer::GenericSource::BufferingMonitor::restartPollBuffering() {
   1620     Mutex::Autolock _l(mLock);
   1621     if (mIsStreaming) {
   1622         cancelPollBuffering_l();
   1623         onPollBuffering_l();
   1624     }
   1625 }
   1626 
   1627 void NuPlayer::GenericSource::BufferingMonitor::stopBufferingIfNecessary() {
   1628     Mutex::Autolock _l(mLock);
   1629     stopBufferingIfNecessary_l();
   1630 }
   1631 
   1632 void NuPlayer::GenericSource::BufferingMonitor::ensureCacheIsFetching() {
   1633     Mutex::Autolock _l(mLock);
   1634     ensureCacheIsFetching_l();
   1635 }
   1636 
   1637 void NuPlayer::GenericSource::BufferingMonitor::updateQueuedTime(bool isAudio, int64_t timeUs) {
   1638     Mutex::Autolock _l(mLock);
   1639     if (isAudio) {
   1640         mAudioTimeUs = timeUs;
   1641     } else {
   1642         mVideoTimeUs = timeUs;
   1643     }
   1644 }
   1645 
   1646 void NuPlayer::GenericSource::BufferingMonitor::setOffloadAudio(bool offload) {
   1647     Mutex::Autolock _l(mLock);
   1648     mOffloadAudio = offload;
   1649 }
   1650 
   1651 void NuPlayer::GenericSource::BufferingMonitor::updateDequeuedBufferTime(int64_t mediaUs) {
   1652     Mutex::Autolock _l(mLock);
   1653     if (mediaUs < 0) {
   1654         mFirstDequeuedBufferRealUs = -1ll;
   1655         mFirstDequeuedBufferMediaUs = -1ll;
   1656     } else if (mFirstDequeuedBufferRealUs < 0) {
   1657         mFirstDequeuedBufferRealUs = ALooper::GetNowUs();
   1658         mFirstDequeuedBufferMediaUs = mediaUs;
   1659     }
   1660     mlastDequeuedBufferMediaUs = mediaUs;
   1661 }
   1662 
   1663 void NuPlayer::GenericSource::BufferingMonitor::prepare_l(
   1664         const sp<NuCachedSource2> &cachedSource,
   1665         int64_t durationUs,
   1666         int64_t bitrate,
   1667         bool isStreaming) {
   1668 
   1669     mCachedSource = cachedSource;
   1670     mDurationUs = durationUs;
   1671     mBitrate = bitrate;
   1672     mIsStreaming = isStreaming;
   1673     mAudioTimeUs = 0;
   1674     mVideoTimeUs = 0;
   1675     mPrepareBuffering = (cachedSource != NULL);
   1676     cancelPollBuffering_l();
   1677     mOffloadAudio = false;
   1678     mFirstDequeuedBufferRealUs = -1ll;
   1679     mFirstDequeuedBufferMediaUs = -1ll;
   1680     mlastDequeuedBufferMediaUs = -1ll;
   1681 }
   1682 
   1683 void NuPlayer::GenericSource::BufferingMonitor::cancelPollBuffering_l() {
   1684     mBuffering = false;
   1685     ++mPollBufferingGeneration;
   1686     mPrevBufferPercentage = -1;
   1687 }
   1688 
   1689 void NuPlayer::GenericSource::BufferingMonitor::notifyBufferingUpdate_l(int32_t percentage) {
   1690     // Buffering percent could go backward as it's estimated from remaining
   1691     // data and last access time. This could cause the buffering position
   1692     // drawn on media control to jitter slightly. Remember previously reported
   1693     // percentage and don't allow it to go backward.
   1694     if (percentage < mPrevBufferPercentage) {
   1695         percentage = mPrevBufferPercentage;
   1696     } else if (percentage > 100) {
   1697         percentage = 100;
   1698     }
   1699 
   1700     mPrevBufferPercentage = percentage;
   1701 
   1702     ALOGV("notifyBufferingUpdate_l: buffering %d%%", percentage);
   1703 
   1704     sp<AMessage> msg = mNotify->dup();
   1705     msg->setInt32("what", kWhatBufferingUpdate);
   1706     msg->setInt32("percentage", percentage);
   1707     msg->post();
   1708 }
   1709 
   1710 void NuPlayer::GenericSource::BufferingMonitor::startBufferingIfNecessary_l() {
   1711     if (mPrepareBuffering) {
   1712         return;
   1713     }
   1714 
   1715     if (!mBuffering) {
   1716         ALOGD("startBufferingIfNecessary_l");
   1717 
   1718         mBuffering = true;
   1719 
   1720         ensureCacheIsFetching_l();
   1721         sendCacheStats_l();
   1722 
   1723         sp<AMessage> notify = mNotify->dup();
   1724         notify->setInt32("what", kWhatPauseOnBufferingStart);
   1725         notify->post();
   1726     }
   1727 }
   1728 
   1729 void NuPlayer::GenericSource::BufferingMonitor::stopBufferingIfNecessary_l() {
   1730     if (mPrepareBuffering) {
   1731         ALOGD("stopBufferingIfNecessary_l, mBuffering=%d", mBuffering);
   1732 
   1733         mPrepareBuffering = false;
   1734 
   1735         sp<AMessage> notify = mNotify->dup();
   1736         notify->setInt32("what", kWhatPrepared);
   1737         notify->setInt32("err", OK);
   1738         notify->post();
   1739 
   1740         return;
   1741     }
   1742 
   1743     if (mBuffering) {
   1744         ALOGD("stopBufferingIfNecessary_l");
   1745         mBuffering = false;
   1746 
   1747         sendCacheStats_l();
   1748 
   1749         sp<AMessage> notify = mNotify->dup();
   1750         notify->setInt32("what", kWhatResumeOnBufferingEnd);
   1751         notify->post();
   1752     }
   1753 }
   1754 
   1755 void NuPlayer::GenericSource::BufferingMonitor::sendCacheStats_l() {
   1756     int32_t kbps = 0;
   1757     status_t err = UNKNOWN_ERROR;
   1758 
   1759     if (mCachedSource != NULL) {
   1760         err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
   1761     }
   1762 
   1763     if (err == OK) {
   1764         sp<AMessage> notify = mNotify->dup();
   1765         notify->setInt32("what", kWhatCacheStats);
   1766         notify->setInt32("bandwidth", kbps);
   1767         notify->post();
   1768     }
   1769 }
   1770 
   1771 void NuPlayer::GenericSource::BufferingMonitor::ensureCacheIsFetching_l() {
   1772     if (mCachedSource != NULL) {
   1773         mCachedSource->resumeFetchingIfNecessary();
   1774     }
   1775 }
   1776 
   1777 void NuPlayer::GenericSource::BufferingMonitor::schedulePollBuffering_l() {
   1778     sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
   1779     msg->setInt32("generation", mPollBufferingGeneration);
   1780     // Enquires buffering status every second.
   1781     msg->post(1000000ll);
   1782 }
   1783 
   1784 int64_t NuPlayer::GenericSource::BufferingMonitor::getLastReadPosition_l() {
   1785     if (mAudioTimeUs > 0) {
   1786         return mAudioTimeUs;
   1787     } else if (mVideoTimeUs > 0) {
   1788         return mVideoTimeUs;
   1789     } else {
   1790         return 0;
   1791     }
   1792 }
   1793 
   1794 void NuPlayer::GenericSource::BufferingMonitor::onPollBuffering_l() {
   1795     status_t finalStatus = UNKNOWN_ERROR;
   1796     int64_t cachedDurationUs = -1ll;
   1797     ssize_t cachedDataRemaining = -1;
   1798 
   1799     if (mCachedSource != NULL) {
   1800         cachedDataRemaining =
   1801                 mCachedSource->approxDataRemaining(&finalStatus);
   1802 
   1803         if (finalStatus == OK) {
   1804             off64_t size;
   1805             int64_t bitrate = 0ll;
   1806             if (mDurationUs > 0 && mCachedSource->getSize(&size) == OK) {
   1807                 // |bitrate| uses bits/second unit, while size is number of bytes.
   1808                 bitrate = size * 8000000ll / mDurationUs;
   1809             } else if (mBitrate > 0) {
   1810                 bitrate = mBitrate;
   1811             }
   1812             if (bitrate > 0) {
   1813                 cachedDurationUs = cachedDataRemaining * 8000000ll / bitrate;
   1814             }
   1815         }
   1816     }
   1817 
   1818     if (finalStatus != OK) {
   1819         ALOGV("onPollBuffering_l: EOS (finalStatus = %d)", finalStatus);
   1820 
   1821         if (finalStatus == ERROR_END_OF_STREAM) {
   1822             notifyBufferingUpdate_l(100);
   1823         }
   1824 
   1825         stopBufferingIfNecessary_l();
   1826         return;
   1827     }
   1828 
   1829     if (cachedDurationUs >= 0ll) {
   1830         if (mDurationUs > 0ll) {
   1831             int64_t cachedPosUs = getLastReadPosition_l() + cachedDurationUs;
   1832             int percentage = 100.0 * cachedPosUs / mDurationUs;
   1833             if (percentage > 100) {
   1834                 percentage = 100;
   1835             }
   1836 
   1837             notifyBufferingUpdate_l(percentage);
   1838         }
   1839 
   1840         ALOGV("onPollBuffering_l: cachedDurationUs %.1f sec", cachedDurationUs / 1000000.0f);
   1841 
   1842         if (mPrepareBuffering) {
   1843             if (cachedDurationUs > mSettings.mInitialWatermarkMs * 1000) {
   1844                 stopBufferingIfNecessary_l();
   1845             }
   1846         } else if (mSettings.IsTimeBasedBufferingMode(mSettings.mRebufferingMode)) {
   1847             if (cachedDurationUs < mSettings.mRebufferingWatermarkLowMs * 1000) {
   1848                 // Take into account the data cached in downstream components to try to avoid
   1849                 // unnecessary pause.
   1850                 if (mOffloadAudio && mFirstDequeuedBufferRealUs >= 0) {
   1851                     int64_t downStreamCacheUs =
   1852                         mlastDequeuedBufferMediaUs - mFirstDequeuedBufferMediaUs
   1853                             - (ALooper::GetNowUs() - mFirstDequeuedBufferRealUs);
   1854                     if (downStreamCacheUs > 0) {
   1855                         cachedDurationUs += downStreamCacheUs;
   1856                     }
   1857                 }
   1858 
   1859                 if (cachedDurationUs < mSettings.mRebufferingWatermarkLowMs * 1000) {
   1860                     startBufferingIfNecessary_l();
   1861                 }
   1862             } else if (cachedDurationUs > mSettings.mRebufferingWatermarkHighMs * 1000) {
   1863                 stopBufferingIfNecessary_l();
   1864             }
   1865         }
   1866     } else if (cachedDataRemaining >= 0
   1867             && mSettings.IsSizeBasedBufferingMode(mSettings.mRebufferingMode)) {
   1868         ALOGV("onPollBuffering_l: cachedDataRemaining %zd bytes",
   1869                 cachedDataRemaining);
   1870 
   1871         if (cachedDataRemaining < (mSettings.mRebufferingWatermarkLowKB << 10)) {
   1872             startBufferingIfNecessary_l();
   1873         } else if (cachedDataRemaining > (mSettings.mRebufferingWatermarkHighKB << 10)) {
   1874             stopBufferingIfNecessary_l();
   1875         }
   1876     }
   1877 
   1878     schedulePollBuffering_l();
   1879 }
   1880 
   1881 void NuPlayer::GenericSource::BufferingMonitor::onMessageReceived(const sp<AMessage> &msg) {
   1882     switch (msg->what()) {
   1883       case kWhatPollBuffering:
   1884       {
   1885           int32_t generation;
   1886           CHECK(msg->findInt32("generation", &generation));
   1887           Mutex::Autolock _l(mLock);
   1888           if (generation == mPollBufferingGeneration) {
   1889               onPollBuffering_l();
   1890           }
   1891           break;
   1892       }
   1893       default:
   1894           TRESPASS();
   1895           break;
   1896     }
   1897 }
   1898 
   1899 // Modular DRM
   1900 status_t NuPlayer::GenericSource::prepareDrm(
   1901         const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId, sp<ICrypto> *crypto)
   1902 {
   1903     ALOGV("prepareDrm");
   1904 
   1905     sp<AMessage> msg = new AMessage(kWhatPrepareDrm, this);
   1906     // synchronous call so just passing the address but with local copies of "const" args
   1907     uint8_t UUID[16];
   1908     memcpy(UUID, uuid, sizeof(UUID));
   1909     Vector<uint8_t> sessionId = drmSessionId;
   1910     msg->setPointer("uuid", (void*)UUID);
   1911     msg->setPointer("drmSessionId", (void*)&sessionId);
   1912     msg->setPointer("crypto", (void*)crypto);
   1913 
   1914     sp<AMessage> response;
   1915     status_t status = msg->postAndAwaitResponse(&response);
   1916 
   1917     if (status == OK && response != NULL) {
   1918         CHECK(response->findInt32("status", &status));
   1919         ALOGV_IF(status == OK, "prepareDrm: mCrypto: %p (%d)", crypto->get(),
   1920                 (*crypto != NULL ? (*crypto)->getStrongCount() : 0));
   1921         ALOGD("prepareDrm ret: %d ", status);
   1922     } else {
   1923         ALOGE("prepareDrm err: %d", status);
   1924     }
   1925 
   1926     return status;
   1927 }
   1928 
   1929 status_t NuPlayer::GenericSource::releaseDrm()
   1930 {
   1931     ALOGV("releaseDrm");
   1932 
   1933     sp<AMessage> msg = new AMessage(kWhatReleaseDrm, this);
   1934 
   1935     // synchronous call to update the source states before the player proceedes with crypto cleanup
   1936     sp<AMessage> response;
   1937     status_t status = msg->postAndAwaitResponse(&response);
   1938 
   1939     if (status == OK && response != NULL) {
   1940         ALOGD("releaseDrm ret: OK ");
   1941     } else {
   1942         ALOGE("releaseDrm err: %d", status);
   1943     }
   1944 
   1945     return status;
   1946 }
   1947 
   1948 status_t NuPlayer::GenericSource::onPrepareDrm(const sp<AMessage> &msg)
   1949 {
   1950     ALOGV("onPrepareDrm ");
   1951 
   1952     mIsDrmProtected = false;
   1953     mIsDrmReleased = false;
   1954     mIsSecure = false;
   1955 
   1956     uint8_t *uuid;
   1957     Vector<uint8_t> *drmSessionId;
   1958     sp<ICrypto> *outCrypto;
   1959     CHECK(msg->findPointer("uuid", (void**)&uuid));
   1960     CHECK(msg->findPointer("drmSessionId", (void**)&drmSessionId));
   1961     CHECK(msg->findPointer("crypto", (void**)&outCrypto));
   1962 
   1963     status_t status = OK;
   1964     sp<ICrypto> crypto = NuPlayerDrm::createCryptoAndPlugin(uuid, *drmSessionId, status);
   1965     if (crypto == NULL) {
   1966         ALOGE("onPrepareDrm: createCrypto failed. status: %d", status);
   1967         return status;
   1968     }
   1969     ALOGV("onPrepareDrm: createCryptoAndPlugin succeeded for uuid: %s",
   1970             DrmUUID::toHexString(uuid).string());
   1971 
   1972     *outCrypto = crypto;
   1973     // as long a there is an active crypto
   1974     mIsDrmProtected = true;
   1975 
   1976     if (mMimes.size() == 0) {
   1977         status = UNKNOWN_ERROR;
   1978         ALOGE("onPrepareDrm: Unexpected. Must have at least one track. status: %d", status);
   1979         return status;
   1980     }
   1981 
   1982     // first mime in this list is either the video track, or the first audio track
   1983     const char *mime = mMimes[0].string();
   1984     mIsSecure = crypto->requiresSecureDecoderComponent(mime);
   1985     ALOGV("onPrepareDrm: requiresSecureDecoderComponent mime: %s  isSecure: %d",
   1986             mime, mIsSecure);
   1987 
   1988     // Checking the member flags while in the looper to send out the notification.
   1989     // The legacy mDecryptHandle!=NULL check (for FLAG_PROTECTED) is equivalent to mIsDrmProtected.
   1990     notifyFlagsChanged(
   1991             (mIsSecure ? FLAG_SECURE : 0) |
   1992             // Setting "protected screen" only for L1: b/38390836
   1993             (mIsSecure ? FLAG_PROTECTED : 0) |
   1994             FLAG_CAN_PAUSE |
   1995             FLAG_CAN_SEEK_BACKWARD |
   1996             FLAG_CAN_SEEK_FORWARD |
   1997             FLAG_CAN_SEEK);
   1998 
   1999     return status;
   2000 }
   2001 
   2002 status_t NuPlayer::GenericSource::onReleaseDrm()
   2003 {
   2004     if (mIsDrmProtected) {
   2005         mIsDrmProtected = false;
   2006         // to prevent returning any more buffer after stop/releaseDrm (b/37960096)
   2007         mIsDrmReleased = true;
   2008         ALOGV("onReleaseDrm: mIsDrmProtected is reset.");
   2009     } else {
   2010         ALOGE("onReleaseDrm: mIsDrmProtected is already false.");
   2011     }
   2012 
   2013     return OK;
   2014 }
   2015 
   2016 status_t NuPlayer::GenericSource::checkDrmInfo()
   2017 {
   2018     // clearing the flag at prepare in case the player is reused after stop/releaseDrm with the
   2019     // same source without being reset (called by prepareAsync/initFromDataSource)
   2020     mIsDrmReleased = false;
   2021 
   2022     if (mFileMeta == NULL) {
   2023         ALOGI("checkDrmInfo: No metadata");
   2024         return OK; // letting the caller responds accordingly
   2025     }
   2026 
   2027     uint32_t type;
   2028     const void *pssh;
   2029     size_t psshsize;
   2030 
   2031     if (!mFileMeta->findData(kKeyPssh, &type, &pssh, &psshsize)) {
   2032         ALOGV("checkDrmInfo: No PSSH");
   2033         return OK; // source without DRM info
   2034     }
   2035 
   2036     Parcel parcel;
   2037     NuPlayerDrm::retrieveDrmInfo(pssh, psshsize, &parcel);
   2038     ALOGV("checkDrmInfo: MEDIA_DRM_INFO PSSH size: %d  Parcel size: %d  objects#: %d",
   2039           (int)psshsize, (int)parcel.dataSize(), (int)parcel.objectsCount());
   2040 
   2041     if (parcel.dataSize() == 0) {
   2042         ALOGE("checkDrmInfo: Unexpected parcel size: 0");
   2043         return UNKNOWN_ERROR;
   2044     }
   2045 
   2046     // Can't pass parcel as a message to the player. Converting Parcel->ABuffer to pass it
   2047     // to the Player's onSourceNotify then back to Parcel for calling driver's notifyListener.
   2048     sp<ABuffer> drmInfoBuffer = ABuffer::CreateAsCopy(parcel.data(), parcel.dataSize());
   2049     notifyDrmInfo(drmInfoBuffer);
   2050 
   2051     return OK;
   2052 }
   2053 
   2054 void NuPlayer::GenericSource::signalBufferReturned(MediaBuffer *buffer)
   2055 {
   2056     //ALOGV("signalBufferReturned %p  refCount: %d", buffer, buffer->localRefcount());
   2057 
   2058     buffer->setObserver(NULL);
   2059     buffer->release(); // this leads to delete since that there is no observor
   2060 }
   2061 
   2062 }  // namespace android
   2063