GenericSource.cpp revision eb1735e343a93830df259ae8882160bb0d79dcb5
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#include "GenericSource.h"
18
19#include "AnotherPacketSource.h"
20
21#include <media/stagefright/foundation/ABuffer.h>
22#include <media/stagefright/foundation/ADebug.h>
23#include <media/stagefright/foundation/AMessage.h>
24#include <media/stagefright/DataSource.h>
25#include <media/stagefright/FileSource.h>
26#include <media/stagefright/MediaBuffer.h>
27#include <media/stagefright/MediaDefs.h>
28#include <media/stagefright/MediaExtractor.h>
29#include <media/stagefright/MediaSource.h>
30#include <media/stagefright/MetaData.h>
31#include "../../libstagefright/include/WVMExtractor.h"
32
33namespace android {
34
35NuPlayer::GenericSource::GenericSource(
36        const sp<AMessage> &notify,
37        const sp<IMediaHTTPService> &httpService,
38        const char *url,
39        const KeyedVector<String8, String8> *headers,
40        bool isWidevine,
41        bool uidValid,
42        uid_t uid)
43    : Source(notify),
44      mFetchSubtitleDataGeneration(0),
45      mFetchTimedTextDataGeneration(0),
46      mDurationUs(0ll),
47      mAudioIsVorbis(false),
48      mIsWidevine(isWidevine),
49      mUIDValid(uidValid),
50      mUID(uid) {
51    DataSource::RegisterDefaultSniffers();
52
53    sp<DataSource> dataSource =
54        DataSource::CreateFromURI(httpService, url, headers);
55    CHECK(dataSource != NULL);
56
57    initFromDataSource(dataSource);
58}
59
60NuPlayer::GenericSource::GenericSource(
61        const sp<AMessage> &notify,
62        int fd, int64_t offset, int64_t length)
63    : Source(notify),
64      mFetchSubtitleDataGeneration(0),
65      mFetchTimedTextDataGeneration(0),
66      mDurationUs(0ll),
67      mAudioIsVorbis(false) {
68    DataSource::RegisterDefaultSniffers();
69
70    sp<DataSource> dataSource = new FileSource(dup(fd), offset, length);
71
72    initFromDataSource(dataSource);
73}
74
75void NuPlayer::GenericSource::initFromDataSource(
76        const sp<DataSource> &dataSource) {
77    sp<MediaExtractor> extractor;
78
79    if (mIsWidevine) {
80        String8 mimeType;
81        float confidence;
82        sp<AMessage> dummy;
83        bool success;
84
85        success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
86        if (!success
87                || strcasecmp(
88                    mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
89            ALOGE("unsupported widevine mime: %s", mimeType.string());
90            return;
91        }
92
93        sp<WVMExtractor> wvmExtractor = new WVMExtractor(dataSource);
94        wvmExtractor->setAdaptiveStreamingMode(true);
95        if (mUIDValid) {
96            wvmExtractor->setUID(mUID);
97        }
98        extractor = wvmExtractor;
99    } else {
100        extractor = MediaExtractor::Create(dataSource);
101    }
102
103    CHECK(extractor != NULL);
104
105    sp<MetaData> fileMeta = extractor->getMetaData();
106    if (fileMeta != NULL) {
107        int64_t duration;
108        if (fileMeta->findInt64(kKeyDuration, &duration)) {
109            mDurationUs = duration;
110        }
111    }
112
113    for (size_t i = 0; i < extractor->countTracks(); ++i) {
114        sp<MetaData> meta = extractor->getTrackMetaData(i);
115
116        const char *mime;
117        CHECK(meta->findCString(kKeyMIMEType, &mime));
118
119        sp<MediaSource> track = extractor->getTrack(i);
120
121        if (!strncasecmp(mime, "audio/", 6)) {
122            if (mAudioTrack.mSource == NULL) {
123                mAudioTrack.mIndex = i;
124                mAudioTrack.mSource = track;
125
126                if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
127                    mAudioIsVorbis = true;
128                } else {
129                    mAudioIsVorbis = false;
130                }
131            }
132        } else if (!strncasecmp(mime, "video/", 6)) {
133            if (mVideoTrack.mSource == NULL) {
134                mVideoTrack.mIndex = i;
135                mVideoTrack.mSource = track;
136            }
137        }
138
139        if (track != NULL) {
140            CHECK_EQ(track->start(), (status_t)OK);
141            mSources.push(track);
142            int64_t durationUs;
143            if (meta->findInt64(kKeyDuration, &durationUs)) {
144                if (durationUs > mDurationUs) {
145                    mDurationUs = durationUs;
146                }
147            }
148        }
149    }
150}
151
152status_t NuPlayer::GenericSource::setBuffers(bool audio, Vector<MediaBuffer *> &buffers) {
153    if (mIsWidevine && !audio) {
154        return mVideoTrack.mSource->setBuffers(buffers);
155    }
156    return INVALID_OPERATION;
157}
158
159NuPlayer::GenericSource::~GenericSource() {
160}
161
162void NuPlayer::GenericSource::prepareAsync() {
163    if (mVideoTrack.mSource != NULL) {
164        sp<MetaData> meta = mVideoTrack.mSource->getFormat();
165
166        int32_t width, height;
167        CHECK(meta->findInt32(kKeyWidth, &width));
168        CHECK(meta->findInt32(kKeyHeight, &height));
169
170        notifyVideoSizeChanged(width, height);
171    }
172
173    notifyFlagsChanged(
174            (mIsWidevine ? FLAG_SECURE : 0)
175            | FLAG_CAN_PAUSE
176            | FLAG_CAN_SEEK_BACKWARD
177            | FLAG_CAN_SEEK_FORWARD
178            | FLAG_CAN_SEEK);
179
180    notifyPrepared();
181}
182
183void NuPlayer::GenericSource::start() {
184    ALOGI("start");
185
186    if (mAudioTrack.mSource != NULL) {
187        mAudioTrack.mPackets =
188            new AnotherPacketSource(mAudioTrack.mSource->getFormat());
189
190        readBuffer(MEDIA_TRACK_TYPE_AUDIO);
191    }
192
193    if (mVideoTrack.mSource != NULL) {
194        mVideoTrack.mPackets =
195            new AnotherPacketSource(mVideoTrack.mSource->getFormat());
196
197        readBuffer(MEDIA_TRACK_TYPE_VIDEO);
198    }
199}
200
201status_t NuPlayer::GenericSource::feedMoreTSData() {
202    return OK;
203}
204
205void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
206    switch (msg->what()) {
207      case kWhatFetchSubtitleData:
208      {
209          fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
210                  mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
211          break;
212      }
213
214      case kWhatFetchTimedTextData:
215      {
216          fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
217                  mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
218          break;
219      }
220
221      case kWhatSendSubtitleData:
222      {
223          sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
224                  mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
225          break;
226      }
227
228      case kWhatSendTimedTextData:
229      {
230          sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
231                  mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
232          break;
233      }
234
235      case kWhatChangeAVSource:
236      {
237          int32_t trackIndex;
238          CHECK(msg->findInt32("trackIndex", &trackIndex));
239          const sp<MediaSource> source = mSources.itemAt(trackIndex);
240
241          Track* track;
242          const char *mime;
243          media_track_type trackType, counterpartType;
244          sp<MetaData> meta = source->getFormat();
245          meta->findCString(kKeyMIMEType, &mime);
246          if (!strncasecmp(mime, "audio/", 6)) {
247              track = &mAudioTrack;
248              trackType = MEDIA_TRACK_TYPE_AUDIO;
249              counterpartType = MEDIA_TRACK_TYPE_VIDEO;;
250          } else {
251              CHECK(!strncasecmp(mime, "video/", 6));
252              track = &mVideoTrack;
253              trackType = MEDIA_TRACK_TYPE_VIDEO;
254              counterpartType = MEDIA_TRACK_TYPE_AUDIO;;
255          }
256
257
258          track->mSource = source;
259          track->mIndex = trackIndex;
260
261          status_t avail;
262          if (!track->mPackets->hasBufferAvailable(&avail)) {
263              // sync from other source
264              TRESPASS();
265              break;
266          }
267
268          int64_t timeUs, actualTimeUs;
269          const bool formatChange = true;
270          sp<AMessage> latestMeta = track->mPackets->getLatestMeta();
271          CHECK(latestMeta != NULL && latestMeta->findInt64("timeUs", &timeUs));
272          readBuffer(trackType, timeUs, &actualTimeUs, formatChange);
273          readBuffer(counterpartType, -1, NULL, formatChange);
274          ALOGV("timeUs %lld actualTimeUs %lld", timeUs, actualTimeUs);
275
276          break;
277      }
278
279      default:
280          Source::onMessageReceived(msg);
281          break;
282    }
283}
284
285void NuPlayer::GenericSource::fetchTextData(
286        uint32_t sendWhat,
287        media_track_type type,
288        int32_t curGen,
289        sp<AnotherPacketSource> packets,
290        sp<AMessage> msg) {
291    int32_t msgGeneration;
292    CHECK(msg->findInt32("generation", &msgGeneration));
293    if (msgGeneration != curGen) {
294        // stale
295        return;
296    }
297
298    int32_t avail;
299    if (packets->hasBufferAvailable(&avail)) {
300        return;
301    }
302
303    int64_t timeUs;
304    CHECK(msg->findInt64("timeUs", &timeUs));
305
306    int64_t subTimeUs;
307    readBuffer(type, timeUs, &subTimeUs);
308
309    int64_t delayUs = subTimeUs - timeUs;
310    if (msg->what() == kWhatFetchSubtitleData) {
311        const int64_t oneSecUs = 1000000ll;
312        delayUs -= oneSecUs;
313    }
314    sp<AMessage> msg2 = new AMessage(sendWhat, id());
315    msg2->setInt32("generation", msgGeneration);
316    msg2->post(delayUs < 0 ? 0 : delayUs);
317}
318
319void NuPlayer::GenericSource::sendTextData(
320        uint32_t what,
321        media_track_type type,
322        int32_t curGen,
323        sp<AnotherPacketSource> packets,
324        sp<AMessage> msg) {
325    int32_t msgGeneration;
326    CHECK(msg->findInt32("generation", &msgGeneration));
327    if (msgGeneration != curGen) {
328        // stale
329        return;
330    }
331
332    int64_t subTimeUs;
333    if (packets->nextBufferTime(&subTimeUs) != OK) {
334        return;
335    }
336
337    int64_t nextSubTimeUs;
338    readBuffer(type, -1, &nextSubTimeUs);
339
340    sp<ABuffer> buffer;
341    status_t dequeueStatus = packets->dequeueAccessUnit(&buffer);
342    if (dequeueStatus == OK) {
343        sp<AMessage> notify = dupNotify();
344        notify->setInt32("what", what);
345        notify->setBuffer("buffer", buffer);
346        notify->post();
347
348        const int64_t delayUs = nextSubTimeUs - subTimeUs;
349        msg->post(delayUs < 0 ? 0 : delayUs);
350    }
351}
352
353sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) {
354    sp<MediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
355
356    if (source == NULL) {
357        return NULL;
358    }
359
360    return source->getFormat();
361}
362
363status_t NuPlayer::GenericSource::dequeueAccessUnit(
364        bool audio, sp<ABuffer> *accessUnit) {
365    Track *track = audio ? &mAudioTrack : &mVideoTrack;
366
367    if (track->mSource == NULL) {
368        return -EWOULDBLOCK;
369    }
370
371    if (mIsWidevine && !audio) {
372        // try to read a buffer as we may not have been able to the last time
373        readBuffer(MEDIA_TRACK_TYPE_AUDIO, -1ll);
374    }
375
376    status_t finalResult;
377    if (!track->mPackets->hasBufferAvailable(&finalResult)) {
378        return (finalResult == OK ? -EWOULDBLOCK : finalResult);
379    }
380
381    status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
382
383    if (!track->mPackets->hasBufferAvailable(&finalResult)) {
384        readBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO, -1ll);
385    }
386
387    if (mSubtitleTrack.mSource == NULL && mTimedTextTrack.mSource == NULL) {
388        return result;
389    }
390
391    if (mSubtitleTrack.mSource != NULL) {
392        CHECK(mSubtitleTrack.mPackets != NULL);
393    }
394    if (mTimedTextTrack.mSource != NULL) {
395        CHECK(mTimedTextTrack.mPackets != NULL);
396    }
397
398    if (result != OK) {
399        if (mSubtitleTrack.mSource != NULL) {
400            mSubtitleTrack.mPackets->clear();
401            mFetchSubtitleDataGeneration++;
402        }
403        if (mTimedTextTrack.mSource != NULL) {
404            mTimedTextTrack.mPackets->clear();
405            mFetchTimedTextDataGeneration++;
406        }
407        return result;
408    }
409
410    int64_t timeUs;
411    status_t eosResult; // ignored
412    CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
413
414    if (mSubtitleTrack.mSource != NULL
415            && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
416        sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, id());
417        msg->setInt64("timeUs", timeUs);
418        msg->setInt32("generation", mFetchSubtitleDataGeneration);
419        msg->post();
420    }
421
422    if (mTimedTextTrack.mSource != NULL
423            && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
424        sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, id());
425        msg->setInt64("timeUs", timeUs);
426        msg->setInt32("generation", mFetchTimedTextDataGeneration);
427        msg->post();
428    }
429
430    return result;
431}
432
433status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) {
434    *durationUs = mDurationUs;
435    return OK;
436}
437
438size_t NuPlayer::GenericSource::getTrackCount() const {
439    return mSources.size();
440}
441
442sp<AMessage> NuPlayer::GenericSource::getTrackInfo(size_t trackIndex) const {
443    size_t trackCount = mSources.size();
444    if (trackIndex >= trackCount) {
445        return NULL;
446    }
447
448    sp<AMessage> format = new AMessage();
449    sp<MetaData> meta = mSources.itemAt(trackIndex)->getFormat();
450
451    const char *mime;
452    CHECK(meta->findCString(kKeyMIMEType, &mime));
453
454    int32_t trackType;
455    if (!strncasecmp(mime, "video/", 6)) {
456        trackType = MEDIA_TRACK_TYPE_VIDEO;
457    } else if (!strncasecmp(mime, "audio/", 6)) {
458        trackType = MEDIA_TRACK_TYPE_AUDIO;
459    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
460        trackType = MEDIA_TRACK_TYPE_TIMEDTEXT;
461    } else {
462        trackType = MEDIA_TRACK_TYPE_UNKNOWN;
463    }
464    format->setInt32("type", trackType);
465
466    const char *lang;
467    if (!meta->findCString(kKeyMediaLanguage, &lang)) {
468        lang = "und";
469    }
470    format->setString("language", lang);
471
472    if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
473        format->setString("mime", mime);
474
475        int32_t isAutoselect = 1, isDefault = 0, isForced = 0;
476        meta->findInt32(kKeyTrackIsAutoselect, &isAutoselect);
477        meta->findInt32(kKeyTrackIsDefault, &isDefault);
478        meta->findInt32(kKeyTrackIsForced, &isForced);
479
480        format->setInt32("auto", !!isAutoselect);
481        format->setInt32("default", !!isDefault);
482        format->setInt32("forced", !!isForced);
483    }
484
485    return format;
486}
487
488ssize_t NuPlayer::GenericSource::getSelectedTrack(media_track_type type) const {
489    const Track *track = NULL;
490    switch (type) {
491    case MEDIA_TRACK_TYPE_VIDEO:
492        track = &mVideoTrack;
493        break;
494    case MEDIA_TRACK_TYPE_AUDIO:
495        track = &mAudioTrack;
496        break;
497    case MEDIA_TRACK_TYPE_TIMEDTEXT:
498        track = &mTimedTextTrack;
499        break;
500    case MEDIA_TRACK_TYPE_SUBTITLE:
501        track = &mSubtitleTrack;
502        break;
503    default:
504        break;
505    }
506
507    if (track != NULL && track->mSource != NULL) {
508        return track->mIndex;
509    }
510
511    return -1;
512}
513
514status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select) {
515    ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex);
516    if (trackIndex >= mSources.size()) {
517        return BAD_INDEX;
518    }
519
520    if (!select) {
521        Track* track = NULL;
522        if (mSubtitleTrack.mSource != NULL && trackIndex == mSubtitleTrack.mIndex) {
523            track = &mSubtitleTrack;
524            mFetchSubtitleDataGeneration++;
525        } else if (mTimedTextTrack.mSource != NULL && trackIndex == mTimedTextTrack.mIndex) {
526            track = &mTimedTextTrack;
527            mFetchTimedTextDataGeneration++;
528        }
529        if (track == NULL) {
530            return INVALID_OPERATION;
531        }
532        track->mSource = NULL;
533        track->mPackets->clear();
534        return OK;
535    }
536
537    const sp<MediaSource> source = mSources.itemAt(trackIndex);
538    sp<MetaData> meta = source->getFormat();
539    const char *mime;
540    CHECK(meta->findCString(kKeyMIMEType, &mime));
541    if (!strncasecmp(mime, "text/", 5)) {
542        bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP);
543        Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack;
544        if (track->mSource != NULL && track->mIndex == trackIndex) {
545            return OK;
546        }
547        track->mIndex = trackIndex;
548        track->mSource = mSources.itemAt(trackIndex);
549        if (track->mPackets == NULL) {
550            track->mPackets = new AnotherPacketSource(track->mSource->getFormat());
551        } else {
552            track->mPackets->clear();
553            track->mPackets->setFormat(track->mSource->getFormat());
554
555        }
556
557        if (isSubtitle) {
558            mFetchSubtitleDataGeneration++;
559        } else {
560            mFetchTimedTextDataGeneration++;
561        }
562
563        return OK;
564    } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) {
565        bool audio = !strncasecmp(mime, "audio/", 6);
566        Track *track = audio ? &mAudioTrack : &mVideoTrack;
567        if (track->mSource != NULL && track->mIndex == trackIndex) {
568            return OK;
569        }
570
571        sp<AMessage> msg = new AMessage(kWhatChangeAVSource, id());
572        msg->setInt32("trackIndex", trackIndex);
573        msg->post();
574        return OK;
575    }
576
577    return INVALID_OPERATION;
578}
579
580status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs) {
581    if (mVideoTrack.mSource != NULL) {
582        int64_t actualTimeUs;
583        readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, &actualTimeUs);
584
585        seekTimeUs = actualTimeUs;
586    }
587
588    if (mAudioTrack.mSource != NULL) {
589        readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs);
590    }
591
592    return OK;
593}
594
595sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer(
596        MediaBuffer* mb,
597        media_track_type trackType,
598        int64_t *actualTimeUs) {
599    bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
600    size_t outLength = mb->range_length();
601
602    if (audio && mAudioIsVorbis) {
603        outLength += sizeof(int32_t);
604    }
605
606    sp<ABuffer> ab;
607    if (mIsWidevine && !audio) {
608        // data is already provided in the buffer
609        ab = new ABuffer(NULL, mb->range_length());
610        ab->meta()->setPointer("mediaBuffer", mb);
611        mb->add_ref();
612    } else {
613        ab = new ABuffer(outLength);
614        memcpy(ab->data(),
615               (const uint8_t *)mb->data() + mb->range_offset(),
616               mb->range_length());
617    }
618
619    if (audio && mAudioIsVorbis) {
620        int32_t numPageSamples;
621        if (!mb->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) {
622            numPageSamples = -1;
623        }
624
625        uint8_t* abEnd = ab->data() + mb->range_length();
626        memcpy(abEnd, &numPageSamples, sizeof(numPageSamples));
627    }
628
629    sp<AMessage> meta = ab->meta();
630
631    int64_t timeUs;
632    CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs));
633    meta->setInt64("timeUs", timeUs);
634
635    if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
636        const char *mime;
637        CHECK(mTimedTextTrack.mSource != NULL
638                && mTimedTextTrack.mSource->getFormat()->findCString(kKeyMIMEType, &mime));
639        meta->setString("mime", mime);
640    }
641
642    int64_t durationUs;
643    if (mb->meta_data()->findInt64(kKeyDuration, &durationUs)) {
644        meta->setInt64("durationUs", durationUs);
645    }
646
647    if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
648        meta->setInt32("trackIndex", mSubtitleTrack.mIndex);
649    }
650
651    if (actualTimeUs) {
652        *actualTimeUs = timeUs;
653    }
654
655    mb->release();
656    mb = NULL;
657
658    return ab;
659}
660
661void NuPlayer::GenericSource::readBuffer(
662        media_track_type trackType, int64_t seekTimeUs, int64_t *actualTimeUs, bool formatChange) {
663    Track *track;
664    switch (trackType) {
665        case MEDIA_TRACK_TYPE_VIDEO:
666            track = &mVideoTrack;
667            break;
668        case MEDIA_TRACK_TYPE_AUDIO:
669            track = &mAudioTrack;
670            break;
671        case MEDIA_TRACK_TYPE_SUBTITLE:
672            track = &mSubtitleTrack;
673            break;
674        case MEDIA_TRACK_TYPE_TIMEDTEXT:
675            track = &mTimedTextTrack;
676            break;
677        default:
678            TRESPASS();
679    }
680
681    if (track->mSource == NULL) {
682        return;
683    }
684
685    if (actualTimeUs) {
686        *actualTimeUs = seekTimeUs;
687    }
688
689    MediaSource::ReadOptions options;
690
691    bool seeking = false;
692
693    if (seekTimeUs >= 0) {
694        options.setSeekTo(seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
695        seeking = true;
696    }
697
698    if (mIsWidevine && trackType != MEDIA_TRACK_TYPE_AUDIO) {
699        options.setNonBlocking();
700    }
701
702    for (;;) {
703        MediaBuffer *mbuf;
704        status_t err = track->mSource->read(&mbuf, &options);
705
706        options.clearSeekTo();
707
708        if (err == OK) {
709            // formatChange && seeking: track whose source is changed during selection
710            // formatChange && !seeking: track whose source is not changed during selection
711            // !formatChange: normal seek
712            if ((seeking || formatChange)
713                    && (trackType == MEDIA_TRACK_TYPE_AUDIO
714                    || trackType == MEDIA_TRACK_TYPE_VIDEO)) {
715                ATSParser::DiscontinuityType type = formatChange
716                        ? (seeking
717                                ? ATSParser::DISCONTINUITY_FORMATCHANGE
718                                : ATSParser::DISCONTINUITY_NONE)
719                        : ATSParser::DISCONTINUITY_SEEK;
720                track->mPackets->queueDiscontinuity( type, NULL, true /* discard */);
721            }
722
723            sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType, actualTimeUs);
724            track->mPackets->queueAccessUnit(buffer);
725            break;
726        } else if (err == WOULD_BLOCK) {
727            break;
728        } else if (err == INFO_FORMAT_CHANGED) {
729#if 0
730            track->mPackets->queueDiscontinuity(
731                    ATSParser::DISCONTINUITY_FORMATCHANGE,
732                    NULL,
733                    false /* discard */);
734#endif
735        } else {
736            track->mPackets->signalEOS(err);
737            break;
738        }
739    }
740}
741
742}  // namespace android
743