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}
This commit is contained in:
parent
67c76b214d
commit
a24d934ee4
@ -142,7 +142,7 @@ RtpDepacketizer* RtpDepacketizer::Create(VideoCodecType type) {
|
||||
case kVideoCodecVP9:
|
||||
return new RtpDepacketizerVp9();
|
||||
default:
|
||||
return new RtpDepacketizerGeneric();
|
||||
return new RtpDepacketizerGeneric(/*generic_header_enabled=*/true);
|
||||
}
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
||||
@ -35,6 +35,14 @@ RtpPacketizerGeneric::RtpPacketizerGeneric(
|
||||
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 @@ bool RtpPacketizerGeneric::NextPacket(RtpPacketToSend* packet) {
|
||||
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 @@ void RtpPacketizerGeneric::BuildHeader(const RTPVideoHeader& rtp_video_header,
|
||||
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 @@ void RtpPacketizerGeneric::BuildHeader(const RTPVideoHeader& rtp_video_header,
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ bool RtpDepacketizerGeneric::Parse(ParsedPayload* parsed_payload,
|
||||
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;
|
||||
|
||||
@ -34,16 +34,23 @@ class RtpPacketizerGeneric : public RtpPacketizer {
|
||||
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 @@ class RtpPacketizerGeneric : public RtpPacketizer {
|
||||
// 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_
|
||||
|
||||
@ -158,11 +158,23 @@ TEST(RtpPacketizerVideoGeneric, NoFrameIdDoesNotWriteExtendedHeader) {
|
||||
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 @@ TEST(RtpDepacketizerVideoGeneric, ExtendedHeaderParsesFrameId) {
|
||||
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 @@ TEST(RtpDepacketizerVideoGeneric, ExtendedHeaderParsesFrameId) {
|
||||
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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user