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 "AnotherPacketSource"
     19 
     20 #include "AnotherPacketSource.h"
     21 
     22 #include "include/avc_utils.h"
     23 
     24 #include <media/stagefright/foundation/ABuffer.h>
     25 #include <media/stagefright/foundation/ADebug.h>
     26 #include <media/stagefright/foundation/AMessage.h>
     27 #include <media/stagefright/foundation/AString.h>
     28 #include <media/stagefright/foundation/hexdump.h>
     29 #include <media/stagefright/MediaBuffer.h>
     30 #include <media/stagefright/MediaDefs.h>
     31 #include <media/stagefright/MetaData.h>
     32 #include <media/stagefright/Utils.h>
     33 #include <utils/Vector.h>
     34 
     35 #include <inttypes.h>
     36 
     37 namespace android {
     38 
     39 const int64_t kNearEOSMarkUs = 2000000ll; // 2 secs
     40 
     41 AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta)
     42     : mIsAudio(false),
     43       mIsVideo(false),
     44       mEnabled(true),
     45       mFormat(NULL),
     46       mLastQueuedTimeUs(0),
     47       mEstimatedBufferDurationUs(-1),
     48       mEOSResult(OK),
     49       mLatestEnqueuedMeta(NULL),
     50       mLatestDequeuedMeta(NULL) {
     51     setFormat(meta);
     52 
     53     mDiscontinuitySegments.push_back(DiscontinuitySegment());
     54 }
     55 
     56 void AnotherPacketSource::setFormat(const sp<MetaData> &meta) {
     57     if (mFormat != NULL) {
     58         // Only allowed to be set once. Requires explicit clear to reset.
     59         return;
     60     }
     61 
     62     mIsAudio = false;
     63     mIsVideo = false;
     64 
     65     if (meta == NULL) {
     66         return;
     67     }
     68 
     69     mFormat = meta;
     70     const char *mime;
     71     CHECK(meta->findCString(kKeyMIMEType, &mime));
     72 
     73     if (!strncasecmp("audio/", mime, 6)) {
     74         mIsAudio = true;
     75     } else  if (!strncasecmp("video/", mime, 6)) {
     76         mIsVideo = true;
     77     } else {
     78         CHECK(!strncasecmp("text/", mime, 5) || !strncasecmp("application/", mime, 12));
     79     }
     80 }
     81 
     82 AnotherPacketSource::~AnotherPacketSource() {
     83 }
     84 
     85 status_t AnotherPacketSource::start(MetaData * /* params */) {
     86     return OK;
     87 }
     88 
     89 status_t AnotherPacketSource::stop() {
     90     return OK;
     91 }
     92 
     93 sp<MetaData> AnotherPacketSource::getFormat() {
     94     Mutex::Autolock autoLock(mLock);
     95     if (mFormat != NULL) {
     96         return mFormat;
     97     }
     98 
     99     List<sp<ABuffer> >::iterator it = mBuffers.begin();
    100     while (it != mBuffers.end()) {
    101         sp<ABuffer> buffer = *it;
    102         int32_t discontinuity;
    103         if (!buffer->meta()->findInt32("discontinuity", &discontinuity)) {
    104             sp<RefBase> object;
    105             if (buffer->meta()->findObject("format", &object)) {
    106                 setFormat(static_cast<MetaData*>(object.get()));
    107                 return mFormat;
    108             }
    109         }
    110 
    111         ++it;
    112     }
    113     return NULL;
    114 }
    115 
    116 status_t AnotherPacketSource::dequeueAccessUnit(sp<ABuffer> *buffer) {
    117     buffer->clear();
    118 
    119     Mutex::Autolock autoLock(mLock);
    120     while (mEOSResult == OK && mBuffers.empty()) {
    121         mCondition.wait(mLock);
    122     }
    123 
    124     if (!mBuffers.empty()) {
    125         *buffer = *mBuffers.begin();
    126         mBuffers.erase(mBuffers.begin());
    127 
    128         int32_t discontinuity;
    129         if ((*buffer)->meta()->findInt32("discontinuity", &discontinuity)) {
    130             if (wasFormatChange(discontinuity)) {
    131                 mFormat.clear();
    132             }
    133 
    134             mDiscontinuitySegments.erase(mDiscontinuitySegments.begin());
    135             // CHECK(!mDiscontinuitySegments.empty());
    136             return INFO_DISCONTINUITY;
    137         }
    138 
    139         // CHECK(!mDiscontinuitySegments.empty());
    140         DiscontinuitySegment &seg = *mDiscontinuitySegments.begin();
    141 
    142         int64_t timeUs;
    143         mLatestDequeuedMeta = (*buffer)->meta()->dup();
    144         CHECK(mLatestDequeuedMeta->findInt64("timeUs", &timeUs));
    145         if (timeUs > seg.mMaxDequeTimeUs) {
    146             seg.mMaxDequeTimeUs = timeUs;
    147         }
    148 
    149         sp<RefBase> object;
    150         if ((*buffer)->meta()->findObject("format", &object)) {
    151             setFormat(static_cast<MetaData*>(object.get()));
    152         }
    153 
    154         return OK;
    155     }
    156 
    157     return mEOSResult;
    158 }
    159 
    160 void AnotherPacketSource::requeueAccessUnit(const sp<ABuffer> &buffer) {
    161     // TODO: update corresponding book keeping info.
    162     Mutex::Autolock autoLock(mLock);
    163     mBuffers.push_front(buffer);
    164 }
    165 
    166 status_t AnotherPacketSource::read(
    167         MediaBuffer **out, const ReadOptions *) {
    168     *out = NULL;
    169 
    170     Mutex::Autolock autoLock(mLock);
    171     while (mEOSResult == OK && mBuffers.empty()) {
    172         mCondition.wait(mLock);
    173     }
    174 
    175     if (!mBuffers.empty()) {
    176 
    177         const sp<ABuffer> buffer = *mBuffers.begin();
    178         mBuffers.erase(mBuffers.begin());
    179 
    180         int32_t discontinuity;
    181         if (buffer->meta()->findInt32("discontinuity", &discontinuity)) {
    182             if (wasFormatChange(discontinuity)) {
    183                 mFormat.clear();
    184             }
    185 
    186             mDiscontinuitySegments.erase(mDiscontinuitySegments.begin());
    187             // CHECK(!mDiscontinuitySegments.empty());
    188             return INFO_DISCONTINUITY;
    189         }
    190 
    191         mLatestDequeuedMeta = buffer->meta()->dup();
    192 
    193         sp<RefBase> object;
    194         if (buffer->meta()->findObject("format", &object)) {
    195             setFormat(static_cast<MetaData*>(object.get()));
    196         }
    197 
    198         int64_t timeUs;
    199         CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
    200         // CHECK(!mDiscontinuitySegments.empty());
    201         DiscontinuitySegment &seg = *mDiscontinuitySegments.begin();
    202         if (timeUs > seg.mMaxDequeTimeUs) {
    203             seg.mMaxDequeTimeUs = timeUs;
    204         }
    205 
    206         MediaBuffer *mediaBuffer = new MediaBuffer(buffer);
    207         sp<MetaData> bufmeta = mediaBuffer->meta_data();
    208 
    209         bufmeta->setInt64(kKeyTime, timeUs);
    210 
    211         int32_t isSync;
    212         if (buffer->meta()->findInt32("isSync", &isSync)) {
    213             bufmeta->setInt32(kKeyIsSyncFrame, isSync);
    214         }
    215 
    216         sp<ABuffer> sei;
    217         if (buffer->meta()->findBuffer("sei", &sei) && sei != NULL) {
    218             bufmeta->setData(kKeySEI, 0, sei->data(), sei->size());
    219         }
    220 
    221         sp<ABuffer> mpegUserData;
    222         if (buffer->meta()->findBuffer("mpegUserData", &mpegUserData) && mpegUserData != NULL) {
    223             bufmeta->setData(
    224                     kKeyMpegUserData, 0, mpegUserData->data(), mpegUserData->size());
    225         }
    226 
    227         int32_t cryptoMode;
    228         if (buffer->meta()->findInt32("cryptoMode", &cryptoMode)) {
    229             int32_t cryptoKey;
    230             sp<ABuffer> clearBytesBuffer, encBytesBuffer;
    231 
    232             CHECK(buffer->meta()->findInt32("cryptoKey", &cryptoKey));
    233             CHECK(buffer->meta()->findBuffer("clearBytes", &clearBytesBuffer)
    234                     && clearBytesBuffer != NULL);
    235             CHECK(buffer->meta()->findBuffer("encBytes", &encBytesBuffer)
    236                     && encBytesBuffer != NULL);
    237 
    238             bufmeta->setInt32(kKeyCryptoMode, cryptoMode);
    239 
    240             uint8_t array[16] = {0};
    241             bufmeta->setData(kKeyCryptoIV, 0, array, 16);
    242 
    243             array[0] = (uint8_t) (cryptoKey & 0xff);
    244             bufmeta->setData(kKeyCryptoKey, 0, array, 16);
    245 
    246             bufmeta->setData(kKeyPlainSizes, 0,
    247                     clearBytesBuffer->data(), clearBytesBuffer->size());
    248 
    249             bufmeta->setData(kKeyEncryptedSizes, 0,
    250                     encBytesBuffer->data(), encBytesBuffer->size());
    251         }
    252 
    253 
    254         *out = mediaBuffer;
    255         return OK;
    256     }
    257 
    258     return mEOSResult;
    259 }
    260 
    261 bool AnotherPacketSource::wasFormatChange(
    262         int32_t discontinuityType) const {
    263     if (mIsAudio) {
    264         return (discontinuityType & ATSParser::DISCONTINUITY_AUDIO_FORMAT) != 0;
    265     }
    266 
    267     if (mIsVideo) {
    268         return (discontinuityType & ATSParser::DISCONTINUITY_VIDEO_FORMAT) != 0;
    269     }
    270 
    271     return false;
    272 }
    273 
    274 void AnotherPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
    275     int32_t damaged;
    276     if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
    277         // LOG(VERBOSE) << "discarding damaged AU";
    278         return;
    279     }
    280 
    281     Mutex::Autolock autoLock(mLock);
    282     mBuffers.push_back(buffer);
    283     mCondition.signal();
    284 
    285     int32_t discontinuity;
    286     if (buffer->meta()->findInt32("discontinuity", &discontinuity)){
    287         ALOGV("queueing a discontinuity with queueAccessUnit");
    288 
    289         mLastQueuedTimeUs = 0ll;
    290         mEOSResult = OK;
    291         mLatestEnqueuedMeta = NULL;
    292 
    293         mDiscontinuitySegments.push_back(DiscontinuitySegment());
    294         return;
    295     }
    296 
    297     int64_t lastQueuedTimeUs;
    298     CHECK(buffer->meta()->findInt64("timeUs", &lastQueuedTimeUs));
    299     mLastQueuedTimeUs = lastQueuedTimeUs;
    300     ALOGV("queueAccessUnit timeUs=%" PRIi64 " us (%.2f secs)",
    301             mLastQueuedTimeUs, mLastQueuedTimeUs / 1E6);
    302 
    303     // CHECK(!mDiscontinuitySegments.empty());
    304     DiscontinuitySegment &tailSeg = *(--mDiscontinuitySegments.end());
    305     if (lastQueuedTimeUs > tailSeg.mMaxEnqueTimeUs) {
    306         tailSeg.mMaxEnqueTimeUs = lastQueuedTimeUs;
    307     }
    308     if (tailSeg.mMaxDequeTimeUs == -1) {
    309         tailSeg.mMaxDequeTimeUs = lastQueuedTimeUs;
    310     }
    311 
    312     if (mLatestEnqueuedMeta == NULL) {
    313         mLatestEnqueuedMeta = buffer->meta()->dup();
    314     } else {
    315         int64_t latestTimeUs = 0;
    316         int64_t frameDeltaUs = 0;
    317         CHECK(mLatestEnqueuedMeta->findInt64("timeUs", &latestTimeUs));
    318         if (lastQueuedTimeUs > latestTimeUs) {
    319             mLatestEnqueuedMeta = buffer->meta()->dup();
    320             frameDeltaUs = lastQueuedTimeUs - latestTimeUs;
    321             mLatestEnqueuedMeta->setInt64("durationUs", frameDeltaUs);
    322         } else if (!mLatestEnqueuedMeta->findInt64("durationUs", &frameDeltaUs)) {
    323             // For B frames
    324             frameDeltaUs = latestTimeUs - lastQueuedTimeUs;
    325             mLatestEnqueuedMeta->setInt64("durationUs", frameDeltaUs);
    326         }
    327     }
    328 }
    329 
    330 void AnotherPacketSource::clear() {
    331     Mutex::Autolock autoLock(mLock);
    332 
    333     mBuffers.clear();
    334     mEOSResult = OK;
    335 
    336     mDiscontinuitySegments.clear();
    337     mDiscontinuitySegments.push_back(DiscontinuitySegment());
    338 
    339     mFormat = NULL;
    340     mLatestEnqueuedMeta = NULL;
    341 
    342     mEstimatedBufferDurationUs = -1;
    343 }
    344 
    345 void AnotherPacketSource::queueDiscontinuity(
    346         ATSParser::DiscontinuityType type,
    347         const sp<AMessage> &extra,
    348         bool discard) {
    349     Mutex::Autolock autoLock(mLock);
    350 
    351     if (discard) {
    352         // Leave only discontinuities in the queue.
    353         List<sp<ABuffer> >::iterator it = mBuffers.begin();
    354         while (it != mBuffers.end()) {
    355             sp<ABuffer> oldBuffer = *it;
    356 
    357             int32_t oldDiscontinuityType;
    358             if (!oldBuffer->meta()->findInt32(
    359                         "discontinuity", &oldDiscontinuityType)) {
    360                 it = mBuffers.erase(it);
    361                 continue;
    362             }
    363 
    364             ++it;
    365         }
    366 
    367         for (List<DiscontinuitySegment>::iterator it2 = mDiscontinuitySegments.begin();
    368                 it2 != mDiscontinuitySegments.end();
    369                 ++it2) {
    370             DiscontinuitySegment &seg = *it2;
    371             seg.clear();
    372         }
    373 
    374     }
    375 
    376     mEOSResult = OK;
    377     mLastQueuedTimeUs = 0;
    378     mLatestEnqueuedMeta = NULL;
    379 
    380     if (type == ATSParser::DISCONTINUITY_NONE) {
    381         return;
    382     }
    383 
    384     mDiscontinuitySegments.push_back(DiscontinuitySegment());
    385 
    386     sp<ABuffer> buffer = new ABuffer(0);
    387     buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type));
    388     buffer->meta()->setMessage("extra", extra);
    389 
    390     mBuffers.push_back(buffer);
    391     mCondition.signal();
    392 }
    393 
    394 void AnotherPacketSource::signalEOS(status_t result) {
    395     CHECK(result != OK);
    396 
    397     Mutex::Autolock autoLock(mLock);
    398     mEOSResult = result;
    399     mCondition.signal();
    400 }
    401 
    402 bool AnotherPacketSource::hasBufferAvailable(status_t *finalResult) {
    403     Mutex::Autolock autoLock(mLock);
    404     *finalResult = OK;
    405     if (!mEnabled) {
    406         return false;
    407     }
    408     if (!mBuffers.empty()) {
    409         return true;
    410     }
    411 
    412     *finalResult = mEOSResult;
    413     return false;
    414 }
    415 
    416 bool AnotherPacketSource::hasDataBufferAvailable(status_t *finalResult) {
    417     Mutex::Autolock autoLock(mLock);
    418     *finalResult = OK;
    419     if (!mEnabled) {
    420         return false;
    421     }
    422     List<sp<ABuffer> >::iterator it;
    423     for (it = mBuffers.begin(); it != mBuffers.end(); it++) {
    424         int32_t discontinuity;
    425         if (!(*it)->meta()->findInt32("discontinuity", &discontinuity)) {
    426             return true;
    427         }
    428     }
    429 
    430     *finalResult = mEOSResult;
    431     return false;
    432 }
    433 
    434 size_t AnotherPacketSource::getAvailableBufferCount(status_t *finalResult) {
    435     Mutex::Autolock autoLock(mLock);
    436 
    437     *finalResult = OK;
    438     if (!mEnabled) {
    439         return 0;
    440     }
    441     if (!mBuffers.empty()) {
    442         return mBuffers.size();
    443     }
    444     *finalResult = mEOSResult;
    445     return 0;
    446 }
    447 
    448 int64_t AnotherPacketSource::getBufferedDurationUs(status_t *finalResult) {
    449     Mutex::Autolock autoLock(mLock);
    450     *finalResult = mEOSResult;
    451 
    452     int64_t durationUs = 0;
    453     for (List<DiscontinuitySegment>::iterator it = mDiscontinuitySegments.begin();
    454             it != mDiscontinuitySegments.end();
    455             ++it) {
    456         const DiscontinuitySegment &seg = *it;
    457         // dequeued access units should be a subset of enqueued access units
    458         // CHECK(seg.maxEnqueTimeUs >= seg.mMaxDequeTimeUs);
    459         durationUs += (seg.mMaxEnqueTimeUs - seg.mMaxDequeTimeUs);
    460     }
    461 
    462     return durationUs;
    463 }
    464 
    465 int64_t AnotherPacketSource::getEstimatedBufferDurationUs() {
    466     Mutex::Autolock autoLock(mLock);
    467     if (mEstimatedBufferDurationUs >= 0) {
    468         return mEstimatedBufferDurationUs;
    469     }
    470 
    471     SortedVector<int64_t> maxTimesUs;
    472     List<sp<ABuffer> >::iterator it;
    473     int64_t t1 = 0, t2 = 0;
    474     for (it = mBuffers.begin(); it != mBuffers.end(); ++it) {
    475         int64_t timeUs = 0;
    476         const sp<ABuffer> &buffer = *it;
    477         if (!buffer->meta()->findInt64("timeUs", &timeUs)) {
    478             continue;
    479         }
    480         maxTimesUs.add(timeUs);
    481         while (maxTimesUs.size() > 2) {
    482             maxTimesUs.removeAt(0);
    483             t1 = maxTimesUs.itemAt(0);
    484             t2 = maxTimesUs.itemAt(1);
    485         }
    486     }
    487     return mEstimatedBufferDurationUs = t2 - t1;
    488 }
    489 
    490 status_t AnotherPacketSource::nextBufferTime(int64_t *timeUs) {
    491     *timeUs = 0;
    492 
    493     Mutex::Autolock autoLock(mLock);
    494 
    495     if (mBuffers.empty()) {
    496         return mEOSResult != OK ? mEOSResult : -EWOULDBLOCK;
    497     }
    498 
    499     sp<ABuffer> buffer = *mBuffers.begin();
    500     CHECK(buffer->meta()->findInt64("timeUs", timeUs));
    501 
    502     return OK;
    503 }
    504 
    505 bool AnotherPacketSource::isFinished(int64_t duration) const {
    506     if (duration > 0) {
    507         int64_t diff = duration - mLastQueuedTimeUs;
    508         if (diff < kNearEOSMarkUs && diff > -kNearEOSMarkUs) {
    509             ALOGV("Detecting EOS due to near end");
    510             return true;
    511         }
    512     }
    513     return (mEOSResult != OK);
    514 }
    515 
    516 sp<AMessage> AnotherPacketSource::getLatestEnqueuedMeta() {
    517     Mutex::Autolock autoLock(mLock);
    518     return mLatestEnqueuedMeta;
    519 }
    520 
    521 sp<AMessage> AnotherPacketSource::getLatestDequeuedMeta() {
    522     Mutex::Autolock autoLock(mLock);
    523     return mLatestDequeuedMeta;
    524 }
    525 
    526 void AnotherPacketSource::enable(bool enable) {
    527     Mutex::Autolock autoLock(mLock);
    528     mEnabled = enable;
    529 }
    530 
    531 /*
    532  * returns the sample meta that's delayUs after queue head
    533  * (NULL if such sample is unavailable)
    534  */
    535 sp<AMessage> AnotherPacketSource::getMetaAfterLastDequeued(int64_t delayUs) {
    536     Mutex::Autolock autoLock(mLock);
    537     int64_t firstUs = -1;
    538     int64_t lastUs = -1;
    539     int64_t durationUs = 0;
    540 
    541     List<sp<ABuffer> >::iterator it;
    542     for (it = mBuffers.begin(); it != mBuffers.end(); ++it) {
    543         const sp<ABuffer> &buffer = *it;
    544         int32_t discontinuity;
    545         if (buffer->meta()->findInt32("discontinuity", &discontinuity)) {
    546             durationUs += lastUs - firstUs;
    547             firstUs = -1;
    548             lastUs = -1;
    549             continue;
    550         }
    551         int64_t timeUs;
    552         if (buffer->meta()->findInt64("timeUs", &timeUs)) {
    553             if (firstUs < 0) {
    554                 firstUs = timeUs;
    555             }
    556             if (lastUs < 0 || timeUs > lastUs) {
    557                 lastUs = timeUs;
    558             }
    559             if (durationUs + (lastUs - firstUs) >= delayUs) {
    560                 return buffer->meta();
    561             }
    562         }
    563     }
    564     return NULL;
    565 }
    566 
    567 /*
    568  * removes samples with time equal or after meta
    569  */
    570 void AnotherPacketSource::trimBuffersAfterMeta(
    571         const sp<AMessage> &meta) {
    572     if (meta == NULL) {
    573         ALOGW("trimming with NULL meta, ignoring");
    574         return;
    575     }
    576 
    577     Mutex::Autolock autoLock(mLock);
    578     if (mBuffers.empty()) {
    579         return;
    580     }
    581 
    582     HLSTime stopTime(meta);
    583     ALOGV("trimBuffersAfterMeta: discontinuitySeq %d, timeUs %lld",
    584             stopTime.mSeq, (long long)stopTime.mTimeUs);
    585 
    586     List<sp<ABuffer> >::iterator it;
    587     List<DiscontinuitySegment >::iterator it2;
    588     sp<AMessage> newLatestEnqueuedMeta = NULL;
    589     int64_t newLastQueuedTimeUs = 0;
    590     for (it = mBuffers.begin(), it2 = mDiscontinuitySegments.begin(); it != mBuffers.end(); ++it) {
    591         const sp<ABuffer> &buffer = *it;
    592         int32_t discontinuity;
    593         if (buffer->meta()->findInt32("discontinuity", &discontinuity)) {
    594             // CHECK(it2 != mDiscontinuitySegments.end());
    595             ++it2;
    596             continue;
    597         }
    598 
    599         HLSTime curTime(buffer->meta());
    600         if (!(curTime < stopTime)) {
    601             ALOGV("trimming from %lld (inclusive) to end",
    602                     (long long)curTime.mTimeUs);
    603             break;
    604         }
    605         newLatestEnqueuedMeta = buffer->meta();
    606         newLastQueuedTimeUs = curTime.mTimeUs;
    607     }
    608 
    609     mBuffers.erase(it, mBuffers.end());
    610     mLatestEnqueuedMeta = newLatestEnqueuedMeta;
    611     mLastQueuedTimeUs = newLastQueuedTimeUs;
    612 
    613     DiscontinuitySegment &seg = *it2;
    614     if (newLatestEnqueuedMeta != NULL) {
    615         seg.mMaxEnqueTimeUs = newLastQueuedTimeUs;
    616     } else {
    617         seg.clear();
    618     }
    619     mDiscontinuitySegments.erase(++it2, mDiscontinuitySegments.end());
    620 }
    621 
    622 /*
    623  * removes samples with time equal or before meta;
    624  * returns first sample left in the queue.
    625  *
    626  * (for AVC, if trim happens, the samples left will always start
    627  * at next IDR.)
    628  */
    629 sp<AMessage> AnotherPacketSource::trimBuffersBeforeMeta(
    630         const sp<AMessage> &meta) {
    631     HLSTime startTime(meta);
    632     ALOGV("trimBuffersBeforeMeta: discontinuitySeq %d, timeUs %lld",
    633             startTime.mSeq, (long long)startTime.mTimeUs);
    634 
    635     sp<AMessage> firstMeta;
    636     int64_t firstTimeUs = -1;
    637     Mutex::Autolock autoLock(mLock);
    638     if (mBuffers.empty()) {
    639         return NULL;
    640     }
    641 
    642     sp<MetaData> format;
    643     bool isAvc = false;
    644 
    645     List<sp<ABuffer> >::iterator it;
    646     for (it = mBuffers.begin(); it != mBuffers.end(); ++it) {
    647         const sp<ABuffer> &buffer = *it;
    648         int32_t discontinuity;
    649         if (buffer->meta()->findInt32("discontinuity", &discontinuity)) {
    650             mDiscontinuitySegments.erase(mDiscontinuitySegments.begin());
    651             // CHECK(!mDiscontinuitySegments.empty());
    652             format = NULL;
    653             isAvc = false;
    654             continue;
    655         }
    656         if (format == NULL) {
    657             sp<RefBase> object;
    658             if (buffer->meta()->findObject("format", &object)) {
    659                 const char* mime;
    660                 format = static_cast<MetaData*>(object.get());
    661                 isAvc = format != NULL
    662                         && format->findCString(kKeyMIMEType, &mime)
    663                         && !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
    664             }
    665         }
    666         if (isAvc && !IsIDR(buffer)) {
    667             continue;
    668         }
    669 
    670         HLSTime curTime(buffer->meta());
    671         if (startTime < curTime) {
    672             ALOGV("trimming from beginning to %lld (not inclusive)",
    673                     (long long)curTime.mTimeUs);
    674             firstMeta = buffer->meta();
    675             firstTimeUs = curTime.mTimeUs;
    676             break;
    677         }
    678     }
    679     mBuffers.erase(mBuffers.begin(), it);
    680     mLatestDequeuedMeta = NULL;
    681 
    682     // CHECK(!mDiscontinuitySegments.empty());
    683     DiscontinuitySegment &seg = *mDiscontinuitySegments.begin();
    684     if (firstTimeUs >= 0) {
    685         seg.mMaxDequeTimeUs = firstTimeUs;
    686     } else {
    687         seg.clear();
    688     }
    689 
    690     return firstMeta;
    691 }
    692 
    693 }  // namespace android
    694