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.
5 #include "media/cast/net/rtcp/rtcp_utility.h"
7 #include "base/logging.h"
8 #include "media/cast/net/cast_transport_defines.h"
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) {
22 RtcpParser::~RtcpParser() {}
24 bool RtcpParser::Parse(base::BigEndianReader* reader) {
25 while (reader->remaining()) {
26 RtcpCommonHeader header;
27 if (!ParseCommonHeader(reader, &header))
30 base::StringPiece tmp;
31 if (!reader->ReadPiece(&tmp, header.length_in_octets - 4))
33 base::BigEndianReader chunk(tmp.data(), tmp.size());
36 case kPacketTypeSenderReport:
37 if (!ParseSR(&chunk, header))
41 case kPacketTypeReceiverReport:
42 if (!ParseRR(&chunk, header))
46 case kPacketTypeApplicationDefined:
47 if (!ParseApplicationDefined(&chunk, header))
51 case kPacketTypePayloadSpecific:
52 if (!ParseFeedbackCommon(&chunk, header))
57 if (!ParseExtendedReport(&chunk, header))
65 bool RtcpParser::ParseCommonHeader(base::BigEndianReader* reader,
66 RtcpCommonHeader* parsed_header) {
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 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
73 // Common header for all Rtcp packets, 4 octets.
76 if (!reader->ReadU8(&byte))
78 parsed_header->V = byte >> 6;
79 parsed_header->P = ((byte & 0x20) == 0) ? false : true;
81 // Check if RTP version field == 2.
82 if (parsed_header->V != 2)
85 parsed_header->IC = byte & 0x1f;
86 if (!reader->ReadU8(&parsed_header->PT))
90 if (!reader->ReadU16(&bytes))
93 parsed_header->length_in_octets = (static_cast<size_t>(bytes) + 1) * 4;
95 if (parsed_header->length_in_octets == 0)
101 bool RtcpParser::ParseSR(base::BigEndianReader* reader,
102 const RtcpCommonHeader& header) {
104 if (!reader->ReadU32(&sender_ssrc))
107 if (sender_ssrc != remote_ssrc_)
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))
117 sender_report_.send_octet_count = tmp;
118 has_sender_report_ = true;
120 for (size_t block = 0; block < header.IC; block++)
121 if (!ParseReportBlock(reader))
127 bool RtcpParser::ParseRR(base::BigEndianReader* reader,
128 const RtcpCommonHeader& header) {
129 uint32 receiver_ssrc;
130 if (!reader->ReadU32(&receiver_ssrc))
133 if (receiver_ssrc != remote_ssrc_)
136 for (size_t block = 0; block < header.IC; block++)
137 if (!ParseReportBlock(reader))
143 bool RtcpParser::ParseReportBlock(base::BigEndianReader* reader) {
144 uint32 ssrc, last_report, delay;
145 if (!reader->ReadU32(&ssrc) ||
147 !reader->ReadU32(&last_report) ||
148 !reader->ReadU32(&delay))
151 if (ssrc == local_ssrc_) {
152 last_report_ = last_report;
153 delay_since_last_report_ = delay;
154 has_last_report_ = true;
160 bool RtcpParser::ParseApplicationDefined(base::BigEndianReader* reader,
161 const RtcpCommonHeader& header) {
164 if (!reader->ReadU32(&sender_ssrc) ||
165 !reader->ReadU32(&name))
168 if (sender_ssrc != remote_ssrc_)
174 switch (header.IC /* subtype */ ) {
175 case kReceiverLogSubtype:
176 if (!ParseCastReceiverLogFrameItem(reader))
183 bool RtcpParser::ParseCastReceiverLogFrameItem(
184 base::BigEndianReader* reader) {
186 while (reader->remaining()) {
187 uint32 rtp_timestamp;
189 if (!reader->ReadU32(&rtp_timestamp) ||
190 !reader->ReadU32(&data))
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);
197 size_t num_events = 1 + static_cast<uint8>(data >> 24);
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))
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;
217 event_log.delay_delta = base::TimeDelta::FromMilliseconds(
218 static_cast<int16>(delay_delta_or_packet_id));
220 frame_log.event_log_messages_.push_back(event_log);
223 receiver_log_.push_back(frame_log);
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) {
238 if (!reader->ReadU32(&remote_ssrc) ||
239 !reader->ReadU32(&media_ssrc))
242 if (remote_ssrc != remote_ssrc_)
246 if (!reader->ReadU32(&name))
253 cast_message_.media_ssrc = remote_ssrc;
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))
262 // Please note, this frame_id is still only 8-bit!
263 cast_message_.ack_frame_id = last_frame_id;
265 for (size_t i = 0; i < number_of_lost_fields; i++) {
269 if (!reader->ReadU8(&frame_id) ||
270 !reader->ReadU16(&packet_id) ||
271 !reader->ReadU8(&bitmask))
273 cast_message_.missing_frames_and_packets[frame_id].insert(packet_id);
274 if (packet_id != kRtcpCastAllPacketsLost) {
278 cast_message_.missing_frames_and_packets[frame_id].insert(packet_id);
284 has_cast_message_ = true;
288 bool RtcpParser::ParseExtendedReport(base::BigEndianReader* reader,
289 const RtcpCommonHeader& header) {
291 if (!reader->ReadU32(&remote_ssrc))
295 if (remote_ssrc != remote_ssrc_)
298 while (reader->remaining()) {
301 if (!reader->ReadU8(&block_type) ||
303 !reader->ReadU16(&block_length))
306 switch (block_type) {
307 case 4: // RRTR. RFC3611 Section 4.4.
308 if (block_length != 2)
310 if (!ParseExtendedReportReceiverReferenceTimeReport(reader,
316 // Skip unknown item.
317 if (!reader->Skip(block_length * 4))
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))
333 has_receiver_reference_time_report_ = true;
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) {
348 case PACKET_RECEIVED:
351 return 0; // Not an interesting event.
355 CastLoggingEvent TranslateToLogEventFromWireFormat(uint8 event) {
356 // TODO(imcheng): Remove the old mappings once they are no longer used.
358 case 1: // AudioAckSent
359 case 5: // VideoAckSent
361 return FRAME_ACK_SENT;
362 case 2: // AudioPlayoutDelay
363 case 7: // VideoRenderDelay
365 return FRAME_PLAYOUT;
366 case 3: // AudioFrameDecoded
367 case 6: // VideoFrameDecoded
369 return FRAME_DECODED;
370 case 4: // AudioPacketReceived
371 case 8: // VideoPacketReceived
373 return PACKET_RECEIVED;
374 case 9: // DuplicateAudioPacketReceived
375 case 10: // DuplicateVideoPacketReceived
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);