/* * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "modules/rtp_rtcp/source/flexfec_03_header_reader_writer.h" #include #include #include #include "api/scoped_refptr.h" #include "modules/rtp_rtcp/source/byte_io.h" #include "modules/rtp_rtcp/source/forward_error_correction.h" #include "modules/rtp_rtcp/source/forward_error_correction_internal.h" #include "rtc_base/checks.h" #include "rtc_base/random.h" #include "test/gmock.h" #include "test/gtest.h" namespace webrtc { namespace { using Packet = ForwardErrorCorrection::Packet; using ReceivedFecPacket = ForwardErrorCorrection::ReceivedFecPacket; using ::testing::ElementsAreArray; using ::testing::make_tuple; using ::testing::SizeIs; // General. Assume single-stream protection. constexpr uint32_t kMediaSsrc = 1254983; constexpr uint16_t kMediaStartSeqNum = 825; constexpr size_t kMediaPacketLength = 1234; constexpr uint32_t kFlexfecSsrc = 52142; constexpr size_t kFlexfecHeaderSizes[] = {20, 24, 32}; constexpr size_t kFlexfecPacketMaskOffset = 18; constexpr size_t kFlexfecPacketMaskSizes[] = {2, 6, 14}; constexpr size_t kFlexfecMaxPacketSize = kFlexfecPacketMaskSizes[2]; // Reader tests. constexpr uint8_t kNoRBit = 0 << 7; constexpr uint8_t kNoFBit = 0 << 6; constexpr uint8_t kPtRecovery = 123; constexpr uint8_t kLengthRecov[] = {0xab, 0xcd}; constexpr uint8_t kTsRecovery[] = {0x01, 0x23, 0x45, 0x67}; constexpr uint8_t kSsrcCount = 1; constexpr uint8_t kReservedBits = 0x00; constexpr uint8_t kProtSsrc[] = {0x11, 0x22, 0x33, 0x44}; constexpr uint8_t kSnBase[] = {0xaa, 0xbb}; constexpr uint8_t kPayloadBits = 0x00; std::unique_ptr GeneratePacketMask(size_t packet_mask_size, uint64_t seed) { Random random(seed); std::unique_ptr packet_mask(new uint8_t[kFlexfecMaxPacketSize]); memset(packet_mask.get(), 0, kFlexfecMaxPacketSize); for (size_t i = 0; i < packet_mask_size; ++i) { packet_mask[i] = random.Rand(); } return packet_mask; } void ClearBit(size_t index, uint8_t* packet_mask) { packet_mask[index / 8] &= ~(1 << (7 - index % 8)); } void SetBit(size_t index, uint8_t* packet_mask) { packet_mask[index / 8] |= (1 << (7 - index % 8)); } rtc::scoped_refptr WriteHeader(const uint8_t* packet_mask, size_t packet_mask_size) { Flexfec03HeaderWriter writer; rtc::scoped_refptr written_packet(new 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; // Actual content doesn't matter. } const FecHeaderWriter::ProtectedStream protected_streams[] = { {.ssrc = kMediaSsrc, .seq_num_base = kMediaStartSeqNum, .packet_mask = {packet_mask, packet_mask_size}}}; writer.FinalizeFecHeader(protected_streams, *written_packet); return written_packet; } std::unique_ptr ReadHeader(const Packet& written_packet) { Flexfec03HeaderReader reader; std::unique_ptr read_packet(new ReceivedFecPacket()); read_packet->ssrc = kFlexfecSsrc; read_packet->pkt = rtc::scoped_refptr(new Packet()); read_packet->pkt->data = written_packet.data; EXPECT_TRUE(reader.ReadFecHeader(read_packet.get())); return read_packet; } void VerifyReadHeaders(size_t expected_fec_header_size, const uint8_t* expected_packet_mask, size_t expected_packet_mask_size, const ReceivedFecPacket& read_packet) { EXPECT_EQ(expected_fec_header_size, read_packet.fec_header_size); EXPECT_EQ(ByteReader::ReadBigEndian(kProtSsrc), read_packet.protected_streams[0].ssrc); EXPECT_EQ(ByteReader::ReadBigEndian(kSnBase), read_packet.protected_streams[0].seq_num_base); auto packet_mask_offset = read_packet.protected_streams[0].packet_mask_offset; EXPECT_EQ(kFlexfecPacketMaskOffset, packet_mask_offset); EXPECT_EQ(expected_packet_mask_size, read_packet.protected_streams[0].packet_mask_size); EXPECT_EQ(read_packet.pkt->data.size() - expected_fec_header_size, read_packet.protection_length); // Ensure that the K-bits are removed and the packet mask has been packed. EXPECT_THAT( make_tuple(read_packet.pkt->data.cdata() + packet_mask_offset, read_packet.protected_streams[0].packet_mask_size), ElementsAreArray(expected_packet_mask, expected_packet_mask_size)); } void VerifyFinalizedHeaders(const uint8_t* expected_packet_mask, size_t expected_packet_mask_size, const Packet& written_packet) { const uint8_t* packet = written_packet.data.cdata(); EXPECT_EQ(0x00, packet[0] & 0x80); // F bit clear. EXPECT_EQ(0x00, packet[0] & 0x40); // R bit clear. EXPECT_EQ(0x01, packet[8]); // SSRCCount = 1. EXPECT_EQ(kMediaSsrc, ByteReader::ReadBigEndian(packet + 12)); EXPECT_EQ(kMediaStartSeqNum, ByteReader::ReadBigEndian(packet + 16)); EXPECT_THAT( make_tuple(packet + kFlexfecPacketMaskOffset, expected_packet_mask_size), ElementsAreArray(expected_packet_mask, expected_packet_mask_size)); } void VerifyWrittenAndReadHeaders(size_t expected_fec_header_size, const uint8_t* expected_packet_mask, size_t expected_packet_mask_size, const Packet& written_packet, const ReceivedFecPacket& read_packet) { EXPECT_EQ(kFlexfecSsrc, read_packet.ssrc); EXPECT_EQ(expected_fec_header_size, read_packet.fec_header_size); ASSERT_THAT(read_packet.protected_streams, SizeIs(1)); EXPECT_EQ(read_packet.protected_streams[0].ssrc, kMediaSsrc); EXPECT_EQ(read_packet.protected_streams[0].seq_num_base, kMediaStartSeqNum); EXPECT_EQ(read_packet.protected_streams[0].packet_mask_offset, kFlexfecPacketMaskOffset); ASSERT_EQ(read_packet.protected_streams[0].packet_mask_size, expected_packet_mask_size); EXPECT_EQ(written_packet.data.size() - expected_fec_header_size, read_packet.protection_length); // Verify that the call to ReadFecHeader did normalize the packet masks. EXPECT_THAT( make_tuple(read_packet.pkt->data.cdata() + kFlexfecPacketMaskOffset, read_packet.protected_streams[0].packet_mask_size), ElementsAreArray(expected_packet_mask, expected_packet_mask_size)); // Verify that the call to ReadFecHeader did not tamper with the payload. EXPECT_THAT( make_tuple(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_fec_header_size, written_packet.data.size() - expected_fec_header_size)); } } // namespace TEST(Flexfec03HeaderReaderTest, ReadsHeaderWithKBit0Set) { constexpr uint8_t kKBit0 = 1 << 7; constexpr size_t kExpectedPacketMaskSize = 2; constexpr size_t kExpectedFecHeaderSize = 20; // clang-format off constexpr uint8_t kFlexfecPktMask[] = {kKBit0 | 0x08, 0x81}; constexpr uint8_t kUlpfecPacketMask[] = {0x11, 0x02}; // clang-format on constexpr uint8_t kPacketData[] = { kNoRBit | kNoFBit, kPtRecovery, kLengthRecov[0], kLengthRecov[1], kTsRecovery[0], kTsRecovery[1], kTsRecovery[2], kTsRecovery[3], kSsrcCount, kReservedBits, kReservedBits, kReservedBits, kProtSsrc[0], kProtSsrc[1], kProtSsrc[2], kProtSsrc[3], kSnBase[0], kSnBase[1], kFlexfecPktMask[0], kFlexfecPktMask[1], kPayloadBits, kPayloadBits, kPayloadBits, kPayloadBits}; const size_t packet_length = sizeof(kPacketData); ReceivedFecPacket read_packet; read_packet.pkt = rtc::scoped_refptr(new Packet()); read_packet.pkt->data.SetData(kPacketData, packet_length); Flexfec03HeaderReader reader; EXPECT_TRUE(reader.ReadFecHeader(&read_packet)); VerifyReadHeaders(kExpectedFecHeaderSize, kUlpfecPacketMask, kExpectedPacketMaskSize, read_packet); } TEST(Flexfec03HeaderReaderTest, ReadsHeaderWithKBit1Set) { constexpr uint8_t kKBit0 = 0 << 7; constexpr uint8_t kKBit1 = 1 << 7; constexpr size_t kExpectedPacketMaskSize = 6; constexpr size_t kExpectedFecHeaderSize = 24; // clang-format off constexpr uint8_t kFlxfecPktMsk[] = {kKBit0 | 0x48, 0x81, kKBit1 | 0x02, 0x11, 0x00, 0x21}; constexpr uint8_t kUlpfecPacketMask[] = {0x91, 0x02, 0x08, 0x44, 0x00, 0x84}; // clang-format on constexpr uint8_t kPacketData[] = { kNoRBit | kNoFBit, kPtRecovery, kLengthRecov[0], kLengthRecov[1], kTsRecovery[0], kTsRecovery[1], kTsRecovery[2], kTsRecovery[3], kSsrcCount, kReservedBits, kReservedBits, kReservedBits, kProtSsrc[0], kProtSsrc[1], kProtSsrc[2], kProtSsrc[3], kSnBase[0], kSnBase[1], kFlxfecPktMsk[0], kFlxfecPktMsk[1], kFlxfecPktMsk[2], kFlxfecPktMsk[3], kFlxfecPktMsk[4], kFlxfecPktMsk[5], kPayloadBits, kPayloadBits, kPayloadBits, kPayloadBits}; const size_t packet_length = sizeof(kPacketData); ReceivedFecPacket read_packet; read_packet.pkt = rtc::scoped_refptr(new Packet()); read_packet.pkt->data.SetData(kPacketData, packet_length); Flexfec03HeaderReader reader; EXPECT_TRUE(reader.ReadFecHeader(&read_packet)); VerifyReadHeaders(kExpectedFecHeaderSize, kUlpfecPacketMask, kExpectedPacketMaskSize, read_packet); } TEST(Flexfec03HeaderReaderTest, ReadsHeaderWithKBit2Set) { constexpr uint8_t kKBit0 = 0 << 7; constexpr uint8_t kKBit1 = 0 << 7; constexpr uint8_t kKBit2 = 1 << 7; constexpr size_t kExpectedPacketMaskSize = 14; constexpr size_t kExpectedFecHeaderSize = 32; // clang-format off constexpr uint8_t kFlxfcPktMsk[] = {kKBit0 | 0x48, 0x81, kKBit1 | 0x02, 0x11, 0x00, 0x21, kKBit2 | 0x01, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}; constexpr uint8_t kUlpfecPacketMask[] = {0x91, 0x02, 0x08, 0x44, 0x00, 0x84, 0x08, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88}; // clang-format on constexpr uint8_t kPacketData[] = { kNoRBit | kNoFBit, kPtRecovery, kLengthRecov[0], kLengthRecov[1], kTsRecovery[0], kTsRecovery[1], kTsRecovery[2], kTsRecovery[3], kSsrcCount, kReservedBits, kReservedBits, kReservedBits, kProtSsrc[0], kProtSsrc[1], kProtSsrc[2], kProtSsrc[3], kSnBase[0], kSnBase[1], kFlxfcPktMsk[0], kFlxfcPktMsk[1], kFlxfcPktMsk[2], kFlxfcPktMsk[3], kFlxfcPktMsk[4], kFlxfcPktMsk[5], kFlxfcPktMsk[6], kFlxfcPktMsk[7], kFlxfcPktMsk[8], kFlxfcPktMsk[9], kFlxfcPktMsk[10], kFlxfcPktMsk[11], kFlxfcPktMsk[12], kFlxfcPktMsk[13], kPayloadBits, kPayloadBits, kPayloadBits, kPayloadBits}; const size_t packet_length = sizeof(kPacketData); ReceivedFecPacket read_packet; read_packet.pkt = rtc::scoped_refptr(new Packet()); read_packet.pkt->data.SetData(kPacketData, packet_length); Flexfec03HeaderReader reader; EXPECT_TRUE(reader.ReadFecHeader(&read_packet)); VerifyReadHeaders(kExpectedFecHeaderSize, kUlpfecPacketMask, kExpectedPacketMaskSize, read_packet); } TEST(Flexfec03HeaderReaderTest, ReadPacketWithoutStreamSpecificHeaderShouldFail) { const size_t packet_mask_size = kUlpfecPacketMaskSizeLBitClear; auto packet_mask = GeneratePacketMask(packet_mask_size, 0xabcd); auto written_packet = WriteHeader(packet_mask.get(), packet_mask_size); // Simulate short received packet. ReceivedFecPacket read_packet; read_packet.ssrc = kFlexfecSsrc; read_packet.pkt = std::move(written_packet); read_packet.pkt->data.SetSize(12); Flexfec03HeaderReader reader; EXPECT_FALSE(reader.ReadFecHeader(&read_packet)); } TEST(Flexfec03HeaderReaderTest, ReadShortPacketWithKBit0SetShouldFail) { const size_t packet_mask_size = kUlpfecPacketMaskSizeLBitClear; auto packet_mask = GeneratePacketMask(packet_mask_size, 0xabcd); auto written_packet = WriteHeader(packet_mask.get(), packet_mask_size); // Simulate short received packet. ReceivedFecPacket read_packet; read_packet.ssrc = kFlexfecSsrc; read_packet.pkt = std::move(written_packet); read_packet.pkt->data.SetSize(18); Flexfec03HeaderReader reader; EXPECT_FALSE(reader.ReadFecHeader(&read_packet)); } TEST(Flexfec03HeaderReaderTest, ReadShortPacketWithKBit1SetShouldFail) { const size_t packet_mask_size = kUlpfecPacketMaskSizeLBitClear; auto packet_mask = GeneratePacketMask(packet_mask_size, 0xabcd); SetBit(15, packet_mask.get()); // This expands the packet mask "once". auto written_packet = WriteHeader(packet_mask.get(), packet_mask_size); // Simulate short received packet. ReceivedFecPacket read_packet; read_packet.ssrc = kFlexfecSsrc; read_packet.pkt = std::move(written_packet); read_packet.pkt->data.SetSize(20); Flexfec03HeaderReader reader; EXPECT_FALSE(reader.ReadFecHeader(&read_packet)); } TEST(Flexfec03HeaderReaderTest, ReadShortPacketWithKBit2SetShouldFail) { const size_t packet_mask_size = kUlpfecPacketMaskSizeLBitSet; auto packet_mask = GeneratePacketMask(packet_mask_size, 0xabcd); SetBit(47, packet_mask.get()); // This expands the packet mask "twice". auto written_packet = WriteHeader(packet_mask.get(), packet_mask_size); // Simulate short received packet. ReceivedFecPacket read_packet; read_packet.ssrc = kFlexfecSsrc; read_packet.pkt = std::move(written_packet); read_packet.pkt->data.SetSize(24); Flexfec03HeaderReader reader; EXPECT_FALSE(reader.ReadFecHeader(&read_packet)); } TEST(Flexfec03HeaderWriterTest, FinalizesHeaderWithKBit0Set) { constexpr size_t kExpectedPacketMaskSize = 2; constexpr uint8_t kFlexfecPacketMask[] = {0x88, 0x81}; constexpr uint8_t kUlpfecPacketMask[] = {0x11, 0x02}; 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; } Flexfec03HeaderWriter writer; const FecHeaderWriter::ProtectedStream protected_streams[] = { {.ssrc = kMediaSsrc, .seq_num_base = kMediaStartSeqNum, .packet_mask = kUlpfecPacketMask}}; writer.FinalizeFecHeader(protected_streams, written_packet); VerifyFinalizedHeaders(kFlexfecPacketMask, kExpectedPacketMaskSize, written_packet); } TEST(Flexfec03HeaderWriterTest, FinalizesHeaderWithKBit1Set) { constexpr size_t kExpectedPacketMaskSize = 6; constexpr uint8_t kFlexfecPacketMask[] = {0x48, 0x81, 0x82, 0x11, 0x00, 0x21}; constexpr uint8_t kUlpfecPacketMask[] = {0x91, 0x02, 0x08, 0x44, 0x00, 0x84}; 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; } Flexfec03HeaderWriter writer; const FecHeaderWriter::ProtectedStream protected_streams[] = { {.ssrc = kMediaSsrc, .seq_num_base = kMediaStartSeqNum, .packet_mask = kUlpfecPacketMask}}; writer.FinalizeFecHeader(protected_streams, written_packet); VerifyFinalizedHeaders(kFlexfecPacketMask, kExpectedPacketMaskSize, written_packet); } TEST(Flexfec03HeaderWriterTest, FinalizesHeaderWithKBit2Set) { constexpr size_t kExpectedPacketMaskSize = 14; constexpr uint8_t kFlexfecPacketMask[] = { 0x11, 0x11, // K-bit 0 clear. 0x11, 0x11, 0x11, 0x10, // K-bit 1 clear. 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // K-bit 2 set. }; constexpr uint8_t kUlpfecPacketMask[] = {0x22, 0x22, 0x44, 0x44, 0x44, 0x41}; 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; } Flexfec03HeaderWriter writer; const FecHeaderWriter::ProtectedStream protected_streams[] = { {.ssrc = kMediaSsrc, .seq_num_base = kMediaStartSeqNum, .packet_mask = kUlpfecPacketMask}}; writer.FinalizeFecHeader(protected_streams, written_packet); VerifyFinalizedHeaders(kFlexfecPacketMask, kExpectedPacketMaskSize, written_packet); } TEST(Flexfec03HeaderWriterTest, ContractsShortUlpfecPacketMaskWithBit15Clear) { const size_t packet_mask_size = kUlpfecPacketMaskSizeLBitClear; auto packet_mask = GeneratePacketMask(packet_mask_size, 0xabcd); ClearBit(15, packet_mask.get()); Flexfec03HeaderWriter writer; size_t min_packet_mask_size = writer.MinPacketMaskSize(packet_mask.get(), packet_mask_size); EXPECT_EQ(kFlexfecPacketMaskSizes[0], min_packet_mask_size); EXPECT_EQ(kFlexfecHeaderSizes[0], writer.FecHeaderSize(min_packet_mask_size)); } TEST(Flexfec03HeaderWriterTest, ExpandsShortUlpfecPacketMaskWithBit15Set) { const size_t packet_mask_size = kUlpfecPacketMaskSizeLBitClear; auto packet_mask = GeneratePacketMask(packet_mask_size, 0xabcd); SetBit(15, packet_mask.get()); Flexfec03HeaderWriter writer; size_t min_packet_mask_size = writer.MinPacketMaskSize(packet_mask.get(), packet_mask_size); EXPECT_EQ(kFlexfecPacketMaskSizes[1], min_packet_mask_size); EXPECT_EQ(kFlexfecHeaderSizes[1], writer.FecHeaderSize(min_packet_mask_size)); } TEST(Flexfec03HeaderWriterTest, ContractsLongUlpfecPacketMaskWithBit46ClearBit47Clear) { const size_t packet_mask_size = kUlpfecPacketMaskSizeLBitSet; auto packet_mask = GeneratePacketMask(packet_mask_size, 0xabcd); ClearBit(46, packet_mask.get()); ClearBit(47, packet_mask.get()); Flexfec03HeaderWriter writer; size_t min_packet_mask_size = writer.MinPacketMaskSize(packet_mask.get(), packet_mask_size); EXPECT_EQ(kFlexfecPacketMaskSizes[1], min_packet_mask_size); EXPECT_EQ(kFlexfecHeaderSizes[1], writer.FecHeaderSize(min_packet_mask_size)); } TEST(Flexfec03HeaderWriterTest, ExpandsLongUlpfecPacketMaskWithBit46SetBit47Clear) { const size_t packet_mask_size = kUlpfecPacketMaskSizeLBitSet; auto packet_mask = GeneratePacketMask(packet_mask_size, 0xabcd); SetBit(46, packet_mask.get()); ClearBit(47, packet_mask.get()); Flexfec03HeaderWriter writer; size_t min_packet_mask_size = writer.MinPacketMaskSize(packet_mask.get(), packet_mask_size); EXPECT_EQ(kFlexfecPacketMaskSizes[2], min_packet_mask_size); EXPECT_EQ(kFlexfecHeaderSizes[2], writer.FecHeaderSize(min_packet_mask_size)); } TEST(Flexfec03HeaderWriterTest, ExpandsLongUlpfecPacketMaskWithBit46ClearBit47Set) { const size_t packet_mask_size = kUlpfecPacketMaskSizeLBitSet; auto packet_mask = GeneratePacketMask(packet_mask_size, 0xabcd); ClearBit(46, packet_mask.get()); SetBit(47, packet_mask.get()); Flexfec03HeaderWriter writer; size_t min_packet_mask_size = writer.MinPacketMaskSize(packet_mask.get(), packet_mask_size); EXPECT_EQ(kFlexfecPacketMaskSizes[2], min_packet_mask_size); EXPECT_EQ(kFlexfecHeaderSizes[2], writer.FecHeaderSize(min_packet_mask_size)); } TEST(Flexfec03HeaderWriterTest, ExpandsLongUlpfecPacketMaskWithBit46SetBit47Set) { const size_t packet_mask_size = kUlpfecPacketMaskSizeLBitSet; auto packet_mask = GeneratePacketMask(packet_mask_size, 0xabcd); SetBit(46, packet_mask.get()); SetBit(47, packet_mask.get()); Flexfec03HeaderWriter writer; size_t min_packet_mask_size = writer.MinPacketMaskSize(packet_mask.get(), packet_mask_size); EXPECT_EQ(kFlexfecPacketMaskSizes[2], min_packet_mask_size); EXPECT_EQ(kFlexfecHeaderSizes[2], writer.FecHeaderSize(min_packet_mask_size)); } TEST(Flexfec03HeaderReaderWriterTest, WriteAndReadSmallUlpfecPacketHeaderWithMaskBit15Clear) { const size_t packet_mask_size = kUlpfecPacketMaskSizeLBitClear; auto packet_mask = GeneratePacketMask(packet_mask_size, 0xabcd); ClearBit(15, packet_mask.get()); auto written_packet = WriteHeader(packet_mask.get(), packet_mask_size); auto read_packet = ReadHeader(*written_packet); VerifyWrittenAndReadHeaders(kFlexfecHeaderSizes[0], packet_mask.get(), kFlexfecPacketMaskSizes[0], *written_packet, *read_packet); } TEST(Flexfec03HeaderReaderWriterTest, WriteAndReadSmallUlpfecPacketHeaderWithMaskBit15Set) { const size_t packet_mask_size = kUlpfecPacketMaskSizeLBitClear; auto packet_mask = GeneratePacketMask(packet_mask_size, 0xabcd); SetBit(15, packet_mask.get()); auto written_packet = WriteHeader(packet_mask.get(), packet_mask_size); auto read_packet = ReadHeader(*written_packet); VerifyWrittenAndReadHeaders(kFlexfecHeaderSizes[1], packet_mask.get(), kFlexfecPacketMaskSizes[1], *written_packet, *read_packet); } TEST(Flexfec03HeaderReaderWriterTest, WriteAndReadLargeUlpfecPacketHeaderWithMaskBits46And47Clear) { const size_t packet_mask_size = kUlpfecPacketMaskSizeLBitSet; auto packet_mask = GeneratePacketMask(packet_mask_size, 0xabcd); ClearBit(46, packet_mask.get()); ClearBit(47, packet_mask.get()); auto written_packet = WriteHeader(packet_mask.get(), packet_mask_size); auto read_packet = ReadHeader(*written_packet); VerifyWrittenAndReadHeaders(kFlexfecHeaderSizes[1], packet_mask.get(), kFlexfecPacketMaskSizes[1], *written_packet, *read_packet); } TEST(Flexfec03HeaderReaderWriterTest, WriteAndReadLargeUlpfecPacketHeaderWithMaskBit46SetBit47Clear) { const size_t packet_mask_size = kUlpfecPacketMaskSizeLBitSet; auto packet_mask = GeneratePacketMask(packet_mask_size, 0xabcd); SetBit(46, packet_mask.get()); ClearBit(47, packet_mask.get()); auto written_packet = WriteHeader(packet_mask.get(), packet_mask_size); auto read_packet = ReadHeader(*written_packet); VerifyWrittenAndReadHeaders(kFlexfecHeaderSizes[2], packet_mask.get(), kFlexfecPacketMaskSizes[2], *written_packet, *read_packet); } TEST(Flexfec03HeaderReaderWriterTest, WriteAndReadLargeUlpfecPacketHeaderMaskWithBit46ClearBit47Set) { const size_t packet_mask_size = kUlpfecPacketMaskSizeLBitSet; auto packet_mask = GeneratePacketMask(packet_mask_size, 0xabcd); ClearBit(46, packet_mask.get()); SetBit(47, packet_mask.get()); auto written_packet = WriteHeader(packet_mask.get(), packet_mask_size); auto read_packet = ReadHeader(*written_packet); VerifyWrittenAndReadHeaders(kFlexfecHeaderSizes[2], packet_mask.get(), kFlexfecPacketMaskSizes[2], *written_packet, *read_packet); } TEST(Flexfec03HeaderReaderWriterTest, WriteAndReadLargeUlpfecPacketHeaderWithMaskBits46And47Set) { const size_t packet_mask_size = kUlpfecPacketMaskSizeLBitSet; auto packet_mask = GeneratePacketMask(packet_mask_size, 0xabcd); SetBit(46, packet_mask.get()); SetBit(47, packet_mask.get()); auto written_packet = WriteHeader(packet_mask.get(), packet_mask_size); auto read_packet = ReadHeader(*written_packet); VerifyWrittenAndReadHeaders(kFlexfecHeaderSizes[2], packet_mask.get(), kFlexfecPacketMaskSizes[2], *written_packet, *read_packet); } } // namespace webrtc