From be9d2a45499d87f3b04e644fc173b0d997a9eeea Mon Sep 17 00:00:00 2001 From: "pbos@webrtc.org" Date: Mon, 30 Jun 2014 13:19:09 +0000 Subject: [PATCH] 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 --- webrtc/test/call_test.cc | 62 +++--- webrtc/test/call_test.h | 16 +- webrtc/video/call_perf_tests.cc | 17 +- webrtc/video/end_to_end_tests.cc | 243 ++++++++++++++++-------- webrtc/video/full_stack.cc | 2 +- webrtc/video/video_send_stream.cc | 64 +++---- webrtc/video/video_send_stream.h | 1 + webrtc/video/video_send_stream_tests.cc | 152 ++------------- webrtc/video_engine/vie_channel.cc | 140 ++++++++------ webrtc/video_engine/vie_channel.h | 5 + 10 files changed, 362 insertions(+), 340 deletions(-) diff --git a/webrtc/test/call_test.cc b/webrtc/test/call_test.cc index ad2416f5e2..5d8b8e679b 100644 --- a/webrtc/test/call_test.cc +++ b/webrtc/test/call_test.cc @@ -16,7 +16,6 @@ namespace test { CallTest::CallTest() : send_stream_(NULL), - receive_stream_(NULL), fake_encoder_(Clock::GetRealTimeClock()) { } CallTest::~CallTest() { @@ -39,9 +38,9 @@ void CallTest::RunBaseTest(BaseTest* test) { if (test->ShouldCreateReceivers()) { CreateMatchingReceiveConfigs(); } - test->ModifyConfigs(&send_config_, &receive_config_, &video_streams_); + test->ModifyConfigs(&send_config_, &receive_configs_, &video_streams_); CreateStreams(); - test->OnStreamsCreated(send_stream_, receive_stream_); + test->OnStreamsCreated(send_stream_, receive_streams_); CreateFrameGeneratorCapturer(); test->OnFrameGeneratorCapturerCreated(frame_generator_capturer_.get()); @@ -56,15 +55,17 @@ void CallTest::RunBaseTest(BaseTest* test) { void CallTest::Start() { send_stream_->Start(); - if (receive_stream_ != NULL) - receive_stream_->Start(); - frame_generator_capturer_->Start(); + for (size_t i = 0; i < receive_streams_.size(); ++i) + receive_streams_[i]->Start(); + if (frame_generator_capturer_.get() != NULL) + frame_generator_capturer_->Start(); } void CallTest::Stop() { - frame_generator_capturer_->Stop(); - if (receive_stream_ != NULL) - receive_stream_->Stop(); + if (frame_generator_capturer_.get() != NULL) + frame_generator_capturer_->Stop(); + for (size_t i = 0; i < receive_streams_.size(); ++i) + receive_streams_[i]->Stop(); send_stream_->Stop(); } @@ -93,21 +94,24 @@ void CallTest::CreateSendConfig(size_t num_streams) { send_config_.rtp.ssrcs.push_back(kSendSsrcs[i]); } -// TODO(pbos): Make receive configs into a vector. void CallTest::CreateMatchingReceiveConfigs() { - assert(send_config_.rtp.ssrcs.size() == 1); - receive_config_ = receiver_call_->GetDefaultReceiveConfig(); + assert(!send_config_.rtp.ssrcs.empty()); + assert(receive_configs_.empty()); + VideoReceiveStream::Config config = receiver_call_->GetDefaultReceiveConfig(); VideoCodec codec = 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_) { ExternalVideoDecoder decoder; decoder.decoder = &fake_decoder_; 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() { @@ -121,22 +125,24 @@ void CallTest::CreateFrameGeneratorCapturer() { } void CallTest::CreateStreams() { assert(send_stream_ == NULL); - assert(receive_stream_ == NULL); + assert(receive_streams_.empty()); send_stream_ = sender_call_->CreateVideoSendStream(send_config_, video_streams_, NULL); - if (receiver_call_.get() != NULL) - receive_stream_ = receiver_call_->CreateVideoReceiveStream(receive_config_); + for (size_t i = 0; i < receive_configs_.size(); ++i) { + receive_streams_.push_back( + receiver_call_->CreateVideoReceiveStream(receive_configs_[i])); + } } void CallTest::DestroyStreams() { if (send_stream_ != NULL) sender_call_->DestroyVideoSendStream(send_stream_); - if (receive_stream_ != NULL) - receiver_call_->DestroyVideoReceiveStream(receive_stream_); 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; @@ -175,13 +181,15 @@ size_t BaseTest::GetNumStreams() const { return 1; } -void BaseTest::ModifyConfigs(VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, - std::vector* video_streams) { +void BaseTest::ModifyConfigs( + VideoSendStream::Config* send_config, + std::vector* receive_configs, + std::vector* video_streams) { } -void BaseTest::OnStreamsCreated(VideoSendStream* send_stream, - VideoReceiveStream* receive_stream) { +void BaseTest::OnStreamsCreated( + VideoSendStream* send_stream, + const std::vector& receive_streams) { } void BaseTest::OnFrameGeneratorCapturerCreated( diff --git a/webrtc/test/call_test.h b/webrtc/test/call_test.h index 94ac2fabf3..37a883d685 100644 --- a/webrtc/test/call_test.h +++ b/webrtc/test/call_test.h @@ -64,8 +64,8 @@ class CallTest : public ::testing::Test { VideoSendStream* send_stream_; scoped_ptr receiver_call_; - VideoReceiveStream::Config receive_config_; - VideoReceiveStream* receive_stream_; + std::vector receive_configs_; + std::vector receive_streams_; scoped_ptr frame_generator_capturer_; test::FakeEncoder fake_encoder_; @@ -87,11 +87,13 @@ class BaseTest : public RtpRtcpObserver { virtual Call::Config GetReceiverCallConfig(); virtual void OnCallsCreated(Call* sender_call, Call* receiver_call); - virtual void ModifyConfigs(VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, - std::vector* video_streams); - virtual void OnStreamsCreated(VideoSendStream* send_stream, - VideoReceiveStream* receive_stream); + virtual void ModifyConfigs( + VideoSendStream::Config* send_config, + std::vector* receive_configs, + std::vector* video_streams); + virtual void OnStreamsCreated( + VideoSendStream* send_stream, + const std::vector& receive_streams); virtual void OnFrameGeneratorCapturerCreated( FrameGeneratorCapturer* frame_generator_capturer); diff --git a/webrtc/video/call_perf_tests.cc b/webrtc/video/call_perf_tests.cc index b6e2b3408d..18246168bc 100644 --- a/webrtc/video/call_perf_tests.cc +++ b/webrtc/video/call_perf_tests.cc @@ -254,8 +254,8 @@ TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSync) { CreateSendConfig(1); CreateMatchingReceiveConfigs(); - receive_config_.renderer = &observer; - receive_config_.audio_channel_id = channel; + receive_configs_[0].renderer = &observer; + receive_configs_[0].audio_channel_id = channel; CreateStreams(); @@ -379,11 +379,11 @@ void CallPerfTest::TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config, virtual void ModifyConfigs( VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, + std::vector* receive_configs, std::vector* video_streams) OVERRIDE { - receive_config->renderer = this; + (*receive_configs)[0].renderer = this; // 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 { @@ -518,14 +518,15 @@ void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) { return send_transport_receiver_->DeliverPacket(packet, length); } - virtual void OnStreamsCreated(VideoSendStream* send_stream, - VideoReceiveStream* receive_stream) { + virtual void OnStreamsCreated( + VideoSendStream* send_stream, + const std::vector& receive_streams) OVERRIDE { send_stream_ = send_stream; } virtual void ModifyConfigs( VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, + std::vector* receive_configs, std::vector* video_streams) OVERRIDE { if (pad_to_min_bitrate_) { send_config->rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps; diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc index 0f6f2dced3..fa3d3cf449 100644 --- a/webrtc/video/end_to_end_tests.cc +++ b/webrtc/video/end_to_end_tests.cc @@ -49,39 +49,15 @@ class EndToEndTest : public test::CallTest { virtual ~EndToEndTest() { EXPECT_EQ(NULL, send_stream_); - EXPECT_EQ(NULL, receive_stream_); + EXPECT_TRUE(receive_streams_.empty()); } 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 ReceivesPliAndRecovers(int rtp_history_ms); void RespectsRtcpMode(newapi::RtcpMode rtcp_mode); void TestXrReceiverReferenceTimeReport(bool enable_rrtr); + void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first); }; TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) { @@ -93,8 +69,8 @@ TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) { CreateStreams(); - receive_stream_->Start(); - receive_stream_->Start(); + receive_streams_[0]->Start(); + receive_streams_[0]->Start(); DestroyStreams(); } @@ -108,8 +84,8 @@ TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) { CreateStreams(); - receive_stream_->Stop(); - receive_stream_->Stop(); + receive_streams_[0]->Stop(); + receive_streams_[0]->Stop(); DestroyStreams(); } @@ -163,11 +139,11 @@ TEST_F(EndToEndTest, RendersSingleDelayedFrame) { CreateMatchingReceiveConfigs(); TestFrameCallback pre_render_callback; - receive_config_.pre_render_callback = &pre_render_callback; - receive_config_.renderer = &renderer; + receive_configs_[0].pre_render_callback = &pre_render_callback; + receive_configs_[0].renderer = &renderer; CreateStreams(); - StartSending(); + Start(); // Create frames that are smaller than the send width/height, this is done to // check that the callbacks are done after processing video. @@ -179,7 +155,7 @@ TEST_F(EndToEndTest, RendersSingleDelayedFrame) { EXPECT_EQ(kEventSignaled, renderer.Wait()) << "Timed out while waiting for the frame to render."; - StopSending(); + Stop(); sender_transport.StopSending(); receiver_transport.StopSending(); @@ -212,10 +188,10 @@ TEST_F(EndToEndTest, TransmitsFirstFrame) { CreateSendConfig(1); CreateMatchingReceiveConfigs(); - receive_config_.renderer = &renderer; + receive_configs_[0].renderer = &renderer; CreateStreams(); - StartSending(); + Start(); scoped_ptr frame_generator(test::FrameGenerator::Create( video_streams_[0].width, video_streams_[0].height)); @@ -224,7 +200,7 @@ TEST_F(EndToEndTest, TransmitsFirstFrame) { EXPECT_EQ(kEventSignaled, renderer.Wait()) << "Timed out while waiting for the frame to render."; - StopSending(); + Stop(); sender_transport.StopSending(); receiver_transport.StopSending(); @@ -328,10 +304,10 @@ TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) { virtual void ModifyConfigs( VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, + std::vector* receive_configs, std::vector* video_streams) OVERRIDE { 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 { @@ -422,18 +398,18 @@ TEST_F(EndToEndTest, DISABLED_CanReceiveFec) { virtual void ModifyConfigs( VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, + std::vector* receive_configs, std::vector* video_streams) OVERRIDE { // TODO(pbos): Run this test with combined NACK/FEC enabled as well. // 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.fec.red_payload_type = kRedPayloadType; send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; - receive_config->rtp.fec.red_payload_type = kRedPayloadType; - receive_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; - receive_config->renderer = this; + (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType; + (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; + (*receive_configs)[0].renderer = this; } virtual void PerformTest() OVERRIDE { @@ -500,16 +476,16 @@ void EndToEndTest::DecodesRetransmittedFrame(bool retransmit_over_rtx) { virtual void ModifyConfigs( VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, + std::vector* receive_configs, std::vector* video_streams) OVERRIDE { send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs; - receive_config->pre_render_callback = this; - receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs; + (*receive_configs)[0].pre_render_callback = this; + (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs; if (retransmission_ssrc_ == kSendRtxSsrc) { send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrc); send_config->rtp.rtx.payload_type = kSendRtxPayloadType; - receive_config->rtp.rtx[kSendRtxPayloadType].ssrc = kSendRtxSsrc; - receive_config->rtp.rtx[kSendRtxPayloadType].payload_type = + (*receive_configs)[0].rtp.rtx[kSendRtxPayloadType].ssrc = kSendRtxSsrc; + (*receive_configs)[0].rtp.rtx[kSendRtxPayloadType].payload_type = kSendRtxPayloadType; } } @@ -611,11 +587,11 @@ TEST_F(EndToEndTest, UsesFrameCallbacks) { send_config_.pre_encode_callback = &pre_encode_callback; CreateMatchingReceiveConfigs(); - receive_config_.pre_render_callback = &pre_render_callback; - receive_config_.renderer = &renderer; + receive_configs_[0].pre_render_callback = &pre_render_callback; + receive_configs_[0].renderer = &renderer; CreateStreams(); - StartSending(); + Start(); // Create frames that are smaller than the send width/height, this is done to // check that the callbacks are done after processing video. @@ -630,7 +606,7 @@ TEST_F(EndToEndTest, UsesFrameCallbacks) { EXPECT_EQ(kEventSignaled, renderer.Wait()) << "Timed out while waiting for the frame to render."; - StopSending(); + Stop(); sender_transport.StopSending(); receiver_transport.StopSending(); @@ -701,11 +677,11 @@ void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) { virtual void ModifyConfigs( VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, + std::vector* receive_configs, std::vector* video_streams) OVERRIDE { send_config->rtp.nack.rtp_history_ms = rtp_history_ms_; - receive_config->rtp.nack.rtp_history_ms = rtp_history_ms_; - receive_config->renderer = this; + (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_; + (*receive_configs)[0].renderer = this; } virtual void PerformTest() OVERRIDE { @@ -773,16 +749,16 @@ TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) { CreateMatchingReceiveConfigs(); CreateStreams(); - CreateFrameGenerator(); - StartSending(); + CreateFrameGeneratorCapturer(); + Start(); - receiver_call_->DestroyVideoReceiveStream(receive_stream_); - receive_stream_ = NULL; + receiver_call_->DestroyVideoReceiveStream(receive_streams_[0]); + receive_streams_.clear(); // Wait() waits for a received packet. EXPECT_EQ(kEventSignaled, input_observer.Wait()); - StopSending(); + Stop(); DestroyStreams(); @@ -848,11 +824,11 @@ void EndToEndTest::RespectsRtcpMode(newapi::RtcpMode rtcp_mode) { virtual void ModifyConfigs( VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, + std::vector* receive_configs, std::vector* video_streams) OVERRIDE { send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs; - receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs; - receive_config->rtp.rtcp_mode = rtcp_mode_; + (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs; + (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_; } virtual void PerformTest() OVERRIDE { @@ -1040,10 +1016,10 @@ TEST_F(EndToEndTest, ObserversEncodedFrames) { CreateSendConfig(1); CreateMatchingReceiveConfigs(); 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(); - StartSending(); + Start(); scoped_ptr frame_generator(test::FrameGenerator::Create( video_streams_[0].width, video_streams_[0].height)); @@ -1057,7 +1033,7 @@ TEST_F(EndToEndTest, ObserversEncodedFrames) { post_encode_observer.ExpectEqualFrames(pre_decode_observer); - StopSending(); + Stop(); sender_transport.StopSending(); receiver_transport.StopSending(); @@ -1170,10 +1146,11 @@ void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) { virtual void ModifyConfigs( VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, + std::vector* receive_configs, std::vector* video_streams) OVERRIDE { - receive_config->rtp.rtcp_mode = newapi::kRtcpReducedSize; - receive_config->rtp.rtcp_xr.receiver_reference_time_report = enable_rrtr_; + (*receive_configs)[0].rtp.rtcp_mode = newapi::kRtcpReducedSize; + (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = + enable_rrtr_; } virtual void PerformTest() OVERRIDE { @@ -1191,6 +1168,104 @@ void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) { 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(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* receive_configs, + std::vector* 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& 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 valid_ssrcs_; + std::map 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 all_streams_; + } test(kSendSsrcs, num_ssrcs, send_single_ssrc_first); + + RunBaseTest(&test); +} + TEST_F(EndToEndTest, GetStats) { class StatsObserver : public test::EndToEndTest, public I420FrameCallback { public: @@ -1332,12 +1407,12 @@ TEST_F(EndToEndTest, GetStats) { virtual void ModifyConfigs( VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, + std::vector* receive_configs, std::vector* video_streams) OVERRIDE { send_config->pre_encode_callback = this; // Used to inject delay. 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& ssrcs = send_config->rtp.ssrcs; for (size_t i = 0; i < ssrcs.size(); ++i) expected_send_ssrcs_.insert(ssrcs[i]); @@ -1345,10 +1420,11 @@ TEST_F(EndToEndTest, GetStats) { expected_cname_ = send_config->rtp.c_name; } - virtual void OnStreamsCreated(VideoSendStream* send_stream, - VideoReceiveStream* receive_stream) OVERRIDE { + virtual void OnStreamsCreated( + VideoSendStream* send_stream, + const std::vector& receive_streams) OVERRIDE { send_stream_ = send_stream; - receive_stream_ = receive_stream; + receive_stream_ = receive_streams[0]; } virtual void PerformTest() OVERRIDE { @@ -1427,9 +1503,10 @@ TEST_F(EndToEndTest, TestReceivedRtpPacketStats) { sent_rtp_(0) {} private: - virtual void OnStreamsCreated(VideoSendStream* send_stream, - VideoReceiveStream* receive_stream) OVERRIDE { - receive_stream_ = receive_stream; + virtual void OnStreamsCreated( + VideoSendStream* send_stream, + const std::vector& receive_streams) OVERRIDE { + receive_stream_ = receive_streams[0]; } virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { @@ -1456,4 +1533,14 @@ TEST_F(EndToEndTest, TestReceivedRtpPacketStats) { 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 diff --git a/webrtc/video/full_stack.cc b/webrtc/video/full_stack.cc index 1c03042db6..e2a8e86351 100644 --- a/webrtc/video/full_stack.cc +++ b/webrtc/video/full_stack.cc @@ -396,7 +396,7 @@ void FullStackTest::TestWithoutPacketLoss(const FullStackTestParams& params) { stream->max_framerate = params.clip.fps; CreateMatchingReceiveConfigs(); - receive_config_.renderer = &analyzer; + receive_configs_[0].renderer = &analyzer; CreateStreams(); analyzer.input_ = send_stream_->Input(); diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc index f9bbd57237..4d32ab4010 100644 --- a/webrtc/video/video_send_stream.cc +++ b/webrtc/video/video_send_stream.cc @@ -173,6 +173,8 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport, rtp_rtcp_->SetNACKStatus(channel_, config_.rtp.nack.rtp_history_ms > 0); } + ConfigureSsrcs(); + char rtcp_cname[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); @@ -373,38 +375,7 @@ bool VideoSendStream::ReconfigureVideoEncoder( assert(streams[0].max_framerate > 0); video_codec.maxFramerate = streams[0].max_framerate; - if (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(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(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; + return codec_->SetSendCodec(channel_, video_codec) == 0; } bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { @@ -427,5 +398,34 @@ std::string VideoSendStream::GetCName() { 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(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(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 webrtc diff --git a/webrtc/video/video_send_stream.h b/webrtc/video/video_send_stream.h index ed77665c1a..df65b74efc 100644 --- a/webrtc/video/video_send_stream.h +++ b/webrtc/video/video_send_stream.h @@ -71,6 +71,7 @@ class VideoSendStream : public webrtc::VideoSendStream, virtual std::string GetCName() OVERRIDE; private: + void ConfigureSsrcs(); TransportAdapter transport_adapter_; EncodedFrameCallbackAdapter encoded_frame_proxy_; const VideoSendStream::Config config_; diff --git a/webrtc/video/video_send_stream_tests.cc b/webrtc/video/video_send_stream_tests.cc index 2d9bf5b5f9..b1197ef64e 100644 --- a/webrtc/video/video_send_stream_tests.cc +++ b/webrtc/video/video_send_stream_tests.cc @@ -60,113 +60,8 @@ class VideoSendStreamTest : public test::CallTest { void TestNackRetransmission(uint32_t retransmit_ssrc, uint8_t retransmit_payload_type); 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(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* 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 valid_ssrcs_; - std::map 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 all_streams_; - } test(kSendSsrcs, num_ssrcs, send_single_ssrc_first); - - RunBaseTest(&test); -} - TEST_F(VideoSendStreamTest, CanStartStartedStream) { test::NullTransport transport; Call::Config call_config(&transport); @@ -191,16 +86,6 @@ TEST_F(VideoSendStreamTest, CanStopStoppedStream) { 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) { static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo="; class CNameObserver : public test::SendTest { @@ -227,7 +112,7 @@ TEST_F(VideoSendStreamTest, SupportsCName) { virtual void ModifyConfigs( VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, + std::vector* receive_configs, std::vector* video_streams) OVERRIDE { send_config->rtp.c_name = kCName; } @@ -265,7 +150,7 @@ TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) { virtual void ModifyConfigs( VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, + std::vector* receive_configs, std::vector* video_streams) OVERRIDE { send_config->rtp.extensions.push_back( RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId)); @@ -306,7 +191,7 @@ TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) { virtual void ModifyConfigs( VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, + std::vector* receive_configs, std::vector* video_streams) OVERRIDE { send_config->encoder_settings.encoder = &encoder_; send_config->rtp.extensions.push_back( @@ -475,7 +360,7 @@ TEST_F(VideoSendStreamTest, SupportsFec) { virtual void ModifyConfigs( VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, + std::vector* receive_configs, std::vector* video_streams) OVERRIDE { send_config->rtp.fec.red_payload_type = kRedPayloadType; send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; @@ -555,9 +440,9 @@ void VideoSendStreamTest::TestNackRetransmission( virtual void ModifyConfigs( VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, + std::vector* receive_configs, std::vector* 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_; if (retransmit_ssrc_ != kSendSsrcs[0]) send_config->rtp.rtx.ssrcs.push_back(retransmit_ssrc_); @@ -730,7 +615,7 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format, virtual void ModifyConfigs( VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, + std::vector* receive_configs, std::vector* video_streams) OVERRIDE { if (use_fec_) { send_config->rtp.fec.red_payload_type = kRedPayloadType; @@ -897,16 +782,17 @@ TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) { transport_.SetReceiver(send_transport_receiver); } - virtual void OnStreamsCreated(VideoSendStream* send_stream, - VideoReceiveStream* receive_stream) OVERRIDE { + virtual void OnStreamsCreated( + VideoSendStream* send_stream, + const std::vector& receive_streams) OVERRIDE { stream_ = send_stream; } virtual void ModifyConfigs( VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, + std::vector* receive_configs, std::vector* 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->suspend_below_min_bitrate = true; int min_bitrate_bps = (*video_streams)[0].min_bitrate_bps; @@ -1095,14 +981,15 @@ TEST_F(VideoSendStreamTest, ProducesStats) { virtual void ModifyConfigs( VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, + std::vector* receive_configs, std::vector* video_streams) OVERRIDE { send_config->rtp.c_name = kCName; SetConfig(*send_config); } - virtual void OnStreamsCreated(VideoSendStream* send_stream, - VideoReceiveStream* receive_stream) OVERRIDE { + virtual void OnStreamsCreated( + VideoSendStream* send_stream, + const std::vector& receive_streams) OVERRIDE { stream_ = send_stream; } @@ -1145,8 +1032,9 @@ TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) { rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound); } - virtual void OnStreamsCreated(VideoSendStream* send_stream, - VideoReceiveStream* receive_stream) OVERRIDE { + virtual void OnStreamsCreated( + VideoSendStream* send_stream, + const std::vector& receive_streams) OVERRIDE { stream_ = send_stream; } @@ -1191,7 +1079,7 @@ TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) { virtual void ModifyConfigs( VideoSendStream::Config* send_config, - VideoReceiveStream::Config* receive_config, + std::vector* receive_configs, std::vector* video_streams) OVERRIDE { send_config->rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps; } diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc index 62bb095996..80d3065b85 100644 --- a/webrtc/video_engine/vie_channel.cc +++ b/webrtc/video_engine/vie_channel.cc @@ -244,31 +244,25 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec, num_modules_to_add = 0; } - while (removed_rtp_rtcp_.size() > 0 && num_modules_to_add > 0) { - RtpRtcp* rtp_rtcp = removed_rtp_rtcp_.front(); + // Add back removed rtp modules. Order is important (allocate from front of + // removed modules) to preserve RTP settings such as SSRCs for simulcast + // streams. + std::list 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(); - 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) { - 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_; + for (int i = 0; i < num_modules_to_add; ++i) + new_rtp_modules.push_back(CreateRtpRtcpModule()); - RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration); + // Initialize newly added modules. + for (std::list::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()); if (rtp_rtcp_->StorePackets()) { @@ -278,13 +272,18 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec, } if (fec_enabled) { - rtp_rtcp->SetGenericFECStatus(fec_enabled, payload_type_red, - payload_type_fec); + rtp_rtcp->SetGenericFECStatus( + fec_enabled, payload_type_red, payload_type_fec); } rtp_rtcp->SetSendingStatus(rtp_rtcp_->Sending()); rtp_rtcp->SetSendingMediaStatus(rtp_rtcp_->SendingMedia()); + 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. for (int j = simulcast_rtp_rtcp_.size(); j > (video_codec.numberOfSimulcastStreams - 1); @@ -792,29 +791,15 @@ int32_t ViEChannel::EnableKeyFrameRequestCallback(const bool enable) { int32_t ViEChannel::SetSSRC(const uint32_t SSRC, const StreamType usage, 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()); - if (simulcast_idx > simulcast_rtp_rtcp_.size()) { - return -1; - } - std::list::const_iterator it = simulcast_rtp_rtcp_.begin(); - for (int i = 1; i < simulcast_idx; ++i, ++it) { - if (it == simulcast_rtp_rtcp_.end()) { - return -1; - } - } - RtpRtcp* rtp_rtcp_module = *it; + ReserveRtpRtcpModules(simulcast_idx + 1); + RtpRtcp* rtp_rtcp = GetRtpRtcpModule(simulcast_idx); + if (rtp_rtcp == NULL) + return -1; if (usage == kViEStreamTypeRtx) { - rtp_rtcp_module->SetRtxSsrc(SSRC); + rtp_rtcp->SetRtxSsrc(SSRC); } else { - rtp_rtcp_module->SetSSRC(SSRC); + rtp_rtcp->SetSSRC(SSRC); } return 0; } @@ -826,21 +811,11 @@ int32_t ViEChannel::SetRemoteSSRCType(const StreamType usage, } 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()); - if (idx > simulcast_rtp_rtcp_.size()) { + RtpRtcp* rtp_rtcp = GetRtpRtcpModule(idx); + if (rtp_rtcp == NULL) return -1; - } - std::list::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(); + *ssrc = rtp_rtcp->SSRC(); return 0; } @@ -1530,6 +1505,61 @@ void ViEChannel::OnRttUpdate(uint32_t 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::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::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() { // Start the decode thread if (decode_thread_) { diff --git a/webrtc/video_engine/vie_channel.h b/webrtc/video_engine/vie_channel.h index 23b7e5e592..c76d1298e3 100644 --- a/webrtc/video_engine/vie_channel.h +++ b/webrtc/video_engine/vie_channel.h @@ -362,6 +362,11 @@ class ViEChannel void OnRttUpdate(uint32_t rtt); 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. int32_t StartDecodeThread(); int32_t StopDecodeThread();