Home | History | Annotate | Download | only in nuplayer2
      1 /*
      2  * Copyright 2017 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 "GenericSource2"
     19 
     20 #include "GenericSource2.h"
     21 #include "NuPlayer2Drm.h"
     22 
     23 #include "AnotherPacketSource.h"
     24 #include <binder/IServiceManager.h>
     25 #include <cutils/properties.h>
     26 #include <media/DataSource.h>
     27 #include <media/MediaBufferHolder.h>
     28 #include <media/IMediaExtractorService.h>
     29 #include <media/IMediaSource.h>
     30 #include <media/MediaHTTPService.h>
     31 #include <media/MediaExtractor.h>
     32 #include <media/MediaSource.h>
     33 #include <media/NdkWrapper.h>
     34 #include <media/stagefright/foundation/ABuffer.h>
     35 #include <media/stagefright/foundation/ADebug.h>
     36 #include <media/stagefright/foundation/AMessage.h>
     37 #include <media/stagefright/DataSourceFactory.h>
     38 #include <media/stagefright/InterfaceUtils.h>
     39 #include <media/stagefright/MediaBuffer.h>
     40 #include <media/stagefright/MediaClock.h>
     41 #include <media/stagefright/MediaDefs.h>
     42 #include <media/stagefright/MediaExtractorFactory.h>
     43 #include <media/stagefright/MetaData.h>
     44 #include <media/stagefright/NdkUtils.h>
     45 #include <media/stagefright/Utils.h>
     46 #include "../../libstagefright/include/NuCachedSource2.h"
     47 #include "../../libstagefright/include/HTTPBase.h"
     48 
     49 namespace android {
     50 
     51 static const int kInitialMarkMs        = 5000;  // 5secs
     52 
     53 //static const int kPausePlaybackMarkMs  = 2000;  // 2secs
     54 static const int kResumePlaybackMarkMs = 15000;  // 15secs
     55 
     56 NuPlayer2::GenericSource2::GenericSource2(
     57         const sp<AMessage> &notify,
     58         uid_t uid,
     59         const sp<MediaClock> &mediaClock)
     60     : Source(notify),
     61       mAudioTimeUs(0),
     62       mAudioLastDequeueTimeUs(0),
     63       mVideoTimeUs(0),
     64       mVideoLastDequeueTimeUs(0),
     65       mPrevBufferPercentage(-1),
     66       mPollBufferingGeneration(0),
     67       mSentPauseOnBuffering(false),
     68       mAudioDataGeneration(0),
     69       mVideoDataGeneration(0),
     70       mFetchSubtitleDataGeneration(0),
     71       mFetchTimedTextDataGeneration(0),
     72       mDurationUs(-1ll),
     73       mAudioIsVorbis(false),
     74       mIsSecure(false),
     75       mIsStreaming(false),
     76       mUID(uid),
     77       mMediaClock(mediaClock),
     78       mFd(-1),
     79       mBitrate(-1ll),
     80       mPendingReadBufferTypes(0) {
     81     ALOGV("GenericSource2");
     82     CHECK(mediaClock != NULL);
     83 
     84     mBufferingSettings.mInitialMarkMs = kInitialMarkMs;
     85     mBufferingSettings.mResumePlaybackMarkMs = kResumePlaybackMarkMs;
     86     resetDataSource();
     87 }
     88 
     89 void NuPlayer2::GenericSource2::resetDataSource() {
     90     ALOGV("resetDataSource");
     91 
     92     mHTTPService.clear();
     93     mHttpSource.clear();
     94     mDisconnected = false;
     95     mUri.clear();
     96     mUriHeaders.clear();
     97     if (mFd >= 0) {
     98         close(mFd);
     99         mFd = -1;
    100     }
    101     mOffset = 0;
    102     mLength = 0;
    103     mStarted = false;
    104     mPreparing = false;
    105 
    106     mIsDrmProtected = false;
    107     mIsDrmReleased = false;
    108     mIsSecure = false;
    109     mMimes.clear();
    110 }
    111 
    112 status_t NuPlayer2::GenericSource2::setDataSource(
    113         const sp<MediaHTTPService> &httpService,
    114         const char *url,
    115         const KeyedVector<String8, String8> *headers) {
    116     Mutex::Autolock _l(mLock);
    117     ALOGV("setDataSource url: %s", url);
    118 
    119     resetDataSource();
    120 
    121     mHTTPService = httpService;
    122     mUri = url;
    123 
    124     if (headers) {
    125         mUriHeaders = *headers;
    126     }
    127 
    128     // delay data source creation to prepareAsync() to avoid blocking
    129     // the calling thread in setDataSource for any significant time.
    130     return OK;
    131 }
    132 
    133 status_t NuPlayer2::GenericSource2::setDataSource(
    134         int fd, int64_t offset, int64_t length) {
    135     Mutex::Autolock _l(mLock);
    136     ALOGV("setDataSource %d/%lld/%lld", fd, (long long)offset, (long long)length);
    137 
    138     resetDataSource();
    139 
    140     mFd = dup(fd);
    141     mOffset = offset;
    142     mLength = length;
    143 
    144     // delay data source creation to prepareAsync() to avoid blocking
    145     // the calling thread in setDataSource for any significant time.
    146     return OK;
    147 }
    148 
    149 status_t NuPlayer2::GenericSource2::setDataSource(const sp<DataSource>& source) {
    150     Mutex::Autolock _l(mLock);
    151     ALOGV("setDataSource (source: %p)", source.get());
    152 
    153     resetDataSource();
    154     mDataSource = source;
    155     return OK;
    156 }
    157 
    158 sp<MetaData> NuPlayer2::GenericSource2::getFileFormatMeta() const {
    159     Mutex::Autolock _l(mLock);
    160     return mFileMeta;
    161 }
    162 
    163 status_t NuPlayer2::GenericSource2::initFromDataSource() {
    164     mExtractor = new AMediaExtractorWrapper(AMediaExtractor_new());
    165     CHECK(mDataSource != NULL || mFd != -1);
    166     sp<DataSource> dataSource = mDataSource;
    167     const int fd = mFd;
    168     const int64_t offset = mOffset;
    169     const int64_t length = mLength;
    170 
    171     mLock.unlock();
    172     // This might take long time if data source is not reliable.
    173     status_t err;
    174     if (dataSource != nullptr) {
    175         mDataSourceWrapper = new AMediaDataSourceWrapper(dataSource);
    176         err = mExtractor->setDataSource(mDataSourceWrapper->getAMediaDataSource());
    177     } else {
    178         err = mExtractor->setDataSource(fd, offset, length);
    179     }
    180 
    181     if (err != OK) {
    182         ALOGE("initFromDataSource, failed to create data source!");
    183         mLock.lock();
    184         return UNKNOWN_ERROR;
    185     }
    186 
    187     size_t numtracks = mExtractor->getTrackCount();
    188     if (numtracks == 0) {
    189         ALOGE("initFromDataSource, source has no track!");
    190         mLock.lock();
    191         return UNKNOWN_ERROR;
    192     }
    193 
    194     mLock.lock();
    195     mFd = -1;
    196     mDataSource = dataSource;
    197     mFileMeta = convertMediaFormatWrapperToMetaData(mExtractor->getFormat());
    198     if (mFileMeta != NULL) {
    199         int64_t duration;
    200         if (mFileMeta->findInt64(kKeyDuration, &duration)) {
    201             mDurationUs = duration;
    202         }
    203     }
    204 
    205     int32_t totalBitrate = 0;
    206 
    207     mMimes.clear();
    208 
    209     for (size_t i = 0; i < numtracks; ++i) {
    210 
    211         sp<AMediaFormatWrapper> trackFormat = mExtractor->getTrackFormat(i);
    212         if (trackFormat == NULL) {
    213             ALOGE("no metadata for track %zu", i);
    214             return UNKNOWN_ERROR;
    215         }
    216 
    217         sp<AMediaExtractorWrapper> trackExtractor = new AMediaExtractorWrapper(AMediaExtractor_new());
    218         if (mDataSourceWrapper != nullptr) {
    219             err = trackExtractor->setDataSource(mDataSourceWrapper->getAMediaDataSource());
    220         } else {
    221             err = trackExtractor->setDataSource(fd, offset, length);
    222         }
    223 
    224         const char *mime;
    225         sp<MetaData> meta = convertMediaFormatWrapperToMetaData(trackFormat);
    226         CHECK(meta->findCString(kKeyMIMEType, &mime));
    227 
    228         ALOGV("initFromDataSource track[%zu]: %s", i, mime);
    229 
    230         // Do the string compare immediately with "mime",
    231         // we can't assume "mime" would stay valid after another
    232         // extractor operation, some extractors might modify meta
    233         // during getTrack() and make it invalid.
    234         if (!strncasecmp(mime, "audio/", 6)) {
    235             if (mAudioTrack.mExtractor == NULL) {
    236                 mAudioTrack.mIndex = i;
    237                 mAudioTrack.mExtractor = trackExtractor;
    238                 mAudioTrack.mExtractor->selectTrack(i);
    239                 mAudioTrack.mPackets = new AnotherPacketSource(meta);
    240 
    241                 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
    242                     mAudioIsVorbis = true;
    243                 } else {
    244                     mAudioIsVorbis = false;
    245                 }
    246 
    247                 mMimes.add(String8(mime));
    248             }
    249         } else if (!strncasecmp(mime, "video/", 6)) {
    250             if (mVideoTrack.mExtractor == NULL) {
    251                 mVideoTrack.mIndex = i;
    252                 mVideoTrack.mExtractor = trackExtractor;
    253                 mVideoTrack.mExtractor->selectTrack(i);
    254                 mVideoTrack.mPackets = new AnotherPacketSource(meta);
    255 
    256                 // video always at the beginning
    257                 mMimes.insertAt(String8(mime), 0);
    258             }
    259         }
    260 
    261         mExtractors.push(trackExtractor);
    262         int64_t durationUs;
    263         if (meta->findInt64(kKeyDuration, &durationUs)) {
    264             if (durationUs > mDurationUs) {
    265                 mDurationUs = durationUs;
    266             }
    267         }
    268 
    269         int32_t bitrate;
    270         if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) {
    271             totalBitrate += bitrate;
    272         } else {
    273             totalBitrate = -1;
    274         }
    275     }
    276 
    277     ALOGV("initFromDataSource mExtractors.size(): %zu  mIsSecure: %d  mime[0]: %s", mExtractors.size(),
    278             mIsSecure, (mMimes.isEmpty() ? "NONE" : mMimes[0].string()));
    279 
    280     if (mExtractors.size() == 0) {
    281         ALOGE("b/23705695");
    282         return UNKNOWN_ERROR;
    283     }
    284 
    285     // Modular DRM: The return value doesn't affect source initialization.
    286     (void)checkDrmInfo();
    287 
    288     mBitrate = totalBitrate;
    289 
    290     return OK;
    291 }
    292 
    293 status_t NuPlayer2::GenericSource2::getBufferingSettings(
    294         BufferingSettings* buffering /* nonnull */) {
    295     {
    296         Mutex::Autolock _l(mLock);
    297         *buffering = mBufferingSettings;
    298     }
    299 
    300     ALOGV("getBufferingSettings{%s}", buffering->toString().string());
    301     return OK;
    302 }
    303 
    304 status_t NuPlayer2::GenericSource2::setBufferingSettings(const BufferingSettings& buffering) {
    305     ALOGV("setBufferingSettings{%s}", buffering.toString().string());
    306 
    307     Mutex::Autolock _l(mLock);
    308     mBufferingSettings = buffering;
    309     return OK;
    310 }
    311 
    312 int64_t NuPlayer2::GenericSource2::getLastReadPosition() {
    313     if (mAudioTrack.mExtractor != NULL) {
    314         return mAudioTimeUs;
    315     } else if (mVideoTrack.mExtractor != NULL) {
    316         return mVideoTimeUs;
    317     } else {
    318         return 0;
    319     }
    320 }
    321 
    322 bool NuPlayer2::GenericSource2::isStreaming() const {
    323     Mutex::Autolock _l(mLock);
    324     return mIsStreaming;
    325 }
    326 
    327 NuPlayer2::GenericSource2::~GenericSource2() {
    328     ALOGV("~GenericSource2");
    329     if (mLooper != NULL) {
    330         mLooper->unregisterHandler(id());
    331         mLooper->stop();
    332     }
    333     if (mDataSource != NULL) {
    334         mDataSource->close();
    335     }
    336     resetDataSource();
    337 }
    338 
    339 void NuPlayer2::GenericSource2::prepareAsync() {
    340     Mutex::Autolock _l(mLock);
    341     ALOGV("prepareAsync: (looper: %d)", (mLooper != NULL));
    342 
    343     if (mLooper == NULL) {
    344         mLooper = new ALooper;
    345         mLooper->setName("generic");
    346         mLooper->start(false, /* runOnCallingThread */
    347                        true,  /* canCallJava */
    348                        PRIORITY_DEFAULT);
    349 
    350         mLooper->registerHandler(this);
    351     }
    352 
    353     sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this);
    354     msg->post();
    355 }
    356 
    357 void NuPlayer2::GenericSource2::onPrepareAsync() {
    358     ALOGV("onPrepareAsync: mDataSource: %d", (mDataSource != NULL));
    359 
    360     // delayed data source creation
    361     if (mDataSource == NULL) {
    362         // set to false first, if the extractor
    363         // comes back as secure, set it to true then.
    364         mIsSecure = false;
    365 
    366         if (!mUri.empty()) {
    367             const char* uri = mUri.c_str();
    368             String8 contentType;
    369 
    370             if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
    371                 mHttpSource = DataSourceFactory::CreateMediaHTTP(mHTTPService);
    372                 if (mHttpSource == NULL) {
    373                     ALOGE("Failed to create http source!");
    374                     notifyPreparedAndCleanup(UNKNOWN_ERROR);
    375                     return;
    376                 }
    377             }
    378 
    379             mLock.unlock();
    380             // This might take long time if connection has some issue.
    381             sp<DataSource> dataSource = DataSourceFactory::CreateFromURI(
    382                    mHTTPService, uri, &mUriHeaders, &contentType,
    383                    static_cast<HTTPBase *>(mHttpSource.get()));
    384             mLock.lock();
    385             if (!mDisconnected) {
    386                 mDataSource = dataSource;
    387             }
    388         }
    389 
    390         if (mFd == -1 && mDataSource == NULL) {
    391             ALOGE("Failed to create data source!");
    392             notifyPreparedAndCleanup(UNKNOWN_ERROR);
    393             return;
    394         }
    395     }
    396 
    397     if (mDataSource != nullptr && mDataSource->flags() & DataSource::kIsCachingDataSource) {
    398         mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
    399     }
    400 
    401     // For cached streaming cases, we need to wait for enough
    402     // buffering before reporting prepared.
    403     mIsStreaming = (mCachedSource != NULL);
    404 
    405     // init extractor from data source
    406     status_t err = initFromDataSource();
    407 
    408     if (err != OK) {
    409         ALOGE("Failed to init from data source!");
    410         notifyPreparedAndCleanup(err);
    411         return;
    412     }
    413 
    414     if (mVideoTrack.mExtractor != NULL) {
    415         sp<MetaData> meta = getFormatMeta_l(false /* audio */);
    416         sp<AMessage> msg = new AMessage;
    417         err = convertMetaDataToMessage(meta, &msg);
    418         if(err != OK) {
    419             notifyPreparedAndCleanup(err);
    420             return;
    421         }
    422         notifyVideoSizeChanged(msg);
    423     }
    424 
    425     notifyFlagsChanged(
    426             // FLAG_SECURE will be known if/when prepareDrm is called by the app
    427             // FLAG_PROTECTED will be known if/when prepareDrm is called by the app
    428             FLAG_CAN_PAUSE |
    429             FLAG_CAN_SEEK_BACKWARD |
    430             FLAG_CAN_SEEK_FORWARD |
    431             FLAG_CAN_SEEK);
    432 
    433     finishPrepareAsync();
    434 
    435     ALOGV("onPrepareAsync: Done");
    436 }
    437 
    438 void NuPlayer2::GenericSource2::finishPrepareAsync() {
    439     ALOGV("finishPrepareAsync");
    440 
    441     if (mIsStreaming) {
    442         mCachedSource->resumeFetchingIfNecessary();
    443         mPreparing = true;
    444         schedulePollBuffering();
    445     } else {
    446         notifyPrepared();
    447     }
    448 
    449     if (mAudioTrack.mExtractor != NULL) {
    450         postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
    451     }
    452 
    453     if (mVideoTrack.mExtractor != NULL) {
    454         postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
    455     }
    456 }
    457 
    458 void NuPlayer2::GenericSource2::notifyPreparedAndCleanup(status_t err) {
    459     if (err != OK) {
    460         mDataSource.clear();
    461         mCachedSource.clear();
    462         mHttpSource.clear();
    463 
    464         mBitrate = -1;
    465         mPrevBufferPercentage = -1;
    466         ++mPollBufferingGeneration;
    467     }
    468     notifyPrepared(err);
    469 }
    470 
    471 void NuPlayer2::GenericSource2::start() {
    472     Mutex::Autolock _l(mLock);
    473     ALOGI("start");
    474 
    475     if (mAudioTrack.mExtractor != NULL) {
    476         postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
    477     }
    478 
    479     if (mVideoTrack.mExtractor != NULL) {
    480         postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
    481     }
    482 
    483     mStarted = true;
    484 }
    485 
    486 void NuPlayer2::GenericSource2::stop() {
    487     Mutex::Autolock _l(mLock);
    488     mStarted = false;
    489 }
    490 
    491 void NuPlayer2::GenericSource2::pause() {
    492     Mutex::Autolock _l(mLock);
    493     mStarted = false;
    494 }
    495 
    496 void NuPlayer2::GenericSource2::resume() {
    497     Mutex::Autolock _l(mLock);
    498     mStarted = true;
    499 }
    500 
    501 void NuPlayer2::GenericSource2::disconnect() {
    502     sp<DataSource> dataSource, httpSource;
    503     {
    504         Mutex::Autolock _l(mLock);
    505         dataSource = mDataSource;
    506         httpSource = mHttpSource;
    507         mDisconnected = true;
    508     }
    509 
    510     if (dataSource != NULL) {
    511         // disconnect data source
    512         if (dataSource->flags() & DataSource::kIsCachingDataSource) {
    513             static_cast<NuCachedSource2 *>(dataSource.get())->disconnect();
    514         }
    515     } else if (httpSource != NULL) {
    516         static_cast<HTTPBase *>(httpSource.get())->disconnect();
    517     }
    518 
    519     mDataSourceWrapper = NULL;
    520 
    521 }
    522 
    523 status_t NuPlayer2::GenericSource2::feedMoreTSData() {
    524     return OK;
    525 }
    526 
    527 void NuPlayer2::GenericSource2::sendCacheStats() {
    528     int32_t kbps = 0;
    529     status_t err = UNKNOWN_ERROR;
    530 
    531     if (mCachedSource != NULL) {
    532         err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
    533     }
    534 
    535     if (err == OK) {
    536         sp<AMessage> notify = dupNotify();
    537         notify->setInt32("what", kWhatCacheStats);
    538         notify->setInt32("bandwidth", kbps);
    539         notify->post();
    540     }
    541 }
    542 
    543 void NuPlayer2::GenericSource2::onMessageReceived(const sp<AMessage> &msg) {
    544     Mutex::Autolock _l(mLock);
    545     switch (msg->what()) {
    546       case kWhatPrepareAsync:
    547       {
    548           onPrepareAsync();
    549           break;
    550       }
    551       case kWhatFetchSubtitleData:
    552       {
    553           fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
    554                   mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
    555           break;
    556       }
    557 
    558       case kWhatFetchTimedTextData:
    559       {
    560           fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
    561                   mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
    562           break;
    563       }
    564 
    565       case kWhatSendSubtitleData:
    566       {
    567           sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
    568                   mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
    569           break;
    570       }
    571 
    572       case kWhatSendGlobalTimedTextData:
    573       {
    574           sendGlobalTextData(kWhatTimedTextData, mFetchTimedTextDataGeneration, msg);
    575           break;
    576       }
    577       case kWhatSendTimedTextData:
    578       {
    579           sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
    580                   mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
    581           break;
    582       }
    583 
    584       case kWhatChangeAVSource:
    585       {
    586           int32_t trackIndex;
    587           CHECK(msg->findInt32("trackIndex", &trackIndex));
    588           const sp<AMediaExtractorWrapper> extractor = mExtractors.itemAt(trackIndex);
    589 
    590           Track* track;
    591           AString mime;
    592           media_track_type trackType, counterpartType;
    593           sp<AMediaFormatWrapper> format = extractor->getTrackFormat(trackIndex);
    594           format->getString(AMEDIAFORMAT_KEY_MIME, &mime);
    595           if (!strncasecmp(mime.c_str(), "audio/", 6)) {
    596               track = &mAudioTrack;
    597               trackType = MEDIA_TRACK_TYPE_AUDIO;
    598               counterpartType = MEDIA_TRACK_TYPE_VIDEO;;
    599           } else {
    600               CHECK(!strncasecmp(mime.c_str(), "video/", 6));
    601               track = &mVideoTrack;
    602               trackType = MEDIA_TRACK_TYPE_VIDEO;
    603               counterpartType = MEDIA_TRACK_TYPE_AUDIO;;
    604           }
    605 
    606 
    607           track->mExtractor = extractor;
    608           track->mExtractor->selectSingleTrack(trackIndex);
    609           track->mIndex = trackIndex;
    610           ++mAudioDataGeneration;
    611           ++mVideoDataGeneration;
    612 
    613           int64_t timeUs, actualTimeUs;
    614           const bool formatChange = true;
    615           if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
    616               timeUs = mAudioLastDequeueTimeUs;
    617           } else {
    618               timeUs = mVideoLastDequeueTimeUs;
    619           }
    620           readBuffer(trackType, timeUs, MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC /* mode */,
    621                   &actualTimeUs, formatChange);
    622           readBuffer(counterpartType, -1, MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC /* mode */,
    623                   NULL, !formatChange);
    624           ALOGV("timeUs %lld actualTimeUs %lld", (long long)timeUs, (long long)actualTimeUs);
    625 
    626           break;
    627       }
    628 
    629       case kWhatSeek:
    630       {
    631           onSeek(msg);
    632           break;
    633       }
    634 
    635       case kWhatReadBuffer:
    636       {
    637           onReadBuffer(msg);
    638           break;
    639       }
    640 
    641       case kWhatPollBuffering:
    642       {
    643           int32_t generation;
    644           CHECK(msg->findInt32("generation", &generation));
    645           if (generation == mPollBufferingGeneration) {
    646               onPollBuffering();
    647           }
    648           break;
    649       }
    650 
    651       default:
    652           Source::onMessageReceived(msg);
    653           break;
    654     }
    655 }
    656 
    657 void NuPlayer2::GenericSource2::fetchTextData(
    658         uint32_t sendWhat,
    659         media_track_type type,
    660         int32_t curGen,
    661         const sp<AnotherPacketSource>& packets,
    662         const sp<AMessage>& msg) {
    663     int32_t msgGeneration;
    664     CHECK(msg->findInt32("generation", &msgGeneration));
    665     if (msgGeneration != curGen) {
    666         // stale
    667         return;
    668     }
    669 
    670     int32_t avail;
    671     if (packets->hasBufferAvailable(&avail)) {
    672         return;
    673     }
    674 
    675     int64_t timeUs;
    676     CHECK(msg->findInt64("timeUs", &timeUs));
    677 
    678     int64_t subTimeUs = 0;
    679     readBuffer(type, timeUs, MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC /* mode */, &subTimeUs);
    680 
    681     status_t eosResult;
    682     if (!packets->hasBufferAvailable(&eosResult)) {
    683         return;
    684     }
    685 
    686     if (msg->what() == kWhatFetchSubtitleData) {
    687         subTimeUs -= 1000000ll;  // send subtile data one second earlier
    688     }
    689     sp<AMessage> msg2 = new AMessage(sendWhat, this);
    690     msg2->setInt32("generation", msgGeneration);
    691     mMediaClock->addTimer(msg2, subTimeUs);
    692 }
    693 
    694 void NuPlayer2::GenericSource2::sendTextData(
    695         uint32_t what,
    696         media_track_type type,
    697         int32_t curGen,
    698         const sp<AnotherPacketSource>& packets,
    699         const sp<AMessage>& msg) {
    700     int32_t msgGeneration;
    701     CHECK(msg->findInt32("generation", &msgGeneration));
    702     if (msgGeneration != curGen) {
    703         // stale
    704         return;
    705     }
    706 
    707     int64_t subTimeUs;
    708     if (packets->nextBufferTime(&subTimeUs) != OK) {
    709         return;
    710     }
    711 
    712     int64_t nextSubTimeUs;
    713     readBuffer(type, -1, MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC /* mode */, &nextSubTimeUs);
    714 
    715     sp<ABuffer> buffer;
    716     status_t dequeueStatus = packets->dequeueAccessUnit(&buffer);
    717     if (dequeueStatus == OK) {
    718         sp<AMessage> notify = dupNotify();
    719         notify->setInt32("what", what);
    720         notify->setBuffer("buffer", buffer);
    721         notify->post();
    722 
    723         if (msg->what() == kWhatSendSubtitleData) {
    724             nextSubTimeUs -= 1000000ll;  // send subtile data one second earlier
    725         }
    726         mMediaClock->addTimer(msg, nextSubTimeUs);
    727     }
    728 }
    729 
    730 void NuPlayer2::GenericSource2::sendGlobalTextData(
    731         uint32_t what,
    732         int32_t curGen,
    733         sp<AMessage> msg) {
    734     int32_t msgGeneration;
    735     CHECK(msg->findInt32("generation", &msgGeneration));
    736     if (msgGeneration != curGen) {
    737         // stale
    738         return;
    739     }
    740 
    741     void *data = NULL;
    742     size_t size = 0;
    743     if (mTimedTextTrack.mExtractor->getTrackFormat(mTimedTextTrack.mIndex)->getBuffer(
    744                     "text", &data, &size)) {
    745         mGlobalTimedText = new ABuffer(size);
    746         if (mGlobalTimedText->data()) {
    747             memcpy(mGlobalTimedText->data(), data, size);
    748             sp<AMessage> globalMeta = mGlobalTimedText->meta();
    749             globalMeta->setInt64("timeUs", 0);
    750             globalMeta->setString("mime", MEDIA_MIMETYPE_TEXT_3GPP);
    751             globalMeta->setInt32("global", 1);
    752             sp<AMessage> notify = dupNotify();
    753             notify->setInt32("what", what);
    754             notify->setBuffer("buffer", mGlobalTimedText);
    755             notify->post();
    756         }
    757     }
    758 }
    759 
    760 sp<AMessage> NuPlayer2::GenericSource2::getFormat(bool audio) {
    761     Mutex::Autolock _l(mLock);
    762     return getFormat_l(audio);
    763 }
    764 
    765 sp<MetaData> NuPlayer2::GenericSource2::getFormatMeta(bool audio) {
    766     Mutex::Autolock _l(mLock);
    767     return getFormatMeta_l(audio);
    768 }
    769 
    770 sp<AMessage> NuPlayer2::GenericSource2::getFormat_l(bool audio) {
    771     sp<AMediaExtractorWrapper> extractor = audio ? mAudioTrack.mExtractor : mVideoTrack.mExtractor;
    772     size_t trackIndex = audio ? mAudioTrack.mIndex : mVideoTrack.mIndex;
    773 
    774     if (extractor == NULL) {
    775         return NULL;
    776     }
    777 
    778     return extractor->getTrackFormat(trackIndex)->toAMessage();
    779 }
    780 
    781 sp<MetaData> NuPlayer2::GenericSource2::getFormatMeta_l(bool audio) {
    782     sp<AMediaExtractorWrapper> extractor = audio ? mAudioTrack.mExtractor : mVideoTrack.mExtractor;
    783     size_t trackIndex = audio ? mAudioTrack.mIndex : mVideoTrack.mIndex;
    784 
    785     if (extractor == NULL) {
    786         return NULL;
    787     }
    788 
    789     return convertMediaFormatWrapperToMetaData(extractor->getTrackFormat(trackIndex));
    790 }
    791 
    792 status_t NuPlayer2::GenericSource2::dequeueAccessUnit(
    793         bool audio, sp<ABuffer> *accessUnit) {
    794     Mutex::Autolock _l(mLock);
    795     // If has gone through stop/releaseDrm sequence, we no longer send down any buffer b/c
    796     // the codec's crypto object has gone away (b/37960096).
    797     // Note: This will be unnecessary when stop() changes behavior and releases codec (b/35248283).
    798     if (!mStarted && mIsDrmReleased) {
    799         return -EWOULDBLOCK;
    800     }
    801 
    802     Track *track = audio ? &mAudioTrack : &mVideoTrack;
    803 
    804     if (track->mExtractor == NULL) {
    805         return -EWOULDBLOCK;
    806     }
    807 
    808     status_t finalResult;
    809     if (!track->mPackets->hasBufferAvailable(&finalResult)) {
    810         if (finalResult == OK) {
    811             postReadBuffer(
    812                     audio ? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
    813             return -EWOULDBLOCK;
    814         }
    815         return finalResult;
    816     }
    817 
    818     status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
    819 
    820     // start pulling in more buffers if cache is running low
    821     // so that decoder has less chance of being starved
    822     if (!mIsStreaming) {
    823         if (track->mPackets->getAvailableBufferCount(&finalResult) < 2) {
    824             postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
    825         }
    826     } else {
    827         int64_t durationUs = track->mPackets->getBufferedDurationUs(&finalResult);
    828         // TODO: maxRebufferingMarkMs could be larger than
    829         // mBufferingSettings.mResumePlaybackMarkMs
    830         int64_t restartBufferingMarkUs =
    831              mBufferingSettings.mResumePlaybackMarkMs * 1000ll / 2;
    832         if (finalResult == OK) {
    833             if (durationUs < restartBufferingMarkUs) {
    834                 postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
    835             }
    836             if (track->mPackets->getAvailableBufferCount(&finalResult) < 2
    837                 && !mSentPauseOnBuffering && !mPreparing) {
    838                 mCachedSource->resumeFetchingIfNecessary();
    839                 sendCacheStats();
    840                 mSentPauseOnBuffering = true;
    841                 sp<AMessage> notify = dupNotify();
    842                 notify->setInt32("what", kWhatPauseOnBufferingStart);
    843                 notify->post();
    844             }
    845         }
    846     }
    847 
    848     if (result != OK) {
    849         if (mSubtitleTrack.mExtractor != NULL) {
    850             mSubtitleTrack.mPackets->clear();
    851             mFetchSubtitleDataGeneration++;
    852         }
    853         if (mTimedTextTrack.mExtractor != NULL) {
    854             mTimedTextTrack.mPackets->clear();
    855             mFetchTimedTextDataGeneration++;
    856         }
    857         return result;
    858     }
    859 
    860     int64_t timeUs;
    861     status_t eosResult; // ignored
    862     CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
    863     if (audio) {
    864         mAudioLastDequeueTimeUs = timeUs;
    865     } else {
    866         mVideoLastDequeueTimeUs = timeUs;
    867     }
    868 
    869     if (mSubtitleTrack.mExtractor != NULL
    870             && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
    871         sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
    872         msg->setInt64("timeUs", timeUs);
    873         msg->setInt32("generation", mFetchSubtitleDataGeneration);
    874         msg->post();
    875     }
    876 
    877     if (mTimedTextTrack.mExtractor != NULL
    878             && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
    879         sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
    880         msg->setInt64("timeUs", timeUs);
    881         msg->setInt32("generation", mFetchTimedTextDataGeneration);
    882         msg->post();
    883     }
    884 
    885     return result;
    886 }
    887 
    888 status_t NuPlayer2::GenericSource2::getDuration(int64_t *durationUs) {
    889     Mutex::Autolock _l(mLock);
    890     *durationUs = mDurationUs;
    891     return OK;
    892 }
    893 
    894 size_t NuPlayer2::GenericSource2::getTrackCount() const {
    895     Mutex::Autolock _l(mLock);
    896     return mExtractors.size();
    897 }
    898 
    899 sp<AMessage> NuPlayer2::GenericSource2::getTrackInfo(size_t trackIndex) const {
    900     Mutex::Autolock _l(mLock);
    901     size_t trackCount = mExtractors.size();
    902     if (trackIndex >= trackCount) {
    903         return NULL;
    904     }
    905 
    906     sp<AMessage> format = mExtractors.itemAt(trackIndex)->getTrackFormat(trackIndex)->toAMessage();
    907     if (format == NULL) {
    908         ALOGE("no metadata for track %zu", trackIndex);
    909         return NULL;
    910     }
    911 
    912     AString mime;
    913     CHECK(format->findString(AMEDIAFORMAT_KEY_MIME, &mime));
    914 
    915     int32_t trackType;
    916     if (!strncasecmp(mime.c_str(), "video/", 6)) {
    917         trackType = MEDIA_TRACK_TYPE_VIDEO;
    918     } else if (!strncasecmp(mime.c_str(), "audio/", 6)) {
    919         trackType = MEDIA_TRACK_TYPE_AUDIO;
    920     } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_TEXT_3GPP)) {
    921         trackType = MEDIA_TRACK_TYPE_TIMEDTEXT;
    922     } else {
    923         trackType = MEDIA_TRACK_TYPE_UNKNOWN;
    924     }
    925     format->setInt32("type", trackType);
    926 
    927     AString lang;
    928     if (!format->findString("language", &lang)) {
    929         format->setString("language", "und");
    930     }
    931 
    932     if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
    933         int32_t isAutoselect = 1, isDefault = 0, isForced = 0;
    934         format->findInt32(AMEDIAFORMAT_KEY_IS_AUTOSELECT, &isAutoselect);
    935         format->findInt32(AMEDIAFORMAT_KEY_IS_DEFAULT, &isDefault);
    936         format->findInt32(AMEDIAFORMAT_KEY_IS_FORCED_SUBTITLE, &isForced);
    937 
    938         format->setInt32("auto", !!isAutoselect);
    939         format->setInt32("default", !!isDefault);
    940         format->setInt32("forced", !!isForced);
    941     }
    942 
    943     return format;
    944 }
    945 
    946 ssize_t NuPlayer2::GenericSource2::getSelectedTrack(media_track_type type) const {
    947     Mutex::Autolock _l(mLock);
    948     const Track *track = NULL;
    949     switch (type) {
    950     case MEDIA_TRACK_TYPE_VIDEO:
    951         track = &mVideoTrack;
    952         break;
    953     case MEDIA_TRACK_TYPE_AUDIO:
    954         track = &mAudioTrack;
    955         break;
    956     case MEDIA_TRACK_TYPE_TIMEDTEXT:
    957         track = &mTimedTextTrack;
    958         break;
    959     case MEDIA_TRACK_TYPE_SUBTITLE:
    960         track = &mSubtitleTrack;
    961         break;
    962     default:
    963         break;
    964     }
    965 
    966     if (track != NULL && track->mExtractor != NULL) {
    967         return track->mIndex;
    968     }
    969 
    970     return -1;
    971 }
    972 
    973 status_t NuPlayer2::GenericSource2::selectTrack(size_t trackIndex, bool select, int64_t timeUs) {
    974     Mutex::Autolock _l(mLock);
    975     ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex);
    976 
    977     if (trackIndex >= mExtractors.size()) {
    978         return BAD_INDEX;
    979     }
    980 
    981     if (!select) {
    982         Track* track = NULL;
    983         if (mSubtitleTrack.mExtractor != NULL && trackIndex == mSubtitleTrack.mIndex) {
    984             track = &mSubtitleTrack;
    985             mFetchSubtitleDataGeneration++;
    986         } else if (mTimedTextTrack.mExtractor != NULL && trackIndex == mTimedTextTrack.mIndex) {
    987             track = &mTimedTextTrack;
    988             mFetchTimedTextDataGeneration++;
    989         }
    990         if (track == NULL) {
    991             return INVALID_OPERATION;
    992         }
    993         track->mExtractor = NULL;
    994         track->mPackets->clear();
    995         return OK;
    996     }
    997 
    998     const sp<AMediaExtractorWrapper> extractor = mExtractors.itemAt(trackIndex);
    999     sp<MetaData> meta = convertMediaFormatWrapperToMetaData(extractor->getTrackFormat(trackIndex));
   1000     const char *mime;
   1001     CHECK(meta->findCString(kKeyMIMEType, &mime));
   1002     if (!strncasecmp(mime, "text/", 5)) {
   1003         bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP);
   1004         Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack;
   1005         if (track->mExtractor != NULL && track->mIndex == trackIndex) {
   1006             return OK;
   1007         }
   1008         track->mIndex = trackIndex;
   1009         track->mExtractor = mExtractors.itemAt(trackIndex);
   1010         track->mExtractor->selectSingleTrack(trackIndex);
   1011         if (track->mPackets == NULL) {
   1012             track->mPackets = new AnotherPacketSource(meta);
   1013         } else {
   1014             track->mPackets->clear();
   1015             track->mPackets->setFormat(meta);
   1016 
   1017         }
   1018 
   1019         if (isSubtitle) {
   1020             mFetchSubtitleDataGeneration++;
   1021         } else {
   1022             mFetchTimedTextDataGeneration++;
   1023         }
   1024 
   1025         status_t eosResult; // ignored
   1026         if (mSubtitleTrack.mExtractor != NULL
   1027                 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
   1028             sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
   1029             msg->setInt64("timeUs", timeUs);
   1030             msg->setInt32("generation", mFetchSubtitleDataGeneration);
   1031             msg->post();
   1032         }
   1033 
   1034         sp<AMessage> msg2 = new AMessage(kWhatSendGlobalTimedTextData, this);
   1035         msg2->setInt32("generation", mFetchTimedTextDataGeneration);
   1036         msg2->post();
   1037 
   1038         if (mTimedTextTrack.mExtractor != NULL
   1039                 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
   1040             sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
   1041             msg->setInt64("timeUs", timeUs);
   1042             msg->setInt32("generation", mFetchTimedTextDataGeneration);
   1043             msg->post();
   1044         }
   1045 
   1046         return OK;
   1047     } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) {
   1048         bool audio = !strncasecmp(mime, "audio/", 6);
   1049         Track *track = audio ? &mAudioTrack : &mVideoTrack;
   1050         if (track->mExtractor != NULL && track->mIndex == trackIndex) {
   1051             return OK;
   1052         }
   1053 
   1054         sp<AMessage> msg = new AMessage(kWhatChangeAVSource, this);
   1055         msg->setInt32("trackIndex", trackIndex);
   1056         msg->post();
   1057         return OK;
   1058     }
   1059 
   1060     return INVALID_OPERATION;
   1061 }
   1062 
   1063 status_t NuPlayer2::GenericSource2::seekTo(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
   1064     ALOGV("seekTo: %lld, %d", (long long)seekTimeUs, mode);
   1065     sp<AMessage> msg = new AMessage(kWhatSeek, this);
   1066     msg->setInt64("seekTimeUs", seekTimeUs);
   1067     msg->setInt32("mode", mode);
   1068 
   1069     // Need to call readBuffer on |mLooper| to ensure the calls to
   1070     // IMediaSource::read* are serialized. Note that IMediaSource::read*
   1071     // is called without |mLock| acquired and MediaSource is not thread safe.
   1072     sp<AMessage> response;
   1073     status_t err = msg->postAndAwaitResponse(&response);
   1074     if (err == OK && response != NULL) {
   1075         CHECK(response->findInt32("err", &err));
   1076     }
   1077 
   1078     return err;
   1079 }
   1080 
   1081 void NuPlayer2::GenericSource2::onSeek(const sp<AMessage>& msg) {
   1082     int64_t seekTimeUs;
   1083     int32_t mode;
   1084     CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
   1085     CHECK(msg->findInt32("mode", &mode));
   1086 
   1087     sp<AMessage> response = new AMessage;
   1088     status_t err = doSeek(seekTimeUs, (MediaPlayer2SeekMode)mode);
   1089     response->setInt32("err", err);
   1090 
   1091     sp<AReplyToken> replyID;
   1092     CHECK(msg->senderAwaitsResponse(&replyID));
   1093     response->postReply(replyID);
   1094 }
   1095 
   1096 status_t NuPlayer2::GenericSource2::doSeek(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
   1097     if (mVideoTrack.mExtractor != NULL) {
   1098         ++mVideoDataGeneration;
   1099 
   1100         int64_t actualTimeUs;
   1101         readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, mode, &actualTimeUs);
   1102 
   1103         if (mode != MediaPlayer2SeekMode::SEEK_CLOSEST) {
   1104             seekTimeUs = actualTimeUs;
   1105         }
   1106         mVideoLastDequeueTimeUs = actualTimeUs;
   1107     }
   1108 
   1109     if (mAudioTrack.mExtractor != NULL) {
   1110         ++mAudioDataGeneration;
   1111         readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs, MediaPlayer2SeekMode::SEEK_CLOSEST);
   1112         mAudioLastDequeueTimeUs = seekTimeUs;
   1113     }
   1114 
   1115     if (mSubtitleTrack.mExtractor != NULL) {
   1116         mSubtitleTrack.mPackets->clear();
   1117         mFetchSubtitleDataGeneration++;
   1118     }
   1119 
   1120     if (mTimedTextTrack.mExtractor != NULL) {
   1121         mTimedTextTrack.mPackets->clear();
   1122         mFetchTimedTextDataGeneration++;
   1123     }
   1124 
   1125     ++mPollBufferingGeneration;
   1126     schedulePollBuffering();
   1127     return OK;
   1128 }
   1129 
   1130 sp<ABuffer> NuPlayer2::GenericSource2::mediaBufferToABuffer(
   1131         MediaBufferBase* mb,
   1132         media_track_type trackType) {
   1133     bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
   1134     size_t outLength = mb->range_length();
   1135 
   1136     if (audio && mAudioIsVorbis) {
   1137         outLength += sizeof(int32_t);
   1138     }
   1139 
   1140     sp<ABuffer> ab;
   1141 
   1142     if (mIsDrmProtected)   {
   1143         // Modular DRM
   1144         // Enabled for both video/audio so 1) media buffer is reused without extra copying
   1145         // 2) meta data can be retrieved in onInputBufferFetched for calling queueSecureInputBuffer.
   1146 
   1147         // data is already provided in the buffer
   1148         ab = new ABuffer(NULL, mb->range_length());
   1149         ab->meta()->setObject("mediaBufferHolder", new MediaBufferHolder(mb));
   1150 
   1151         // Modular DRM: Required b/c of the above add_ref.
   1152         // If ref>0, there must be an observer, or it'll crash at release().
   1153         // TODO: MediaBuffer might need to be revised to ease such need.
   1154         mb->setObserver(this);
   1155         // setMediaBufferBase() interestingly doesn't increment the ref count on its own.
   1156         // Extra increment (since we want to keep mb alive and attached to ab beyond this function
   1157         // call. This is to counter the effect of mb->release() towards the end.
   1158         mb->add_ref();
   1159 
   1160     } else {
   1161         ab = new ABuffer(outLength);
   1162         memcpy(ab->data(),
   1163                (const uint8_t *)mb->data() + mb->range_offset(),
   1164                mb->range_length());
   1165     }
   1166 
   1167     if (audio && mAudioIsVorbis) {
   1168         int32_t numPageSamples;
   1169         if (!mb->meta_data().findInt32(kKeyValidSamples, &numPageSamples)) {
   1170             numPageSamples = -1;
   1171         }
   1172 
   1173         uint8_t* abEnd = ab->data() + mb->range_length();
   1174         memcpy(abEnd, &numPageSamples, sizeof(numPageSamples));
   1175     }
   1176 
   1177     sp<AMessage> meta = ab->meta();
   1178 
   1179     int64_t timeUs;
   1180     CHECK(mb->meta_data().findInt64(kKeyTime, &timeUs));
   1181     meta->setInt64("timeUs", timeUs);
   1182 
   1183     if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
   1184         int32_t layerId;
   1185         if (mb->meta_data().findInt32(kKeyTemporalLayerId, &layerId)) {
   1186             meta->setInt32("temporal-layer-id", layerId);
   1187         }
   1188     }
   1189 
   1190     if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
   1191         AString mime;
   1192         sp<AMediaExtractorWrapper> extractor = mTimedTextTrack.mExtractor;
   1193         size_t trackIndex = mTimedTextTrack.mIndex;
   1194         CHECK(extractor != NULL
   1195                 && extractor->getTrackFormat(trackIndex)->getString(AMEDIAFORMAT_KEY_MIME, &mime));
   1196         meta->setString("mime", mime.c_str());
   1197     }
   1198 
   1199     int64_t durationUs;
   1200     if (mb->meta_data().findInt64(kKeyDuration, &durationUs)) {
   1201         meta->setInt64("durationUs", durationUs);
   1202     }
   1203 
   1204     if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
   1205         meta->setInt32(AMEDIAFORMAT_KEY_TRACK_INDEX, mSubtitleTrack.mIndex);
   1206     }
   1207 
   1208     uint32_t dataType; // unused
   1209     const void *seiData;
   1210     size_t seiLength;
   1211     if (mb->meta_data().findData(kKeySEI, &dataType, &seiData, &seiLength)) {
   1212         sp<ABuffer> sei = ABuffer::CreateAsCopy(seiData, seiLength);;
   1213         meta->setBuffer("sei", sei);
   1214     }
   1215 
   1216     const void *mpegUserDataPointer;
   1217     size_t mpegUserDataLength;
   1218     if (mb->meta_data().findData(
   1219             kKeyMpegUserData, &dataType, &mpegUserDataPointer, &mpegUserDataLength)) {
   1220         sp<ABuffer> mpegUserData = ABuffer::CreateAsCopy(mpegUserDataPointer, mpegUserDataLength);
   1221         meta->setBuffer(AMEDIAFORMAT_KEY_MPEG_USER_DATA, mpegUserData);
   1222     }
   1223 
   1224     mb->release();
   1225     mb = NULL;
   1226 
   1227     return ab;
   1228 }
   1229 
   1230 int32_t NuPlayer2::GenericSource2::getDataGeneration(media_track_type type) const {
   1231     int32_t generation = -1;
   1232     switch (type) {
   1233     case MEDIA_TRACK_TYPE_VIDEO:
   1234         generation = mVideoDataGeneration;
   1235         break;
   1236     case MEDIA_TRACK_TYPE_AUDIO:
   1237         generation = mAudioDataGeneration;
   1238         break;
   1239     case MEDIA_TRACK_TYPE_TIMEDTEXT:
   1240         generation = mFetchTimedTextDataGeneration;
   1241         break;
   1242     case MEDIA_TRACK_TYPE_SUBTITLE:
   1243         generation = mFetchSubtitleDataGeneration;
   1244         break;
   1245     default:
   1246         break;
   1247     }
   1248 
   1249     return generation;
   1250 }
   1251 
   1252 void NuPlayer2::GenericSource2::postReadBuffer(media_track_type trackType) {
   1253     if ((mPendingReadBufferTypes & (1 << trackType)) == 0) {
   1254         mPendingReadBufferTypes |= (1 << trackType);
   1255         sp<AMessage> msg = new AMessage(kWhatReadBuffer, this);
   1256         msg->setInt32("trackType", trackType);
   1257         msg->post();
   1258     }
   1259 }
   1260 
   1261 void NuPlayer2::GenericSource2::onReadBuffer(const sp<AMessage>& msg) {
   1262     int32_t tmpType;
   1263     CHECK(msg->findInt32("trackType", &tmpType));
   1264     media_track_type trackType = (media_track_type)tmpType;
   1265     mPendingReadBufferTypes &= ~(1 << trackType);
   1266     readBuffer(trackType);
   1267 }
   1268 
   1269 void NuPlayer2::GenericSource2::readBuffer(
   1270         media_track_type trackType, int64_t seekTimeUs, MediaPlayer2SeekMode mode,
   1271         int64_t *actualTimeUs, bool formatChange) {
   1272     Track *track;
   1273     size_t maxBuffers = 1;
   1274     switch (trackType) {
   1275         case MEDIA_TRACK_TYPE_VIDEO:
   1276             track = &mVideoTrack;
   1277             maxBuffers = 8;  // too large of a number may influence seeks
   1278             break;
   1279         case MEDIA_TRACK_TYPE_AUDIO:
   1280             track = &mAudioTrack;
   1281             maxBuffers = 64;
   1282             break;
   1283         case MEDIA_TRACK_TYPE_SUBTITLE:
   1284             track = &mSubtitleTrack;
   1285             break;
   1286         case MEDIA_TRACK_TYPE_TIMEDTEXT:
   1287             track = &mTimedTextTrack;
   1288             break;
   1289         default:
   1290             TRESPASS();
   1291     }
   1292 
   1293     if (track->mExtractor == NULL) {
   1294         return;
   1295     }
   1296 
   1297     if (actualTimeUs) {
   1298         *actualTimeUs = seekTimeUs;
   1299     }
   1300 
   1301 
   1302     bool seeking = false;
   1303     sp<AMediaExtractorWrapper> extractor = track->mExtractor;
   1304     if (seekTimeUs >= 0) {
   1305         extractor->seekTo(seekTimeUs, mode);
   1306         seeking = true;
   1307     }
   1308 
   1309     int32_t generation = getDataGeneration(trackType);
   1310     for (size_t numBuffers = 0; numBuffers < maxBuffers; ) {
   1311         Vector<sp<ABuffer> > aBuffers;
   1312 
   1313         mLock.unlock();
   1314 
   1315         sp<AMediaFormatWrapper> format;
   1316         ssize_t sampleSize = -1;
   1317         status_t err = extractor->getSampleFormat(format);
   1318         if (err == OK) {
   1319             sampleSize = extractor->getSampleSize();
   1320         }
   1321 
   1322         if (err != OK || sampleSize < 0) {
   1323             mLock.lock();
   1324             track->mPackets->signalEOS(err != OK ? err : ERROR_END_OF_STREAM);
   1325             break;
   1326         }
   1327 
   1328         sp<ABuffer> abuf = new ABuffer(sampleSize);
   1329         sampleSize = extractor->readSampleData(abuf);
   1330         mLock.lock();
   1331 
   1332         // in case track has been changed since we don't have lock for some time.
   1333         if (generation != getDataGeneration(trackType)) {
   1334             break;
   1335         }
   1336 
   1337         int64_t timeUs = extractor->getSampleTime();
   1338         if (timeUs < 0) {
   1339             track->mPackets->signalEOS(ERROR_MALFORMED);
   1340             break;
   1341         }
   1342 
   1343         sp<AMessage> meta = abuf->meta();
   1344         format->writeToAMessage(meta);
   1345         meta->setInt64("timeUs", timeUs);
   1346         if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
   1347             mAudioTimeUs = timeUs;
   1348         } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
   1349             mVideoTimeUs = timeUs;
   1350         }
   1351 
   1352         queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
   1353 
   1354         if (numBuffers == 0 && actualTimeUs != nullptr) {
   1355             *actualTimeUs = timeUs;
   1356         }
   1357         if (seeking) {
   1358             if (meta != nullptr && mode == MediaPlayer2SeekMode::SEEK_CLOSEST
   1359                     && seekTimeUs > timeUs) {
   1360                 sp<AMessage> extra = new AMessage;
   1361                 extra->setInt64("resume-at-mediaTimeUs", seekTimeUs);
   1362                 meta->setMessage("extra", extra);
   1363             }
   1364         }
   1365 
   1366         track->mPackets->queueAccessUnit(abuf);
   1367         formatChange = false;
   1368         seeking = false;
   1369         ++numBuffers;
   1370         extractor->advance();
   1371 
   1372     }
   1373 
   1374     if (mIsStreaming
   1375         && (trackType == MEDIA_TRACK_TYPE_VIDEO || trackType == MEDIA_TRACK_TYPE_AUDIO)) {
   1376         status_t finalResult;
   1377         int64_t durationUs = track->mPackets->getBufferedDurationUs(&finalResult);
   1378 
   1379         // TODO: maxRebufferingMarkMs could be larger than
   1380         // mBufferingSettings.mResumePlaybackMarkMs
   1381         int64_t markUs = (mPreparing ? mBufferingSettings.mInitialMarkMs
   1382             : mBufferingSettings.mResumePlaybackMarkMs) * 1000ll;
   1383         if (finalResult == ERROR_END_OF_STREAM || durationUs >= markUs) {
   1384             if (mPreparing || mSentPauseOnBuffering) {
   1385                 Track *counterTrack =
   1386                     (trackType == MEDIA_TRACK_TYPE_VIDEO ? &mAudioTrack : &mVideoTrack);
   1387                 if (counterTrack->mExtractor != NULL) {
   1388                     durationUs = counterTrack->mPackets->getBufferedDurationUs(&finalResult);
   1389                 }
   1390                 if (finalResult == ERROR_END_OF_STREAM || durationUs >= markUs) {
   1391                     if (mPreparing) {
   1392                         notifyPrepared();
   1393                         mPreparing = false;
   1394                     } else {
   1395                         sendCacheStats();
   1396                         mSentPauseOnBuffering = false;
   1397                         sp<AMessage> notify = dupNotify();
   1398                         notify->setInt32("what", kWhatResumeOnBufferingEnd);
   1399                         notify->post();
   1400                     }
   1401                 }
   1402             }
   1403             return;
   1404         }
   1405 
   1406         postReadBuffer(trackType);
   1407     }
   1408 }
   1409 
   1410 void NuPlayer2::GenericSource2::queueDiscontinuityIfNeeded(
   1411         bool seeking, bool formatChange, media_track_type trackType, Track *track) {
   1412     // formatChange && seeking: track whose source is changed during selection
   1413     // formatChange && !seeking: track whose source is not changed during selection
   1414     // !formatChange: normal seek
   1415     if ((seeking || formatChange)
   1416             && (trackType == MEDIA_TRACK_TYPE_AUDIO
   1417             || trackType == MEDIA_TRACK_TYPE_VIDEO)) {
   1418         ATSParser::DiscontinuityType type = (formatChange && seeking)
   1419                 ? ATSParser::DISCONTINUITY_FORMATCHANGE
   1420                 : ATSParser::DISCONTINUITY_NONE;
   1421         track->mPackets->queueDiscontinuity(type, NULL /* extra */, true /* discard */);
   1422     }
   1423 }
   1424 
   1425 void NuPlayer2::GenericSource2::notifyBufferingUpdate(int32_t percentage) {
   1426     // Buffering percent could go backward as it's estimated from remaining
   1427     // data and last access time. This could cause the buffering position
   1428     // drawn on media control to jitter slightly. Remember previously reported
   1429     // percentage and don't allow it to go backward.
   1430     if (percentage < mPrevBufferPercentage) {
   1431         percentage = mPrevBufferPercentage;
   1432     } else if (percentage > 100) {
   1433         percentage = 100;
   1434     }
   1435 
   1436     mPrevBufferPercentage = percentage;
   1437 
   1438     ALOGV("notifyBufferingUpdate: buffering %d%%", percentage);
   1439 
   1440     sp<AMessage> notify = dupNotify();
   1441     notify->setInt32("what", kWhatBufferingUpdate);
   1442     notify->setInt32("percentage", percentage);
   1443     notify->post();
   1444 }
   1445 
   1446 void NuPlayer2::GenericSource2::schedulePollBuffering() {
   1447     sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
   1448     msg->setInt32("generation", mPollBufferingGeneration);
   1449     // Enquires buffering status every second.
   1450     msg->post(1000000ll);
   1451 }
   1452 
   1453 void NuPlayer2::GenericSource2::onPollBuffering() {
   1454     status_t finalStatus = UNKNOWN_ERROR;
   1455     int64_t cachedDurationUs = -1ll;
   1456     ssize_t cachedDataRemaining = -1;
   1457 
   1458     if (mCachedSource != NULL) {
   1459         cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
   1460 
   1461         if (finalStatus == OK) {
   1462             off64_t size;
   1463             int64_t bitrate = 0ll;
   1464             if (mDurationUs > 0 && mCachedSource->getSize(&size) == OK) {
   1465                 // |bitrate| uses bits/second unit, while size is number of bytes.
   1466                 bitrate = size * 8000000ll / mDurationUs;
   1467             } else if (mBitrate > 0) {
   1468                 bitrate = mBitrate;
   1469             }
   1470             if (bitrate > 0) {
   1471                 cachedDurationUs = cachedDataRemaining * 8000000ll / bitrate;
   1472             }
   1473         }
   1474     }
   1475 
   1476     if (finalStatus != OK) {
   1477         ALOGV("onPollBuffering: EOS (finalStatus = %d)", finalStatus);
   1478 
   1479         if (finalStatus == ERROR_END_OF_STREAM) {
   1480             notifyBufferingUpdate(100);
   1481         }
   1482 
   1483         return;
   1484     }
   1485 
   1486     if (cachedDurationUs >= 0ll) {
   1487         if (mDurationUs > 0ll) {
   1488             int64_t cachedPosUs = getLastReadPosition() + cachedDurationUs;
   1489             int percentage = 100.0 * cachedPosUs / mDurationUs;
   1490             if (percentage > 100) {
   1491                 percentage = 100;
   1492             }
   1493 
   1494             notifyBufferingUpdate(percentage);
   1495         }
   1496 
   1497         ALOGV("onPollBuffering: cachedDurationUs %.1f sec", cachedDurationUs / 1000000.0f);
   1498     }
   1499 
   1500     schedulePollBuffering();
   1501 }
   1502 
   1503 // Modular DRM
   1504 status_t NuPlayer2::GenericSource2::prepareDrm(
   1505         const uint8_t uuid[16],
   1506         const Vector<uint8_t> &drmSessionId,
   1507         sp<AMediaCryptoWrapper> *outCrypto) {
   1508     Mutex::Autolock _l(mLock);
   1509     ALOGV("prepareDrm");
   1510 
   1511     mIsDrmProtected = false;
   1512     mIsDrmReleased = false;
   1513     mIsSecure = false;
   1514 
   1515     status_t status = OK;
   1516     sp<AMediaCryptoWrapper> crypto =
   1517         new AMediaCryptoWrapper(uuid, drmSessionId.array(), drmSessionId.size());
   1518     if (crypto == NULL) {
   1519         ALOGE("prepareDrm: failed to create crypto.");
   1520         return UNKNOWN_ERROR;
   1521     }
   1522     ALOGV("prepareDrm: crypto created for uuid: %s",
   1523             DrmUUID::toHexString(uuid).string());
   1524 
   1525     *outCrypto = crypto;
   1526     // as long a there is an active crypto
   1527     mIsDrmProtected = true;
   1528 
   1529     if (mMimes.size() == 0) {
   1530         status = UNKNOWN_ERROR;
   1531         ALOGE("prepareDrm: Unexpected. Must have at least one track. status: %d", status);
   1532         return status;
   1533     }
   1534 
   1535     // first mime in this list is either the video track, or the first audio track
   1536     const char *mime = mMimes[0].string();
   1537     mIsSecure = crypto->requiresSecureDecoderComponent(mime);
   1538     ALOGV("prepareDrm: requiresSecureDecoderComponent mime: %s  isSecure: %d",
   1539             mime, mIsSecure);
   1540 
   1541     // Checking the member flags while in the looper to send out the notification.
   1542     // The legacy mDecryptHandle!=NULL check (for FLAG_PROTECTED) is equivalent to mIsDrmProtected.
   1543     notifyFlagsChanged(
   1544             (mIsSecure ? FLAG_SECURE : 0) |
   1545             // Setting "protected screen" only for L1: b/38390836
   1546             (mIsSecure ? FLAG_PROTECTED : 0) |
   1547             FLAG_CAN_PAUSE |
   1548             FLAG_CAN_SEEK_BACKWARD |
   1549             FLAG_CAN_SEEK_FORWARD |
   1550             FLAG_CAN_SEEK);
   1551 
   1552     if (status == OK) {
   1553         ALOGV("prepareDrm: mCrypto: %p", outCrypto->get());
   1554         ALOGD("prepareDrm ret: %d ", status);
   1555     } else {
   1556         ALOGE("prepareDrm err: %d", status);
   1557     }
   1558     return status;
   1559 }
   1560 
   1561 status_t NuPlayer2::GenericSource2::releaseDrm() {
   1562     Mutex::Autolock _l(mLock);
   1563     ALOGV("releaseDrm");
   1564 
   1565     if (mIsDrmProtected) {
   1566         mIsDrmProtected = false;
   1567         // to prevent returning any more buffer after stop/releaseDrm (b/37960096)
   1568         mIsDrmReleased = true;
   1569         ALOGV("releaseDrm: mIsDrmProtected is reset.");
   1570     } else {
   1571         ALOGE("releaseDrm: mIsDrmProtected is already false.");
   1572     }
   1573 
   1574     return OK;
   1575 }
   1576 
   1577 status_t NuPlayer2::GenericSource2::checkDrmInfo()
   1578 {
   1579     // clearing the flag at prepare in case the player is reused after stop/releaseDrm with the
   1580     // same source without being reset (called by prepareAsync/initFromDataSource)
   1581     mIsDrmReleased = false;
   1582 
   1583     if (mExtractor == NULL) {
   1584         ALOGV("checkDrmInfo: No extractor");
   1585         return OK; // letting the caller responds accordingly
   1586     }
   1587 
   1588     PsshInfo *psshInfo = mExtractor->getPsshInfo();
   1589     if (psshInfo == NULL) {
   1590         ALOGV("checkDrmInfo: No PSSH");
   1591         return OK; // source without DRM info
   1592     }
   1593 
   1594     sp<ABuffer> drmInfoBuffer = NuPlayer2Drm::retrieveDrmInfo(psshInfo);
   1595     ALOGV("checkDrmInfo: MEDIA_DRM_INFO PSSH drm info size: %d", (int)drmInfoBuffer->size());
   1596 
   1597     if (drmInfoBuffer->size() == 0) {
   1598         ALOGE("checkDrmInfo: Unexpected parcel size: 0");
   1599         return UNKNOWN_ERROR;
   1600     }
   1601 
   1602     notifyDrmInfo(drmInfoBuffer);
   1603 
   1604     return OK;
   1605 }
   1606 
   1607 void NuPlayer2::GenericSource2::signalBufferReturned(MediaBufferBase *buffer)
   1608 {
   1609     //ALOGV("signalBufferReturned %p  refCount: %d", buffer, buffer->localRefcount());
   1610 
   1611     buffer->setObserver(NULL);
   1612     buffer->release(); // this leads to delete since that there is no observor
   1613 }
   1614 
   1615 }  // namespace android
   1616