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