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