marpan@webrtc.org | cdba1a8 | 2012-01-31 00:36:14 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 3 | * |
marpan@webrtc.org | cdba1a8 | 2012-01-31 00:36:14 +0000 | [diff] [blame] | 4 | * Use of this source code is governed by a BSD-style license |
| 5 | * that can be found in the LICENSE file in the root of the source |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
| 11 | /* |
| 12 | * Test application for core FEC algorithm. Calls encoding and decoding |
| 13 | * functions in ForwardErrorCorrection directly. |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 14 | */ |
| 15 | |
pbos@webrtc.org | 12dc1a3 | 2013-08-05 16:22:53 +0000 | [diff] [blame] | 16 | #include <string.h> |
| 17 | #include <time.h> |
| 18 | |
pwestin@webrtc.org | 95cf479 | 2012-01-20 06:59:06 +0000 | [diff] [blame] | 19 | #include <list> |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 20 | |
danilchap | 47a740b | 2015-12-15 00:30:07 -0800 | [diff] [blame] | 21 | #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
pbos@webrtc.org | a048d7c | 2013-05-29 14:27:38 +0000 | [diff] [blame] | 22 | #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" |
| 23 | #include "webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.h" |
Edward Lemur | c20978e | 2017-07-06 19:44:34 +0200 | [diff] [blame] | 24 | #include "webrtc/rtc_base/random.h" |
kwiberg | ac9f876 | 2016-09-30 22:29:43 -0700 | [diff] [blame] | 25 | #include "webrtc/test/gtest.h" |
pbos@webrtc.org | a048d7c | 2013-05-29 14:27:38 +0000 | [diff] [blame] | 26 | #include "webrtc/test/testsupport/fileutils.h" |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 27 | |
danilchap | 40f349f | 2015-12-14 06:39:33 -0800 | [diff] [blame] | 28 | // #define VERBOSE_OUTPUT |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 29 | |
kjellander@webrtc.org | 22bbbdf | 2013-06-12 11:55:05 +0000 | [diff] [blame] | 30 | namespace webrtc { |
danilchap | 6a6f089 | 2015-12-10 12:39:08 -0800 | [diff] [blame] | 31 | namespace fec_private_tables { |
| 32 | extern const uint8_t** kPacketMaskBurstyTbl[12]; |
| 33 | } |
kjellander@webrtc.org | 22bbbdf | 2013-06-12 11:55:05 +0000 | [diff] [blame] | 34 | namespace test { |
danilchap | 6a6f089 | 2015-12-10 12:39:08 -0800 | [diff] [blame] | 35 | using fec_private_tables::kPacketMaskBurstyTbl; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 36 | |
pwestin@webrtc.org | 95cf479 | 2012-01-20 06:59:06 +0000 | [diff] [blame] | 37 | void ReceivePackets( |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 38 | ForwardErrorCorrection::ReceivedPacketList* to_decode_list, |
| 39 | ForwardErrorCorrection::ReceivedPacketList* received_packet_list, |
| 40 | size_t num_packets_to_decode, |
| 41 | float reorder_rate, |
| 42 | float duplicate_rate, |
danilchap | 47a740b | 2015-12-15 00:30:07 -0800 | [diff] [blame] | 43 | Random* random) { |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 44 | RTC_DCHECK(to_decode_list->empty()); |
| 45 | RTC_DCHECK_LE(num_packets_to_decode, received_packet_list->size()); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 46 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 47 | for (size_t i = 0; i < num_packets_to_decode; i++) { |
| 48 | auto it = received_packet_list->begin(); |
kjellander@webrtc.org | 22bbbdf | 2013-06-12 11:55:05 +0000 | [diff] [blame] | 49 | // Reorder packets. |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 50 | float random_variable = random->Rand<float>(); |
| 51 | while (random_variable < reorder_rate) { |
kjellander@webrtc.org | 22bbbdf | 2013-06-12 11:55:05 +0000 | [diff] [blame] | 52 | ++it; |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 53 | if (it == received_packet_list->end()) { |
kjellander@webrtc.org | 22bbbdf | 2013-06-12 11:55:05 +0000 | [diff] [blame] | 54 | --it; |
| 55 | break; |
| 56 | } |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 57 | random_variable = random->Rand<float>(); |
kjellander@webrtc.org | 22bbbdf | 2013-06-12 11:55:05 +0000 | [diff] [blame] | 58 | } |
brandtr | 35c480c | 2016-08-09 01:23:23 -0700 | [diff] [blame] | 59 | to_decode_list->push_back(std::move(*it)); |
| 60 | received_packet_list->erase(it); |
kjellander@webrtc.org | 22bbbdf | 2013-06-12 11:55:05 +0000 | [diff] [blame] | 61 | |
| 62 | // Duplicate packets. |
brandtr | 35c480c | 2016-08-09 01:23:23 -0700 | [diff] [blame] | 63 | ForwardErrorCorrection::ReceivedPacket* received_packet = |
| 64 | to_decode_list->back().get(); |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 65 | random_variable = random->Rand<float>(); |
| 66 | while (random_variable < duplicate_rate) { |
brandtr | 35c480c | 2016-08-09 01:23:23 -0700 | [diff] [blame] | 67 | std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> duplicate_packet( |
| 68 | new ForwardErrorCorrection::ReceivedPacket()); |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 69 | *duplicate_packet = *received_packet; |
| 70 | duplicate_packet->pkt = new ForwardErrorCorrection::Packet(); |
| 71 | memcpy(duplicate_packet->pkt->data, received_packet->pkt->data, |
| 72 | received_packet->pkt->length); |
| 73 | duplicate_packet->pkt->length = received_packet->pkt->length; |
kjellander@webrtc.org | 22bbbdf | 2013-06-12 11:55:05 +0000 | [diff] [blame] | 74 | |
brandtr | 35c480c | 2016-08-09 01:23:23 -0700 | [diff] [blame] | 75 | to_decode_list->push_back(std::move(duplicate_packet)); |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 76 | random_variable = random->Rand<float>(); |
kjellander@webrtc.org | 22bbbdf | 2013-06-12 11:55:05 +0000 | [diff] [blame] | 77 | } |
kjellander@webrtc.org | 22bbbdf | 2013-06-12 11:55:05 +0000 | [diff] [blame] | 78 | } |
| 79 | } |
| 80 | |
brandtr | d726a3f | 2017-06-29 02:45:35 -0700 | [diff] [blame] | 81 | void RunTest(bool use_flexfec) { |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 82 | // TODO(marpan): Split this function into subroutines/helper functions. |
danilchap | 40f349f | 2015-12-14 06:39:33 -0800 | [diff] [blame] | 83 | enum { kMaxNumberMediaPackets = 48 }; |
| 84 | enum { kMaxNumberFecPackets = 48 }; |
marpan@webrtc.org | 040cb71 | 2011-11-04 22:57:56 +0000 | [diff] [blame] | 85 | |
pbos@webrtc.org | 2f44673 | 2013-04-08 11:08:41 +0000 | [diff] [blame] | 86 | const uint32_t kNumMaskBytesL0 = 2; |
| 87 | const uint32_t kNumMaskBytesL1 = 6; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 88 | |
pwestin@webrtc.org | 95cf479 | 2012-01-20 06:59:06 +0000 | [diff] [blame] | 89 | // FOR UEP |
| 90 | const bool kUseUnequalProtection = true; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 91 | |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 92 | // FEC mask types. |
danilchap | 40f349f | 2015-12-14 06:39:33 -0800 | [diff] [blame] | 93 | const FecMaskType kMaskTypes[] = {kFecMaskRandom, kFecMaskBursty}; |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 94 | const int kNumFecMaskTypes = sizeof(kMaskTypes) / sizeof(*kMaskTypes); |
pbos@webrtc.org | 3004c79 | 2013-05-07 12:36:21 +0000 | [diff] [blame] | 95 | |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 96 | // Maximum number of media packets allowed for the mask type. |
danilchap | 40f349f | 2015-12-14 06:39:33 -0800 | [diff] [blame] | 97 | const uint16_t kMaxMediaPackets[] = { |
| 98 | kMaxNumberMediaPackets, |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 99 | sizeof(kPacketMaskBurstyTbl) / sizeof(*kPacketMaskBurstyTbl)}; |
pbos@webrtc.org | 3004c79 | 2013-05-07 12:36:21 +0000 | [diff] [blame] | 100 | |
kjellander@webrtc.org | 22bbbdf | 2013-06-12 11:55:05 +0000 | [diff] [blame] | 101 | ASSERT_EQ(12, kMaxMediaPackets[1]) << "Max media packets for bursty mode not " |
| 102 | << "equal to 12."; |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 103 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 104 | ForwardErrorCorrection::PacketList media_packet_list; |
brandtr | 35c480c | 2016-08-09 01:23:23 -0700 | [diff] [blame] | 105 | std::list<ForwardErrorCorrection::Packet*> fec_packet_list; |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 106 | ForwardErrorCorrection::ReceivedPacketList to_decode_list; |
| 107 | ForwardErrorCorrection::ReceivedPacketList received_packet_list; |
| 108 | ForwardErrorCorrection::RecoveredPacketList recovered_packet_list; |
| 109 | std::list<uint8_t*> fec_mask_list; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 110 | |
brandtr | a25a695 | 2017-08-01 05:01:07 -0700 | [diff] [blame] | 111 | // Running over only two loss rates to limit execution time. |
| 112 | const float loss_rate[] = {0.05f, 0.01f}; |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 113 | const uint32_t loss_rate_size = sizeof(loss_rate) / sizeof(*loss_rate); |
| 114 | const float reorder_rate = 0.1f; |
| 115 | const float duplicate_rate = 0.1f; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 116 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 117 | uint8_t media_loss_mask[kMaxNumberMediaPackets]; |
| 118 | uint8_t fec_loss_mask[kMaxNumberFecPackets]; |
| 119 | uint8_t fec_packet_masks[kMaxNumberFecPackets][kMaxNumberMediaPackets]; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 120 | |
pwestin@webrtc.org | 95cf479 | 2012-01-20 06:59:06 +0000 | [diff] [blame] | 121 | // Seed the random number generator, storing the seed to file in order to |
| 122 | // reproduce past results. |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 123 | const unsigned int random_seed = static_cast<unsigned int>(time(nullptr)); |
| 124 | Random random(random_seed); |
marpan@webrtc.org | cdba1a8 | 2012-01-31 00:36:14 +0000 | [diff] [blame] | 125 | std::string filename = webrtc::test::OutputPath() + "randomSeedLog.txt"; |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 126 | FILE* random_seed_file = fopen(filename.c_str(), "a"); |
| 127 | fprintf(random_seed_file, "%u\n", random_seed); |
| 128 | fclose(random_seed_file); |
| 129 | random_seed_file = nullptr; |
marpan@webrtc.org | 040cb71 | 2011-11-04 22:57:56 +0000 | [diff] [blame] | 130 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 131 | uint16_t seq_num = 0; |
| 132 | uint32_t timestamp = random.Rand<uint32_t>(); |
brandtr | d726a3f | 2017-06-29 02:45:35 -0700 | [diff] [blame] | 133 | const uint32_t media_ssrc = random.Rand(1u, 0xfffffffe); |
| 134 | uint32_t fec_ssrc; |
| 135 | uint16_t fec_seq_num_offset; |
| 136 | if (use_flexfec) { |
| 137 | fec_ssrc = random.Rand(1u, 0xfffffffe); |
brandtr | fa85678 | 2017-06-30 07:22:15 -0700 | [diff] [blame] | 138 | fec_seq_num_offset = random.Rand(0, 1 << 15); |
brandtr | d726a3f | 2017-06-29 02:45:35 -0700 | [diff] [blame] | 139 | } else { |
| 140 | fec_ssrc = media_ssrc; |
| 141 | fec_seq_num_offset = 0; |
| 142 | } |
| 143 | |
| 144 | std::unique_ptr<ForwardErrorCorrection> fec; |
| 145 | if (use_flexfec) { |
| 146 | fec = ForwardErrorCorrection::CreateFlexfec(fec_ssrc, media_ssrc); |
| 147 | } else { |
| 148 | RTC_DCHECK_EQ(media_ssrc, fec_ssrc); |
| 149 | fec = ForwardErrorCorrection::CreateUlpfec(fec_ssrc); |
| 150 | } |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 151 | |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 152 | // Loop over the mask types: random and bursty. |
| 153 | for (int mask_type_idx = 0; mask_type_idx < kNumFecMaskTypes; |
phoglund@webrtc.org | 9919ad5 | 2013-05-16 15:06:28 +0000 | [diff] [blame] | 154 | ++mask_type_idx) { |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 155 | for (uint32_t loss_rate_idx = 0; loss_rate_idx < loss_rate_size; |
| 156 | ++loss_rate_idx) { |
| 157 | printf("Loss rate: %.2f, Mask type %d \n", loss_rate[loss_rate_idx], |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 158 | mask_type_idx); |
pwestin@webrtc.org | 95cf479 | 2012-01-20 06:59:06 +0000 | [diff] [blame] | 159 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 160 | const uint32_t packet_mask_max = kMaxMediaPackets[mask_type_idx]; |
| 161 | std::unique_ptr<uint8_t[]> packet_mask( |
| 162 | new uint8_t[packet_mask_max * kNumMaskBytesL1]); |
pwestin@webrtc.org | 95cf479 | 2012-01-20 06:59:06 +0000 | [diff] [blame] | 163 | |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 164 | FecMaskType fec_mask_type = kMaskTypes[mask_type_idx]; |
pwestin@webrtc.org | 95cf479 | 2012-01-20 06:59:06 +0000 | [diff] [blame] | 165 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 166 | for (uint32_t num_media_packets = 1; num_media_packets <= packet_mask_max; |
| 167 | num_media_packets++) { |
| 168 | internal::PacketMaskTable mask_table(fec_mask_type, num_media_packets); |
pwestin@webrtc.org | 95cf479 | 2012-01-20 06:59:06 +0000 | [diff] [blame] | 169 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 170 | for (uint32_t num_fec_packets = 1; |
| 171 | num_fec_packets <= num_media_packets && |
| 172 | num_fec_packets <= packet_mask_max; |
| 173 | num_fec_packets++) { |
| 174 | // Loop over num_imp_packets: usually <= (0.3*num_media_packets). |
| 175 | // For this test we check up to ~ (num_media_packets / 4). |
| 176 | uint32_t max_num_imp_packets = num_media_packets / 4 + 1; |
| 177 | for (uint32_t num_imp_packets = 0; |
| 178 | num_imp_packets <= max_num_imp_packets && |
| 179 | num_imp_packets <= packet_mask_max; |
| 180 | num_imp_packets++) { |
| 181 | uint8_t protection_factor = |
| 182 | static_cast<uint8_t>(num_fec_packets * 255 / num_media_packets); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 183 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 184 | const uint32_t mask_bytes_per_fec_packet = |
| 185 | (num_media_packets > 16) ? kNumMaskBytesL1 : kNumMaskBytesL0; |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 186 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 187 | memset(packet_mask.get(), 0, |
| 188 | num_media_packets * mask_bytes_per_fec_packet); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 189 | |
| 190 | // Transfer packet masks from bit-mask to byte-mask. |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 191 | internal::GeneratePacketMasks(num_media_packets, num_fec_packets, |
| 192 | num_imp_packets, |
| 193 | kUseUnequalProtection, |
| 194 | mask_table, packet_mask.get()); |
pwestin@webrtc.org | 95cf479 | 2012-01-20 06:59:06 +0000 | [diff] [blame] | 195 | |
| 196 | #ifdef VERBOSE_OUTPUT |
danilchap | 40f349f | 2015-12-14 06:39:33 -0800 | [diff] [blame] | 197 | printf( |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 198 | "%u media packets, %u FEC packets, %u num_imp_packets, " |
danilchap | 40f349f | 2015-12-14 06:39:33 -0800 | [diff] [blame] | 199 | "loss rate = %.2f \n", |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 200 | num_media_packets, num_fec_packets, num_imp_packets, |
| 201 | loss_rate[loss_rate_idx]); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 202 | printf("Packet mask matrix \n"); |
pwestin@webrtc.org | 95cf479 | 2012-01-20 06:59:06 +0000 | [diff] [blame] | 203 | #endif |
| 204 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 205 | for (uint32_t i = 0; i < num_fec_packets; i++) { |
| 206 | for (uint32_t j = 0; j < num_media_packets; j++) { |
| 207 | const uint8_t byte_mask = |
| 208 | packet_mask[i * mask_bytes_per_fec_packet + j / 8]; |
| 209 | const uint32_t bit_position = (7 - j % 8); |
| 210 | fec_packet_masks[i][j] = |
| 211 | (byte_mask & (1 << bit_position)) >> bit_position; |
pwestin@webrtc.org | 95cf479 | 2012-01-20 06:59:06 +0000 | [diff] [blame] | 212 | #ifdef VERBOSE_OUTPUT |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 213 | printf("%u ", fec_packet_masks[i][j]); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 214 | #endif |
| 215 | } |
| 216 | #ifdef VERBOSE_OUTPUT |
| 217 | printf("\n"); |
pwestin@webrtc.org | 95cf479 | 2012-01-20 06:59:06 +0000 | [diff] [blame] | 218 | #endif |
| 219 | } |
| 220 | #ifdef VERBOSE_OUTPUT |
| 221 | printf("\n"); |
| 222 | #endif |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 223 | // Check for all zero rows or columns: indicates incorrect mask. |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 224 | uint32_t row_limit = num_media_packets; |
| 225 | for (uint32_t i = 0; i < num_fec_packets; ++i) { |
| 226 | uint32_t row_sum = 0; |
| 227 | for (uint32_t j = 0; j < row_limit; ++j) { |
| 228 | row_sum += fec_packet_masks[i][j]; |
pwestin@webrtc.org | 95cf479 | 2012-01-20 06:59:06 +0000 | [diff] [blame] | 229 | } |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 230 | ASSERT_NE(0u, row_sum) << "Row is all zero " << i; |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 231 | } |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 232 | for (uint32_t j = 0; j < row_limit; ++j) { |
| 233 | uint32_t column_sum = 0; |
| 234 | for (uint32_t i = 0; i < num_fec_packets; ++i) { |
| 235 | column_sum += fec_packet_masks[i][j]; |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 236 | } |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 237 | ASSERT_NE(0u, column_sum) << "Column is all zero " << j; |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 238 | } |
| 239 | |
| 240 | // Construct media packets. |
marpan@webrtc.org | c836453 | 2014-07-03 16:49:30 +0000 | [diff] [blame] | 241 | // Reset the sequence number here for each FEC code/mask tested |
| 242 | // below, to avoid sequence number wrap-around. In actual decoding, |
| 243 | // old FEC packets in list are dropped if sequence number wrap |
| 244 | // around is detected. This case is currently not handled below. |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 245 | seq_num = 0; |
| 246 | for (uint32_t i = 0; i < num_media_packets; ++i) { |
brandtr | 35c480c | 2016-08-09 01:23:23 -0700 | [diff] [blame] | 247 | std::unique_ptr<ForwardErrorCorrection::Packet> media_packet( |
| 248 | new ForwardErrorCorrection::Packet()); |
danilchap | 47a740b | 2015-12-15 00:30:07 -0800 | [diff] [blame] | 249 | const uint32_t kMinPacketSize = 12; |
| 250 | const uint32_t kMaxPacketSize = static_cast<uint32_t>( |
Rasmus Brandt | 78db158 | 2016-09-21 09:19:34 +0200 | [diff] [blame] | 251 | IP_PACKET_SIZE - 12 - 28 - fec->MaxPacketOverhead()); |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 252 | media_packet->length = random.Rand(kMinPacketSize, |
| 253 | kMaxPacketSize); |
danilchap | 47a740b | 2015-12-15 00:30:07 -0800 | [diff] [blame] | 254 | |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 255 | // Generate random values for the first 2 bytes. |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 256 | media_packet->data[0] = random.Rand<uint8_t>(); |
| 257 | media_packet->data[1] = random.Rand<uint8_t>(); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 258 | |
| 259 | // The first two bits are assumed to be 10 by the |
| 260 | // FEC encoder. In fact the FEC decoder will set the |
| 261 | // two first bits to 10 regardless of what they |
| 262 | // actually were. Set the first two bits to 10 |
| 263 | // so that a memcmp can be performed for the |
| 264 | // whole restored packet. |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 265 | media_packet->data[0] |= 0x80; |
| 266 | media_packet->data[0] &= 0xbf; |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 267 | |
| 268 | // FEC is applied to a whole frame. |
| 269 | // A frame is signaled by multiple packets without |
| 270 | // the marker bit set followed by the last packet of |
| 271 | // the frame for which the marker bit is set. |
| 272 | // Only push one (fake) frame to the FEC. |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 273 | media_packet->data[1] &= 0x7f; |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 274 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 275 | ByteWriter<uint16_t>::WriteBigEndian(&media_packet->data[2], |
| 276 | seq_num); |
| 277 | ByteWriter<uint32_t>::WriteBigEndian(&media_packet->data[4], |
| 278 | timestamp); |
| 279 | ByteWriter<uint32_t>::WriteBigEndian(&media_packet->data[8], |
brandtr | d726a3f | 2017-06-29 02:45:35 -0700 | [diff] [blame] | 280 | media_ssrc); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 281 | // Generate random values for payload |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 282 | for (size_t j = 12; j < media_packet->length; ++j) { |
| 283 | media_packet->data[j] = random.Rand<uint8_t>(); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 284 | } |
brandtr | 35c480c | 2016-08-09 01:23:23 -0700 | [diff] [blame] | 285 | media_packet_list.push_back(std::move(media_packet)); |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 286 | seq_num++; |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 287 | } |
brandtr | 35c480c | 2016-08-09 01:23:23 -0700 | [diff] [blame] | 288 | media_packet_list.back()->data[1] |= 0x80; |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 289 | |
Rasmus Brandt | 78db158 | 2016-09-21 09:19:34 +0200 | [diff] [blame] | 290 | ASSERT_EQ(0, fec->EncodeFec(media_packet_list, protection_factor, |
| 291 | num_imp_packets, kUseUnequalProtection, |
| 292 | fec_mask_type, &fec_packet_list)) |
brandtr | ece4aba | 2016-09-20 23:16:28 -0700 | [diff] [blame] | 293 | << "EncodeFec() failed"; |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 294 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 295 | ASSERT_EQ(num_fec_packets, fec_packet_list.size()) |
| 296 | << "We requested " << num_fec_packets << " FEC packets, but " |
brandtr | ece4aba | 2016-09-20 23:16:28 -0700 | [diff] [blame] | 297 | << "EncodeFec() produced " << fec_packet_list.size(); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 298 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 299 | memset(media_loss_mask, 0, sizeof(media_loss_mask)); |
| 300 | uint32_t media_packet_idx = 0; |
brandtr | 35c480c | 2016-08-09 01:23:23 -0700 | [diff] [blame] | 301 | for (const auto& media_packet : media_packet_list) { |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 302 | // We want a value between 0 and 1. |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 303 | const float loss_random_variable = random.Rand<float>(); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 304 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 305 | if (loss_random_variable >= loss_rate[loss_rate_idx]) { |
| 306 | media_loss_mask[media_packet_idx] = 1; |
brandtr | 35c480c | 2016-08-09 01:23:23 -0700 | [diff] [blame] | 307 | std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> |
| 308 | received_packet( |
| 309 | new ForwardErrorCorrection::ReceivedPacket()); |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 310 | received_packet->pkt = new ForwardErrorCorrection::Packet(); |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 311 | received_packet->pkt->length = media_packet->length; |
| 312 | memcpy(received_packet->pkt->data, media_packet->data, |
| 313 | media_packet->length); |
brandtr | d726a3f | 2017-06-29 02:45:35 -0700 | [diff] [blame] | 314 | received_packet->ssrc = media_ssrc; |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 315 | received_packet->seq_num = |
| 316 | ByteReader<uint16_t>::ReadBigEndian(&media_packet->data[2]); |
| 317 | received_packet->is_fec = false; |
brandtr | 35c480c | 2016-08-09 01:23:23 -0700 | [diff] [blame] | 318 | received_packet_list.push_back(std::move(received_packet)); |
pwestin@webrtc.org | 95cf479 | 2012-01-20 06:59:06 +0000 | [diff] [blame] | 319 | } |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 320 | media_packet_idx++; |
pwestin@webrtc.org | 95cf479 | 2012-01-20 06:59:06 +0000 | [diff] [blame] | 321 | } |
marpan@webrtc.org | 63b50f6 | 2011-12-08 19:05:39 +0000 | [diff] [blame] | 322 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 323 | memset(fec_loss_mask, 0, sizeof(fec_loss_mask)); |
| 324 | uint32_t fec_packet_idx = 0; |
| 325 | for (auto* fec_packet : fec_packet_list) { |
| 326 | const float loss_random_variable = random.Rand<float>(); |
| 327 | if (loss_random_variable >= loss_rate[loss_rate_idx]) { |
| 328 | fec_loss_mask[fec_packet_idx] = 1; |
brandtr | 35c480c | 2016-08-09 01:23:23 -0700 | [diff] [blame] | 329 | std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> |
| 330 | received_packet( |
| 331 | new ForwardErrorCorrection::ReceivedPacket()); |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 332 | received_packet->pkt = new ForwardErrorCorrection::Packet(); |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 333 | received_packet->pkt->length = fec_packet->length; |
| 334 | memcpy(received_packet->pkt->data, fec_packet->data, |
| 335 | fec_packet->length); |
brandtr | d726a3f | 2017-06-29 02:45:35 -0700 | [diff] [blame] | 336 | received_packet->seq_num = fec_seq_num_offset + seq_num; |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 337 | received_packet->is_fec = true; |
brandtr | d726a3f | 2017-06-29 02:45:35 -0700 | [diff] [blame] | 338 | received_packet->ssrc = fec_ssrc; |
brandtr | 35c480c | 2016-08-09 01:23:23 -0700 | [diff] [blame] | 339 | received_packet_list.push_back(std::move(received_packet)); |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 340 | |
| 341 | fec_mask_list.push_back(fec_packet_masks[fec_packet_idx]); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 342 | } |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 343 | ++fec_packet_idx; |
| 344 | ++seq_num; |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 345 | } |
| 346 | |
| 347 | #ifdef VERBOSE_OUTPUT |
| 348 | printf("Media loss mask:\n"); |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 349 | for (uint32_t i = 0; i < num_media_packets; i++) { |
| 350 | printf("%u ", media_loss_mask[i]); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 351 | } |
| 352 | printf("\n\n"); |
| 353 | |
| 354 | printf("FEC loss mask:\n"); |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 355 | for (uint32_t i = 0; i < num_fec_packets; i++) { |
| 356 | printf("%u ", fec_loss_mask[i]); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 357 | } |
| 358 | printf("\n\n"); |
| 359 | #endif |
| 360 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 361 | auto fec_mask_it = fec_mask_list.begin(); |
| 362 | while (fec_mask_it != fec_mask_list.end()) { |
| 363 | uint32_t hamming_dist = 0; |
| 364 | uint32_t recovery_position = 0; |
| 365 | for (uint32_t i = 0; i < num_media_packets; i++) { |
| 366 | if (media_loss_mask[i] == 0 && (*fec_mask_it)[i] == 1) { |
| 367 | recovery_position = i; |
| 368 | ++hamming_dist; |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 369 | } |
| 370 | } |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 371 | auto item_to_delete = fec_mask_it; |
| 372 | ++fec_mask_it; |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 373 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 374 | if (hamming_dist == 1) { |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 375 | // Recovery possible. Restart search. |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 376 | media_loss_mask[recovery_position] = 1; |
| 377 | fec_mask_it = fec_mask_list.begin(); |
| 378 | } else if (hamming_dist == 0) { |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 379 | // FEC packet cannot provide further recovery. |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 380 | fec_mask_list.erase(item_to_delete); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 381 | } |
| 382 | } |
| 383 | #ifdef VERBOSE_OUTPUT |
| 384 | printf("Recovery mask:\n"); |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 385 | for (uint32_t i = 0; i < num_media_packets; ++i) { |
| 386 | printf("%u ", media_loss_mask[i]); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 387 | } |
| 388 | printf("\n\n"); |
| 389 | #endif |
| 390 | // For error-checking frame completion. |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 391 | bool fec_packet_received = false; |
| 392 | while (!received_packet_list.empty()) { |
| 393 | size_t num_packets_to_decode = random.Rand( |
| 394 | 1u, static_cast<uint32_t>(received_packet_list.size())); |
| 395 | ReceivePackets(&to_decode_list, &received_packet_list, |
| 396 | num_packets_to_decode, reorder_rate, |
| 397 | duplicate_rate, &random); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 398 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 399 | if (fec_packet_received == false) { |
brandtr | 35c480c | 2016-08-09 01:23:23 -0700 | [diff] [blame] | 400 | for (const auto& received_packet : to_decode_list) { |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 401 | if (received_packet->is_fec) { |
| 402 | fec_packet_received = true; |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 403 | } |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 404 | } |
| 405 | } |
brandtr | ece4aba | 2016-09-20 23:16:28 -0700 | [diff] [blame] | 406 | ASSERT_EQ(0, |
Rasmus Brandt | 78db158 | 2016-09-21 09:19:34 +0200 | [diff] [blame] | 407 | fec->DecodeFec(&to_decode_list, &recovered_packet_list)) |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 408 | << "DecodeFec() failed"; |
| 409 | ASSERT_TRUE(to_decode_list.empty()) |
kjellander@webrtc.org | 22bbbdf | 2013-06-12 11:55:05 +0000 | [diff] [blame] | 410 | << "Received packet list is not empty."; |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 411 | } |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 412 | media_packet_idx = 0; |
brandtr | 35c480c | 2016-08-09 01:23:23 -0700 | [diff] [blame] | 413 | for (const auto& media_packet : media_packet_list) { |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 414 | if (media_loss_mask[media_packet_idx] == 1) { |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 415 | // Should have recovered this packet. |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 416 | auto recovered_packet_list_it = recovered_packet_list.cbegin(); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 417 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 418 | ASSERT_FALSE(recovered_packet_list_it == |
| 419 | recovered_packet_list.end()) |
danilchap | 40f349f | 2015-12-14 06:39:33 -0800 | [diff] [blame] | 420 | << "Insufficient number of recovered packets."; |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 421 | ForwardErrorCorrection::RecoveredPacket* recovered_packet = |
brandtr | 35c480c | 2016-08-09 01:23:23 -0700 | [diff] [blame] | 422 | recovered_packet_list_it->get(); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 423 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 424 | ASSERT_EQ(recovered_packet->pkt->length, media_packet->length) |
kjellander@webrtc.org | 22bbbdf | 2013-06-12 11:55:05 +0000 | [diff] [blame] | 425 | << "Recovered packet length not identical to original " |
| 426 | << "media packet"; |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 427 | ASSERT_EQ(0, memcmp(recovered_packet->pkt->data, |
| 428 | media_packet->data, media_packet->length)) |
kjellander@webrtc.org | 22bbbdf | 2013-06-12 11:55:05 +0000 | [diff] [blame] | 429 | << "Recovered packet payload not identical to original " |
| 430 | << "media packet"; |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 431 | recovered_packet_list.pop_front(); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 432 | } |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 433 | ++media_packet_idx; |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 434 | } |
Rasmus Brandt | 78db158 | 2016-09-21 09:19:34 +0200 | [diff] [blame] | 435 | fec->ResetState(&recovered_packet_list); |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 436 | ASSERT_TRUE(recovered_packet_list.empty()) |
kjellander@webrtc.org | 22bbbdf | 2013-06-12 11:55:05 +0000 | [diff] [blame] | 437 | << "Excessive number of recovered packets.\t size is: " |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 438 | << recovered_packet_list.size(); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 439 | // -- Teardown -- |
brandtr | 35c480c | 2016-08-09 01:23:23 -0700 | [diff] [blame] | 440 | media_packet_list.clear(); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 441 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 442 | // Clear FEC packet list, so we don't pass in a non-empty |
| 443 | // list in the next call to DecodeFec(). |
| 444 | fec_packet_list.clear(); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 445 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 446 | // Delete received packets we didn't pass to DecodeFec(), due to |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 447 | // early frame completion. |
brandtr | 35c480c | 2016-08-09 01:23:23 -0700 | [diff] [blame] | 448 | received_packet_list.clear(); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 449 | |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 450 | while (!fec_mask_list.empty()) { |
| 451 | fec_mask_list.pop_front(); |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 452 | } |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 453 | timestamp += 90000 / 30; |
| 454 | } // loop over num_imp_packets |
danilchap | 40f349f | 2015-12-14 06:39:33 -0800 | [diff] [blame] | 455 | } // loop over FecPackets |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 456 | } // loop over num_media_packets |
marpan@webrtc.org | 8866bb1 | 2012-06-05 16:42:20 +0000 | [diff] [blame] | 457 | } // loop over loss rates |
danilchap | 40f349f | 2015-12-14 06:39:33 -0800 | [diff] [blame] | 458 | } // loop over mask types |
marpan@webrtc.org | 63b50f6 | 2011-12-08 19:05:39 +0000 | [diff] [blame] | 459 | |
brandtr | 35c480c | 2016-08-09 01:23:23 -0700 | [diff] [blame] | 460 | // Have DecodeFec clear the recovered packet list. |
Rasmus Brandt | 78db158 | 2016-09-21 09:19:34 +0200 | [diff] [blame] | 461 | fec->ResetState(&recovered_packet_list); |
Rasmus Brandt | ae4f767 | 2016-07-07 09:40:51 +0200 | [diff] [blame] | 462 | ASSERT_TRUE(recovered_packet_list.empty()) |
kjellander@webrtc.org | 22bbbdf | 2013-06-12 11:55:05 +0000 | [diff] [blame] | 463 | << "Recovered packet list is not empty"; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 464 | } |
| 465 | |
brandtr | a25a695 | 2017-08-01 05:01:07 -0700 | [diff] [blame] | 466 | TEST(FecTest, UlpfecTest) { |
brandtr | d726a3f | 2017-06-29 02:45:35 -0700 | [diff] [blame] | 467 | RunTest(false); |
| 468 | } |
| 469 | |
brandtr | a25a695 | 2017-08-01 05:01:07 -0700 | [diff] [blame] | 470 | TEST(FecTest, FlexfecTest) { |
brandtr | d726a3f | 2017-06-29 02:45:35 -0700 | [diff] [blame] | 471 | RunTest(true); |
| 472 | } |
| 473 | |
kjellander@webrtc.org | 22bbbdf | 2013-06-12 11:55:05 +0000 | [diff] [blame] | 474 | } // namespace test |
| 475 | } // namespace webrtc |