Add option to configure raw RTP packetization per payload type.

Bug: webrtc:10625
Change-Id: I699f61af29656827eccb3c4ed507b4229dee972a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/137803
Commit-Queue: Mirta Dvornicic <mirtad@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28036}
This commit is contained in:
Mirta Dvornicic
2019-05-23 13:21:12 +02:00
committed by Commit Bot
parent a352248c43
commit fe68daab97
17 changed files with 175 additions and 60 deletions

View File

@ -76,6 +76,7 @@ std::string RtpConfig::ToString() const {
ss << ", ulpfec: " << ulpfec.ToString(); ss << ", ulpfec: " << ulpfec.ToString();
ss << ", payload_name: " << payload_name; ss << ", payload_name: " << payload_name;
ss << ", payload_type: " << payload_type; ss << ", payload_type: " << payload_type;
ss << ", raw_payload: " << (raw_payload ? "true" : "false");
ss << ", flexfec: {payload_type: " << flexfec.payload_type; ss << ", flexfec: {payload_type: " << flexfec.payload_type;
ss << ", ssrc: " << flexfec.ssrc; ss << ", ssrc: " << flexfec.ssrc;

View File

@ -99,6 +99,10 @@ struct RtpConfig {
// images to the right payload type. // images to the right payload type.
std::string payload_name; std::string payload_name;
int payload_type = -1; 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. // See NackConfig for description.
NackConfig nack; NackConfig nack;

View File

@ -312,7 +312,8 @@ RtpVideoSender::RtpVideoSender(
stream.rtp_rtcp->RegisterSendPayloadFrequency(rtp_config.payload_type, stream.rtp_rtcp->RegisterSendPayloadFrequency(rtp_config.payload_type,
kVideoPayloadTypeFrequency); kVideoPayloadTypeFrequency);
stream.sender_video->RegisterPayloadType(rtp_config.payload_type, 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, // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
// so enable that logic if either of those FEC schemes are enabled. // so enable that logic if either of those FEC schemes are enabled.

View File

@ -125,6 +125,11 @@ std::string VideoReceiveStream::Config::Rtp::ToString() const {
ss << kv.first << " (pt) -> " << kv.second << " (apt), "; ss << kv.first << " (pt) -> " << kv.second << " (apt), ";
} }
ss << '}'; ss << '}';
ss << ", raw_payload_types: {";
for (const auto& pt : raw_payload_types) {
ss << pt << ", ";
}
ss << '}';
ss << ", extensions: ["; ss << ", extensions: [";
for (size_t i = 0; i < extensions.size(); ++i) { for (size_t i = 0; i < extensions.size(); ++i) {
ss << extensions[i].ToString(); ss << extensions[i].ToString();

View File

@ -13,6 +13,7 @@
#include <limits> #include <limits>
#include <map> #include <map>
#include <set>
#include <string> #include <string>
#include <vector> #include <vector>
@ -195,6 +196,12 @@ class VideoReceiveStream {
// For RTX to be enabled, both an SSRC and this mapping are needed. // For RTX to be enabled, both an SSRC and this mapping are needed.
std::map<int, int> rtx_associated_payload_types; std::map<int, int> 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<int> raw_payload_types;
// RTP header extensions used for the received stream. // RTP header extensions used for the received stream.
std::vector<RtpExtension> extensions; std::vector<RtpExtension> extensions;
} rtp; } rtp;

View File

@ -151,7 +151,8 @@ class RtpRtcpRtxNackTest : public ::testing::Test {
// single rtp_rtcp module for both send and receive side. // single rtp_rtcp module for both send and receive side.
rtp_rtcp_module_->SetRemoteSSRC(kTestSsrc); 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); rtp_rtcp_module_->SetRtxSendPayloadType(kRtxPayloadType, kPayloadType);
transport_.SetSendModule(rtp_rtcp_module_.get()); transport_.SetSendModule(rtp_rtcp_module_.get());
media_receiver_ = transport_.stream_receiver_controller_.CreateReceiver( media_receiver_ = transport_.stream_receiver_controller_.CreateReceiver(

View File

@ -24,14 +24,19 @@
namespace webrtc { namespace webrtc {
std::unique_ptr<RtpPacketizer> RtpPacketizer::Create( std::unique_ptr<RtpPacketizer> RtpPacketizer::Create(
VideoCodecType type, absl::optional<VideoCodecType> type,
rtc::ArrayView<const uint8_t> payload, rtc::ArrayView<const uint8_t> payload,
PayloadSizeLimits limits, PayloadSizeLimits limits,
// Codec-specific details. // Codec-specific details.
const RTPVideoHeader& rtp_video_header, const RTPVideoHeader& rtp_video_header,
VideoFrameType frame_type, VideoFrameType frame_type,
const RTPFragmentationHeader* fragmentation) { const RTPFragmentationHeader* fragmentation) {
switch (type) { if (!type) {
// Use raw packetizer.
return absl::make_unique<RtpPacketizerGeneric>(payload, limits);
}
switch (*type) {
case kVideoCodecH264: { case kVideoCodecH264: {
RTC_CHECK(fragmentation); RTC_CHECK(fragmentation);
const auto& h264 = const auto& h264 =
@ -133,8 +138,13 @@ std::vector<int> RtpPacketizer::SplitAboutEqually(
return result; return result;
} }
RtpDepacketizer* RtpDepacketizer::Create(VideoCodecType type) { RtpDepacketizer* RtpDepacketizer::Create(absl::optional<VideoCodecType> type) {
switch (type) { if (!type) {
// Use raw depacketizer.
return new RtpDepacketizerGeneric(/*generic_header_enabled=*/false);
}
switch (*type) {
case kVideoCodecH264: case kVideoCodecH264:
return new RtpDepacketizerH264(); return new RtpDepacketizerH264();
case kVideoCodecVP8: case kVideoCodecVP8:
@ -145,4 +155,5 @@ RtpDepacketizer* RtpDepacketizer::Create(VideoCodecType type) {
return new RtpDepacketizerGeneric(/*generic_header_enabled=*/true); return new RtpDepacketizerGeneric(/*generic_header_enabled=*/true);
} }
} }
} // namespace webrtc } // namespace webrtc

View File

@ -15,6 +15,7 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h" #include "api/array_view.h"
#include "modules/include/module_common_types.h" #include "modules/include/module_common_types.h"
#include "modules/rtp_rtcp/source/rtp_video_header.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. // Reduction len for packet that is first & last at the same time.
int single_packet_reduction_len = 0; int single_packet_reduction_len = 0;
}; };
// If type is not set, returns a raw packetizer.
static std::unique_ptr<RtpPacketizer> Create( static std::unique_ptr<RtpPacketizer> Create(
VideoCodecType type, absl::optional<VideoCodecType> type,
rtc::ArrayView<const uint8_t> payload, rtc::ArrayView<const uint8_t> payload,
PayloadSizeLimits limits, PayloadSizeLimits limits,
// Codec-specific details. // Codec-specific details.
@ -79,7 +82,8 @@ class RtpDepacketizer {
size_t payload_length; size_t payload_length;
}; };
static RtpDepacketizer* Create(VideoCodecType type); // If type is not set, returns a raw depacketizer.
static RtpDepacketizer* Create(absl::optional<VideoCodecType> type);
virtual ~RtpDepacketizer() {} virtual ~RtpDepacketizer() {}

View File

@ -193,7 +193,8 @@ class RtpRtcpImplTest : public ::testing::Test {
codec_.plType = 100; codec_.plType = 100;
codec_.width = 320; codec_.width = 320;
codec_.height = 180; codec_.height = 180;
sender_video_->RegisterPayloadType(codec_.plType, "VP8"); sender_video_->RegisterPayloadType(codec_.plType, "VP8",
/*raw_payload=*/false);
// Receive module. // Receive module.
EXPECT_EQ(0, receiver_.impl_->SetSendingStatus(false)); EXPECT_EQ(0, receiver_.impl_->SetSendingStatus(false));

View File

@ -521,7 +521,8 @@ TEST_P(RtpSenderTestWithoutPacer, OnSendSideDelayUpdated) {
const uint8_t kPayloadType = 127; const uint8_t kPayloadType = 127;
const char payload_name[] = "GENERIC"; 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 const uint32_t kCaptureTimeMsToRtpTimestamp = 90; // 90 kHz clock
RTPVideoHeader video_header; RTPVideoHeader video_header;
@ -1099,7 +1100,8 @@ TEST_P(RtpSenderTestWithoutPacer, SendGenericVideo) {
RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), nullptr, RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), nullptr,
&playout_delay_oracle, nullptr, false, &playout_delay_oracle, nullptr, false,
FieldTrialBasedConfig()); 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}; uint8_t payload[] = {47, 11, 32, 93, 89};
// Send keyframe // Send keyframe
@ -1132,6 +1134,29 @@ TEST_P(RtpSenderTestWithoutPacer, SendGenericVideo) {
EXPECT_THAT(sent_payload.subview(1), ElementsAreArray(payload)); 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) { TEST_P(RtpSenderTest, SendFlexfecPackets) {
constexpr uint32_t kTimestamp = 1234; constexpr uint32_t kTimestamp = 1234;
constexpr int kMediaPayloadType = 127; constexpr int kMediaPayloadType = 127;
@ -1158,7 +1183,8 @@ TEST_P(RtpSenderTest, SendFlexfecPackets) {
RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(),
&flexfec_sender, &playout_delay_oracle, &flexfec_sender, &playout_delay_oracle,
nullptr, false, FieldTrialBasedConfig()); 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. // Parameters selected to generate a single FEC packet per media packet.
FecProtectionParams params; FecProtectionParams params;
@ -1234,7 +1260,8 @@ TEST_P(RtpSenderTest, NoFlexfecForTimingFrames) {
RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(),
&flexfec_sender, &playout_delay_oracle, &flexfec_sender, &playout_delay_oracle,
nullptr, false, FieldTrialBasedConfig()); 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. // Need extension to be registered for timing frames to be sent.
ASSERT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( ASSERT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
@ -1335,7 +1362,8 @@ TEST_P(RtpSenderTestWithoutPacer, SendFlexfecPackets) {
RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(),
&flexfec_sender, &playout_delay_oracle, &flexfec_sender, &playout_delay_oracle,
nullptr, false, FieldTrialBasedConfig()); 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. // Parameters selected to generate a single FEC packet per media packet.
FecProtectionParams params; FecProtectionParams params;
@ -1465,7 +1493,8 @@ TEST_P(RtpSenderTest, FecOverheadRate) {
RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(),
&flexfec_sender, &playout_delay_oracle, &flexfec_sender, &playout_delay_oracle,
nullptr, false, FieldTrialBasedConfig()); 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. // Parameters selected to generate a single FEC packet per media packet.
FecProtectionParams params; FecProtectionParams params;
params.fec_rate = 15; params.fec_rate = 15;
@ -1537,7 +1566,8 @@ TEST_P(RtpSenderTest, BitrateCallbacks) {
FieldTrialBasedConfig()); FieldTrialBasedConfig());
const char payload_name[] = "GENERIC"; const char payload_name[] = "GENERIC";
const uint8_t payload_type = 127; 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 // Simulate kNumPackets sent with kPacketInterval ms intervals, with the
// number of packets selected so that we fill (but don't overflow) the one // 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, RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), nullptr,
&playout_delay_oracle, nullptr, false, &playout_delay_oracle, nullptr, false,
FieldTrialBasedConfig()); 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}; uint8_t payload[] = {47, 11, 32, 93, 89};
rtp_sender_->SetStorePacketsStatus(true, 1); rtp_sender_->SetStorePacketsStatus(true, 1);
uint32_t ssrc = rtp_sender_->SSRC(); uint32_t ssrc = rtp_sender_->SSRC();

View File

@ -24,9 +24,7 @@
#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h" #include "modules/remote_bitrate_estimator/test/bwe_test_logging.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/byte_io.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.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_generic_frame_descriptor_extension.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_header_extensions.h"
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h" #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
@ -224,28 +222,28 @@ RTPSenderVideo::RTPSenderVideo(Clock* clock,
RTPSenderVideo::~RTPSenderVideo() {} RTPSenderVideo::~RTPSenderVideo() {}
void RTPSenderVideo::RegisterPayloadType(int8_t payload_type, void RTPSenderVideo::RegisterPayloadType(int8_t payload_type,
absl::string_view payload_name) { absl::string_view payload_name,
VideoCodecType video_type; bool raw_payload) {
absl::optional<VideoCodecType> video_type;
if (!raw_payload) {
if (absl::EqualsIgnoreCase(payload_name, "VP8")) { if (absl::EqualsIgnoreCase(payload_name, "VP8")) {
video_type = kVideoCodecVP8; video_type = kVideoCodecVP8;
} else if (absl::EqualsIgnoreCase(payload_name, "VP9")) { } else if (absl::EqualsIgnoreCase(payload_name, "VP9")) {
video_type = kVideoCodecVP9; video_type = kVideoCodecVP9;
} else if (absl::EqualsIgnoreCase(payload_name, "H264")) { } else if (absl::EqualsIgnoreCase(payload_name, "H264")) {
video_type = kVideoCodecH264; video_type = kVideoCodecH264;
} else if (absl::EqualsIgnoreCase(payload_name, "I420")) {
video_type = kVideoCodecGeneric;
} else if (absl::EqualsIgnoreCase(payload_name, "stereo")) {
video_type = kVideoCodecGeneric;
} else { } else {
video_type = kVideoCodecGeneric; video_type = kVideoCodecGeneric;
} }
}
{
rtc::CritScope cs(&payload_type_crit_); rtc::CritScope cs(&payload_type_crit_);
payload_type_map_[payload_type] = video_type; payload_type_map_[payload_type] = video_type;
}
// Backward compatibility for older receivers without temporal layer logic // Backward compatibility for older receivers without temporal layer logic
if (video_type == kVideoCodecH264) { if (absl::EqualsIgnoreCase(payload_name, "H264")) {
rtc::CritScope cs(&crit_); rtc::CritScope cs(&crit_);
retransmission_settings_ = kRetransmitBaseLayer | kRetransmitHigherLayers; retransmission_settings_ = kRetransmitBaseLayer | kRetransmitHigherLayers;
} }
@ -613,7 +611,7 @@ bool RTPSenderVideo::SendVideo(VideoFrameType frame_type,
<< "one is required since require_frame_encryptor is set"; << "one is required since require_frame_encryptor is set";
} }
VideoCodecType video_type; absl::optional<VideoCodecType> type;
{ {
rtc::CritScope cs(&payload_type_crit_); rtc::CritScope cs(&payload_type_crit_);
const auto it = payload_type_map_.find(payload_type); const auto it = payload_type_map_.find(payload_type);
@ -622,10 +620,10 @@ bool RTPSenderVideo::SendVideo(VideoFrameType frame_type,
<< " not registered."; << " not registered.";
return false; return false;
} }
video_type = it->second; type = it->second;
} }
std::unique_ptr<RtpPacketizer> packetizer = RtpPacketizer::Create( std::unique_ptr<RtpPacketizer> 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); *packetize_video_header, frame_type, fragmentation);
const uint8_t temporal_id = GetTemporalId(*video_header); const uint8_t temporal_id = GetTemporalId(*video_header);

View File

@ -71,7 +71,9 @@ class RTPSenderVideo {
const RTPVideoHeader* video_header, const RTPVideoHeader* video_header,
int64_t expected_retransmission_time_ms); 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 // 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 // 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. // Maps payload type to codec type, for packetization.
// TODO(nisse): Set on construction, to avoid lock. // TODO(nisse): Set on construction, to avoid lock.
rtc::CriticalSection payload_type_crit_; rtc::CriticalSection payload_type_crit_;
std::map<int8_t, VideoCodecType> payload_type_map_ std::map<int8_t, absl::optional<VideoCodecType>> payload_type_map_
RTC_GUARDED_BY(payload_type_crit_); RTC_GUARDED_BY(payload_type_crit_);
// Should never be held when calling out of this class. // Should never be held when calling out of this class.

View File

@ -163,7 +163,8 @@ class RtpSenderVideoTest : public ::testing::TestWithParam<bool> {
rtp_sender_.SetTimestampOffset(0); rtp_sender_.SetTimestampOffset(0);
rtp_sender_.SetSSRC(kSsrc); rtp_sender_.SetSSRC(kSsrc);
rtp_sender_video_.RegisterPayloadType(kPayload, "generic"); rtp_sender_video_.RegisterPayloadType(kPayload, "generic",
/*raw_payload=*/false);
} }
void PopulateGenericFrameDescriptor(int version); void PopulateGenericFrameDescriptor(int version);
@ -618,7 +619,7 @@ void RtpSenderVideoTest::
vp8.keyIdx = 2; vp8.keyIdx = 2;
RTPVideoHeader::GenericDescriptorInfo& generic = hdr.generic.emplace(); RTPVideoHeader::GenericDescriptorInfo& generic = hdr.generic.emplace();
generic.frame_id = kFrameId; 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, rtp_sender_video_.SendVideo(VideoFrameType::kVideoFrameDelta, kPayload,
kTimestamp, 0, kFrame, sizeof(kFrame), nullptr, kTimestamp, 0, kFrame, sizeof(kFrame), nullptr,
&hdr, kDefaultExpectedRetransmissionTimeMs); &hdr, kDefaultExpectedRetransmissionTimeMs);

View File

@ -193,8 +193,13 @@ RtpVideoStreamReceiver::~RtpVideoStreamReceiver() {
void RtpVideoStreamReceiver::AddReceiveCodec( void RtpVideoStreamReceiver::AddReceiveCodec(
const VideoCodec& video_codec, const VideoCodec& video_codec,
const std::map<std::string, std::string>& codec_params) { const std::map<std::string, std::string>& codec_params,
pt_codec_type_.emplace(video_codec.plType, video_codec.codecType); bool raw_payload) {
absl::optional<VideoCodecType> 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); pt_codec_params_.emplace(video_codec.plType, codec_params);
} }
@ -503,12 +508,12 @@ void RtpVideoStreamReceiver::ReceivePacket(const RtpPacketReceived& packet) {
return; return;
} }
const auto codec_type_it = pt_codec_type_.find(packet.PayloadType()); const auto type_it = payload_type_map_.find(packet.PayloadType());
if (codec_type_it == pt_codec_type_.end()) { if (type_it == payload_type_map_.end()) {
return; return;
} }
auto depacketizer = auto depacketizer =
absl::WrapUnique(RtpDepacketizer::Create(codec_type_it->second)); absl::WrapUnique(RtpDepacketizer::Create(type_it->second));
if (!depacketizer) { if (!depacketizer) {
RTC_LOG(LS_ERROR) << "Failed to create depacketizer."; RTC_LOG(LS_ERROR) << "Failed to create depacketizer.";

View File

@ -82,7 +82,8 @@ class RtpVideoStreamReceiver : public LossNotificationSender,
~RtpVideoStreamReceiver() override; ~RtpVideoStreamReceiver() override;
void AddReceiveCodec(const VideoCodec& video_codec, void AddReceiveCodec(const VideoCodec& video_codec,
const std::map<std::string, std::string>& codec_params); const std::map<std::string, std::string>& codec_params,
bool raw_payload);
void StartReceive(); void StartReceive();
void StopReceive(); void StopReceive();
@ -214,7 +215,9 @@ class RtpVideoStreamReceiver : public LossNotificationSender,
RTC_GUARDED_BY(last_seq_num_cs_); RTC_GUARDED_BY(last_seq_num_cs_);
video_coding::H264SpsPpsTracker tracker_; video_coding::H264SpsPpsTracker tracker_;
std::map<uint8_t, VideoCodecType> pt_codec_type_; // Maps payload type to codec type, for packetization.
std::map<uint8_t, absl::optional<VideoCodecType>> payload_type_map_;
// TODO(johan): Remove pt_codec_params_ once // TODO(johan): Remove pt_codec_params_ once
// https://bugs.chromium.org/p/webrtc/issues/detail?id=6883 is resolved. // 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. // Maps a payload type to a map of out-of-band supplied codec parameters.

View File

@ -278,7 +278,8 @@ TEST_F(RtpVideoStreamReceiverTest, CacheColorSpaceFromLastPacketOfKeyframe) {
codec.plType = kPayloadType; codec.plType = kPayloadType;
codec.codecType = kVideoCodecVP9; codec.codecType = kVideoCodecVP9;
std::map<std::string, std::string> codec_params; std::map<std::string, std::string> 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. // Generate key frame packets.
received_packet_generator.SetPayload(kKeyFramePayload, received_packet_generator.SetPayload(kKeyFramePayload,
@ -345,7 +346,7 @@ TEST_F(RtpVideoStreamReceiverTest, NoInfiniteRecursionOnEncapsulatedRedPacket) {
const uint8_t kRedPayloadType = 125; const uint8_t kRedPayloadType = 125;
VideoCodec codec; VideoCodec codec;
codec.plType = kRedPayloadType; codec.plType = kRedPayloadType;
rtp_video_stream_receiver_->AddReceiveCodec(codec, {}); rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
const std::vector<uint8_t> data({ const std::vector<uint8_t> data({
0x80, // RTP version. 0x80, // RTP version.
kRedPayloadType, // Payload type. kRedPayloadType, // Payload type.
@ -469,7 +470,8 @@ TEST_P(RtpVideoStreamReceiverTestH264, OutOfBandFmtpSpsPps) {
// . // .
codec_params.insert( codec_params.insert(
{cricket::kH264FmtpSpropParameterSets, "Z0IACpZTBYmI,aMljiA=="}); {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, const uint8_t binary_sps[] = {0x67, 0x42, 0x00, 0x0a, 0x96,
0x53, 0x05, 0x89, 0x88}; 0x53, 0x05, 0x89, 0x88};
mock_on_complete_frame_callback_.AppendExpectedBitstream( mock_on_complete_frame_callback_.AppendExpectedBitstream(
@ -683,7 +685,7 @@ TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
VideoCodec codec; VideoCodec codec;
codec.plType = kPayloadType; codec.plType = kPayloadType;
rtp_video_stream_receiver_->AddReceiveCodec(codec, {}); rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
rtp_video_stream_receiver_->StartReceive(); rtp_video_stream_receiver_->StartReceive();
RtpHeaderExtensionMap extension_map; RtpHeaderExtensionMap extension_map;
@ -731,7 +733,7 @@ TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
VideoCodec codec; VideoCodec codec;
codec.plType = kPayloadType; codec.plType = kPayloadType;
rtp_video_stream_receiver_->AddReceiveCodec(codec, {}); rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
rtp_video_stream_receiver_->StartReceive(); rtp_video_stream_receiver_->StartReceive();
RtpHeaderExtensionMap extension_map; RtpHeaderExtensionMap extension_map;
@ -792,7 +794,7 @@ TEST_F(RtpVideoStreamReceiverGenericDescriptorTest,
VideoCodec codec; VideoCodec codec;
codec.plType = kPayloadType; codec.plType = kPayloadType;
rtp_video_stream_receiver_->AddReceiveCodec(codec, {}); rtp_video_stream_receiver_->AddReceiveCodec(codec, {}, /*raw_payload=*/false);
rtp_video_stream_receiver_->StartReceive(); rtp_video_stream_receiver_->StartReceive();
RtpHeaderExtensionMap extension_map; RtpHeaderExtensionMap extension_map;
@ -824,6 +826,41 @@ TEST_F(RtpVideoStreamReceiverGenericDescriptorTest,
rtp_video_stream_receiver_->OnRtpPacket(rtp_packet); rtp_video_stream_receiver_->OnRtpPacket(rtp_packet);
} }
TEST_P(RtpVideoStreamReceiverGenericDescriptorTest,
ParseGenericDescriptorRawPayload) {
const int version = GetParam();
const std::vector<uint8_t> 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) #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
TEST_F(RtpVideoStreamReceiverTest, RepeatedSecondarySinkDisallowed) { TEST_F(RtpVideoStreamReceiverTest, RepeatedSecondarySinkDisallowed) {
MockRtpPacketSink secondary_sink; MockRtpPacketSink secondary_sink;

View File

@ -367,8 +367,11 @@ void VideoReceiveStream::Start() {
video_receiver_.RegisterExternalDecoder(video_decoders_.back().get(), video_receiver_.RegisterExternalDecoder(video_decoders_.back().get(),
decoder.payload_type); decoder.payload_type);
VideoCodec codec = CreateDecoderVideoCodec(decoder); 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( RTC_CHECK_EQ(VCM_OK, video_receiver_.RegisterReceiveCodec(
&codec, num_cpu_cores_, false)); &codec, num_cpu_cores_, false));
} }