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