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