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/cast/rtcp/rtcp_utility.h"
6
7#include "base/big_endian.h"
8#include "base/logging.h"
9#include "media/cast/transport/cast_transport_defines.h"
10
11namespace media {
12namespace cast {
13
14RtcpParser::RtcpParser(const uint8* rtcpData, size_t rtcpDataLength)
15    : rtcp_data_begin_(rtcpData),
16      rtcp_data_end_(rtcpData + rtcpDataLength),
17      valid_packet_(false),
18      rtcp_data_(rtcpData),
19      rtcp_block_end_(NULL),
20      state_(kStateTopLevel),
21      number_of_blocks_(0),
22      field_type_(kRtcpNotValidCode) {
23  memset(&field_, 0, sizeof(field_));
24  Validate();
25}
26
27RtcpParser::~RtcpParser() {}
28
29RtcpFieldTypes RtcpParser::FieldType() const { return field_type_; }
30
31const RtcpField& RtcpParser::Field() const { return field_; }
32
33RtcpFieldTypes RtcpParser::Begin() {
34  rtcp_data_ = rtcp_data_begin_;
35  return Iterate();
36}
37
38RtcpFieldTypes RtcpParser::Iterate() {
39  // Reset packet type
40  field_type_ = kRtcpNotValidCode;
41
42  if (!IsValid())
43    return kRtcpNotValidCode;
44
45  switch (state_) {
46    case kStateTopLevel:
47      IterateTopLevel();
48      break;
49    case kStateReportBlock:
50      IterateReportBlockItem();
51      break;
52    case kStateSdes:
53      IterateSdesItem();
54      break;
55    case kStateBye:
56      IterateByeItem();
57      break;
58    case kStateApplicationSpecificCastReceiverFrameLog:
59      IterateCastReceiverLogFrame();
60      break;
61    case kStateApplicationSpecificCastReceiverEventLog:
62      IterateCastReceiverLogEvent();
63      break;
64    case kStateExtendedReportBlock:
65      IterateExtendedReportItem();
66      break;
67    case kStateExtendedReportDelaySinceLastReceiverReport:
68      IterateExtendedReportDelaySinceLastReceiverReportItem();
69      break;
70    case kStateGenericRtpFeedbackNack:
71      IterateNackItem();
72      break;
73    case kStatePayloadSpecificRpsi:
74      IterateRpsiItem();
75      break;
76    case kStatePayloadSpecificFir:
77      IterateFirItem();
78      break;
79    case kStatePayloadSpecificApplication:
80      IteratePayloadSpecificAppItem();
81      break;
82    case kStatePayloadSpecificRemb:
83      IteratePayloadSpecificRembItem();
84      break;
85    case kStatePayloadSpecificCast:
86      IteratePayloadSpecificCastItem();
87      break;
88    case kStatePayloadSpecificCastNack:
89      IteratePayloadSpecificCastNackItem();
90      break;
91  }
92  return field_type_;
93}
94
95void RtcpParser::IterateTopLevel() {
96  for (;;) {
97    RtcpCommonHeader header;
98
99    bool success = RtcpParseCommonHeader(rtcp_data_, rtcp_data_end_, &header);
100    if (!success)
101      return;
102
103    rtcp_block_end_ = rtcp_data_ + header.length_in_octets;
104
105    if (rtcp_block_end_ > rtcp_data_end_)
106      return;  // Bad block!
107
108    switch (header.PT) {
109      case transport::kPacketTypeSenderReport:
110        // number of Report blocks
111        number_of_blocks_ = header.IC;
112        ParseSR();
113        return;
114      case transport::kPacketTypeReceiverReport:
115        // number of Report blocks
116        number_of_blocks_ = header.IC;
117        ParseRR();
118        return;
119      case transport::kPacketTypeSdes:
120        // number of Sdes blocks
121        number_of_blocks_ = header.IC;
122        if (!ParseSdes()) {
123          break;  // Nothing supported found, continue to next block!
124        }
125        return;
126      case transport::kPacketTypeBye:
127        number_of_blocks_ = header.IC;
128        if (!ParseBye()) {
129          // Nothing supported found, continue to next block!
130          break;
131        }
132        return;
133      case transport::kPacketTypeApplicationDefined:
134        if (!ParseApplicationDefined(header.IC)) {
135          // Nothing supported found, continue to next block!
136          break;
137        }
138        return;
139      case transport::kPacketTypeGenericRtpFeedback:  // Fall through!
140      case transport::kPacketTypePayloadSpecific:
141        if (!ParseFeedBackCommon(header)) {
142          // Nothing supported found, continue to next block!
143          break;
144        }
145        return;
146      case transport::kPacketTypeXr:
147        if (!ParseExtendedReport()) {
148          break;  // Nothing supported found, continue to next block!
149        }
150        return;
151      default:
152        // Not supported! Skip!
153        EndCurrentBlock();
154        break;
155    }
156  }
157}
158
159void RtcpParser::IterateReportBlockItem() {
160  bool success = ParseReportBlockItem();
161  if (!success)
162    Iterate();
163}
164
165void RtcpParser::IterateSdesItem() {
166  bool success = ParseSdesItem();
167  if (!success)
168    Iterate();
169}
170
171void RtcpParser::IterateByeItem() {
172  bool success = ParseByeItem();
173  if (!success)
174    Iterate();
175}
176
177void RtcpParser::IterateExtendedReportItem() {
178  bool success = ParseExtendedReportItem();
179  if (!success)
180    Iterate();
181}
182
183void RtcpParser::IterateExtendedReportDelaySinceLastReceiverReportItem() {
184  bool success = ParseExtendedReportDelaySinceLastReceiverReport();
185  if (!success)
186    Iterate();
187}
188
189void RtcpParser::IterateNackItem() {
190  bool success = ParseNackItem();
191  if (!success)
192    Iterate();
193}
194
195void RtcpParser::IterateRpsiItem() {
196  bool success = ParseRpsiItem();
197  if (!success)
198    Iterate();
199}
200
201void RtcpParser::IterateFirItem() {
202  bool success = ParseFirItem();
203  if (!success)
204    Iterate();
205}
206
207void RtcpParser::IteratePayloadSpecificAppItem() {
208  bool success = ParsePayloadSpecificAppItem();
209  if (!success)
210    Iterate();
211}
212
213void RtcpParser::IteratePayloadSpecificRembItem() {
214  bool success = ParsePayloadSpecificRembItem();
215  if (!success)
216    Iterate();
217}
218
219void RtcpParser::IteratePayloadSpecificCastItem() {
220  bool success = ParsePayloadSpecificCastItem();
221  if (!success)
222    Iterate();
223}
224
225void RtcpParser::IteratePayloadSpecificCastNackItem() {
226  bool success = ParsePayloadSpecificCastNackItem();
227  if (!success)
228    Iterate();
229}
230
231void RtcpParser::IterateCastReceiverLogFrame() {
232  bool success = ParseCastReceiverLogFrameItem();
233  if (!success)
234    Iterate();
235}
236
237void RtcpParser::IterateCastReceiverLogEvent() {
238  bool success = ParseCastReceiverLogEventItem();
239  if (!success)
240    Iterate();
241}
242
243void RtcpParser::Validate() {
244  if (rtcp_data_ == NULL)
245    return;  // NOT VALID
246
247  RtcpCommonHeader header;
248  bool success =
249      RtcpParseCommonHeader(rtcp_data_begin_, rtcp_data_end_, &header);
250
251  if (!success)
252    return;  // NOT VALID!
253
254  valid_packet_ = true;
255}
256
257bool RtcpParser::IsValid() const { return valid_packet_; }
258
259void RtcpParser::EndCurrentBlock() { rtcp_data_ = rtcp_block_end_; }
260
261bool RtcpParser::RtcpParseCommonHeader(const uint8* data_begin,
262                                       const uint8* data_end,
263                                       RtcpCommonHeader* parsed_header) const {
264  if (!data_begin || !data_end)
265    return false;
266
267  //  0                   1                   2                   3
268  //  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
269  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
270  // |V=2|P|    IC   |      PT       |             length            |
271  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
272  //
273  // Common header for all Rtcp packets, 4 octets.
274
275  if ((data_end - data_begin) < 4)
276    return false;
277
278  parsed_header->V = data_begin[0] >> 6;
279  parsed_header->P = ((data_begin[0] & 0x20) == 0) ? false : true;
280  parsed_header->IC = data_begin[0] & 0x1f;
281  parsed_header->PT = data_begin[1];
282
283  parsed_header->length_in_octets =
284      ((data_begin[2] << 8) + data_begin[3] + 1) * 4;
285
286  if (parsed_header->length_in_octets == 0)
287    return false;
288
289  // Check if RTP version field == 2.
290  if (parsed_header->V != 2)
291    return false;
292
293  return true;
294}
295
296bool RtcpParser::ParseRR() {
297  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
298  if (length < 8)
299    return false;
300
301  field_type_ = kRtcpRrCode;
302
303  base::BigEndianReader big_endian_reader(
304      reinterpret_cast<const char*>(rtcp_data_), length);
305  big_endian_reader.Skip(4);  // Skip header
306  big_endian_reader.ReadU32(&field_.receiver_report.sender_ssrc);
307  field_.receiver_report.number_of_report_blocks = number_of_blocks_;
308  rtcp_data_ += 8;
309
310  // State transition
311  state_ = kStateReportBlock;
312  return true;
313}
314
315bool RtcpParser::ParseSR() {
316  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
317  if (length < 28) {
318    EndCurrentBlock();
319    return false;
320  }
321  field_type_ = kRtcpSrCode;
322
323  base::BigEndianReader big_endian_reader(
324      reinterpret_cast<const char*>(rtcp_data_), length);
325  big_endian_reader.Skip(4);  // Skip header
326  big_endian_reader.ReadU32(&field_.sender_report.sender_ssrc);
327  big_endian_reader.ReadU32(&field_.sender_report.ntp_most_significant);
328  big_endian_reader.ReadU32(&field_.sender_report.ntp_least_significant);
329  big_endian_reader.ReadU32(&field_.sender_report.rtp_timestamp);
330  big_endian_reader.ReadU32(&field_.sender_report.sender_packet_count);
331  big_endian_reader.ReadU32(&field_.sender_report.sender_octet_count);
332  field_.sender_report.number_of_report_blocks = number_of_blocks_;
333  rtcp_data_ += 28;
334
335  if (number_of_blocks_ != 0) {
336    // State transition.
337    state_ = kStateReportBlock;
338  } else {
339    // Don't go to state report block item if 0 report blocks.
340    state_ = kStateTopLevel;
341    EndCurrentBlock();
342  }
343  return true;
344}
345
346bool RtcpParser::ParseReportBlockItem() {
347  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
348  if (length < 24 || number_of_blocks_ <= 0) {
349    state_ = kStateTopLevel;
350    EndCurrentBlock();
351    return false;
352  }
353
354  base::BigEndianReader big_endian_reader(
355      reinterpret_cast<const char*>(rtcp_data_), length);
356  big_endian_reader.ReadU32(&field_.report_block_item.ssrc);
357  big_endian_reader.ReadU8(&field_.report_block_item.fraction_lost);
358
359  uint8 temp_number_of_packets_lost;
360  big_endian_reader.ReadU8(&temp_number_of_packets_lost);
361  field_.report_block_item.cumulative_number_of_packets_lost =
362      temp_number_of_packets_lost << 16;
363  big_endian_reader.ReadU8(&temp_number_of_packets_lost);
364  field_.report_block_item.cumulative_number_of_packets_lost +=
365      temp_number_of_packets_lost << 8;
366  big_endian_reader.ReadU8(&temp_number_of_packets_lost);
367  field_.report_block_item.cumulative_number_of_packets_lost +=
368      temp_number_of_packets_lost;
369
370  big_endian_reader.ReadU32(
371      &field_.report_block_item.extended_highest_sequence_number);
372  big_endian_reader.ReadU32(&field_.report_block_item.jitter);
373  big_endian_reader.ReadU32(&field_.report_block_item.last_sender_report);
374  big_endian_reader.ReadU32(&field_.report_block_item.delay_last_sender_report);
375  rtcp_data_ += 24;
376
377  number_of_blocks_--;
378  field_type_ = kRtcpReportBlockItemCode;
379  return true;
380}
381
382bool RtcpParser::ParseSdes() {
383  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
384
385  if (length < 8) {
386    state_ = kStateTopLevel;
387    EndCurrentBlock();
388    return false;
389  }
390  rtcp_data_ += 4;  // Skip header
391
392  state_ = kStateSdes;
393  field_type_ = kRtcpSdesCode;
394  return true;
395}
396
397bool RtcpParser::ParseSdesItem() {
398  if (number_of_blocks_ <= 0) {
399    state_ = kStateTopLevel;
400    EndCurrentBlock();
401    return false;
402  }
403  number_of_blocks_--;
404
405  // Find c_name item in a Sdes chunk.
406  while (rtcp_data_ < rtcp_block_end_) {
407    ptrdiff_t data_length = rtcp_block_end_ - rtcp_data_;
408    if (data_length < 4) {
409      state_ = kStateTopLevel;
410      EndCurrentBlock();
411      return false;
412    }
413
414    uint32 ssrc;
415    base::BigEndianReader big_endian_reader(
416        reinterpret_cast<const char*>(rtcp_data_), data_length);
417    big_endian_reader.ReadU32(&ssrc);
418    rtcp_data_ += 4;
419
420    bool found_c_name = ParseSdesTypes();
421    if (found_c_name) {
422      field_.c_name.sender_ssrc = ssrc;
423      return true;
424    }
425  }
426  state_ = kStateTopLevel;
427  EndCurrentBlock();
428  return false;
429}
430
431bool RtcpParser::ParseSdesTypes() {
432  // Only the c_name item is mandatory. RFC 3550 page 46.
433  bool found_c_name = false;
434  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
435  base::BigEndianReader big_endian_reader(
436      reinterpret_cast<const char*>(rtcp_data_), length);
437
438  while (big_endian_reader.remaining() > 0) {
439    uint8 tag;
440    big_endian_reader.ReadU8(&tag);
441
442    if (tag == 0) {
443      // End tag! 4 octet aligned.
444      rtcp_data_ = rtcp_block_end_;
445      return found_c_name;
446    }
447
448    if (big_endian_reader.remaining() > 0) {
449      uint8 len;
450      big_endian_reader.ReadU8(&len);
451
452      if (tag == 1) {  // c_name.
453        // Sanity check.
454        if (big_endian_reader.remaining() < len) {
455          state_ = kStateTopLevel;
456          EndCurrentBlock();
457          return false;
458        }
459        int i = 0;
460        for (; i < len; ++i) {
461          uint8 c;
462          big_endian_reader.ReadU8(&c);
463          if ((c < ' ') || (c > '{') || (c == '%') || (c == '\\')) {
464            // Illegal char.
465            state_ = kStateTopLevel;
466            EndCurrentBlock();
467            return false;
468          }
469          field_.c_name.name[i] = c;
470        }
471        // Make sure we are null terminated.
472        field_.c_name.name[i] = 0;
473        field_type_ = kRtcpSdesChunkCode;
474        found_c_name = true;
475      } else {
476        big_endian_reader.Skip(len);
477      }
478    }
479  }
480  // No end tag found!
481  state_ = kStateTopLevel;
482  EndCurrentBlock();
483  return false;
484}
485
486bool RtcpParser::ParseBye() {
487  rtcp_data_ += 4;  // Skip header.
488  state_ = kStateBye;
489  return ParseByeItem();
490}
491
492bool RtcpParser::ParseByeItem() {
493  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
494  if (length < 4 || number_of_blocks_ == 0) {
495    state_ = kStateTopLevel;
496    EndCurrentBlock();
497    return false;
498  }
499
500  field_type_ = kRtcpByeCode;
501
502  base::BigEndianReader big_endian_reader(
503      reinterpret_cast<const char*>(rtcp_data_), length);
504  big_endian_reader.ReadU32(&field_.bye.sender_ssrc);
505  rtcp_data_ += 4;
506
507  // We can have several CSRCs attached.
508  if (length >= 4 * number_of_blocks_) {
509    rtcp_data_ += (number_of_blocks_ - 1) * 4;
510  }
511  number_of_blocks_ = 0;
512  return true;
513}
514
515bool RtcpParser::ParseApplicationDefined(uint8 subtype) {
516  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
517  if (length < 16 || subtype != kReceiverLogSubtype) {
518    state_ = kStateTopLevel;
519    EndCurrentBlock();
520    return false;
521  }
522
523  uint32 sender_ssrc;
524  uint32 name;
525
526  base::BigEndianReader big_endian_reader(
527      reinterpret_cast<const char*>(rtcp_data_), length);
528  big_endian_reader.Skip(4);  // Skip header.
529  big_endian_reader.ReadU32(&sender_ssrc);
530  big_endian_reader.ReadU32(&name);
531
532  if (name != kCast) {
533    state_ = kStateTopLevel;
534    EndCurrentBlock();
535    return false;
536  }
537  rtcp_data_ += 12;
538  switch (subtype) {
539    case kReceiverLogSubtype:
540      state_ = kStateApplicationSpecificCastReceiverFrameLog;
541      field_type_ = kRtcpApplicationSpecificCastReceiverLogCode;
542      field_.cast_receiver_log.sender_ssrc = sender_ssrc;
543      break;
544    default:
545      NOTREACHED();
546  }
547  return true;
548}
549
550bool RtcpParser::ParseCastReceiverLogFrameItem() {
551  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
552  if (length < 12) {
553    state_ = kStateTopLevel;
554    EndCurrentBlock();
555    return false;
556  }
557  uint32 rtp_timestamp;
558  uint32 data;
559  base::BigEndianReader big_endian_reader(
560      reinterpret_cast<const char*>(rtcp_data_), length);
561  big_endian_reader.ReadU32(&rtp_timestamp);
562  big_endian_reader.ReadU32(&data);
563
564  rtcp_data_ += 8;
565
566  field_.cast_receiver_log.rtp_timestamp = rtp_timestamp;
567  // We have 24 LSB of the event timestamp base on the wire.
568  field_.cast_receiver_log.event_timestamp_base = data & 0xffffff;
569
570  number_of_blocks_ = 1 + static_cast<uint8>(data >> 24);
571  state_ = kStateApplicationSpecificCastReceiverEventLog;
572  field_type_ = kRtcpApplicationSpecificCastReceiverLogFrameCode;
573  return true;
574}
575
576bool RtcpParser::ParseCastReceiverLogEventItem() {
577  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
578  if (length < 4) {
579    state_ = kStateTopLevel;
580    EndCurrentBlock();
581    return false;
582  }
583  if (number_of_blocks_ == 0) {
584    // Continue parsing the next receiver frame event.
585    state_ = kStateApplicationSpecificCastReceiverFrameLog;
586    return false;
587  }
588  number_of_blocks_--;
589
590  uint16 delay_delta_or_packet_id;
591  uint16 event_type_and_timestamp_delta;
592  base::BigEndianReader big_endian_reader(
593      reinterpret_cast<const char*>(rtcp_data_), length);
594  big_endian_reader.ReadU16(&delay_delta_or_packet_id);
595  big_endian_reader.ReadU16(&event_type_and_timestamp_delta);
596
597  rtcp_data_ += 4;
598
599  field_.cast_receiver_log.event =
600      static_cast<uint8>(event_type_and_timestamp_delta >> 12);
601  // delay_delta is in union'ed with packet_id.
602  field_.cast_receiver_log.delay_delta_or_packet_id.packet_id =
603      delay_delta_or_packet_id;
604  field_.cast_receiver_log.event_timestamp_delta =
605      event_type_and_timestamp_delta & 0xfff;
606
607  field_type_ = kRtcpApplicationSpecificCastReceiverLogEventCode;
608  return true;
609}
610
611bool RtcpParser::ParseFeedBackCommon(const RtcpCommonHeader& header) {
612  DCHECK((header.PT == transport::kPacketTypeGenericRtpFeedback) ||
613         (header.PT == transport::kPacketTypePayloadSpecific))
614      << "Invalid state";
615
616  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
617
618  if (length < 12) {  // 4 * 3, RFC4585 section 6.1
619    EndCurrentBlock();
620    return false;
621  }
622
623  uint32 sender_ssrc;
624  uint32 media_ssrc;
625  base::BigEndianReader big_endian_reader(
626      reinterpret_cast<const char*>(rtcp_data_), length);
627  big_endian_reader.Skip(4);  // Skip header.
628  big_endian_reader.ReadU32(&sender_ssrc);
629  big_endian_reader.ReadU32(&media_ssrc);
630
631  rtcp_data_ += 12;
632
633  if (header.PT == transport::kPacketTypeGenericRtpFeedback) {
634    // Transport layer feedback
635    switch (header.IC) {
636      case 1:
637        // Nack
638        field_type_ = kRtcpGenericRtpFeedbackNackCode;
639        field_.nack.sender_ssrc = sender_ssrc;
640        field_.nack.media_ssrc = media_ssrc;
641        state_ = kStateGenericRtpFeedbackNack;
642        return true;
643      case 2:
644        // Used to be ACK is this code point, which is removed conficts with
645        // http://tools.ietf.org/html/draft-levin-avt-rtcp-burst-00
646        break;
647      case 3:
648        // Tmmbr
649        break;
650      case 4:
651        // Tmmbn
652        break;
653      case 5:
654        // RFC 6051 RTCP-sender_report-REQ Rapid Synchronisation of RTP Flows
655        // Trigger a new Rtcp sender_report
656        field_type_ = kRtcpGenericRtpFeedbackSrReqCode;
657
658        // Note: No state transition, sender report REQ is empty!
659        return true;
660      default:
661        break;
662    }
663    EndCurrentBlock();
664    return false;
665
666  } else if (header.PT == transport::kPacketTypePayloadSpecific) {
667    // Payload specific feedback
668    switch (header.IC) {
669      case 1:
670        // PLI
671        field_type_ = kRtcpPayloadSpecificPliCode;
672        field_.pli.sender_ssrc = sender_ssrc;
673        field_.pli.media_ssrc = media_ssrc;
674
675        // Note: No state transition, PLI FCI is empty!
676        return true;
677      case 2:
678        // Sli
679        break;
680      case 3:
681        field_type_ = kRtcpPayloadSpecificRpsiCode;
682        field_.rpsi.sender_ssrc = sender_ssrc;
683        field_.rpsi.media_ssrc = media_ssrc;
684        state_ = kStatePayloadSpecificRpsi;
685        return true;
686      case 4:
687        // fir
688        break;
689      case 15:
690        field_type_ = kRtcpPayloadSpecificAppCode;
691        field_.application_specific.sender_ssrc = sender_ssrc;
692        field_.application_specific.media_ssrc = media_ssrc;
693        state_ = kStatePayloadSpecificApplication;
694        return true;
695      default:
696        break;
697    }
698
699    EndCurrentBlock();
700    return false;
701  } else {
702    DCHECK(false) << "Invalid state";
703    EndCurrentBlock();
704    return false;
705  }
706}
707
708bool RtcpParser::ParseRpsiItem() {
709  // RFC 4585 6.3.3.  Reference Picture Selection Indication (rpsi)
710  /*
711    0                   1                   2                   3
712    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
713    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
714    |      PB       |0| Payload Type|    Native rpsi bit string     |
715    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
716    |   defined per codec          ...                | Padding (0) |
717    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
718   */
719  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
720
721  if (length < 4) {
722    state_ = kStateTopLevel;
723    EndCurrentBlock();
724    return false;
725  }
726  if (length > 2 + kRtcpRpsiDataSize) {
727    state_ = kStateTopLevel;
728    EndCurrentBlock();
729    return false;
730  }
731
732  field_type_ = kRtcpPayloadSpecificRpsiCode;
733
734  uint8 padding_bits;
735  base::BigEndianReader big_endian_reader(
736      reinterpret_cast<const char*>(rtcp_data_), length);
737  big_endian_reader.ReadU8(&padding_bits);
738  big_endian_reader.ReadU8(&field_.rpsi.payload_type);
739  big_endian_reader.ReadBytes(&field_.rpsi.native_bit_string, length - 2);
740  field_.rpsi.number_of_valid_bits =
741      static_cast<uint16>(length - 2) * 8 - padding_bits;
742
743  rtcp_data_ += length;
744  return true;
745}
746
747bool RtcpParser::ParseNackItem() {
748  // RFC 4585 6.2.1. Generic Nack
749
750  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
751  if (length < 4) {
752    state_ = kStateTopLevel;
753    EndCurrentBlock();
754    return false;
755  }
756
757  field_type_ = kRtcpGenericRtpFeedbackNackItemCode;
758
759  base::BigEndianReader big_endian_reader(
760      reinterpret_cast<const char*>(rtcp_data_), length);
761  big_endian_reader.ReadU16(&field_.nack_item.packet_id);
762  big_endian_reader.ReadU16(&field_.nack_item.bitmask);
763  rtcp_data_ += 4;
764  return true;
765}
766
767bool RtcpParser::ParsePayloadSpecificAppItem() {
768  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
769
770  if (length < 4) {
771    state_ = kStateTopLevel;
772    EndCurrentBlock();
773    return false;
774  }
775  uint32 name;
776  base::BigEndianReader big_endian_reader(
777      reinterpret_cast<const char*>(rtcp_data_), length);
778  big_endian_reader.ReadU32(&name);
779  rtcp_data_ += 4;
780
781  if (name == kRemb) {
782    field_type_ = kRtcpPayloadSpecificRembCode;
783    state_ = kStatePayloadSpecificRemb;
784    return true;
785  } else if (name == kCast) {
786    field_type_ = kRtcpPayloadSpecificCastCode;
787    state_ = kStatePayloadSpecificCast;
788    return true;
789  }
790  state_ = kStateTopLevel;
791  EndCurrentBlock();
792  return false;
793}
794
795bool RtcpParser::ParsePayloadSpecificRembItem() {
796  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
797
798  if (length < 4) {
799    state_ = kStateTopLevel;
800    EndCurrentBlock();
801    return false;
802  }
803
804  base::BigEndianReader big_endian_reader(
805      reinterpret_cast<const char*>(rtcp_data_), length);
806  big_endian_reader.ReadU8(&field_.remb_item.number_of_ssrcs);
807
808  uint8 byte_1;
809  uint8 byte_2;
810  uint8 byte_3;
811  big_endian_reader.ReadU8(&byte_1);
812  big_endian_reader.ReadU8(&byte_2);
813  big_endian_reader.ReadU8(&byte_3);
814  rtcp_data_ += 4;
815
816  uint8 br_exp = (byte_1 >> 2) & 0x3F;
817  uint32 br_mantissa = ((byte_1 & 0x03) << 16) + (byte_2 << 8) + byte_3;
818  field_.remb_item.bitrate = (br_mantissa << br_exp);
819
820  ptrdiff_t length_ssrcs = rtcp_block_end_ - rtcp_data_;
821  if (length_ssrcs < 4 * field_.remb_item.number_of_ssrcs) {
822    state_ = kStateTopLevel;
823    EndCurrentBlock();
824    return false;
825  }
826
827  field_type_ = kRtcpPayloadSpecificRembItemCode;
828
829  for (int i = 0; i < field_.remb_item.number_of_ssrcs; i++) {
830    big_endian_reader.ReadU32(&field_.remb_item.ssrcs[i]);
831  }
832  return true;
833}
834
835bool RtcpParser::ParsePayloadSpecificCastItem() {
836  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
837  if (length < 4) {
838    state_ = kStateTopLevel;
839    EndCurrentBlock();
840    return false;
841  }
842  field_type_ = kRtcpPayloadSpecificCastCode;
843
844  base::BigEndianReader big_endian_reader(
845      reinterpret_cast<const char*>(rtcp_data_), length);
846  big_endian_reader.ReadU8(&field_.cast_item.last_frame_id);
847  big_endian_reader.ReadU8(&field_.cast_item.number_of_lost_fields);
848  big_endian_reader.ReadU16(&field_.cast_item.target_delay_ms);
849
850  rtcp_data_ += 4;
851
852  if (field_.cast_item.number_of_lost_fields != 0) {
853    // State transition
854    state_ = kStatePayloadSpecificCastNack;
855  } else {
856    // Don't go to state cast nack item if got 0 fields.
857    state_ = kStateTopLevel;
858    EndCurrentBlock();
859  }
860  return true;
861}
862
863bool RtcpParser::ParsePayloadSpecificCastNackItem() {
864  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
865  if (length < 4) {
866    state_ = kStateTopLevel;
867    EndCurrentBlock();
868    return false;
869  }
870  field_type_ = kRtcpPayloadSpecificCastNackItemCode;
871
872  base::BigEndianReader big_endian_reader(
873      reinterpret_cast<const char*>(rtcp_data_), length);
874  big_endian_reader.ReadU8(&field_.cast_nack_item.frame_id);
875  big_endian_reader.ReadU16(&field_.cast_nack_item.packet_id);
876  big_endian_reader.ReadU8(&field_.cast_nack_item.bitmask);
877
878  rtcp_data_ += 4;
879  return true;
880}
881
882bool RtcpParser::ParseFirItem() {
883  // RFC 5104 4.3.1. Full Intra Request (fir)
884  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
885
886  if (length < 8) {
887    state_ = kStateTopLevel;
888    EndCurrentBlock();
889    return false;
890  }
891  field_type_ = kRtcpPayloadSpecificFirItemCode;
892
893  base::BigEndianReader big_endian_reader(
894      reinterpret_cast<const char*>(rtcp_data_), length);
895  big_endian_reader.ReadU32(&field_.fir_item.ssrc);
896  big_endian_reader.ReadU8(&field_.fir_item.command_sequence_number);
897
898  rtcp_data_ += 8;
899  return true;
900}
901
902bool RtcpParser::ParseExtendedReport() {
903  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
904  if (length < 8)
905    return false;
906
907  field_type_ = kRtcpXrCode;
908
909  base::BigEndianReader big_endian_reader(
910      reinterpret_cast<const char*>(rtcp_data_), length);
911  big_endian_reader.Skip(4);  // Skip header.
912  big_endian_reader.ReadU32(&field_.extended_report.sender_ssrc);
913
914  rtcp_data_ += 8;
915
916  state_ = kStateExtendedReportBlock;
917  return true;
918}
919
920bool RtcpParser::ParseExtendedReportItem() {
921  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
922  if (length < 4) {
923    state_ = kStateTopLevel;
924    EndCurrentBlock();
925    return false;
926  }
927
928  uint8 block_type;
929  uint16 block_length;
930  base::BigEndianReader big_endian_reader(
931      reinterpret_cast<const char*>(rtcp_data_), length);
932  big_endian_reader.ReadU8(&block_type);
933  big_endian_reader.Skip(1);  // Ignore reserved.
934  big_endian_reader.ReadU16(&block_length);
935
936  rtcp_data_ += 4;
937
938  switch (block_type) {
939    case 4:
940      if (block_length != 2) {
941        // Invalid block length.
942        state_ = kStateTopLevel;
943        EndCurrentBlock();
944        return false;
945      }
946      return ParseExtendedReportReceiverReferenceTimeReport();
947    case 5:
948      if (block_length % 3 != 0) {
949        // Invalid block length.
950        state_ = kStateTopLevel;
951        EndCurrentBlock();
952        return false;
953      }
954      if (block_length >= 3) {
955        number_of_blocks_ = block_length / 3;
956        state_ = kStateExtendedReportDelaySinceLastReceiverReport;
957        return ParseExtendedReportDelaySinceLastReceiverReport();
958      }
959      return true;
960    default:
961      if (length < block_length * 4) {
962        state_ = kStateTopLevel;
963        EndCurrentBlock();
964        return false;
965      }
966      field_type_ = kRtcpXrUnknownItemCode;
967      rtcp_data_ += block_length * 4;
968      return true;
969  }
970}
971
972bool RtcpParser::ParseExtendedReportReceiverReferenceTimeReport() {
973  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
974  if (length < 8) {
975    state_ = kStateTopLevel;
976    EndCurrentBlock();
977    return false;
978  }
979
980  base::BigEndianReader big_endian_reader(
981      reinterpret_cast<const char*>(rtcp_data_), length);
982  big_endian_reader.ReadU32(&field_.rrtr.ntp_most_significant);
983  big_endian_reader.ReadU32(&field_.rrtr.ntp_least_significant);
984
985  rtcp_data_ += 8;
986
987  field_type_ = kRtcpXrRrtrCode;
988  return true;
989}
990
991bool RtcpParser::ParseExtendedReportDelaySinceLastReceiverReport() {
992  ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
993  if (length < 12) {
994    state_ = kStateTopLevel;
995    EndCurrentBlock();
996    return false;
997  }
998  if (number_of_blocks_ == 0) {
999    // Continue parsing the extended report block.
1000    state_ = kStateExtendedReportBlock;
1001    return false;
1002  }
1003
1004  base::BigEndianReader big_endian_reader(
1005      reinterpret_cast<const char*>(rtcp_data_), length);
1006  big_endian_reader.ReadU32(&field_.dlrr.receivers_ssrc);
1007  big_endian_reader.ReadU32(&field_.dlrr.last_receiver_report);
1008  big_endian_reader.ReadU32(&field_.dlrr.delay_last_receiver_report);
1009
1010  rtcp_data_ += 12;
1011
1012  number_of_blocks_--;
1013  field_type_ = kRtcpXrDlrrCode;
1014  return true;
1015}
1016
1017// Converts a log event type to an integer value.
1018// NOTE: We have only allocated 4 bits to represent the type of event over the
1019// wire. Therefore, this function can only return values from 0 to 15.
1020uint8 ConvertEventTypeToWireFormat(CastLoggingEvent event) {
1021  switch (event) {
1022    case FRAME_ACK_SENT:
1023      return 11;
1024    case FRAME_PLAYOUT:
1025      return 12;
1026    case FRAME_DECODED:
1027      return 13;
1028    case PACKET_RECEIVED:
1029      return 14;
1030    default:
1031      return 0;  // Not an interesting event.
1032  }
1033}
1034
1035CastLoggingEvent TranslateToLogEventFromWireFormat(uint8 event) {
1036  // TODO(imcheng): Remove the old mappings once they are no longer used.
1037  switch (event) {
1038    case 1:  // AudioAckSent
1039    case 5:  // VideoAckSent
1040    case 11:  // Unified
1041      return FRAME_ACK_SENT;
1042    case 2:  // AudioPlayoutDelay
1043    case 7:  // VideoRenderDelay
1044    case 12:  // Unified
1045      return FRAME_PLAYOUT;
1046    case 3:  // AudioFrameDecoded
1047    case 6:  // VideoFrameDecoded
1048    case 13:  // Unified
1049      return FRAME_DECODED;
1050    case 4:  // AudioPacketReceived
1051    case 8:  // VideoPacketReceived
1052    case 14:  // Unified
1053      return PACKET_RECEIVED;
1054    case 9:  // DuplicateAudioPacketReceived
1055    case 10:  // DuplicateVideoPacketReceived
1056    default:
1057      // If the sender adds new log messages we will end up here until we add
1058      // the new messages in the receiver.
1059      VLOG(1) << "Unexpected log message received: " << static_cast<int>(event);
1060      NOTREACHED();
1061      return UNKNOWN;
1062  }
1063}
1064
1065}  // namespace cast
1066}  // namespace media
1067