From e6b16194c7a28c46a5309a4ab17803a104b7c88d Mon Sep 17 00:00:00 2001 From: erikvarga Date: Thu, 11 May 2017 02:36:32 -0700 Subject: [PATCH] Add write support for the RtpStreamId and RepairedRtpStreamId header extensions. BUG=webrtc:7433 Review-Url: https://codereview.webrtc.org/2871813003 Cr-Commit-Position: refs/heads/master@{#18093} --- .../rtp_rtcp/source/rtp_header_extensions.cc | 30 ++++++++++++++ .../rtp_rtcp/source/rtp_header_extensions.h | 32 +++++++++++++-- webrtc/modules/rtp_rtcp/source/rtp_packet.h | 5 ++- .../rtp_rtcp/source/rtp_packet_unittest.cc | 40 +++++++++++++++++++ 4 files changed, 102 insertions(+), 5 deletions(-) diff --git a/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.cc b/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.cc index 13f488b09a..ba512ef349 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.cc @@ -257,6 +257,13 @@ bool RtpStreamId::Parse(rtc::ArrayView data, StreamId* rsid) { return true; } +bool RtpStreamId::Write(uint8_t* data, const StreamId& rsid) { + RTC_DCHECK_GE(rsid.size(), 1); + RTC_DCHECK_LE(rsid.size(), StreamId::kMaxSize); + memcpy(data, rsid.data(), rsid.size()); + return true; +} + bool RtpStreamId::Parse(rtc::ArrayView data, std::string* rsid) { if (data.empty() || data[0] == 0) // Valid rsid can't be empty. return false; @@ -268,6 +275,13 @@ bool RtpStreamId::Parse(rtc::ArrayView data, std::string* rsid) { return true; } +bool RtpStreamId::Write(uint8_t* data, const std::string& rsid) { + RTC_DCHECK_GE(rsid.size(), 1); + RTC_DCHECK_LE(rsid.size(), StreamId::kMaxSize); + memcpy(data, rsid.data(), rsid.size()); + return true; +} + // RepairedRtpStreamId. constexpr RTPExtensionType RepairedRtpStreamId::kId; constexpr uint8_t RepairedRtpStreamId::kValueSizeBytes; @@ -279,9 +293,25 @@ bool RepairedRtpStreamId::Parse(rtc::ArrayView data, return RtpStreamId::Parse(data, rsid); } +size_t RepairedRtpStreamId::ValueSize(const StreamId& rsid) { + return RtpStreamId::ValueSize(rsid); +} + +bool RepairedRtpStreamId::Write(uint8_t* data, const StreamId& rsid) { + return RtpStreamId::Write(data, rsid); +} + bool RepairedRtpStreamId::Parse(rtc::ArrayView data, std::string* rsid) { return RtpStreamId::Parse(data, rsid); } +size_t RepairedRtpStreamId::ValueSize(const std::string& rsid) { + return RtpStreamId::ValueSize(rsid); +} + +bool RepairedRtpStreamId::Write(uint8_t* data, const std::string& rsid) { + return RtpStreamId::Write(data, rsid); +} + } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h b/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h index c60f29050d..df68b21735 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h @@ -28,6 +28,7 @@ class AbsoluteSendTime { "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time"; static bool Parse(rtc::ArrayView data, uint32_t* time_24bits); + static size_t ValueSize(int64_t time_ms) { return kValueSizeBytes; } static bool Write(uint8_t* data, int64_t time_ms); static constexpr uint32_t MsTo24Bits(int64_t time_ms) { @@ -45,6 +46,9 @@ class AudioLevel { static bool Parse(rtc::ArrayView data, bool* voice_activity, uint8_t* audio_level); + static size_t ValueSize(bool voice_activity, uint8_t audio_level) { + return kValueSizeBytes; + } static bool Write(uint8_t* data, bool voice_activity, uint8_t audio_level); }; @@ -55,6 +59,7 @@ class TransmissionOffset { static constexpr const char* kUri = "urn:ietf:params:rtp-hdrext:toffset"; static bool Parse(rtc::ArrayView data, int32_t* rtp_time); + static size_t ValueSize(int32_t rtp_time) { return kValueSizeBytes; } static bool Write(uint8_t* data, int32_t rtp_time); }; @@ -66,6 +71,7 @@ class TransportSequenceNumber { "http://www.ietf.org/id/" "draft-holmer-rmcat-transport-wide-cc-extensions-01"; static bool Parse(rtc::ArrayView data, uint16_t* value); + static size_t ValueSize(uint16_t value) { return kValueSizeBytes; } static bool Write(uint8_t* data, uint16_t value); }; @@ -76,8 +82,10 @@ class VideoOrientation { static constexpr const char* kUri = "urn:3gpp:video-orientation"; static bool Parse(rtc::ArrayView data, VideoRotation* value); + static size_t ValueSize(VideoRotation) { return kValueSizeBytes; } static bool Write(uint8_t* data, VideoRotation value); static bool Parse(rtc::ArrayView data, uint8_t* value); + static size_t ValueSize(uint8_t value) { return kValueSizeBytes; } static bool Write(uint8_t* data, uint8_t value); }; @@ -97,6 +105,9 @@ class PlayoutDelayLimits { static bool Parse(rtc::ArrayView data, PlayoutDelay* playout_delay); + static size_t ValueSize(const PlayoutDelay&) { + return kValueSizeBytes; + } static bool Write(uint8_t* data, const PlayoutDelay& playout_delay); }; @@ -109,6 +120,9 @@ class VideoContentTypeExtension { static bool Parse(rtc::ArrayView data, VideoContentType* content_type); + static size_t ValueSize(VideoContentType) { + return kValueSizeBytes; + } static bool Write(uint8_t* data, VideoContentType content_type); }; @@ -121,8 +135,13 @@ class RtpStreamId { static constexpr const char* kUri = "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id"; - static bool Parse(rtc::ArrayView data, StreamId* rid); - static bool Parse(rtc::ArrayView data, std::string* rid); + static bool Parse(rtc::ArrayView data, StreamId* rsid); + static size_t ValueSize(const StreamId& rsid) { return rsid.size(); } + static bool Write(uint8_t* data, const StreamId& rsid); + + static bool Parse(rtc::ArrayView data, std::string* rsid); + static size_t ValueSize(const std::string& rsid) { return rsid.size(); } + static bool Write(uint8_t* data, const std::string& rsid); }; class RepairedRtpStreamId { @@ -134,8 +153,13 @@ class RepairedRtpStreamId { static constexpr const char* kUri = "urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id"; - static bool Parse(rtc::ArrayView data, StreamId* rid); - static bool Parse(rtc::ArrayView data, std::string* rid); + static bool Parse(rtc::ArrayView data, StreamId* rsid); + static size_t ValueSize(const StreamId& rsid); + static bool Write(uint8_t* data, const StreamId& rsid); + + static bool Parse(rtc::ArrayView data, std::string* rsid); + static size_t ValueSize(const std::string& rsid); + static bool Write(uint8_t* data, const std::string& rsid); }; } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtp_packet.h b/webrtc/modules/rtp_rtcp/source/rtp_packet.h index ca189dbe0d..0901fc2506 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_packet.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_packet.h @@ -183,7 +183,10 @@ bool Packet::GetExtension(Values... values) const { template bool Packet::SetExtension(Values... values) { - auto buffer = AllocateExtension(Extension::kId, Extension::kValueSizeBytes); + const size_t value_size = Extension::ValueSize(values...); + if (value_size == 0 || value_size > 16) + return false; + auto buffer = AllocateExtension(Extension::kId, value_size); if (buffer.empty()) return false; return Extension::Write(buffer.data(), values...); diff --git a/webrtc/modules/rtp_rtcp/source/rtp_packet_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_packet_unittest.cc index bbe40808ae..001f06f39f 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_packet_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_packet_unittest.cc @@ -28,15 +28,18 @@ constexpr uint16_t kSeqNum = 88; constexpr uint32_t kTimestamp = 0x65431278; constexpr uint8_t kTransmissionOffsetExtensionId = 1; constexpr uint8_t kAudioLevelExtensionId = 9; +constexpr uint8_t kRtpStreamIdExtensionId = 0xa; constexpr int32_t kTimeOffset = 0x56ce; constexpr bool kVoiceActive = true; constexpr uint8_t kAudioLevel = 0x5a; +constexpr char kStreamId[] = "streamid"; constexpr size_t kMaxPaddingSize = 224u; // clang-format off constexpr uint8_t kMinimumPacket[] = { 0x80, kPayloadType, 0x00, kSeqNum, 0x65, 0x43, 0x12, 0x78, 0x12, 0x34, 0x56, 0x78}; + constexpr uint8_t kPacketWithTO[] = { 0x90, kPayloadType, 0x00, kSeqNum, 0x65, 0x43, 0x12, 0x78, @@ -52,6 +55,15 @@ constexpr uint8_t kPacketWithTOAndAL[] = { 0x12, 0x00, 0x56, 0xce, 0x90, 0x80|kAudioLevel, 0x00, 0x00}; +constexpr uint8_t kPacketWithRsid[] = { + 0x90, kPayloadType, 0x00, kSeqNum, + 0x65, 0x43, 0x12, 0x78, + 0x12, 0x34, 0x56, 0x78, + 0xbe, 0xde, 0x00, 0x03, + 0xa7, 's', 't', 'r', + 'e', 'a', 'm', 'i', + 'd' , 0x00, 0x00, 0x00}; + constexpr uint32_t kCsrcs[] = {0x34567890, 0x32435465}; constexpr uint8_t kPayload[] = {'p', 'a', 'y', 'l', 'o', 'a', 'd'}; constexpr uint8_t kPacketPaddingSize = 8; @@ -117,6 +129,34 @@ TEST(RtpPacketTest, CreateWith2Extensions) { ElementsAreArray(packet.data(), packet.size())); } +TEST(RtpPacketTest, CreateWithDynamicSizedExtensions) { + RtpPacketToSend::ExtensionManager extensions; + extensions.Register(kRtpStreamIdExtensionId); + RtpPacketToSend packet(&extensions); + packet.SetPayloadType(kPayloadType); + packet.SetSequenceNumber(kSeqNum); + packet.SetTimestamp(kTimestamp); + packet.SetSsrc(kSsrc); + packet.SetExtension(kStreamId); + EXPECT_THAT(kPacketWithRsid, ElementsAreArray(packet.data(), packet.size())); +} + +TEST(RtpPacketTest, TryToCreateWithEmptyRsid) { + RtpPacketToSend::ExtensionManager extensions; + extensions.Register(kRtpStreamIdExtensionId); + RtpPacketToSend packet(&extensions); + EXPECT_FALSE(packet.SetExtension("")); +} + +TEST(RtpPacketTest, TryToCreateWithLongRsid) { + RtpPacketToSend::ExtensionManager extensions; + constexpr char kLongStreamId[] = "LoooooooooongRsid"; + ASSERT_EQ(strlen(kLongStreamId), 17u); + extensions.Register(kRtpStreamIdExtensionId); + RtpPacketToSend packet(&extensions); + EXPECT_FALSE(packet.SetExtension(kLongStreamId)); +} + TEST(RtpPacketTest, CreateWithExtensionsWithoutManager) { RtpPacketToSend packet(nullptr); packet.SetPayloadType(kPayloadType);