Forward LossNotification from RTCPReceiver to EncoderRtcpFeedback
TBR=sprang@webrtc.org
Bug: webrtc:10501
Change-Id: I09a571a65ba8515b027ee32d1f46e5cc7f699704
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/131325
Reviewed-by: Elad Alon <eladalon@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Elad Alon <eladalon@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27513}
diff --git a/call/rtp_transport_controller_send_interface.h b/call/rtp_transport_controller_send_interface.h
index d564035..450b65b 100644
--- a/call/rtp_transport_controller_send_interface.h
+++ b/call/rtp_transport_controller_send_interface.h
@@ -54,6 +54,7 @@
struct RtpSenderObservers {
RtcpRttStats* rtcp_rtt_stats;
RtcpIntraFrameObserver* intra_frame_callback;
+ RtcpLossNotificationObserver* rtcp_loss_notification_observer;
RtcpStatisticsCallback* rtcp_stats;
StreamDataCountersCallback* rtp_stats;
BitrateStatisticsObserver* bitrate_observer;
diff --git a/call/rtp_video_sender.cc b/call/rtp_video_sender.cc
index 98cdd9a..94a8fad 100644
--- a/call/rtp_video_sender.cc
+++ b/call/rtp_video_sender.cc
@@ -63,6 +63,7 @@
int rtcp_report_interval_ms,
Transport* send_transport,
RtcpIntraFrameObserver* intra_frame_callback,
+ RtcpLossNotificationObserver* rtcp_loss_notification_observer,
RtcpBandwidthObserver* bandwidth_callback,
RtpTransportControllerSendInterface* transport,
RtcpRttStats* rtt_stats,
@@ -84,6 +85,8 @@
configuration.receiver_only = false;
configuration.outgoing_transport = send_transport;
configuration.intra_frame_callback = intra_frame_callback;
+ configuration.rtcp_loss_notification_observer =
+ rtcp_loss_notification_observer;
configuration.bandwidth_callback = bandwidth_callback;
configuration.transport_feedback_callback =
transport->transport_feedback_observer();
@@ -228,24 +231,26 @@
flexfec_sender_(
MaybeCreateFlexfecSender(clock, rtp_config, suspended_ssrcs_)),
fec_controller_(std::move(fec_controller)),
- rtp_streams_(CreateRtpStreamSenders(clock,
- rtp_config,
- rtcp_report_interval_ms,
- send_transport,
- observers.intra_frame_callback,
- transport->GetBandwidthObserver(),
- transport,
- observers.rtcp_rtt_stats,
- flexfec_sender_.get(),
- observers.bitrate_observer,
- observers.rtcp_type_observer,
- observers.send_delay_observer,
- observers.send_packet_observer,
- event_log,
- retransmission_limiter,
- this,
- frame_encryptor,
- crypto_options)),
+ rtp_streams_(
+ CreateRtpStreamSenders(clock,
+ rtp_config,
+ rtcp_report_interval_ms,
+ send_transport,
+ observers.intra_frame_callback,
+ observers.rtcp_loss_notification_observer,
+ transport->GetBandwidthObserver(),
+ transport,
+ observers.rtcp_rtt_stats,
+ flexfec_sender_.get(),
+ observers.bitrate_observer,
+ observers.rtcp_type_observer,
+ observers.send_delay_observer,
+ observers.send_packet_observer,
+ event_log,
+ retransmission_limiter,
+ this,
+ frame_encryptor,
+ crypto_options)),
rtp_config_(rtp_config),
transport_(transport),
transport_overhead_bytes_per_packet_(0),
diff --git a/modules/rtp_rtcp/include/rtp_rtcp.h b/modules/rtp_rtcp/include/rtp_rtcp.h
index 9ae6ddb..1c589f4 100644
--- a/modules/rtp_rtcp/include/rtp_rtcp.h
+++ b/modules/rtp_rtcp/include/rtp_rtcp.h
@@ -64,9 +64,12 @@
// out on the network.
Transport* outgoing_transport = nullptr;
- // Called when the receiver request a intra frame.
+ // Called when the receiver requests an intra frame.
RtcpIntraFrameObserver* intra_frame_callback = nullptr;
+ // Called when the receiver sends a loss notification.
+ RtcpLossNotificationObserver* rtcp_loss_notification_observer = nullptr;
+
// Called when we receive a changed estimate from the receiver of out
// stream.
RtcpBandwidthObserver* bandwidth_callback = nullptr;
diff --git a/modules/rtp_rtcp/include/rtp_rtcp_defines.h b/modules/rtp_rtcp/include/rtp_rtcp_defines.h
index cbeb77f..41ab1cf 100644
--- a/modules/rtp_rtcp/include/rtp_rtcp_defines.h
+++ b/modules/rtp_rtcp/include/rtp_rtcp_defines.h
@@ -186,6 +186,18 @@
virtual void OnReceivedIntraFrameRequest(uint32_t ssrc) = 0;
};
+// Observer for incoming LossNotification RTCP messages.
+// See the documentation of LossNotification for details.
+class RtcpLossNotificationObserver {
+ public:
+ virtual ~RtcpLossNotificationObserver() = default;
+
+ virtual void OnReceivedLossNotification(uint32_t ssrc,
+ uint16_t seq_num_of_last_decodable,
+ uint16_t seq_num_of_last_received,
+ bool decodability_flag) = 0;
+};
+
class RtcpBandwidthObserver {
public:
// REMB or TMMBR
diff --git a/modules/rtp_rtcp/source/rtcp_receiver.cc b/modules/rtp_rtcp/source/rtcp_receiver.cc
index e3b1d13..0c1c326 100644
--- a/modules/rtp_rtcp/source/rtcp_receiver.cc
+++ b/modules/rtp_rtcp/source/rtcp_receiver.cc
@@ -131,6 +131,7 @@
RtcpPacketTypeCounterObserver* packet_type_counter_observer,
RtcpBandwidthObserver* rtcp_bandwidth_observer,
RtcpIntraFrameObserver* rtcp_intra_frame_observer,
+ RtcpLossNotificationObserver* rtcp_loss_notification_observer,
TransportFeedbackObserver* transport_feedback_observer,
VideoBitrateAllocationObserver* bitrate_allocation_observer,
int report_interval_ms,
@@ -140,6 +141,7 @@
rtp_rtcp_(owner),
rtcp_bandwidth_observer_(rtcp_bandwidth_observer),
rtcp_intra_frame_observer_(rtcp_intra_frame_observer),
+ rtcp_loss_notification_observer_(rtcp_loss_notification_observer),
transport_feedback_observer_(transport_feedback_observer),
bitrate_allocation_observer_(bitrate_allocation_observer),
report_interval_ms_(report_interval_ms),
@@ -1019,6 +1021,18 @@
rtcp_intra_frame_observer_->OnReceivedIntraFrameRequest(local_ssrc);
}
}
+ if (rtcp_loss_notification_observer_ &&
+ (packet_information.packet_type_flags & kRtcpLossNotification)) {
+ rtcp::LossNotification* loss_notification =
+ packet_information.loss_notification.get();
+ RTC_DCHECK(loss_notification);
+ if (loss_notification->media_ssrc() == local_ssrc) {
+ rtcp_loss_notification_observer_->OnReceivedLossNotification(
+ loss_notification->media_ssrc(), loss_notification->last_decoded(),
+ loss_notification->last_received(),
+ loss_notification->decodability_flag());
+ }
+ }
if (rtcp_bandwidth_observer_) {
RTC_DCHECK(!receiver_only_);
if (packet_information.packet_type_flags & kRtcpRemb) {
@@ -1028,16 +1042,6 @@
rtcp_bandwidth_observer_->OnReceivedEstimatedBitrate(
packet_information.receiver_estimated_max_bitrate_bps);
}
- if (packet_information.packet_type_flags & kRtcpLossNotification) {
- rtcp::LossNotification* loss_notification =
- packet_information.loss_notification.get();
- RTC_DCHECK(loss_notification);
- RTC_LOG(LS_VERBOSE) << "Incoming Loss Notification: ("
- << loss_notification->last_decoded() << ", "
- << loss_notification->last_received() << ", "
- << loss_notification->decodability_flag() << ").";
- // TODO(eladalon): Notify observer.
- }
if ((packet_information.packet_type_flags & kRtcpSr) ||
(packet_information.packet_type_flags & kRtcpRr)) {
int64_t now_ms = clock_->TimeInMilliseconds();
diff --git a/modules/rtp_rtcp/source/rtcp_receiver.h b/modules/rtp_rtcp/source/rtcp_receiver.h
index fe6ec4c..afc3f96 100644
--- a/modules/rtp_rtcp/source/rtcp_receiver.h
+++ b/modules/rtp_rtcp/source/rtcp_receiver.h
@@ -55,6 +55,7 @@
RtcpPacketTypeCounterObserver* packet_type_counter_observer,
RtcpBandwidthObserver* rtcp_bandwidth_observer,
RtcpIntraFrameObserver* rtcp_intra_frame_observer,
+ RtcpLossNotificationObserver* rtcp_loss_notification_observer,
TransportFeedbackObserver* transport_feedback_observer,
VideoBitrateAllocationObserver* bitrate_allocation_observer,
int report_interval_ms,
@@ -215,6 +216,7 @@
rtc::CriticalSection feedbacks_lock_;
RtcpBandwidthObserver* const rtcp_bandwidth_observer_;
RtcpIntraFrameObserver* const rtcp_intra_frame_observer_;
+ RtcpLossNotificationObserver* const rtcp_loss_notification_observer_;
TransportFeedbackObserver* const transport_feedback_observer_;
VideoBitrateAllocationObserver* const bitrate_allocation_observer_;
const int report_interval_ms_;
diff --git a/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc b/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
index 10351da..e1483a4 100644
--- a/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
+++ b/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
@@ -66,6 +66,16 @@
MOCK_METHOD1(OnReceivedIntraFrameRequest, void(uint32_t));
};
+class MockRtcpLossNotificationObserver : public RtcpLossNotificationObserver {
+ public:
+ ~MockRtcpLossNotificationObserver() override = default;
+ MOCK_METHOD4(OnReceivedLossNotification,
+ void(uint32_t ssrc,
+ uint16_t seq_num_of_last_decodable,
+ uint16_t seq_num_of_last_received,
+ bool decodability_flag));
+};
+
class MockRtcpCallbackImpl : public RtcpStatisticsCallback {
public:
MOCK_METHOD2(StatisticsUpdated, void(const RtcpStatistics&, uint32_t));
@@ -119,6 +129,7 @@
&packet_type_counter_observer_,
&bandwidth_observer_,
&intra_frame_observer_,
+ &rtcp_loss_notification_observer_,
&transport_feedback_observer_,
&bitrate_allocation_observer_,
kRtcpIntervalMs,
@@ -145,6 +156,7 @@
NiceMock<MockRtcpPacketTypeCounterObserver> packet_type_counter_observer_;
StrictMock<MockRtcpBandwidthObserver> bandwidth_observer_;
StrictMock<MockRtcpIntraFrameObserver> intra_frame_observer_;
+ StrictMock<MockRtcpLossNotificationObserver> rtcp_loss_notification_observer_;
StrictMock<MockTransportFeedbackObserver> transport_feedback_observer_;
StrictMock<MockVideoBitrateAllocationObserver> bitrate_allocation_observer_;
StrictMock<MockModuleRtpRtcp> rtp_rtcp_impl_;
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
index 9a0fc7c..f716718 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
@@ -74,6 +74,7 @@
configuration.rtcp_packet_type_counter_observer,
configuration.bandwidth_callback,
configuration.intra_frame_callback,
+ configuration.rtcp_loss_notification_observer,
configuration.transport_feedback_callback,
configuration.bitrate_allocation_observer,
configuration.rtcp_report_interval_ms > 0
diff --git a/test/fuzzers/rtcp_receiver_fuzzer.cc b/test/fuzzers/rtcp_receiver_fuzzer.cc
index f729e55..f686121 100644
--- a/test/fuzzers/rtcp_receiver_fuzzer.cc
+++ b/test/fuzzers/rtcp_receiver_fuzzer.cc
@@ -40,7 +40,7 @@
SimulatedClock clock(1234);
RTCPReceiver receiver(&clock, false, nullptr, nullptr, nullptr, nullptr,
- nullptr, kRtcpIntervalMs, &rtp_rtcp_module);
+ nullptr, nullptr, kRtcpIntervalMs, &rtp_rtcp_module);
receiver.IncomingPacket(data, size);
}
diff --git a/video/encoder_rtcp_feedback.cc b/video/encoder_rtcp_feedback.cc
index 2c54701..5a0920f 100644
--- a/video/encoder_rtcp_feedback.cc
+++ b/video/encoder_rtcp_feedback.cc
@@ -68,4 +68,12 @@
video_stream_encoder_->SendKeyFrame();
}
+void EncoderRtcpFeedback::OnReceivedLossNotification(
+ uint32_t ssrc,
+ uint16_t seq_num_of_last_decodable,
+ uint16_t seq_num_of_last_received,
+ bool decodability_flag) {
+ // TODO(eladalon): Handle.
+}
+
} // namespace webrtc
diff --git a/video/encoder_rtcp_feedback.h b/video/encoder_rtcp_feedback.h
index 1a58a67..4fa2335 100644
--- a/video/encoder_rtcp_feedback.h
+++ b/video/encoder_rtcp_feedback.h
@@ -27,16 +27,25 @@
// TODO(bugs.webrtc.org/9719): Should be eliminated when RtpMediaTransport is
// implemented.
class EncoderRtcpFeedback : public RtcpIntraFrameObserver,
+ public RtcpLossNotificationObserver,
public MediaTransportKeyFrameRequestCallback {
public:
EncoderRtcpFeedback(Clock* clock,
const std::vector<uint32_t>& ssrcs,
VideoStreamEncoderInterface* encoder);
+ ~EncoderRtcpFeedback() override = default;
+
void OnReceivedIntraFrameRequest(uint32_t ssrc) override;
// Implements MediaTransportKeyFrameRequestCallback
void OnKeyFrameRequested(uint64_t channel_id) override;
+ // Implements RtcpLossNotificationObserver.
+ void OnReceivedLossNotification(uint32_t ssrc,
+ uint16_t seq_num_of_last_decodable,
+ uint16_t seq_num_of_last_received,
+ bool decodability_flag) override;
+
private:
bool HasSsrc(uint32_t ssrc);
diff --git a/video/video_send_stream_impl.cc b/video/video_send_stream_impl.cc
index 1acf0b3..f2a7756 100644
--- a/video/video_send_stream_impl.cc
+++ b/video/video_send_stream_impl.cc
@@ -149,6 +149,7 @@
RtpSenderObservers observers;
observers.rtcp_rtt_stats = call_stats;
observers.intra_frame_callback = encoder_feedback;
+ observers.rtcp_loss_notification_observer = encoder_feedback;
observers.rtcp_stats = stats_proxy;
observers.rtp_stats = stats_proxy;
observers.bitrate_observer = stats_proxy;