diff --git a/webrtc/config.h b/webrtc/config.h index 62f9fc8559..9ff8a55fa4 100644 --- a/webrtc/config.h +++ b/webrtc/config.h @@ -71,16 +71,6 @@ struct FecConfig { int red_payload_type; }; -// Settings for RTP retransmission payload format, see RFC 4588 for details. -struct RtxConfig { - RtxConfig() : rtx_payload_type(0) {} - // SSRCs to use for the RTX streams. - std::vector ssrcs; - - // Payload type to use for the RTX stream. - int rtx_payload_type; -}; - // RTP header extension to use for the video stream, see RFC 5285. struct RtpExtension { static const char* kTOffset; diff --git a/webrtc/test/rtp_rtcp_observer.h b/webrtc/test/rtp_rtcp_observer.h index 3b4ad7b145..5ed9a3f3eb 100644 --- a/webrtc/test/rtp_rtcp_observer.h +++ b/webrtc/test/rtp_rtcp_observer.h @@ -13,6 +13,8 @@ #include #include +#include "testing/gtest/include/gtest/gtest.h" + #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" #include "webrtc/typedefs.h" #include "webrtc/video_send_stream.h" @@ -123,6 +125,7 @@ class RtpRtcpObserver { private: virtual bool SendRtp(const uint8_t* packet, size_t length) OVERRIDE { + EXPECT_FALSE(RtpHeaderParser::IsRtcp(packet, static_cast(length))); Action action; { CriticalSectionScoped crit_(lock_); @@ -139,6 +142,7 @@ class RtpRtcpObserver { } virtual bool SendRtcp(const uint8_t* packet, size_t length) OVERRIDE { + EXPECT_TRUE(RtpHeaderParser::IsRtcp(packet, static_cast(length))); Action action; { CriticalSectionScoped crit_(lock_); diff --git a/webrtc/video/call.cc b/webrtc/video/call.cc index 12daa8eaae..baa2d404dc 100644 --- a/webrtc/video/call.cc +++ b/webrtc/video/call.cc @@ -170,8 +170,9 @@ void CreateTraceDispatcher() { Call* Call::Create(const Call::Config& config) { CreateTraceDispatcher(); - VideoEngine* video_engine = config.webrtc_config != NULL ? - VideoEngine::Create(*config.webrtc_config) : VideoEngine::Create(); + VideoEngine* video_engine = config.webrtc_config != NULL + ? VideoEngine::Create(*config.webrtc_config) + : VideoEngine::Create(); assert(video_engine != NULL); return new internal::Call(video_engine, config); @@ -294,6 +295,12 @@ VideoReceiveStream* Call::CreateVideoReceiveStream( WriteLockScoped write_lock(*receive_lock_); assert(receive_ssrcs_.find(config.rtp.remote_ssrc) == receive_ssrcs_.end()); receive_ssrcs_[config.rtp.remote_ssrc] = receive_stream; + // TODO(pbos): Configure different RTX payloads per receive payload. + VideoReceiveStream::Config::Rtp::RtxMap::const_iterator it = + config.rtp.rtx.begin(); + if (it != config.rtp.rtx.end()) + receive_ssrcs_[it->second.ssrc] = receive_stream; + return receive_stream; } @@ -304,14 +311,16 @@ void Call::DestroyVideoReceiveStream( VideoReceiveStream* receive_stream_impl = NULL; { WriteLockScoped write_lock(*receive_lock_); - for (std::map::iterator it = - receive_ssrcs_.begin(); - it != receive_ssrcs_.end(); - ++it) { + // Remove all ssrcs pointing to a receive stream. As RTX retransmits on a + // separate SSRC there can be either one or two. + std::map::iterator it = + receive_ssrcs_.begin(); + while (it != receive_ssrcs_.end()) { if (it->second == static_cast(receive_stream)) { receive_stream_impl = it->second; - receive_ssrcs_.erase(it); - break; + receive_ssrcs_.erase(it++); + } else { + ++it; } } } diff --git a/webrtc/video/call_tests.cc b/webrtc/video/call_tests.cc index 3ec66fdd66..bbd8ad0d81 100644 --- a/webrtc/video/call_tests.cc +++ b/webrtc/video/call_tests.cc @@ -18,7 +18,6 @@ #include "webrtc/call.h" #include "webrtc/frame_callback.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/event_wrapper.h" @@ -41,8 +40,10 @@ namespace webrtc { static unsigned int kDefaultTimeoutMs = 30 * 1000; static unsigned int kLongTimeoutMs = 120 * 1000; static const uint32_t kSendSsrc = 0x654321; +static const uint32_t kSendRtxSsrc = 0x424242; static const uint32_t kReceiverLocalSsrc = 0x123456; static const uint8_t kSendPayloadType = 125; +static const uint8_t kSendRtxPayloadType = 126; class CallTest : public ::testing::Test { public: @@ -125,6 +126,7 @@ class CallTest : public ::testing::Test { receive_stream_ = NULL; } + void DecodesRetransmittedFrame(bool retransmit_over_rtx); void ReceivesPliAndRecovers(int rtp_history_ms); void RespectsRtcpMode(newapi::RtcpMode rtcp_mode); void TestXrReceiverReferenceTimeReport(bool enable_rrtr); @@ -159,8 +161,6 @@ class NackObserver : public test::RtpRtcpObserver { private: virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { - EXPECT_FALSE(RtpHeaderParser::IsRtcp(packet, static_cast(length))); - RTPHeader header; EXPECT_TRUE(rtp_parser_->Parse(packet, static_cast(length), &header)); @@ -328,7 +328,7 @@ TEST_F(CallTest, RendersSingleDelayedFrame) { EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); } private: - virtual void FrameCallback(I420VideoFrame* frame) { + virtual void FrameCallback(I420VideoFrame* frame) OVERRIDE { SleepMs(kDelayRenderCallbackMs); event_->Set(); } @@ -485,6 +485,99 @@ TEST_F(CallTest, ReceivesAndRetransmitsNack) { DestroyStreams(); } +// This test drops second RTP packet with a marker bit set, makes sure it's +// retransmitted and renders. Retransmission SSRCs are also checked. +void CallTest::DecodesRetransmittedFrame(bool retransmit_over_rtx) { + static const int kDroppedFrameNumber = 2; + class RetransmissionObserver : public test::RtpRtcpObserver, + public I420FrameCallback { + public: + RetransmissionObserver(bool expect_rtx) + : RtpRtcpObserver(kDefaultTimeoutMs), + retransmission_ssrc_(expect_rtx ? kSendRtxSsrc : kSendSsrc), + retransmission_payload_type_(expect_rtx ? kSendRtxPayloadType + : kSendPayloadType), + marker_bits_observed_(0), + retransmitted_timestamp_(0), + frame_retransmitted_(false) {} + + private: + virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { + RTPHeader header; + EXPECT_TRUE(parser_->Parse(packet, static_cast(length), &header)); + + if (header.timestamp == retransmitted_timestamp_) { + EXPECT_EQ(retransmission_ssrc_, header.ssrc); + EXPECT_EQ(retransmission_payload_type_, header.payloadType); + frame_retransmitted_ = true; + return SEND_PACKET; + } + + EXPECT_EQ(kSendSsrc, header.ssrc); + EXPECT_EQ(kSendPayloadType, header.payloadType); + + // Found the second frame's final packet, drop this and expect a + // retransmission. + if (header.markerBit && ++marker_bits_observed_ == kDroppedFrameNumber) { + retransmitted_timestamp_ = header.timestamp; + return DROP_PACKET; + } + + return SEND_PACKET; + } + + virtual void FrameCallback(I420VideoFrame* frame) OVERRIDE { + CriticalSectionScoped crit_(lock_.get()); + if (frame->timestamp() == retransmitted_timestamp_) { + EXPECT_TRUE(frame_retransmitted_); + observation_complete_->Set(); + } + } + + const uint32_t retransmission_ssrc_; + const int retransmission_payload_type_; + int marker_bits_observed_; + uint32_t retransmitted_timestamp_; + bool frame_retransmitted_; + } observer(retransmit_over_rtx); + + CreateCalls(Call::Config(observer.SendTransport()), + Call::Config(observer.ReceiveTransport())); + + observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver()); + + CreateTestConfigs(); + send_config_.rtp.nack.rtp_history_ms = + receive_config_.rtp.nack.rtp_history_ms = 1000; + if (retransmit_over_rtx) { + send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrc); + send_config_.rtp.rtx.payload_type = kSendRtxPayloadType; + int payload_type = send_config_.codec.plType; + receive_config_.rtp.rtx[payload_type].ssrc = kSendRtxSsrc; + receive_config_.rtp.rtx[payload_type].payload_type = kSendRtxPayloadType; + } + receive_config_.pre_render_callback = &observer; + + CreateStreams(); + CreateFrameGenerator(); + StartSending(); + + EXPECT_EQ(kEventSignaled, observer.Wait()) + << "Timed out while waiting for retransmission to render."; + + StopSending(); + observer.StopSending(); + DestroyStreams(); +} + +TEST_F(CallTest, DecodesRetransmittedFrame) { + DecodesRetransmittedFrame(false); +} + +TEST_F(CallTest, DecodesRetransmittedFrameOverRtx) { + DecodesRetransmittedFrame(true); +} + TEST_F(CallTest, UsesFrameCallbacks) { static const int kWidth = 320; static const int kHeight = 240; @@ -588,7 +681,6 @@ class PliObserver : public test::RtpRtcpObserver, public VideoRenderer { public: explicit PliObserver(bool nack_enabled) : test::RtpRtcpObserver(kLongTimeoutMs), - rtp_header_parser_(RtpHeaderParser::Create()), nack_enabled_(nack_enabled), highest_dropped_timestamp_(0), frames_to_drop_(0), @@ -596,8 +688,7 @@ class PliObserver : public test::RtpRtcpObserver, public VideoRenderer { virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { RTPHeader header; - EXPECT_TRUE( - rtp_header_parser_->Parse(packet, static_cast(length), &header)); + EXPECT_TRUE(parser_->Parse(packet, static_cast(length), &header)); // Drop all retransmitted packets to force a PLI. if (header.timestamp <= highest_dropped_timestamp_) @@ -643,7 +734,6 @@ class PliObserver : public test::RtpRtcpObserver, public VideoRenderer { private: static const int kPacketsToDrop = 1; - scoped_ptr rtp_header_parser_; bool nack_enabled_; uint32_t highest_dropped_timestamp_; int frames_to_drop_; @@ -933,9 +1023,10 @@ TEST_F(CallTest, SendsAndReceivesMultipleStreams) { TEST_F(CallTest, ObserversEncodedFrames) { class EncodedFrameTestObserver : public EncodedFrameObserver { public: - EncodedFrameTestObserver() : length_(0), - frame_type_(kFrameEmpty), - called_(EventWrapper::Create()) {} + EncodedFrameTestObserver() + : length_(0), + frame_type_(kFrameEmpty), + called_(EventWrapper::Create()) {} virtual ~EncodedFrameTestObserver() {} virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) { @@ -946,9 +1037,7 @@ TEST_F(CallTest, ObserversEncodedFrames) { called_->Set(); } - EventTypeWrapper Wait() { - return called_->Wait(kDefaultTimeoutMs); - } + EventTypeWrapper Wait() { return called_->Wait(kDefaultTimeoutMs); } void ExpectEqualFrames(const EncodedFrameTestObserver& observer) { ASSERT_EQ(length_, observer.length_) @@ -1064,6 +1153,7 @@ void CallTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) { sent_rtcp_rr_(0), sent_rtcp_rrtr_(0), sent_rtcp_dlrr_(0) {} + private: // Receive stream should send RR packets (and RRTR packets if enabled). virtual Action OnReceiveRtcp(const uint8_t* packet, @@ -1075,8 +1165,8 @@ void CallTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) { while (packet_type != RTCPUtility::kRtcpNotValidCode) { if (packet_type == RTCPUtility::kRtcpRrCode) { ++sent_rtcp_rr_; - } else if ( - packet_type == RTCPUtility::kRtcpXrReceiverReferenceTimeCode) { + } else if (packet_type == + RTCPUtility::kRtcpXrReceiverReferenceTimeCode) { ++sent_rtcp_rrtr_; } EXPECT_NE(packet_type, RTCPUtility::kRtcpSrCode); @@ -1122,8 +1212,7 @@ void CallTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) { CreateCalls(Call::Config(observer.SendTransport()), Call::Config(observer.ReceiveTransport())); - observer.SetReceivers(receiver_call_->Receiver(), - sender_call_->Receiver()); + observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver()); CreateTestConfigs(); receive_config_.rtp.rtcp_mode = newapi::kRtcpReducedSize; diff --git a/webrtc/video/rampup_tests.cc b/webrtc/video/rampup_tests.cc index 0386bd0bff..7486357859 100644 --- a/webrtc/video/rampup_tests.cc +++ b/webrtc/video/rampup_tests.cc @@ -36,8 +36,8 @@ namespace webrtc { namespace { - static const int kAbsoluteSendTimeExtensionId = 7; - static const int kMaxPacketSize = 1500; +static const int kAbsoluteSendTimeExtensionId = 7; +static const int kMaxPacketSize = 1500; } class StreamObserver : public newapi::Transport, public RemoteBitrateObserver { @@ -53,8 +53,9 @@ class StreamObserver : public newapi::Transport, public RemoteBitrateObserver { rtp_parser_(RtpHeaderParser::Create()), feedback_transport_(feedback_transport), receive_stats_(ReceiveStatistics::Create(clock)), - payload_registry_(new RTPPayloadRegistry( - -1, RTPPayloadStrategy::CreateStrategy(false))), + payload_registry_( + new RTPPayloadRegistry(-1, + RTPPayloadStrategy::CreateStrategy(false))), clock_(clock), num_expected_ssrcs_(num_expected_ssrcs), rtx_media_ssrcs_(rtx_media_ssrcs), @@ -88,19 +89,39 @@ class StreamObserver : public newapi::Transport, public RemoteBitrateObserver { if (ssrcs.size() == num_expected_ssrcs_ && bitrate >= kExpectedBitrateBps) { if (rtx_media_ssrcs_.empty() || rtx_media_sent_ > 0) { const ::testing::TestInfo* const test_info = - ::testing::UnitTest::GetInstance()->current_test_info(); - webrtc::test::PrintResult("total-sent", "", test_info->name(), - total_sent_, "bytes", false); - webrtc::test::PrintResult("padding-sent", "", test_info->name(), - padding_sent_, "bytes", false); - webrtc::test::PrintResult("rtx-media-sent", "", test_info->name(), - rtx_media_sent_, "bytes", false); - webrtc::test::PrintResult("total-packets-sent", "", test_info->name(), - total_packets_sent_, "packets", false); - webrtc::test::PrintResult("padding-packets-sent", "", test_info->name(), - padding_packets_sent_, "packets", false); - webrtc::test::PrintResult("rtx-packets-sent", "", test_info->name(), - rtx_media_packets_sent_, "packets", false); + ::testing::UnitTest::GetInstance()->current_test_info(); + webrtc::test::PrintResult( + "total-sent", "", test_info->name(), total_sent_, "bytes", false); + webrtc::test::PrintResult("padding-sent", + "", + test_info->name(), + padding_sent_, + "bytes", + false); + webrtc::test::PrintResult("rtx-media-sent", + "", + test_info->name(), + rtx_media_sent_, + "bytes", + false); + webrtc::test::PrintResult("total-packets-sent", + "", + test_info->name(), + total_packets_sent_, + "packets", + false); + webrtc::test::PrintResult("padding-packets-sent", + "", + test_info->name(), + padding_packets_sent_, + "packets", + false); + webrtc::test::PrintResult("rtx-packets-sent", + "", + test_info->name(), + rtx_media_packets_sent_, + "packets", + false); all_ssrcs_sent_->Set(); } } @@ -132,13 +153,14 @@ class StreamObserver : public newapi::Transport, public RemoteBitrateObserver { uint8_t restored_packet[kMaxPacketSize]; uint8_t* restored_packet_ptr = restored_packet; int restored_length = static_cast(length); - payload_registry_->RestoreOriginalPacket( - &restored_packet_ptr, packet, &restored_length, - rtx_media_ssrcs_[header.ssrc], - header); + payload_registry_->RestoreOriginalPacket(&restored_packet_ptr, + packet, + &restored_length, + rtx_media_ssrcs_[header.ssrc], + header); length = restored_length; - EXPECT_TRUE(rtp_parser_->Parse(restored_packet, static_cast(length), - &header)); + EXPECT_TRUE(rtp_parser_->Parse( + restored_packet, static_cast(length), &header)); } else { rtp_rtcp_->SetRemoteSSRC(header.ssrc); } @@ -191,9 +213,10 @@ class RampUpTest : public ::testing::TestWithParam { } test::DirectTransport receiver_transport; int num_expected_ssrcs = kNumberOfStreams + (rtx ? 1 : 0); - StreamObserver stream_observer( - num_expected_ssrcs, rtx_ssrc_map, &receiver_transport, - Clock::GetRealTimeClock()); + StreamObserver stream_observer(num_expected_ssrcs, + rtx_ssrc_map, + &receiver_transport, + Clock::GetRealTimeClock()); Call::Config call_config(&stream_observer); webrtc::Config webrtc_config; @@ -211,10 +234,10 @@ class RampUpTest : public ::testing::TestWithParam { send_config.codec.plType = 125; send_config.pacing = pacing; send_config.rtp.nack.rtp_history_ms = 1000; - send_config.rtp.ssrcs.insert(send_config.rtp.ssrcs.begin(), ssrcs.begin(), - ssrcs.end()); + send_config.rtp.ssrcs.insert( + send_config.rtp.ssrcs.begin(), ssrcs.begin(), ssrcs.end()); if (rtx) { - send_config.rtp.rtx.rtx_payload_type = 96; + send_config.rtp.rtx.payload_type = 96; send_config.rtp.rtx.ssrcs.insert(send_config.rtp.rtx.ssrcs.begin(), kRtxSsrcs, kRtxSsrcs + kNumberOfStreams); @@ -244,16 +267,10 @@ class RampUpTest : public ::testing::TestWithParam { std::map reserved_ssrcs_; }; -TEST_F(RampUpTest, WithoutPacing) { - RunRampUpTest(false, false); -} +TEST_F(RampUpTest, WithoutPacing) { RunRampUpTest(false, false); } -TEST_F(RampUpTest, WithPacing) { - RunRampUpTest(true, false); -} +TEST_F(RampUpTest, WithPacing) { RunRampUpTest(true, false); } -TEST_F(RampUpTest, WithPacingAndRtx) { - RunRampUpTest(true, true); -} +TEST_F(RampUpTest, WithPacingAndRtx) { RunRampUpTest(true, true); } } // namespace webrtc diff --git a/webrtc/video/video_receive_stream.cc b/webrtc/video/video_receive_stream.cc index 71fc1521e4..38947c4ac0 100644 --- a/webrtc/video/video_receive_stream.cc +++ b/webrtc/video/video_receive_stream.cc @@ -59,10 +59,21 @@ VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine, } assert(config_.rtp.remote_ssrc != 0); + // TODO(pbos): What's an appropriate local_ssrc for receive-only streams? assert(config_.rtp.local_ssrc != 0); assert(config_.rtp.remote_ssrc != config_.rtp.local_ssrc); rtp_rtcp_->SetLocalSSRC(channel_, config_.rtp.local_ssrc); + // TODO(pbos): Support multiple RTX, per video payload. + Config::Rtp::RtxMap::const_iterator it = config_.rtp.rtx.begin(); + if (it != config_.rtp.rtx.end()) { + assert(it->second.ssrc != 0); + assert(it->second.payload_type != 0); + + rtp_rtcp_->SetRemoteSSRCType(channel_, kViEStreamTypeRtx, it->second.ssrc); + rtp_rtcp_->SetRtxReceivePayloadType(channel_, it->second.payload_type); + } + rtp_rtcp_->SetRembStatus(channel_, false, config_.rtp.remb); for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) { @@ -102,8 +113,7 @@ VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine, decoder->payload_type, decoder->decoder, decoder->renderer, - decoder->expected_delay_ms) != - 0) { + decoder->expected_delay_ms) != 0) { // TODO(pbos): Abort gracefully? Can this be a runtime error? abort(); } @@ -182,8 +192,7 @@ bool VideoReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) { bool VideoReceiveStream::DeliverRtp(const uint8_t* packet, size_t length) { return network_->ReceivedRTPPacket( - channel_, packet, static_cast(length), - PacketTime()) == 0; + channel_, packet, static_cast(length), PacketTime()) == 0; } int32_t VideoReceiveStream::RenderFrame(const uint32_t stream_id, diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc index 3f0e593785..a9fd50dfa7 100644 --- a/webrtc/video/video_send_stream.cc +++ b/webrtc/video/video_send_stream.cc @@ -156,9 +156,11 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport, if (config.encoder) { external_codec_ = ViEExternalCodec::GetInterface(video_engine); - if (external_codec_->RegisterExternalSendCodec( - channel_, config.codec.plType, config.encoder, - config.internal_source) != 0) { + if (external_codec_->RegisterExternalSendCodec(channel_, + config.codec.plType, + config.encoder, + config.internal_source) != + 0) { abort(); } } @@ -168,9 +170,8 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport, abort(); if (overuse_detection) { - overuse_observer_.reset( - new ResolutionAdaptor(codec_, channel_, config_.codec.width, - config_.codec.height)); + overuse_observer_.reset(new ResolutionAdaptor( + codec_, channel_, config_.codec.width, config_.codec.height)); video_engine_base_->RegisterCpuOveruseObserver(channel_, overuse_observer_.get()); } @@ -187,8 +188,7 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport, codec_->SuspendBelowMinBitrate(channel_); } - stats_proxy_.reset( - new SendStatisticsProxy(config, this)); + stats_proxy_.reset(new SendStatisticsProxy(config, this)); rtp_rtcp_->RegisterSendChannelRtcpStatisticsCallback(channel_, stats_proxy_.get()); @@ -282,7 +282,9 @@ bool VideoSendStream::SetCodec(const VideoCodec& codec) { static_cast(i)); } - config_.codec = codec; + if (&config_.codec != &codec) + config_.codec = codec; + if (config_.rtp.rtx.ssrcs.empty()) return true; @@ -295,10 +297,8 @@ bool VideoSendStream::SetCodec(const VideoCodec& codec) { static_cast(i)); } - if (config_.rtp.rtx.rtx_payload_type != 0) { - rtp_rtcp_->SetRtxSendPayloadType(channel_, - config_.rtp.rtx.rtx_payload_type); - } + if (config_.rtp.rtx.payload_type != 0) + rtp_rtcp_->SetRtxSendPayloadType(channel_, config_.rtp.rtx.payload_type); return true; } diff --git a/webrtc/video/video_send_stream_tests.cc b/webrtc/video/video_send_stream_tests.cc index b69fbe2f25..3eb4f90e84 100644 --- a/webrtc/video/video_send_stream_tests.cc +++ b/webrtc/video/video_send_stream_tests.cc @@ -93,8 +93,8 @@ const uint8_t VideoSendStreamTest::kSendPayloadType = 100; const uint8_t VideoSendStreamTest::kFakeSendPayloadType = 125; const uint8_t VideoSendStreamTest::kSendRtxPayloadType = 98; const uint32_t VideoSendStreamTest::kSendRtxSsrc = 0xBADCAFE; -const uint32_t VideoSendStreamTest::kSendSsrcs[kNumSendSsrcs] = { 0xC0FFED, - 0xC0FFEE, 0xC0FFEF }; +const uint32_t VideoSendStreamTest::kSendSsrcs[kNumSendSsrcs] = { + 0xC0FFED, 0xC0FFEE, 0xC0FFEF}; const uint32_t VideoSendStreamTest::kSendSsrc = VideoSendStreamTest::kSendSsrcs[0]; @@ -121,10 +121,10 @@ void VideoSendStreamTest::SendsSetSsrcs(size_t num_ssrcs, // 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]) + // EXPECT_TRUE(valid_ssrcs_[header.ssrc]) // << "Received unknown SSRC: " << header.ssrc; // - //if (!valid_ssrcs_[header.ssrc]) + // if (!valid_ssrcs_[header.ssrc]) // observation_complete_->Set(); if (!is_observed_[header.ssrc]) { @@ -271,8 +271,7 @@ TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) { virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { RTPHeader header; - EXPECT_TRUE( - parser_->Parse(packet, static_cast(length), &header)); + EXPECT_TRUE(parser_->Parse(packet, static_cast(length), &header)); EXPECT_FALSE(header.extension.hasTransmissionTimeOffset); EXPECT_TRUE(header.extension.hasAbsoluteSendTime); @@ -299,10 +298,10 @@ TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) { class DelayedEncoder : public test::FakeEncoder { public: explicit DelayedEncoder(Clock* clock) : test::FakeEncoder(clock) {} - virtual int32_t Encode( - const I420VideoFrame& input_image, - const CodecSpecificInfo* codec_specific_info, - const std::vector* frame_types) OVERRIDE { + virtual int32_t Encode(const I420VideoFrame& input_image, + const CodecSpecificInfo* codec_specific_info, + const std::vector* frame_types) + OVERRIDE { // A delay needs to be introduced to assure that we get a timestamp // offset. SleepMs(5); @@ -319,8 +318,7 @@ TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) { virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { RTPHeader header; - EXPECT_TRUE( - parser_->Parse(packet, static_cast(length), &header)); + EXPECT_TRUE(parser_->Parse(packet, static_cast(length), &header)); EXPECT_TRUE(header.extension.hasTransmissionTimeOffset); EXPECT_FALSE(header.extension.hasAbsoluteSendTime); @@ -439,8 +437,7 @@ TEST_F(VideoSendStreamTest, SupportsFec) { virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { RTPHeader header; - EXPECT_TRUE( - parser_->Parse(packet, static_cast(length), &header)); + EXPECT_TRUE(parser_->Parse(packet, static_cast(length), &header)); // Send lossy receive reports to trigger FEC enabling. if (send_count_++ % 2 != 0) { @@ -511,8 +508,7 @@ void VideoSendStreamTest::TestNackRetransmission( virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { RTPHeader header; - EXPECT_TRUE( - parser_->Parse(packet, static_cast(length), &header)); + EXPECT_TRUE(parser_->Parse(packet, static_cast(length), &header)); // Nack second packet after receiving the third one. if (++send_count_ == 3) { @@ -564,7 +560,7 @@ void VideoSendStreamTest::TestNackRetransmission( VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1); send_config.rtp.nack.rtp_history_ms = 1000; - send_config.rtp.rtx.rtx_payload_type = retransmit_payload_type; + send_config.rtp.rtx.payload_type = retransmit_payload_type; send_config.pacing = enable_pacing; if (retransmit_ssrc != kSendSsrc) send_config.rtp.rtx.ssrcs.push_back(retransmit_ssrc); @@ -611,8 +607,7 @@ TEST_F(VideoSendStreamTest, FragmentsAccordingToMaxPacketSize) { virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { RTPHeader header; - EXPECT_TRUE( - parser_->Parse(packet, static_cast(length), &header)); + EXPECT_TRUE(parser_->Parse(packet, static_cast(length), &header)); EXPECT_LE(length, max_packet_size_); @@ -721,9 +716,7 @@ TEST_F(VideoSendStreamTest, CanChangeSendCodec) { return kEventSignaled; } - void SetSecondCodec(const VideoCodec& codec) { - second_codec_ = codec; - } + void SetSecondCodec(const VideoCodec& codec) { second_codec_ = codec; } private: scoped_ptr received_first_payload_; @@ -913,8 +906,9 @@ TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) { virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE { CriticalSectionScoped lock(crit_sect_.get()); const int kVideoMutedThresholdMs = 10000; - if (last_packet_time_ms_ > 0 && clock_->TimeInMilliseconds() - - last_packet_time_ms_ > kVideoMutedThresholdMs) + if (last_packet_time_ms_ > 0 && + clock_->TimeInMilliseconds() - last_packet_time_ms_ > + kVideoMutedThresholdMs) observation_complete_->Set(); // Receive statistics reporting having lost 50% of the packets. FakeReceiveStatistics receive_stats(kSendSsrcs[0], 1, 1, 0); diff --git a/webrtc/video_receive_stream.h b/webrtc/video_receive_stream.h index ac1afc694e..ae1b112155 100644 --- a/webrtc/video_receive_stream.h +++ b/webrtc/video_receive_stream.h @@ -26,10 +26,7 @@ namespace webrtc { namespace newapi { // RTCP mode to use. Compound mode is described by RFC 4585 and reduced-size // RTCP mode is described by RFC 5506. -enum RtcpMode { - kRtcpCompound, - kRtcpReducedSize -}; +enum RtcpMode { kRtcpCompound, kRtcpReducedSize }; } // namespace newapi class VideoDecoder; @@ -138,9 +135,21 @@ class VideoReceiveStream { // See FecConfig for description. FecConfig fec; - // RTX settings for video payloads that may be received. RTX is disabled - // if there's no config present. - std::map rtx; + // RTX settings for incoming video payloads that may be received. RTX is + // disabled if there's no config present. + struct Rtx { + Rtx() : ssrc(0), payload_type(0) {} + + // SSRCs to use for the RTX streams. + uint32_t ssrc; + + // Payload type to use for the RTX stream. + int payload_type; + }; + + // Map from video RTP payload type -> RTX config. + typedef std::map RtxMap; + RtxMap rtx; // RTP header extensions used for the received stream. std::vector extensions; diff --git a/webrtc/video_send_stream.h b/webrtc/video_send_stream.h index e59ef60dee..d1c17264c2 100644 --- a/webrtc/video_send_stream.h +++ b/webrtc/video_send_stream.h @@ -96,8 +96,16 @@ class VideoSendStream { // See FecConfig for description. FecConfig fec; - // See RtxConfig for description. - RtxConfig rtx; + // Settings for RTP retransmission payload format, see RFC 4588 for + // details. + struct Rtx { + Rtx() : payload_type(0) {} + // SSRCs to use for the RTX streams. + std::vector ssrcs; + + // Payload type to use for the RTX stream. + int payload_type; + } rtx; // RTCP CNAME, see RFC 3550. std::string c_name;