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(&params, 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(&params, 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(&params, 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