From fe68daab97dfaf0551638c25e321165bb7727432 Mon Sep 17 00:00:00 2001 From: Mirta Dvornicic Date: Thu, 23 May 2019 13:21:12 +0200 Subject: [PATCH] Add option to configure raw RTP packetization per payload type. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: webrtc:10625 Change-Id: I699f61af29656827eccb3c4ed507b4229dee972a Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/137803 Commit-Queue: Mirta Dvornicic Reviewed-by: Niels Moller Reviewed-by: Åsa Persson Reviewed-by: Rasmus Brandt Cr-Commit-Position: refs/heads/master@{#28036} --- call/rtp_config.cc | 1 + call/rtp_config.h | 4 ++ call/rtp_video_sender.cc | 3 +- call/video_receive_stream.cc | 5 ++ call/video_receive_stream.h | 7 +++ modules/rtp_rtcp/source/nack_rtx_unittest.cc | 3 +- modules/rtp_rtcp/source/rtp_format.cc | 19 +++++-- modules/rtp_rtcp/source/rtp_format.h | 8 ++- .../rtp_rtcp/source/rtp_rtcp_impl_unittest.cc | 3 +- .../rtp_rtcp/source/rtp_sender_unittest.cc | 47 +++++++++++++++--- modules/rtp_rtcp/source/rtp_sender_video.cc | 46 +++++++++-------- modules/rtp_rtcp/source/rtp_sender_video.h | 6 ++- .../source/rtp_sender_video_unittest.cc | 5 +- video/rtp_video_stream_receiver.cc | 15 ++++-- video/rtp_video_stream_receiver.h | 7 ++- video/rtp_video_stream_receiver_unittest.cc | 49 ++++++++++++++++--- video/video_receive_stream.cc | 7 ++- 17 files changed, 175 insertions(+), 60 deletions(-) diff --git a/call/rtp_config.cc b/call/rtp_config.cc index cce78ad64c..f11d69c22c 100644 --- a/call/rtp_config.cc +++ b/call/rtp_config.cc @@ -76,6 +76,7 @@ std::string RtpConfig::ToString() const { ss << ", ulpfec: " << ulpfec.ToString(); ss << ", payload_name: " << payload_name; ss << ", payload_type: " << payload_type; + ss << ", raw_payload: " << (raw_payload ? "true" : "false"); ss << ", flexfec: {payload_type: " << flexfec.payload_type; ss << ", ssrc: " << flexfec.ssrc; diff --git a/call/rtp_config.h b/call/rtp_config.h index b6155c05f8..adffc89d12 100644 --- a/call/rtp_config.h +++ b/call/rtp_config.h @@ -99,6 +99,10 @@ struct RtpConfig { // images to the right payload type. std::string payload_name; int payload_type = -1; + // Payload should be packetized using raw packetizer (payload header will + // not be added, additional meta data is expected to be present in generic + // frame descriptor RTP header extension). + bool raw_payload = false; // See NackConfig for description. NackConfig nack; diff --git a/call/rtp_video_sender.cc b/call/rtp_video_sender.cc index 796575b095..332fc95e15 100644 --- a/call/rtp_video_sender.cc +++ b/call/rtp_video_sender.cc @@ -312,7 +312,8 @@ RtpVideoSender::RtpVideoSender( stream.rtp_rtcp->RegisterSendPayloadFrequency(rtp_config.payload_type, kVideoPayloadTypeFrequency); stream.sender_video->RegisterPayloadType(rtp_config.payload_type, - rtp_config.payload_name); + rtp_config.payload_name, + rtp_config.raw_payload); } // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic, // so enable that logic if either of those FEC schemes are enabled. diff --git a/call/video_receive_stream.cc b/call/video_receive_stream.cc index 92787cc26b..e825956754 100644 --- a/call/video_receive_stream.cc +++ b/call/video_receive_stream.cc @@ -125,6 +125,11 @@ std::string VideoReceiveStream::Config::Rtp::ToString() const { ss << kv.first << " (pt) -> " << kv.second << " (apt), "; } ss << '}'; + ss << ", raw_payload_types: {"; + for (const auto& pt : raw_payload_types) { + ss << pt << ", "; + } + ss << '}'; ss << ", extensions: ["; for (size_t i = 0; i < extensions.size(); ++i) { ss << extensions[i].ToString(); diff --git a/call/video_receive_stream.h b/call/video_receive_stream.h index a1fa86d293..5a819f9bcc 100644 --- a/call/video_receive_stream.h +++ b/call/video_receive_stream.h @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -195,6 +196,12 @@ class VideoReceiveStream { // For RTX to be enabled, both an SSRC and this mapping are needed. std::map rtx_associated_payload_types; + // Payload types that should be depacketized using raw depacketizer + // (payload header will not be parsed and must not be present, additional + // meta data is expected to be present in generic frame descriptor + // RTP header extension). + std::set raw_payload_types; + // RTP header extensions used for the received stream. std::vector extensions; } rtp; diff --git a/modules/rtp_rtcp/source/nack_rtx_unittest.cc b/modules/rtp_rtcp/source/nack_rtx_unittest.cc index 2ae324c933..f8fd39a55f 100644 --- a/modules/rtp_rtcp/source/nack_rtx_unittest.cc +++ b/modules/rtp_rtcp/source/nack_rtx_unittest.cc @@ -151,7 +151,8 @@ class RtpRtcpRtxNackTest : public ::testing::Test { // single rtp_rtcp module for both send and receive side. rtp_rtcp_module_->SetRemoteSSRC(kTestSsrc); - rtp_sender_video_->RegisterPayloadType(kPayloadType, "video"); + rtp_sender_video_->RegisterPayloadType(kPayloadType, "video", + /*raw_payload=*/false); rtp_rtcp_module_->SetRtxSendPayloadType(kRtxPayloadType, kPayloadType); transport_.SetSendModule(rtp_rtcp_module_.get()); media_receiver_ = transport_.stream_receiver_controller_.CreateReceiver( diff --git a/modules/rtp_rtcp/source/rtp_format.cc b/modules/rtp_rtcp/source/rtp_format.cc index 843cbb85fa..e870232a4d 100644 --- a/modules/rtp_rtcp/source/rtp_format.cc +++ b/modules/rtp_rtcp/source/rtp_format.cc @@ -24,14 +24,19 @@ namespace webrtc { std::unique_ptr RtpPacketizer::Create( - VideoCodecType type, + absl::optional type, rtc::ArrayView payload, PayloadSizeLimits limits, // Codec-specific details. const RTPVideoHeader& rtp_video_header, VideoFrameType frame_type, const RTPFragmentationHeader* fragmentation) { - switch (type) { + if (!type) { + // Use raw packetizer. + return absl::make_unique(payload, limits); + } + + switch (*type) { case kVideoCodecH264: { RTC_CHECK(fragmentation); const auto& h264 = @@ -133,8 +138,13 @@ std::vector RtpPacketizer::SplitAboutEqually( return result; } -RtpDepacketizer* RtpDepacketizer::Create(VideoCodecType type) { - switch (type) { +RtpDepacketizer* RtpDepacketizer::Create(absl::optional type) { + if (!type) { + // Use raw depacketizer. + return new RtpDepacketizerGeneric(/*generic_header_enabled=*/false); + } + + switch (*type) { case kVideoCodecH264: return new RtpDepacketizerH264(); case kVideoCodecVP8: @@ -145,4 +155,5 @@ RtpDepacketizer* RtpDepacketizer::Create(VideoCodecType type) { return new RtpDepacketizerGeneric(/*generic_header_enabled=*/true); } } + } // namespace webrtc diff --git a/modules/rtp_rtcp/source/rtp_format.h b/modules/rtp_rtcp/source/rtp_format.h index f9c1e7651d..b28e9a6614 100644 --- a/modules/rtp_rtcp/source/rtp_format.h +++ b/modules/rtp_rtcp/source/rtp_format.h @@ -15,6 +15,7 @@ #include #include +#include "absl/types/optional.h" #include "api/array_view.h" #include "modules/include/module_common_types.h" #include "modules/rtp_rtcp/source/rtp_video_header.h" @@ -32,8 +33,10 @@ class RtpPacketizer { // Reduction len for packet that is first & last at the same time. int single_packet_reduction_len = 0; }; + + // If type is not set, returns a raw packetizer. static std::unique_ptr Create( - VideoCodecType type, + absl::optional type, rtc::ArrayView payload, PayloadSizeLimits limits, // Codec-specific details. @@ -79,7 +82,8 @@ class RtpDepacketizer { size_t payload_length; }; - static RtpDepacketizer* Create(VideoCodecType type); + // If type is not set, returns a raw depacketizer. + static RtpDepacketizer* Create(absl::optional type); virtual ~RtpDepacketizer() {} diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc index 28712c5912..09f8dbd61d 100644 --- a/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc +++ b/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc @@ -193,7 +193,8 @@ class RtpRtcpImplTest : public ::testing::Test { codec_.plType = 100; codec_.width = 320; codec_.height = 180; - sender_video_->RegisterPayloadType(codec_.plType, "VP8"); + sender_video_->RegisterPayloadType(codec_.plType, "VP8", + /*raw_payload=*/false); // Receive module. EXPECT_EQ(0, receiver_.impl_->SetSendingStatus(false)); diff --git a/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_unittest.cc index 9ac23fc478..3d1bed45d1 100644 --- a/modules/rtp_rtcp/source/rtp_sender_unittest.cc +++ b/modules/rtp_rtcp/source/rtp_sender_unittest.cc @@ -521,7 +521,8 @@ TEST_P(RtpSenderTestWithoutPacer, OnSendSideDelayUpdated) { const uint8_t kPayloadType = 127; const char payload_name[] = "GENERIC"; - rtp_sender_video.RegisterPayloadType(kPayloadType, payload_name); + rtp_sender_video.RegisterPayloadType(kPayloadType, payload_name, + /*raw_payload=*/false); const uint32_t kCaptureTimeMsToRtpTimestamp = 90; // 90 kHz clock RTPVideoHeader video_header; @@ -1099,7 +1100,8 @@ TEST_P(RtpSenderTestWithoutPacer, SendGenericVideo) { RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), nullptr, &playout_delay_oracle, nullptr, false, FieldTrialBasedConfig()); - rtp_sender_video.RegisterPayloadType(payload_type, payload_name); + rtp_sender_video.RegisterPayloadType(payload_type, payload_name, + /*raw_payload=*/false); uint8_t payload[] = {47, 11, 32, 93, 89}; // Send keyframe @@ -1132,6 +1134,29 @@ TEST_P(RtpSenderTestWithoutPacer, SendGenericVideo) { EXPECT_THAT(sent_payload.subview(1), ElementsAreArray(payload)); } +TEST_P(RtpSenderTestWithoutPacer, SendRawVideo) { + const char payload_name[] = "VP8"; + const uint8_t payload_type = 111; + const uint8_t payload[] = {11, 22, 33, 44, 55}; + + PlayoutDelayOracle playout_delay_oracle; + RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), nullptr, + &playout_delay_oracle, nullptr, false, + FieldTrialBasedConfig()); + rtp_sender_video.RegisterPayloadType(payload_type, payload_name, + /*raw_payload=*/true); + + // Send a frame. + RTPVideoHeader video_header; + ASSERT_TRUE(rtp_sender_video.SendVideo( + VideoFrameType::kVideoFrameKey, payload_type, 1234, 4321, payload, + sizeof(payload), nullptr, &video_header, + kDefaultExpectedRetransmissionTimeMs)); + + auto sent_payload = transport_.last_sent_packet().payload(); + EXPECT_THAT(sent_payload, ElementsAreArray(payload)); +} + TEST_P(RtpSenderTest, SendFlexfecPackets) { constexpr uint32_t kTimestamp = 1234; constexpr int kMediaPayloadType = 127; @@ -1158,7 +1183,8 @@ TEST_P(RtpSenderTest, SendFlexfecPackets) { RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), &flexfec_sender, &playout_delay_oracle, nullptr, false, FieldTrialBasedConfig()); - rtp_sender_video.RegisterPayloadType(kMediaPayloadType, "GENERIC"); + rtp_sender_video.RegisterPayloadType(kMediaPayloadType, "GENERIC", + /*raw_payload=*/false); // Parameters selected to generate a single FEC packet per media packet. FecProtectionParams params; @@ -1234,7 +1260,8 @@ TEST_P(RtpSenderTest, NoFlexfecForTimingFrames) { RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), &flexfec_sender, &playout_delay_oracle, nullptr, false, FieldTrialBasedConfig()); - rtp_sender_video.RegisterPayloadType(kMediaPayloadType, "GENERIC"); + rtp_sender_video.RegisterPayloadType(kMediaPayloadType, "GENERIC", + /*raw_payload=*/false); // Need extension to be registered for timing frames to be sent. ASSERT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( @@ -1335,7 +1362,8 @@ TEST_P(RtpSenderTestWithoutPacer, SendFlexfecPackets) { RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), &flexfec_sender, &playout_delay_oracle, nullptr, false, FieldTrialBasedConfig()); - rtp_sender_video.RegisterPayloadType(kMediaPayloadType, "GENERIC"); + rtp_sender_video.RegisterPayloadType(kMediaPayloadType, "GENERIC", + /*raw_payload=*/false); // Parameters selected to generate a single FEC packet per media packet. FecProtectionParams params; @@ -1465,7 +1493,8 @@ TEST_P(RtpSenderTest, FecOverheadRate) { RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), &flexfec_sender, &playout_delay_oracle, nullptr, false, FieldTrialBasedConfig()); - rtp_sender_video.RegisterPayloadType(kMediaPayloadType, "GENERIC"); + rtp_sender_video.RegisterPayloadType(kMediaPayloadType, "GENERIC", + /*raw_payload=*/false); // Parameters selected to generate a single FEC packet per media packet. FecProtectionParams params; params.fec_rate = 15; @@ -1537,7 +1566,8 @@ TEST_P(RtpSenderTest, BitrateCallbacks) { FieldTrialBasedConfig()); const char payload_name[] = "GENERIC"; const uint8_t payload_type = 127; - rtp_sender_video.RegisterPayloadType(payload_type, payload_name); + rtp_sender_video.RegisterPayloadType(payload_type, payload_name, + /*raw_payload=*/false); // Simulate kNumPackets sent with kPacketInterval ms intervals, with the // number of packets selected so that we fill (but don't overflow) the one @@ -1623,7 +1653,8 @@ TEST_P(RtpSenderTestWithoutPacer, StreamDataCountersCallbacks) { RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), nullptr, &playout_delay_oracle, nullptr, false, FieldTrialBasedConfig()); - rtp_sender_video.RegisterPayloadType(payload_type, payload_name); + rtp_sender_video.RegisterPayloadType(payload_type, payload_name, + /*raw_payload=*/false); uint8_t payload[] = {47, 11, 32, 93, 89}; rtp_sender_->SetStorePacketsStatus(true, 1); uint32_t ssrc = rtp_sender_->SSRC(); diff --git a/modules/rtp_rtcp/source/rtp_sender_video.cc b/modules/rtp_rtcp/source/rtp_sender_video.cc index a71a6e5b05..8d12ff4cd1 100644 --- a/modules/rtp_rtcp/source/rtp_sender_video.cc +++ b/modules/rtp_rtcp/source/rtp_sender_video.cc @@ -24,9 +24,7 @@ #include "modules/remote_bitrate_estimator/test/bwe_test_logging.h" #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "modules/rtp_rtcp/source/byte_io.h" -#include "modules/rtp_rtcp/source/rtp_format_video_generic.h" -#include "modules/rtp_rtcp/source/rtp_format_vp8.h" -#include "modules/rtp_rtcp/source/rtp_format_vp9.h" +#include "modules/rtp_rtcp/source/rtp_format.h" #include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h" #include "modules/rtp_rtcp/source/rtp_header_extensions.h" #include "modules/rtp_rtcp/source/rtp_packet_to_send.h" @@ -224,28 +222,28 @@ RTPSenderVideo::RTPSenderVideo(Clock* clock, RTPSenderVideo::~RTPSenderVideo() {} void RTPSenderVideo::RegisterPayloadType(int8_t payload_type, - absl::string_view payload_name) { - VideoCodecType video_type; - - if (absl::EqualsIgnoreCase(payload_name, "VP8")) { - video_type = kVideoCodecVP8; - } else if (absl::EqualsIgnoreCase(payload_name, "VP9")) { - video_type = kVideoCodecVP9; - } else if (absl::EqualsIgnoreCase(payload_name, "H264")) { - video_type = kVideoCodecH264; - } else if (absl::EqualsIgnoreCase(payload_name, "I420")) { - video_type = kVideoCodecGeneric; - } else if (absl::EqualsIgnoreCase(payload_name, "stereo")) { - video_type = kVideoCodecGeneric; - } else { - video_type = kVideoCodecGeneric; + absl::string_view payload_name, + bool raw_payload) { + absl::optional video_type; + if (!raw_payload) { + if (absl::EqualsIgnoreCase(payload_name, "VP8")) { + video_type = kVideoCodecVP8; + } else if (absl::EqualsIgnoreCase(payload_name, "VP9")) { + video_type = kVideoCodecVP9; + } else if (absl::EqualsIgnoreCase(payload_name, "H264")) { + video_type = kVideoCodecH264; + } else { + video_type = kVideoCodecGeneric; + } } - rtc::CritScope cs(&payload_type_crit_); - payload_type_map_[payload_type] = video_type; + { + rtc::CritScope cs(&payload_type_crit_); + payload_type_map_[payload_type] = video_type; + } // Backward compatibility for older receivers without temporal layer logic - if (video_type == kVideoCodecH264) { + if (absl::EqualsIgnoreCase(payload_name, "H264")) { rtc::CritScope cs(&crit_); retransmission_settings_ = kRetransmitBaseLayer | kRetransmitHigherLayers; } @@ -613,7 +611,7 @@ bool RTPSenderVideo::SendVideo(VideoFrameType frame_type, << "one is required since require_frame_encryptor is set"; } - VideoCodecType video_type; + absl::optional type; { rtc::CritScope cs(&payload_type_crit_); const auto it = payload_type_map_.find(payload_type); @@ -622,10 +620,10 @@ bool RTPSenderVideo::SendVideo(VideoFrameType frame_type, << " not registered."; return false; } - video_type = it->second; + type = it->second; } std::unique_ptr packetizer = RtpPacketizer::Create( - video_type, rtc::MakeArrayView(payload_data, payload_size), limits, + type, rtc::MakeArrayView(payload_data, payload_size), limits, *packetize_video_header, frame_type, fragmentation); const uint8_t temporal_id = GetTemporalId(*video_header); diff --git a/modules/rtp_rtcp/source/rtp_sender_video.h b/modules/rtp_rtcp/source/rtp_sender_video.h index cc7c1fa624..bdbe90a2f5 100644 --- a/modules/rtp_rtcp/source/rtp_sender_video.h +++ b/modules/rtp_rtcp/source/rtp_sender_video.h @@ -71,7 +71,9 @@ class RTPSenderVideo { const RTPVideoHeader* video_header, int64_t expected_retransmission_time_ms); - void RegisterPayloadType(int8_t payload_type, absl::string_view payload_name); + void RegisterPayloadType(int8_t payload_type, + absl::string_view payload_name, + bool raw_payload); // Set RED and ULPFEC payload types. A payload type of -1 means that the // corresponding feature is turned off. Note that we DO NOT support enabling @@ -162,7 +164,7 @@ class RTPSenderVideo { // Maps payload type to codec type, for packetization. // TODO(nisse): Set on construction, to avoid lock. rtc::CriticalSection payload_type_crit_; - std::map payload_type_map_ + std::map> payload_type_map_ RTC_GUARDED_BY(payload_type_crit_); // Should never be held when calling out of this class. diff --git a/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc index b54934cf57..9864ecb0f6 100644 --- a/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc +++ b/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc @@ -163,7 +163,8 @@ class RtpSenderVideoTest : public ::testing::TestWithParam { rtp_sender_.SetTimestampOffset(0); rtp_sender_.SetSSRC(kSsrc); - rtp_sender_video_.RegisterPayloadType(kPayload, "generic"); + rtp_sender_video_.RegisterPayloadType(kPayload, "generic", + /*raw_payload=*/false); } void PopulateGenericFrameDescriptor(int version); @@ -618,7 +619,7 @@ void RtpSenderVideoTest:: vp8.keyIdx = 2; RTPVideoHeader::GenericDescriptorInfo& generic = hdr.generic.emplace(); generic.frame_id = kFrameId; - rtp_sender_video_.RegisterPayloadType(kPayload, "vp8"); + rtp_sender_video_.RegisterPayloadType(kPayload, "vp8", /*raw_payload=*/false); rtp_sender_video_.SendVideo(VideoFrameType::kVideoFrameDelta, kPayload, kTimestamp, 0, kFrame, sizeof(kFrame), nullptr, &hdr, kDefaultExpectedRetransmissionTimeMs); diff --git a/video/rtp_video_stream_receiver.cc b/video/rtp_video_stream_receiver.cc index edced5d6b2..e12bd5c49e 100644 --- a/video/rtp_video_stream_receiver.cc +++ b/video/rtp_video_stream_receiver.cc @@ -193,8 +193,13 @@ RtpVideoStreamReceiver::~RtpVideoStreamReceiver() { void RtpVideoStreamReceiver::AddReceiveCodec( const VideoCodec& video_codec, - const std::map& codec_params) { - pt_codec_type_.emplace(video_codec.plType, video_codec.codecType); + const std::map& codec_params, + bool raw_payload) { + absl::optional video_type; + if (!raw_payload) { + video_type = video_codec.codecType; + } + payload_type_map_.emplace(video_codec.plType, video_type); pt_codec_params_.emplace(video_codec.plType, codec_params); } @@ -503,12 +508,12 @@ void RtpVideoStreamReceiver::ReceivePacket(const RtpPacketReceived& packet) { return; } - const auto codec_type_it = pt_codec_type_.find(packet.PayloadType()); - if (codec_type_it == pt_codec_type_.end()) { + const auto type_it = payload_type_map_.find(packet.PayloadType()); + if (type_it == payload_type_map_.end()) { return; } auto depacketizer = - absl::WrapUnique(RtpDepacketizer::Create(codec_type_it->second)); + absl::WrapUnique(RtpDepacketizer::Create(type_it->second)); if (!depacketizer) { RTC_LOG(LS_ERROR) << "Failed to create depacketizer."; diff --git a/video/rtp_video_stream_receiver.h b/video/rtp_video_stream_receiver.h index fdacca9fe8..237a5144a0 100644 --- a/video/rtp_video_stream_receiver.h +++ b/video/rtp_video_stream_receiver.h @@ -82,7 +82,8 @@ class RtpVideoStreamReceiver : public LossNotificationSender, ~RtpVideoStreamReceiver() override; void AddReceiveCodec(const VideoCodec& video_codec, - const std::map& codec_params); + const std::map& codec_params, + bool raw_payload); void StartReceive(); void StopReceive(); @@ -214,7 +215,9 @@ class RtpVideoStreamReceiver : public LossNotificationSender, RTC_GUARDED_BY(last_seq_num_cs_); video_coding::H264SpsPpsTracker tracker_; - std::map pt_codec_type_; + // Maps payload type to codec type, for packetization. + std::map> payload_type_map_; + // TODO(johan): Remove pt_codec_params_ once // https://bugs.chromium.org/p/webrtc/issues/detail?id=6883 is resolved. // Maps a payload type to a map of out-of-band supplied codec parameters. diff --git a/video/rtp_video_stream_receiver_unittest.cc b/video/rtp_video_stream_receiver_unittest.cc index 11335603f9..d9c10713b9 100644 --- a/video/rtp_video_stream_receiver_unittest.cc +++ b/video/rtp_video_stream_receiver_unittest.cc @@ -278,7 +278,8 @@ TEST_F(RtpVideoStreamReceiverTest, CacheColorSpaceFromLastPacketOfKeyframe) { codec.plType = kPayloadType; codec.codecType = kVideoCodecVP9; std::map codec_params; - rtp_video_stream_receiver_->AddReceiveCodec(codec, codec_params); + rtp_video_stream_receiver_->AddReceiveCodec(codec, codec_params, + /*raw_payload=*/false); // Generate key frame packets. received_packet_generator.SetPayload(kKeyFramePayload, @@ -345,7 +346,7 @@ TEST_F(RtpVideoStreamReceiverTest, NoInfiniteRecursionOnEncapsulatedRedPacket) { const uint8_t kRedPayloadType = 125; VideoCodec codec; codec.plType = kRedPayloadType; - rtp_video_stream_receiver_->AddReceiveCodec(codec, {}); + rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false); const std::vector data({ 0x80, // RTP version. kRedPayloadType, // Payload type. @@ -469,7 +470,8 @@ TEST_P(RtpVideoStreamReceiverTestH264, OutOfBandFmtpSpsPps) { // . codec_params.insert( {cricket::kH264FmtpSpropParameterSets, "Z0IACpZTBYmI,aMljiA=="}); - rtp_video_stream_receiver_->AddReceiveCodec(codec, codec_params); + rtp_video_stream_receiver_->AddReceiveCodec(codec, codec_params, + /*raw_payload=*/false); const uint8_t binary_sps[] = {0x67, 0x42, 0x00, 0x0a, 0x96, 0x53, 0x05, 0x89, 0x88}; mock_on_complete_frame_callback_.AppendExpectedBitstream( @@ -683,7 +685,7 @@ TEST_P(RtpVideoStreamReceiverGenericDescriptorTest, VideoCodec codec; codec.plType = kPayloadType; - rtp_video_stream_receiver_->AddReceiveCodec(codec, {}); + rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false); rtp_video_stream_receiver_->StartReceive(); RtpHeaderExtensionMap extension_map; @@ -731,7 +733,7 @@ TEST_P(RtpVideoStreamReceiverGenericDescriptorTest, VideoCodec codec; codec.plType = kPayloadType; - rtp_video_stream_receiver_->AddReceiveCodec(codec, {}); + rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false); rtp_video_stream_receiver_->StartReceive(); RtpHeaderExtensionMap extension_map; @@ -792,7 +794,7 @@ TEST_F(RtpVideoStreamReceiverGenericDescriptorTest, VideoCodec codec; codec.plType = kPayloadType; - rtp_video_stream_receiver_->AddReceiveCodec(codec, {}); + rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false); rtp_video_stream_receiver_->StartReceive(); RtpHeaderExtensionMap extension_map; @@ -824,6 +826,41 @@ TEST_F(RtpVideoStreamReceiverGenericDescriptorTest, rtp_video_stream_receiver_->OnRtpPacket(rtp_packet); } +TEST_P(RtpVideoStreamReceiverGenericDescriptorTest, + ParseGenericDescriptorRawPayload) { + const int version = GetParam(); + + const std::vector data = {0, 1, 2, 3, 4}; + const int kPayloadType = 123; + + VideoCodec codec; + codec.plType = kPayloadType; + rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/true); + rtp_video_stream_receiver_->StartReceive(); + + RtpHeaderExtensionMap extension_map; + RegisterRtpGenericFrameDescriptorExtension(&extension_map, version); + RtpPacketReceived rtp_packet(&extension_map); + + RtpGenericFrameDescriptor generic_descriptor; + generic_descriptor.SetFirstPacketInSubFrame(true); + generic_descriptor.SetLastPacketInSubFrame(true); + ASSERT_TRUE(SetExtensionRtpGenericFrameDescriptorExtension( + generic_descriptor, &rtp_packet, version)); + + uint8_t* payload = rtp_packet.SetPayloadSize(data.size()); + memcpy(payload, data.data(), data.size()); + mock_on_complete_frame_callback_.AppendExpectedBitstream(data.data(), + data.size()); + + rtp_packet.SetMarker(true); + rtp_packet.SetPayloadType(kPayloadType); + rtp_packet.SetSequenceNumber(1); + + EXPECT_CALL(mock_on_complete_frame_callback_, DoOnCompleteFrame); + rtp_video_stream_receiver_->OnRtpPacket(rtp_packet); +} + #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) TEST_F(RtpVideoStreamReceiverTest, RepeatedSecondarySinkDisallowed) { MockRtpPacketSink secondary_sink; diff --git a/video/video_receive_stream.cc b/video/video_receive_stream.cc index 20a19674f3..176b68258e 100644 --- a/video/video_receive_stream.cc +++ b/video/video_receive_stream.cc @@ -367,8 +367,11 @@ void VideoReceiveStream::Start() { video_receiver_.RegisterExternalDecoder(video_decoders_.back().get(), decoder.payload_type); VideoCodec codec = CreateDecoderVideoCodec(decoder); - rtp_video_stream_receiver_.AddReceiveCodec(codec, - decoder.video_format.parameters); + + const bool raw_payload = + config_.rtp.raw_payload_types.count(codec.plType) > 0; + rtp_video_stream_receiver_.AddReceiveCodec( + codec, decoder.video_format.parameters, raw_payload); RTC_CHECK_EQ(VCM_OK, video_receiver_.RegisterReceiveCodec( &codec, num_cpu_cores_, false)); }