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 
GenericSource2(const sp<AMessage> & notify,uid_t uid,const sp<MediaClock> & mediaClock)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 
resetDataSource()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 
setDataSource(const sp<MediaHTTPService> & httpService,const char * url,const KeyedVector<String8,String8> * headers)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 
setDataSource(int fd,int64_t offset,int64_t length)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 
setDataSource(const sp<DataSource> & source)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 
getFileFormatMeta() const158 sp<MetaData> NuPlayer2::GenericSource2::getFileFormatMeta() const {
159     Mutex::Autolock _l(mLock);
160     return mFileMeta;
161 }
162 
initFromDataSource()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 
getBufferingSettings(BufferingSettings * buffering)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 
setBufferingSettings(const BufferingSettings & buffering)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 
getLastReadPosition()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 
isStreaming() const322 bool NuPlayer2::GenericSource2::isStreaming() const {
323     Mutex::Autolock _l(mLock);
324     return mIsStreaming;
325 }
326 
~GenericSource2()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 
prepareAsync()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 
onPrepareAsync()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 
finishPrepareAsync()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 
notifyPreparedAndCleanup(status_t err)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 
start()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 
stop()486 void NuPlayer2::GenericSource2::stop() {
487     Mutex::Autolock _l(mLock);
488     mStarted = false;
489 }
490 
pause()491 void NuPlayer2::GenericSource2::pause() {
492     Mutex::Autolock _l(mLock);
493     mStarted = false;
494 }
495 
resume()496 void NuPlayer2::GenericSource2::resume() {
497     Mutex::Autolock _l(mLock);
498     mStarted = true;
499 }
500 
disconnect()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 
feedMoreTSData()523 status_t NuPlayer2::GenericSource2::feedMoreTSData() {
524     return OK;
525 }
526 
sendCacheStats()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 
onMessageReceived(const sp<AMessage> & msg)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 
fetchTextData(uint32_t sendWhat,media_track_type type,int32_t curGen,const sp<AnotherPacketSource> & packets,const sp<AMessage> & msg)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 
sendTextData(uint32_t what,media_track_type type,int32_t curGen,const sp<AnotherPacketSource> & packets,const sp<AMessage> & msg)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 
sendGlobalTextData(uint32_t what,int32_t curGen,sp<AMessage> msg)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 
getFormat(bool audio)760 sp<AMessage> NuPlayer2::GenericSource2::getFormat(bool audio) {
761     Mutex::Autolock _l(mLock);
762     return getFormat_l(audio);
763 }
764 
getFormatMeta(bool audio)765 sp<MetaData> NuPlayer2::GenericSource2::getFormatMeta(bool audio) {
766     Mutex::Autolock _l(mLock);
767     return getFormatMeta_l(audio);
768 }
769 
getFormat_l(bool audio)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 
getFormatMeta_l(bool audio)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 
dequeueAccessUnit(bool audio,sp<ABuffer> * accessUnit)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 
getDuration(int64_t * durationUs)888 status_t NuPlayer2::GenericSource2::getDuration(int64_t *durationUs) {
889     Mutex::Autolock _l(mLock);
890     *durationUs = mDurationUs;
891     return OK;
892 }
893 
getTrackCount() const894 size_t NuPlayer2::GenericSource2::getTrackCount() const {
895     Mutex::Autolock _l(mLock);
896     return mExtractors.size();
897 }
898 
getTrackInfo(size_t trackIndex) const899 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 
getSelectedTrack(media_track_type type) const946 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 
selectTrack(size_t trackIndex,bool select,int64_t timeUs)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 
seekTo(int64_t seekTimeUs,MediaPlayer2SeekMode mode)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 
onSeek(const sp<AMessage> & msg)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 
doSeek(int64_t seekTimeUs,MediaPlayer2SeekMode mode)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 
mediaBufferToABuffer(MediaBufferBase * mb,media_track_type trackType)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 
getDataGeneration(media_track_type type) const1230 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 
postReadBuffer(media_track_type trackType)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 
onReadBuffer(const sp<AMessage> & msg)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 
readBuffer(media_track_type trackType,int64_t seekTimeUs,MediaPlayer2SeekMode mode,int64_t * actualTimeUs,bool formatChange)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 
queueDiscontinuityIfNeeded(bool seeking,bool formatChange,media_track_type trackType,Track * track)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 
notifyBufferingUpdate(int32_t percentage)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 
schedulePollBuffering()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 
onPollBuffering()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
prepareDrm(const uint8_t uuid[16],const Vector<uint8_t> & drmSessionId,sp<AMediaCryptoWrapper> * outCrypto)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 
releaseDrm()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 
checkDrmInfo()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 
signalBufferReturned(MediaBufferBase * buffer)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