1 /*
2 * Copyright (C) 2011 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 "MPEG2PSExtractor"
19 #include <utils/Log.h>
20
21 #include "MPEG2PSExtractor.h"
22
23 #include "mpeg2ts/AnotherPacketSource.h"
24 #include "mpeg2ts/ESQueue.h"
25
26 #include <media/DataSourceBase.h>
27 #include <media/MediaTrack.h>
28 #include <media/stagefright/foundation/ABitReader.h>
29 #include <media/stagefright/foundation/ABuffer.h>
30 #include <media/stagefright/foundation/ADebug.h>
31 #include <media/stagefright/foundation/AMessage.h>
32 #include <media/stagefright/foundation/ByteUtils.h>
33 #include <media/stagefright/foundation/hexdump.h>
34 #include <media/stagefright/MediaDefs.h>
35 #include <media/stagefright/MediaErrors.h>
36 #include <media/stagefright/MetaData.h>
37 #include <utils/String8.h>
38
39 #include <inttypes.h>
40
41 namespace android {
42
43 struct MPEG2PSExtractor::Track : public MediaTrack, public RefBase {
44 Track(MPEG2PSExtractor *extractor,
45 unsigned stream_id, unsigned stream_type);
46
47 virtual status_t start(MetaDataBase *params);
48 virtual status_t stop();
49 virtual status_t getFormat(MetaDataBase &);
50
51 virtual status_t read(
52 MediaBufferBase **buffer, const ReadOptions *options);
53
54 protected:
55 virtual ~Track();
56
57 private:
58 friend struct MPEG2PSExtractor;
59
60 MPEG2PSExtractor *mExtractor;
61
62 unsigned mStreamID;
63 unsigned mStreamType;
64 ElementaryStreamQueue *mQueue;
65 sp<AnotherPacketSource> mSource;
66
67 status_t appendPESData(
68 unsigned PTS_DTS_flags,
69 uint64_t PTS, uint64_t DTS,
70 const uint8_t *data, size_t size);
71
72 DISALLOW_EVIL_CONSTRUCTORS(Track);
73 };
74
75 struct MPEG2PSExtractor::WrappedTrack : public MediaTrack {
76 WrappedTrack(MPEG2PSExtractor *extractor, const sp<Track> &track);
77
78 virtual status_t start(MetaDataBase *params);
79 virtual status_t stop();
80 virtual status_t getFormat(MetaDataBase &);
81
82 virtual status_t read(
83 MediaBufferBase **buffer, const ReadOptions *options);
84
85 protected:
86 virtual ~WrappedTrack();
87
88 private:
89 MPEG2PSExtractor *mExtractor;
90 sp<MPEG2PSExtractor::Track> mTrack;
91
92 DISALLOW_EVIL_CONSTRUCTORS(WrappedTrack);
93 };
94
95 ////////////////////////////////////////////////////////////////////////////////
96
MPEG2PSExtractor(DataSourceBase * source)97 MPEG2PSExtractor::MPEG2PSExtractor(DataSourceBase *source)
98 : mDataSource(source),
99 mOffset(0),
100 mFinalResult(OK),
101 mBuffer(new ABuffer(0)),
102 mScanning(true),
103 mProgramStreamMapValid(false) {
104 for (size_t i = 0; i < 500; ++i) {
105 if (feedMore() != OK) {
106 break;
107 }
108 }
109
110 // Remove all tracks that were unable to determine their format.
111 MetaDataBase meta;
112 for (size_t i = mTracks.size(); i > 0;) {
113 i--;
114 if (mTracks.valueAt(i)->getFormat(meta) != OK) {
115 mTracks.removeItemsAt(i);
116 }
117 }
118
119 mScanning = false;
120 }
121
~MPEG2PSExtractor()122 MPEG2PSExtractor::~MPEG2PSExtractor() {
123 }
124
countTracks()125 size_t MPEG2PSExtractor::countTracks() {
126 return mTracks.size();
127 }
128
getTrack(size_t index)129 MediaTrack *MPEG2PSExtractor::getTrack(size_t index) {
130 if (index >= mTracks.size()) {
131 return NULL;
132 }
133
134 return new WrappedTrack(this, mTracks.valueAt(index));
135 }
136
getTrackMetaData(MetaDataBase & meta,size_t index,uint32_t)137 status_t MPEG2PSExtractor::getTrackMetaData(
138 MetaDataBase &meta,
139 size_t index, uint32_t /* flags */) {
140 if (index >= mTracks.size()) {
141 return UNKNOWN_ERROR;
142 }
143
144 return mTracks.valueAt(index)->getFormat(meta);
145 }
146
getMetaData(MetaDataBase & meta)147 status_t MPEG2PSExtractor::getMetaData(MetaDataBase &meta) {
148 meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2PS);
149
150 return OK;
151 }
152
flags() const153 uint32_t MPEG2PSExtractor::flags() const {
154 return CAN_PAUSE;
155 }
156
feedMore()157 status_t MPEG2PSExtractor::feedMore() {
158 Mutex::Autolock autoLock(mLock);
159
160 // How much data we're reading at a time
161 static const size_t kChunkSize = 8192;
162
163 for (;;) {
164 status_t err = dequeueChunk();
165
166 if (err == -EAGAIN && mFinalResult == OK) {
167 memmove(mBuffer->base(), mBuffer->data(), mBuffer->size());
168 mBuffer->setRange(0, mBuffer->size());
169
170 if (mBuffer->size() + kChunkSize > mBuffer->capacity()) {
171 size_t newCapacity = mBuffer->capacity() + kChunkSize;
172 sp<ABuffer> newBuffer = new ABuffer(newCapacity);
173 memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size());
174 newBuffer->setRange(0, mBuffer->size());
175 mBuffer = newBuffer;
176 }
177
178 ssize_t n = mDataSource->readAt(
179 mOffset, mBuffer->data() + mBuffer->size(), kChunkSize);
180
181 if (n < (ssize_t)kChunkSize) {
182 mFinalResult = (n < 0) ? (status_t)n : ERROR_END_OF_STREAM;
183 return mFinalResult;
184 }
185
186 mBuffer->setRange(mBuffer->offset(), mBuffer->size() + n);
187 mOffset += n;
188 } else if (err != OK) {
189 mFinalResult = err;
190 return err;
191 } else {
192 return OK;
193 }
194 }
195 }
196
dequeueChunk()197 status_t MPEG2PSExtractor::dequeueChunk() {
198 if (mBuffer->size() < 4) {
199 return -EAGAIN;
200 }
201
202 if (memcmp("\x00\x00\x01", mBuffer->data(), 3)) {
203 return ERROR_MALFORMED;
204 }
205
206 unsigned chunkType = mBuffer->data()[3];
207
208 ssize_t res;
209
210 switch (chunkType) {
211 case 0xba:
212 {
213 res = dequeuePack();
214 break;
215 }
216
217 case 0xbb:
218 {
219 res = dequeueSystemHeader();
220 break;
221 }
222
223 default:
224 {
225 res = dequeuePES();
226 break;
227 }
228 }
229
230 if (res > 0) {
231 if (mBuffer->size() < (size_t)res) {
232 return -EAGAIN;
233 }
234
235 mBuffer->setRange(mBuffer->offset() + res, mBuffer->size() - res);
236 res = OK;
237 }
238
239 return res;
240 }
241
dequeuePack()242 ssize_t MPEG2PSExtractor::dequeuePack() {
243 // 32 + 2 + 3 + 1 + 15 + 1 + 15+ 1 + 9 + 1 + 22 + 1 + 1 | +5
244
245 if (mBuffer->size() < 14) {
246 return -EAGAIN;
247 }
248
249 unsigned pack_stuffing_length = mBuffer->data()[13] & 7;
250
251 return pack_stuffing_length + 14;
252 }
253
dequeueSystemHeader()254 ssize_t MPEG2PSExtractor::dequeueSystemHeader() {
255 if (mBuffer->size() < 6) {
256 return -EAGAIN;
257 }
258
259 unsigned header_length = U16_AT(mBuffer->data() + 4);
260
261 return header_length + 6;
262 }
263
dequeuePES()264 ssize_t MPEG2PSExtractor::dequeuePES() {
265 if (mBuffer->size() < 6) {
266 return -EAGAIN;
267 }
268
269 unsigned PES_packet_length = U16_AT(mBuffer->data() + 4);
270 if (PES_packet_length == 0u) {
271 ALOGE("PES_packet_length is 0");
272 return -EAGAIN;
273 }
274
275 size_t n = PES_packet_length + 6;
276
277 if (mBuffer->size() < n) {
278 return -EAGAIN;
279 }
280
281 ABitReader br(mBuffer->data(), n);
282
283 unsigned packet_startcode_prefix = br.getBits(24);
284
285 ALOGV("packet_startcode_prefix = 0x%08x", packet_startcode_prefix);
286
287 if (packet_startcode_prefix != 1) {
288 ALOGV("Supposedly payload_unit_start=1 unit does not start "
289 "with startcode.");
290
291 return ERROR_MALFORMED;
292 }
293
294 if (packet_startcode_prefix != 0x000001u) {
295 ALOGE("Wrong PES prefix");
296 return ERROR_MALFORMED;
297 }
298
299 unsigned stream_id = br.getBits(8);
300 ALOGV("stream_id = 0x%02x", stream_id);
301
302 /* unsigned PES_packet_length = */br.getBits(16);
303
304 if (stream_id == 0xbc) {
305 // program_stream_map
306
307 if (!mScanning) {
308 return n;
309 }
310
311 mStreamTypeByESID.clear();
312
313 /* unsigned current_next_indicator = */br.getBits(1);
314 /* unsigned reserved = */br.getBits(2);
315 /* unsigned program_stream_map_version = */br.getBits(5);
316 /* unsigned reserved = */br.getBits(7);
317 /* unsigned marker_bit = */br.getBits(1);
318 unsigned program_stream_info_length = br.getBits(16);
319
320 size_t offset = 0;
321 while (offset < program_stream_info_length) {
322 if (offset + 2 > program_stream_info_length) {
323 return ERROR_MALFORMED;
324 }
325
326 unsigned descriptor_tag = br.getBits(8);
327 unsigned descriptor_length = br.getBits(8);
328
329 ALOGI("found descriptor tag 0x%02x of length %u",
330 descriptor_tag, descriptor_length);
331
332 if (offset + 2 + descriptor_length > program_stream_info_length) {
333 return ERROR_MALFORMED;
334 }
335
336 br.skipBits(8 * descriptor_length);
337
338 offset += 2 + descriptor_length;
339 }
340
341 unsigned elementary_stream_map_length = br.getBits(16);
342
343 offset = 0;
344 while (offset < elementary_stream_map_length) {
345 if (offset + 4 > elementary_stream_map_length) {
346 return ERROR_MALFORMED;
347 }
348
349 unsigned stream_type = br.getBits(8);
350 unsigned elementary_stream_id = br.getBits(8);
351
352 ALOGI("elementary stream id 0x%02x has stream type 0x%02x",
353 elementary_stream_id, stream_type);
354
355 mStreamTypeByESID.add(elementary_stream_id, stream_type);
356
357 unsigned elementary_stream_info_length = br.getBits(16);
358
359 if (offset + 4 + elementary_stream_info_length
360 > elementary_stream_map_length) {
361 return ERROR_MALFORMED;
362 }
363
364 offset += 4 + elementary_stream_info_length;
365 }
366
367 /* unsigned CRC32 = */br.getBits(32);
368
369 mProgramStreamMapValid = true;
370 } else if (stream_id != 0xbe // padding_stream
371 && stream_id != 0xbf // private_stream_2
372 && stream_id != 0xf0 // ECM
373 && stream_id != 0xf1 // EMM
374 && stream_id != 0xff // program_stream_directory
375 && stream_id != 0xf2 // DSMCC
376 && stream_id != 0xf8) { // H.222.1 type E
377 /* unsigned PES_marker_bits = */br.getBits(2); // should be 0x2(hex)
378 /* unsigned PES_scrambling_control = */br.getBits(2);
379 /* unsigned PES_priority = */br.getBits(1);
380 /* unsigned data_alignment_indicator = */br.getBits(1);
381 /* unsigned copyright = */br.getBits(1);
382 /* unsigned original_or_copy = */br.getBits(1);
383
384 unsigned PTS_DTS_flags = br.getBits(2);
385 ALOGV("PTS_DTS_flags = %u", PTS_DTS_flags);
386
387 unsigned ESCR_flag = br.getBits(1);
388 ALOGV("ESCR_flag = %u", ESCR_flag);
389
390 unsigned ES_rate_flag = br.getBits(1);
391 ALOGV("ES_rate_flag = %u", ES_rate_flag);
392
393 unsigned DSM_trick_mode_flag = br.getBits(1);
394 ALOGV("DSM_trick_mode_flag = %u", DSM_trick_mode_flag);
395
396 unsigned additional_copy_info_flag = br.getBits(1);
397 ALOGV("additional_copy_info_flag = %u", additional_copy_info_flag);
398
399 /* unsigned PES_CRC_flag = */br.getBits(1);
400 /* PES_extension_flag = */br.getBits(1);
401
402 unsigned PES_header_data_length = br.getBits(8);
403 ALOGV("PES_header_data_length = %u", PES_header_data_length);
404
405 unsigned optional_bytes_remaining = PES_header_data_length;
406
407 uint64_t PTS = 0, DTS = 0;
408
409 if (PTS_DTS_flags == 2 || PTS_DTS_flags == 3) {
410 if (optional_bytes_remaining < 5u) {
411 return ERROR_MALFORMED;
412 }
413
414 if (br.getBits(4) != PTS_DTS_flags) {
415 return ERROR_MALFORMED;
416 }
417
418 PTS = ((uint64_t)br.getBits(3)) << 30;
419 if (br.getBits(1) != 1u) {
420 return ERROR_MALFORMED;
421 }
422 PTS |= ((uint64_t)br.getBits(15)) << 15;
423 if (br.getBits(1) != 1u) {
424 return ERROR_MALFORMED;
425 }
426 PTS |= br.getBits(15);
427 if (br.getBits(1) != 1u) {
428 return ERROR_MALFORMED;
429 }
430
431 ALOGV("PTS = %" PRIu64, PTS);
432 // ALOGI("PTS = %.2f secs", PTS / 90000.0f);
433
434 optional_bytes_remaining -= 5;
435
436 if (PTS_DTS_flags == 3) {
437 if (optional_bytes_remaining < 5u) {
438 return ERROR_MALFORMED;
439 }
440
441 if (br.getBits(4) != 1u) {
442 return ERROR_MALFORMED;
443 }
444
445 DTS = ((uint64_t)br.getBits(3)) << 30;
446 if (br.getBits(1) != 1u) {
447 return ERROR_MALFORMED;
448 }
449 DTS |= ((uint64_t)br.getBits(15)) << 15;
450 if (br.getBits(1) != 1u) {
451 return ERROR_MALFORMED;
452 }
453 DTS |= br.getBits(15);
454 if (br.getBits(1) != 1u) {
455 return ERROR_MALFORMED;
456 }
457
458 ALOGV("DTS = %" PRIu64, DTS);
459
460 optional_bytes_remaining -= 5;
461 }
462 }
463
464 if (ESCR_flag) {
465 if (optional_bytes_remaining < 6u) {
466 return ERROR_MALFORMED;
467 }
468
469 br.getBits(2);
470
471 uint64_t ESCR = ((uint64_t)br.getBits(3)) << 30;
472 if (br.getBits(1) != 1u) {
473 return ERROR_MALFORMED;
474 }
475 ESCR |= ((uint64_t)br.getBits(15)) << 15;
476 if (br.getBits(1) != 1u) {
477 return ERROR_MALFORMED;
478 }
479 ESCR |= br.getBits(15);
480 if (br.getBits(1) != 1u) {
481 return ERROR_MALFORMED;
482 }
483
484 ALOGV("ESCR = %" PRIu64, ESCR);
485 /* unsigned ESCR_extension = */br.getBits(9);
486
487 if (br.getBits(1) != 1u) {
488 return ERROR_MALFORMED;
489 }
490
491 optional_bytes_remaining -= 6;
492 }
493
494 if (ES_rate_flag) {
495 if (optional_bytes_remaining < 3u) {
496 return ERROR_MALFORMED;
497 }
498
499 if (br.getBits(1) != 1u) {
500 return ERROR_MALFORMED;
501 }
502 /* unsigned ES_rate = */br.getBits(22);
503 if (br.getBits(1) != 1u) {
504 return ERROR_MALFORMED;
505 }
506
507 optional_bytes_remaining -= 3;
508 }
509
510 if (br.numBitsLeft() < optional_bytes_remaining * 8) {
511 return ERROR_MALFORMED;
512 }
513
514 br.skipBits(optional_bytes_remaining * 8);
515
516 // ES data follows.
517
518 if (PES_packet_length < PES_header_data_length + 3) {
519 return ERROR_MALFORMED;
520 }
521
522 unsigned dataLength =
523 PES_packet_length - 3 - PES_header_data_length;
524
525 if (br.numBitsLeft() < dataLength * 8) {
526 ALOGE("PES packet does not carry enough data to contain "
527 "payload. (numBitsLeft = %zu, required = %u)",
528 br.numBitsLeft(), dataLength * 8);
529
530 return ERROR_MALFORMED;
531 }
532
533 if (br.numBitsLeft() < dataLength * 8) {
534 return ERROR_MALFORMED;
535 }
536
537 ssize_t index = mTracks.indexOfKey(stream_id);
538 if (index < 0 && mScanning) {
539 unsigned streamType;
540
541 ssize_t streamTypeIndex;
542 if (mProgramStreamMapValid
543 && (streamTypeIndex =
544 mStreamTypeByESID.indexOfKey(stream_id)) >= 0) {
545 streamType = mStreamTypeByESID.valueAt(streamTypeIndex);
546 } else if ((stream_id & ~0x1f) == 0xc0) {
547 // ISO/IEC 13818-3 or ISO/IEC 11172-3 or ISO/IEC 13818-7
548 // or ISO/IEC 14496-3 audio
549 streamType = ATSParser::STREAMTYPE_MPEG2_AUDIO;
550 } else if ((stream_id & ~0x0f) == 0xe0) {
551 // ISO/IEC 13818-2 or ISO/IEC 11172-2 or ISO/IEC 14496-2 video
552 streamType = ATSParser::STREAMTYPE_MPEG2_VIDEO;
553 } else {
554 streamType = ATSParser::STREAMTYPE_RESERVED;
555 }
556
557 index = mTracks.add(
558 stream_id, new Track(this, stream_id, streamType));
559 }
560
561 status_t err = OK;
562
563 if (index >= 0) {
564 err =
565 mTracks.editValueAt(index)->appendPESData(
566 PTS_DTS_flags, PTS, DTS, br.data(), dataLength);
567 }
568
569 br.skipBits(dataLength * 8);
570
571 if (err != OK) {
572 return err;
573 }
574 } else if (stream_id == 0xbe) { // padding_stream
575 if (PES_packet_length == 0u) {
576 return ERROR_MALFORMED;
577 }
578 br.skipBits(PES_packet_length * 8);
579 } else {
580 if (PES_packet_length == 0u) {
581 return ERROR_MALFORMED;
582 }
583 br.skipBits(PES_packet_length * 8);
584 }
585
586 return n;
587 }
588
589 ////////////////////////////////////////////////////////////////////////////////
590
Track(MPEG2PSExtractor * extractor,unsigned stream_id,unsigned stream_type)591 MPEG2PSExtractor::Track::Track(
592 MPEG2PSExtractor *extractor, unsigned stream_id, unsigned stream_type)
593 : mExtractor(extractor),
594 mStreamID(stream_id),
595 mStreamType(stream_type),
596 mQueue(NULL) {
597 bool supported = true;
598 ElementaryStreamQueue::Mode mode;
599
600 switch (mStreamType) {
601 case ATSParser::STREAMTYPE_H264:
602 mode = ElementaryStreamQueue::H264;
603 break;
604 case ATSParser::STREAMTYPE_MPEG2_AUDIO_ADTS:
605 mode = ElementaryStreamQueue::AAC;
606 break;
607 case ATSParser::STREAMTYPE_MPEG1_AUDIO:
608 case ATSParser::STREAMTYPE_MPEG2_AUDIO:
609 mode = ElementaryStreamQueue::MPEG_AUDIO;
610 break;
611
612 case ATSParser::STREAMTYPE_MPEG1_VIDEO:
613 case ATSParser::STREAMTYPE_MPEG2_VIDEO:
614 mode = ElementaryStreamQueue::MPEG_VIDEO;
615 break;
616
617 case ATSParser::STREAMTYPE_MPEG4_VIDEO:
618 mode = ElementaryStreamQueue::MPEG4_VIDEO;
619 break;
620
621 default:
622 supported = false;
623 break;
624 }
625
626 if (supported) {
627 mQueue = new ElementaryStreamQueue(mode);
628 } else {
629 ALOGI("unsupported stream ID 0x%02x", stream_id);
630 }
631 }
632
~Track()633 MPEG2PSExtractor::Track::~Track() {
634 delete mQueue;
635 mQueue = NULL;
636 }
637
start(MetaDataBase *)638 status_t MPEG2PSExtractor::Track::start(MetaDataBase *) {
639 if (mSource == NULL) {
640 return NO_INIT;
641 }
642
643 return mSource->start(NULL); // AnotherPacketSource::start doesn't use its argument
644 }
645
stop()646 status_t MPEG2PSExtractor::Track::stop() {
647 if (mSource == NULL) {
648 return NO_INIT;
649 }
650
651 return mSource->stop();
652 }
653
getFormat(MetaDataBase & meta)654 status_t MPEG2PSExtractor::Track::getFormat(MetaDataBase &meta) {
655 if (mSource == NULL) {
656 return NO_INIT;
657 }
658
659 sp<MetaData> sourceMeta = mSource->getFormat();
660 meta = *sourceMeta;
661 return OK;
662 }
663
read(MediaBufferBase ** buffer,const ReadOptions * options)664 status_t MPEG2PSExtractor::Track::read(
665 MediaBufferBase **buffer, const ReadOptions *options) {
666 if (mSource == NULL) {
667 return NO_INIT;
668 }
669
670 status_t finalResult;
671 while (!mSource->hasBufferAvailable(&finalResult)) {
672 if (finalResult != OK) {
673 return ERROR_END_OF_STREAM;
674 }
675
676 status_t err = mExtractor->feedMore();
677
678 if (err != OK) {
679 mSource->signalEOS(err);
680 }
681 }
682
683 return mSource->read(buffer, options);
684 }
685
appendPESData(unsigned PTS_DTS_flags,uint64_t PTS,uint64_t,const uint8_t * data,size_t size)686 status_t MPEG2PSExtractor::Track::appendPESData(
687 unsigned PTS_DTS_flags,
688 uint64_t PTS, uint64_t /* DTS */,
689 const uint8_t *data, size_t size) {
690 if (mQueue == NULL) {
691 return OK;
692 }
693
694 int64_t timeUs;
695 if (PTS_DTS_flags == 2 || PTS_DTS_flags == 3) {
696 timeUs = (PTS * 100) / 9;
697 } else {
698 timeUs = 0;
699 }
700
701 status_t err = mQueue->appendData(data, size, timeUs);
702
703 if (err != OK) {
704 return err;
705 }
706
707 sp<ABuffer> accessUnit;
708 while ((accessUnit = mQueue->dequeueAccessUnit()) != NULL) {
709 if (mSource == NULL) {
710 sp<MetaData> meta = mQueue->getFormat();
711
712 if (meta != NULL) {
713 ALOGV("Stream ID 0x%02x now has data.", mStreamID);
714
715 mSource = new AnotherPacketSource(meta);
716 mSource->queueAccessUnit(accessUnit);
717 }
718 } else if (mQueue->getFormat() != NULL) {
719 mSource->queueAccessUnit(accessUnit);
720 }
721 }
722
723 return OK;
724 }
725
726 ////////////////////////////////////////////////////////////////////////////////
727
WrappedTrack(MPEG2PSExtractor * extractor,const sp<Track> & track)728 MPEG2PSExtractor::WrappedTrack::WrappedTrack(
729 MPEG2PSExtractor *extractor, const sp<Track> &track)
730 : mExtractor(extractor),
731 mTrack(track) {
732 }
733
~WrappedTrack()734 MPEG2PSExtractor::WrappedTrack::~WrappedTrack() {
735 }
736
start(MetaDataBase * params)737 status_t MPEG2PSExtractor::WrappedTrack::start(MetaDataBase *params) {
738 return mTrack->start(params);
739 }
740
stop()741 status_t MPEG2PSExtractor::WrappedTrack::stop() {
742 return mTrack->stop();
743 }
744
getFormat(MetaDataBase & meta)745 status_t MPEG2PSExtractor::WrappedTrack::getFormat(MetaDataBase &meta) {
746 return mTrack->getFormat(meta);
747 }
748
read(MediaBufferBase ** buffer,const ReadOptions * options)749 status_t MPEG2PSExtractor::WrappedTrack::read(
750 MediaBufferBase **buffer, const ReadOptions *options) {
751 return mTrack->read(buffer, options);
752 }
753
754 ////////////////////////////////////////////////////////////////////////////////
755
SniffMPEG2PS(DataSourceBase * source,float * confidence)756 bool SniffMPEG2PS(
757 DataSourceBase *source, float *confidence) {
758 uint8_t header[5];
759 if (source->readAt(0, header, sizeof(header)) < (ssize_t)sizeof(header)) {
760 return false;
761 }
762
763 if (memcmp("\x00\x00\x01\xba", header, 4) || (header[4] >> 6) != 1) {
764 return false;
765 }
766
767 *confidence = 0.25f; // Slightly larger than .mp3 extractor's confidence
768
769 return true;
770 }
771
772 } // namespace android
773