• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
RtcpParser(uint32 local_ssrc,uint32 remote_ssrc)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 
~RtcpParser()22 RtcpParser::~RtcpParser() {}
23 
Parse(base::BigEndianReader * reader)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 
ParseCommonHeader(base::BigEndianReader * reader,RtcpCommonHeader * parsed_header)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 
ParseSR(base::BigEndianReader * reader,const RtcpCommonHeader & header)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 
ParseRR(base::BigEndianReader * reader,const RtcpCommonHeader & header)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 
ParseReportBlock(base::BigEndianReader * reader)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 
ParseApplicationDefined(base::BigEndianReader * reader,const RtcpCommonHeader & header)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 
ParseCastReceiverLogFrameItem(base::BigEndianReader * reader)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.
ParseFeedbackCommon(base::BigEndianReader * reader,const RtcpCommonHeader & header)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 
ParseExtendedReport(base::BigEndianReader * reader,const RtcpCommonHeader & header)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 
ParseExtendedReportReceiverReferenceTimeReport(base::BigEndianReader * reader,uint32 remote_ssrc)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.
ConvertEventTypeToWireFormat(CastLoggingEvent event)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 
TranslateToLogEventFromWireFormat(uint8 event)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