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_pes.h" 6 7 #include "base/logging.h" 8 #include "base/strings/string_number_conversions.h" 9 #include "media/base/bit_reader.h" 10 #include "media/base/buffers.h" 11 #include "media/mp2t/es_parser.h" 12 #include "media/mp2t/mp2t_common.h" 13 14 static const int kPesStartCode = 0x000001; 15 16 // Given that |time| is coded using 33 bits, 17 // UnrollTimestamp returns the corresponding unrolled timestamp. 18 // The unrolled timestamp is defined by: 19 // |time| + k * (2 ^ 33) 20 // where k is estimated so that the unrolled timestamp 21 // is as close as possible to |previous_unrolled_time|. 22 static int64 UnrollTimestamp(int64 previous_unrolled_time, int64 time) { 23 // Mpeg2 TS timestamps have an accuracy of 33 bits. 24 const int nbits = 33; 25 26 // |timestamp| has a precision of |nbits| 27 // so make sure the highest bits are set to 0. 28 DCHECK_EQ((time >> nbits), 0); 29 30 // Consider 3 possibilities to estimate the missing high bits of |time|. 31 int64 previous_unrolled_time_high = 32 (previous_unrolled_time >> nbits); 33 int64 time0 = ((previous_unrolled_time_high - 1) << nbits) | time; 34 int64 time1 = ((previous_unrolled_time_high + 0) << nbits) | time; 35 int64 time2 = ((previous_unrolled_time_high + 1) << nbits) | time; 36 37 // Select the min absolute difference with the current time 38 // so as to ensure time continuity. 39 int64 diff0 = time0 - previous_unrolled_time; 40 int64 diff1 = time1 - previous_unrolled_time; 41 int64 diff2 = time2 - previous_unrolled_time; 42 if (diff0 < 0) 43 diff0 = -diff0; 44 if (diff1 < 0) 45 diff1 = -diff1; 46 if (diff2 < 0) 47 diff2 = -diff2; 48 49 int64 unrolled_time; 50 int64 min_diff; 51 if (diff1 < diff0) { 52 unrolled_time = time1; 53 min_diff = diff1; 54 } else { 55 unrolled_time = time0; 56 min_diff = diff0; 57 } 58 if (diff2 < min_diff) 59 unrolled_time = time2; 60 61 return unrolled_time; 62 } 63 64 static bool IsTimestampSectionValid(int64 timestamp_section) { 65 // |pts_section| has 40 bits: 66 // - starting with either '0010' or '0011' or '0001' 67 // - and ending with a marker bit. 68 // See ITU H.222 standard - PES section. 69 70 // Verify that all the marker bits are set to one. 71 return ((timestamp_section & 0x1) != 0) && 72 ((timestamp_section & 0x10000) != 0) && 73 ((timestamp_section & 0x100000000) != 0); 74 } 75 76 static int64 ConvertTimestampSectionToTimestamp(int64 timestamp_section) { 77 return (((timestamp_section >> 33) & 0x7) << 30) | 78 (((timestamp_section >> 17) & 0x7fff) << 15) | 79 (((timestamp_section >> 1) & 0x7fff) << 0); 80 } 81 82 namespace media { 83 namespace mp2t { 84 85 TsSectionPes::TsSectionPes(scoped_ptr<EsParser> es_parser) 86 : es_parser_(es_parser.release()), 87 wait_for_pusi_(true), 88 previous_pts_valid_(false), 89 previous_pts_(0), 90 previous_dts_valid_(false), 91 previous_dts_(0) { 92 DCHECK(es_parser_); 93 } 94 95 TsSectionPes::~TsSectionPes() { 96 } 97 98 bool TsSectionPes::Parse(bool payload_unit_start_indicator, 99 const uint8* buf, int size) { 100 // Ignore partial PES. 101 if (wait_for_pusi_ && !payload_unit_start_indicator) 102 return true; 103 104 bool parse_result = true; 105 if (payload_unit_start_indicator) { 106 // Try emitting a packet since we might have a pending PES packet 107 // with an undefined size. 108 // In this case, a unit is emitted when the next unit is coming. 109 int raw_pes_size; 110 const uint8* raw_pes; 111 pes_byte_queue_.Peek(&raw_pes, &raw_pes_size); 112 if (raw_pes_size > 0) 113 parse_result = Emit(true); 114 115 // Reset the state. 116 ResetPesState(); 117 118 // Update the state. 119 wait_for_pusi_ = false; 120 } 121 122 // Add the data to the parser state. 123 if (size > 0) 124 pes_byte_queue_.Push(buf, size); 125 126 // Try emitting the current PES packet. 127 return (parse_result && Emit(false)); 128 } 129 130 void TsSectionPes::Flush() { 131 // Try emitting a packet since we might have a pending PES packet 132 // with an undefined size. 133 Emit(true); 134 135 // Flush the underlying ES parser. 136 es_parser_->Flush(); 137 } 138 139 void TsSectionPes::Reset() { 140 ResetPesState(); 141 142 previous_pts_valid_ = false; 143 previous_pts_ = 0; 144 previous_dts_valid_ = false; 145 previous_dts_ = 0; 146 147 es_parser_->Reset(); 148 } 149 150 bool TsSectionPes::Emit(bool emit_for_unknown_size) { 151 int raw_pes_size; 152 const uint8* raw_pes; 153 pes_byte_queue_.Peek(&raw_pes, &raw_pes_size); 154 155 // A PES should be at least 6 bytes. 156 // Wait for more data to come if not enough bytes. 157 if (raw_pes_size < 6) 158 return true; 159 160 // Check whether we have enough data to start parsing. 161 int pes_packet_length = 162 (static_cast<int>(raw_pes[4]) << 8) | 163 (static_cast<int>(raw_pes[5])); 164 if ((pes_packet_length == 0 && !emit_for_unknown_size) || 165 (pes_packet_length != 0 && raw_pes_size < pes_packet_length + 6)) { 166 // Wait for more data to come either because: 167 // - there are not enough bytes, 168 // - or the PES size is unknown and the "force emit" flag is not set. 169 // (PES size might be unknown for video PES packet). 170 return true; 171 } 172 DVLOG(LOG_LEVEL_PES) << "pes_packet_length=" << pes_packet_length; 173 174 // Parse the packet. 175 bool parse_result = ParseInternal(raw_pes, raw_pes_size); 176 177 // Reset the state. 178 ResetPesState(); 179 180 return parse_result; 181 } 182 183 bool TsSectionPes::ParseInternal(const uint8* raw_pes, int raw_pes_size) { 184 BitReader bit_reader(raw_pes, raw_pes_size); 185 186 // Read up to the pes_packet_length (6 bytes). 187 int packet_start_code_prefix; 188 int stream_id; 189 int pes_packet_length; 190 RCHECK(bit_reader.ReadBits(24, &packet_start_code_prefix)); 191 RCHECK(bit_reader.ReadBits(8, &stream_id)); 192 RCHECK(bit_reader.ReadBits(16, &pes_packet_length)); 193 194 RCHECK(packet_start_code_prefix == kPesStartCode); 195 DVLOG(LOG_LEVEL_PES) << "stream_id=" << std::hex << stream_id << std::dec; 196 if (pes_packet_length == 0) 197 pes_packet_length = bit_reader.bits_available() / 8; 198 199 // Ignore the PES for unknown stream IDs. 200 // See ITU H.222 Table 2-22 "Stream_id assignments" 201 bool is_audio_stream_id = ((stream_id & 0xe0) == 0xc0); 202 bool is_video_stream_id = ((stream_id & 0xf0) == 0xe0); 203 if (!is_audio_stream_id && !is_video_stream_id) 204 return true; 205 206 // Read up to "pes_header_data_length". 207 int dummy_2; 208 int PES_scrambling_control; 209 int PES_priority; 210 int data_alignment_indicator; 211 int copyright; 212 int original_or_copy; 213 int pts_dts_flags; 214 int escr_flag; 215 int es_rate_flag; 216 int dsm_trick_mode_flag; 217 int additional_copy_info_flag; 218 int pes_crc_flag; 219 int pes_extension_flag; 220 int pes_header_data_length; 221 RCHECK(bit_reader.ReadBits(2, &dummy_2)); 222 RCHECK(dummy_2 == 0x2); 223 RCHECK(bit_reader.ReadBits(2, &PES_scrambling_control)); 224 RCHECK(bit_reader.ReadBits(1, &PES_priority)); 225 RCHECK(bit_reader.ReadBits(1, &data_alignment_indicator)); 226 RCHECK(bit_reader.ReadBits(1, ©right)); 227 RCHECK(bit_reader.ReadBits(1, &original_or_copy)); 228 RCHECK(bit_reader.ReadBits(2, &pts_dts_flags)); 229 RCHECK(bit_reader.ReadBits(1, &escr_flag)); 230 RCHECK(bit_reader.ReadBits(1, &es_rate_flag)); 231 RCHECK(bit_reader.ReadBits(1, &dsm_trick_mode_flag)); 232 RCHECK(bit_reader.ReadBits(1, &additional_copy_info_flag)); 233 RCHECK(bit_reader.ReadBits(1, &pes_crc_flag)); 234 RCHECK(bit_reader.ReadBits(1, &pes_extension_flag)); 235 RCHECK(bit_reader.ReadBits(8, &pes_header_data_length)); 236 int pes_header_start_size = bit_reader.bits_available() / 8; 237 238 // Compute the size and the offset of the ES payload. 239 // "6" for the 6 bytes read before and including |pes_packet_length|. 240 // "3" for the 3 bytes read before and including |pes_header_data_length|. 241 int es_size = pes_packet_length - 3 - pes_header_data_length; 242 int es_offset = 6 + 3 + pes_header_data_length; 243 RCHECK(es_size >= 0); 244 RCHECK(es_offset + es_size <= raw_pes_size); 245 246 // Read the timing information section. 247 bool is_pts_valid = false; 248 bool is_dts_valid = false; 249 int64 pts_section = 0; 250 int64 dts_section = 0; 251 if (pts_dts_flags == 0x2) { 252 RCHECK(bit_reader.ReadBits(40, &pts_section)); 253 RCHECK((((pts_section >> 36) & 0xf) == 0x2) && 254 IsTimestampSectionValid(pts_section)); 255 is_pts_valid = true; 256 } 257 if (pts_dts_flags == 0x3) { 258 RCHECK(bit_reader.ReadBits(40, &pts_section)); 259 RCHECK(bit_reader.ReadBits(40, &dts_section)); 260 RCHECK((((pts_section >> 36) & 0xf) == 0x3) && 261 IsTimestampSectionValid(pts_section)); 262 RCHECK((((dts_section >> 36) & 0xf) == 0x1) && 263 IsTimestampSectionValid(dts_section)); 264 is_pts_valid = true; 265 is_dts_valid = true; 266 } 267 268 // Convert and unroll the timestamps. 269 base::TimeDelta media_pts(kNoTimestamp()); 270 base::TimeDelta media_dts(kNoTimestamp()); 271 if (is_pts_valid) { 272 int64 pts = ConvertTimestampSectionToTimestamp(pts_section); 273 if (previous_pts_valid_) 274 pts = UnrollTimestamp(previous_pts_, pts); 275 previous_pts_ = pts; 276 previous_pts_valid_ = true; 277 media_pts = base::TimeDelta::FromMicroseconds((1000 * pts) / 90); 278 } 279 if (is_dts_valid) { 280 int64 dts = ConvertTimestampSectionToTimestamp(dts_section); 281 if (previous_dts_valid_) 282 dts = UnrollTimestamp(previous_dts_, dts); 283 previous_dts_ = dts; 284 previous_dts_valid_ = true; 285 media_dts = base::TimeDelta::FromMicroseconds((1000 * dts) / 90); 286 } 287 288 // Discard the rest of the PES packet header. 289 // TODO(damienv): check if some info of the PES packet header are useful. 290 DCHECK_EQ(bit_reader.bits_available() % 8, 0); 291 int pes_header_remaining_size = pes_header_data_length - 292 (pes_header_start_size - bit_reader.bits_available() / 8); 293 RCHECK(pes_header_remaining_size >= 0); 294 295 // Read the PES packet. 296 DVLOG(LOG_LEVEL_PES) 297 << "Emit a reassembled PES:" 298 << " size=" << es_size 299 << " pts=" << media_pts.InMilliseconds() 300 << " dts=" << media_dts.InMilliseconds() 301 << " data_alignment_indicator=" << data_alignment_indicator; 302 return es_parser_->Parse(&raw_pes[es_offset], es_size, media_pts, media_dts); 303 } 304 305 void TsSectionPes::ResetPesState() { 306 pes_byte_queue_.Reset(); 307 wait_for_pusi_ = true; 308 } 309 310 } // namespace mp2t 311 } // namespace media 312 313