Compound/reduced-size RTCP in VideoReceiveStream.
BUG=2424
R=mflodman@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/2413004
git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@4987 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/video_engine/internal/video_receive_stream.cc b/video_engine/internal/video_receive_stream.cc
index fc742c7..c92cc8d 100644
--- a/video_engine/internal/video_receive_stream.cc
+++ b/video_engine/internal/video_receive_stream.cc
@@ -42,6 +42,14 @@
// TODO(pbos): This is not fine grained enough...
rtp_rtcp_->SetNACKStatus(channel_, config_.rtp.nack.rtp_history_ms > 0);
rtp_rtcp_->SetKeyFrameRequestMethod(channel_, kViEKeyFrameRequestPliRtcp);
+ switch (config_.rtp.rtcp_mode) {
+ case newapi::kRtcpCompound:
+ rtp_rtcp_->SetRTCPStatus(channel_, kRtcpCompound_RFC4585);
+ break;
+ case newapi::kRtcpReducedSize:
+ rtp_rtcp_->SetRTCPStatus(channel_, kRtcpNonCompound_RFC5506);
+ break;
+ }
assert(config_.rtp.ssrc != 0);
diff --git a/video_engine/new_include/config.h b/video_engine/new_include/config.h
index d19c8d9..fec34ba 100644
--- a/video_engine/new_include/config.h
+++ b/video_engine/new_include/config.h
@@ -29,15 +29,6 @@
std::string c_name;
};
-namespace newapi {
-// RTCP mode to use. Compound mode is described by RFC 4585 and reduced-size
-// RTCP mode is described by RFC 5506.
-enum RtcpMode {
- kRtcpCompound,
- kRtcpReducedSize
-};
-} // namespace newapi
-
// Settings for NACK, see RFC 4585 for details.
struct NackConfig {
NackConfig() : rtp_history_ms(0) {}
diff --git a/video_engine/new_include/video_receive_stream.h b/video_engine/new_include/video_receive_stream.h
index 0235ee0..ba0f260 100644
--- a/video_engine/new_include/video_receive_stream.h
+++ b/video_engine/new_include/video_receive_stream.h
@@ -22,6 +22,15 @@
namespace webrtc {
+namespace newapi {
+// RTCP mode to use. Compound mode is described by RFC 4585 and reduced-size
+// RTCP mode is described by RFC 5506.
+enum RtcpMode {
+ kRtcpCompound,
+ kRtcpReducedSize
+};
+} // namespace newapi
+
class VideoDecoder;
// TODO(mflodman) Move all these settings to VideoDecoder and move the
@@ -96,11 +105,15 @@
// Receive-stream specific RTP settings.
struct Rtp {
- Rtp() : ssrc(0) {}
+ Rtp() : ssrc(0), rtcp_mode(newapi::kRtcpReducedSize) {}
+
// TODO(mflodman) Do we require a set ssrc? What happens if the ssrc
// changes?
uint32_t ssrc;
+ // See RtcpMode for description.
+ newapi::RtcpMode rtcp_mode;
+
// See NackConfig for description.
NackConfig nack;
diff --git a/video_engine/new_include/video_send_stream.h b/video_engine/new_include/video_send_stream.h
index 5c0ec32..c85ed78 100644
--- a/video_engine/new_include/video_send_stream.h
+++ b/video_engine/new_include/video_send_stream.h
@@ -86,9 +86,7 @@
static const size_t kDefaultMaxPacketSize = 1500 - 40; // TCP over IPv4.
struct Rtp {
- Rtp() : mode(newapi::kRtcpReducedSize),
- max_packet_size(kDefaultMaxPacketSize) {}
- newapi::RtcpMode mode;
+ Rtp() : max_packet_size(kDefaultMaxPacketSize) {}
std::vector<uint32_t> ssrcs;
diff --git a/video_engine/test/call_tests.cc b/video_engine/test/call_tests.cc
index bb10906..2fd25f3 100644
--- a/video_engine/test/call_tests.cc
+++ b/video_engine/test/call_tests.cc
@@ -28,6 +28,9 @@
namespace webrtc {
+static unsigned int kDefaultTimeoutMs = 30 * 1000;
+static unsigned int kLongTimeoutMs = 120 * 1000;
+
class CallTest : public ::testing::Test {
public:
CallTest()
@@ -106,6 +109,7 @@
}
void ReceivesPliAndRecovers(int rtp_history_ms);
+ void RespectsRtcpMode(newapi::RtcpMode rtcp_mode);
scoped_ptr<Call> sender_call_;
scoped_ptr<Call> receiver_call_;
@@ -131,7 +135,7 @@
public:
NackObserver()
- : test::RtpRtcpObserver(120 * 1000),
+ : test::RtpRtcpObserver(kLongTimeoutMs),
rtp_parser_(RtpHeaderParser::Create()),
drop_burst_count_(0),
sent_rtp_packets_(0),
@@ -242,7 +246,7 @@
done_->Set();
}
- EventTypeWrapper Wait() { return done_->Wait(30 * 1000); }
+ EventTypeWrapper Wait() { return done_->Wait(kDefaultTimeoutMs); }
private:
unsigned int filter_;
@@ -315,7 +319,7 @@
public:
explicit PliObserver(bool nack_enabled)
- : test::RtpRtcpObserver(120 * 1000),
+ : test::RtpRtcpObserver(kLongTimeoutMs),
rtp_header_parser_(RtpHeaderParser::Create()),
nack_enabled_(nack_enabled),
first_retransmitted_timestamp_(0),
@@ -428,7 +432,9 @@
explicit PacketInputObserver(PacketReceiver* receiver)
: receiver_(receiver), delivered_packet_(EventWrapper::Create()) {}
- EventTypeWrapper Wait() { return delivered_packet_->Wait(30 * 1000); }
+ EventTypeWrapper Wait() {
+ return delivered_packet_->Wait(kDefaultTimeoutMs);
+ }
private:
virtual bool DeliverPacket(const uint8_t* packet, size_t length) {
@@ -474,6 +480,100 @@
receive_transport.StopSending();
}
+void CallTest::RespectsRtcpMode(newapi::RtcpMode rtcp_mode) {
+ static const int kRtpHistoryMs = 1000;
+ static const int kNumCompoundRtcpPacketsToObserve = 10;
+ class RtcpModeObserver : public test::RtpRtcpObserver {
+ public:
+ RtcpModeObserver(newapi::RtcpMode rtcp_mode)
+ : test::RtpRtcpObserver(kDefaultTimeoutMs),
+ rtcp_mode_(rtcp_mode),
+ sent_rtp_(0),
+ sent_rtcp_(0) {}
+
+ private:
+ virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
+ if (++sent_rtp_ % 3 == 0)
+ return DROP_PACKET;
+
+ return SEND_PACKET;
+ }
+
+ virtual Action OnReceiveRtcp(const uint8_t* packet,
+ size_t length) OVERRIDE {
+ ++sent_rtcp_;
+ RTCPUtility::RTCPParserV2 parser(packet, length, true);
+ EXPECT_TRUE(parser.IsValid());
+
+ RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
+ bool has_report_block = false;
+ while (packet_type != RTCPUtility::kRtcpNotValidCode) {
+ EXPECT_NE(RTCPUtility::kRtcpSrCode, packet_type);
+ if (packet_type == RTCPUtility::kRtcpRrCode) {
+ has_report_block = true;
+ break;
+ }
+ packet_type = parser.Iterate();
+ }
+
+ switch (rtcp_mode_) {
+ case newapi::kRtcpCompound:
+ if (!has_report_block) {
+ ADD_FAILURE() << "Received RTCP packet without receiver report for "
+ "kRtcpCompound.";
+ observation_complete_->Set();
+ }
+
+ if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
+ observation_complete_->Set();
+
+ break;
+ case newapi::kRtcpReducedSize:
+ if (!has_report_block)
+ observation_complete_->Set();
+ break;
+ }
+
+ return SEND_PACKET;
+ }
+
+ newapi::RtcpMode rtcp_mode_;
+ int sent_rtp_;
+ int sent_rtcp_;
+ } observer(rtcp_mode);
+
+ CreateCalls(Call::Config(observer.SendTransport()),
+ Call::Config(observer.ReceiveTransport()));
+
+ observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
+
+ CreateTestConfigs();
+ send_config_.rtp.nack.rtp_history_ms = kRtpHistoryMs;
+ receive_config_.rtp.nack.rtp_history_ms = kRtpHistoryMs;
+ receive_config_.rtp.rtcp_mode = rtcp_mode;
+
+ CreateStreams();
+ CreateFrameGenerator();
+ StartSending();
+
+ EXPECT_EQ(kEventSignaled, observer.Wait())
+ << (rtcp_mode == newapi::kRtcpCompound
+ ? "Timed out before observing enough compound packets."
+ : "Timed out before receiving a non-compound RTCP packet.");
+
+ StopSending();
+ observer.StopSending();
+ DestroyStreams();
+}
+
+TEST_F(CallTest, UsesRtcpCompoundMode) {
+ RespectsRtcpMode(newapi::kRtcpCompound);
+}
+
+TEST_F(CallTest, UsesRtcpReducedSizeMode) {
+ RespectsRtcpMode(newapi::kRtcpReducedSize);
+}
+
// Test sets up a Call multiple senders with different resolutions and SSRCs.
// Another is set up to receive all three of these with different renderers.
// Each renderer verifies that it receives the expected resolution, and as soon
@@ -493,7 +593,7 @@
done_->Set();
}
- void Wait() { done_->Wait(30 * 1000); }
+ void Wait() { done_->Wait(kDefaultTimeoutMs); }
private:
int width_;