Cleanup RtpPacketizerGeneric
merge SetPayloadData into constructor. Reuse payload size split function Bug: webrtc:9680 Change-Id: If8de22b2fc39c0bdf6d60154ecaaf19e2dccdcc9 Reviewed-on: https://webrtc-review.googlesource.com/97640 Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/master@{#24598}
This commit is contained in:

committed by
Commit Bot

parent
8a7916b3f8
commit
af8c03673b
@ -53,11 +53,8 @@ std::unique_ptr<RtpPacketizer> RtpPacketizer::Create(
|
|||||||
return std::move(packetizer);
|
return std::move(packetizer);
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
auto packetizer = absl::make_unique<RtpPacketizerGeneric>(
|
return absl::make_unique<RtpPacketizerGeneric>(
|
||||||
rtp_video_header, frame_type, limits.max_payload_len,
|
payload, limits, rtp_video_header, frame_type);
|
||||||
limits.last_packet_reduction_len);
|
|
||||||
packetizer->SetPayloadData(payload.data(), payload.size(), nullptr);
|
|
||||||
return std::move(packetizer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,121 +21,70 @@ static const size_t kGenericHeaderLength = 1;
|
|||||||
static const size_t kExtendedHeaderLength = 2;
|
static const size_t kExtendedHeaderLength = 2;
|
||||||
|
|
||||||
RtpPacketizerGeneric::RtpPacketizerGeneric(
|
RtpPacketizerGeneric::RtpPacketizerGeneric(
|
||||||
|
rtc::ArrayView<const uint8_t> payload,
|
||||||
|
PayloadSizeLimits limits,
|
||||||
const RTPVideoHeader& rtp_video_header,
|
const RTPVideoHeader& rtp_video_header,
|
||||||
FrameType frame_type,
|
FrameType frame_type)
|
||||||
size_t max_payload_len,
|
: remaining_payload_(payload) {
|
||||||
size_t last_packet_reduction_len)
|
BuildHeader(rtp_video_header, frame_type);
|
||||||
: picture_id_(rtp_video_header.generic
|
|
||||||
? absl::optional<uint16_t>(
|
|
||||||
rtp_video_header.generic->frame_id & 0x7FFF)
|
|
||||||
: absl::nullopt),
|
|
||||||
payload_data_(nullptr),
|
|
||||||
payload_size_(0),
|
|
||||||
max_payload_len_(max_payload_len - kGenericHeaderLength -
|
|
||||||
(picture_id_.has_value() ? kExtendedHeaderLength : 0)),
|
|
||||||
last_packet_reduction_len_(last_packet_reduction_len),
|
|
||||||
frame_type_(frame_type),
|
|
||||||
num_packets_left_(0),
|
|
||||||
num_larger_packets_(0) {}
|
|
||||||
|
|
||||||
RtpPacketizerGeneric::~RtpPacketizerGeneric() {}
|
limits.max_payload_len -= header_size_;
|
||||||
|
payload_sizes_ = SplitAboutEqually(payload.size(), limits);
|
||||||
size_t RtpPacketizerGeneric::SetPayloadData(
|
current_packet_ = payload_sizes_.begin();
|
||||||
const uint8_t* payload_data,
|
|
||||||
size_t payload_size,
|
|
||||||
const RTPFragmentationHeader* fragmentation) {
|
|
||||||
payload_data_ = payload_data;
|
|
||||||
payload_size_ = payload_size;
|
|
||||||
|
|
||||||
// Fragment packets such that they are almost the same size, even accounting
|
|
||||||
// for larger header in the last packet.
|
|
||||||
// Since we are given how much extra space is occupied by the longer header
|
|
||||||
// in the last packet, we can pretend that RTP headers are the same, but
|
|
||||||
// there's last_packet_reduction_len_ virtual payload, to be put at the end of
|
|
||||||
// the last packet.
|
|
||||||
//
|
|
||||||
size_t total_bytes = payload_size_ + last_packet_reduction_len_;
|
|
||||||
|
|
||||||
// Minimum needed number of packets to fit payload and virtual payload in the
|
|
||||||
// last packet.
|
|
||||||
num_packets_left_ = (total_bytes + max_payload_len_ - 1) / max_payload_len_;
|
|
||||||
// Given number of packets, calculate average size rounded down.
|
|
||||||
payload_len_per_packet_ = total_bytes / num_packets_left_;
|
|
||||||
// If we can't divide everything perfectly evenly, we put 1 extra byte in some
|
|
||||||
// last packets: 14 bytes in 4 packets would be split as 3+3+4+4.
|
|
||||||
num_larger_packets_ = total_bytes % num_packets_left_;
|
|
||||||
RTC_DCHECK_LE(payload_len_per_packet_, max_payload_len_);
|
|
||||||
|
|
||||||
generic_header_ = RtpFormatVideoGeneric::kFirstPacketBit;
|
|
||||||
if (frame_type_ == kVideoFrameKey) {
|
|
||||||
generic_header_ |= RtpFormatVideoGeneric::kKeyFrameBit;
|
|
||||||
}
|
|
||||||
if (picture_id_.has_value()) {
|
|
||||||
generic_header_ |= RtpFormatVideoGeneric::kExtendedHeaderBit;
|
|
||||||
}
|
|
||||||
|
|
||||||
return num_packets_left_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RtpPacketizerGeneric::~RtpPacketizerGeneric() = default;
|
||||||
|
|
||||||
size_t RtpPacketizerGeneric::NumPackets() const {
|
size_t RtpPacketizerGeneric::NumPackets() const {
|
||||||
return num_packets_left_;
|
return payload_sizes_.end() - current_packet_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RtpPacketizerGeneric::NextPacket(RtpPacketToSend* packet) {
|
bool RtpPacketizerGeneric::NextPacket(RtpPacketToSend* packet) {
|
||||||
RTC_DCHECK(packet);
|
RTC_DCHECK(packet);
|
||||||
if (num_packets_left_ == 0)
|
if (current_packet_ == payload_sizes_.end())
|
||||||
return false;
|
return false;
|
||||||
// Last larger_packets_ packets are 1 byte larger than previous packets.
|
|
||||||
// Increase per packet payload once needed.
|
|
||||||
if (num_packets_left_ == num_larger_packets_)
|
|
||||||
++payload_len_per_packet_;
|
|
||||||
size_t next_packet_payload_len = payload_len_per_packet_;
|
|
||||||
if (payload_size_ <= next_packet_payload_len) {
|
|
||||||
// Whole payload fits into this packet.
|
|
||||||
next_packet_payload_len = payload_size_;
|
|
||||||
if (num_packets_left_ == 2) {
|
|
||||||
// This is the penultimate packet. Leave at least 1 payload byte for the
|
|
||||||
// last packet.
|
|
||||||
--next_packet_payload_len;
|
|
||||||
RTC_DCHECK_GT(next_packet_payload_len, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RTC_DCHECK_LE(next_packet_payload_len, max_payload_len_);
|
|
||||||
|
|
||||||
size_t total_length = next_packet_payload_len + kGenericHeaderLength +
|
size_t next_packet_payload_len = *current_packet_;
|
||||||
(picture_id_.has_value() ? kExtendedHeaderLength : 0);
|
|
||||||
uint8_t* out_ptr = packet->AllocatePayload(total_length);
|
|
||||||
|
|
||||||
// Put generic header in packet.
|
uint8_t* out_ptr =
|
||||||
out_ptr[0] = generic_header_;
|
packet->AllocatePayload(header_size_ + next_packet_payload_len);
|
||||||
out_ptr += kGenericHeaderLength;
|
RTC_CHECK(out_ptr);
|
||||||
|
|
||||||
if (picture_id_.has_value()) {
|
memcpy(out_ptr, header_, header_size_);
|
||||||
WriteExtendedHeader(out_ptr);
|
memcpy(out_ptr + header_size_, remaining_payload_.data(),
|
||||||
out_ptr += kExtendedHeaderLength;
|
next_packet_payload_len);
|
||||||
}
|
|
||||||
|
|
||||||
// Remove first-packet bit, following packets are intermediate.
|
// Remove first-packet bit, following packets are intermediate.
|
||||||
generic_header_ &= ~RtpFormatVideoGeneric::kFirstPacketBit;
|
header_[0] &= ~RtpFormatVideoGeneric::kFirstPacketBit;
|
||||||
|
|
||||||
|
remaining_payload_ = remaining_payload_.subview(next_packet_payload_len);
|
||||||
|
|
||||||
|
++current_packet_;
|
||||||
|
|
||||||
// Put payload in packet.
|
|
||||||
memcpy(out_ptr, payload_data_, next_packet_payload_len);
|
|
||||||
payload_data_ += next_packet_payload_len;
|
|
||||||
payload_size_ -= next_packet_payload_len;
|
|
||||||
--num_packets_left_;
|
|
||||||
// Packets left to produce and data left to split should end at the same time.
|
// Packets left to produce and data left to split should end at the same time.
|
||||||
RTC_DCHECK_EQ(num_packets_left_ == 0, payload_size_ == 0);
|
RTC_DCHECK_EQ(current_packet_ == payload_sizes_.end(),
|
||||||
|
remaining_payload_.empty());
|
||||||
packet->SetMarker(payload_size_ == 0);
|
|
||||||
|
|
||||||
|
packet->SetMarker(remaining_payload_.empty());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtpPacketizerGeneric::WriteExtendedHeader(uint8_t* out_ptr) {
|
void RtpPacketizerGeneric::BuildHeader(const RTPVideoHeader& rtp_video_header,
|
||||||
// Store bottom 15 bits of the the sequence number. Only 15 bits are used for
|
FrameType frame_type) {
|
||||||
// compatibility with other packetizer implemenetations that also use 15 bits.
|
header_size_ = kGenericHeaderLength;
|
||||||
out_ptr[0] = (*picture_id_ >> 8) & 0x7F;
|
header_[0] = RtpFormatVideoGeneric::kFirstPacketBit;
|
||||||
out_ptr[1] = *picture_id_ & 0xFF;
|
if (frame_type == kVideoFrameKey) {
|
||||||
|
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
|
||||||
|
// compatibility with other packetizer implemenetations.
|
||||||
|
uint16_t picture_id = rtp_video_header.generic->frame_id & 0x7FFF;
|
||||||
|
header_[0] |= RtpFormatVideoGeneric::kExtendedHeaderBit;
|
||||||
|
header_[1] = (picture_id >> 8) & 0x7F;
|
||||||
|
header_[2] = picture_id & 0xFF;
|
||||||
|
header_size_ += kExtendedHeaderLength;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RtpDepacketizerGeneric::~RtpDepacketizerGeneric() = default;
|
RtpDepacketizerGeneric::~RtpDepacketizerGeneric() = default;
|
||||||
|
@ -10,8 +10,9 @@
|
|||||||
#ifndef MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VIDEO_GENERIC_H_
|
#ifndef MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VIDEO_GENERIC_H_
|
||||||
#define MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VIDEO_GENERIC_H_
|
#define MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VIDEO_GENERIC_H_
|
||||||
|
|
||||||
#include <string>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "api/array_view.h"
|
||||||
#include "common_types.h" // NOLINT(build/include)
|
#include "common_types.h" // NOLINT(build/include)
|
||||||
#include "modules/rtp_rtcp/source/rtp_format.h"
|
#include "modules/rtp_rtcp/source/rtp_format.h"
|
||||||
#include "rtc_base/constructormagic.h"
|
#include "rtc_base/constructormagic.h"
|
||||||
@ -29,18 +30,13 @@ class RtpPacketizerGeneric : public RtpPacketizer {
|
|||||||
public:
|
public:
|
||||||
// Initialize with payload from encoder.
|
// Initialize with payload from encoder.
|
||||||
// The payload_data must be exactly one encoded generic frame.
|
// The payload_data must be exactly one encoded generic frame.
|
||||||
RtpPacketizerGeneric(const RTPVideoHeader& rtp_video_header,
|
RtpPacketizerGeneric(rtc::ArrayView<const uint8_t> payload,
|
||||||
FrameType frametype,
|
PayloadSizeLimits limits,
|
||||||
size_t max_payload_len,
|
const RTPVideoHeader& rtp_video_header,
|
||||||
size_t last_packet_reduction_len);
|
FrameType frametype);
|
||||||
|
|
||||||
~RtpPacketizerGeneric() override;
|
~RtpPacketizerGeneric() override;
|
||||||
|
|
||||||
// Returns total number of packets to be generated.
|
|
||||||
size_t SetPayloadData(const uint8_t* payload_data,
|
|
||||||
size_t payload_size,
|
|
||||||
const RTPFragmentationHeader* fragmentation);
|
|
||||||
|
|
||||||
size_t NumPackets() const override;
|
size_t NumPackets() const override;
|
||||||
|
|
||||||
// Get the next payload with generic payload header.
|
// Get the next payload with generic payload header.
|
||||||
@ -49,20 +45,15 @@ class RtpPacketizerGeneric : public RtpPacketizer {
|
|||||||
bool NextPacket(RtpPacketToSend* packet) override;
|
bool NextPacket(RtpPacketToSend* packet) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const absl::optional<uint16_t> picture_id_;
|
// Fills header_ and header_size_ members.
|
||||||
const uint8_t* payload_data_;
|
void BuildHeader(const RTPVideoHeader& rtp_video_header,
|
||||||
size_t payload_size_;
|
FrameType frame_type);
|
||||||
const size_t max_payload_len_;
|
|
||||||
const size_t last_packet_reduction_len_;
|
|
||||||
FrameType frame_type_;
|
|
||||||
size_t payload_len_per_packet_;
|
|
||||||
uint8_t generic_header_;
|
|
||||||
// Number of packets yet to be retrieved by NextPacket() call.
|
|
||||||
size_t num_packets_left_;
|
|
||||||
// Number of packets, which will be 1 byte more than the rest.
|
|
||||||
size_t num_larger_packets_;
|
|
||||||
|
|
||||||
void WriteExtendedHeader(uint8_t* out_ptr);
|
uint8_t header_[3];
|
||||||
|
size_t header_size_;
|
||||||
|
rtc::ArrayView<const uint8_t> remaining_payload_;
|
||||||
|
std::vector<size_t> payload_sizes_;
|
||||||
|
std::vector<size_t>::const_iterator current_packet_;
|
||||||
|
|
||||||
RTC_DISALLOW_COPY_AND_ASSIGN(RtpPacketizerGeneric);
|
RTC_DISALLOW_COPY_AND_ASSIGN(RtpPacketizerGeneric);
|
||||||
};
|
};
|
||||||
|
@ -29,10 +29,9 @@ using ::testing::Each;
|
|||||||
using ::testing::ElementsAreArray;
|
using ::testing::ElementsAreArray;
|
||||||
using ::testing::Le;
|
using ::testing::Le;
|
||||||
using ::testing::SizeIs;
|
using ::testing::SizeIs;
|
||||||
|
using ::testing::Contains;
|
||||||
|
|
||||||
const size_t kMaxPayloadSize = 1200;
|
constexpr RtpPacketizer::PayloadSizeLimits kNoSizeLimits;
|
||||||
|
|
||||||
uint8_t kTestPayload[kMaxPayloadSize];
|
|
||||||
|
|
||||||
std::vector<size_t> NextPacketFillPayloadSizes(
|
std::vector<size_t> NextPacketFillPayloadSizes(
|
||||||
RtpPacketizerGeneric* packetizer) {
|
RtpPacketizerGeneric* packetizer) {
|
||||||
@ -44,185 +43,100 @@ std::vector<size_t> NextPacketFillPayloadSizes(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetEffectivePacketsSizeDifference(std::vector<size_t>* payload_sizes,
|
TEST(RtpPacketizerVideoGeneric, RespectsMaxPayloadSize) {
|
||||||
size_t last_packet_reduction_len) {
|
const size_t kPayloadSize = 50;
|
||||||
// Account for larger last packet header.
|
const uint8_t kPayload[kPayloadSize] = {};
|
||||||
payload_sizes->back() += last_packet_reduction_len;
|
|
||||||
auto minmax =
|
RtpPacketizer::PayloadSizeLimits limits;
|
||||||
std::minmax_element(payload_sizes->begin(), payload_sizes->end());
|
limits.max_payload_len = 6;
|
||||||
// MAX-MIN
|
RtpPacketizerGeneric packetizer(kPayload, limits, RTPVideoHeader(),
|
||||||
size_t difference = *minmax.second - *minmax.first;
|
kVideoFrameKey);
|
||||||
// Revert temporary changes.
|
|
||||||
payload_sizes->back() -= last_packet_reduction_len;
|
std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
|
||||||
return difference;
|
|
||||||
|
EXPECT_THAT(payload_sizes, Each(Le(limits.max_payload_len)));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
TEST(RtpPacketizerVideoGeneric, UsesMaxPayloadSize) {
|
||||||
|
const size_t kPayloadSize = 50;
|
||||||
|
const uint8_t kPayload[kPayloadSize] = {};
|
||||||
|
|
||||||
TEST(RtpPacketizerVideoGeneric, AllPacketsMayBeEqualAndRespectMaxPayloadSize) {
|
RtpPacketizer::PayloadSizeLimits limits;
|
||||||
const size_t kMaxPayloadLen = 6;
|
limits.max_payload_len = 6;
|
||||||
const size_t kLastPacketReductionLen = 2;
|
RtpPacketizerGeneric packetizer(kPayload, limits, RTPVideoHeader(),
|
||||||
const size_t kPayloadSize = 13;
|
kVideoFrameKey);
|
||||||
RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
|
|
||||||
kMaxPayloadLen, kLastPacketReductionLen);
|
std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
|
||||||
size_t num_packets =
|
|
||||||
packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
|
// With kPayloadSize > max_payload_len^2, there should be packets that use
|
||||||
std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
|
// all the payload, otherwise it is possible to use less packets.
|
||||||
EXPECT_THAT(payload_sizes, SizeIs(num_packets));
|
EXPECT_THAT(payload_sizes, Contains(limits.max_payload_len));
|
||||||
|
}
|
||||||
EXPECT_THAT(payload_sizes, Each(Le(kMaxPayloadLen)));
|
|
||||||
}
|
TEST(RtpPacketizerVideoGeneric, WritesExtendedHeaderWhenPictureIdIsSet) {
|
||||||
|
|
||||||
TEST(RtpPacketizerVideoGeneric,
|
|
||||||
AllPacketsMayBeEqual_RespectsLastPacketReductionLength) {
|
|
||||||
const size_t kMaxPayloadLen = 6;
|
|
||||||
const size_t kLastPacketReductionLen = 2;
|
|
||||||
const size_t kPayloadSize = 13;
|
|
||||||
RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
|
|
||||||
kMaxPayloadLen, kLastPacketReductionLen);
|
|
||||||
size_t num_packets =
|
|
||||||
packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
|
|
||||||
std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
|
|
||||||
EXPECT_THAT(payload_sizes, SizeIs(num_packets));
|
|
||||||
|
|
||||||
EXPECT_LE(payload_sizes.back(), kMaxPayloadLen - kLastPacketReductionLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(RtpPacketizerVideoGeneric,
|
|
||||||
AllPacketsMayBeEqual_MakesPacketsAlmostEqualInSize) {
|
|
||||||
const size_t kMaxPayloadLen = 6;
|
|
||||||
const size_t kLastPacketReductionLen = 2;
|
|
||||||
const size_t kPayloadSize = 13;
|
|
||||||
RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
|
|
||||||
kMaxPayloadLen, kLastPacketReductionLen);
|
|
||||||
size_t num_packets =
|
|
||||||
packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
|
|
||||||
std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
|
|
||||||
EXPECT_THAT(payload_sizes, SizeIs(num_packets));
|
|
||||||
|
|
||||||
size_t sizes_difference = GetEffectivePacketsSizeDifference(
|
|
||||||
&payload_sizes, kLastPacketReductionLen);
|
|
||||||
EXPECT_LE(sizes_difference, 1u);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(RtpPacketizerVideoGeneric,
|
|
||||||
AllPacketsMayBeEqual_GeneratesMinimumNumberOfPackets) {
|
|
||||||
const size_t kMaxPayloadLen = 6;
|
|
||||||
const size_t kLastPacketReductionLen = 3;
|
|
||||||
const size_t kPayloadSize = 13;
|
|
||||||
// Computed by hand. 3 packets would have capacity 3*(6-1)-3=12 (max length -
|
|
||||||
// generic header lengh for each packet minus last packet reduction).
|
|
||||||
// 4 packets is enough for kPayloadSize.
|
|
||||||
const size_t kMinNumPackets = 4;
|
|
||||||
RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
|
|
||||||
kMaxPayloadLen, kLastPacketReductionLen);
|
|
||||||
size_t num_packets =
|
|
||||||
packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
|
|
||||||
std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
|
|
||||||
EXPECT_THAT(payload_sizes, SizeIs(num_packets));
|
|
||||||
|
|
||||||
EXPECT_EQ(num_packets, kMinNumPackets);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(RtpPacketizerVideoGeneric, SomePacketsAreSmaller_RespectsMaxPayloadSize) {
|
|
||||||
const size_t kMaxPayloadLen = 8;
|
|
||||||
const size_t kLastPacketReductionLen = 5;
|
|
||||||
const size_t kPayloadSize = 28;
|
|
||||||
RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
|
|
||||||
kMaxPayloadLen, kLastPacketReductionLen);
|
|
||||||
size_t num_packets =
|
|
||||||
packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
|
|
||||||
std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
|
|
||||||
EXPECT_THAT(payload_sizes, SizeIs(num_packets));
|
|
||||||
|
|
||||||
EXPECT_THAT(payload_sizes, Each(Le(kMaxPayloadLen)));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(RtpPacketizerVideoGeneric,
|
|
||||||
SomePacketsAreSmaller_RespectsLastPacketReductionLength) {
|
|
||||||
const size_t kMaxPayloadLen = 8;
|
|
||||||
const size_t kLastPacketReductionLen = 5;
|
|
||||||
const size_t kPayloadSize = 28;
|
|
||||||
RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
|
|
||||||
kMaxPayloadLen, kLastPacketReductionLen);
|
|
||||||
size_t num_packets =
|
|
||||||
packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
|
|
||||||
std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
|
|
||||||
EXPECT_THAT(payload_sizes, SizeIs(num_packets));
|
|
||||||
|
|
||||||
EXPECT_LE(payload_sizes.back(), kMaxPayloadLen - kLastPacketReductionLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(RtpPacketizerVideoGeneric,
|
|
||||||
SomePacketsAreSmaller_MakesPacketsAlmostEqualInSize) {
|
|
||||||
const size_t kMaxPayloadLen = 8;
|
|
||||||
const size_t kLastPacketReductionLen = 5;
|
|
||||||
const size_t kPayloadSize = 28;
|
|
||||||
RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
|
|
||||||
kMaxPayloadLen, kLastPacketReductionLen);
|
|
||||||
size_t num_packets =
|
|
||||||
packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
|
|
||||||
std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
|
|
||||||
EXPECT_THAT(payload_sizes, SizeIs(num_packets));
|
|
||||||
|
|
||||||
size_t sizes_difference = GetEffectivePacketsSizeDifference(
|
|
||||||
&payload_sizes, kLastPacketReductionLen);
|
|
||||||
EXPECT_LE(sizes_difference, 1u);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(RtpPacketizerVideoGeneric,
|
|
||||||
SomePacketsAreSmaller_GeneratesMinimumNumberOfPackets) {
|
|
||||||
const size_t kMaxPayloadLen = 8;
|
|
||||||
const size_t kLastPacketReductionLen = 5;
|
|
||||||
const size_t kPayloadSize = 28;
|
|
||||||
// Computed by hand. 4 packets would have capacity 4*(8-1)-5=23 (max length -
|
|
||||||
// generic header lengh for each packet minus last packet reduction).
|
|
||||||
// 5 packets is enough for kPayloadSize.
|
|
||||||
const size_t kMinNumPackets = 5;
|
|
||||||
RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
|
|
||||||
kMaxPayloadLen, kLastPacketReductionLen);
|
|
||||||
size_t num_packets =
|
|
||||||
packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
|
|
||||||
std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
|
|
||||||
EXPECT_THAT(payload_sizes, SizeIs(num_packets));
|
|
||||||
|
|
||||||
EXPECT_EQ(num_packets, kMinNumPackets);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(RtpPacketizerVideoGeneric, HasFrameIdWritesExtendedHeader) {
|
|
||||||
const size_t kMaxPayloadLen = 6;
|
|
||||||
const size_t kLastPacketReductionLen = 2;
|
|
||||||
const size_t kPayloadSize = 13;
|
const size_t kPayloadSize = 13;
|
||||||
|
const uint8_t kPayload[kPayloadSize] = {};
|
||||||
|
|
||||||
RTPVideoHeader rtp_video_header;
|
RTPVideoHeader rtp_video_header;
|
||||||
rtp_video_header.generic.emplace().frame_id = 37;
|
rtp_video_header.generic.emplace().frame_id = 37;
|
||||||
RtpPacketizerGeneric packetizer(rtp_video_header, kVideoFrameKey,
|
RtpPacketizerGeneric packetizer(kPayload, kNoSizeLimits, rtp_video_header,
|
||||||
kMaxPayloadLen, kLastPacketReductionLen);
|
kVideoFrameKey);
|
||||||
packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
|
|
||||||
|
|
||||||
RtpPacketToSend packet(nullptr);
|
RtpPacketToSend packet(nullptr);
|
||||||
packetizer.NextPacket(&packet);
|
ASSERT_TRUE(packetizer.NextPacket(&packet));
|
||||||
|
|
||||||
rtc::ArrayView<const uint8_t> payload = packet.payload();
|
rtc::ArrayView<const uint8_t> payload = packet.payload();
|
||||||
|
EXPECT_EQ(payload.size(), 3 + kPayloadSize);
|
||||||
EXPECT_TRUE(payload[0] & 0x04); // Extended header bit is set.
|
EXPECT_TRUE(payload[0] & 0x04); // Extended header bit is set.
|
||||||
// Frame id is 37.
|
// Frame id is 37.
|
||||||
EXPECT_EQ(0u, payload[1]);
|
EXPECT_EQ(0u, payload[1]);
|
||||||
EXPECT_EQ(37u, payload[2]);
|
EXPECT_EQ(37u, payload[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(RtpPacketizerVideoGeneric, RespectsMaxPayloadSizeWithExtendedHeader) {
|
||||||
|
const size_t kPayloadSize = 50;
|
||||||
|
const uint8_t kPayload[kPayloadSize] = {};
|
||||||
|
|
||||||
|
RtpPacketizer::PayloadSizeLimits limits;
|
||||||
|
limits.max_payload_len = 6;
|
||||||
|
RTPVideoHeader rtp_video_header;
|
||||||
|
rtp_video_header.generic.emplace().frame_id = 37;
|
||||||
|
RtpPacketizerGeneric packetizer(kPayload, limits, rtp_video_header,
|
||||||
|
kVideoFrameKey);
|
||||||
|
|
||||||
|
std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
|
||||||
|
|
||||||
|
EXPECT_THAT(payload_sizes, Each(Le(limits.max_payload_len)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(RtpPacketizerVideoGeneric, UsesMaxPayloadSizeWithExtendedHeader) {
|
||||||
|
const size_t kPayloadSize = 50;
|
||||||
|
const uint8_t kPayload[kPayloadSize] = {};
|
||||||
|
|
||||||
|
RtpPacketizer::PayloadSizeLimits limits;
|
||||||
|
limits.max_payload_len = 6;
|
||||||
|
RTPVideoHeader rtp_video_header;
|
||||||
|
rtp_video_header.generic.emplace().frame_id = 37;
|
||||||
|
RtpPacketizerGeneric packetizer(kPayload, limits, rtp_video_header,
|
||||||
|
kVideoFrameKey);
|
||||||
|
std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
|
||||||
|
|
||||||
|
// With kPayloadSize > max_payload_len^2, there should be packets that use
|
||||||
|
// all the payload, otherwise it is possible to use less packets.
|
||||||
|
EXPECT_THAT(payload_sizes, Contains(limits.max_payload_len));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(RtpPacketizerVideoGeneric, FrameIdOver15bitsWrapsAround) {
|
TEST(RtpPacketizerVideoGeneric, FrameIdOver15bitsWrapsAround) {
|
||||||
const size_t kMaxPayloadLen = 6;
|
|
||||||
const size_t kLastPacketReductionLen = 2;
|
|
||||||
const size_t kPayloadSize = 13;
|
const size_t kPayloadSize = 13;
|
||||||
|
const uint8_t kPayload[kPayloadSize] = {};
|
||||||
|
|
||||||
RTPVideoHeader rtp_video_header;
|
RTPVideoHeader rtp_video_header;
|
||||||
rtp_video_header.generic.emplace().frame_id = 0x8137;
|
rtp_video_header.generic.emplace().frame_id = 0x8137;
|
||||||
RtpPacketizerGeneric packetizer(rtp_video_header, kVideoFrameKey,
|
RtpPacketizerGeneric packetizer(kPayload, kNoSizeLimits, rtp_video_header,
|
||||||
kMaxPayloadLen, kLastPacketReductionLen);
|
kVideoFrameKey);
|
||||||
packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
|
|
||||||
|
|
||||||
RtpPacketToSend packet(nullptr);
|
RtpPacketToSend packet(nullptr);
|
||||||
packetizer.NextPacket(&packet);
|
ASSERT_TRUE(packetizer.NextPacket(&packet));
|
||||||
|
|
||||||
rtc::ArrayView<const uint8_t> payload = packet.payload();
|
rtc::ArrayView<const uint8_t> payload = packet.payload();
|
||||||
EXPECT_TRUE(payload[0] & 0x04); // Extended header bit is set.
|
EXPECT_TRUE(payload[0] & 0x04); // Extended header bit is set.
|
||||||
@ -232,16 +146,14 @@ TEST(RtpPacketizerVideoGeneric, FrameIdOver15bitsWrapsAround) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(RtpPacketizerVideoGeneric, NoFrameIdDoesNotWriteExtendedHeader) {
|
TEST(RtpPacketizerVideoGeneric, NoFrameIdDoesNotWriteExtendedHeader) {
|
||||||
const size_t kMaxPayloadLen = 6;
|
|
||||||
const size_t kLastPacketReductionLen = 2;
|
|
||||||
const size_t kPayloadSize = 13;
|
const size_t kPayloadSize = 13;
|
||||||
|
const uint8_t kPayload[kPayloadSize] = {};
|
||||||
|
|
||||||
RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
|
RtpPacketizerGeneric packetizer(kPayload, kNoSizeLimits, RTPVideoHeader(),
|
||||||
kMaxPayloadLen, kLastPacketReductionLen);
|
kVideoFrameKey);
|
||||||
packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
|
|
||||||
|
|
||||||
RtpPacketToSend packet(nullptr);
|
RtpPacketToSend packet(nullptr);
|
||||||
packetizer.NextPacket(&packet);
|
ASSERT_TRUE(packetizer.NextPacket(&packet));
|
||||||
|
|
||||||
rtc::ArrayView<const uint8_t> payload = packet.payload();
|
rtc::ArrayView<const uint8_t> payload = packet.payload();
|
||||||
EXPECT_FALSE(payload[0] & 0x04);
|
EXPECT_FALSE(payload[0] & 0x04);
|
||||||
@ -270,4 +182,5 @@ TEST(RtpDepacketizerVideoGeneric, ExtendedHeaderParsesFrameId) {
|
|||||||
EXPECT_EQ(0x1337, parsed_payload.video_header().generic->frame_id);
|
EXPECT_EQ(0x1337, parsed_payload.video_header().generic->frame_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
Reference in New Issue
Block a user