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 "ATSParser"
19 #include <utils/Log.h>
20
21 #include "ATSParser.h"
22
23 #include "AnotherPacketSource.h"
24 #include "ESQueue.h"
25 #include "include/avc_utils.h"
26
27 #include <media/stagefright/foundation/ABitReader.h>
28 #include <media/stagefright/foundation/ABuffer.h>
29 #include <media/stagefright/foundation/ADebug.h>
30 #include <media/stagefright/foundation/AMessage.h>
31 #include <media/stagefright/foundation/hexdump.h>
32 #include <media/stagefright/MediaDefs.h>
33 #include <media/stagefright/MediaErrors.h>
34 #include <media/stagefright/MetaData.h>
35 #include <media/stagefright/Utils.h>
36 #include <media/IStreamSource.h>
37 #include <utils/KeyedVector.h>
38
39 #include <inttypes.h>
40
41 namespace android {
42
43 // I want the expression "y" evaluated even if verbose logging is off.
44 #define MY_LOGV(x, y) \
45 do { unsigned tmp = y; ALOGV(x, tmp); } while (0)
46
47 static const size_t kTSPacketSize = 188;
48
49 struct ATSParser::Program : public RefBase {
50 Program(ATSParser *parser, unsigned programNumber, unsigned programMapPID);
51
52 bool parsePSISection(
53 unsigned pid, ABitReader *br, status_t *err);
54
55 bool parsePID(
56 unsigned pid, unsigned continuity_counter,
57 unsigned payload_unit_start_indicator,
58 ABitReader *br, status_t *err);
59
60 void signalDiscontinuity(
61 DiscontinuityType type, const sp<AMessage> &extra);
62
63 void signalEOS(status_t finalResult);
64
65 sp<MediaSource> getSource(SourceType type);
66 bool hasSource(SourceType type) const;
67
68 int64_t convertPTSToTimestamp(uint64_t PTS);
69
PTSTimeDeltaEstablishedandroid::ATSParser::Program70 bool PTSTimeDeltaEstablished() const {
71 return mFirstPTSValid;
72 }
73
numberandroid::ATSParser::Program74 unsigned number() const { return mProgramNumber; }
75
updateProgramMapPIDandroid::ATSParser::Program76 void updateProgramMapPID(unsigned programMapPID) {
77 mProgramMapPID = programMapPID;
78 }
79
programMapPIDandroid::ATSParser::Program80 unsigned programMapPID() const {
81 return mProgramMapPID;
82 }
83
parserFlagsandroid::ATSParser::Program84 uint32_t parserFlags() const {
85 return mParser->mFlags;
86 }
87
88 private:
89 ATSParser *mParser;
90 unsigned mProgramNumber;
91 unsigned mProgramMapPID;
92 KeyedVector<unsigned, sp<Stream> > mStreams;
93 bool mFirstPTSValid;
94 uint64_t mFirstPTS;
95
96 status_t parseProgramMap(ABitReader *br);
97
98 DISALLOW_EVIL_CONSTRUCTORS(Program);
99 };
100
101 struct ATSParser::Stream : public RefBase {
102 Stream(Program *program,
103 unsigned elementaryPID,
104 unsigned streamType,
105 unsigned PCR_PID);
106
typeandroid::ATSParser::Stream107 unsigned type() const { return mStreamType; }
pidandroid::ATSParser::Stream108 unsigned pid() const { return mElementaryPID; }
setPIDandroid::ATSParser::Stream109 void setPID(unsigned pid) { mElementaryPID = pid; }
110
111 status_t parse(
112 unsigned continuity_counter,
113 unsigned payload_unit_start_indicator,
114 ABitReader *br);
115
116 void signalDiscontinuity(
117 DiscontinuityType type, const sp<AMessage> &extra);
118
119 void signalEOS(status_t finalResult);
120
121 sp<MediaSource> getSource(SourceType type);
122
123 bool isAudio() const;
124 bool isVideo() const;
125
126 protected:
127 virtual ~Stream();
128
129 private:
130 Program *mProgram;
131 unsigned mElementaryPID;
132 unsigned mStreamType;
133 unsigned mPCR_PID;
134 int32_t mExpectedContinuityCounter;
135
136 sp<ABuffer> mBuffer;
137 sp<AnotherPacketSource> mSource;
138 bool mPayloadStarted;
139
140 uint64_t mPrevPTS;
141
142 ElementaryStreamQueue *mQueue;
143
144 status_t flush();
145 status_t parsePES(ABitReader *br);
146
147 void onPayloadData(
148 unsigned PTS_DTS_flags, uint64_t PTS, uint64_t DTS,
149 const uint8_t *data, size_t size);
150
151 void extractAACFrames(const sp<ABuffer> &buffer);
152
153 DISALLOW_EVIL_CONSTRUCTORS(Stream);
154 };
155
156 struct ATSParser::PSISection : public RefBase {
157 PSISection();
158
159 status_t append(const void *data, size_t size);
160 void clear();
161
162 bool isComplete() const;
163 bool isEmpty() const;
164
165 const uint8_t *data() const;
166 size_t size() const;
167
168 protected:
169 virtual ~PSISection();
170
171 private:
172 sp<ABuffer> mBuffer;
173
174 DISALLOW_EVIL_CONSTRUCTORS(PSISection);
175 };
176
177 ////////////////////////////////////////////////////////////////////////////////
178
Program(ATSParser * parser,unsigned programNumber,unsigned programMapPID)179 ATSParser::Program::Program(
180 ATSParser *parser, unsigned programNumber, unsigned programMapPID)
181 : mParser(parser),
182 mProgramNumber(programNumber),
183 mProgramMapPID(programMapPID),
184 mFirstPTSValid(false),
185 mFirstPTS(0) {
186 ALOGV("new program number %u", programNumber);
187 }
188
parsePSISection(unsigned pid,ABitReader * br,status_t * err)189 bool ATSParser::Program::parsePSISection(
190 unsigned pid, ABitReader *br, status_t *err) {
191 *err = OK;
192
193 if (pid != mProgramMapPID) {
194 return false;
195 }
196
197 *err = parseProgramMap(br);
198
199 return true;
200 }
201
parsePID(unsigned pid,unsigned continuity_counter,unsigned payload_unit_start_indicator,ABitReader * br,status_t * err)202 bool ATSParser::Program::parsePID(
203 unsigned pid, unsigned continuity_counter,
204 unsigned payload_unit_start_indicator,
205 ABitReader *br, status_t *err) {
206 *err = OK;
207
208 ssize_t index = mStreams.indexOfKey(pid);
209 if (index < 0) {
210 return false;
211 }
212
213 *err = mStreams.editValueAt(index)->parse(
214 continuity_counter, payload_unit_start_indicator, br);
215
216 return true;
217 }
218
signalDiscontinuity(DiscontinuityType type,const sp<AMessage> & extra)219 void ATSParser::Program::signalDiscontinuity(
220 DiscontinuityType type, const sp<AMessage> &extra) {
221 int64_t mediaTimeUs;
222 if ((type & DISCONTINUITY_TIME)
223 && extra != NULL
224 && extra->findInt64(
225 IStreamListener::kKeyMediaTimeUs, &mediaTimeUs)) {
226 mFirstPTSValid = false;
227 }
228
229 for (size_t i = 0; i < mStreams.size(); ++i) {
230 mStreams.editValueAt(i)->signalDiscontinuity(type, extra);
231 }
232 }
233
signalEOS(status_t finalResult)234 void ATSParser::Program::signalEOS(status_t finalResult) {
235 for (size_t i = 0; i < mStreams.size(); ++i) {
236 mStreams.editValueAt(i)->signalEOS(finalResult);
237 }
238 }
239
240 struct StreamInfo {
241 unsigned mType;
242 unsigned mPID;
243 };
244
parseProgramMap(ABitReader * br)245 status_t ATSParser::Program::parseProgramMap(ABitReader *br) {
246 unsigned table_id = br->getBits(8);
247 ALOGV(" table_id = %u", table_id);
248 if (table_id != 0x02u) {
249 ALOGE("PMT data error!");
250 return ERROR_MALFORMED;
251 }
252 unsigned section_syntax_indicator = br->getBits(1);
253 ALOGV(" section_syntax_indicator = %u", section_syntax_indicator);
254 if (section_syntax_indicator != 1u) {
255 ALOGE("PMT data error!");
256 return ERROR_MALFORMED;
257 }
258
259 CHECK_EQ(br->getBits(1), 0u);
260 MY_LOGV(" reserved = %u", br->getBits(2));
261
262 unsigned section_length = br->getBits(12);
263 ALOGV(" section_length = %u", section_length);
264 CHECK_EQ(section_length & 0xc00, 0u);
265 CHECK_LE(section_length, 1021u);
266
267 MY_LOGV(" program_number = %u", br->getBits(16));
268 MY_LOGV(" reserved = %u", br->getBits(2));
269 MY_LOGV(" version_number = %u", br->getBits(5));
270 MY_LOGV(" current_next_indicator = %u", br->getBits(1));
271 MY_LOGV(" section_number = %u", br->getBits(8));
272 MY_LOGV(" last_section_number = %u", br->getBits(8));
273 MY_LOGV(" reserved = %u", br->getBits(3));
274
275 unsigned PCR_PID = br->getBits(13);
276 ALOGV(" PCR_PID = 0x%04x", PCR_PID);
277
278 MY_LOGV(" reserved = %u", br->getBits(4));
279
280 unsigned program_info_length = br->getBits(12);
281 ALOGV(" program_info_length = %u", program_info_length);
282 CHECK_EQ(program_info_length & 0xc00, 0u);
283
284 br->skipBits(program_info_length * 8); // skip descriptors
285
286 Vector<StreamInfo> infos;
287
288 // infoBytesRemaining is the number of bytes that make up the
289 // variable length section of ES_infos. It does not include the
290 // final CRC.
291 size_t infoBytesRemaining = section_length - 9 - program_info_length - 4;
292
293 while (infoBytesRemaining > 0) {
294 CHECK_GE(infoBytesRemaining, 5u);
295
296 unsigned streamType = br->getBits(8);
297 ALOGV(" stream_type = 0x%02x", streamType);
298
299 MY_LOGV(" reserved = %u", br->getBits(3));
300
301 unsigned elementaryPID = br->getBits(13);
302 ALOGV(" elementary_PID = 0x%04x", elementaryPID);
303
304 MY_LOGV(" reserved = %u", br->getBits(4));
305
306 unsigned ES_info_length = br->getBits(12);
307 ALOGV(" ES_info_length = %u", ES_info_length);
308 CHECK_EQ(ES_info_length & 0xc00, 0u);
309
310 CHECK_GE(infoBytesRemaining - 5, ES_info_length);
311
312 #if 0
313 br->skipBits(ES_info_length * 8); // skip descriptors
314 #else
315 unsigned info_bytes_remaining = ES_info_length;
316 while (info_bytes_remaining >= 2) {
317 MY_LOGV(" tag = 0x%02x", br->getBits(8));
318
319 unsigned descLength = br->getBits(8);
320 ALOGV(" len = %u", descLength);
321
322 CHECK_GE(info_bytes_remaining, 2 + descLength);
323
324 br->skipBits(descLength * 8);
325
326 info_bytes_remaining -= descLength + 2;
327 }
328 CHECK_EQ(info_bytes_remaining, 0u);
329 #endif
330
331 StreamInfo info;
332 info.mType = streamType;
333 info.mPID = elementaryPID;
334 infos.push(info);
335
336 infoBytesRemaining -= 5 + ES_info_length;
337 }
338
339 CHECK_EQ(infoBytesRemaining, 0u);
340 MY_LOGV(" CRC = 0x%08x", br->getBits(32));
341
342 bool PIDsChanged = false;
343 for (size_t i = 0; i < infos.size(); ++i) {
344 StreamInfo &info = infos.editItemAt(i);
345
346 ssize_t index = mStreams.indexOfKey(info.mPID);
347
348 if (index >= 0 && mStreams.editValueAt(index)->type() != info.mType) {
349 ALOGI("uh oh. stream PIDs have changed.");
350 PIDsChanged = true;
351 break;
352 }
353 }
354
355 if (PIDsChanged) {
356 #if 0
357 ALOGI("before:");
358 for (size_t i = 0; i < mStreams.size(); ++i) {
359 sp<Stream> stream = mStreams.editValueAt(i);
360
361 ALOGI("PID 0x%08x => type 0x%02x", stream->pid(), stream->type());
362 }
363
364 ALOGI("after:");
365 for (size_t i = 0; i < infos.size(); ++i) {
366 StreamInfo &info = infos.editItemAt(i);
367
368 ALOGI("PID 0x%08x => type 0x%02x", info.mPID, info.mType);
369 }
370 #endif
371
372 // The only case we can recover from is if we have two streams
373 // and they switched PIDs.
374
375 bool success = false;
376
377 if (mStreams.size() == 2 && infos.size() == 2) {
378 const StreamInfo &info1 = infos.itemAt(0);
379 const StreamInfo &info2 = infos.itemAt(1);
380
381 sp<Stream> s1 = mStreams.editValueAt(0);
382 sp<Stream> s2 = mStreams.editValueAt(1);
383
384 bool caseA =
385 info1.mPID == s1->pid() && info1.mType == s2->type()
386 && info2.mPID == s2->pid() && info2.mType == s1->type();
387
388 bool caseB =
389 info1.mPID == s2->pid() && info1.mType == s1->type()
390 && info2.mPID == s1->pid() && info2.mType == s2->type();
391
392 if (caseA || caseB) {
393 unsigned pid1 = s1->pid();
394 unsigned pid2 = s2->pid();
395 s1->setPID(pid2);
396 s2->setPID(pid1);
397
398 mStreams.clear();
399 mStreams.add(s1->pid(), s1);
400 mStreams.add(s2->pid(), s2);
401
402 success = true;
403 }
404 }
405
406 if (!success) {
407 ALOGI("Stream PIDs changed and we cannot recover.");
408 return ERROR_MALFORMED;
409 }
410 }
411
412 for (size_t i = 0; i < infos.size(); ++i) {
413 StreamInfo &info = infos.editItemAt(i);
414
415 ssize_t index = mStreams.indexOfKey(info.mPID);
416
417 if (index < 0) {
418 sp<Stream> stream = new Stream(
419 this, info.mPID, info.mType, PCR_PID);
420
421 mStreams.add(info.mPID, stream);
422 }
423 }
424
425 return OK;
426 }
427
getSource(SourceType type)428 sp<MediaSource> ATSParser::Program::getSource(SourceType type) {
429 size_t index = (type == AUDIO) ? 0 : 0;
430
431 for (size_t i = 0; i < mStreams.size(); ++i) {
432 sp<MediaSource> source = mStreams.editValueAt(i)->getSource(type);
433 if (source != NULL) {
434 if (index == 0) {
435 return source;
436 }
437 --index;
438 }
439 }
440
441 return NULL;
442 }
443
hasSource(SourceType type) const444 bool ATSParser::Program::hasSource(SourceType type) const {
445 for (size_t i = 0; i < mStreams.size(); ++i) {
446 const sp<Stream> &stream = mStreams.valueAt(i);
447 if (type == AUDIO && stream->isAudio()) {
448 return true;
449 } else if (type == VIDEO && stream->isVideo()) {
450 return true;
451 }
452 }
453
454 return false;
455 }
456
convertPTSToTimestamp(uint64_t PTS)457 int64_t ATSParser::Program::convertPTSToTimestamp(uint64_t PTS) {
458 if (!(mParser->mFlags & TS_TIMESTAMPS_ARE_ABSOLUTE)) {
459 if (!mFirstPTSValid) {
460 mFirstPTSValid = true;
461 mFirstPTS = PTS;
462 PTS = 0;
463 } else if (PTS < mFirstPTS) {
464 PTS = 0;
465 } else {
466 PTS -= mFirstPTS;
467 }
468 }
469
470 int64_t timeUs = (PTS * 100) / 9;
471
472 if (mParser->mAbsoluteTimeAnchorUs >= 0ll) {
473 timeUs += mParser->mAbsoluteTimeAnchorUs;
474 }
475
476 if (mParser->mTimeOffsetValid) {
477 timeUs += mParser->mTimeOffsetUs;
478 }
479
480 return timeUs;
481 }
482
483 ////////////////////////////////////////////////////////////////////////////////
484
Stream(Program * program,unsigned elementaryPID,unsigned streamType,unsigned PCR_PID)485 ATSParser::Stream::Stream(
486 Program *program,
487 unsigned elementaryPID,
488 unsigned streamType,
489 unsigned PCR_PID)
490 : mProgram(program),
491 mElementaryPID(elementaryPID),
492 mStreamType(streamType),
493 mPCR_PID(PCR_PID),
494 mExpectedContinuityCounter(-1),
495 mPayloadStarted(false),
496 mPrevPTS(0),
497 mQueue(NULL) {
498 switch (mStreamType) {
499 case STREAMTYPE_H264:
500 mQueue = new ElementaryStreamQueue(
501 ElementaryStreamQueue::H264,
502 (mProgram->parserFlags() & ALIGNED_VIDEO_DATA)
503 ? ElementaryStreamQueue::kFlag_AlignedData : 0);
504 break;
505 case STREAMTYPE_MPEG2_AUDIO_ADTS:
506 mQueue = new ElementaryStreamQueue(ElementaryStreamQueue::AAC);
507 break;
508 case STREAMTYPE_MPEG1_AUDIO:
509 case STREAMTYPE_MPEG2_AUDIO:
510 mQueue = new ElementaryStreamQueue(
511 ElementaryStreamQueue::MPEG_AUDIO);
512 break;
513
514 case STREAMTYPE_MPEG1_VIDEO:
515 case STREAMTYPE_MPEG2_VIDEO:
516 mQueue = new ElementaryStreamQueue(
517 ElementaryStreamQueue::MPEG_VIDEO);
518 break;
519
520 case STREAMTYPE_MPEG4_VIDEO:
521 mQueue = new ElementaryStreamQueue(
522 ElementaryStreamQueue::MPEG4_VIDEO);
523 break;
524
525 case STREAMTYPE_LPCM_AC3:
526 case STREAMTYPE_AC3:
527 mQueue = new ElementaryStreamQueue(
528 ElementaryStreamQueue::AC3);
529 break;
530
531 default:
532 break;
533 }
534
535 ALOGV("new stream PID 0x%02x, type 0x%02x", elementaryPID, streamType);
536
537 if (mQueue != NULL) {
538 mBuffer = new ABuffer(192 * 1024);
539 mBuffer->setRange(0, 0);
540 }
541 }
542
~Stream()543 ATSParser::Stream::~Stream() {
544 delete mQueue;
545 mQueue = NULL;
546 }
547
parse(unsigned continuity_counter,unsigned payload_unit_start_indicator,ABitReader * br)548 status_t ATSParser::Stream::parse(
549 unsigned continuity_counter,
550 unsigned payload_unit_start_indicator, ABitReader *br) {
551 if (mQueue == NULL) {
552 return OK;
553 }
554
555 if (mExpectedContinuityCounter >= 0
556 && (unsigned)mExpectedContinuityCounter != continuity_counter) {
557 ALOGI("discontinuity on stream pid 0x%04x", mElementaryPID);
558
559 mPayloadStarted = false;
560 mBuffer->setRange(0, 0);
561 mExpectedContinuityCounter = -1;
562
563 #if 0
564 // Uncomment this if you'd rather see no corruption whatsoever on
565 // screen and suspend updates until we come across another IDR frame.
566
567 if (mStreamType == STREAMTYPE_H264) {
568 ALOGI("clearing video queue");
569 mQueue->clear(true /* clearFormat */);
570 }
571 #endif
572
573 if (!payload_unit_start_indicator) {
574 return OK;
575 }
576 }
577
578 mExpectedContinuityCounter = (continuity_counter + 1) & 0x0f;
579
580 if (payload_unit_start_indicator) {
581 if (mPayloadStarted) {
582 // Otherwise we run the danger of receiving the trailing bytes
583 // of a PES packet that we never saw the start of and assuming
584 // we have a a complete PES packet.
585
586 status_t err = flush();
587
588 if (err != OK) {
589 return err;
590 }
591 }
592
593 mPayloadStarted = true;
594 }
595
596 if (!mPayloadStarted) {
597 return OK;
598 }
599
600 size_t payloadSizeBits = br->numBitsLeft();
601 CHECK_EQ(payloadSizeBits % 8, 0u);
602
603 size_t neededSize = mBuffer->size() + payloadSizeBits / 8;
604 if (mBuffer->capacity() < neededSize) {
605 // Increment in multiples of 64K.
606 neededSize = (neededSize + 65535) & ~65535;
607
608 ALOGI("resizing buffer to %zu bytes", neededSize);
609
610 sp<ABuffer> newBuffer = new ABuffer(neededSize);
611 memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size());
612 newBuffer->setRange(0, mBuffer->size());
613 mBuffer = newBuffer;
614 }
615
616 memcpy(mBuffer->data() + mBuffer->size(), br->data(), payloadSizeBits / 8);
617 mBuffer->setRange(0, mBuffer->size() + payloadSizeBits / 8);
618
619 return OK;
620 }
621
isVideo() const622 bool ATSParser::Stream::isVideo() const {
623 switch (mStreamType) {
624 case STREAMTYPE_H264:
625 case STREAMTYPE_MPEG1_VIDEO:
626 case STREAMTYPE_MPEG2_VIDEO:
627 case STREAMTYPE_MPEG4_VIDEO:
628 return true;
629
630 default:
631 return false;
632 }
633 }
634
isAudio() const635 bool ATSParser::Stream::isAudio() const {
636 switch (mStreamType) {
637 case STREAMTYPE_MPEG1_AUDIO:
638 case STREAMTYPE_MPEG2_AUDIO:
639 case STREAMTYPE_MPEG2_AUDIO_ADTS:
640 case STREAMTYPE_LPCM_AC3:
641 case STREAMTYPE_AC3:
642 return true;
643
644 default:
645 return false;
646 }
647 }
648
signalDiscontinuity(DiscontinuityType type,const sp<AMessage> & extra)649 void ATSParser::Stream::signalDiscontinuity(
650 DiscontinuityType type, const sp<AMessage> &extra) {
651 mExpectedContinuityCounter = -1;
652
653 if (mQueue == NULL) {
654 return;
655 }
656
657 mPayloadStarted = false;
658 mBuffer->setRange(0, 0);
659
660 bool clearFormat = false;
661 if (isAudio()) {
662 if (type & DISCONTINUITY_AUDIO_FORMAT) {
663 clearFormat = true;
664 }
665 } else {
666 if (type & DISCONTINUITY_VIDEO_FORMAT) {
667 clearFormat = true;
668 }
669 }
670
671 mQueue->clear(clearFormat);
672
673 if (type & DISCONTINUITY_TIME) {
674 uint64_t resumeAtPTS;
675 if (extra != NULL
676 && extra->findInt64(
677 IStreamListener::kKeyResumeAtPTS,
678 (int64_t *)&resumeAtPTS)) {
679 int64_t resumeAtMediaTimeUs =
680 mProgram->convertPTSToTimestamp(resumeAtPTS);
681
682 extra->setInt64("resume-at-mediaTimeUs", resumeAtMediaTimeUs);
683 }
684 }
685
686 if (mSource != NULL) {
687 mSource->queueDiscontinuity(type, extra, true);
688 }
689 }
690
signalEOS(status_t finalResult)691 void ATSParser::Stream::signalEOS(status_t finalResult) {
692 if (mSource != NULL) {
693 mSource->signalEOS(finalResult);
694 }
695 }
696
parsePES(ABitReader * br)697 status_t ATSParser::Stream::parsePES(ABitReader *br) {
698 unsigned packet_startcode_prefix = br->getBits(24);
699
700 ALOGV("packet_startcode_prefix = 0x%08x", packet_startcode_prefix);
701
702 if (packet_startcode_prefix != 1) {
703 ALOGV("Supposedly payload_unit_start=1 unit does not start "
704 "with startcode.");
705
706 return ERROR_MALFORMED;
707 }
708
709 CHECK_EQ(packet_startcode_prefix, 0x000001u);
710
711 unsigned stream_id = br->getBits(8);
712 ALOGV("stream_id = 0x%02x", stream_id);
713
714 unsigned PES_packet_length = br->getBits(16);
715 ALOGV("PES_packet_length = %u", PES_packet_length);
716
717 if (stream_id != 0xbc // program_stream_map
718 && stream_id != 0xbe // padding_stream
719 && stream_id != 0xbf // private_stream_2
720 && stream_id != 0xf0 // ECM
721 && stream_id != 0xf1 // EMM
722 && stream_id != 0xff // program_stream_directory
723 && stream_id != 0xf2 // DSMCC
724 && stream_id != 0xf8) { // H.222.1 type E
725 CHECK_EQ(br->getBits(2), 2u);
726
727 MY_LOGV("PES_scrambling_control = %u", br->getBits(2));
728 MY_LOGV("PES_priority = %u", br->getBits(1));
729 MY_LOGV("data_alignment_indicator = %u", br->getBits(1));
730 MY_LOGV("copyright = %u", br->getBits(1));
731 MY_LOGV("original_or_copy = %u", br->getBits(1));
732
733 unsigned PTS_DTS_flags = br->getBits(2);
734 ALOGV("PTS_DTS_flags = %u", PTS_DTS_flags);
735
736 unsigned ESCR_flag = br->getBits(1);
737 ALOGV("ESCR_flag = %u", ESCR_flag);
738
739 unsigned ES_rate_flag = br->getBits(1);
740 ALOGV("ES_rate_flag = %u", ES_rate_flag);
741
742 unsigned DSM_trick_mode_flag = br->getBits(1);
743 ALOGV("DSM_trick_mode_flag = %u", DSM_trick_mode_flag);
744
745 unsigned additional_copy_info_flag = br->getBits(1);
746 ALOGV("additional_copy_info_flag = %u", additional_copy_info_flag);
747
748 MY_LOGV("PES_CRC_flag = %u", br->getBits(1));
749 MY_LOGV("PES_extension_flag = %u", br->getBits(1));
750
751 unsigned PES_header_data_length = br->getBits(8);
752 ALOGV("PES_header_data_length = %u", PES_header_data_length);
753
754 unsigned optional_bytes_remaining = PES_header_data_length;
755
756 uint64_t PTS = 0, DTS = 0;
757
758 if (PTS_DTS_flags == 2 || PTS_DTS_flags == 3) {
759 CHECK_GE(optional_bytes_remaining, 5u);
760
761 if (br->getBits(4) != PTS_DTS_flags) {
762 ALOGE("PES data Error!");
763 return ERROR_MALFORMED;
764 }
765 PTS = ((uint64_t)br->getBits(3)) << 30;
766 CHECK_EQ(br->getBits(1), 1u);
767 PTS |= ((uint64_t)br->getBits(15)) << 15;
768 CHECK_EQ(br->getBits(1), 1u);
769 PTS |= br->getBits(15);
770 CHECK_EQ(br->getBits(1), 1u);
771
772 ALOGV("PTS = 0x%016" PRIx64 " (%.2f)", PTS, PTS / 90000.0);
773
774 optional_bytes_remaining -= 5;
775
776 if (PTS_DTS_flags == 3) {
777 CHECK_GE(optional_bytes_remaining, 5u);
778
779 CHECK_EQ(br->getBits(4), 1u);
780
781 DTS = ((uint64_t)br->getBits(3)) << 30;
782 CHECK_EQ(br->getBits(1), 1u);
783 DTS |= ((uint64_t)br->getBits(15)) << 15;
784 CHECK_EQ(br->getBits(1), 1u);
785 DTS |= br->getBits(15);
786 CHECK_EQ(br->getBits(1), 1u);
787
788 ALOGV("DTS = %" PRIu64, DTS);
789
790 optional_bytes_remaining -= 5;
791 }
792 }
793
794 if (ESCR_flag) {
795 CHECK_GE(optional_bytes_remaining, 6u);
796
797 br->getBits(2);
798
799 uint64_t ESCR = ((uint64_t)br->getBits(3)) << 30;
800 CHECK_EQ(br->getBits(1), 1u);
801 ESCR |= ((uint64_t)br->getBits(15)) << 15;
802 CHECK_EQ(br->getBits(1), 1u);
803 ESCR |= br->getBits(15);
804 CHECK_EQ(br->getBits(1), 1u);
805
806 ALOGV("ESCR = %" PRIu64, ESCR);
807 MY_LOGV("ESCR_extension = %u", br->getBits(9));
808
809 CHECK_EQ(br->getBits(1), 1u);
810
811 optional_bytes_remaining -= 6;
812 }
813
814 if (ES_rate_flag) {
815 CHECK_GE(optional_bytes_remaining, 3u);
816
817 CHECK_EQ(br->getBits(1), 1u);
818 MY_LOGV("ES_rate = %u", br->getBits(22));
819 CHECK_EQ(br->getBits(1), 1u);
820
821 optional_bytes_remaining -= 3;
822 }
823
824 br->skipBits(optional_bytes_remaining * 8);
825
826 // ES data follows.
827
828 if (PES_packet_length != 0) {
829 CHECK_GE(PES_packet_length, PES_header_data_length + 3);
830
831 unsigned dataLength =
832 PES_packet_length - 3 - PES_header_data_length;
833
834 if (br->numBitsLeft() < dataLength * 8) {
835 ALOGE("PES packet does not carry enough data to contain "
836 "payload. (numBitsLeft = %zu, required = %u)",
837 br->numBitsLeft(), dataLength * 8);
838
839 return ERROR_MALFORMED;
840 }
841
842 CHECK_GE(br->numBitsLeft(), dataLength * 8);
843
844 onPayloadData(
845 PTS_DTS_flags, PTS, DTS, br->data(), dataLength);
846
847 br->skipBits(dataLength * 8);
848 } else {
849 onPayloadData(
850 PTS_DTS_flags, PTS, DTS,
851 br->data(), br->numBitsLeft() / 8);
852
853 size_t payloadSizeBits = br->numBitsLeft();
854 CHECK_EQ(payloadSizeBits % 8, 0u);
855
856 ALOGV("There's %zu bytes of payload.", payloadSizeBits / 8);
857 }
858 } else if (stream_id == 0xbe) { // padding_stream
859 CHECK_NE(PES_packet_length, 0u);
860 br->skipBits(PES_packet_length * 8);
861 } else {
862 CHECK_NE(PES_packet_length, 0u);
863 br->skipBits(PES_packet_length * 8);
864 }
865
866 return OK;
867 }
868
flush()869 status_t ATSParser::Stream::flush() {
870 if (mBuffer->size() == 0) {
871 return OK;
872 }
873
874 ALOGV("flushing stream 0x%04x size = %zu", mElementaryPID, mBuffer->size());
875
876 ABitReader br(mBuffer->data(), mBuffer->size());
877
878 status_t err = parsePES(&br);
879
880 mBuffer->setRange(0, 0);
881
882 return err;
883 }
884
onPayloadData(unsigned PTS_DTS_flags,uint64_t PTS,uint64_t,const uint8_t * data,size_t size)885 void ATSParser::Stream::onPayloadData(
886 unsigned PTS_DTS_flags, uint64_t PTS, uint64_t /* DTS */,
887 const uint8_t *data, size_t size) {
888 #if 0
889 ALOGI("payload streamType 0x%02x, PTS = 0x%016llx, dPTS = %lld",
890 mStreamType,
891 PTS,
892 (int64_t)PTS - mPrevPTS);
893 mPrevPTS = PTS;
894 #endif
895
896 ALOGV("onPayloadData mStreamType=0x%02x", mStreamType);
897
898 int64_t timeUs = 0ll; // no presentation timestamp available.
899 if (PTS_DTS_flags == 2 || PTS_DTS_flags == 3) {
900 timeUs = mProgram->convertPTSToTimestamp(PTS);
901 }
902
903 status_t err = mQueue->appendData(data, size, timeUs);
904
905 if (err != OK) {
906 return;
907 }
908
909 sp<ABuffer> accessUnit;
910 while ((accessUnit = mQueue->dequeueAccessUnit()) != NULL) {
911 if (mSource == NULL) {
912 sp<MetaData> meta = mQueue->getFormat();
913
914 if (meta != NULL) {
915 ALOGV("Stream PID 0x%08x of type 0x%02x now has data.",
916 mElementaryPID, mStreamType);
917
918 const char *mime;
919 if (meta->findCString(kKeyMIMEType, &mime)
920 && !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
921 && !IsIDR(accessUnit)) {
922 continue;
923 }
924 mSource = new AnotherPacketSource(meta);
925 mSource->queueAccessUnit(accessUnit);
926 }
927 } else if (mQueue->getFormat() != NULL) {
928 // After a discontinuity we invalidate the queue's format
929 // and won't enqueue any access units to the source until
930 // the queue has reestablished the new format.
931
932 if (mSource->getFormat() == NULL) {
933 mSource->setFormat(mQueue->getFormat());
934 }
935 mSource->queueAccessUnit(accessUnit);
936 }
937 }
938 }
939
getSource(SourceType type)940 sp<MediaSource> ATSParser::Stream::getSource(SourceType type) {
941 switch (type) {
942 case VIDEO:
943 {
944 if (isVideo()) {
945 return mSource;
946 }
947 break;
948 }
949
950 case AUDIO:
951 {
952 if (isAudio()) {
953 return mSource;
954 }
955 break;
956 }
957
958 default:
959 break;
960 }
961
962 return NULL;
963 }
964
965 ////////////////////////////////////////////////////////////////////////////////
966
ATSParser(uint32_t flags)967 ATSParser::ATSParser(uint32_t flags)
968 : mFlags(flags),
969 mAbsoluteTimeAnchorUs(-1ll),
970 mTimeOffsetValid(false),
971 mTimeOffsetUs(0ll),
972 mNumTSPacketsParsed(0),
973 mNumPCRs(0) {
974 mPSISections.add(0 /* PID */, new PSISection);
975 }
976
~ATSParser()977 ATSParser::~ATSParser() {
978 }
979
feedTSPacket(const void * data,size_t size)980 status_t ATSParser::feedTSPacket(const void *data, size_t size) {
981 CHECK_EQ(size, kTSPacketSize);
982
983 ABitReader br((const uint8_t *)data, kTSPacketSize);
984 return parseTS(&br);
985 }
986
signalDiscontinuity(DiscontinuityType type,const sp<AMessage> & extra)987 void ATSParser::signalDiscontinuity(
988 DiscontinuityType type, const sp<AMessage> &extra) {
989 int64_t mediaTimeUs;
990 if ((type & DISCONTINUITY_TIME)
991 && extra != NULL
992 && extra->findInt64(
993 IStreamListener::kKeyMediaTimeUs, &mediaTimeUs)) {
994 mAbsoluteTimeAnchorUs = mediaTimeUs;
995 } else if (type == DISCONTINUITY_ABSOLUTE_TIME) {
996 int64_t timeUs;
997 CHECK(extra->findInt64("timeUs", &timeUs));
998
999 CHECK(mPrograms.empty());
1000 mAbsoluteTimeAnchorUs = timeUs;
1001 return;
1002 } else if (type == DISCONTINUITY_TIME_OFFSET) {
1003 int64_t offset;
1004 CHECK(extra->findInt64("offset", &offset));
1005
1006 mTimeOffsetValid = true;
1007 mTimeOffsetUs = offset;
1008 return;
1009 }
1010
1011 for (size_t i = 0; i < mPrograms.size(); ++i) {
1012 mPrograms.editItemAt(i)->signalDiscontinuity(type, extra);
1013 }
1014 }
1015
signalEOS(status_t finalResult)1016 void ATSParser::signalEOS(status_t finalResult) {
1017 CHECK_NE(finalResult, (status_t)OK);
1018
1019 for (size_t i = 0; i < mPrograms.size(); ++i) {
1020 mPrograms.editItemAt(i)->signalEOS(finalResult);
1021 }
1022 }
1023
parseProgramAssociationTable(ABitReader * br)1024 void ATSParser::parseProgramAssociationTable(ABitReader *br) {
1025 unsigned table_id = br->getBits(8);
1026 ALOGV(" table_id = %u", table_id);
1027 if (table_id != 0x00u) {
1028 ALOGE("PAT data error!");
1029 return ;
1030 }
1031 unsigned section_syntax_indictor = br->getBits(1);
1032 ALOGV(" section_syntax_indictor = %u", section_syntax_indictor);
1033 CHECK_EQ(section_syntax_indictor, 1u);
1034
1035 CHECK_EQ(br->getBits(1), 0u);
1036 MY_LOGV(" reserved = %u", br->getBits(2));
1037
1038 unsigned section_length = br->getBits(12);
1039 ALOGV(" section_length = %u", section_length);
1040 CHECK_EQ(section_length & 0xc00, 0u);
1041
1042 MY_LOGV(" transport_stream_id = %u", br->getBits(16));
1043 MY_LOGV(" reserved = %u", br->getBits(2));
1044 MY_LOGV(" version_number = %u", br->getBits(5));
1045 MY_LOGV(" current_next_indicator = %u", br->getBits(1));
1046 MY_LOGV(" section_number = %u", br->getBits(8));
1047 MY_LOGV(" last_section_number = %u", br->getBits(8));
1048
1049 size_t numProgramBytes = (section_length - 5 /* header */ - 4 /* crc */);
1050 CHECK_EQ((numProgramBytes % 4), 0u);
1051
1052 for (size_t i = 0; i < numProgramBytes / 4; ++i) {
1053 unsigned program_number = br->getBits(16);
1054 ALOGV(" program_number = %u", program_number);
1055
1056 MY_LOGV(" reserved = %u", br->getBits(3));
1057
1058 if (program_number == 0) {
1059 MY_LOGV(" network_PID = 0x%04x", br->getBits(13));
1060 } else {
1061 unsigned programMapPID = br->getBits(13);
1062
1063 ALOGV(" program_map_PID = 0x%04x", programMapPID);
1064
1065 bool found = false;
1066 for (size_t index = 0; index < mPrograms.size(); ++index) {
1067 const sp<Program> &program = mPrograms.itemAt(index);
1068
1069 if (program->number() == program_number) {
1070 program->updateProgramMapPID(programMapPID);
1071 found = true;
1072 break;
1073 }
1074 }
1075
1076 if (!found) {
1077 mPrograms.push(
1078 new Program(this, program_number, programMapPID));
1079 }
1080
1081 if (mPSISections.indexOfKey(programMapPID) < 0) {
1082 mPSISections.add(programMapPID, new PSISection);
1083 }
1084 }
1085 }
1086
1087 MY_LOGV(" CRC = 0x%08x", br->getBits(32));
1088 }
1089
parsePID(ABitReader * br,unsigned PID,unsigned continuity_counter,unsigned payload_unit_start_indicator)1090 status_t ATSParser::parsePID(
1091 ABitReader *br, unsigned PID,
1092 unsigned continuity_counter,
1093 unsigned payload_unit_start_indicator) {
1094 ssize_t sectionIndex = mPSISections.indexOfKey(PID);
1095
1096 if (sectionIndex >= 0) {
1097 sp<PSISection> section = mPSISections.valueAt(sectionIndex);
1098
1099 if (payload_unit_start_indicator) {
1100 if (!section->isEmpty()) {
1101 return ERROR_UNSUPPORTED;
1102 }
1103
1104 unsigned skip = br->getBits(8);
1105 br->skipBits(skip * 8);
1106 }
1107
1108 CHECK((br->numBitsLeft() % 8) == 0);
1109 status_t err = section->append(br->data(), br->numBitsLeft() / 8);
1110
1111 if (err != OK) {
1112 return err;
1113 }
1114
1115 if (!section->isComplete()) {
1116 return OK;
1117 }
1118
1119 ABitReader sectionBits(section->data(), section->size());
1120
1121 if (PID == 0) {
1122 parseProgramAssociationTable(§ionBits);
1123 } else {
1124 bool handled = false;
1125 for (size_t i = 0; i < mPrograms.size(); ++i) {
1126 status_t err;
1127 if (!mPrograms.editItemAt(i)->parsePSISection(
1128 PID, §ionBits, &err)) {
1129 continue;
1130 }
1131
1132 if (err != OK) {
1133 return err;
1134 }
1135
1136 handled = true;
1137 break;
1138 }
1139
1140 if (!handled) {
1141 mPSISections.removeItem(PID);
1142 section.clear();
1143 }
1144 }
1145
1146 if (section != NULL) {
1147 section->clear();
1148 }
1149
1150 return OK;
1151 }
1152
1153 bool handled = false;
1154 for (size_t i = 0; i < mPrograms.size(); ++i) {
1155 status_t err;
1156 if (mPrograms.editItemAt(i)->parsePID(
1157 PID, continuity_counter, payload_unit_start_indicator,
1158 br, &err)) {
1159 if (err != OK) {
1160 return err;
1161 }
1162
1163 handled = true;
1164 break;
1165 }
1166 }
1167
1168 if (!handled) {
1169 ALOGV("PID 0x%04x not handled.", PID);
1170 }
1171
1172 return OK;
1173 }
1174
parseAdaptationField(ABitReader * br,unsigned PID)1175 void ATSParser::parseAdaptationField(ABitReader *br, unsigned PID) {
1176 unsigned adaptation_field_length = br->getBits(8);
1177
1178 if (adaptation_field_length > 0) {
1179 unsigned discontinuity_indicator = br->getBits(1);
1180
1181 if (discontinuity_indicator) {
1182 ALOGV("PID 0x%04x: discontinuity_indicator = 1 (!!!)", PID);
1183 }
1184
1185 br->skipBits(2);
1186 unsigned PCR_flag = br->getBits(1);
1187
1188 size_t numBitsRead = 4;
1189
1190 if (PCR_flag) {
1191 br->skipBits(4);
1192 uint64_t PCR_base = br->getBits(32);
1193 PCR_base = (PCR_base << 1) | br->getBits(1);
1194
1195 br->skipBits(6);
1196 unsigned PCR_ext = br->getBits(9);
1197
1198 // The number of bytes from the start of the current
1199 // MPEG2 transport stream packet up and including
1200 // the final byte of this PCR_ext field.
1201 size_t byteOffsetFromStartOfTSPacket =
1202 (188 - br->numBitsLeft() / 8);
1203
1204 uint64_t PCR = PCR_base * 300 + PCR_ext;
1205
1206 ALOGV("PID 0x%04x: PCR = 0x%016" PRIx64 " (%.2f)",
1207 PID, PCR, PCR / 27E6);
1208
1209 // The number of bytes received by this parser up to and
1210 // including the final byte of this PCR_ext field.
1211 size_t byteOffsetFromStart =
1212 mNumTSPacketsParsed * 188 + byteOffsetFromStartOfTSPacket;
1213
1214 for (size_t i = 0; i < mPrograms.size(); ++i) {
1215 updatePCR(PID, PCR, byteOffsetFromStart);
1216 }
1217
1218 numBitsRead += 52;
1219 }
1220
1221 CHECK_GE(adaptation_field_length * 8, numBitsRead);
1222
1223 br->skipBits(adaptation_field_length * 8 - numBitsRead);
1224 }
1225 }
1226
parseTS(ABitReader * br)1227 status_t ATSParser::parseTS(ABitReader *br) {
1228 ALOGV("---");
1229
1230 unsigned sync_byte = br->getBits(8);
1231 if (sync_byte != 0x47u) {
1232 ALOGE("[error] parseTS: return error as sync_byte=0x%x", sync_byte);
1233 return BAD_VALUE;
1234 }
1235
1236 if (br->getBits(1)) { // transport_error_indicator
1237 // silently ignore.
1238 return OK;
1239 }
1240
1241 unsigned payload_unit_start_indicator = br->getBits(1);
1242 ALOGV("payload_unit_start_indicator = %u", payload_unit_start_indicator);
1243
1244 MY_LOGV("transport_priority = %u", br->getBits(1));
1245
1246 unsigned PID = br->getBits(13);
1247 ALOGV("PID = 0x%04x", PID);
1248
1249 MY_LOGV("transport_scrambling_control = %u", br->getBits(2));
1250
1251 unsigned adaptation_field_control = br->getBits(2);
1252 ALOGV("adaptation_field_control = %u", adaptation_field_control);
1253
1254 unsigned continuity_counter = br->getBits(4);
1255 ALOGV("PID = 0x%04x, continuity_counter = %u", PID, continuity_counter);
1256
1257 // ALOGI("PID = 0x%04x, continuity_counter = %u", PID, continuity_counter);
1258
1259 if (adaptation_field_control == 2 || adaptation_field_control == 3) {
1260 parseAdaptationField(br, PID);
1261 }
1262
1263 status_t err = OK;
1264
1265 if (adaptation_field_control == 1 || adaptation_field_control == 3) {
1266 err = parsePID(
1267 br, PID, continuity_counter, payload_unit_start_indicator);
1268 }
1269
1270 ++mNumTSPacketsParsed;
1271
1272 return err;
1273 }
1274
getSource(SourceType type)1275 sp<MediaSource> ATSParser::getSource(SourceType type) {
1276 int which = -1; // any
1277
1278 for (size_t i = 0; i < mPrograms.size(); ++i) {
1279 const sp<Program> &program = mPrograms.editItemAt(i);
1280
1281 if (which >= 0 && (int)program->number() != which) {
1282 continue;
1283 }
1284
1285 sp<MediaSource> source = program->getSource(type);
1286
1287 if (source != NULL) {
1288 return source;
1289 }
1290 }
1291
1292 return NULL;
1293 }
1294
hasSource(SourceType type) const1295 bool ATSParser::hasSource(SourceType type) const {
1296 for (size_t i = 0; i < mPrograms.size(); ++i) {
1297 const sp<Program> &program = mPrograms.itemAt(i);
1298 if (program->hasSource(type)) {
1299 return true;
1300 }
1301 }
1302
1303 return false;
1304 }
1305
PTSTimeDeltaEstablished()1306 bool ATSParser::PTSTimeDeltaEstablished() {
1307 if (mPrograms.isEmpty()) {
1308 return false;
1309 }
1310
1311 return mPrograms.editItemAt(0)->PTSTimeDeltaEstablished();
1312 }
1313
updatePCR(unsigned,uint64_t PCR,size_t byteOffsetFromStart)1314 void ATSParser::updatePCR(
1315 unsigned /* PID */, uint64_t PCR, size_t byteOffsetFromStart) {
1316 ALOGV("PCR 0x%016" PRIx64 " @ %zu", PCR, byteOffsetFromStart);
1317
1318 if (mNumPCRs == 2) {
1319 mPCR[0] = mPCR[1];
1320 mPCRBytes[0] = mPCRBytes[1];
1321 mSystemTimeUs[0] = mSystemTimeUs[1];
1322 mNumPCRs = 1;
1323 }
1324
1325 mPCR[mNumPCRs] = PCR;
1326 mPCRBytes[mNumPCRs] = byteOffsetFromStart;
1327 mSystemTimeUs[mNumPCRs] = ALooper::GetNowUs();
1328
1329 ++mNumPCRs;
1330
1331 if (mNumPCRs == 2) {
1332 double transportRate =
1333 (mPCRBytes[1] - mPCRBytes[0]) * 27E6 / (mPCR[1] - mPCR[0]);
1334
1335 ALOGV("transportRate = %.2f bytes/sec", transportRate);
1336 }
1337 }
1338
1339 ////////////////////////////////////////////////////////////////////////////////
1340
PSISection()1341 ATSParser::PSISection::PSISection() {
1342 }
1343
~PSISection()1344 ATSParser::PSISection::~PSISection() {
1345 }
1346
append(const void * data,size_t size)1347 status_t ATSParser::PSISection::append(const void *data, size_t size) {
1348 if (mBuffer == NULL || mBuffer->size() + size > mBuffer->capacity()) {
1349 size_t newCapacity =
1350 (mBuffer == NULL) ? size : mBuffer->capacity() + size;
1351
1352 newCapacity = (newCapacity + 1023) & ~1023;
1353
1354 sp<ABuffer> newBuffer = new ABuffer(newCapacity);
1355
1356 if (mBuffer != NULL) {
1357 memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size());
1358 newBuffer->setRange(0, mBuffer->size());
1359 } else {
1360 newBuffer->setRange(0, 0);
1361 }
1362
1363 mBuffer = newBuffer;
1364 }
1365
1366 memcpy(mBuffer->data() + mBuffer->size(), data, size);
1367 mBuffer->setRange(0, mBuffer->size() + size);
1368
1369 return OK;
1370 }
1371
clear()1372 void ATSParser::PSISection::clear() {
1373 if (mBuffer != NULL) {
1374 mBuffer->setRange(0, 0);
1375 }
1376 }
1377
isComplete() const1378 bool ATSParser::PSISection::isComplete() const {
1379 if (mBuffer == NULL || mBuffer->size() < 3) {
1380 return false;
1381 }
1382
1383 unsigned sectionLength = U16_AT(mBuffer->data() + 1) & 0xfff;
1384 return mBuffer->size() >= sectionLength + 3;
1385 }
1386
isEmpty() const1387 bool ATSParser::PSISection::isEmpty() const {
1388 return mBuffer == NULL || mBuffer->size() == 0;
1389 }
1390
data() const1391 const uint8_t *ATSParser::PSISection::data() const {
1392 return mBuffer == NULL ? NULL : mBuffer->data();
1393 }
1394
size() const1395 size_t ATSParser::PSISection::size() const {
1396 return mBuffer == NULL ? 0 : mBuffer->size();
1397 }
1398
1399 } // namespace android
1400