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