Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / media / cast / net / rtcp / rtcp_utility.cc
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/big_endian.h"
8 #include "base/logging.h"
9 #include "media/cast/net/cast_transport_defines.h"
10
11 namespace media {
12 namespace cast {
13
14 RtcpParser::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
27 RtcpParser::~RtcpParser() {}
28
29 RtcpFieldTypes RtcpParser::FieldType() const { return field_type_; }
30
31 const RtcpField& RtcpParser::Field() const { return field_; }
32
33 RtcpFieldTypes RtcpParser::Begin() {
34   rtcp_data_ = rtcp_data_begin_;
35   return Iterate();
36 }
37
38 RtcpFieldTypes 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 kStateApplicationSpecificCastReceiverFrameLog:
53       IterateCastReceiverLogFrame();
54       break;
55     case kStateApplicationSpecificCastReceiverEventLog:
56       IterateCastReceiverLogEvent();
57       break;
58     case kStateExtendedReportBlock:
59       IterateExtendedReportItem();
60       break;
61     case kStateExtendedReportDelaySinceLastReceiverReport:
62       IterateExtendedReportDelaySinceLastReceiverReportItem();
63       break;
64     case kStatePayloadSpecificApplication:
65       IteratePayloadSpecificAppItem();
66       break;
67     case kStatePayloadSpecificCast:
68       IteratePayloadSpecificCastItem();
69       break;
70     case kStatePayloadSpecificCastNack:
71       IteratePayloadSpecificCastNackItem();
72       break;
73   }
74   return field_type_;
75 }
76
77 void RtcpParser::IterateTopLevel() {
78   for (;;) {
79     RtcpCommonHeader header;
80
81     bool success = RtcpParseCommonHeader(rtcp_data_, rtcp_data_end_, &header);
82     if (!success)
83       return;
84
85     rtcp_block_end_ = rtcp_data_ + header.length_in_octets;
86
87     if (rtcp_block_end_ > rtcp_data_end_)
88       return;  // Bad block!
89
90     switch (header.PT) {
91       case kPacketTypeSenderReport:
92         // number of Report blocks
93         number_of_blocks_ = header.IC;
94         ParseSR();
95         return;
96       case kPacketTypeReceiverReport:
97         // number of Report blocks
98         number_of_blocks_ = header.IC;
99         ParseRR();
100         return;
101       case kPacketTypeApplicationDefined:
102         if (!ParseApplicationDefined(header.IC)) {
103           // Nothing supported found, continue to next block!
104           break;
105         }
106         return;
107       case kPacketTypeGenericRtpFeedback:  // Fall through!
108       case kPacketTypePayloadSpecific:
109         if (!ParseFeedBackCommon(header)) {
110           // Nothing supported found, continue to next block!
111           break;
112         }
113         return;
114       case kPacketTypeXr:
115         if (!ParseExtendedReport()) {
116           break;  // Nothing supported found, continue to next block!
117         }
118         return;
119       default:
120         // Not supported! Skip!
121         EndCurrentBlock();
122         break;
123     }
124   }
125 }
126
127 void RtcpParser::IterateReportBlockItem() {
128   bool success = ParseReportBlockItem();
129   if (!success)
130     Iterate();
131 }
132
133 void RtcpParser::IterateExtendedReportItem() {
134   bool success = ParseExtendedReportItem();
135   if (!success)
136     Iterate();
137 }
138
139 void RtcpParser::IterateExtendedReportDelaySinceLastReceiverReportItem() {
140   bool success = ParseExtendedReportDelaySinceLastReceiverReport();
141   if (!success)
142     Iterate();
143 }
144
145 void RtcpParser::IteratePayloadSpecificAppItem() {
146   bool success = ParsePayloadSpecificAppItem();
147   if (!success)
148     Iterate();
149 }
150
151 void RtcpParser::IteratePayloadSpecificCastItem() {
152   bool success = ParsePayloadSpecificCastItem();
153   if (!success)
154     Iterate();
155 }
156
157 void RtcpParser::IteratePayloadSpecificCastNackItem() {
158   bool success = ParsePayloadSpecificCastNackItem();
159   if (!success)
160     Iterate();
161 }
162
163 void RtcpParser::IterateCastReceiverLogFrame() {
164   bool success = ParseCastReceiverLogFrameItem();
165   if (!success)
166     Iterate();
167 }
168
169 void RtcpParser::IterateCastReceiverLogEvent() {
170   bool success = ParseCastReceiverLogEventItem();
171   if (!success)
172     Iterate();
173 }
174
175 void RtcpParser::Validate() {
176   if (rtcp_data_ == NULL)
177     return;  // NOT VALID
178
179   RtcpCommonHeader header;
180   bool success =
181       RtcpParseCommonHeader(rtcp_data_begin_, rtcp_data_end_, &header);
182
183   if (!success)
184     return;  // NOT VALID!
185
186   valid_packet_ = true;
187 }
188
189 bool RtcpParser::IsValid() const { return valid_packet_; }
190
191 void RtcpParser::EndCurrentBlock() { rtcp_data_ = rtcp_block_end_; }
192
193 bool RtcpParser::RtcpParseCommonHeader(const uint8* data_begin,
194                                        const uint8* data_end,
195                                        RtcpCommonHeader* parsed_header) const {
196   if (!data_begin || !data_end)
197     return false;
198
199   //  0                   1                   2                   3
200   //  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
201   // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
202   // |V=2|P|    IC   |      PT       |             length            |
203   // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
204   //
205   // Common header for all Rtcp packets, 4 octets.
206
207   if ((data_end - data_begin) < 4)
208     return false;
209
210   parsed_header->V = data_begin[0] >> 6;
211   parsed_header->P = ((data_begin[0] & 0x20) == 0) ? false : true;
212   parsed_header->IC = data_begin[0] & 0x1f;
213   parsed_header->PT = data_begin[1];
214
215   parsed_header->length_in_octets =
216       ((data_begin[2] << 8) + data_begin[3] + 1) * 4;
217
218   if (parsed_header->length_in_octets == 0)
219     return false;
220
221   // Check if RTP version field == 2.
222   if (parsed_header->V != 2)
223     return false;
224
225   return true;
226 }
227
228 bool RtcpParser::ParseRR() {
229   ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
230   if (length < 8)
231     return false;
232
233   field_type_ = kRtcpRrCode;
234
235   base::BigEndianReader big_endian_reader(
236       reinterpret_cast<const char*>(rtcp_data_), length);
237   big_endian_reader.Skip(4);  // Skip header
238   big_endian_reader.ReadU32(&field_.receiver_report.sender_ssrc);
239   field_.receiver_report.number_of_report_blocks = number_of_blocks_;
240   rtcp_data_ += 8;
241
242   // State transition
243   state_ = kStateReportBlock;
244   return true;
245 }
246
247 bool RtcpParser::ParseSR() {
248   ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
249   if (length < 28) {
250     EndCurrentBlock();
251     return false;
252   }
253   field_type_ = kRtcpSrCode;
254
255   base::BigEndianReader big_endian_reader(
256       reinterpret_cast<const char*>(rtcp_data_), length);
257   big_endian_reader.Skip(4);  // Skip header
258   big_endian_reader.ReadU32(&field_.sender_report.sender_ssrc);
259   big_endian_reader.ReadU32(&field_.sender_report.ntp_most_significant);
260   big_endian_reader.ReadU32(&field_.sender_report.ntp_least_significant);
261   big_endian_reader.ReadU32(&field_.sender_report.rtp_timestamp);
262   big_endian_reader.ReadU32(&field_.sender_report.sender_packet_count);
263   big_endian_reader.ReadU32(&field_.sender_report.sender_octet_count);
264   field_.sender_report.number_of_report_blocks = number_of_blocks_;
265   rtcp_data_ += 28;
266
267   if (number_of_blocks_ != 0) {
268     // State transition.
269     state_ = kStateReportBlock;
270   } else {
271     // Don't go to state report block item if 0 report blocks.
272     state_ = kStateTopLevel;
273     EndCurrentBlock();
274   }
275   return true;
276 }
277
278 bool RtcpParser::ParseReportBlockItem() {
279   ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
280   if (length < 24 || number_of_blocks_ <= 0) {
281     state_ = kStateTopLevel;
282     EndCurrentBlock();
283     return false;
284   }
285
286   base::BigEndianReader big_endian_reader(
287       reinterpret_cast<const char*>(rtcp_data_), length);
288   big_endian_reader.ReadU32(&field_.report_block_item.ssrc);
289   big_endian_reader.ReadU8(&field_.report_block_item.fraction_lost);
290
291   uint8 temp_number_of_packets_lost;
292   big_endian_reader.ReadU8(&temp_number_of_packets_lost);
293   field_.report_block_item.cumulative_number_of_packets_lost =
294       temp_number_of_packets_lost << 16;
295   big_endian_reader.ReadU8(&temp_number_of_packets_lost);
296   field_.report_block_item.cumulative_number_of_packets_lost +=
297       temp_number_of_packets_lost << 8;
298   big_endian_reader.ReadU8(&temp_number_of_packets_lost);
299   field_.report_block_item.cumulative_number_of_packets_lost +=
300       temp_number_of_packets_lost;
301
302   big_endian_reader.ReadU32(
303       &field_.report_block_item.extended_highest_sequence_number);
304   big_endian_reader.ReadU32(&field_.report_block_item.jitter);
305   big_endian_reader.ReadU32(&field_.report_block_item.last_sender_report);
306   big_endian_reader.ReadU32(&field_.report_block_item.delay_last_sender_report);
307   rtcp_data_ += 24;
308
309   number_of_blocks_--;
310   field_type_ = kRtcpReportBlockItemCode;
311   return true;
312 }
313
314 bool RtcpParser::ParseApplicationDefined(uint8 subtype) {
315   ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
316   if (length < 16 || subtype != kReceiverLogSubtype) {
317     state_ = kStateTopLevel;
318     EndCurrentBlock();
319     return false;
320   }
321
322   uint32 sender_ssrc;
323   uint32 name;
324
325   base::BigEndianReader big_endian_reader(
326       reinterpret_cast<const char*>(rtcp_data_), length);
327   big_endian_reader.Skip(4);  // Skip header.
328   big_endian_reader.ReadU32(&sender_ssrc);
329   big_endian_reader.ReadU32(&name);
330
331   if (name != kCast) {
332     state_ = kStateTopLevel;
333     EndCurrentBlock();
334     return false;
335   }
336   rtcp_data_ += 12;
337   switch (subtype) {
338     case kReceiverLogSubtype:
339       state_ = kStateApplicationSpecificCastReceiverFrameLog;
340       field_type_ = kRtcpApplicationSpecificCastReceiverLogCode;
341       field_.cast_receiver_log.sender_ssrc = sender_ssrc;
342       break;
343     default:
344       NOTREACHED();
345   }
346   return true;
347 }
348
349 bool RtcpParser::ParseCastReceiverLogFrameItem() {
350   ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
351   if (length < 12) {
352     state_ = kStateTopLevel;
353     EndCurrentBlock();
354     return false;
355   }
356   uint32 rtp_timestamp;
357   uint32 data;
358   base::BigEndianReader big_endian_reader(
359       reinterpret_cast<const char*>(rtcp_data_), length);
360   big_endian_reader.ReadU32(&rtp_timestamp);
361   big_endian_reader.ReadU32(&data);
362
363   rtcp_data_ += 8;
364
365   field_.cast_receiver_log.rtp_timestamp = rtp_timestamp;
366   // We have 24 LSB of the event timestamp base on the wire.
367   field_.cast_receiver_log.event_timestamp_base = data & 0xffffff;
368
369   number_of_blocks_ = 1 + static_cast<uint8>(data >> 24);
370   state_ = kStateApplicationSpecificCastReceiverEventLog;
371   field_type_ = kRtcpApplicationSpecificCastReceiverLogFrameCode;
372   return true;
373 }
374
375 bool RtcpParser::ParseCastReceiverLogEventItem() {
376   ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
377   if (length < 4) {
378     state_ = kStateTopLevel;
379     EndCurrentBlock();
380     return false;
381   }
382   if (number_of_blocks_ == 0) {
383     // Continue parsing the next receiver frame event.
384     state_ = kStateApplicationSpecificCastReceiverFrameLog;
385     return false;
386   }
387   number_of_blocks_--;
388
389   uint16 delay_delta_or_packet_id;
390   uint16 event_type_and_timestamp_delta;
391   base::BigEndianReader big_endian_reader(
392       reinterpret_cast<const char*>(rtcp_data_), length);
393   big_endian_reader.ReadU16(&delay_delta_or_packet_id);
394   big_endian_reader.ReadU16(&event_type_and_timestamp_delta);
395
396   rtcp_data_ += 4;
397
398   field_.cast_receiver_log.event =
399       static_cast<uint8>(event_type_and_timestamp_delta >> 12);
400   // delay_delta is in union'ed with packet_id.
401   field_.cast_receiver_log.delay_delta_or_packet_id.packet_id =
402       delay_delta_or_packet_id;
403   field_.cast_receiver_log.event_timestamp_delta =
404       event_type_and_timestamp_delta & 0xfff;
405
406   field_type_ = kRtcpApplicationSpecificCastReceiverLogEventCode;
407   return true;
408 }
409
410 bool RtcpParser::ParseFeedBackCommon(const RtcpCommonHeader& header) {
411   DCHECK((header.PT == kPacketTypeGenericRtpFeedback) ||
412          (header.PT == kPacketTypePayloadSpecific))
413       << "Invalid state";
414
415   ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
416
417   if (length < 12) {  // 4 * 3, RFC4585 section 6.1
418     EndCurrentBlock();
419     return false;
420   }
421
422   uint32 sender_ssrc;
423   uint32 media_ssrc;
424   base::BigEndianReader big_endian_reader(
425       reinterpret_cast<const char*>(rtcp_data_), length);
426   big_endian_reader.Skip(4);  // Skip header.
427   big_endian_reader.ReadU32(&sender_ssrc);
428   big_endian_reader.ReadU32(&media_ssrc);
429
430   rtcp_data_ += 12;
431
432   if (header.PT == kPacketTypePayloadSpecific) {
433     // Payload specific feedback
434     switch (header.IC) {
435       case 1:
436         // PLI
437         break;
438       case 2:
439         // SLI.
440         break;
441       case 3:
442         // RPSI.
443         break;
444       case 4:
445         // FIR.
446         break;
447       case 15:
448         field_type_ = kRtcpPayloadSpecificAppCode;
449         field_.application_specific.sender_ssrc = sender_ssrc;
450         field_.application_specific.media_ssrc = media_ssrc;
451         state_ = kStatePayloadSpecificApplication;
452         return true;
453       default:
454         break;
455     }
456
457     EndCurrentBlock();
458     return false;
459   } else {
460     DCHECK(false) << "Invalid state";
461     EndCurrentBlock();
462     return false;
463   }
464 }
465
466 bool RtcpParser::ParsePayloadSpecificAppItem() {
467   ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
468
469   if (length < 4) {
470     state_ = kStateTopLevel;
471     EndCurrentBlock();
472     return false;
473   }
474   uint32 name;
475   base::BigEndianReader big_endian_reader(
476       reinterpret_cast<const char*>(rtcp_data_), length);
477   big_endian_reader.ReadU32(&name);
478   rtcp_data_ += 4;
479
480   if (name == kCast) {
481     field_type_ = kRtcpPayloadSpecificCastCode;
482     state_ = kStatePayloadSpecificCast;
483     return true;
484   }
485   state_ = kStateTopLevel;
486   EndCurrentBlock();
487   return false;
488 }
489
490 bool RtcpParser::ParsePayloadSpecificCastItem() {
491   ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
492   if (length < 4) {
493     state_ = kStateTopLevel;
494     EndCurrentBlock();
495     return false;
496   }
497   field_type_ = kRtcpPayloadSpecificCastCode;
498
499   base::BigEndianReader big_endian_reader(
500       reinterpret_cast<const char*>(rtcp_data_), length);
501   big_endian_reader.ReadU8(&field_.cast_item.last_frame_id);
502   big_endian_reader.ReadU8(&field_.cast_item.number_of_lost_fields);
503   big_endian_reader.ReadU16(&field_.cast_item.target_delay_ms);
504
505   rtcp_data_ += 4;
506
507   if (field_.cast_item.number_of_lost_fields != 0) {
508     // State transition
509     state_ = kStatePayloadSpecificCastNack;
510   } else {
511     // Don't go to state cast nack item if got 0 fields.
512     state_ = kStateTopLevel;
513     EndCurrentBlock();
514   }
515   return true;
516 }
517
518 bool RtcpParser::ParsePayloadSpecificCastNackItem() {
519   ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
520   if (length < 4) {
521     state_ = kStateTopLevel;
522     EndCurrentBlock();
523     return false;
524   }
525   field_type_ = kRtcpPayloadSpecificCastNackItemCode;
526
527   base::BigEndianReader big_endian_reader(
528       reinterpret_cast<const char*>(rtcp_data_), length);
529   big_endian_reader.ReadU8(&field_.cast_nack_item.frame_id);
530   big_endian_reader.ReadU16(&field_.cast_nack_item.packet_id);
531   big_endian_reader.ReadU8(&field_.cast_nack_item.bitmask);
532
533   rtcp_data_ += 4;
534   return true;
535 }
536
537 bool RtcpParser::ParseExtendedReport() {
538   ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
539   if (length < 8)
540     return false;
541
542   field_type_ = kRtcpXrCode;
543
544   base::BigEndianReader big_endian_reader(
545       reinterpret_cast<const char*>(rtcp_data_), length);
546   big_endian_reader.Skip(4);  // Skip header.
547   big_endian_reader.ReadU32(&field_.extended_report.sender_ssrc);
548
549   rtcp_data_ += 8;
550
551   state_ = kStateExtendedReportBlock;
552   return true;
553 }
554
555 bool RtcpParser::ParseExtendedReportItem() {
556   ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
557   if (length < 4) {
558     state_ = kStateTopLevel;
559     EndCurrentBlock();
560     return false;
561   }
562
563   uint8 block_type;
564   uint16 block_length;
565   base::BigEndianReader big_endian_reader(
566       reinterpret_cast<const char*>(rtcp_data_), length);
567   big_endian_reader.ReadU8(&block_type);
568   big_endian_reader.Skip(1);  // Ignore reserved.
569   big_endian_reader.ReadU16(&block_length);
570
571   rtcp_data_ += 4;
572
573   switch (block_type) {
574     case 4:  // RRTR. RFC3611 Section 4.4.
575       if (block_length != 2) {
576         // Invalid block length.
577         state_ = kStateTopLevel;
578         EndCurrentBlock();
579         return false;
580       }
581       return ParseExtendedReportReceiverReferenceTimeReport();
582     case 5:  // DLRR. RFC3611 Section 4.5.
583       if (block_length % 3 != 0) {
584         // Invalid block length.
585         state_ = kStateTopLevel;
586         EndCurrentBlock();
587         return false;
588       }
589       if (block_length >= 3) {
590         number_of_blocks_ = block_length / 3;
591         state_ = kStateExtendedReportDelaySinceLastReceiverReport;
592         return ParseExtendedReportDelaySinceLastReceiverReport();
593       }
594       return true;
595     default:
596       if (length < block_length * 4) {
597         state_ = kStateTopLevel;
598         EndCurrentBlock();
599         return false;
600       }
601       field_type_ = kRtcpXrUnknownItemCode;
602       rtcp_data_ += block_length * 4;
603       return true;
604   }
605 }
606
607 bool RtcpParser::ParseExtendedReportReceiverReferenceTimeReport() {
608   ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
609   if (length < 8) {
610     state_ = kStateTopLevel;
611     EndCurrentBlock();
612     return false;
613   }
614
615   base::BigEndianReader big_endian_reader(
616       reinterpret_cast<const char*>(rtcp_data_), length);
617   big_endian_reader.ReadU32(&field_.rrtr.ntp_most_significant);
618   big_endian_reader.ReadU32(&field_.rrtr.ntp_least_significant);
619
620   rtcp_data_ += 8;
621
622   field_type_ = kRtcpXrRrtrCode;
623   return true;
624 }
625
626 bool RtcpParser::ParseExtendedReportDelaySinceLastReceiverReport() {
627   ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
628   if (length < 12) {
629     state_ = kStateTopLevel;
630     EndCurrentBlock();
631     return false;
632   }
633   if (number_of_blocks_ == 0) {
634     // Continue parsing the extended report block.
635     state_ = kStateExtendedReportBlock;
636     return false;
637   }
638
639   base::BigEndianReader big_endian_reader(
640       reinterpret_cast<const char*>(rtcp_data_), length);
641   big_endian_reader.ReadU32(&field_.dlrr.receivers_ssrc);
642   big_endian_reader.ReadU32(&field_.dlrr.last_receiver_report);
643   big_endian_reader.ReadU32(&field_.dlrr.delay_last_receiver_report);
644
645   rtcp_data_ += 12;
646
647   number_of_blocks_--;
648   field_type_ = kRtcpXrDlrrCode;
649   return true;
650 }
651
652 // Converts a log event type to an integer value.
653 // NOTE: We have only allocated 4 bits to represent the type of event over the
654 // wire. Therefore, this function can only return values from 0 to 15.
655 uint8 ConvertEventTypeToWireFormat(CastLoggingEvent event) {
656   switch (event) {
657     case FRAME_ACK_SENT:
658       return 11;
659     case FRAME_PLAYOUT:
660       return 12;
661     case FRAME_DECODED:
662       return 13;
663     case PACKET_RECEIVED:
664       return 14;
665     default:
666       return 0;  // Not an interesting event.
667   }
668 }
669
670 CastLoggingEvent TranslateToLogEventFromWireFormat(uint8 event) {
671   // TODO(imcheng): Remove the old mappings once they are no longer used.
672   switch (event) {
673     case 1:  // AudioAckSent
674     case 5:  // VideoAckSent
675     case 11:  // Unified
676       return FRAME_ACK_SENT;
677     case 2:  // AudioPlayoutDelay
678     case 7:  // VideoRenderDelay
679     case 12:  // Unified
680       return FRAME_PLAYOUT;
681     case 3:  // AudioFrameDecoded
682     case 6:  // VideoFrameDecoded
683     case 13:  // Unified
684       return FRAME_DECODED;
685     case 4:  // AudioPacketReceived
686     case 8:  // VideoPacketReceived
687     case 14:  // Unified
688       return PACKET_RECEIVED;
689     case 9:  // DuplicateAudioPacketReceived
690     case 10:  // DuplicateVideoPacketReceived
691     default:
692       // If the sender adds new log messages we will end up here until we add
693       // the new messages in the receiver.
694       VLOG(1) << "Unexpected log message received: " << static_cast<int>(event);
695       NOTREACHED();
696       return UNKNOWN;
697   }
698 }
699
700 }  // namespace cast
701 }  // namespace media