Add the option to use raw RTP packetization without the generic header.
Bug: webrtc:10625
Change-Id: I198031154dbb706ae1e7c15bd34a3bdf93d1a51a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/136923
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Commit-Queue: Mirta Dvornicic <mirtad@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27964}
diff --git a/modules/rtp_rtcp/source/rtp_format.cc b/modules/rtp_rtcp/source/rtp_format.cc
index 7375a63..843cbb8 100644
--- a/modules/rtp_rtcp/source/rtp_format.cc
+++ b/modules/rtp_rtcp/source/rtp_format.cc
@@ -142,7 +142,7 @@
case kVideoCodecVP9:
return new RtpDepacketizerVp9();
default:
- return new RtpDepacketizerGeneric();
+ return new RtpDepacketizerGeneric(/*generic_header_enabled=*/true);
}
}
} // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_format_video_generic.cc b/modules/rtp_rtcp/source/rtp_format_video_generic.cc
index 171c5ff..a45597d 100644
--- a/modules/rtp_rtcp/source/rtp_format_video_generic.cc
+++ b/modules/rtp_rtcp/source/rtp_format_video_generic.cc
@@ -35,6 +35,14 @@
current_packet_ = payload_sizes_.begin();
}
+RtpPacketizerGeneric::RtpPacketizerGeneric(
+ rtc::ArrayView<const uint8_t> payload,
+ PayloadSizeLimits limits)
+ : header_size_(0), remaining_payload_(payload) {
+ payload_sizes_ = SplitAboutEqually(payload.size(), limits);
+ current_packet_ = payload_sizes_.begin();
+}
+
RtpPacketizerGeneric::~RtpPacketizerGeneric() = default;
size_t RtpPacketizerGeneric::NumPackets() const {
@@ -52,13 +60,15 @@
packet->AllocatePayload(header_size_ + next_packet_payload_len);
RTC_CHECK(out_ptr);
- memcpy(out_ptr, header_, header_size_);
+ if (header_size_ > 0) {
+ memcpy(out_ptr, header_, header_size_);
+ // Remove first-packet bit, following packets are intermediate.
+ header_[0] &= ~RtpFormatVideoGeneric::kFirstPacketBit;
+ }
+
memcpy(out_ptr + header_size_, remaining_payload_.data(),
next_packet_payload_len);
- // Remove first-packet bit, following packets are intermediate.
- header_[0] &= ~RtpFormatVideoGeneric::kFirstPacketBit;
-
remaining_payload_ = remaining_payload_.subview(next_packet_payload_len);
++current_packet_;
@@ -79,7 +89,7 @@
header_[0] |= RtpFormatVideoGeneric::kKeyFrameBit;
}
if (rtp_video_header.generic.has_value()) {
- // Store bottom 15 bits of the the picture id. Only 15 bits are used for
+ // Store bottom 15 bits of the picture id. Only 15 bits are used for
// compatibility with other packetizer implemenetations.
uint16_t picture_id = rtp_video_header.generic->frame_id & 0x7FFF;
header_[0] |= RtpFormatVideoGeneric::kExtendedHeaderBit;
@@ -89,6 +99,9 @@
}
}
+RtpDepacketizerGeneric::RtpDepacketizerGeneric(bool generic_header_enabled)
+ : generic_header_enabled_(generic_header_enabled) {}
+
RtpDepacketizerGeneric::~RtpDepacketizerGeneric() = default;
bool RtpDepacketizerGeneric::Parse(ParsedPayload* parsed_payload,
@@ -100,29 +113,31 @@
return false;
}
- uint8_t generic_header = *payload_data++;
- --payload_data_length;
+ if (generic_header_enabled_) {
+ uint8_t generic_header = *payload_data++;
+ --payload_data_length;
- parsed_payload->video_header().frame_type =
- ((generic_header & RtpFormatVideoGeneric::kKeyFrameBit) != 0)
- ? VideoFrameType::kVideoFrameKey
- : VideoFrameType::kVideoFrameDelta;
- parsed_payload->video_header().is_first_packet_in_frame =
- (generic_header & RtpFormatVideoGeneric::kFirstPacketBit) != 0;
- parsed_payload->video_header().codec = kVideoCodecGeneric;
- parsed_payload->video_header().width = 0;
- parsed_payload->video_header().height = 0;
+ parsed_payload->video_header().frame_type =
+ ((generic_header & RtpFormatVideoGeneric::kKeyFrameBit) != 0)
+ ? VideoFrameType::kVideoFrameKey
+ : VideoFrameType::kVideoFrameDelta;
+ parsed_payload->video_header().is_first_packet_in_frame =
+ (generic_header & RtpFormatVideoGeneric::kFirstPacketBit) != 0;
+ parsed_payload->video_header().codec = kVideoCodecGeneric;
+ parsed_payload->video_header().width = 0;
+ parsed_payload->video_header().height = 0;
- if (generic_header & RtpFormatVideoGeneric::kExtendedHeaderBit) {
- if (payload_data_length < kExtendedHeaderLength) {
- RTC_LOG(LS_WARNING) << "Too short payload for generic header.";
- return false;
+ if (generic_header & RtpFormatVideoGeneric::kExtendedHeaderBit) {
+ if (payload_data_length < kExtendedHeaderLength) {
+ RTC_LOG(LS_WARNING) << "Too short payload for generic header.";
+ return false;
+ }
+ parsed_payload->video_header().generic.emplace();
+ parsed_payload->video_header().generic->frame_id =
+ ((payload_data[0] & 0x7F) << 8) | payload_data[1];
+ payload_data += kExtendedHeaderLength;
+ payload_data_length -= kExtendedHeaderLength;
}
- parsed_payload->video_header().generic.emplace();
- parsed_payload->video_header().generic->frame_id =
- ((payload_data[0] & 0x7F) << 8) | payload_data[1];
- payload_data += kExtendedHeaderLength;
- payload_data_length -= kExtendedHeaderLength;
}
parsed_payload->payload = payload_data;
diff --git a/modules/rtp_rtcp/source/rtp_format_video_generic.h b/modules/rtp_rtcp/source/rtp_format_video_generic.h
index 6406b74..4e21c96 100644
--- a/modules/rtp_rtcp/source/rtp_format_video_generic.h
+++ b/modules/rtp_rtcp/source/rtp_format_video_generic.h
@@ -34,16 +34,23 @@
public:
// Initialize with payload from encoder.
// The payload_data must be exactly one encoded generic frame.
+ // Packets returned by |NextPacket| will contain the generic payload header.
RtpPacketizerGeneric(rtc::ArrayView<const uint8_t> payload,
PayloadSizeLimits limits,
const RTPVideoHeader& rtp_video_header,
VideoFrameType frametype);
+ // Initialize with payload from encoder.
+ // The payload_data must be exactly one encoded generic frame.
+ // Packets returned by |NextPacket| will contain raw payload without the
+ // generic payload header.
+ RtpPacketizerGeneric(rtc::ArrayView<const uint8_t> payload,
+ PayloadSizeLimits limits);
~RtpPacketizerGeneric() override;
size_t NumPackets() const override;
- // Get the next payload with generic payload header.
+ // Get the next payload.
// Write payload and set marker bit of the |packet|.
// Returns true on success, false otherwise.
bool NextPacket(RtpPacketToSend* packet) override;
@@ -65,11 +72,17 @@
// Depacketizer for generic codec.
class RtpDepacketizerGeneric : public RtpDepacketizer {
public:
+ // Parses the generic payload header if |generic_header_enabled| is true,
+ // returns raw payload otherwise.
+ explicit RtpDepacketizerGeneric(bool generic_header_enabled);
~RtpDepacketizerGeneric() override;
bool Parse(ParsedPayload* parsed_payload,
const uint8_t* payload_data,
size_t payload_data_length) override;
+
+ private:
+ bool generic_header_enabled_;
};
} // namespace webrtc
#endif // MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VIDEO_GENERIC_H_
diff --git a/modules/rtp_rtcp/source/rtp_format_video_generic_unittest.cc b/modules/rtp_rtcp/source/rtp_format_video_generic_unittest.cc
index fa274dd..d43af77 100644
--- a/modules/rtp_rtcp/source/rtp_format_video_generic_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_format_video_generic_unittest.cc
@@ -158,11 +158,23 @@
EXPECT_FALSE(payload[0] & 0x04);
}
+TEST(RtpPacketizerVideoGeneric, DoesNotWriteHeaderForRawPayload) {
+ const uint8_t kPayload[] = {0x05, 0x25, 0x52};
+
+ RtpPacketizerGeneric packetizer(kPayload, kNoSizeLimits);
+
+ RtpPacketToSend packet(nullptr);
+ ASSERT_TRUE(packetizer.NextPacket(&packet));
+
+ rtc::ArrayView<const uint8_t> payload = packet.payload();
+ EXPECT_THAT(payload, ElementsAreArray(kPayload));
+}
+
TEST(RtpDepacketizerVideoGeneric, NonExtendedHeaderNoFrameId) {
const size_t kPayloadLen = 1;
uint8_t payload[kPayloadLen] = {0x01};
- RtpDepacketizerGeneric depacketizer;
+ RtpDepacketizerGeneric depacketizer(/*generic_header_enabled=*/true);
RtpDepacketizer::ParsedPayload parsed_payload;
depacketizer.Parse(&parsed_payload, payload, kPayloadLen);
@@ -173,7 +185,7 @@
const size_t kPayloadLen = 3;
uint8_t payload[kPayloadLen] = {0x05, 0x13, 0x37};
- RtpDepacketizerGeneric depacketizer;
+ RtpDepacketizerGeneric depacketizer(/*generic_header_enabled=*/true);
RtpDepacketizer::ParsedPayload parsed_payload;
depacketizer.Parse(&parsed_payload, payload, kPayloadLen);
@@ -181,5 +193,19 @@
EXPECT_EQ(0x1337, parsed_payload.video_header().generic->frame_id);
}
+TEST(RtpDepacketizerVideoGeneric, DoesNotParseHeaderForRawPayload) {
+ const uint8_t kPayload[] = {0x05, 0x25, 0x52};
+ const size_t kPayloadLen = sizeof(kPayload);
+
+ RtpDepacketizerGeneric depacketizer(/*generic_header_enabled=*/false);
+ RtpDepacketizer::ParsedPayload parsed_payload;
+ depacketizer.Parse(&parsed_payload, kPayload, kPayloadLen);
+
+ EXPECT_FALSE(parsed_payload.video_header().generic);
+ EXPECT_THAT(rtc::MakeArrayView<const uint8_t>(parsed_payload.payload,
+ parsed_payload.payload_length),
+ ElementsAreArray(kPayload));
+}
+
} // namespace
} // namespace webrtc
diff --git a/test/fuzzers/generic_depacketizer_fuzzer.cc b/test/fuzzers/generic_depacketizer_fuzzer.cc
index 4775501..6b98b41 100644
--- a/test/fuzzers/generic_depacketizer_fuzzer.cc
+++ b/test/fuzzers/generic_depacketizer_fuzzer.cc
@@ -14,7 +14,7 @@
namespace webrtc {
void FuzzOneInput(const uint8_t* data, size_t size) {
- RtpDepacketizerGeneric depacketizer;
+ RtpDepacketizerGeneric depacketizer(/*generic_header_enabled=*/true);
RtpDepacketizer::ParsedPayload parsed_payload;
depacketizer.Parse(&parsed_payload, data, size);
}