Reserve RTP/RTCP modules in SetSSRC.

Allows setting SSRCs for future simulcast layers even though no set send
codec uses them.

Also re-enabling CanSwitchToUseAllSsrcs as an end-to-end test, required
for bitrate ramp-up, instead of send-side only (resolving issue 3078).
This test was used to verify reserved modules' SSRCs are preserved
correctly.

To enable a multiple-stream end-to-end test test::CallTest was modified
to work on a vector of receive streams instead of just one.

BUG=3078
R=kjellander@webrtc.org, stefan@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/15859005

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6565 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
pbos@webrtc.org 2014-06-30 13:19:09 +00:00
parent cd9b90ab53
commit be9d2a4549
10 changed files with 362 additions and 340 deletions

View File

@ -16,7 +16,6 @@ namespace test {
CallTest::CallTest() CallTest::CallTest()
: send_stream_(NULL), : send_stream_(NULL),
receive_stream_(NULL),
fake_encoder_(Clock::GetRealTimeClock()) { fake_encoder_(Clock::GetRealTimeClock()) {
} }
CallTest::~CallTest() { CallTest::~CallTest() {
@ -39,9 +38,9 @@ void CallTest::RunBaseTest(BaseTest* test) {
if (test->ShouldCreateReceivers()) { if (test->ShouldCreateReceivers()) {
CreateMatchingReceiveConfigs(); CreateMatchingReceiveConfigs();
} }
test->ModifyConfigs(&send_config_, &receive_config_, &video_streams_); test->ModifyConfigs(&send_config_, &receive_configs_, &video_streams_);
CreateStreams(); CreateStreams();
test->OnStreamsCreated(send_stream_, receive_stream_); test->OnStreamsCreated(send_stream_, receive_streams_);
CreateFrameGeneratorCapturer(); CreateFrameGeneratorCapturer();
test->OnFrameGeneratorCapturerCreated(frame_generator_capturer_.get()); test->OnFrameGeneratorCapturerCreated(frame_generator_capturer_.get());
@ -56,15 +55,17 @@ void CallTest::RunBaseTest(BaseTest* test) {
void CallTest::Start() { void CallTest::Start() {
send_stream_->Start(); send_stream_->Start();
if (receive_stream_ != NULL) for (size_t i = 0; i < receive_streams_.size(); ++i)
receive_stream_->Start(); receive_streams_[i]->Start();
frame_generator_capturer_->Start(); if (frame_generator_capturer_.get() != NULL)
frame_generator_capturer_->Start();
} }
void CallTest::Stop() { void CallTest::Stop() {
frame_generator_capturer_->Stop(); if (frame_generator_capturer_.get() != NULL)
if (receive_stream_ != NULL) frame_generator_capturer_->Stop();
receive_stream_->Stop(); for (size_t i = 0; i < receive_streams_.size(); ++i)
receive_streams_[i]->Stop();
send_stream_->Stop(); send_stream_->Stop();
} }
@ -93,21 +94,24 @@ void CallTest::CreateSendConfig(size_t num_streams) {
send_config_.rtp.ssrcs.push_back(kSendSsrcs[i]); send_config_.rtp.ssrcs.push_back(kSendSsrcs[i]);
} }
// TODO(pbos): Make receive configs into a vector.
void CallTest::CreateMatchingReceiveConfigs() { void CallTest::CreateMatchingReceiveConfigs() {
assert(send_config_.rtp.ssrcs.size() == 1); assert(!send_config_.rtp.ssrcs.empty());
receive_config_ = receiver_call_->GetDefaultReceiveConfig(); assert(receive_configs_.empty());
VideoReceiveStream::Config config = receiver_call_->GetDefaultReceiveConfig();
VideoCodec codec = VideoCodec codec =
test::CreateDecoderVideoCodec(send_config_.encoder_settings); test::CreateDecoderVideoCodec(send_config_.encoder_settings);
receive_config_.codecs.push_back(codec); config.codecs.push_back(codec);
if (send_config_.encoder_settings.encoder == &fake_encoder_) { if (send_config_.encoder_settings.encoder == &fake_encoder_) {
ExternalVideoDecoder decoder; ExternalVideoDecoder decoder;
decoder.decoder = &fake_decoder_; decoder.decoder = &fake_decoder_;
decoder.payload_type = send_config_.encoder_settings.payload_type; decoder.payload_type = send_config_.encoder_settings.payload_type;
receive_config_.external_decoders.push_back(decoder); config.external_decoders.push_back(decoder);
}
config.rtp.local_ssrc = kReceiverLocalSsrc;
for (size_t i = 0; i < send_config_.rtp.ssrcs.size(); ++i) {
config.rtp.remote_ssrc = send_config_.rtp.ssrcs[i];
receive_configs_.push_back(config);
} }
receive_config_.rtp.remote_ssrc = send_config_.rtp.ssrcs[0];
receive_config_.rtp.local_ssrc = kReceiverLocalSsrc;
} }
void CallTest::CreateFrameGeneratorCapturer() { void CallTest::CreateFrameGeneratorCapturer() {
@ -121,22 +125,24 @@ void CallTest::CreateFrameGeneratorCapturer() {
} }
void CallTest::CreateStreams() { void CallTest::CreateStreams() {
assert(send_stream_ == NULL); assert(send_stream_ == NULL);
assert(receive_stream_ == NULL); assert(receive_streams_.empty());
send_stream_ = send_stream_ =
sender_call_->CreateVideoSendStream(send_config_, video_streams_, NULL); sender_call_->CreateVideoSendStream(send_config_, video_streams_, NULL);
if (receiver_call_.get() != NULL) for (size_t i = 0; i < receive_configs_.size(); ++i) {
receive_stream_ = receiver_call_->CreateVideoReceiveStream(receive_config_); receive_streams_.push_back(
receiver_call_->CreateVideoReceiveStream(receive_configs_[i]));
}
} }
void CallTest::DestroyStreams() { void CallTest::DestroyStreams() {
if (send_stream_ != NULL) if (send_stream_ != NULL)
sender_call_->DestroyVideoSendStream(send_stream_); sender_call_->DestroyVideoSendStream(send_stream_);
if (receive_stream_ != NULL)
receiver_call_->DestroyVideoReceiveStream(receive_stream_);
send_stream_ = NULL; send_stream_ = NULL;
receive_stream_ = NULL; for (size_t i = 0; i < receive_streams_.size(); ++i)
receiver_call_->DestroyVideoReceiveStream(receive_streams_[i]);
receive_streams_.clear();
} }
const unsigned int CallTest::kDefaultTimeoutMs = 30 * 1000; const unsigned int CallTest::kDefaultTimeoutMs = 30 * 1000;
@ -175,13 +181,15 @@ size_t BaseTest::GetNumStreams() const {
return 1; return 1;
} }
void BaseTest::ModifyConfigs(VideoSendStream::Config* send_config, void BaseTest::ModifyConfigs(
VideoReceiveStream::Config* receive_config, VideoSendStream::Config* send_config,
std::vector<VideoStream>* video_streams) { std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) {
} }
void BaseTest::OnStreamsCreated(VideoSendStream* send_stream, void BaseTest::OnStreamsCreated(
VideoReceiveStream* receive_stream) { VideoSendStream* send_stream,
const std::vector<VideoReceiveStream*>& receive_streams) {
} }
void BaseTest::OnFrameGeneratorCapturerCreated( void BaseTest::OnFrameGeneratorCapturerCreated(

View File

@ -64,8 +64,8 @@ class CallTest : public ::testing::Test {
VideoSendStream* send_stream_; VideoSendStream* send_stream_;
scoped_ptr<Call> receiver_call_; scoped_ptr<Call> receiver_call_;
VideoReceiveStream::Config receive_config_; std::vector<VideoReceiveStream::Config> receive_configs_;
VideoReceiveStream* receive_stream_; std::vector<VideoReceiveStream*> receive_streams_;
scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_; scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
test::FakeEncoder fake_encoder_; test::FakeEncoder fake_encoder_;
@ -87,11 +87,13 @@ class BaseTest : public RtpRtcpObserver {
virtual Call::Config GetReceiverCallConfig(); virtual Call::Config GetReceiverCallConfig();
virtual void OnCallsCreated(Call* sender_call, Call* receiver_call); virtual void OnCallsCreated(Call* sender_call, Call* receiver_call);
virtual void ModifyConfigs(VideoSendStream::Config* send_config, virtual void ModifyConfigs(
VideoReceiveStream::Config* receive_config, VideoSendStream::Config* send_config,
std::vector<VideoStream>* video_streams); std::vector<VideoReceiveStream::Config>* receive_configs,
virtual void OnStreamsCreated(VideoSendStream* send_stream, std::vector<VideoStream>* video_streams);
VideoReceiveStream* receive_stream); virtual void OnStreamsCreated(
VideoSendStream* send_stream,
const std::vector<VideoReceiveStream*>& receive_streams);
virtual void OnFrameGeneratorCapturerCreated( virtual void OnFrameGeneratorCapturerCreated(
FrameGeneratorCapturer* frame_generator_capturer); FrameGeneratorCapturer* frame_generator_capturer);

View File

@ -254,8 +254,8 @@ TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSync) {
CreateSendConfig(1); CreateSendConfig(1);
CreateMatchingReceiveConfigs(); CreateMatchingReceiveConfigs();
receive_config_.renderer = &observer; receive_configs_[0].renderer = &observer;
receive_config_.audio_channel_id = channel; receive_configs_[0].audio_channel_id = channel;
CreateStreams(); CreateStreams();
@ -379,11 +379,11 @@ void CallPerfTest::TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config,
virtual void ModifyConfigs( virtual void ModifyConfigs(
VideoSendStream::Config* send_config, VideoSendStream::Config* send_config,
VideoReceiveStream::Config* receive_config, std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) OVERRIDE { std::vector<VideoStream>* video_streams) OVERRIDE {
receive_config->renderer = this; (*receive_configs)[0].renderer = this;
// Enable the receiver side rtt calculation. // Enable the receiver side rtt calculation.
receive_config->rtp.rtcp_xr.receiver_reference_time_report = true; (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
} }
virtual void PerformTest() OVERRIDE { virtual void PerformTest() OVERRIDE {
@ -518,14 +518,15 @@ void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) {
return send_transport_receiver_->DeliverPacket(packet, length); return send_transport_receiver_->DeliverPacket(packet, length);
} }
virtual void OnStreamsCreated(VideoSendStream* send_stream, virtual void OnStreamsCreated(
VideoReceiveStream* receive_stream) { VideoSendStream* send_stream,
const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
send_stream_ = send_stream; send_stream_ = send_stream;
} }
virtual void ModifyConfigs( virtual void ModifyConfigs(
VideoSendStream::Config* send_config, VideoSendStream::Config* send_config,
VideoReceiveStream::Config* receive_config, std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) OVERRIDE { std::vector<VideoStream>* video_streams) OVERRIDE {
if (pad_to_min_bitrate_) { if (pad_to_min_bitrate_) {
send_config->rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps; send_config->rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps;

View File

@ -49,39 +49,15 @@ class EndToEndTest : public test::CallTest {
virtual ~EndToEndTest() { virtual ~EndToEndTest() {
EXPECT_EQ(NULL, send_stream_); EXPECT_EQ(NULL, send_stream_);
EXPECT_EQ(NULL, receive_stream_); EXPECT_TRUE(receive_streams_.empty());
} }
protected: protected:
void CreateFrameGenerator() {
frame_generator_capturer_.reset(
test::FrameGeneratorCapturer::Create(send_stream_->Input(),
video_streams_[0].width,
video_streams_[0].height,
30,
Clock::GetRealTimeClock()));
}
void StartSending() {
receive_stream_->Start();
send_stream_->Start();
if (frame_generator_capturer_.get() != NULL)
frame_generator_capturer_->Start();
}
void StopSending() {
if (frame_generator_capturer_.get() != NULL)
frame_generator_capturer_->Stop();
if (send_stream_ != NULL)
send_stream_->Stop();
if (receive_stream_ != NULL)
receive_stream_->Stop();
}
void DecodesRetransmittedFrame(bool retransmit_over_rtx); void DecodesRetransmittedFrame(bool retransmit_over_rtx);
void ReceivesPliAndRecovers(int rtp_history_ms); void ReceivesPliAndRecovers(int rtp_history_ms);
void RespectsRtcpMode(newapi::RtcpMode rtcp_mode); void RespectsRtcpMode(newapi::RtcpMode rtcp_mode);
void TestXrReceiverReferenceTimeReport(bool enable_rrtr); void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
}; };
TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) { TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
@ -93,8 +69,8 @@ TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
CreateStreams(); CreateStreams();
receive_stream_->Start(); receive_streams_[0]->Start();
receive_stream_->Start(); receive_streams_[0]->Start();
DestroyStreams(); DestroyStreams();
} }
@ -108,8 +84,8 @@ TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
CreateStreams(); CreateStreams();
receive_stream_->Stop(); receive_streams_[0]->Stop();
receive_stream_->Stop(); receive_streams_[0]->Stop();
DestroyStreams(); DestroyStreams();
} }
@ -163,11 +139,11 @@ TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
CreateMatchingReceiveConfigs(); CreateMatchingReceiveConfigs();
TestFrameCallback pre_render_callback; TestFrameCallback pre_render_callback;
receive_config_.pre_render_callback = &pre_render_callback; receive_configs_[0].pre_render_callback = &pre_render_callback;
receive_config_.renderer = &renderer; receive_configs_[0].renderer = &renderer;
CreateStreams(); CreateStreams();
StartSending(); Start();
// Create frames that are smaller than the send width/height, this is done to // Create frames that are smaller than the send width/height, this is done to
// check that the callbacks are done after processing video. // check that the callbacks are done after processing video.
@ -179,7 +155,7 @@ TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
EXPECT_EQ(kEventSignaled, renderer.Wait()) EXPECT_EQ(kEventSignaled, renderer.Wait())
<< "Timed out while waiting for the frame to render."; << "Timed out while waiting for the frame to render.";
StopSending(); Stop();
sender_transport.StopSending(); sender_transport.StopSending();
receiver_transport.StopSending(); receiver_transport.StopSending();
@ -212,10 +188,10 @@ TEST_F(EndToEndTest, TransmitsFirstFrame) {
CreateSendConfig(1); CreateSendConfig(1);
CreateMatchingReceiveConfigs(); CreateMatchingReceiveConfigs();
receive_config_.renderer = &renderer; receive_configs_[0].renderer = &renderer;
CreateStreams(); CreateStreams();
StartSending(); Start();
scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create( scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
video_streams_[0].width, video_streams_[0].height)); video_streams_[0].width, video_streams_[0].height));
@ -224,7 +200,7 @@ TEST_F(EndToEndTest, TransmitsFirstFrame) {
EXPECT_EQ(kEventSignaled, renderer.Wait()) EXPECT_EQ(kEventSignaled, renderer.Wait())
<< "Timed out while waiting for the frame to render."; << "Timed out while waiting for the frame to render.";
StopSending(); Stop();
sender_transport.StopSending(); sender_transport.StopSending();
receiver_transport.StopSending(); receiver_transport.StopSending();
@ -328,10 +304,10 @@ TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
virtual void ModifyConfigs( virtual void ModifyConfigs(
VideoSendStream::Config* send_config, VideoSendStream::Config* send_config,
VideoReceiveStream::Config* receive_config, std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) OVERRIDE { std::vector<VideoStream>* video_streams) OVERRIDE {
send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs; send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs; (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
} }
virtual void PerformTest() OVERRIDE { virtual void PerformTest() OVERRIDE {
@ -422,18 +398,18 @@ TEST_F(EndToEndTest, DISABLED_CanReceiveFec) {
virtual void ModifyConfigs( virtual void ModifyConfigs(
VideoSendStream::Config* send_config, VideoSendStream::Config* send_config,
VideoReceiveStream::Config* receive_config, std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) OVERRIDE { std::vector<VideoStream>* video_streams) OVERRIDE {
// TODO(pbos): Run this test with combined NACK/FEC enabled as well. // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
// int rtp_history_ms = 1000; // int rtp_history_ms = 1000;
// receive_config->rtp.nack.rtp_history_ms = rtp_history_ms; // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
// send_config->rtp.nack.rtp_history_ms = rtp_history_ms; // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
send_config->rtp.fec.red_payload_type = kRedPayloadType; send_config->rtp.fec.red_payload_type = kRedPayloadType;
send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
receive_config->rtp.fec.red_payload_type = kRedPayloadType; (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
receive_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
receive_config->renderer = this; (*receive_configs)[0].renderer = this;
} }
virtual void PerformTest() OVERRIDE { virtual void PerformTest() OVERRIDE {
@ -500,16 +476,16 @@ void EndToEndTest::DecodesRetransmittedFrame(bool retransmit_over_rtx) {
virtual void ModifyConfigs( virtual void ModifyConfigs(
VideoSendStream::Config* send_config, VideoSendStream::Config* send_config,
VideoReceiveStream::Config* receive_config, std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) OVERRIDE { std::vector<VideoStream>* video_streams) OVERRIDE {
send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs; send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
receive_config->pre_render_callback = this; (*receive_configs)[0].pre_render_callback = this;
receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs; (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
if (retransmission_ssrc_ == kSendRtxSsrc) { if (retransmission_ssrc_ == kSendRtxSsrc) {
send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrc); send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrc);
send_config->rtp.rtx.payload_type = kSendRtxPayloadType; send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
receive_config->rtp.rtx[kSendRtxPayloadType].ssrc = kSendRtxSsrc; (*receive_configs)[0].rtp.rtx[kSendRtxPayloadType].ssrc = kSendRtxSsrc;
receive_config->rtp.rtx[kSendRtxPayloadType].payload_type = (*receive_configs)[0].rtp.rtx[kSendRtxPayloadType].payload_type =
kSendRtxPayloadType; kSendRtxPayloadType;
} }
} }
@ -611,11 +587,11 @@ TEST_F(EndToEndTest, UsesFrameCallbacks) {
send_config_.pre_encode_callback = &pre_encode_callback; send_config_.pre_encode_callback = &pre_encode_callback;
CreateMatchingReceiveConfigs(); CreateMatchingReceiveConfigs();
receive_config_.pre_render_callback = &pre_render_callback; receive_configs_[0].pre_render_callback = &pre_render_callback;
receive_config_.renderer = &renderer; receive_configs_[0].renderer = &renderer;
CreateStreams(); CreateStreams();
StartSending(); Start();
// Create frames that are smaller than the send width/height, this is done to // Create frames that are smaller than the send width/height, this is done to
// check that the callbacks are done after processing video. // check that the callbacks are done after processing video.
@ -630,7 +606,7 @@ TEST_F(EndToEndTest, UsesFrameCallbacks) {
EXPECT_EQ(kEventSignaled, renderer.Wait()) EXPECT_EQ(kEventSignaled, renderer.Wait())
<< "Timed out while waiting for the frame to render."; << "Timed out while waiting for the frame to render.";
StopSending(); Stop();
sender_transport.StopSending(); sender_transport.StopSending();
receiver_transport.StopSending(); receiver_transport.StopSending();
@ -701,11 +677,11 @@ void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
virtual void ModifyConfigs( virtual void ModifyConfigs(
VideoSendStream::Config* send_config, VideoSendStream::Config* send_config,
VideoReceiveStream::Config* receive_config, std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) OVERRIDE { std::vector<VideoStream>* video_streams) OVERRIDE {
send_config->rtp.nack.rtp_history_ms = rtp_history_ms_; send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
receive_config->rtp.nack.rtp_history_ms = rtp_history_ms_; (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
receive_config->renderer = this; (*receive_configs)[0].renderer = this;
} }
virtual void PerformTest() OVERRIDE { virtual void PerformTest() OVERRIDE {
@ -773,16 +749,16 @@ TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
CreateMatchingReceiveConfigs(); CreateMatchingReceiveConfigs();
CreateStreams(); CreateStreams();
CreateFrameGenerator(); CreateFrameGeneratorCapturer();
StartSending(); Start();
receiver_call_->DestroyVideoReceiveStream(receive_stream_); receiver_call_->DestroyVideoReceiveStream(receive_streams_[0]);
receive_stream_ = NULL; receive_streams_.clear();
// Wait() waits for a received packet. // Wait() waits for a received packet.
EXPECT_EQ(kEventSignaled, input_observer.Wait()); EXPECT_EQ(kEventSignaled, input_observer.Wait());
StopSending(); Stop();
DestroyStreams(); DestroyStreams();
@ -848,11 +824,11 @@ void EndToEndTest::RespectsRtcpMode(newapi::RtcpMode rtcp_mode) {
virtual void ModifyConfigs( virtual void ModifyConfigs(
VideoSendStream::Config* send_config, VideoSendStream::Config* send_config,
VideoReceiveStream::Config* receive_config, std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) OVERRIDE { std::vector<VideoStream>* video_streams) OVERRIDE {
send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs; send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs; (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
receive_config->rtp.rtcp_mode = rtcp_mode_; (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
} }
virtual void PerformTest() OVERRIDE { virtual void PerformTest() OVERRIDE {
@ -1040,10 +1016,10 @@ TEST_F(EndToEndTest, ObserversEncodedFrames) {
CreateSendConfig(1); CreateSendConfig(1);
CreateMatchingReceiveConfigs(); CreateMatchingReceiveConfigs();
send_config_.post_encode_callback = &post_encode_observer; send_config_.post_encode_callback = &post_encode_observer;
receive_config_.pre_decode_callback = &pre_decode_observer; receive_configs_[0].pre_decode_callback = &pre_decode_observer;
CreateStreams(); CreateStreams();
StartSending(); Start();
scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create( scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
video_streams_[0].width, video_streams_[0].height)); video_streams_[0].width, video_streams_[0].height));
@ -1057,7 +1033,7 @@ TEST_F(EndToEndTest, ObserversEncodedFrames) {
post_encode_observer.ExpectEqualFrames(pre_decode_observer); post_encode_observer.ExpectEqualFrames(pre_decode_observer);
StopSending(); Stop();
sender_transport.StopSending(); sender_transport.StopSending();
receiver_transport.StopSending(); receiver_transport.StopSending();
@ -1170,10 +1146,11 @@ void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
virtual void ModifyConfigs( virtual void ModifyConfigs(
VideoSendStream::Config* send_config, VideoSendStream::Config* send_config,
VideoReceiveStream::Config* receive_config, std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) OVERRIDE { std::vector<VideoStream>* video_streams) OVERRIDE {
receive_config->rtp.rtcp_mode = newapi::kRtcpReducedSize; (*receive_configs)[0].rtp.rtcp_mode = newapi::kRtcpReducedSize;
receive_config->rtp.rtcp_xr.receiver_reference_time_report = enable_rrtr_; (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
enable_rrtr_;
} }
virtual void PerformTest() OVERRIDE { virtual void PerformTest() OVERRIDE {
@ -1191,6 +1168,104 @@ void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
RunBaseTest(&test); RunBaseTest(&test);
} }
void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
bool send_single_ssrc_first) {
class SendsSetSsrcs : public test::EndToEndTest {
public:
SendsSetSsrcs(const uint32_t* ssrcs,
size_t num_ssrcs,
bool send_single_ssrc_first)
: EndToEndTest(kDefaultTimeoutMs),
num_ssrcs_(num_ssrcs),
send_single_ssrc_first_(send_single_ssrc_first),
ssrcs_to_observe_(num_ssrcs),
expect_single_ssrc_(send_single_ssrc_first) {
for (size_t i = 0; i < num_ssrcs; ++i)
valid_ssrcs_[ssrcs[i]] = true;
}
private:
virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
RTPHeader header;
EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
EXPECT_TRUE(valid_ssrcs_[header.ssrc])
<< "Received unknown SSRC: " << header.ssrc;
if (!valid_ssrcs_[header.ssrc])
observation_complete_->Set();
if (!is_observed_[header.ssrc]) {
is_observed_[header.ssrc] = true;
--ssrcs_to_observe_;
if (expect_single_ssrc_) {
expect_single_ssrc_ = false;
observation_complete_->Set();
}
}
if (ssrcs_to_observe_ == 0)
observation_complete_->Set();
return SEND_PACKET;
}
virtual size_t GetNumStreams() const OVERRIDE { return num_ssrcs_; }
virtual void ModifyConfigs(
VideoSendStream::Config* send_config,
std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) OVERRIDE {
if (num_ssrcs_ > 1) {
// Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
for (size_t i = 0; i < video_streams->size(); ++i) {
(*video_streams)[i].min_bitrate_bps = 10000;
(*video_streams)[i].target_bitrate_bps = 15000;
(*video_streams)[i].max_bitrate_bps = 20000;
}
}
all_streams_ = *video_streams;
if (send_single_ssrc_first_)
video_streams->resize(1);
}
virtual void OnStreamsCreated(
VideoSendStream* send_stream,
const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
send_stream_ = send_stream;
}
virtual void PerformTest() OVERRIDE {
EXPECT_EQ(kEventSignaled, Wait())
<< "Timed out while waiting for "
<< (send_single_ssrc_first_ ? "first SSRC." : "SSRCs.");
if (send_single_ssrc_first_) {
// Set full simulcast and continue with the rest of the SSRCs.
send_stream_->ReconfigureVideoEncoder(all_streams_, NULL);
EXPECT_EQ(kEventSignaled, Wait())
<< "Timed out while waiting on additional SSRCs.";
}
}
private:
std::map<uint32_t, bool> valid_ssrcs_;
std::map<uint32_t, bool> is_observed_;
const size_t num_ssrcs_;
const bool send_single_ssrc_first_;
size_t ssrcs_to_observe_;
bool expect_single_ssrc_;
VideoSendStream* send_stream_;
std::vector<VideoStream> all_streams_;
} test(kSendSsrcs, num_ssrcs, send_single_ssrc_first);
RunBaseTest(&test);
}
TEST_F(EndToEndTest, GetStats) { TEST_F(EndToEndTest, GetStats) {
class StatsObserver : public test::EndToEndTest, public I420FrameCallback { class StatsObserver : public test::EndToEndTest, public I420FrameCallback {
public: public:
@ -1332,12 +1407,12 @@ TEST_F(EndToEndTest, GetStats) {
virtual void ModifyConfigs( virtual void ModifyConfigs(
VideoSendStream::Config* send_config, VideoSendStream::Config* send_config,
VideoReceiveStream::Config* receive_config, std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) OVERRIDE { std::vector<VideoStream>* video_streams) OVERRIDE {
send_config->pre_encode_callback = this; // Used to inject delay. send_config->pre_encode_callback = this; // Used to inject delay.
send_config->rtp.c_name = "SomeCName"; send_config->rtp.c_name = "SomeCName";
expected_receive_ssrc_ = receive_config->rtp.local_ssrc; expected_receive_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs; const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
for (size_t i = 0; i < ssrcs.size(); ++i) for (size_t i = 0; i < ssrcs.size(); ++i)
expected_send_ssrcs_.insert(ssrcs[i]); expected_send_ssrcs_.insert(ssrcs[i]);
@ -1345,10 +1420,11 @@ TEST_F(EndToEndTest, GetStats) {
expected_cname_ = send_config->rtp.c_name; expected_cname_ = send_config->rtp.c_name;
} }
virtual void OnStreamsCreated(VideoSendStream* send_stream, virtual void OnStreamsCreated(
VideoReceiveStream* receive_stream) OVERRIDE { VideoSendStream* send_stream,
const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
send_stream_ = send_stream; send_stream_ = send_stream;
receive_stream_ = receive_stream; receive_stream_ = receive_streams[0];
} }
virtual void PerformTest() OVERRIDE { virtual void PerformTest() OVERRIDE {
@ -1427,9 +1503,10 @@ TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
sent_rtp_(0) {} sent_rtp_(0) {}
private: private:
virtual void OnStreamsCreated(VideoSendStream* send_stream, virtual void OnStreamsCreated(
VideoReceiveStream* receive_stream) OVERRIDE { VideoSendStream* send_stream,
receive_stream_ = receive_stream; const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
receive_stream_ = receive_streams[0];
} }
virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
@ -1456,4 +1533,14 @@ TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
RunBaseTest(&test); RunBaseTest(&test);
} }
TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
TestSendsSetSsrcs(kNumSsrcs, false);
}
TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
TestSendsSetSsrcs(kNumSsrcs, true);
}
} // namespace webrtc } // namespace webrtc

View File

@ -396,7 +396,7 @@ void FullStackTest::TestWithoutPacketLoss(const FullStackTestParams& params) {
stream->max_framerate = params.clip.fps; stream->max_framerate = params.clip.fps;
CreateMatchingReceiveConfigs(); CreateMatchingReceiveConfigs();
receive_config_.renderer = &analyzer; receive_configs_[0].renderer = &analyzer;
CreateStreams(); CreateStreams();
analyzer.input_ = send_stream_->Input(); analyzer.input_ = send_stream_->Input();

View File

@ -173,6 +173,8 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport,
rtp_rtcp_->SetNACKStatus(channel_, config_.rtp.nack.rtp_history_ms > 0); rtp_rtcp_->SetNACKStatus(channel_, config_.rtp.nack.rtp_history_ms > 0);
} }
ConfigureSsrcs();
char rtcp_cname[ViERTP_RTCP::KMaxRTCPCNameLength]; char rtcp_cname[ViERTP_RTCP::KMaxRTCPCNameLength];
assert(config_.rtp.c_name.length() < ViERTP_RTCP::KMaxRTCPCNameLength); assert(config_.rtp.c_name.length() < ViERTP_RTCP::KMaxRTCPCNameLength);
strncpy(rtcp_cname, config_.rtp.c_name.c_str(), sizeof(rtcp_cname) - 1); strncpy(rtcp_cname, config_.rtp.c_name.c_str(), sizeof(rtcp_cname) - 1);
@ -373,38 +375,7 @@ bool VideoSendStream::ReconfigureVideoEncoder(
assert(streams[0].max_framerate > 0); assert(streams[0].max_framerate > 0);
video_codec.maxFramerate = streams[0].max_framerate; video_codec.maxFramerate = streams[0].max_framerate;
if (codec_->SetSendCodec(channel_, video_codec) != 0) return codec_->SetSendCodec(channel_, video_codec) == 0;
return false;
for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
rtp_rtcp_->SetLocalSSRC(channel_,
config_.rtp.ssrcs[i],
kViEStreamTypeNormal,
static_cast<unsigned char>(i));
}
if (config_.rtp.rtx.ssrcs.empty()) {
assert(!config_.rtp.rtx.pad_with_redundant_payloads);
return true;
}
// Set up RTX.
assert(config_.rtp.rtx.ssrcs.size() == config_.rtp.ssrcs.size());
for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
rtp_rtcp_->SetLocalSSRC(channel_,
config_.rtp.rtx.ssrcs[i],
kViEStreamTypeRtx,
static_cast<unsigned char>(i));
}
if (config_.rtp.rtx.pad_with_redundant_payloads) {
rtp_rtcp_->SetPadWithRedundantPayloads(channel_, true);
}
assert(config_.rtp.rtx.payload_type >= 0);
rtp_rtcp_->SetRtxSendPayloadType(channel_, config_.rtp.rtx.payload_type);
return true;
} }
bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
@ -427,5 +398,34 @@ std::string VideoSendStream::GetCName() {
return rtcp_cname; return rtcp_cname;
} }
void VideoSendStream::ConfigureSsrcs() {
for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
uint32_t ssrc = config_.rtp.ssrcs[i];
rtp_rtcp_->SetLocalSSRC(
channel_, ssrc, kViEStreamTypeNormal, static_cast<unsigned char>(i));
}
if (config_.rtp.rtx.ssrcs.empty()) {
assert(!config_.rtp.rtx.pad_with_redundant_payloads);
return;
}
// Set up RTX.
assert(config_.rtp.rtx.ssrcs.size() == config_.rtp.ssrcs.size());
for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
rtp_rtcp_->SetLocalSSRC(channel_,
config_.rtp.rtx.ssrcs[i],
kViEStreamTypeRtx,
static_cast<unsigned char>(i));
}
if (config_.rtp.rtx.pad_with_redundant_payloads) {
rtp_rtcp_->SetPadWithRedundantPayloads(channel_, true);
}
assert(config_.rtp.rtx.payload_type >= 0);
rtp_rtcp_->SetRtxSendPayloadType(channel_, config_.rtp.rtx.payload_type);
}
} // namespace internal } // namespace internal
} // namespace webrtc } // namespace webrtc

View File

@ -71,6 +71,7 @@ class VideoSendStream : public webrtc::VideoSendStream,
virtual std::string GetCName() OVERRIDE; virtual std::string GetCName() OVERRIDE;
private: private:
void ConfigureSsrcs();
TransportAdapter transport_adapter_; TransportAdapter transport_adapter_;
EncodedFrameCallbackAdapter encoded_frame_proxy_; EncodedFrameCallbackAdapter encoded_frame_proxy_;
const VideoSendStream::Config config_; const VideoSendStream::Config config_;

View File

@ -60,113 +60,8 @@ class VideoSendStreamTest : public test::CallTest {
void TestNackRetransmission(uint32_t retransmit_ssrc, void TestNackRetransmission(uint32_t retransmit_ssrc,
uint8_t retransmit_payload_type); uint8_t retransmit_payload_type);
void TestPacketFragmentationSize(VideoFormat format, bool with_fec); void TestPacketFragmentationSize(VideoFormat format, bool with_fec);
void SendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
}; };
void VideoSendStreamTest::SendsSetSsrcs(size_t num_ssrcs,
bool send_single_ssrc_first) {
class SendsSetSsrcs : public test::SendTest {
public:
SendsSetSsrcs(const uint32_t* ssrcs,
size_t num_ssrcs,
bool send_single_ssrc_first)
: SendTest(kDefaultTimeoutMs),
num_ssrcs_(num_ssrcs),
send_single_ssrc_first_(send_single_ssrc_first),
ssrcs_to_observe_(num_ssrcs),
expect_single_ssrc_(send_single_ssrc_first) {
for (size_t i = 0; i < num_ssrcs; ++i)
valid_ssrcs_[ssrcs[i]] = true;
}
private:
virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
RTPHeader header;
EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
// TODO(pbos): Reenable this part of the test when #1695 is resolved and
// all SSRCs are allocated on startup. This test was
// observed
// to fail on TSan as the codec gets set before the SSRCs
// are
// set up and some frames are sent on a random-generated
// SSRC
// before the correct SSRC gets set.
// EXPECT_TRUE(valid_ssrcs_[header.ssrc])
// << "Received unknown SSRC: " << header.ssrc;
//
// if (!valid_ssrcs_[header.ssrc])
// observation_complete_->Set();
if (!is_observed_[header.ssrc]) {
is_observed_[header.ssrc] = true;
--ssrcs_to_observe_;
if (expect_single_ssrc_) {
expect_single_ssrc_ = false;
observation_complete_->Set();
}
}
if (ssrcs_to_observe_ == 0)
observation_complete_->Set();
return SEND_PACKET;
}
virtual void ModifyConfigs(
VideoSendStream::Config* send_config,
VideoReceiveStream::Config* receive_config,
std::vector<VideoStream>* video_streams) OVERRIDE {
if (num_ssrcs_ > 1) {
// Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
for (size_t i = 0; i < video_streams->size(); ++i) {
(*video_streams)[i].min_bitrate_bps = 10000;
(*video_streams)[i].target_bitrate_bps = 10000;
(*video_streams)[i].max_bitrate_bps = 10000;
}
}
all_streams_ = *video_streams;
if (send_single_ssrc_first_)
video_streams->resize(1);
}
virtual void OnStreamsCreated(VideoSendStream* send_stream,
VideoReceiveStream* receive_stream) OVERRIDE {
send_stream_ = send_stream;
}
virtual void PerformTest() OVERRIDE {
EXPECT_EQ(kEventSignaled, Wait())
<< "Timed out while waiting for "
<< (send_single_ssrc_first_ ? "first SSRC." : "SSRCs.");
if (send_single_ssrc_first_) {
// Set full simulcast and continue with the rest of the SSRCs.
send_stream_->ReconfigureVideoEncoder(all_streams_, NULL);
EXPECT_EQ(kEventSignaled, Wait())
<< "Timed out while waiting on additional SSRCs.";
}
}
private:
std::map<uint32_t, bool> valid_ssrcs_;
std::map<uint32_t, bool> is_observed_;
const size_t num_ssrcs_;
const bool send_single_ssrc_first_;
size_t ssrcs_to_observe_;
bool expect_single_ssrc_;
VideoSendStream* send_stream_;
std::vector<VideoStream> all_streams_;
} test(kSendSsrcs, num_ssrcs, send_single_ssrc_first);
RunBaseTest(&test);
}
TEST_F(VideoSendStreamTest, CanStartStartedStream) { TEST_F(VideoSendStreamTest, CanStartStartedStream) {
test::NullTransport transport; test::NullTransport transport;
Call::Config call_config(&transport); Call::Config call_config(&transport);
@ -191,16 +86,6 @@ TEST_F(VideoSendStreamTest, CanStopStoppedStream) {
DestroyStreams(); DestroyStreams();
} }
TEST_F(VideoSendStreamTest, SendsSetSsrc) { SendsSetSsrcs(1, false); }
TEST_F(VideoSendStreamTest, DISABLED_SendsSetSimulcastSsrcs) {
SendsSetSsrcs(kNumSsrcs, false);
}
TEST_F(VideoSendStreamTest, DISABLED_CanSwitchToUseAllSsrcs) {
SendsSetSsrcs(kNumSsrcs, true);
}
TEST_F(VideoSendStreamTest, SupportsCName) { TEST_F(VideoSendStreamTest, SupportsCName) {
static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo="; static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
class CNameObserver : public test::SendTest { class CNameObserver : public test::SendTest {
@ -227,7 +112,7 @@ TEST_F(VideoSendStreamTest, SupportsCName) {
virtual void ModifyConfigs( virtual void ModifyConfigs(
VideoSendStream::Config* send_config, VideoSendStream::Config* send_config,
VideoReceiveStream::Config* receive_config, std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) OVERRIDE { std::vector<VideoStream>* video_streams) OVERRIDE {
send_config->rtp.c_name = kCName; send_config->rtp.c_name = kCName;
} }
@ -265,7 +150,7 @@ TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
virtual void ModifyConfigs( virtual void ModifyConfigs(
VideoSendStream::Config* send_config, VideoSendStream::Config* send_config,
VideoReceiveStream::Config* receive_config, std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) OVERRIDE { std::vector<VideoStream>* video_streams) OVERRIDE {
send_config->rtp.extensions.push_back( send_config->rtp.extensions.push_back(
RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId)); RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
@ -306,7 +191,7 @@ TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
virtual void ModifyConfigs( virtual void ModifyConfigs(
VideoSendStream::Config* send_config, VideoSendStream::Config* send_config,
VideoReceiveStream::Config* receive_config, std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) OVERRIDE { std::vector<VideoStream>* video_streams) OVERRIDE {
send_config->encoder_settings.encoder = &encoder_; send_config->encoder_settings.encoder = &encoder_;
send_config->rtp.extensions.push_back( send_config->rtp.extensions.push_back(
@ -475,7 +360,7 @@ TEST_F(VideoSendStreamTest, SupportsFec) {
virtual void ModifyConfigs( virtual void ModifyConfigs(
VideoSendStream::Config* send_config, VideoSendStream::Config* send_config,
VideoReceiveStream::Config* receive_config, std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) OVERRIDE { std::vector<VideoStream>* video_streams) OVERRIDE {
send_config->rtp.fec.red_payload_type = kRedPayloadType; send_config->rtp.fec.red_payload_type = kRedPayloadType;
send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
@ -555,9 +440,9 @@ void VideoSendStreamTest::TestNackRetransmission(
virtual void ModifyConfigs( virtual void ModifyConfigs(
VideoSendStream::Config* send_config, VideoSendStream::Config* send_config,
VideoReceiveStream::Config* receive_config, std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) OVERRIDE { std::vector<VideoStream>* video_streams) OVERRIDE {
send_config->rtp.nack.rtp_history_ms = 1000; send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
send_config->rtp.rtx.payload_type = retransmit_payload_type_; send_config->rtp.rtx.payload_type = retransmit_payload_type_;
if (retransmit_ssrc_ != kSendSsrcs[0]) if (retransmit_ssrc_ != kSendSsrcs[0])
send_config->rtp.rtx.ssrcs.push_back(retransmit_ssrc_); send_config->rtp.rtx.ssrcs.push_back(retransmit_ssrc_);
@ -730,7 +615,7 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
virtual void ModifyConfigs( virtual void ModifyConfigs(
VideoSendStream::Config* send_config, VideoSendStream::Config* send_config,
VideoReceiveStream::Config* receive_config, std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) OVERRIDE { std::vector<VideoStream>* video_streams) OVERRIDE {
if (use_fec_) { if (use_fec_) {
send_config->rtp.fec.red_payload_type = kRedPayloadType; send_config->rtp.fec.red_payload_type = kRedPayloadType;
@ -897,16 +782,17 @@ TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) {
transport_.SetReceiver(send_transport_receiver); transport_.SetReceiver(send_transport_receiver);
} }
virtual void OnStreamsCreated(VideoSendStream* send_stream, virtual void OnStreamsCreated(
VideoReceiveStream* receive_stream) OVERRIDE { VideoSendStream* send_stream,
const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
stream_ = send_stream; stream_ = send_stream;
} }
virtual void ModifyConfigs( virtual void ModifyConfigs(
VideoSendStream::Config* send_config, VideoSendStream::Config* send_config,
VideoReceiveStream::Config* receive_config, std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) OVERRIDE { std::vector<VideoStream>* video_streams) OVERRIDE {
send_config->rtp.nack.rtp_history_ms = 1000; send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
send_config->pre_encode_callback = this; send_config->pre_encode_callback = this;
send_config->suspend_below_min_bitrate = true; send_config->suspend_below_min_bitrate = true;
int min_bitrate_bps = (*video_streams)[0].min_bitrate_bps; int min_bitrate_bps = (*video_streams)[0].min_bitrate_bps;
@ -1095,14 +981,15 @@ TEST_F(VideoSendStreamTest, ProducesStats) {
virtual void ModifyConfigs( virtual void ModifyConfigs(
VideoSendStream::Config* send_config, VideoSendStream::Config* send_config,
VideoReceiveStream::Config* receive_config, std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) OVERRIDE { std::vector<VideoStream>* video_streams) OVERRIDE {
send_config->rtp.c_name = kCName; send_config->rtp.c_name = kCName;
SetConfig(*send_config); SetConfig(*send_config);
} }
virtual void OnStreamsCreated(VideoSendStream* send_stream, virtual void OnStreamsCreated(
VideoReceiveStream* receive_stream) OVERRIDE { VideoSendStream* send_stream,
const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
stream_ = send_stream; stream_ = send_stream;
} }
@ -1145,8 +1032,9 @@ TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) {
rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound); rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound);
} }
virtual void OnStreamsCreated(VideoSendStream* send_stream, virtual void OnStreamsCreated(
VideoReceiveStream* receive_stream) OVERRIDE { VideoSendStream* send_stream,
const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
stream_ = send_stream; stream_ = send_stream;
} }
@ -1191,7 +1079,7 @@ TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) {
virtual void ModifyConfigs( virtual void ModifyConfigs(
VideoSendStream::Config* send_config, VideoSendStream::Config* send_config,
VideoReceiveStream::Config* receive_config, std::vector<VideoReceiveStream::Config>* receive_configs,
std::vector<VideoStream>* video_streams) OVERRIDE { std::vector<VideoStream>* video_streams) OVERRIDE {
send_config->rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps; send_config->rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
} }

View File

@ -244,31 +244,25 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec,
num_modules_to_add = 0; num_modules_to_add = 0;
} }
while (removed_rtp_rtcp_.size() > 0 && num_modules_to_add > 0) { // Add back removed rtp modules. Order is important (allocate from front of
RtpRtcp* rtp_rtcp = removed_rtp_rtcp_.front(); // removed modules) to preserve RTP settings such as SSRCs for simulcast
// streams.
std::list<RtpRtcp*> new_rtp_modules;
for (; removed_rtp_rtcp_.size() > 0 && num_modules_to_add > 0;
--num_modules_to_add) {
new_rtp_modules.push_back(removed_rtp_rtcp_.front());
removed_rtp_rtcp_.pop_front(); removed_rtp_rtcp_.pop_front();
simulcast_rtp_rtcp_.push_back(rtp_rtcp);
rtp_rtcp->SetSendingStatus(rtp_rtcp_->Sending());
rtp_rtcp->SetSendingMediaStatus(rtp_rtcp_->SendingMedia());
module_process_thread_.RegisterModule(rtp_rtcp);
--num_modules_to_add;
} }
for (int i = 0; i < num_modules_to_add; ++i) { for (int i = 0; i < num_modules_to_add; ++i)
RtpRtcp::Configuration configuration; new_rtp_modules.push_back(CreateRtpRtcpModule());
configuration.id = ViEModuleId(engine_id_, channel_id_);
configuration.audio = false; // Video.
configuration.default_module = default_rtp_rtcp_;
configuration.outgoing_transport = &vie_sender_;
configuration.intra_frame_callback = intra_frame_observer_;
configuration.bandwidth_callback = bandwidth_observer_.get();
configuration.rtt_stats = rtt_stats_;
configuration.paced_sender = paced_sender_;
RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration); // Initialize newly added modules.
for (std::list<RtpRtcp*>::iterator it = new_rtp_modules.begin();
it != new_rtp_modules.end();
++it) {
RtpRtcp* rtp_rtcp = *it;
// Silently ignore error.
module_process_thread_.RegisterModule(rtp_rtcp);
rtp_rtcp->SetRTCPStatus(rtp_rtcp_->RTCP()); rtp_rtcp->SetRTCPStatus(rtp_rtcp_->RTCP());
if (rtp_rtcp_->StorePackets()) { if (rtp_rtcp_->StorePackets()) {
@ -278,13 +272,18 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec,
} }
if (fec_enabled) { if (fec_enabled) {
rtp_rtcp->SetGenericFECStatus(fec_enabled, payload_type_red, rtp_rtcp->SetGenericFECStatus(
payload_type_fec); fec_enabled, payload_type_red, payload_type_fec);
} }
rtp_rtcp->SetSendingStatus(rtp_rtcp_->Sending()); rtp_rtcp->SetSendingStatus(rtp_rtcp_->Sending());
rtp_rtcp->SetSendingMediaStatus(rtp_rtcp_->SendingMedia()); rtp_rtcp->SetSendingMediaStatus(rtp_rtcp_->SendingMedia());
simulcast_rtp_rtcp_.push_back(rtp_rtcp); simulcast_rtp_rtcp_.push_back(rtp_rtcp);
// Silently ignore error.
module_process_thread_.RegisterModule(rtp_rtcp);
} }
// Remove last in list if we have too many. // Remove last in list if we have too many.
for (int j = simulcast_rtp_rtcp_.size(); for (int j = simulcast_rtp_rtcp_.size();
j > (video_codec.numberOfSimulcastStreams - 1); j > (video_codec.numberOfSimulcastStreams - 1);
@ -792,29 +791,15 @@ int32_t ViEChannel::EnableKeyFrameRequestCallback(const bool enable) {
int32_t ViEChannel::SetSSRC(const uint32_t SSRC, int32_t ViEChannel::SetSSRC(const uint32_t SSRC,
const StreamType usage, const StreamType usage,
const uint8_t simulcast_idx) { const uint8_t simulcast_idx) {
if (simulcast_idx == 0) {
if (usage == kViEStreamTypeRtx) {
rtp_rtcp_->SetRtxSsrc(SSRC);
} else {
rtp_rtcp_->SetSSRC(SSRC);
}
return 0;
}
CriticalSectionScoped cs(rtp_rtcp_cs_.get()); CriticalSectionScoped cs(rtp_rtcp_cs_.get());
if (simulcast_idx > simulcast_rtp_rtcp_.size()) { ReserveRtpRtcpModules(simulcast_idx + 1);
return -1; RtpRtcp* rtp_rtcp = GetRtpRtcpModule(simulcast_idx);
} if (rtp_rtcp == NULL)
std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin(); return -1;
for (int i = 1; i < simulcast_idx; ++i, ++it) {
if (it == simulcast_rtp_rtcp_.end()) {
return -1;
}
}
RtpRtcp* rtp_rtcp_module = *it;
if (usage == kViEStreamTypeRtx) { if (usage == kViEStreamTypeRtx) {
rtp_rtcp_module->SetRtxSsrc(SSRC); rtp_rtcp->SetRtxSsrc(SSRC);
} else { } else {
rtp_rtcp_module->SetSSRC(SSRC); rtp_rtcp->SetSSRC(SSRC);
} }
return 0; return 0;
} }
@ -826,21 +811,11 @@ int32_t ViEChannel::SetRemoteSSRCType(const StreamType usage,
} }
int32_t ViEChannel::GetLocalSSRC(uint8_t idx, unsigned int* ssrc) { int32_t ViEChannel::GetLocalSSRC(uint8_t idx, unsigned int* ssrc) {
if (idx == 0) {
*ssrc = rtp_rtcp_->SSRC();
return 0;
}
CriticalSectionScoped cs(rtp_rtcp_cs_.get()); CriticalSectionScoped cs(rtp_rtcp_cs_.get());
if (idx > simulcast_rtp_rtcp_.size()) { RtpRtcp* rtp_rtcp = GetRtpRtcpModule(idx);
if (rtp_rtcp == NULL)
return -1; return -1;
} *ssrc = rtp_rtcp->SSRC();
std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
for (int i = 1; i < idx; ++i, ++it) {
if (it == simulcast_rtp_rtcp_.end()) {
return -1;
}
}
*ssrc = (*it)->SSRC();
return 0; return 0;
} }
@ -1530,6 +1505,61 @@ void ViEChannel::OnRttUpdate(uint32_t rtt) {
vcm_->SetReceiveChannelParameters(rtt); vcm_->SetReceiveChannelParameters(rtt);
} }
void ViEChannel::ReserveRtpRtcpModules(size_t num_modules) {
for (size_t total_modules =
1 + simulcast_rtp_rtcp_.size() + removed_rtp_rtcp_.size();
total_modules < num_modules;
++total_modules) {
RtpRtcp* rtp_rtcp = CreateRtpRtcpModule();
rtp_rtcp->SetSendingStatus(false);
rtp_rtcp->SetSendingMediaStatus(false);
rtp_rtcp->RegisterSendFrameCountObserver(NULL);
rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(NULL);
rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(NULL);
rtp_rtcp->RegisterVideoBitrateObserver(NULL);
removed_rtp_rtcp_.push_back(rtp_rtcp);
}
}
RtpRtcp* ViEChannel::GetRtpRtcpModule(size_t index) const {
if (index == 0)
return rtp_rtcp_.get();
if (index <= simulcast_rtp_rtcp_.size()) {
std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
for (size_t i = 1; i < index; ++i) {
++it;
}
return *it;
}
// If the requested module exists it must be in the removed list. Index
// translation to this list must remove the default module as well as all
// active simulcast modules.
size_t removed_idx = index - simulcast_rtp_rtcp_.size() - 1;
if (removed_idx >= removed_rtp_rtcp_.size())
return NULL;
std::list<RtpRtcp*>::const_iterator it = removed_rtp_rtcp_.begin();
while (removed_idx-- > 0)
++it;
return *it;
}
RtpRtcp* ViEChannel::CreateRtpRtcpModule() {
RtpRtcp::Configuration configuration;
configuration.id = ViEModuleId(engine_id_, channel_id_);
configuration.audio = false; // Video.
configuration.default_module = default_rtp_rtcp_;
configuration.outgoing_transport = &vie_sender_;
configuration.intra_frame_callback = intra_frame_observer_;
configuration.bandwidth_callback = bandwidth_observer_.get();
configuration.rtt_stats = rtt_stats_;
configuration.paced_sender = paced_sender_;
return RtpRtcp::CreateRtpRtcp(configuration);
}
int32_t ViEChannel::StartDecodeThread() { int32_t ViEChannel::StartDecodeThread() {
// Start the decode thread // Start the decode thread
if (decode_thread_) { if (decode_thread_) {

View File

@ -362,6 +362,11 @@ class ViEChannel
void OnRttUpdate(uint32_t rtt); void OnRttUpdate(uint32_t rtt);
private: private:
void ReserveRtpRtcpModules(size_t total_modules)
EXCLUSIVE_LOCKS_REQUIRED(rtp_rtcp_cs_);
RtpRtcp* GetRtpRtcpModule(size_t simulcast_idx) const
EXCLUSIVE_LOCKS_REQUIRED(rtp_rtcp_cs_);
RtpRtcp* CreateRtpRtcpModule();
// Assumed to be protected. // Assumed to be protected.
int32_t StartDecodeThread(); int32_t StartDecodeThread();
int32_t StopDecodeThread(); int32_t StopDecodeThread();