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