Change flexfec header writer to finalize header according to updated RFC

Change implementation of `FinalizeFecHeader` to write the FEC header
for multiple ssrcs according to the updated RFC.

Change-Id: I280964b2e53c3579f348fbd42815c966840375ac
Bug: webrtc:15002
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/307601
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40270}
This commit is contained in:
Yosef Twaik 2023-06-08 16:22:22 +03:00 committed by WebRTC LUCI CQ
parent bde7c6ad11
commit 61deed5696
2 changed files with 380 additions and 99 deletions

View File

@ -49,17 +49,6 @@ constexpr size_t kHeaderSizes[] = {
kBaseHeaderSize + kStreamSpecificHeaderSize + kFlexfecPacketMaskSizes[1],
kBaseHeaderSize + kStreamSpecificHeaderSize + kFlexfecPacketMaskSizes[2]};
// We currently only support single-stream protection.
// TODO(brandtr): Update this when we support multistream protection.
constexpr uint8_t kSsrcCount = 1;
// There are three reserved bytes that MUST be set to zero in the header.
constexpr uint32_t kReservedBits = 0;
// TODO(brandtr): Update this when we support multistream protection.
constexpr size_t kPacketMaskOffset =
kBaseHeaderSize + kStreamSpecificHeaderSize;
// Here we count the K-bits as belonging to the packet mask.
// This can be used in conjunction with FlexfecHeaderWriter::MinPacketMaskSize,
// which calculates a bound on the needed packet mask size including K-bits,
@ -255,78 +244,84 @@ size_t FlexfecHeaderWriter::FecHeaderSize(size_t packet_mask_size) const {
// FecHeaderSize(), so in this function we can be sure that we are
// writing in space that is intended for the header.
//
// TODO(brandtr): Update this function when we support offset-based masks,
// retransmissions, and protecting multiple SSRCs.
// TODO(brandtr): Update this function when we support offset-based masks
// and retransmissions.
void FlexfecHeaderWriter::FinalizeFecHeader(
rtc::ArrayView<const ProtectedStream> protected_streams,
ForwardErrorCorrection::Packet& fec_packet) const {
// TODO(bugs.webrtc.org/15002): Iterate over all streams and update FlexFEC
// header accordingly.
RTC_CHECK_EQ(protected_streams.size(), 1);
uint32_t media_ssrc = protected_streams[0].ssrc;
uint16_t seq_num_base = protected_streams[0].seq_num_base;
const uint8_t* packet_mask = protected_streams[0].packet_mask.data();
size_t packet_mask_size = protected_streams[0].packet_mask.size();
uint8_t* data = fec_packet.data.MutableData();
data[0] &= 0x7f; // Clear R bit.
data[0] &= 0xbf; // Clear F bit.
ByteWriter<uint8_t>::WriteBigEndian(&data[8], kSsrcCount);
ByteWriter<uint32_t, 3>::WriteBigEndian(&data[9], kReservedBits);
ByteWriter<uint32_t>::WriteBigEndian(&data[12], media_ssrc);
ByteWriter<uint16_t>::WriteBigEndian(&data[16], seq_num_base);
// Adapt ULPFEC packet mask to FlexFEC header.
//
// We treat the mask parts as unsigned integers with host order endianness
// in order to simplify the bit shifting between bytes.
uint8_t* const written_packet_mask = data + kPacketMaskOffset;
if (packet_mask_size == kUlpfecPacketMaskSizeLBitSet) {
// The packet mask is 48 bits long.
uint16_t tmp_mask_part0 =
ByteReader<uint16_t>::ReadBigEndian(&packet_mask[0]);
uint32_t tmp_mask_part1 =
ByteReader<uint32_t>::ReadBigEndian(&packet_mask[2]);
*data &= 0x7f; // Clear R bit.
*data &= 0xbf; // Clear F bit.
tmp_mask_part0 >>= 1; // Shift, thus clearing K-bit 0.
ByteWriter<uint16_t>::WriteBigEndian(&written_packet_mask[0],
tmp_mask_part0);
tmp_mask_part1 >>= 2; // Shift, thus clearing K-bit 1 and bit 15.
ByteWriter<uint32_t>::WriteBigEndian(&written_packet_mask[2],
tmp_mask_part1);
bool bit15 = (packet_mask[1] & 0x01) != 0;
if (bit15)
written_packet_mask[2] |= 0x40; // Set bit 15.
bool bit46 = (packet_mask[5] & 0x02) != 0;
bool bit47 = (packet_mask[5] & 0x01) != 0;
if (!bit46 && !bit47) {
written_packet_mask[2] |= 0x80; // Set K-bit 1.
} else {
memset(&written_packet_mask[6], 0, 8); // Clear all trailing bits.
written_packet_mask[6] |= 0x80; // Set K-bit 2.
if (bit46)
written_packet_mask[6] |= 0x40; // Set bit 46.
if (bit47)
written_packet_mask[6] |= 0x20; // Set bit 47.
}
} else if (packet_mask_size == kUlpfecPacketMaskSizeLBitClear) {
// The packet mask is 16 bits long.
uint16_t tmp_mask_part0 =
ByteReader<uint16_t>::ReadBigEndian(&packet_mask[0]);
// First seq_num will be in byte index 8
// (See FEC header schematic in flexfec_header_reader_writer.h.)
uint8_t* write_at = data + 8;
for (const ProtectedStream& protected_stream : protected_streams) {
ByteWriter<uint16_t>::WriteBigEndian(write_at,
protected_stream.seq_num_base);
write_at += kStreamSpecificHeaderSize;
// Adapt ULPFEC packet mask to FlexFEC header.
//
// We treat the mask parts as unsigned integers with host order endianness
// in order to simplify the bit shifting between bytes.
if (protected_stream.packet_mask.size() == kUlpfecPacketMaskSizeLBitSet) {
// The packet mask is 48 bits long.
uint16_t tmp_mask_part0 =
ByteReader<uint16_t>::ReadBigEndian(&protected_stream.packet_mask[0]);
uint32_t tmp_mask_part1 =
ByteReader<uint32_t>::ReadBigEndian(&protected_stream.packet_mask[2]);
tmp_mask_part0 >>= 1; // Shift, thus clearing K-bit 0.
ByteWriter<uint16_t>::WriteBigEndian(&written_packet_mask[0],
tmp_mask_part0);
bool bit15 = (packet_mask[1] & 0x01) != 0;
if (!bit15) {
written_packet_mask[0] |= 0x80; // Set K-bit 0.
tmp_mask_part0 >>= 1; // Shift, thus clearing K-bit 0.
ByteWriter<uint16_t>::WriteBigEndian(write_at, tmp_mask_part0);
write_at += kFlexfecPacketMaskSizes[0];
tmp_mask_part1 >>= 2; // Shift, thus clearing K-bit 1 and bit 15.
ByteWriter<uint32_t>::WriteBigEndian(write_at, tmp_mask_part1);
bool bit15 = (protected_stream.packet_mask[1] & 0x01) != 0;
if (bit15)
*write_at |= 0x40; // Set bit 15.
bool bit46 = (protected_stream.packet_mask[5] & 0x02) != 0;
bool bit47 = (protected_stream.packet_mask[5] & 0x01) != 0;
if (!bit46 && !bit47) {
*write_at |= 0x80; // Set K-bit 1.
write_at += kFlexfecPacketMaskSizes[1] - kFlexfecPacketMaskSizes[0];
} else {
write_at += kFlexfecPacketMaskSizes[1] - kFlexfecPacketMaskSizes[0];
// Clear all trailing bits.
memset(write_at, 0,
kFlexfecPacketMaskSizes[2] - kFlexfecPacketMaskSizes[1]);
if (bit46)
*write_at |= 0x80; // Set bit 46.
if (bit47)
*write_at |= 0x40; // Set bit 47.
write_at += kFlexfecPacketMaskSizes[2] - kFlexfecPacketMaskSizes[1];
}
} else if (protected_stream.packet_mask.size() ==
kUlpfecPacketMaskSizeLBitClear) {
// The packet mask is 16 bits long.
uint16_t tmp_mask_part0 =
ByteReader<uint16_t>::ReadBigEndian(&protected_stream.packet_mask[0]);
tmp_mask_part0 >>= 1; // Shift, thus clearing K-bit 0.
ByteWriter<uint16_t>::WriteBigEndian(write_at, tmp_mask_part0);
bool bit15 = (protected_stream.packet_mask[1] & 0x01) != 0;
if (!bit15) {
*write_at |= 0x80; // Set K-bit 0.
write_at += kFlexfecPacketMaskSizes[0];
} else {
write_at += kFlexfecPacketMaskSizes[0];
// Clear all trailing bits.
memset(write_at, 0U,
kFlexfecPacketMaskSizes[1] - kFlexfecPacketMaskSizes[0]);
*write_at |= 0x80; // Set K-bit 1.
*write_at |= 0x40; // Set bit 15.
write_at += kFlexfecPacketMaskSizes[1] - kFlexfecPacketMaskSizes[0];
}
} else {
memset(&written_packet_mask[2], 0U, 4); // Clear all trailing bits.
written_packet_mask[2] |= 0x80; // Set K-bit 1.
written_packet_mask[2] |= 0x40; // Set bit 15.
RTC_DCHECK_NOTREACHED() << "Incorrect packet mask size: "
<< protected_stream.packet_mask.size() << ".";
}
} else {
RTC_DCHECK_NOTREACHED()
<< "Incorrect packet mask size: " << packet_mask_size << ".";
}
}

View File

@ -33,6 +33,7 @@ namespace {
using Packet = ForwardErrorCorrection::Packet;
using ProtectedStream = ForwardErrorCorrection::ProtectedStream;
using ReceivedFecPacket = ForwardErrorCorrection::ReceivedFecPacket;
using ::testing::Each;
using ::testing::ElementsAreArray;
constexpr uint8_t kMask0[] = {0xAB, 0xCD}; // First K bit is set.
@ -42,6 +43,8 @@ constexpr uint8_t kMask2[] = {0x12, 0x34, // First K bit cleared.
0x56, 0x78, 0x9A, 0xBC, // Second K bit cleared.
0xDE, 0xF0, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC};
constexpr size_t kMediaPacketLength = 1234;
// Reader tests.
constexpr uint8_t kFlexible = 0b00 << 6;
constexpr uint8_t kPtRecovery = 123;
@ -53,14 +56,34 @@ constexpr uint8_t kSnBases[4][2] = {{0x01, 0x02},
{0x07, 0x08}};
constexpr uint8_t kPayloadBits = 0x00;
struct FecPacketStreamProperties {
struct FecPacketStreamReadProperties {
ProtectedStream stream;
rtc::ArrayView<const uint8_t> mask;
};
struct FecPacketStreamWriteProperties {
size_t byte_index;
uint16_t seq_num_base;
rtc::ArrayView<const uint8_t> mask;
};
Packet WritePacket(
std::vector<FecHeaderWriter::ProtectedStream> protected_streams) {
Packet written_packet;
written_packet.data.SetSize(kMediaPacketLength);
uint8_t* data = written_packet.data.MutableData();
for (size_t i = 0; i < written_packet.data.size(); ++i) {
data[i] = i;
}
FlexfecHeaderWriter writer;
writer.FinalizeFecHeader(protected_streams, written_packet);
return written_packet;
}
void VerifyReadHeaders(size_t expected_fec_header_size,
const ReceivedFecPacket& read_packet,
std::vector<FecPacketStreamProperties> expected) {
std::vector<FecPacketStreamReadProperties> expected) {
EXPECT_EQ(read_packet.fec_header_size, expected_fec_header_size);
const size_t protected_streams_num = read_packet.protected_streams.size();
EXPECT_EQ(protected_streams_num, expected.size());
@ -83,6 +106,84 @@ void VerifyReadHeaders(size_t expected_fec_header_size,
read_packet.protection_length);
}
void VerifyFinalizedHeaders(
const Packet& written_packet,
std::vector<FecPacketStreamWriteProperties> expected) {
const uint8_t* packet = written_packet.data.data();
EXPECT_EQ(packet[0] & 0x80, 0x00); // F bit clear.
EXPECT_EQ(packet[0] & 0x40, 0x00); // R bit clear.
for (size_t i = 0; i < expected.size(); ++i) {
SCOPED_TRACE(i);
// Verify value of seq_num_base.
EXPECT_EQ(
ByteReader<uint16_t>::ReadBigEndian(packet + expected[i].byte_index),
expected[i].seq_num_base);
// Verify mask.
EXPECT_THAT(rtc::MakeArrayView(packet + expected[i].byte_index + 2,
expected[i].mask.size()),
ElementsAreArray(expected[i].mask));
}
}
void VerifyWrittenAndReadHeaders(
std::vector<FecHeaderWriter::ProtectedStream> write_protected_streams,
uint16_t expected_header_size) {
// Write FEC Header.
Packet written_packet = WritePacket(write_protected_streams);
// Read FEC Header using written data.
ReceivedFecPacket read_packet;
read_packet.pkt = rtc::make_ref_counted<Packet>();
read_packet.pkt->data = written_packet.data;
for (const FecHeaderWriter::ProtectedStream& stream :
write_protected_streams) {
read_packet.protected_streams.push_back({.ssrc = stream.ssrc});
}
FlexfecHeaderReader reader;
EXPECT_TRUE(reader.ReadFecHeader(&read_packet));
// Verify header contents.
EXPECT_EQ(read_packet.fec_header_size, expected_header_size);
EXPECT_EQ(read_packet.protected_streams.size(),
write_protected_streams.size());
for (size_t i = 0; i < write_protected_streams.size(); ++i) {
SCOPED_TRACE(i);
EXPECT_EQ(read_packet.protected_streams[i].seq_num_base,
write_protected_streams[i].seq_num_base);
size_t mask_write_size = write_protected_streams[i].packet_mask.size();
// Read mask returned may be larger than the mask that was sent to the
// writer; That is ok as long as the specified part of the mask matches, and
// the rest is 0s.
FlexfecHeaderWriter writer;
size_t expected_mask_read_size = writer.MinPacketMaskSize(
write_protected_streams[i].packet_mask.data(), mask_write_size);
EXPECT_EQ(read_packet.protected_streams[i].packet_mask_size,
expected_mask_read_size);
const uint8_t* read_mask_ptr =
read_packet.pkt->data.cdata() +
read_packet.protected_streams[i].packet_mask_offset;
// Verify actual mask bits.
EXPECT_THAT(rtc::MakeArrayView(read_mask_ptr, mask_write_size),
ElementsAreArray(write_protected_streams[i].packet_mask));
// If read mask size is larger than written mask size, verify all other bits
// are 0.
EXPECT_THAT(rtc::MakeArrayView(read_mask_ptr + mask_write_size,
expected_mask_read_size - mask_write_size),
Each(0));
}
// Verify that the call to ReadFecHeader did not tamper with the payload.
EXPECT_THAT(
rtc::MakeArrayView(
read_packet.pkt->data.cdata() + read_packet.fec_header_size,
read_packet.pkt->data.size() - read_packet.fec_header_size),
ElementsAreArray(written_packet.data.cdata() + expected_header_size,
written_packet.data.size() - expected_header_size));
}
} // namespace
TEST(FlexfecHeaderReaderTest, ReadsHeaderWithKBit0SetSingleStream) {
@ -104,7 +205,7 @@ TEST(FlexfecHeaderReaderTest, ReadsHeaderWithKBit0SetSingleStream) {
FlexfecHeaderReader reader;
EXPECT_TRUE(reader.ReadFecHeader(&read_packet));
std::vector<FecPacketStreamProperties> expected = {
std::vector<FecPacketStreamReadProperties> expected = {
{.stream = {.ssrc = 0x01,
.seq_num_base = kSnBase,
.packet_mask_offset = 10,
@ -139,7 +240,7 @@ TEST(FlexfecHeaderReaderTest, ReadsHeaderWithKBit1SetSingleStream) {
FlexfecHeaderReader reader;
EXPECT_TRUE(reader.ReadFecHeader(&read_packet));
std::vector<FecPacketStreamProperties> expected = {
std::vector<FecPacketStreamReadProperties> expected = {
{.stream = {.ssrc = 0x01,
.seq_num_base = kSnBase,
.packet_mask_offset = 10,
@ -198,7 +299,7 @@ TEST(FlexfecHeaderReaderTest, ReadsHeaderWithNoKBitsSetSingleStream) {
FlexfecHeaderReader reader;
EXPECT_TRUE(reader.ReadFecHeader(&read_packet));
std::vector<FecPacketStreamProperties> expected = {
std::vector<FecPacketStreamReadProperties> expected = {
{.stream = {.ssrc = 0x01,
.seq_num_base = kSnBase,
.packet_mask_offset = 10,
@ -232,7 +333,7 @@ TEST(FlexfecHeaderReaderTest, ReadsHeaderWithKBit0Set2Streams) {
FlexfecHeaderReader reader;
EXPECT_TRUE(reader.ReadFecHeader(&read_packet));
std::vector<FecPacketStreamProperties> expected = {
std::vector<FecPacketStreamReadProperties> expected = {
{.stream = {.ssrc = 0x01,
.seq_num_base = kSnBase0,
.packet_mask_offset = 10,
@ -281,7 +382,7 @@ TEST(FlexfecHeaderReaderTest, ReadsHeaderWithKBit1Set2Streams) {
FlexfecHeaderReader reader;
EXPECT_TRUE(reader.ReadFecHeader(&read_packet));
std::vector<FecPacketStreamProperties> expected = {
std::vector<FecPacketStreamReadProperties> expected = {
{.stream = {.ssrc = 0x01,
.seq_num_base = kSnBase0,
.packet_mask_offset = 10,
@ -372,7 +473,7 @@ TEST(FlexfecHeaderReaderTest, ReadsHeaderWithNoKBitsSet2Streams) {
FlexfecHeaderReader reader;
EXPECT_TRUE(reader.ReadFecHeader(&read_packet));
std::vector<FecPacketStreamProperties> expected = {
std::vector<FecPacketStreamReadProperties> expected = {
{.stream = {.ssrc = 0x01,
.seq_num_base = kSnBase0,
.packet_mask_offset = 10,
@ -471,7 +572,7 @@ TEST(FlexfecHeaderReaderTest, ReadsHeaderWithMultipleStreamsMultipleMasks) {
FlexfecHeaderReader reader;
EXPECT_TRUE(reader.ReadFecHeader(&read_packet));
std::vector<FecPacketStreamProperties> expected = {
std::vector<FecPacketStreamReadProperties> expected = {
{.stream = {.ssrc = 0x01,
.seq_num_base = kSnBase0,
.packet_mask_offset = 10,
@ -597,14 +698,113 @@ TEST(FlexfecHeaderReaderTest, ReadShortPacketMultipleStreamsShouldFail) {
EXPECT_FALSE(reader.ReadFecHeader(&read_packet));
}
TEST(FlexfecHeaderWriterTest, FinalizesHeaderWithKBit0SetSingleStream) {
constexpr uint8_t kFlexfecPacketMask[] = {0x88, 0x81};
constexpr uint8_t kUlpfecPacketMask[] = {0x11, 0x02};
constexpr uint16_t kMediaStartSeqNum = 1234;
Packet written_packet = WritePacket({{.ssrc = 0x01,
.seq_num_base = kMediaStartSeqNum,
.packet_mask = kUlpfecPacketMask}});
std::vector<FecPacketStreamWriteProperties> expected = {
{.byte_index = 8,
.seq_num_base = kMediaStartSeqNum,
.mask = kFlexfecPacketMask}};
VerifyFinalizedHeaders(written_packet, expected);
}
TEST(FlexfecHeaderWriterTest, FinalizesHeaderWithKBit1SetSingleStream) {
constexpr uint8_t kFlexfecPacketMask[] = {0x48, 0x81, 0x82, 0x11, 0x00, 0x21};
constexpr uint8_t kUlpfecPacketMask[] = {0x91, 0x02, 0x08, 0x44, 0x00, 0x84};
constexpr uint16_t kMediaStartSeqNum = 1234;
Packet written_packet = WritePacket({{.ssrc = 0x01,
.seq_num_base = kMediaStartSeqNum,
.packet_mask = kUlpfecPacketMask}});
std::vector<FecPacketStreamWriteProperties> expected = {
{.byte_index = 8,
.seq_num_base = kMediaStartSeqNum,
.mask = kFlexfecPacketMask}};
VerifyFinalizedHeaders(written_packet, expected);
}
TEST(FlexfecHeaderWriterTest, FinalizesHeaderWithNoKBitsSetSingleStream) {
constexpr uint8_t kFlexfecPacketMask[] = {
0x11, 0x11, // K-bit 0 clear.
0x11, 0x11, 0x11, 0x10, // K-bit 1 clear.
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 //
};
constexpr uint8_t kUlpfecPacketMask[] = {0x22, 0x22, 0x44, 0x44, 0x44, 0x41};
constexpr uint16_t kMediaStartSeqNum = 1234;
Packet written_packet = WritePacket({{.ssrc = 0x01,
.seq_num_base = kMediaStartSeqNum,
.packet_mask = kUlpfecPacketMask}});
std::vector<FecPacketStreamWriteProperties> expected = {
{.byte_index = 8,
.seq_num_base = kMediaStartSeqNum,
.mask = kFlexfecPacketMask}};
VerifyFinalizedHeaders(written_packet, expected);
}
TEST(FlexfecHeaderWriterTest, FinalizesHeaderMultipleStreamsMultipleMasks) {
constexpr uint8_t kFlexfecPacketMask1[] = {
0x11, 0x11, // K-bit 0 clear.
0x11, 0x11, 0x11, 0x10, // K-bit 1 clear.
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 //
};
constexpr uint8_t kUlpfecPacketMask1[] = {0x22, 0x22, 0x44, 0x44, 0x44, 0x41};
constexpr uint16_t kMediaStartSeqNum1 = 1234;
constexpr uint8_t kFlexfecPacketMask2[] = {0x88, 0x81};
constexpr uint8_t kUlpfecPacketMask2[] = {0x11, 0x02};
constexpr uint16_t kMediaStartSeqNum2 = 2345;
constexpr uint8_t kFlexfecPacketMask3[] = {0x48, 0x81, 0x82,
0x11, 0x00, 0x21};
constexpr uint8_t kUlpfecPacketMask3[] = {0x91, 0x02, 0x08, 0x44, 0x00, 0x84};
constexpr uint16_t kMediaStartSeqNum3 = 3456;
constexpr uint8_t kFlexfecPacketMask4[] = {
0x55, 0xAA, // K-bit 0 clear.
0x22, 0xAB, 0xCD, 0xEF, // K-bit 1 clear.
0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 //
};
constexpr uint8_t kUlpfecPacketMask4[] = {0xAB, 0x54, 0x8A, 0xAF, 0x37, 0xBF};
constexpr uint16_t kMediaStartSeqNum4 = 4567;
Packet written_packet = WritePacket({{.ssrc = 0x01,
.seq_num_base = kMediaStartSeqNum1,
.packet_mask = kUlpfecPacketMask1},
{.ssrc = 0x02,
.seq_num_base = kMediaStartSeqNum2,
.packet_mask = kUlpfecPacketMask2},
{.ssrc = 0x03,
.seq_num_base = kMediaStartSeqNum3,
.packet_mask = kUlpfecPacketMask3},
{.ssrc = 0x04,
.seq_num_base = kMediaStartSeqNum4,
.packet_mask = kUlpfecPacketMask4}});
std::vector<FecPacketStreamWriteProperties> expected = {
{.byte_index = 8,
.seq_num_base = kMediaStartSeqNum1,
.mask = kFlexfecPacketMask1},
{.byte_index = 24,
.seq_num_base = kMediaStartSeqNum2,
.mask = kFlexfecPacketMask2},
{.byte_index = 28,
.seq_num_base = kMediaStartSeqNum3,
.mask = kFlexfecPacketMask3},
{.byte_index = 36,
.seq_num_base = kMediaStartSeqNum4,
.mask = kFlexfecPacketMask4}};
VerifyFinalizedHeaders(written_packet, expected);
}
// TODO(bugs.webrtc.org/15002): reimplement and add tests for multi stream cases
// after updating the Writer code.
TEST(FlexfecHeaderWriterTest, FinalizesHeaderWithKBit0Set) {}
TEST(FlexfecHeaderWriterTest, FinalizesHeaderWithKBit1Set) {}
TEST(FlexfecHeaderWriterTest, FinalizesHeaderWithKBit2Set) {}
// after updating the MinPacketMaskSize and FecHeaderSize functions.
TEST(FlexfecHeaderWriterTest, ContractsShortUlpfecPacketMaskWithBit15Clear) {}
@ -623,21 +823,107 @@ TEST(FlexfecHeaderWriterTest, ExpandsLongUlpfecPacketMaskWithBit46SetBit47Set) {
}
TEST(FlexfecHeaderReaderWriterTest,
WriteAndReadSmallUlpfecPacketHeaderWithMaskBit15Clear) {}
WriteAndReadSmallUlpfecPacketHeaderWithMaskBit15ClearSingleStream) {
constexpr uint8_t kUlpfecPacketMask[] = {0x11, 0x02}; // Bit 15 clear.
constexpr uint16_t kMediaStartSeqNum = 1234;
constexpr uint16_t kExpectedHeaderSize = 12;
VerifyWrittenAndReadHeaders({{.ssrc = 0x01,
.seq_num_base = kMediaStartSeqNum,
.packet_mask = kUlpfecPacketMask}},
kExpectedHeaderSize);
}
TEST(FlexfecHeaderReaderWriterTest,
WriteAndReadSmallUlpfecPacketHeaderWithMaskBit15Set) {}
WriteAndReadSmallUlpfecPacketHeaderWithMaskBit15SetSingleStream) {
constexpr uint8_t kUlpfecPacketMask[] = {0xAA, 0xFF}; // Bit 15 set.
constexpr uint16_t kMediaStartSeqNum = 1234;
constexpr uint16_t kExpectedHeaderSize = 16;
VerifyWrittenAndReadHeaders({{.ssrc = 0x01,
.seq_num_base = kMediaStartSeqNum,
.packet_mask = kUlpfecPacketMask}},
kExpectedHeaderSize);
}
TEST(FlexfecHeaderReaderWriterTest,
WriteAndReadLargeUlpfecPacketHeaderWithMaskBits46And47Clear) {}
WriteAndReadLargeUlpfecPacketHeaderWithMaskBits46And47ClearSingleStream) {
constexpr uint8_t kUlpfecPacketMask[] = {0x91, 0x02, 0x08, 0x44,
0x00, 0x84}; // Bits 46, 47 clear.
constexpr uint16_t kMediaStartSeqNum = 1234;
constexpr uint16_t kExpectedHeaderSize = 16;
VerifyWrittenAndReadHeaders({{.ssrc = 0x01,
.seq_num_base = kMediaStartSeqNum,
.packet_mask = kUlpfecPacketMask}},
kExpectedHeaderSize);
}
TEST(
FlexfecHeaderReaderWriterTest,
WriteAndReadLargeUlpfecPacketHeaderWithMaskBit46SetBit47ClearSingleStream) {
constexpr uint8_t kUlpfecPacketMask[] = {
0x91, 0x02, 0x08, 0x44, 0x00, 0x86}; // Bit 46 set, bit 47 clear.
constexpr uint16_t kMediaStartSeqNum = 1234;
constexpr uint16_t kExpectedHeaderSize = 24;
VerifyWrittenAndReadHeaders({{.ssrc = 0x01,
.seq_num_base = kMediaStartSeqNum,
.packet_mask = kUlpfecPacketMask}},
kExpectedHeaderSize);
}
TEST(
FlexfecHeaderReaderWriterTest,
WriteAndReadLargeUlpfecPacketHeaderMaskWithBit46ClearBit47SetSingleStream) {
constexpr uint8_t kUlpfecPacketMask[] = {
0x91, 0x02, 0x08, 0x44, 0x00, 0x85}; // Bit 46 clear, bit 47 set.
constexpr uint16_t kMediaStartSeqNum = 1234;
constexpr uint16_t kExpectedHeaderSize = 24;
VerifyWrittenAndReadHeaders({{.ssrc = 0x01,
.seq_num_base = kMediaStartSeqNum,
.packet_mask = kUlpfecPacketMask}},
kExpectedHeaderSize);
}
TEST(FlexfecHeaderReaderWriterTest,
WriteAndReadLargeUlpfecPacketHeaderWithMaskBit46SetBit47Clear) {}
WriteAndReadLargeUlpfecPacketHeaderWithMaskBits46And47SetSingleStream) {
constexpr uint8_t kUlpfecPacketMask[] = {0x91, 0x02, 0x08, 0x44,
0x00, 0x87}; // Bits 46, 47 set.
constexpr uint16_t kMediaStartSeqNum = 1234;
constexpr uint16_t kExpectedHeaderSize = 24;
TEST(FlexfecHeaderReaderWriterTest,
WriteAndReadLargeUlpfecPacketHeaderMaskWithBit46ClearBit47Set) {}
VerifyWrittenAndReadHeaders({{.ssrc = 0x01,
.seq_num_base = kMediaStartSeqNum,
.packet_mask = kUlpfecPacketMask}},
kExpectedHeaderSize);
}
TEST(FlexfecHeaderReaderWriterTest,
WriteAndReadLargeUlpfecPacketHeaderWithMaskBits46And47Set) {}
TEST(FlexfecHeaderReaderWriterTest, WriteAndReadMultipleStreamsMultipleMasks) {
constexpr uint8_t kUlpfecPacketMask1[] = {0x11, 0x02};
constexpr uint16_t kMediaStartSeqNum1 = 1234;
constexpr uint8_t kUlpfecPacketMask2[] = {0x91, 0x02, 0x08, 0x44, 0x00, 0x84};
constexpr uint16_t kMediaStartSeqNum2 = 2345;
constexpr uint8_t kUlpfecPacketMask3[] = {0xAA, 0xFF};
constexpr uint16_t kMediaStartSeqNum3 = 3456;
constexpr uint8_t kUlpfecPacketMask4[] = {0x91, 0x02, 0x08, 0x44, 0x00, 0x87};
constexpr uint16_t kMediaStartSeqNum4 = 4567;
constexpr uint16_t kExpectedHeaderSize = 44;
VerifyWrittenAndReadHeaders({{.ssrc = 0x01,
.seq_num_base = kMediaStartSeqNum1,
.packet_mask = kUlpfecPacketMask1},
{.ssrc = 0x02,
.seq_num_base = kMediaStartSeqNum2,
.packet_mask = kUlpfecPacketMask2},
{.ssrc = 0x03,
.seq_num_base = kMediaStartSeqNum3,
.packet_mask = kUlpfecPacketMask3},
{.ssrc = 0x04,
.seq_num_base = kMediaStartSeqNum4,
.packet_mask = kUlpfecPacketMask4}},
kExpectedHeaderSize);
}
} // namespace webrtc