1 // Copyright 2014 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/cast/net/rtcp/rtcp_utility.h" 6 7 #include "base/logging.h" 8 #include "media/cast/net/cast_transport_defines.h" 9 10 namespace media { 11 namespace cast { 12 13 RtcpParser::RtcpParser(uint32 local_ssrc, uint32 remote_ssrc) : 14 local_ssrc_(local_ssrc), 15 remote_ssrc_(remote_ssrc), 16 has_sender_report_(false), 17 has_last_report_(false), 18 has_cast_message_(false), 19 has_receiver_reference_time_report_(false) { 20 } 21 22 RtcpParser::~RtcpParser() {} 23 24 bool RtcpParser::Parse(base::BigEndianReader* reader) { 25 while (reader->remaining()) { 26 RtcpCommonHeader header; 27 if (!ParseCommonHeader(reader, &header)) 28 return false; 29 30 base::StringPiece tmp; 31 if (!reader->ReadPiece(&tmp, header.length_in_octets - 4)) 32 return false; 33 base::BigEndianReader chunk(tmp.data(), tmp.size()); 34 35 switch (header.PT) { 36 case kPacketTypeSenderReport: 37 if (!ParseSR(&chunk, header)) 38 return false; 39 break; 40 41 case kPacketTypeReceiverReport: 42 if (!ParseRR(&chunk, header)) 43 return false; 44 break; 45 46 case kPacketTypeApplicationDefined: 47 if (!ParseApplicationDefined(&chunk, header)) 48 return false; 49 break; 50 51 case kPacketTypePayloadSpecific: 52 if (!ParseFeedbackCommon(&chunk, header)) 53 return false; 54 break; 55 56 case kPacketTypeXr: 57 if (!ParseExtendedReport(&chunk, header)) 58 return false; 59 break; 60 } 61 } 62 return true; 63 } 64 65 bool RtcpParser::ParseCommonHeader(base::BigEndianReader* reader, 66 RtcpCommonHeader* parsed_header) { 67 // 0 1 2 3 68 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 69 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 70 // |V=2|P| IC | PT | length | 71 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 72 // 73 // Common header for all Rtcp packets, 4 octets. 74 75 uint8 byte; 76 if (!reader->ReadU8(&byte)) 77 return false; 78 parsed_header->V = byte >> 6; 79 parsed_header->P = ((byte & 0x20) == 0) ? false : true; 80 81 // Check if RTP version field == 2. 82 if (parsed_header->V != 2) 83 return false; 84 85 parsed_header->IC = byte & 0x1f; 86 if (!reader->ReadU8(&parsed_header->PT)) 87 return false; 88 89 uint16 bytes; 90 if (!reader->ReadU16(&bytes)) 91 return false; 92 93 parsed_header->length_in_octets = (static_cast<size_t>(bytes) + 1) * 4; 94 95 if (parsed_header->length_in_octets == 0) 96 return false; 97 98 return true; 99 } 100 101 bool RtcpParser::ParseSR(base::BigEndianReader* reader, 102 const RtcpCommonHeader& header) { 103 uint32 sender_ssrc; 104 if (!reader->ReadU32(&sender_ssrc)) 105 return false; 106 107 if (sender_ssrc != remote_ssrc_) 108 return true; 109 110 uint32 tmp; 111 if (!reader->ReadU32(&sender_report_.ntp_seconds) || 112 !reader->ReadU32(&sender_report_.ntp_fraction) || 113 !reader->ReadU32(&sender_report_.rtp_timestamp) || 114 !reader->ReadU32(&sender_report_.send_packet_count) || 115 !reader->ReadU32(&tmp)) 116 return false; 117 sender_report_.send_octet_count = tmp; 118 has_sender_report_ = true; 119 120 for (size_t block = 0; block < header.IC; block++) 121 if (!ParseReportBlock(reader)) 122 return false; 123 124 return true; 125 } 126 127 bool RtcpParser::ParseRR(base::BigEndianReader* reader, 128 const RtcpCommonHeader& header) { 129 uint32 receiver_ssrc; 130 if (!reader->ReadU32(&receiver_ssrc)) 131 return false; 132 133 if (receiver_ssrc != remote_ssrc_) 134 return true; 135 136 for (size_t block = 0; block < header.IC; block++) 137 if (!ParseReportBlock(reader)) 138 return false; 139 140 return true; 141 } 142 143 bool RtcpParser::ParseReportBlock(base::BigEndianReader* reader) { 144 uint32 ssrc, last_report, delay; 145 if (!reader->ReadU32(&ssrc) || 146 !reader->Skip(12) || 147 !reader->ReadU32(&last_report) || 148 !reader->ReadU32(&delay)) 149 return false; 150 151 if (ssrc == local_ssrc_) { 152 last_report_ = last_report; 153 delay_since_last_report_ = delay; 154 has_last_report_ = true; 155 } 156 157 return true; 158 } 159 160 bool RtcpParser::ParseApplicationDefined(base::BigEndianReader* reader, 161 const RtcpCommonHeader& header) { 162 uint32 sender_ssrc; 163 uint32 name; 164 if (!reader->ReadU32(&sender_ssrc) || 165 !reader->ReadU32(&name)) 166 return false; 167 168 if (sender_ssrc != remote_ssrc_) 169 return true; 170 171 if (name != kCast) 172 return false; 173 174 switch (header.IC /* subtype */ ) { 175 case kReceiverLogSubtype: 176 if (!ParseCastReceiverLogFrameItem(reader)) 177 return false; 178 break; 179 } 180 return true; 181 } 182 183 bool RtcpParser::ParseCastReceiverLogFrameItem( 184 base::BigEndianReader* reader) { 185 186 while (reader->remaining()) { 187 uint32 rtp_timestamp; 188 uint32 data; 189 if (!reader->ReadU32(&rtp_timestamp) || 190 !reader->ReadU32(&data)) 191 return false; 192 193 // We have 24 LSB of the event timestamp base on the wire. 194 base::TimeTicks event_timestamp_base = base::TimeTicks() + 195 base::TimeDelta::FromMilliseconds(data & 0xffffff); 196 197 size_t num_events = 1 + static_cast<uint8>(data >> 24); 198 199 RtcpReceiverFrameLogMessage frame_log(rtp_timestamp); 200 for (size_t event = 0; event < num_events; event++) { 201 uint16 delay_delta_or_packet_id; 202 uint16 event_type_and_timestamp_delta; 203 if (!reader->ReadU16(&delay_delta_or_packet_id) || 204 !reader->ReadU16(&event_type_and_timestamp_delta)) 205 return false; 206 207 RtcpReceiverEventLogMessage event_log; 208 event_log.type = TranslateToLogEventFromWireFormat( 209 static_cast<uint8>(event_type_and_timestamp_delta >> 12)); 210 event_log.event_timestamp = 211 event_timestamp_base + 212 base::TimeDelta::FromMilliseconds( 213 event_type_and_timestamp_delta & 0xfff); 214 if (event_log.type == PACKET_RECEIVED) { 215 event_log.packet_id = delay_delta_or_packet_id; 216 } else { 217 event_log.delay_delta = base::TimeDelta::FromMilliseconds( 218 static_cast<int16>(delay_delta_or_packet_id)); 219 } 220 frame_log.event_log_messages_.push_back(event_log); 221 } 222 223 receiver_log_.push_back(frame_log); 224 } 225 226 return true; 227 } 228 229 // RFC 4585. 230 bool RtcpParser::ParseFeedbackCommon(base::BigEndianReader* reader, 231 const RtcpCommonHeader& header) { 232 // See RTC 4585 Section 6.4 for application specific feedback messages. 233 if (header.IC != 15) { 234 return true; 235 } 236 uint32 remote_ssrc; 237 uint32 media_ssrc; 238 if (!reader->ReadU32(&remote_ssrc) || 239 !reader->ReadU32(&media_ssrc)) 240 return false; 241 242 if (remote_ssrc != remote_ssrc_) 243 return true; 244 245 uint32 name; 246 if (!reader->ReadU32(&name)) 247 return false; 248 249 if (name != kCast) { 250 return true; 251 } 252 253 cast_message_.media_ssrc = remote_ssrc; 254 255 uint8 last_frame_id; 256 uint8 number_of_lost_fields; 257 if (!reader->ReadU8(&last_frame_id) || 258 !reader->ReadU8(&number_of_lost_fields) || 259 !reader->ReadU16(&cast_message_.target_delay_ms)) 260 return false; 261 262 // Please note, this frame_id is still only 8-bit! 263 cast_message_.ack_frame_id = last_frame_id; 264 265 for (size_t i = 0; i < number_of_lost_fields; i++) { 266 uint8 frame_id; 267 uint16 packet_id; 268 uint8 bitmask; 269 if (!reader->ReadU8(&frame_id) || 270 !reader->ReadU16(&packet_id) || 271 !reader->ReadU8(&bitmask)) 272 return false; 273 cast_message_.missing_frames_and_packets[frame_id].insert(packet_id); 274 if (packet_id != kRtcpCastAllPacketsLost) { 275 while (bitmask) { 276 packet_id++; 277 if (bitmask & 1) 278 cast_message_.missing_frames_and_packets[frame_id].insert(packet_id); 279 bitmask >>= 1; 280 } 281 } 282 } 283 284 has_cast_message_ = true; 285 return true; 286 } 287 288 bool RtcpParser::ParseExtendedReport(base::BigEndianReader* reader, 289 const RtcpCommonHeader& header) { 290 uint32 remote_ssrc; 291 if (!reader->ReadU32(&remote_ssrc)) 292 return false; 293 294 // Is it for us? 295 if (remote_ssrc != remote_ssrc_) 296 return true; 297 298 while (reader->remaining()) { 299 uint8 block_type; 300 uint16 block_length; 301 if (!reader->ReadU8(&block_type) || 302 !reader->Skip(1) || 303 !reader->ReadU16(&block_length)) 304 return false; 305 306 switch (block_type) { 307 case 4: // RRTR. RFC3611 Section 4.4. 308 if (block_length != 2) 309 return false; 310 if (!ParseExtendedReportReceiverReferenceTimeReport(reader, 311 remote_ssrc)) 312 return false; 313 break; 314 315 default: 316 // Skip unknown item. 317 if (!reader->Skip(block_length * 4)) 318 return false; 319 } 320 } 321 322 return true; 323 } 324 325 bool RtcpParser::ParseExtendedReportReceiverReferenceTimeReport( 326 base::BigEndianReader* reader, 327 uint32 remote_ssrc) { 328 receiver_reference_time_report_.remote_ssrc = remote_ssrc; 329 if(!reader->ReadU32(&receiver_reference_time_report_.ntp_seconds) || 330 !reader->ReadU32(&receiver_reference_time_report_.ntp_fraction)) 331 return false; 332 333 has_receiver_reference_time_report_ = true; 334 return true; 335 } 336 337 // Converts a log event type to an integer value. 338 // NOTE: We have only allocated 4 bits to represent the type of event over the 339 // wire. Therefore, this function can only return values from 0 to 15. 340 uint8 ConvertEventTypeToWireFormat(CastLoggingEvent event) { 341 switch (event) { 342 case FRAME_ACK_SENT: 343 return 11; 344 case FRAME_PLAYOUT: 345 return 12; 346 case FRAME_DECODED: 347 return 13; 348 case PACKET_RECEIVED: 349 return 14; 350 default: 351 return 0; // Not an interesting event. 352 } 353 } 354 355 CastLoggingEvent TranslateToLogEventFromWireFormat(uint8 event) { 356 // TODO(imcheng): Remove the old mappings once they are no longer used. 357 switch (event) { 358 case 1: // AudioAckSent 359 case 5: // VideoAckSent 360 case 11: // Unified 361 return FRAME_ACK_SENT; 362 case 2: // AudioPlayoutDelay 363 case 7: // VideoRenderDelay 364 case 12: // Unified 365 return FRAME_PLAYOUT; 366 case 3: // AudioFrameDecoded 367 case 6: // VideoFrameDecoded 368 case 13: // Unified 369 return FRAME_DECODED; 370 case 4: // AudioPacketReceived 371 case 8: // VideoPacketReceived 372 case 14: // Unified 373 return PACKET_RECEIVED; 374 case 9: // DuplicateAudioPacketReceived 375 case 10: // DuplicateVideoPacketReceived 376 default: 377 // If the sender adds new log messages we will end up here until we add 378 // the new messages in the receiver. 379 VLOG(1) << "Unexpected log message received: " << static_cast<int>(event); 380 return UNKNOWN; 381 } 382 } 383 384 } // namespace cast 385 } // namespace media 386