1e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org/* 2e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org * 4e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org * Use of this source code is governed by a BSD-style license 5e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org * that can be found in the LICENSE file in the root of the source 6e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org * tree. An additional intellectual property rights grant can be found 7e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org * in the file PATENTS. All contributing project authors may 8e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org */ 10e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org 11e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org#include <list> 124c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer#include <vector> 13e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org 14a048d7cb0a5bad5ca49bbcc5273cb4cca28c1710pbos@webrtc.org#include "testing/gtest/include/gtest/gtest.h" 154c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer#include "webrtc/modules/rtp_rtcp/source/byte_io.h" 16a048d7cb0a5bad5ca49bbcc5273cb4cca28c1710pbos@webrtc.org#include "webrtc/modules/rtp_rtcp/source/fec_test_helper.h" 17a048d7cb0a5bad5ca49bbcc5273cb4cca28c1710pbos@webrtc.org#include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" 18a048d7cb0a5bad5ca49bbcc5273cb4cca28c1710pbos@webrtc.org#include "webrtc/modules/rtp_rtcp/source/producer_fec.h" 19e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org 20e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.orgnamespace webrtc { 21e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org 22e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.orgvoid VerifyHeader(uint16_t seq_num, 23e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org uint32_t timestamp, 24e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org int red_pltype, 25e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org int fec_pltype, 26e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org RedPacket* packet, 27e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org bool marker_bit) { 284591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org EXPECT_GT(packet->length(), kRtpHeaderSize); 29e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org EXPECT_TRUE(packet->data() != NULL); 30e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org uint8_t* data = packet->data(); 31e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org // Marker bit not set. 32e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org EXPECT_EQ(marker_bit ? 0x80 : 0, data[1] & 0x80); 33e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org EXPECT_EQ(red_pltype, data[1] & 0x7F); 34e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org EXPECT_EQ(seq_num, (data[2] << 8) + data[3]); 35e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org uint32_t parsed_timestamp = (data[4] << 24) + (data[5] << 16) + 36e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org (data[6] << 8) + data[7]; 37e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org EXPECT_EQ(timestamp, parsed_timestamp); 380e81fdf5d2c2665bc3d23e07cfd9ea7f7d36aed9pkasting@chromium.org EXPECT_EQ(static_cast<uint8_t>(fec_pltype), data[kRtpHeaderSize]); 39e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org} 40e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org 41e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.orgclass ProducerFecTest : public ::testing::Test { 42e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org protected: 43e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org virtual void SetUp() { 44dc80bae2a62a1bdbe0d342b3260a7e5b2cb958dfandresp@webrtc.org fec_ = new ForwardErrorCorrection(); 45e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org producer_ = new ProducerFec(fec_); 46e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org generator_ = new FrameGenerator; 47e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org } 48e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org 49e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org virtual void TearDown() { 50e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org delete producer_; 51e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org delete fec_; 52e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org delete generator_; 53e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org } 54e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org ForwardErrorCorrection* fec_; 55e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org ProducerFec* producer_; 56e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org FrameGenerator* generator_; 57e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org}; 58e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org 594c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer// Verifies bug found via fuzzing, where a gap in the packet sequence caused us 604c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer// to move past the end of the current FEC packet mask byte without moving to 614c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer// the next byte. That likely caused us to repeatedly read from the same byte, 624c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer// and if that byte didn't protect packets we would generate empty FEC. 634c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan HolmerTEST_F(ProducerFecTest, NoEmptyFecWithSeqNumGaps) { 644c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer struct Packet { 654c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer size_t header_size; 664c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer size_t payload_size; 674c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer uint16_t seq_num; 684c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer bool marker_bit; 694c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer }; 704c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer std::vector<Packet> protected_packets; 714c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer protected_packets.push_back({15, 3, 41, 0}); 724c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer protected_packets.push_back({14, 1, 43, 0}); 734c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer protected_packets.push_back({19, 0, 48, 0}); 744c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer protected_packets.push_back({19, 0, 50, 0}); 754c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer protected_packets.push_back({14, 3, 51, 0}); 764c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer protected_packets.push_back({13, 8, 52, 0}); 774c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer protected_packets.push_back({19, 2, 53, 0}); 784c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer protected_packets.push_back({12, 3, 54, 0}); 794c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer protected_packets.push_back({21, 0, 55, 0}); 804c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer protected_packets.push_back({13, 3, 57, 1}); 814c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer FecProtectionParams params = {117, 0, 3, kFecMaskBursty}; 824c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer producer_->SetFecParameters(¶ms, 0); 834c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer uint8_t packet[28] = {0}; 844c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer for (Packet p : protected_packets) { 854c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer if (p.marker_bit) { 864c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer packet[1] |= 0x80; 874c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer } else { 884c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer packet[1] &= ~0x80; 894c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer } 904c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer ByteWriter<uint16_t>::WriteBigEndian(&packet[2], p.seq_num); 914c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer producer_->AddRtpPacketAndGenerateFec(packet, p.payload_size, 924c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer p.header_size); 934c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer uint16_t num_fec_packets = producer_->NumAvailableFecPackets(); 944c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer std::vector<RedPacket*> fec_packets; 954c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer if (num_fec_packets > 0) { 964c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer fec_packets = 974c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer producer_->GetFecPackets(kRedPayloadType, 99, 100, p.header_size); 984c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer EXPECT_EQ(num_fec_packets, fec_packets.size()); 994c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer } 1004c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer for (RedPacket* fec_packet : fec_packets) { 1014c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer delete fec_packet; 1024c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer } 1034c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer } 1044c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer} 1054c1093b86f4d0a1c8ade68a4b6a411b2674deac8Stefan Holmer 106e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.orgTEST_F(ProducerFecTest, OneFrameFec) { 107747cd87da1fc7b2acabfd32283c6f692c62e65dcmarpan@webrtc.org // The number of media packets (|kNumPackets|), number of frames (one for 108747cd87da1fc7b2acabfd32283c6f692c62e65dcmarpan@webrtc.org // this test), and the protection factor (|params->fec_rate|) are set to make 109747cd87da1fc7b2acabfd32283c6f692c62e65dcmarpan@webrtc.org // sure the conditions for generating FEC are satisfied. This means: 110747cd87da1fc7b2acabfd32283c6f692c62e65dcmarpan@webrtc.org // (1) protection factor is high enough so that actual overhead over 1 frame 111747cd87da1fc7b2acabfd32283c6f692c62e65dcmarpan@webrtc.org // of packets is within |kMaxExcessOverhead|, and (2) the total number of 112747cd87da1fc7b2acabfd32283c6f692c62e65dcmarpan@webrtc.org // media packets for 1 frame is at least |minimum_media_packets_fec_|. 113c35f5ced92b9d8435afe07c518246f28ab0493a4stefan@webrtc.org const int kNumPackets = 4; 114747cd87da1fc7b2acabfd32283c6f692c62e65dcmarpan@webrtc.org FecProtectionParams params = {15, false, 3}; 115e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org std::list<RtpPacket*> rtp_packets; 116e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org generator_->NewFrame(kNumPackets); 117e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org producer_->SetFecParameters(¶ms, 0); // Expecting one FEC packet. 118e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org uint32_t last_timestamp = 0; 119e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org for (int i = 0; i < kNumPackets; ++i) { 120e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org RtpPacket* rtp_packet = generator_->NextPacket(i, 10); 121e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org rtp_packets.push_back(rtp_packet); 122e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org EXPECT_EQ(0, producer_->AddRtpPacketAndGenerateFec(rtp_packet->data, 123e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org rtp_packet->length, 124e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org kRtpHeaderSize)); 125e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org last_timestamp = rtp_packet->header.header.timestamp; 126e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org } 127e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org EXPECT_TRUE(producer_->FecAvailable()); 128e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org uint16_t seq_num = generator_->NextSeqNum(); 129fcf54bdabbdf495cef7aa587b5cabdcb899ba24fmflodman std::vector<RedPacket*> packets = producer_->GetFecPackets(kRedPayloadType, 130fcf54bdabbdf495cef7aa587b5cabdcb899ba24fmflodman kFecPayloadType, 131fcf54bdabbdf495cef7aa587b5cabdcb899ba24fmflodman seq_num, 132fcf54bdabbdf495cef7aa587b5cabdcb899ba24fmflodman kRtpHeaderSize); 133e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org EXPECT_FALSE(producer_->FecAvailable()); 134fcf54bdabbdf495cef7aa587b5cabdcb899ba24fmflodman ASSERT_EQ(1u, packets.size()); 135e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org VerifyHeader(seq_num, last_timestamp, 136fcf54bdabbdf495cef7aa587b5cabdcb899ba24fmflodman kRedPayloadType, kFecPayloadType, packets.front(), false); 137e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org while (!rtp_packets.empty()) { 138e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org delete rtp_packets.front(); 139e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org rtp_packets.pop_front(); 140e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org } 141fcf54bdabbdf495cef7aa587b5cabdcb899ba24fmflodman delete packets.front(); 142e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org} 143e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org 144e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.orgTEST_F(ProducerFecTest, TwoFrameFec) { 145747cd87da1fc7b2acabfd32283c6f692c62e65dcmarpan@webrtc.org // The number of media packets/frame (|kNumPackets|), the number of frames 146747cd87da1fc7b2acabfd32283c6f692c62e65dcmarpan@webrtc.org // (|kNumFrames|), and the protection factor (|params->fec_rate|) are set to 147747cd87da1fc7b2acabfd32283c6f692c62e65dcmarpan@webrtc.org // make sure the conditions for generating FEC are satisfied. This means: 148747cd87da1fc7b2acabfd32283c6f692c62e65dcmarpan@webrtc.org // (1) protection factor is high enough so that actual overhead over 149747cd87da1fc7b2acabfd32283c6f692c62e65dcmarpan@webrtc.org // |kNumFrames| is within |kMaxExcessOverhead|, and (2) the total number of 150747cd87da1fc7b2acabfd32283c6f692c62e65dcmarpan@webrtc.org // media packets for |kNumFrames| frames is at least 151747cd87da1fc7b2acabfd32283c6f692c62e65dcmarpan@webrtc.org // |minimum_media_packets_fec_|. 152e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org const int kNumPackets = 2; 153e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org const int kNumFrames = 2; 154747cd87da1fc7b2acabfd32283c6f692c62e65dcmarpan@webrtc.org 155747cd87da1fc7b2acabfd32283c6f692c62e65dcmarpan@webrtc.org FecProtectionParams params = {15, 0, 3}; 156e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org std::list<RtpPacket*> rtp_packets; 157e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org producer_->SetFecParameters(¶ms, 0); // Expecting one FEC packet. 158e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org uint32_t last_timestamp = 0; 159e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org for (int i = 0; i < kNumFrames; ++i) { 160e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org generator_->NewFrame(kNumPackets); 161e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org for (int j = 0; j < kNumPackets; ++j) { 162e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org RtpPacket* rtp_packet = generator_->NextPacket(i * kNumPackets + j, 10); 163e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org rtp_packets.push_back(rtp_packet); 164e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org EXPECT_EQ(0, producer_->AddRtpPacketAndGenerateFec(rtp_packet->data, 165e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org rtp_packet->length, 166e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org kRtpHeaderSize)); 167e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org last_timestamp = rtp_packet->header.header.timestamp; 168e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org } 169e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org } 170e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org EXPECT_TRUE(producer_->FecAvailable()); 171e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org uint16_t seq_num = generator_->NextSeqNum(); 172fcf54bdabbdf495cef7aa587b5cabdcb899ba24fmflodman std::vector<RedPacket*> packets = producer_->GetFecPackets(kRedPayloadType, 173fcf54bdabbdf495cef7aa587b5cabdcb899ba24fmflodman kFecPayloadType, 174fcf54bdabbdf495cef7aa587b5cabdcb899ba24fmflodman seq_num, 175fcf54bdabbdf495cef7aa587b5cabdcb899ba24fmflodman kRtpHeaderSize); 176e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org EXPECT_FALSE(producer_->FecAvailable()); 177fcf54bdabbdf495cef7aa587b5cabdcb899ba24fmflodman ASSERT_EQ(1u, packets.size()); 178fcf54bdabbdf495cef7aa587b5cabdcb899ba24fmflodman VerifyHeader(seq_num, last_timestamp, kRedPayloadType, kFecPayloadType, 179fcf54bdabbdf495cef7aa587b5cabdcb899ba24fmflodman packets.front(), false); 180e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org while (!rtp_packets.empty()) { 181e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org delete rtp_packets.front(); 182e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org rtp_packets.pop_front(); 183e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org } 184fcf54bdabbdf495cef7aa587b5cabdcb899ba24fmflodman delete packets.front(); 185e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org} 186e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org 187e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.orgTEST_F(ProducerFecTest, BuildRedPacket) { 188e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org generator_->NewFrame(1); 189e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org RtpPacket* packet = generator_->NextPacket(0, 10); 190fcf54bdabbdf495cef7aa587b5cabdcb899ba24fmflodman rtc::scoped_ptr<RedPacket> red_packet(producer_->BuildRedPacket( 191fcf54bdabbdf495cef7aa587b5cabdcb899ba24fmflodman packet->data, packet->length - kRtpHeaderSize, kRtpHeaderSize, 192fcf54bdabbdf495cef7aa587b5cabdcb899ba24fmflodman kRedPayloadType)); 193e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org EXPECT_EQ(packet->length + 1, red_packet->length()); 194e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org VerifyHeader(packet->header.header.sequenceNumber, 195e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org packet->header.header.timestamp, 196e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org kRedPayloadType, 197e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org packet->header.header.payloadType, 198fcf54bdabbdf495cef7aa587b5cabdcb899ba24fmflodman red_packet.get(), 199e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org true); // Marker bit set. 200e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org for (int i = 0; i < 10; ++i) 201e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org EXPECT_EQ(i, red_packet->data()[kRtpHeaderSize + 1 + i]); 202e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org delete packet; 203e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org} 204e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org 205e0d6fa4c66e025054e199a42f91a8b6d8af282b5stefan@webrtc.org} // namespace webrtc 206