Home | History | Annotate | Download | only in mpeg2ts
      1 /*
      2  * Copyright (C) 2010 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 "MPEG2TSExtractor"
     19 
     20 #include <inttypes.h>
     21 #include <utils/Log.h>
     22 
     23 #include "include/MPEG2TSExtractor.h"
     24 #include "include/NuCachedSource2.h"
     25 
     26 #include <media/stagefright/foundation/ABuffer.h>
     27 #include <media/stagefright/foundation/ADebug.h>
     28 #include <media/stagefright/foundation/ALooper.h>
     29 #include <media/stagefright/foundation/AUtils.h>
     30 #include <media/stagefright/DataSource.h>
     31 #include <media/stagefright/MediaDefs.h>
     32 #include <media/stagefright/MediaErrors.h>
     33 #include <media/stagefright/MediaSource.h>
     34 #include <media/stagefright/MetaData.h>
     35 #include <media/IStreamSource.h>
     36 #include <utils/String8.h>
     37 
     38 #include "AnotherPacketSource.h"
     39 #include "ATSParser.h"
     40 
     41 #include <hidl/HybridInterface.h>
     42 #include <android/hardware/cas/1.0/ICas.h>
     43 
     44 namespace android {
     45 
     46 using hardware::cas::V1_0::ICas;
     47 
     48 static const size_t kTSPacketSize = 188;
     49 static const int kMaxDurationReadSize = 250000LL;
     50 static const int kMaxDurationRetry = 6;
     51 
     52 struct MPEG2TSSource : public MediaSource {
     53     MPEG2TSSource(
     54             const sp<MPEG2TSExtractor> &extractor,
     55             const sp<AnotherPacketSource> &impl,
     56             bool doesSeek);
     57 
     58     virtual status_t start(MetaData *params = NULL);
     59     virtual status_t stop();
     60     virtual sp<MetaData> getFormat();
     61 
     62     virtual status_t read(
     63             MediaBuffer **buffer, const ReadOptions *options = NULL);
     64 
     65 private:
     66     sp<MPEG2TSExtractor> mExtractor;
     67     sp<AnotherPacketSource> mImpl;
     68 
     69     // If there are both audio and video streams, only the video stream
     70     // will signal seek on the extractor; otherwise the single stream will seek.
     71     bool mDoesSeek;
     72 
     73     DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSSource);
     74 };
     75 
     76 MPEG2TSSource::MPEG2TSSource(
     77         const sp<MPEG2TSExtractor> &extractor,
     78         const sp<AnotherPacketSource> &impl,
     79         bool doesSeek)
     80     : mExtractor(extractor),
     81       mImpl(impl),
     82       mDoesSeek(doesSeek) {
     83 }
     84 
     85 status_t MPEG2TSSource::start(MetaData *params) {
     86     return mImpl->start(params);
     87 }
     88 
     89 status_t MPEG2TSSource::stop() {
     90     return mImpl->stop();
     91 }
     92 
     93 sp<MetaData> MPEG2TSSource::getFormat() {
     94     return mImpl->getFormat();
     95 }
     96 
     97 status_t MPEG2TSSource::read(
     98         MediaBuffer **out, const ReadOptions *options) {
     99     *out = NULL;
    100 
    101     int64_t seekTimeUs;
    102     ReadOptions::SeekMode seekMode;
    103     if (mDoesSeek && options && options->getSeekTo(&seekTimeUs, &seekMode)) {
    104         // seek is needed
    105         status_t err = mExtractor->seek(seekTimeUs, seekMode);
    106         if (err != OK) {
    107             return err;
    108         }
    109     }
    110 
    111     if (mExtractor->feedUntilBufferAvailable(mImpl) != OK) {
    112         return ERROR_END_OF_STREAM;
    113     }
    114 
    115     return mImpl->read(out, options);
    116 }
    117 
    118 ////////////////////////////////////////////////////////////////////////////////
    119 
    120 MPEG2TSExtractor::MPEG2TSExtractor(const sp<DataSource> &source)
    121     : mDataSource(source),
    122       mParser(new ATSParser),
    123       mLastSyncEvent(0),
    124       mOffset(0) {
    125     init();
    126 }
    127 
    128 size_t MPEG2TSExtractor::countTracks() {
    129     return mSourceImpls.size();
    130 }
    131 
    132 sp<IMediaSource> MPEG2TSExtractor::getTrack(size_t index) {
    133     if (index >= mSourceImpls.size()) {
    134         return NULL;
    135     }
    136 
    137     // The seek reference track (video if present; audio otherwise) performs
    138     // seek requests, while other tracks ignore requests.
    139     return new MPEG2TSSource(this, mSourceImpls.editItemAt(index),
    140             (mSeekSyncPoints == &mSyncPoints.editItemAt(index)));
    141 }
    142 
    143 sp<MetaData> MPEG2TSExtractor::getTrackMetaData(
    144         size_t index, uint32_t /* flags */) {
    145     return index < mSourceImpls.size()
    146         ? mSourceImpls.editItemAt(index)->getFormat() : NULL;
    147 }
    148 
    149 sp<MetaData> MPEG2TSExtractor::getMetaData() {
    150     sp<MetaData> meta = new MetaData;
    151     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
    152 
    153     return meta;
    154 }
    155 
    156 //static
    157 bool MPEG2TSExtractor::isScrambledFormat(const sp<MetaData> &format) {
    158     const char *mime;
    159     return format->findCString(kKeyMIMEType, &mime)
    160             && (!strcasecmp(MEDIA_MIMETYPE_VIDEO_SCRAMBLED, mime)
    161                     || !strcasecmp(MEDIA_MIMETYPE_AUDIO_SCRAMBLED, mime));
    162 }
    163 
    164 status_t MPEG2TSExtractor::setMediaCas(const HInterfaceToken &casToken) {
    165     HalToken halToken;
    166     halToken.setToExternal((uint8_t*)casToken.data(), casToken.size());
    167     sp<ICas> cas = ICas::castFrom(retrieveHalInterface(halToken));
    168     ALOGD("setMediaCas: %p", cas.get());
    169 
    170     status_t err = mParser->setMediaCas(cas);
    171     if (err == OK) {
    172         ALOGI("All tracks now have descramblers");
    173         init();
    174     }
    175     return err;
    176 }
    177 
    178 void MPEG2TSExtractor::addSource(const sp<AnotherPacketSource> &impl) {
    179     bool found = false;
    180     for (size_t i = 0; i < mSourceImpls.size(); i++) {
    181         if (mSourceImpls[i] == impl) {
    182             found = true;
    183             break;
    184         }
    185     }
    186     if (!found) {
    187         mSourceImpls.push(impl);
    188     }
    189 }
    190 
    191 void MPEG2TSExtractor::init() {
    192     bool haveAudio = false;
    193     bool haveVideo = false;
    194     int64_t startTime = ALooper::GetNowUs();
    195 
    196     status_t err;
    197     while ((err = feedMore(true /* isInit */)) == OK
    198             || err == ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED) {
    199         if (haveAudio && haveVideo) {
    200             addSyncPoint_l(mLastSyncEvent);
    201             mLastSyncEvent.reset();
    202             break;
    203         }
    204         if (!haveVideo) {
    205             sp<AnotherPacketSource> impl =
    206                 (AnotherPacketSource *)mParser->getSource(
    207                         ATSParser::VIDEO).get();
    208 
    209             if (impl != NULL) {
    210                 sp<MetaData> format = impl->getFormat();
    211                 if (format != NULL) {
    212                     haveVideo = true;
    213                     addSource(impl);
    214                     if (!isScrambledFormat(format)) {
    215                         mSyncPoints.push();
    216                         mSeekSyncPoints = &mSyncPoints.editTop();
    217                     }
    218                 }
    219             }
    220         }
    221 
    222         if (!haveAudio) {
    223             sp<AnotherPacketSource> impl =
    224                 (AnotherPacketSource *)mParser->getSource(
    225                         ATSParser::AUDIO).get();
    226 
    227             if (impl != NULL) {
    228                 sp<MetaData> format = impl->getFormat();
    229                 if (format != NULL) {
    230                     haveAudio = true;
    231                     addSource(impl);
    232                     if (!isScrambledFormat(format)) {
    233                         mSyncPoints.push();
    234                         if (!haveVideo) {
    235                             mSeekSyncPoints = &mSyncPoints.editTop();
    236                         }
    237                     }
    238                 }
    239             }
    240         }
    241 
    242         addSyncPoint_l(mLastSyncEvent);
    243         mLastSyncEvent.reset();
    244 
    245         // ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED is returned when the mpeg2ts
    246         // is scrambled but we don't have a MediaCas object set. The extraction
    247         // will only continue when setMediaCas() is called successfully.
    248         if (err == ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED) {
    249             ALOGI("stopped parsing scrambled content, "
    250                   "haveAudio=%d, haveVideo=%d, elaspedTime=%" PRId64,
    251                     haveAudio, haveVideo, ALooper::GetNowUs() - startTime);
    252             return;
    253         }
    254 
    255         // Wait only for 2 seconds to detect audio/video streams.
    256         if (ALooper::GetNowUs() - startTime > 2000000ll) {
    257             break;
    258         }
    259     }
    260 
    261     off64_t size;
    262     if (mDataSource->getSize(&size) == OK && (haveAudio || haveVideo)) {
    263         sp<AnotherPacketSource> impl = haveVideo
    264                 ? (AnotherPacketSource *)mParser->getSource(
    265                         ATSParser::VIDEO).get()
    266                 : (AnotherPacketSource *)mParser->getSource(
    267                         ATSParser::AUDIO).get();
    268         size_t prevSyncSize = 1;
    269         int64_t durationUs = -1;
    270         List<int64_t> durations;
    271         // Estimate duration --- stabilize until you get <500ms deviation.
    272         while (feedMore() == OK
    273                 && ALooper::GetNowUs() - startTime <= 2000000ll) {
    274             if (mSeekSyncPoints->size() > prevSyncSize) {
    275                 prevSyncSize = mSeekSyncPoints->size();
    276                 int64_t diffUs = mSeekSyncPoints->keyAt(prevSyncSize - 1)
    277                         - mSeekSyncPoints->keyAt(0);
    278                 off64_t diffOffset = mSeekSyncPoints->valueAt(prevSyncSize - 1)
    279                         - mSeekSyncPoints->valueAt(0);
    280                 int64_t currentDurationUs = size * diffUs / diffOffset;
    281                 durations.push_back(currentDurationUs);
    282                 if (durations.size() > 5) {
    283                     durations.erase(durations.begin());
    284                     int64_t min = *durations.begin();
    285                     int64_t max = *durations.begin();
    286                     for (auto duration : durations) {
    287                         if (min > duration) {
    288                             min = duration;
    289                         }
    290                         if (max < duration) {
    291                             max = duration;
    292                         }
    293                     }
    294                     if (max - min < 500 * 1000) {
    295                         durationUs = currentDurationUs;
    296                         break;
    297                     }
    298                 }
    299             }
    300         }
    301         status_t err;
    302         int64_t bufferedDurationUs;
    303         bufferedDurationUs = impl->getBufferedDurationUs(&err);
    304         if (err == ERROR_END_OF_STREAM) {
    305             durationUs = bufferedDurationUs;
    306         }
    307         if (durationUs > 0) {
    308             const sp<MetaData> meta = impl->getFormat();
    309             meta->setInt64(kKeyDuration, durationUs);
    310             impl->setFormat(meta);
    311         } else {
    312             estimateDurationsFromTimesUsAtEnd();
    313         }
    314     }
    315 
    316     ALOGI("haveAudio=%d, haveVideo=%d, elaspedTime=%" PRId64,
    317             haveAudio, haveVideo, ALooper::GetNowUs() - startTime);
    318 }
    319 
    320 status_t MPEG2TSExtractor::feedMore(bool isInit) {
    321     Mutex::Autolock autoLock(mLock);
    322 
    323     uint8_t packet[kTSPacketSize];
    324     ssize_t n = mDataSource->readAt(mOffset, packet, kTSPacketSize);
    325 
    326     if (n < (ssize_t)kTSPacketSize) {
    327         if (n >= 0) {
    328             mParser->signalEOS(ERROR_END_OF_STREAM);
    329         }
    330         return (n < 0) ? (status_t)n : ERROR_END_OF_STREAM;
    331     }
    332 
    333     ATSParser::SyncEvent event(mOffset);
    334     mOffset += n;
    335     status_t err = mParser->feedTSPacket(packet, kTSPacketSize, &event);
    336     if (event.hasReturnedData()) {
    337         if (isInit) {
    338             mLastSyncEvent = event;
    339         } else {
    340             addSyncPoint_l(event);
    341         }
    342     }
    343     return err;
    344 }
    345 
    346 void MPEG2TSExtractor::addSyncPoint_l(const ATSParser::SyncEvent &event) {
    347     if (!event.hasReturnedData()) {
    348         return;
    349     }
    350 
    351     for (size_t i = 0; i < mSourceImpls.size(); ++i) {
    352         if (mSourceImpls[i].get() == event.getMediaSource().get()) {
    353             KeyedVector<int64_t, off64_t> *syncPoints = &mSyncPoints.editItemAt(i);
    354             syncPoints->add(event.getTimeUs(), event.getOffset());
    355             // We're keeping the size of the sync points at most 5mb per a track.
    356             size_t size = syncPoints->size();
    357             if (size >= 327680) {
    358                 int64_t firstTimeUs = syncPoints->keyAt(0);
    359                 int64_t lastTimeUs = syncPoints->keyAt(size - 1);
    360                 if (event.getTimeUs() - firstTimeUs > lastTimeUs - event.getTimeUs()) {
    361                     syncPoints->removeItemsAt(0, 4096);
    362                 } else {
    363                     syncPoints->removeItemsAt(size - 4096, 4096);
    364                 }
    365             }
    366             break;
    367         }
    368     }
    369 }
    370 
    371 status_t MPEG2TSExtractor::estimateDurationsFromTimesUsAtEnd()  {
    372     if (!(mDataSource->flags() & DataSource::kIsLocalFileSource)) {
    373         return ERROR_UNSUPPORTED;
    374     }
    375 
    376     off64_t size = 0;
    377     status_t err = mDataSource->getSize(&size);
    378     if (err != OK) {
    379         return err;
    380     }
    381 
    382     uint8_t packet[kTSPacketSize];
    383     const off64_t zero = 0;
    384     off64_t offset = max(zero, size - kMaxDurationReadSize);
    385     if (mDataSource->readAt(offset, &packet, 0) < 0) {
    386         return ERROR_IO;
    387     }
    388 
    389     int retry = 0;
    390     bool allDurationsFound = false;
    391     int64_t timeAnchorUs = mParser->getFirstPTSTimeUs();
    392     do {
    393         int bytesRead = 0;
    394         sp<ATSParser> parser = new ATSParser(ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE);
    395         ATSParser::SyncEvent ev(0);
    396         offset = max(zero, size - (kMaxDurationReadSize << retry));
    397         offset = (offset / kTSPacketSize) * kTSPacketSize;
    398         for (;;) {
    399             if (bytesRead >= kMaxDurationReadSize << max(0, retry - 1)) {
    400                 break;
    401             }
    402 
    403             ssize_t n = mDataSource->readAt(offset, packet, kTSPacketSize);
    404             if (n < 0) {
    405                 return n;
    406             } else if (n < (ssize_t)kTSPacketSize) {
    407                 break;
    408             }
    409 
    410             offset += kTSPacketSize;
    411             bytesRead += kTSPacketSize;
    412             err = parser->feedTSPacket(packet, kTSPacketSize, &ev);
    413             if (err != OK) {
    414                 return err;
    415             }
    416 
    417             if (ev.hasReturnedData()) {
    418                 int64_t durationUs = ev.getTimeUs();
    419                 ATSParser::SourceType type = ev.getType();
    420                 ev.reset();
    421 
    422                 int64_t firstTimeUs;
    423                 sp<AnotherPacketSource> src =
    424                     (AnotherPacketSource *)mParser->getSource(type).get();
    425                 if (src == NULL || src->nextBufferTime(&firstTimeUs) != OK) {
    426                     continue;
    427                 }
    428                 durationUs += src->getEstimatedBufferDurationUs();
    429                 durationUs -= timeAnchorUs;
    430                 durationUs -= firstTimeUs;
    431                 if (durationUs > 0) {
    432                     int64_t origDurationUs, lastDurationUs;
    433                     const sp<MetaData> meta = src->getFormat();
    434                     const uint32_t kKeyLastDuration = 'ldur';
    435                     // Require two consecutive duration calculations to be within 1 sec before
    436                     // updating; use MetaData to store previous duration estimate in per-stream
    437                     // context.
    438                     if (!meta->findInt64(kKeyDuration, &origDurationUs)
    439                             || !meta->findInt64(kKeyLastDuration, &lastDurationUs)
    440                             || (origDurationUs < durationUs
    441                              && abs(durationUs - lastDurationUs) < 60000000)) {
    442                         meta->setInt64(kKeyDuration, durationUs);
    443                     }
    444                     meta->setInt64(kKeyLastDuration, durationUs);
    445                 }
    446             }
    447         }
    448 
    449         if (!allDurationsFound) {
    450             allDurationsFound = true;
    451             for (auto t: {ATSParser::VIDEO, ATSParser::AUDIO}) {
    452                 sp<AnotherPacketSource> src = (AnotherPacketSource *)mParser->getSource(t).get();
    453                 if (src == NULL) {
    454                     continue;
    455                 }
    456                 int64_t durationUs;
    457                 const sp<MetaData> meta = src->getFormat();
    458                 if (!meta->findInt64(kKeyDuration, &durationUs)) {
    459                     allDurationsFound = false;
    460                     break;
    461                 }
    462             }
    463         }
    464 
    465         ++retry;
    466     } while(!allDurationsFound && offset > 0 && retry <= kMaxDurationRetry);
    467 
    468     return allDurationsFound? OK : ERROR_UNSUPPORTED;
    469 }
    470 
    471 uint32_t MPEG2TSExtractor::flags() const {
    472     return CAN_PAUSE | CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD;
    473 }
    474 
    475 status_t MPEG2TSExtractor::seek(int64_t seekTimeUs,
    476         const MediaSource::ReadOptions::SeekMode &seekMode) {
    477     if (mSeekSyncPoints == NULL || mSeekSyncPoints->isEmpty()) {
    478         ALOGW("No sync point to seek to.");
    479         // ... and therefore we have nothing useful to do here.
    480         return OK;
    481     }
    482 
    483     // Determine whether we're seeking beyond the known area.
    484     bool shouldSeekBeyond =
    485             (seekTimeUs > mSeekSyncPoints->keyAt(mSeekSyncPoints->size() - 1));
    486 
    487     // Determine the sync point to seek.
    488     size_t index = 0;
    489     for (; index < mSeekSyncPoints->size(); ++index) {
    490         int64_t timeUs = mSeekSyncPoints->keyAt(index);
    491         if (timeUs > seekTimeUs) {
    492             break;
    493         }
    494     }
    495 
    496     switch (seekMode) {
    497         case MediaSource::ReadOptions::SEEK_NEXT_SYNC:
    498             if (index == mSeekSyncPoints->size()) {
    499                 ALOGW("Next sync not found; starting from the latest sync.");
    500                 --index;
    501             }
    502             break;
    503         case MediaSource::ReadOptions::SEEK_CLOSEST_SYNC:
    504         case MediaSource::ReadOptions::SEEK_CLOSEST:
    505             ALOGW("seekMode not supported: %d; falling back to PREVIOUS_SYNC",
    506                     seekMode);
    507             // fall-through
    508         case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC:
    509             if (index == 0) {
    510                 ALOGW("Previous sync not found; starting from the earliest "
    511                         "sync.");
    512             } else {
    513                 --index;
    514             }
    515             break;
    516     }
    517     if (!shouldSeekBeyond || mOffset <= mSeekSyncPoints->valueAt(index)) {
    518         int64_t actualSeekTimeUs = mSeekSyncPoints->keyAt(index);
    519         mOffset = mSeekSyncPoints->valueAt(index);
    520         status_t err = queueDiscontinuityForSeek(actualSeekTimeUs);
    521         if (err != OK) {
    522             return err;
    523         }
    524     }
    525 
    526     if (shouldSeekBeyond) {
    527         status_t err = seekBeyond(seekTimeUs);
    528         if (err != OK) {
    529             return err;
    530         }
    531     }
    532 
    533     // Fast-forward to sync frame.
    534     for (size_t i = 0; i < mSourceImpls.size(); ++i) {
    535         const sp<AnotherPacketSource> &impl = mSourceImpls[i];
    536         status_t err;
    537         feedUntilBufferAvailable(impl);
    538         while (impl->hasBufferAvailable(&err)) {
    539             sp<AMessage> meta = impl->getMetaAfterLastDequeued(0);
    540             sp<ABuffer> buffer;
    541             if (meta == NULL) {
    542                 return UNKNOWN_ERROR;
    543             }
    544             int32_t sync;
    545             if (meta->findInt32("isSync", &sync) && sync) {
    546                 break;
    547             }
    548             err = impl->dequeueAccessUnit(&buffer);
    549             if (err != OK) {
    550                 return err;
    551             }
    552             feedUntilBufferAvailable(impl);
    553         }
    554     }
    555 
    556     return OK;
    557 }
    558 
    559 status_t MPEG2TSExtractor::queueDiscontinuityForSeek(int64_t actualSeekTimeUs) {
    560     // Signal discontinuity
    561     sp<AMessage> extra(new AMessage);
    562     extra->setInt64(IStreamListener::kKeyMediaTimeUs, actualSeekTimeUs);
    563     mParser->signalDiscontinuity(ATSParser::DISCONTINUITY_TIME, extra);
    564 
    565     // After discontinuity, impl should only have discontinuities
    566     // with the last being what we queued. Dequeue them all here.
    567     for (size_t i = 0; i < mSourceImpls.size(); ++i) {
    568         const sp<AnotherPacketSource> &impl = mSourceImpls.itemAt(i);
    569         sp<ABuffer> buffer;
    570         status_t err;
    571         while (impl->hasBufferAvailable(&err)) {
    572             if (err != OK) {
    573                 return err;
    574             }
    575             err = impl->dequeueAccessUnit(&buffer);
    576             // If the source contains anything but discontinuity, that's
    577             // a programming mistake.
    578             CHECK(err == INFO_DISCONTINUITY);
    579         }
    580     }
    581 
    582     // Feed until we have a buffer for each source.
    583     for (size_t i = 0; i < mSourceImpls.size(); ++i) {
    584         const sp<AnotherPacketSource> &impl = mSourceImpls.itemAt(i);
    585         sp<ABuffer> buffer;
    586         status_t err = feedUntilBufferAvailable(impl);
    587         if (err != OK) {
    588             return err;
    589         }
    590     }
    591 
    592     return OK;
    593 }
    594 
    595 status_t MPEG2TSExtractor::seekBeyond(int64_t seekTimeUs) {
    596     // If we're seeking beyond where we know --- read until we reach there.
    597     size_t syncPointsSize = mSeekSyncPoints->size();
    598 
    599     while (seekTimeUs > mSeekSyncPoints->keyAt(
    600             mSeekSyncPoints->size() - 1)) {
    601         status_t err;
    602         if (syncPointsSize < mSeekSyncPoints->size()) {
    603             syncPointsSize = mSeekSyncPoints->size();
    604             int64_t syncTimeUs = mSeekSyncPoints->keyAt(syncPointsSize - 1);
    605             // Dequeue buffers before sync point in order to avoid too much
    606             // cache building up.
    607             sp<ABuffer> buffer;
    608             for (size_t i = 0; i < mSourceImpls.size(); ++i) {
    609                 const sp<AnotherPacketSource> &impl = mSourceImpls[i];
    610                 int64_t timeUs;
    611                 while ((err = impl->nextBufferTime(&timeUs)) == OK) {
    612                     if (timeUs < syncTimeUs) {
    613                         impl->dequeueAccessUnit(&buffer);
    614                     } else {
    615                         break;
    616                     }
    617                 }
    618                 if (err != OK && err != -EWOULDBLOCK) {
    619                     return err;
    620                 }
    621             }
    622         }
    623         if (feedMore() != OK) {
    624             return ERROR_END_OF_STREAM;
    625         }
    626     }
    627 
    628     return OK;
    629 }
    630 
    631 status_t MPEG2TSExtractor::feedUntilBufferAvailable(
    632         const sp<AnotherPacketSource> &impl) {
    633     status_t finalResult;
    634     while (!impl->hasBufferAvailable(&finalResult)) {
    635         if (finalResult != OK) {
    636             return finalResult;
    637         }
    638 
    639         status_t err = feedMore();
    640         if (err != OK) {
    641             impl->signalEOS(err);
    642         }
    643     }
    644     return OK;
    645 }
    646 
    647 ////////////////////////////////////////////////////////////////////////////////
    648 
    649 bool SniffMPEG2TS(
    650         const sp<DataSource> &source, String8 *mimeType, float *confidence,
    651         sp<AMessage> *) {
    652     for (int i = 0; i < 5; ++i) {
    653         char header;
    654         if (source->readAt(kTSPacketSize * i, &header, 1) != 1
    655                 || header != 0x47) {
    656             return false;
    657         }
    658     }
    659 
    660     *confidence = 0.1f;
    661     mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
    662 
    663     return true;
    664 }
    665 
    666 }  // namespace android
    667