mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-17 15:47:53 +01:00

As per the comment in https://webrtc-review.googlesource.com/c/src/+/303240 on the flexfec_header_reader_writer2.h, renaming this file to flexfec_header_reader_writer.h and renaming the current implementation to flexfec_03_header_reader_writer.h as it is based on the 03 draft of the RFC. Change-Id: I80cb2aba6225ec7cd989a134c3204d1db0ac6f7c Bug: webrtc:15002 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/307600 Reviewed-by: Danil Chapovalov <danilchap@webrtc.org> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/main@{#40231}
643 lines
30 KiB
C++
643 lines
30 KiB
C++
/*
|
|
* Copyright (c) 2023 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_header_reader_writer.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <memory>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "api/array_view.h"
|
|
#include "api/make_ref_counted.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 ProtectedStream = ForwardErrorCorrection::ProtectedStream;
|
|
using ReceivedFecPacket = ForwardErrorCorrection::ReceivedFecPacket;
|
|
using ::testing::ElementsAreArray;
|
|
|
|
constexpr uint8_t kMask0[] = {0xAB, 0xCD}; // First K bit is set.
|
|
constexpr uint8_t kMask1[] = {0x12, 0x34, // First K bit cleared.
|
|
0xF6, 0x78, 0x9A, 0xBC}; // Second K bit set.
|
|
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};
|
|
|
|
// Reader tests.
|
|
constexpr uint8_t kFlexible = 0b00 << 6;
|
|
constexpr uint8_t kPtRecovery = 123;
|
|
constexpr uint8_t kLengthRecovery[] = {0xab, 0xcd};
|
|
constexpr uint8_t kTsRecovery[] = {0x01, 0x23, 0x45, 0x67};
|
|
constexpr uint8_t kSnBases[4][2] = {{0x01, 0x02},
|
|
{0x03, 0x04},
|
|
{0x05, 0x06},
|
|
{0x07, 0x08}};
|
|
constexpr uint8_t kPayloadBits = 0x00;
|
|
|
|
struct FecPacketStreamProperties {
|
|
ProtectedStream stream;
|
|
rtc::ArrayView<const uint8_t> mask;
|
|
};
|
|
|
|
void VerifyReadHeaders(size_t expected_fec_header_size,
|
|
const ReceivedFecPacket& read_packet,
|
|
std::vector<FecPacketStreamProperties> 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());
|
|
for (size_t i = 0; i < protected_streams_num; ++i) {
|
|
SCOPED_TRACE(i);
|
|
ProtectedStream protected_stream = read_packet.protected_streams[i];
|
|
EXPECT_EQ(protected_stream.ssrc, expected[i].stream.ssrc);
|
|
EXPECT_EQ(protected_stream.seq_num_base, expected[i].stream.seq_num_base);
|
|
EXPECT_EQ(protected_stream.packet_mask_offset,
|
|
expected[i].stream.packet_mask_offset);
|
|
EXPECT_EQ(protected_stream.packet_mask_size,
|
|
expected[i].stream.packet_mask_size);
|
|
// Ensure that the K-bits are removed and the packet mask has been packed.
|
|
EXPECT_THAT(rtc::MakeArrayView(read_packet.pkt->data.cdata() +
|
|
protected_stream.packet_mask_offset,
|
|
protected_stream.packet_mask_size),
|
|
ElementsAreArray(expected[i].mask));
|
|
}
|
|
EXPECT_EQ(read_packet.pkt->data.size() - expected_fec_header_size,
|
|
read_packet.protection_length);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
TEST(FlexfecHeaderReaderTest, ReadsHeaderWithKBit0SetSingleStream) {
|
|
constexpr uint8_t kKBit0 = 1 << 7;
|
|
constexpr size_t kExpectedFecHeaderSize = 12;
|
|
constexpr uint16_t kSnBase = 0x0102;
|
|
constexpr uint8_t kFlexfecPktMask[] = {kKBit0 | 0x08, 0x81};
|
|
constexpr uint8_t kUlpfecPacketMask[] = {0x11, 0x02};
|
|
constexpr uint8_t kPacketData[] = {
|
|
kFlexible, kPtRecovery, kLengthRecovery[0], kLengthRecovery[1],
|
|
kTsRecovery[0], kTsRecovery[1], kTsRecovery[2], kTsRecovery[3],
|
|
kSnBase >> 8, kSnBase & 0xFF, kFlexfecPktMask[0], kFlexfecPktMask[1],
|
|
kPayloadBits, kPayloadBits, kPayloadBits, kPayloadBits};
|
|
ReceivedFecPacket read_packet;
|
|
read_packet.pkt = rtc::make_ref_counted<Packet>();
|
|
read_packet.pkt->data.SetData(kPacketData);
|
|
read_packet.protected_streams = {{.ssrc = 0x01}};
|
|
|
|
FlexfecHeaderReader reader;
|
|
EXPECT_TRUE(reader.ReadFecHeader(&read_packet));
|
|
|
|
std::vector<FecPacketStreamProperties> expected = {
|
|
{.stream = {.ssrc = 0x01,
|
|
.seq_num_base = kSnBase,
|
|
.packet_mask_offset = 10,
|
|
.packet_mask_size = std::size(kUlpfecPacketMask)},
|
|
.mask = kUlpfecPacketMask}};
|
|
|
|
VerifyReadHeaders(kExpectedFecHeaderSize, read_packet, expected);
|
|
}
|
|
|
|
TEST(FlexfecHeaderReaderTest, ReadsHeaderWithKBit1SetSingleStream) {
|
|
constexpr uint8_t kKBit0 = 0 << 7;
|
|
constexpr uint8_t kKBit1 = 1 << 7;
|
|
constexpr size_t kExpectedFecHeaderSize = 16;
|
|
constexpr uint16_t kSnBase = 0x0102;
|
|
constexpr uint8_t kFlexfecPktMask[] = {kKBit0 | 0x48, 0x81, //
|
|
kKBit1 | 0x02, 0x11, 0x00, 0x21};
|
|
constexpr uint8_t kUlpfecPacketMask[] = {0x91, 0x02, //
|
|
0x08, 0x44, 0x00, 0x84};
|
|
constexpr uint8_t kPacketData[] = {
|
|
kFlexible, kPtRecovery, kLengthRecovery[0],
|
|
kLengthRecovery[1], kTsRecovery[0], kTsRecovery[1],
|
|
kTsRecovery[2], kTsRecovery[3], kSnBase >> 8,
|
|
kSnBase & 0xFF, kFlexfecPktMask[0], kFlexfecPktMask[1],
|
|
kFlexfecPktMask[2], kFlexfecPktMask[3], kFlexfecPktMask[4],
|
|
kFlexfecPktMask[5], kPayloadBits, kPayloadBits,
|
|
kPayloadBits, kPayloadBits};
|
|
ReceivedFecPacket read_packet;
|
|
read_packet.pkt = rtc::make_ref_counted<Packet>();
|
|
read_packet.pkt->data.SetData(kPacketData);
|
|
read_packet.protected_streams = {{.ssrc = 0x01}};
|
|
|
|
FlexfecHeaderReader reader;
|
|
EXPECT_TRUE(reader.ReadFecHeader(&read_packet));
|
|
|
|
std::vector<FecPacketStreamProperties> expected = {
|
|
{.stream = {.ssrc = 0x01,
|
|
.seq_num_base = kSnBase,
|
|
.packet_mask_offset = 10,
|
|
.packet_mask_size = std::size(kUlpfecPacketMask)},
|
|
.mask = kUlpfecPacketMask}};
|
|
|
|
VerifyReadHeaders(kExpectedFecHeaderSize, read_packet, expected);
|
|
}
|
|
|
|
TEST(FlexfecHeaderReaderTest, ReadsHeaderWithNoKBitsSetSingleStream) {
|
|
constexpr uint8_t kKBit0 = 0 << 7;
|
|
constexpr uint8_t kKBit1 = 0 << 7;
|
|
constexpr size_t kExpectedFecHeaderSize = 24;
|
|
constexpr uint16_t kSnBase = 0x0102;
|
|
constexpr uint8_t kFlexfecPacketMask[] = {kKBit0 | 0x48, 0x81, //
|
|
kKBit1 | 0x02, 0x11, 0x00, 0x21, //
|
|
0x01, 0x11, 0x11, 0x11,
|
|
0x11, 0x11, 0x11, 0x11};
|
|
constexpr uint8_t kUlpfecPacketMask[] = {0x91, 0x02, //
|
|
0x08, 0x44, 0x00, 0x84, //
|
|
0x04, 0x44, 0x44, 0x44,
|
|
0x44, 0x44, 0x44, 0x44};
|
|
constexpr uint8_t kPacketData[] = {kFlexible,
|
|
kPtRecovery,
|
|
kLengthRecovery[0],
|
|
kLengthRecovery[1],
|
|
kTsRecovery[0],
|
|
kTsRecovery[1],
|
|
kTsRecovery[2],
|
|
kTsRecovery[3],
|
|
kSnBase >> 8,
|
|
kSnBase & 0xFF,
|
|
kFlexfecPacketMask[0],
|
|
kFlexfecPacketMask[1],
|
|
kFlexfecPacketMask[2],
|
|
kFlexfecPacketMask[3],
|
|
kFlexfecPacketMask[4],
|
|
kFlexfecPacketMask[5],
|
|
kFlexfecPacketMask[6],
|
|
kFlexfecPacketMask[7],
|
|
kFlexfecPacketMask[8],
|
|
kFlexfecPacketMask[9],
|
|
kFlexfecPacketMask[10],
|
|
kFlexfecPacketMask[11],
|
|
kFlexfecPacketMask[12],
|
|
kFlexfecPacketMask[13],
|
|
kPayloadBits,
|
|
kPayloadBits,
|
|
kPayloadBits,
|
|
kPayloadBits};
|
|
ReceivedFecPacket read_packet;
|
|
read_packet.pkt = rtc::make_ref_counted<Packet>();
|
|
read_packet.pkt->data.SetData(kPacketData);
|
|
read_packet.protected_streams = {{.ssrc = 0x01}};
|
|
|
|
FlexfecHeaderReader reader;
|
|
EXPECT_TRUE(reader.ReadFecHeader(&read_packet));
|
|
|
|
std::vector<FecPacketStreamProperties> expected = {
|
|
{.stream = {.ssrc = 0x01,
|
|
.seq_num_base = kSnBase,
|
|
.packet_mask_offset = 10,
|
|
.packet_mask_size = std::size(kUlpfecPacketMask)},
|
|
.mask = kUlpfecPacketMask}};
|
|
|
|
VerifyReadHeaders(kExpectedFecHeaderSize, read_packet, expected);
|
|
}
|
|
|
|
TEST(FlexfecHeaderReaderTest, ReadsHeaderWithKBit0Set2Streams) {
|
|
constexpr uint8_t kKBit0 = 1 << 7;
|
|
constexpr size_t kExpectedFecHeaderSize = 16;
|
|
constexpr uint16_t kSnBase0 = 0x0102;
|
|
constexpr uint16_t kSnBase1 = 0x0304;
|
|
constexpr uint8_t kFlexfecPktMask1[] = {kKBit0 | 0x08, 0x81};
|
|
constexpr uint8_t kUlpfecPacketMask1[] = {0x11, 0x02};
|
|
constexpr uint8_t kFlexfecPktMask2[] = {kKBit0 | 0x04, 0x41};
|
|
constexpr uint8_t kUlpfecPacketMask2[] = {0x08, 0x82};
|
|
|
|
constexpr uint8_t kPacketData[] = {
|
|
kFlexible, kPtRecovery, kLengthRecovery[0], kLengthRecovery[1],
|
|
kTsRecovery[0], kTsRecovery[1], kTsRecovery[2], kTsRecovery[3],
|
|
kSnBase0 >> 8, kSnBase0 & 0xFF, kFlexfecPktMask1[0], kFlexfecPktMask1[1],
|
|
kSnBase1 >> 8, kSnBase1 & 0xFF, kFlexfecPktMask2[0], kFlexfecPktMask2[1],
|
|
kPayloadBits, kPayloadBits, kPayloadBits, kPayloadBits};
|
|
ReceivedFecPacket read_packet;
|
|
read_packet.pkt = rtc::make_ref_counted<Packet>();
|
|
read_packet.pkt->data.SetData(kPacketData);
|
|
read_packet.protected_streams = {{.ssrc = 0x01}, {.ssrc = 0x02}};
|
|
|
|
FlexfecHeaderReader reader;
|
|
EXPECT_TRUE(reader.ReadFecHeader(&read_packet));
|
|
|
|
std::vector<FecPacketStreamProperties> expected = {
|
|
{.stream = {.ssrc = 0x01,
|
|
.seq_num_base = kSnBase0,
|
|
.packet_mask_offset = 10,
|
|
.packet_mask_size = std::size(kUlpfecPacketMask1)},
|
|
.mask = kUlpfecPacketMask1},
|
|
{.stream = {.ssrc = 0x02,
|
|
.seq_num_base = kSnBase1,
|
|
.packet_mask_offset = 14,
|
|
.packet_mask_size = std::size(kUlpfecPacketMask2)},
|
|
.mask = kUlpfecPacketMask2},
|
|
};
|
|
|
|
VerifyReadHeaders(kExpectedFecHeaderSize, read_packet, expected);
|
|
}
|
|
|
|
TEST(FlexfecHeaderReaderTest, ReadsHeaderWithKBit1Set2Streams) {
|
|
constexpr uint8_t kKBit0 = 0 << 7;
|
|
constexpr uint8_t kKBit1 = 1 << 7;
|
|
constexpr size_t kExpectedFecHeaderSize = 24;
|
|
constexpr uint16_t kSnBase0 = 0x0102;
|
|
constexpr uint16_t kSnBase1 = 0x0304;
|
|
constexpr uint8_t kFlexfecPktMask1[] = {kKBit0 | 0x48, 0x81, //
|
|
kKBit1 | 0x02, 0x11, 0x00, 0x21};
|
|
constexpr uint8_t kUlpfecPacketMask1[] = {0x91, 0x02, //
|
|
0x08, 0x44, 0x00, 0x84};
|
|
constexpr uint8_t kFlexfecPktMask2[] = {kKBit0 | 0x57, 0x82, //
|
|
kKBit1 | 0x04, 0x33, 0x00, 0x51};
|
|
constexpr uint8_t kUlpfecPacketMask2[] = {0xAF, 0x04, //
|
|
0x10, 0xCC, 0x01, 0x44};
|
|
constexpr uint8_t kPacketData[] = {
|
|
kFlexible, kPtRecovery, kLengthRecovery[0],
|
|
kLengthRecovery[1], kTsRecovery[0], kTsRecovery[1],
|
|
kTsRecovery[2], kTsRecovery[3], kSnBase0 >> 8,
|
|
kSnBase0 & 0xFF, kFlexfecPktMask1[0], kFlexfecPktMask1[1],
|
|
kFlexfecPktMask1[2], kFlexfecPktMask1[3], kFlexfecPktMask1[4],
|
|
kFlexfecPktMask1[5], kSnBase1 >> 8, kSnBase1 & 0xFF,
|
|
kFlexfecPktMask2[0], kFlexfecPktMask2[1], kFlexfecPktMask2[2],
|
|
kFlexfecPktMask2[3], kFlexfecPktMask2[4], kFlexfecPktMask2[5],
|
|
kPayloadBits, kPayloadBits, kPayloadBits,
|
|
kPayloadBits};
|
|
ReceivedFecPacket read_packet;
|
|
read_packet.pkt = rtc::make_ref_counted<Packet>();
|
|
read_packet.pkt->data.SetData(kPacketData);
|
|
read_packet.protected_streams = {{.ssrc = 0x01}, {.ssrc = 0x02}};
|
|
|
|
FlexfecHeaderReader reader;
|
|
EXPECT_TRUE(reader.ReadFecHeader(&read_packet));
|
|
|
|
std::vector<FecPacketStreamProperties> expected = {
|
|
{.stream = {.ssrc = 0x01,
|
|
.seq_num_base = kSnBase0,
|
|
.packet_mask_offset = 10,
|
|
.packet_mask_size = std::size(kUlpfecPacketMask1)},
|
|
.mask = kUlpfecPacketMask1},
|
|
{.stream = {.ssrc = 0x02,
|
|
.seq_num_base = kSnBase1,
|
|
.packet_mask_offset = 18,
|
|
.packet_mask_size = std::size(kUlpfecPacketMask2)},
|
|
.mask = kUlpfecPacketMask2},
|
|
};
|
|
|
|
VerifyReadHeaders(kExpectedFecHeaderSize, read_packet, expected);
|
|
}
|
|
|
|
TEST(FlexfecHeaderReaderTest, ReadsHeaderWithNoKBitsSet2Streams) {
|
|
constexpr uint8_t kKBit0 = 0 << 7;
|
|
constexpr uint8_t kKBit1 = 0 << 7;
|
|
constexpr size_t kExpectedFecHeaderSize = 40;
|
|
constexpr uint16_t kSnBase0 = 0x0102;
|
|
constexpr uint16_t kSnBase1 = 0x0304;
|
|
constexpr uint8_t kFlexfecPktMask1[] = {kKBit0 | 0x48, 0x81, //
|
|
kKBit1 | 0x02, 0x11, 0x00, 0x21, //
|
|
0x01, 0x11, 0x11, 0x11,
|
|
0x11, 0x11, 0x11, 0x11};
|
|
constexpr uint8_t kUlpfecPacketMask1[] = {0x91, 0x02, //
|
|
0x08, 0x44, 0x00, 0x84, //
|
|
0x04, 0x44, 0x44, 0x44,
|
|
0x44, 0x44, 0x44, 0x44};
|
|
constexpr uint8_t kFlexfecPktMask2[] = {kKBit0 | 0x32, 0x84, //
|
|
kKBit1 | 0x05, 0x23, 0x00, 0x55, //
|
|
0xA3, 0x22, 0x22, 0x22,
|
|
0x22, 0x22, 0x22, 0x35};
|
|
constexpr uint8_t kUlpfecPacketMask2[] = {0x65, 0x08, //
|
|
0x14, 0x8C, 0x01, 0x56, //
|
|
0x8C, 0x88, 0x88, 0x88,
|
|
0x88, 0x88, 0x88, 0xD4};
|
|
|
|
constexpr uint8_t kPacketData[] = {kFlexible,
|
|
kPtRecovery,
|
|
kLengthRecovery[0],
|
|
kLengthRecovery[1],
|
|
kTsRecovery[0],
|
|
kTsRecovery[1],
|
|
kTsRecovery[2],
|
|
kTsRecovery[3],
|
|
kSnBase0 >> 8,
|
|
kSnBase0 & 0xFF,
|
|
kFlexfecPktMask1[0],
|
|
kFlexfecPktMask1[1],
|
|
kFlexfecPktMask1[2],
|
|
kFlexfecPktMask1[3],
|
|
kFlexfecPktMask1[4],
|
|
kFlexfecPktMask1[5],
|
|
kFlexfecPktMask1[6],
|
|
kFlexfecPktMask1[7],
|
|
kFlexfecPktMask1[8],
|
|
kFlexfecPktMask1[9],
|
|
kFlexfecPktMask1[10],
|
|
kFlexfecPktMask1[11],
|
|
kFlexfecPktMask1[12],
|
|
kFlexfecPktMask1[13],
|
|
kSnBase1 >> 8,
|
|
kSnBase1 & 0xFF,
|
|
kFlexfecPktMask2[0],
|
|
kFlexfecPktMask2[1],
|
|
kFlexfecPktMask2[2],
|
|
kFlexfecPktMask2[3],
|
|
kFlexfecPktMask2[4],
|
|
kFlexfecPktMask2[5],
|
|
kFlexfecPktMask2[6],
|
|
kFlexfecPktMask2[7],
|
|
kFlexfecPktMask2[8],
|
|
kFlexfecPktMask2[9],
|
|
kFlexfecPktMask2[10],
|
|
kFlexfecPktMask2[11],
|
|
kFlexfecPktMask2[12],
|
|
kFlexfecPktMask2[13],
|
|
kPayloadBits,
|
|
kPayloadBits,
|
|
kPayloadBits,
|
|
kPayloadBits};
|
|
ReceivedFecPacket read_packet;
|
|
read_packet.pkt = rtc::make_ref_counted<Packet>();
|
|
read_packet.pkt->data.SetData(kPacketData);
|
|
read_packet.protected_streams = {{.ssrc = 0x01}, {.ssrc = 0x02}};
|
|
|
|
FlexfecHeaderReader reader;
|
|
EXPECT_TRUE(reader.ReadFecHeader(&read_packet));
|
|
|
|
std::vector<FecPacketStreamProperties> expected = {
|
|
{.stream = {.ssrc = 0x01,
|
|
.seq_num_base = kSnBase0,
|
|
.packet_mask_offset = 10,
|
|
.packet_mask_size = std::size(kUlpfecPacketMask1)},
|
|
.mask = kUlpfecPacketMask1},
|
|
{.stream = {.ssrc = 0x02,
|
|
.seq_num_base = kSnBase1,
|
|
.packet_mask_offset = 26,
|
|
.packet_mask_size = std::size(kUlpfecPacketMask2)},
|
|
.mask = kUlpfecPacketMask2},
|
|
};
|
|
|
|
VerifyReadHeaders(kExpectedFecHeaderSize, read_packet, expected);
|
|
}
|
|
|
|
TEST(FlexfecHeaderReaderTest, ReadsHeaderWithMultipleStreamsMultipleMasks) {
|
|
constexpr uint8_t kBit0 = 0 << 7;
|
|
constexpr uint8_t kBit1 = 1 << 7;
|
|
constexpr size_t kExpectedFecHeaderSize = 44;
|
|
constexpr uint16_t kSnBase0 = 0x0102;
|
|
constexpr uint16_t kSnBase1 = 0x0304;
|
|
constexpr uint16_t kSnBase2 = 0x0506;
|
|
constexpr uint16_t kSnBase3 = 0x0708;
|
|
constexpr uint8_t kFlexfecPacketMask1[] = {kBit1 | 0x29, 0x91};
|
|
constexpr uint8_t kUlpfecPacketMask1[] = {0x53, 0x22};
|
|
constexpr uint8_t kFlexfecPacketMask2[] = {kBit0 | 0x32, 0xA1, //
|
|
kBit1 | 0x02, 0x11, 0x00, 0x21};
|
|
constexpr uint8_t kUlpfecPacketMask2[] = {0x65, 0x42, //
|
|
0x08, 0x44, 0x00, 0x84};
|
|
constexpr uint8_t kFlexfecPacketMask3[] = {kBit0 | 0x48, 0x81, //
|
|
kBit0 | 0x02, 0x11, 0x00, 0x21, //
|
|
0x01, 0x11, 0x11, 0x11,
|
|
0x11, 0x11, 0x11, 0x11};
|
|
constexpr uint8_t kUlpfecPacketMask3[] = {0x91, 0x02, //
|
|
0x08, 0x44, 0x00, 0x84, //
|
|
0x04, 0x44, 0x44, 0x44,
|
|
0x44, 0x44, 0x44, 0x44};
|
|
constexpr uint8_t kFlexfecPacketMask4[] = {kBit0 | 0x32, 0x84, //
|
|
kBit1 | 0x05, 0x23, 0x00, 0x55};
|
|
constexpr uint8_t kUlpfecPacketMask4[] = {0x65, 0x08, //
|
|
0x14, 0x8C, 0x01, 0x54};
|
|
constexpr uint8_t kPacketData[] = {kFlexible,
|
|
kPtRecovery,
|
|
kLengthRecovery[0],
|
|
kLengthRecovery[1],
|
|
kTsRecovery[0],
|
|
kTsRecovery[1],
|
|
kTsRecovery[2],
|
|
kTsRecovery[3],
|
|
kSnBase0 >> 8,
|
|
kSnBase0 & 0xFF,
|
|
kFlexfecPacketMask1[0],
|
|
kFlexfecPacketMask1[1],
|
|
kSnBase1 >> 8,
|
|
kSnBase1 & 0xFF,
|
|
kFlexfecPacketMask2[0],
|
|
kFlexfecPacketMask2[1],
|
|
kFlexfecPacketMask2[2],
|
|
kFlexfecPacketMask2[3],
|
|
kFlexfecPacketMask2[4],
|
|
kFlexfecPacketMask2[5],
|
|
kSnBase2 >> 8,
|
|
kSnBase2 & 0xFF,
|
|
kFlexfecPacketMask3[0],
|
|
kFlexfecPacketMask3[1],
|
|
kFlexfecPacketMask3[2],
|
|
kFlexfecPacketMask3[3],
|
|
kFlexfecPacketMask3[4],
|
|
kFlexfecPacketMask3[5],
|
|
kFlexfecPacketMask3[6],
|
|
kFlexfecPacketMask3[7],
|
|
kFlexfecPacketMask3[8],
|
|
kFlexfecPacketMask3[9],
|
|
kFlexfecPacketMask3[10],
|
|
kFlexfecPacketMask3[11],
|
|
kFlexfecPacketMask3[12],
|
|
kFlexfecPacketMask3[13],
|
|
kSnBase3 >> 8,
|
|
kSnBase3 & 0xFF,
|
|
kFlexfecPacketMask4[0],
|
|
kFlexfecPacketMask4[1],
|
|
kFlexfecPacketMask4[2],
|
|
kFlexfecPacketMask4[3],
|
|
kFlexfecPacketMask4[4],
|
|
kFlexfecPacketMask4[5],
|
|
kPayloadBits,
|
|
kPayloadBits,
|
|
kPayloadBits,
|
|
kPayloadBits};
|
|
ReceivedFecPacket read_packet;
|
|
read_packet.pkt = rtc::make_ref_counted<Packet>();
|
|
read_packet.pkt->data.SetData(kPacketData);
|
|
read_packet.protected_streams = {
|
|
{.ssrc = 0x01}, {.ssrc = 0x02}, {.ssrc = 0x03}, {.ssrc = 0x04}};
|
|
|
|
FlexfecHeaderReader reader;
|
|
EXPECT_TRUE(reader.ReadFecHeader(&read_packet));
|
|
|
|
std::vector<FecPacketStreamProperties> expected = {
|
|
{.stream = {.ssrc = 0x01,
|
|
.seq_num_base = kSnBase0,
|
|
.packet_mask_offset = 10,
|
|
.packet_mask_size = std::size(kUlpfecPacketMask1)},
|
|
.mask = kUlpfecPacketMask1},
|
|
{.stream = {.ssrc = 0x02,
|
|
.seq_num_base = kSnBase1,
|
|
.packet_mask_offset = 14,
|
|
.packet_mask_size = std::size(kUlpfecPacketMask2)},
|
|
.mask = kUlpfecPacketMask2},
|
|
{.stream = {.ssrc = 0x03,
|
|
.seq_num_base = kSnBase2,
|
|
.packet_mask_offset = 22,
|
|
.packet_mask_size = std::size(kUlpfecPacketMask3)},
|
|
.mask = kUlpfecPacketMask3},
|
|
{.stream = {.ssrc = 0x04,
|
|
.seq_num_base = kSnBase3,
|
|
.packet_mask_offset = 38,
|
|
.packet_mask_size = std::size(kUlpfecPacketMask4)},
|
|
.mask = kUlpfecPacketMask4},
|
|
};
|
|
|
|
VerifyReadHeaders(kExpectedFecHeaderSize, read_packet, expected);
|
|
}
|
|
|
|
TEST(FlexfecHeaderReaderTest, ReadPacketWithoutProtectedSsrcsShouldFail) {
|
|
constexpr uint8_t kPacketData[] = {
|
|
kFlexible, kPtRecovery, kLengthRecovery[0], kLengthRecovery[1],
|
|
kTsRecovery[0], kTsRecovery[1], kTsRecovery[2], kTsRecovery[3]};
|
|
ReceivedFecPacket read_packet;
|
|
read_packet.pkt = rtc::make_ref_counted<Packet>();
|
|
read_packet.pkt->data.SetData(kPacketData);
|
|
// No protected ssrcs.
|
|
read_packet.protected_streams = {};
|
|
|
|
FlexfecHeaderReader reader;
|
|
EXPECT_FALSE(reader.ReadFecHeader(&read_packet));
|
|
}
|
|
|
|
TEST(FlexfecHeaderReaderTest, ReadPacketWithoutStreamSpecificHeaderShouldFail) {
|
|
// Simulate short received packet.
|
|
constexpr uint8_t kPacketData[] = {
|
|
kFlexible, kPtRecovery, kLengthRecovery[0], kLengthRecovery[1],
|
|
kTsRecovery[0], kTsRecovery[1], kTsRecovery[2], kTsRecovery[3]};
|
|
ReceivedFecPacket read_packet;
|
|
read_packet.pkt = rtc::make_ref_counted<Packet>();
|
|
read_packet.pkt->data.SetData(kPacketData);
|
|
read_packet.protected_streams = {{.ssrc = 0x01}};
|
|
|
|
FlexfecHeaderReader reader;
|
|
EXPECT_FALSE(reader.ReadFecHeader(&read_packet));
|
|
}
|
|
|
|
TEST(FlexfecHeaderReaderTest, ReadShortPacketWithKBit0SetShouldFail) {
|
|
// Simulate short received packet.
|
|
constexpr uint8_t kPacketData[] = {
|
|
kFlexible, kPtRecovery, kLengthRecovery[0], kLengthRecovery[1],
|
|
kTsRecovery[0], kTsRecovery[1], kTsRecovery[2], kTsRecovery[3],
|
|
kSnBases[0][0], kSnBases[0][1], kMask0[0], kMask0[1]};
|
|
ReceivedFecPacket read_packet;
|
|
read_packet.pkt = rtc::make_ref_counted<Packet>();
|
|
// Expected to have 2 bytes of mask but length of packet misses 1 byte.
|
|
read_packet.pkt->data.SetData(kPacketData, sizeof(kPacketData) - 1);
|
|
read_packet.protected_streams = {{.ssrc = 0x01}};
|
|
|
|
FlexfecHeaderReader reader;
|
|
EXPECT_FALSE(reader.ReadFecHeader(&read_packet));
|
|
}
|
|
|
|
TEST(FlexfecHeaderReaderTest, ReadShortPacketWithKBit1SetShouldFail) {
|
|
// Simulate short received packet.
|
|
constexpr uint8_t kPacketData[] = {
|
|
kFlexible, kPtRecovery, kLengthRecovery[0], kLengthRecovery[1],
|
|
kTsRecovery[0], kTsRecovery[1], kTsRecovery[2], kTsRecovery[3],
|
|
kSnBases[0][0], kSnBases[0][1], kMask1[0], kMask1[1],
|
|
kMask1[2], kMask1[3], kMask1[4], kMask1[5]};
|
|
ReceivedFecPacket read_packet;
|
|
read_packet.pkt = rtc::make_ref_counted<Packet>();
|
|
// Expected to have 6 bytes of mask but length of packet misses 2 bytes.
|
|
read_packet.pkt->data.SetData(kPacketData, sizeof(kPacketData) - 2);
|
|
read_packet.protected_streams = {{.ssrc = 0x01}};
|
|
|
|
FlexfecHeaderReader reader;
|
|
EXPECT_FALSE(reader.ReadFecHeader(&read_packet));
|
|
}
|
|
|
|
TEST(FlexfecHeaderReaderTest, ReadShortPacketWithKBit1ClearedShouldFail) {
|
|
// Simulate short received packet.
|
|
constexpr uint8_t kPacketData[] = {
|
|
kFlexible, kPtRecovery, kLengthRecovery[0], kLengthRecovery[1],
|
|
kTsRecovery[0], kTsRecovery[1], kTsRecovery[2], kTsRecovery[3],
|
|
kSnBases[0][0], kSnBases[0][1], kMask2[0], kMask2[1],
|
|
kMask2[2], kMask2[3], kMask2[4], kMask2[5],
|
|
kMask2[6], kMask2[7], kMask2[8], kMask2[9],
|
|
kMask2[10], kMask2[11], kMask2[12], kMask2[13]};
|
|
ReceivedFecPacket read_packet;
|
|
read_packet.pkt = rtc::make_ref_counted<Packet>();
|
|
// Expected to have 14 bytes of mask but length of packet misses 2 bytes.
|
|
read_packet.pkt->data.SetData(kPacketData, sizeof(kPacketData) - 2);
|
|
read_packet.protected_streams = {{.ssrc = 0x01}};
|
|
|
|
FlexfecHeaderReader reader;
|
|
EXPECT_FALSE(reader.ReadFecHeader(&read_packet));
|
|
}
|
|
|
|
TEST(FlexfecHeaderReaderTest, ReadShortPacketMultipleStreamsShouldFail) {
|
|
// Simulate short received packet with 2 protected ssrcs.
|
|
constexpr uint8_t kPacketData[] = {
|
|
kFlexible, kPtRecovery, kLengthRecovery[0], kLengthRecovery[1],
|
|
kTsRecovery[0], kTsRecovery[1], kTsRecovery[2], kTsRecovery[3],
|
|
kSnBases[0][0], kSnBases[0][1], kMask0[0], kMask0[1],
|
|
kSnBases[1][0], kSnBases[1][1], kMask2[0], kMask2[1],
|
|
kMask2[2], kMask2[3], kMask2[4], kMask2[5],
|
|
kMask2[6], kMask2[7], kMask2[8], kMask2[9],
|
|
kMask2[10], kMask2[11], kMask2[12], kMask2[13]};
|
|
ReceivedFecPacket read_packet;
|
|
read_packet.pkt = rtc::make_ref_counted<Packet>();
|
|
// Subtract 2 bytes from length, so the read will fail on parsing second
|
|
read_packet.pkt->data.SetData(kPacketData, sizeof(kPacketData) - 2);
|
|
read_packet.protected_streams = {{.ssrc = 0x01}, {.ssrc = 0x02}};
|
|
|
|
FlexfecHeaderReader reader;
|
|
EXPECT_FALSE(reader.ReadFecHeader(&read_packet));
|
|
}
|
|
|
|
// 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) {}
|
|
|
|
TEST(FlexfecHeaderWriterTest, ContractsShortUlpfecPacketMaskWithBit15Clear) {}
|
|
|
|
TEST(FlexfecHeaderWriterTest, ExpandsShortUlpfecPacketMaskWithBit15Set) {}
|
|
|
|
TEST(FlexfecHeaderWriterTest,
|
|
ContractsLongUlpfecPacketMaskWithBit46ClearBit47Clear) {}
|
|
|
|
TEST(FlexfecHeaderWriterTest,
|
|
ExpandsLongUlpfecPacketMaskWithBit46SetBit47Clear) {}
|
|
|
|
TEST(FlexfecHeaderWriterTest,
|
|
ExpandsLongUlpfecPacketMaskWithBit46ClearBit47Set) {}
|
|
|
|
TEST(FlexfecHeaderWriterTest, ExpandsLongUlpfecPacketMaskWithBit46SetBit47Set) {
|
|
}
|
|
|
|
TEST(FlexfecHeaderReaderWriterTest,
|
|
WriteAndReadSmallUlpfecPacketHeaderWithMaskBit15Clear) {}
|
|
|
|
TEST(FlexfecHeaderReaderWriterTest,
|
|
WriteAndReadSmallUlpfecPacketHeaderWithMaskBit15Set) {}
|
|
|
|
TEST(FlexfecHeaderReaderWriterTest,
|
|
WriteAndReadLargeUlpfecPacketHeaderWithMaskBits46And47Clear) {}
|
|
|
|
TEST(FlexfecHeaderReaderWriterTest,
|
|
WriteAndReadLargeUlpfecPacketHeaderWithMaskBit46SetBit47Clear) {}
|
|
|
|
TEST(FlexfecHeaderReaderWriterTest,
|
|
WriteAndReadLargeUlpfecPacketHeaderMaskWithBit46ClearBit47Set) {}
|
|
|
|
TEST(FlexfecHeaderReaderWriterTest,
|
|
WriteAndReadLargeUlpfecPacketHeaderWithMaskBits46And47Set) {}
|
|
|
|
} // namespace webrtc
|