Move rtp header extension length check from Packet::FindExtension to ExtensionT::Parse
to allow to read variable-length extensions. BUG=webrtc:7433 Review-Url: https://codereview.webrtc.org/2801733002 Cr-Commit-Position: refs/heads/master@{#17554}
This commit is contained in:
@ -35,8 +35,11 @@ constexpr RTPExtensionType AbsoluteSendTime::kId;
|
||||
constexpr uint8_t AbsoluteSendTime::kValueSizeBytes;
|
||||
constexpr const char* AbsoluteSendTime::kUri;
|
||||
|
||||
bool AbsoluteSendTime::Parse(const uint8_t* data, uint32_t* time_24bits) {
|
||||
*time_24bits = ByteReader<uint32_t, 3>::ReadBigEndian(data);
|
||||
bool AbsoluteSendTime::Parse(rtc::ArrayView<const uint8_t> data,
|
||||
uint32_t* time_24bits) {
|
||||
if (data.size() != 3)
|
||||
return false;
|
||||
*time_24bits = ByteReader<uint32_t, 3>::ReadBigEndian(data.data());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -61,9 +64,11 @@ constexpr RTPExtensionType AudioLevel::kId;
|
||||
constexpr uint8_t AudioLevel::kValueSizeBytes;
|
||||
constexpr const char* AudioLevel::kUri;
|
||||
|
||||
bool AudioLevel::Parse(const uint8_t* data,
|
||||
bool AudioLevel::Parse(rtc::ArrayView<const uint8_t> data,
|
||||
bool* voice_activity,
|
||||
uint8_t* audio_level) {
|
||||
if (data.size() != 1)
|
||||
return false;
|
||||
*voice_activity = (data[0] & 0x80) != 0;
|
||||
*audio_level = data[0] & 0x7F;
|
||||
return true;
|
||||
@ -97,8 +102,11 @@ constexpr RTPExtensionType TransmissionOffset::kId;
|
||||
constexpr uint8_t TransmissionOffset::kValueSizeBytes;
|
||||
constexpr const char* TransmissionOffset::kUri;
|
||||
|
||||
bool TransmissionOffset::Parse(const uint8_t* data, int32_t* rtp_time) {
|
||||
*rtp_time = ByteReader<int32_t, 3>::ReadBigEndian(data);
|
||||
bool TransmissionOffset::Parse(rtc::ArrayView<const uint8_t> data,
|
||||
int32_t* rtp_time) {
|
||||
if (data.size() != 3)
|
||||
return false;
|
||||
*rtp_time = ByteReader<int32_t, 3>::ReadBigEndian(data.data());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -117,8 +125,11 @@ constexpr RTPExtensionType TransportSequenceNumber::kId;
|
||||
constexpr uint8_t TransportSequenceNumber::kValueSizeBytes;
|
||||
constexpr const char* TransportSequenceNumber::kUri;
|
||||
|
||||
bool TransportSequenceNumber::Parse(const uint8_t* data, uint16_t* value) {
|
||||
*value = ByteReader<uint16_t>::ReadBigEndian(data);
|
||||
bool TransportSequenceNumber::Parse(rtc::ArrayView<const uint8_t> data,
|
||||
uint16_t* value) {
|
||||
if (data.size() != 2)
|
||||
return false;
|
||||
*value = ByteReader<uint16_t>::ReadBigEndian(data.data());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -142,7 +153,10 @@ constexpr RTPExtensionType VideoOrientation::kId;
|
||||
constexpr uint8_t VideoOrientation::kValueSizeBytes;
|
||||
constexpr const char* VideoOrientation::kUri;
|
||||
|
||||
bool VideoOrientation::Parse(const uint8_t* data, VideoRotation* rotation) {
|
||||
bool VideoOrientation::Parse(rtc::ArrayView<const uint8_t> data,
|
||||
VideoRotation* rotation) {
|
||||
if (data.size() != 1)
|
||||
return false;
|
||||
*rotation = ConvertCVOByteToVideoRotation(data[0]);
|
||||
return true;
|
||||
}
|
||||
@ -152,7 +166,10 @@ bool VideoOrientation::Write(uint8_t* data, VideoRotation rotation) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VideoOrientation::Parse(const uint8_t* data, uint8_t* value) {
|
||||
bool VideoOrientation::Parse(rtc::ArrayView<const uint8_t> data,
|
||||
uint8_t* value) {
|
||||
if (data.size() != 1)
|
||||
return false;
|
||||
*value = data[0];
|
||||
return true;
|
||||
}
|
||||
@ -171,10 +188,12 @@ constexpr RTPExtensionType PlayoutDelayLimits::kId;
|
||||
constexpr uint8_t PlayoutDelayLimits::kValueSizeBytes;
|
||||
constexpr const char* PlayoutDelayLimits::kUri;
|
||||
|
||||
bool PlayoutDelayLimits::Parse(const uint8_t* data,
|
||||
bool PlayoutDelayLimits::Parse(rtc::ArrayView<const uint8_t> data,
|
||||
PlayoutDelay* playout_delay) {
|
||||
RTC_DCHECK(playout_delay);
|
||||
uint32_t raw = ByteReader<uint32_t, 3>::ReadBigEndian(data);
|
||||
if (data.size() != 3)
|
||||
return false;
|
||||
uint32_t raw = ByteReader<uint32_t, 3>::ReadBigEndian(data.data());
|
||||
uint16_t min_raw = (raw >> 12);
|
||||
uint16_t max_raw = (raw & 0xfff);
|
||||
if (min_raw > max_raw)
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "webrtc/api/video/video_rotation.h"
|
||||
#include "webrtc/base/array_view.h"
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -24,7 +25,7 @@ class AbsoluteSendTime {
|
||||
static constexpr const char* kUri =
|
||||
"http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
|
||||
|
||||
static bool Parse(const uint8_t* data, uint32_t* time_24bits);
|
||||
static bool Parse(rtc::ArrayView<const uint8_t> data, uint32_t* time_24bits);
|
||||
static bool Write(uint8_t* data, int64_t time_ms);
|
||||
|
||||
static constexpr uint32_t MsTo24Bits(int64_t time_ms) {
|
||||
@ -39,7 +40,7 @@ class AudioLevel {
|
||||
static constexpr const char* kUri =
|
||||
"urn:ietf:params:rtp-hdrext:ssrc-audio-level";
|
||||
|
||||
static bool Parse(const uint8_t* data,
|
||||
static bool Parse(rtc::ArrayView<const uint8_t> data,
|
||||
bool* voice_activity,
|
||||
uint8_t* audio_level);
|
||||
static bool Write(uint8_t* data, bool voice_activity, uint8_t audio_level);
|
||||
@ -51,7 +52,7 @@ class TransmissionOffset {
|
||||
static constexpr uint8_t kValueSizeBytes = 3;
|
||||
static constexpr const char* kUri = "urn:ietf:params:rtp-hdrext:toffset";
|
||||
|
||||
static bool Parse(const uint8_t* data, int32_t* rtp_time);
|
||||
static bool Parse(rtc::ArrayView<const uint8_t> data, int32_t* rtp_time);
|
||||
static bool Write(uint8_t* data, int32_t rtp_time);
|
||||
};
|
||||
|
||||
@ -62,7 +63,7 @@ class TransportSequenceNumber {
|
||||
static constexpr const char* kUri =
|
||||
"http://www.ietf.org/id/"
|
||||
"draft-holmer-rmcat-transport-wide-cc-extensions-01";
|
||||
static bool Parse(const uint8_t* data, uint16_t* value);
|
||||
static bool Parse(rtc::ArrayView<const uint8_t> data, uint16_t* value);
|
||||
static bool Write(uint8_t* data, uint16_t value);
|
||||
};
|
||||
|
||||
@ -72,9 +73,9 @@ class VideoOrientation {
|
||||
static constexpr uint8_t kValueSizeBytes = 1;
|
||||
static constexpr const char* kUri = "urn:3gpp:video-orientation";
|
||||
|
||||
static bool Parse(const uint8_t* data, VideoRotation* value);
|
||||
static bool Parse(rtc::ArrayView<const uint8_t> data, VideoRotation* value);
|
||||
static bool Write(uint8_t* data, VideoRotation value);
|
||||
static bool Parse(const uint8_t* data, uint8_t* value);
|
||||
static bool Parse(rtc::ArrayView<const uint8_t> data, uint8_t* value);
|
||||
static bool Write(uint8_t* data, uint8_t value);
|
||||
};
|
||||
|
||||
@ -92,7 +93,8 @@ class PlayoutDelayLimits {
|
||||
// Maximum playout delay value in milliseconds.
|
||||
static constexpr int kMaxMs = 0xfff * kGranularityMs; // 40950.
|
||||
|
||||
static bool Parse(const uint8_t* data, PlayoutDelay* playout_delay);
|
||||
static bool Parse(rtc::ArrayView<const uint8_t> data,
|
||||
PlayoutDelay* playout_delay);
|
||||
static bool Write(uint8_t* data, const PlayoutDelay& playout_delay);
|
||||
};
|
||||
|
||||
|
||||
@ -533,27 +533,17 @@ bool Packet::ParseBuffer(const uint8_t* buffer, size_t size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Packet::FindExtension(ExtensionType type,
|
||||
uint8_t length,
|
||||
uint16_t* offset) const {
|
||||
RTC_DCHECK(offset);
|
||||
rtc::ArrayView<const uint8_t> Packet::FindExtension(ExtensionType type) const {
|
||||
for (const ExtensionInfo& extension : extension_entries_) {
|
||||
if (extension.type == type) {
|
||||
if (extension.length == 0) {
|
||||
// Extension is registered but not set.
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
if (length != extension.length) {
|
||||
LOG(LS_WARNING) << "Length mismatch for extension '" << type
|
||||
<< "': expected " << static_cast<int>(length)
|
||||
<< ", received " << static_cast<int>(extension.length);
|
||||
return false;
|
||||
}
|
||||
*offset = extension.offset;
|
||||
return true;
|
||||
return rtc::MakeArrayView(data() + extension.offset, extension.length);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rtc::ArrayView<uint8_t> Packet::AllocateExtension(ExtensionType type,
|
||||
|
||||
@ -142,13 +142,9 @@ class Packet {
|
||||
// but does not touch packet own buffer, leaving packet in invalid state.
|
||||
bool ParseBuffer(const uint8_t* buffer, size_t size);
|
||||
|
||||
// Find an extension based on the type field of the parameter.
|
||||
// If found, length field would be validated, the offset field will be set
|
||||
// and true returned,
|
||||
// otherwise the parameter will be unchanged and false is returned.
|
||||
bool FindExtension(ExtensionType type,
|
||||
uint8_t length,
|
||||
uint16_t* offset) const;
|
||||
// Find an extension |type|.
|
||||
// Returns view of the raw extension or empty view on failure.
|
||||
rtc::ArrayView<const uint8_t> FindExtension(ExtensionType type) const;
|
||||
|
||||
// Find or allocate an extension |type|. Returns view of size |length|
|
||||
// to write raw extension to or an empty view on failure.
|
||||
@ -174,16 +170,15 @@ class Packet {
|
||||
|
||||
template <typename Extension>
|
||||
bool Packet::HasExtension() const {
|
||||
uint16_t offset = 0;
|
||||
return FindExtension(Extension::kId, Extension::kValueSizeBytes, &offset);
|
||||
return !FindExtension(Extension::kId).empty();
|
||||
}
|
||||
|
||||
template <typename Extension, typename... Values>
|
||||
bool Packet::GetExtension(Values... values) const {
|
||||
uint16_t offset = 0;
|
||||
if (!FindExtension(Extension::kId, Extension::kValueSizeBytes, &offset))
|
||||
auto raw = FindExtension(Extension::kId);
|
||||
if (raw.empty())
|
||||
return false;
|
||||
return Extension::Parse(data() + offset, values...);
|
||||
return Extension::Parse(raw, values...);
|
||||
}
|
||||
|
||||
template <typename Extension, typename... Values>
|
||||
|
||||
@ -358,7 +358,7 @@ TEST(RtpPacketTest, ParseWithoutExtensionManager) {
|
||||
int32_t time_offset = 0;
|
||||
auto raw_extension = packet.GetRawExtension(kTransmissionOffsetExtensionId);
|
||||
EXPECT_EQ(raw_extension.size(), TransmissionOffset::kValueSizeBytes);
|
||||
EXPECT_TRUE(TransmissionOffset::Parse(raw_extension.data(), &time_offset));
|
||||
EXPECT_TRUE(TransmissionOffset::Parse(raw_extension, &time_offset));
|
||||
|
||||
EXPECT_EQ(time_offset, kTimeOffset);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user