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