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@4987 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
603ed98bca
commit
c11148b352
@ -42,6 +42,14 @@ VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine,
|
||||
// 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);
|
||||
|
||||
|
@ -29,15 +29,6 @@ struct RtpStatistics {
|
||||
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) {}
|
||||
|
@ -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 @@ class VideoReceiveStream {
|
||||
|
||||
// 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;
|
||||
|
||||
|
@ -86,9 +86,7 @@ class VideoSendStream {
|
||||
|
||||
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;
|
||||
|
||||
|
@ -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 @@ class CallTest : public ::testing::Test {
|
||||
}
|
||||
|
||||
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 @@ class NackObserver : public test::RtpRtcpObserver {
|
||||
|
||||
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 @@ TEST_F(CallTest, UsesTraceCallback) {
|
||||
done_->Set();
|
||||
}
|
||||
|
||||
EventTypeWrapper Wait() { return done_->Wait(30 * 1000); }
|
||||
EventTypeWrapper Wait() { return done_->Wait(kDefaultTimeoutMs); }
|
||||
|
||||
private:
|
||||
unsigned int filter_;
|
||||
@ -315,7 +319,7 @@ class PliObserver : public test::RtpRtcpObserver, public VideoRenderer {
|
||||
|
||||
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 @@ TEST_F(CallTest, SurvivesIncomingRtpPacketsToDestroyedReceiveStream) {
|
||||
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 @@ TEST_F(CallTest, SurvivesIncomingRtpPacketsToDestroyedReceiveStream) {
|
||||
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 @@ TEST_F(CallTest, SendsAndReceivesMultipleStreams) {
|
||||
done_->Set();
|
||||
}
|
||||
|
||||
void Wait() { done_->Wait(30 * 1000); }
|
||||
void Wait() { done_->Wait(kDefaultTimeoutMs); }
|
||||
|
||||
private:
|
||||
int width_;
|
||||
|
Loading…
x
Reference in New Issue
Block a user