1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "media/mp2t/ts_section_psi.h" 6 7 #include "base/basictypes.h" 8 #include "base/logging.h" 9 #include "media/base/bit_reader.h" 10 #include "media/mp2t/mp2t_common.h" 11 12 static bool IsCrcValid(const uint8* buf, int size) { 13 uint32 crc = 0xffffffffu; 14 const uint32 kCrcPoly = 0x4c11db7; 15 16 for (int k = 0; k < size; k++) { 17 int nbits = 8; 18 uint32 data_msb_aligned = buf[k]; 19 data_msb_aligned <<= (32 - nbits); 20 21 while (nbits > 0) { 22 if ((data_msb_aligned ^ crc) & 0x80000000) { 23 crc <<= 1; 24 crc ^= kCrcPoly; 25 } else { 26 crc <<= 1; 27 } 28 29 data_msb_aligned <<= 1; 30 nbits--; 31 } 32 } 33 34 return (crc == 0); 35 } 36 37 namespace media { 38 namespace mp2t { 39 40 TsSectionPsi::TsSectionPsi() 41 : wait_for_pusi_(true), 42 leading_bytes_to_discard_(0) { 43 } 44 45 TsSectionPsi::~TsSectionPsi() { 46 } 47 48 bool TsSectionPsi::Parse(bool payload_unit_start_indicator, 49 const uint8* buf, int size) { 50 // Ignore partial PSI. 51 if (wait_for_pusi_ && !payload_unit_start_indicator) 52 return true; 53 54 if (payload_unit_start_indicator) { 55 // Reset the state of the PSI section. 56 ResetPsiState(); 57 58 // Update the state. 59 wait_for_pusi_ = false; 60 DCHECK_GE(size, 1); 61 int pointer_field = buf[0]; 62 leading_bytes_to_discard_ = pointer_field; 63 buf++; 64 size--; 65 } 66 67 // Discard some leading bytes if needed. 68 if (leading_bytes_to_discard_ > 0) { 69 int nbytes_to_discard = std::min(leading_bytes_to_discard_, size); 70 buf += nbytes_to_discard; 71 size -= nbytes_to_discard; 72 leading_bytes_to_discard_ -= nbytes_to_discard; 73 } 74 if (size == 0) 75 return true; 76 77 // Add the data to the parser state. 78 psi_byte_queue_.Push(buf, size); 79 int raw_psi_size; 80 const uint8* raw_psi; 81 psi_byte_queue_.Peek(&raw_psi, &raw_psi_size); 82 83 // Check whether we have enough data to start parsing. 84 if (raw_psi_size < 3) 85 return true; 86 int section_length = 87 ((static_cast<int>(raw_psi[1]) << 8) | 88 (static_cast<int>(raw_psi[2]))) & 0xfff; 89 if (section_length >= 1021) 90 return false; 91 int psi_length = section_length + 3; 92 if (raw_psi_size < psi_length) { 93 // Don't throw an error when there is not enough data, 94 // just wait for more data to come. 95 return true; 96 } 97 98 // There should not be any trailing bytes after a PMT. 99 // Instead, the pointer field should be used to stuff bytes. 100 DVLOG_IF(1, raw_psi_size > psi_length) 101 << "Trailing bytes after a PSI section: " 102 << psi_length << " vs " << raw_psi_size; 103 104 // Verify the CRC. 105 RCHECK(IsCrcValid(raw_psi, psi_length)); 106 107 // Parse the PSI section. 108 BitReader bit_reader(raw_psi, raw_psi_size); 109 bool status = ParsePsiSection(&bit_reader); 110 if (status) 111 ResetPsiState(); 112 113 return status; 114 } 115 116 void TsSectionPsi::Flush() { 117 } 118 119 void TsSectionPsi::Reset() { 120 ResetPsiSection(); 121 ResetPsiState(); 122 } 123 124 void TsSectionPsi::ResetPsiState() { 125 wait_for_pusi_ = true; 126 psi_byte_queue_.Reset(); 127 leading_bytes_to_discard_ = 0; 128 } 129 130 } // namespace mp2t 131 } // namespace media 132 133