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 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 122 MPEG2PSExtractor::~MPEG2PSExtractor() { 123 } 124 125 size_t MPEG2PSExtractor::countTracks() { 126 return mTracks.size(); 127 } 128 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 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 147 status_t MPEG2PSExtractor::getMetaData(MetaDataBase &meta) { 148 meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2PS); 149 150 return OK; 151 } 152 153 uint32_t MPEG2PSExtractor::flags() const { 154 return CAN_PAUSE; 155 } 156 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 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 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 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 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 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 633 MPEG2PSExtractor::Track::~Track() { 634 delete mQueue; 635 mQueue = NULL; 636 } 637 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 646 status_t MPEG2PSExtractor::Track::stop() { 647 if (mSource == NULL) { 648 return NO_INIT; 649 } 650 651 return mSource->stop(); 652 } 653 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 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 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 728 MPEG2PSExtractor::WrappedTrack::WrappedTrack( 729 MPEG2PSExtractor *extractor, const sp<Track> &track) 730 : mExtractor(extractor), 731 mTrack(track) { 732 } 733 734 MPEG2PSExtractor::WrappedTrack::~WrappedTrack() { 735 } 736 737 status_t MPEG2PSExtractor::WrappedTrack::start(MetaDataBase *params) { 738 return mTrack->start(params); 739 } 740 741 status_t MPEG2PSExtractor::WrappedTrack::stop() { 742 return mTrack->stop(); 743 } 744 745 status_t MPEG2PSExtractor::WrappedTrack::getFormat(MetaDataBase &meta) { 746 return mTrack->getFormat(meta); 747 } 748 749 status_t MPEG2PSExtractor::WrappedTrack::read( 750 MediaBufferBase **buffer, const ReadOptions *options) { 751 return mTrack->read(buffer, options); 752 } 753 754 //////////////////////////////////////////////////////////////////////////////// 755 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