OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/cast/rtcp/rtcp_receiver.h" | 5 #include "media/cast/rtcp/rtcp_receiver.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "media/cast/rtcp/rtcp_utility.h" | 8 #include "media/cast/rtcp/rtcp_utility.h" |
9 | 9 |
| 10 namespace { |
| 11 |
| 12 media::cast::CastLoggingEvent TranslateToLogEventFromWireFormat(uint8 event) { |
| 13 switch (event) { |
| 14 case 1: |
| 15 return media::cast::kAckSent; |
| 16 case 2: |
| 17 return media::cast::kAudioPlayoutDelay; |
| 18 case 3: |
| 19 return media::cast::kAudioFrameDecoded; |
| 20 case 4: |
| 21 return media::cast::kVideoFrameDecoded; |
| 22 case 5: |
| 23 return media::cast::kVideoRenderDelay; |
| 24 case 6: |
| 25 return media::cast::kPacketReceived; |
| 26 default: |
| 27 // If the sender adds new log messages we will end up here until we add |
| 28 // the new messages in the receiver. |
| 29 VLOG(1) << "Unexpected log message received: " << static_cast<int>(event); |
| 30 NOTREACHED(); |
| 31 return media::cast::kUnknown; |
| 32 } |
| 33 } |
| 34 |
| 35 media::cast::RtcpSenderFrameStatus TranslateToFrameStatusFromWireFormat( |
| 36 uint8 status) { |
| 37 switch (status) { |
| 38 case 0: |
| 39 return media::cast::kRtcpSenderFrameStatusUnknown; |
| 40 case 1: |
| 41 return media::cast::kRtcpSenderFrameStatusDroppedByEncoder; |
| 42 case 2: |
| 43 return media::cast::kRtcpSenderFrameStatusDroppedByFlowControl; |
| 44 case 3: |
| 45 return media::cast::kRtcpSenderFrameStatusSentToNetwork; |
| 46 default: |
| 47 // If the sender adds new log messages we will end up here until we add |
| 48 // the new messages in the receiver. |
| 49 NOTREACHED(); |
| 50 VLOG(1) << "Unexpected status received: " << static_cast<int>(status); |
| 51 return media::cast::kRtcpSenderFrameStatusUnknown; |
| 52 } |
| 53 } |
| 54 |
| 55 } // namespace |
| 56 |
10 namespace media { | 57 namespace media { |
11 namespace cast { | 58 namespace cast { |
12 | 59 |
13 RtcpReceiver::RtcpReceiver(scoped_refptr<CastEnvironment> cast_environment, | 60 RtcpReceiver::RtcpReceiver(scoped_refptr<CastEnvironment> cast_environment, |
14 RtcpSenderFeedback* sender_feedback, | 61 RtcpSenderFeedback* sender_feedback, |
15 RtcpReceiverFeedback* receiver_feedback, | 62 RtcpReceiverFeedback* receiver_feedback, |
16 RtcpRttFeedback* rtt_feedback, | 63 RtcpRttFeedback* rtt_feedback, |
17 uint32 local_ssrc) | 64 uint32 local_ssrc) |
18 : ssrc_(local_ssrc), | 65 : ssrc_(local_ssrc), |
19 remote_ssrc_(0), | 66 remote_ssrc_(0), |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 break; | 107 break; |
61 case kRtcpPayloadSpecificRpsiCode: | 108 case kRtcpPayloadSpecificRpsiCode: |
62 HandleRpsi(rtcp_parser); | 109 HandleRpsi(rtcp_parser); |
63 break; | 110 break; |
64 case kRtcpPayloadSpecificFirCode: | 111 case kRtcpPayloadSpecificFirCode: |
65 HandleFIR(rtcp_parser); | 112 HandleFIR(rtcp_parser); |
66 break; | 113 break; |
67 case kRtcpPayloadSpecificAppCode: | 114 case kRtcpPayloadSpecificAppCode: |
68 HandlePayloadSpecificApp(rtcp_parser); | 115 HandlePayloadSpecificApp(rtcp_parser); |
69 break; | 116 break; |
| 117 case kRtcpApplicationSpecificCastReceiverLogCode: |
| 118 HandleApplicationSpecificCastReceiverLog(rtcp_parser); |
| 119 break; |
| 120 case kRtcpApplicationSpecificCastSenderLogCode: |
| 121 HandleApplicationSpecificCastSenderLog(rtcp_parser); |
| 122 break; |
70 case kRtcpPayloadSpecificRembCode: | 123 case kRtcpPayloadSpecificRembCode: |
71 case kRtcpPayloadSpecificRembItemCode: | 124 case kRtcpPayloadSpecificRembItemCode: |
72 // Ignore this until we want to support interop with webrtc. | |
73 rtcp_parser->Iterate(); | |
74 break; | |
75 case kRtcpPayloadSpecificCastCode: | 125 case kRtcpPayloadSpecificCastCode: |
76 case kRtcpPayloadSpecificCastNackItemCode: | 126 case kRtcpPayloadSpecificCastNackItemCode: |
77 rtcp_parser->Iterate(); | 127 case kRtcpApplicationSpecificCastReceiverLogFrameCode: |
78 break; | 128 case kRtcpApplicationSpecificCastReceiverLogEventCode: |
79 case kRtcpNotValidCode: | 129 case kRtcpNotValidCode: |
80 case kRtcpReportBlockItemCode: | 130 case kRtcpReportBlockItemCode: |
81 case kRtcpSdesChunkCode: | 131 case kRtcpSdesChunkCode: |
82 case kRtcpGenericRtpFeedbackNackItemCode: | 132 case kRtcpGenericRtpFeedbackNackItemCode: |
83 case kRtcpPayloadSpecificFirItemCode: | 133 case kRtcpPayloadSpecificFirItemCode: |
84 case kRtcpXrRrtrCode: | 134 case kRtcpXrRrtrCode: |
85 case kRtcpXrDlrrCode: | 135 case kRtcpXrDlrrCode: |
86 case kRtcpXrUnknownItemCode: | 136 case kRtcpXrUnknownItemCode: |
87 rtcp_parser->Iterate(); | 137 rtcp_parser->Iterate(); |
88 DCHECK(false) << "Invalid state"; | 138 NOTREACHED() << "Invalid state"; |
89 break; | 139 break; |
90 } | 140 } |
91 field_type = rtcp_parser->FieldType(); | 141 field_type = rtcp_parser->FieldType(); |
92 } | 142 } |
93 } | 143 } |
94 | 144 |
95 void RtcpReceiver::HandleSenderReport(RtcpParser* rtcp_parser) { | 145 void RtcpReceiver::HandleSenderReport(RtcpParser* rtcp_parser) { |
96 RtcpFieldTypes rtcp_field_type = rtcp_parser->FieldType(); | 146 RtcpFieldTypes rtcp_field_type = rtcp_parser->FieldType(); |
97 const RtcpField& rtcp_field = rtcp_parser->Field(); | 147 const RtcpField& rtcp_field = rtcp_parser->Field(); |
98 | 148 |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 rtt_feedback_->OnReceivedDelaySinceLastReport( | 295 rtt_feedback_->OnReceivedDelaySinceLastReport( |
246 rtcp_field.dlrr.receivers_ssrc, | 296 rtcp_field.dlrr.receivers_ssrc, |
247 rtcp_field.dlrr.last_receiver_report, | 297 rtcp_field.dlrr.last_receiver_report, |
248 rtcp_field.dlrr.delay_last_receiver_report); | 298 rtcp_field.dlrr.delay_last_receiver_report); |
249 } | 299 } |
250 } | 300 } |
251 | 301 |
252 void RtcpReceiver::HandleNACK(RtcpParser* rtcp_parser) { | 302 void RtcpReceiver::HandleNACK(RtcpParser* rtcp_parser) { |
253 const RtcpField& rtcp_field = rtcp_parser->Field(); | 303 const RtcpField& rtcp_field = rtcp_parser->Field(); |
254 if (ssrc_ != rtcp_field.nack.media_ssrc) { | 304 if (ssrc_ != rtcp_field.nack.media_ssrc) { |
255 // Not to us. | 305 RtcpFieldTypes field_type; |
256 rtcp_parser->Iterate(); | 306 // Message not to us. Iterate until we have passed this message. |
| 307 do { |
| 308 field_type = rtcp_parser->Iterate(); |
| 309 } while (field_type == kRtcpGenericRtpFeedbackNackItemCode); |
257 return; | 310 return; |
258 } | 311 } |
259 std::list<uint16> nackSequenceNumbers; | 312 std::list<uint16> nackSequenceNumbers; |
260 | 313 |
261 RtcpFieldTypes field_type = rtcp_parser->Iterate(); | 314 RtcpFieldTypes field_type = rtcp_parser->Iterate(); |
262 while (field_type == kRtcpGenericRtpFeedbackNackItemCode) { | 315 while (field_type == kRtcpGenericRtpFeedbackNackItemCode) { |
263 HandleNACKItem(&rtcp_field, &nackSequenceNumbers); | 316 HandleNACKItem(&rtcp_field, &nackSequenceNumbers); |
264 field_type = rtcp_parser->Iterate(); | 317 field_type = rtcp_parser->Iterate(); |
265 } | 318 } |
266 } | 319 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 } | 377 } |
325 rpsi_picture_id += (rtcp_field.rpsi.native_bit_string[bytes - 1] & 0x7f); | 378 rpsi_picture_id += (rtcp_field.rpsi.native_bit_string[bytes - 1] & 0x7f); |
326 | 379 |
327 VLOG(1) << "Cast RTCP received RPSI with picture_id " << rpsi_picture_id; | 380 VLOG(1) << "Cast RTCP received RPSI with picture_id " << rpsi_picture_id; |
328 } | 381 } |
329 | 382 |
330 void RtcpReceiver::HandlePayloadSpecificApp(RtcpParser* rtcp_parser) { | 383 void RtcpReceiver::HandlePayloadSpecificApp(RtcpParser* rtcp_parser) { |
331 const RtcpField& rtcp_field = rtcp_parser->Field(); | 384 const RtcpField& rtcp_field = rtcp_parser->Field(); |
332 uint32 remote_ssrc = rtcp_field.application_specific.sender_ssrc; | 385 uint32 remote_ssrc = rtcp_field.application_specific.sender_ssrc; |
333 if (remote_ssrc_ != remote_ssrc) { | 386 if (remote_ssrc_ != remote_ssrc) { |
334 // Message not to us. | 387 // Message not to us. Iterate until we have passed this message. |
335 rtcp_parser->Iterate(); | 388 RtcpFieldTypes field_type; |
| 389 do { |
| 390 field_type = rtcp_parser->Iterate(); |
| 391 } while (field_type == kRtcpPayloadSpecificRembCode || |
| 392 field_type == kRtcpPayloadSpecificRembItemCode || |
| 393 field_type == kRtcpPayloadSpecificCastCode || |
| 394 field_type == kRtcpPayloadSpecificCastNackItemCode); |
336 return; | 395 return; |
337 } | 396 } |
338 | 397 |
339 RtcpFieldTypes packet_type = rtcp_parser->Iterate(); | 398 RtcpFieldTypes packet_type = rtcp_parser->Iterate(); |
340 switch (packet_type) { | 399 switch (packet_type) { |
341 case kRtcpPayloadSpecificRembCode: | 400 case kRtcpPayloadSpecificRembCode: |
342 packet_type = rtcp_parser->Iterate(); | 401 packet_type = rtcp_parser->Iterate(); |
343 if (packet_type == kRtcpPayloadSpecificRembItemCode) { | 402 if (packet_type == kRtcpPayloadSpecificRembItemCode) { |
344 HandlePayloadSpecificRembItem(rtcp_parser); | 403 HandlePayloadSpecificRembItem(rtcp_parser); |
345 rtcp_parser->Iterate(); | 404 rtcp_parser->Iterate(); |
(...skipping 16 matching lines...) Expand all Loading... |
362 for (int i = 0; i < rtcp_field.remb_item.number_of_ssrcs; ++i) { | 421 for (int i = 0; i < rtcp_field.remb_item.number_of_ssrcs; ++i) { |
363 if (rtcp_field.remb_item.ssrcs[i] == ssrc_) { | 422 if (rtcp_field.remb_item.ssrcs[i] == ssrc_) { |
364 // Found matching ssrc. | 423 // Found matching ssrc. |
365 VLOG(1) << "Cast RTCP received REMB with received_bitrate " | 424 VLOG(1) << "Cast RTCP received REMB with received_bitrate " |
366 << rtcp_field.remb_item.bitrate; | 425 << rtcp_field.remb_item.bitrate; |
367 return; | 426 return; |
368 } | 427 } |
369 } | 428 } |
370 } | 429 } |
371 | 430 |
| 431 void RtcpReceiver::HandleApplicationSpecificCastReceiverLog( |
| 432 RtcpParser* rtcp_parser) { |
| 433 const RtcpField& rtcp_field = rtcp_parser->Field(); |
| 434 |
| 435 uint32 remote_ssrc = rtcp_field.cast_receiver_log.sender_ssrc; |
| 436 if (remote_ssrc_ != remote_ssrc) { |
| 437 // Message not to us. Iterate until we have passed this message. |
| 438 RtcpFieldTypes field_type; |
| 439 do { |
| 440 field_type = rtcp_parser->Iterate(); |
| 441 } while (field_type == kRtcpApplicationSpecificCastReceiverLogFrameCode || |
| 442 field_type == kRtcpApplicationSpecificCastReceiverLogEventCode); |
| 443 return; |
| 444 } |
| 445 RtcpReceiverLogMessage receiver_log; |
| 446 RtcpFieldTypes field_type = rtcp_parser->Iterate(); |
| 447 while (field_type == kRtcpApplicationSpecificCastReceiverLogFrameCode) { |
| 448 RtcpReceiverFrameLogMessage frame_log( |
| 449 rtcp_field.cast_receiver_log.rtp_timestamp); |
| 450 |
| 451 field_type = rtcp_parser->Iterate(); |
| 452 while (field_type == kRtcpApplicationSpecificCastReceiverLogEventCode) { |
| 453 HandleApplicationSpecificCastReceiverEventLog(rtcp_parser, |
| 454 &frame_log.event_log_messages_); |
| 455 field_type = rtcp_parser->Iterate(); |
| 456 } |
| 457 receiver_log.push_back(frame_log); |
| 458 } |
| 459 |
| 460 if (receiver_feedback_ && !receiver_log.empty()) { |
| 461 receiver_feedback_->OnReceivedReceiverLog(receiver_log); |
| 462 } |
| 463 } |
| 464 |
| 465 void RtcpReceiver::HandleApplicationSpecificCastReceiverEventLog( |
| 466 RtcpParser* rtcp_parser, |
| 467 RtcpReceiverEventLogMessages* event_log_messages) { |
| 468 const RtcpField& rtcp_field = rtcp_parser->Field(); |
| 469 |
| 470 RtcpReceiverEventLogMessage event_log; |
| 471 event_log.type = TranslateToLogEventFromWireFormat( |
| 472 rtcp_field.cast_receiver_log.event); |
| 473 event_log.event_timestamp = base::TimeTicks() + |
| 474 base::TimeDelta::FromMilliseconds( |
| 475 rtcp_field.cast_receiver_log.event_timestamp_base + |
| 476 rtcp_field.cast_receiver_log.event_timestamp_delta); |
| 477 event_log.delay_delta = base::TimeDelta::FromMilliseconds( |
| 478 rtcp_field.cast_receiver_log.delay_delta_or_packet_id); |
| 479 event_log.packet_id = |
| 480 rtcp_field.cast_receiver_log.delay_delta_or_packet_id; |
| 481 event_log_messages->push_back(event_log); |
| 482 } |
| 483 |
| 484 void RtcpReceiver::HandleApplicationSpecificCastSenderLog( |
| 485 RtcpParser* rtcp_parser) { |
| 486 const RtcpField& rtcp_field = rtcp_parser->Field(); |
| 487 uint32 remote_ssrc = rtcp_field.cast_sender_log.sender_ssrc; |
| 488 |
| 489 if (remote_ssrc_ != remote_ssrc) { |
| 490 RtcpFieldTypes field_type; |
| 491 // Message not to us. Iterate until we have passed this message. |
| 492 do { |
| 493 field_type = rtcp_parser->Iterate(); |
| 494 } while (field_type == kRtcpApplicationSpecificCastSenderLogCode); |
| 495 return; |
| 496 } |
| 497 RtcpSenderLogMessage sender_log; |
| 498 |
| 499 RtcpFieldTypes field_type = rtcp_parser->Iterate(); |
| 500 while (field_type == kRtcpApplicationSpecificCastSenderLogCode) { |
| 501 const RtcpField& rtcp_field = rtcp_parser->Field(); |
| 502 RtcpSenderFrameLogMessage frame_log; |
| 503 frame_log.frame_status = |
| 504 TranslateToFrameStatusFromWireFormat(rtcp_field.cast_sender_log.status); |
| 505 frame_log.rtp_timestamp = rtcp_field.cast_sender_log.rtp_timestamp; |
| 506 sender_log.push_back(frame_log); |
| 507 field_type = rtcp_parser->Iterate(); |
| 508 } |
| 509 if (receiver_feedback_) { |
| 510 receiver_feedback_->OnReceivedSenderLog(sender_log); |
| 511 } |
| 512 } |
| 513 |
372 void RtcpReceiver::HandlePayloadSpecificCastItem(RtcpParser* rtcp_parser) { | 514 void RtcpReceiver::HandlePayloadSpecificCastItem(RtcpParser* rtcp_parser) { |
373 const RtcpField& rtcp_field = rtcp_parser->Field(); | 515 const RtcpField& rtcp_field = rtcp_parser->Field(); |
374 | |
375 RtcpCastMessage cast_message(remote_ssrc_); | 516 RtcpCastMessage cast_message(remote_ssrc_); |
376 cast_message.ack_frame_id_ = ack_frame_id_wrap_helper_.MapTo32bitsFrameId( | 517 cast_message.ack_frame_id_ = ack_frame_id_wrap_helper_.MapTo32bitsFrameId( |
377 rtcp_field.cast_item.last_frame_id); | 518 rtcp_field.cast_item.last_frame_id); |
378 | 519 |
379 RtcpFieldTypes packet_type = rtcp_parser->Iterate(); | 520 RtcpFieldTypes packet_type = rtcp_parser->Iterate(); |
380 while (packet_type == kRtcpPayloadSpecificCastNackItemCode) { | 521 while (packet_type == kRtcpPayloadSpecificCastNackItemCode) { |
381 const RtcpField& rtcp_field = rtcp_parser->Field(); | 522 const RtcpField& rtcp_field = rtcp_parser->Field(); |
382 HandlePayloadSpecificCastNackItem( | 523 HandlePayloadSpecificCastNackItem( |
383 &rtcp_field, &cast_message.missing_frames_and_packets_); | 524 &rtcp_field, &cast_message.missing_frames_and_packets_); |
384 packet_type = rtcp_parser->Iterate(); | 525 packet_type = rtcp_parser->Iterate(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
435 | 576 |
436 void RtcpReceiver::HandleFIRItem(const RtcpField* rtcp_field) { | 577 void RtcpReceiver::HandleFIRItem(const RtcpField* rtcp_field) { |
437 // Is it our sender that is requested to generate a new keyframe. | 578 // Is it our sender that is requested to generate a new keyframe. |
438 if (ssrc_ != rtcp_field->fir_item.ssrc) return; | 579 if (ssrc_ != rtcp_field->fir_item.ssrc) return; |
439 | 580 |
440 VLOG(1) << "Cast RTCP received FIR on our SSRC " << ssrc_; | 581 VLOG(1) << "Cast RTCP received FIR on our SSRC " << ssrc_; |
441 } | 582 } |
442 | 583 |
443 } // namespace cast | 584 } // namespace cast |
444 } // namespace media | 585 } // namespace media |
OLD | NEW |