OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | |
3 * | |
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 #include <map> | |
12 #include <memory> | |
13 #include <string> | |
14 #include <utility> | |
15 #include <vector> | |
16 | |
17 #include "webrtc/test/gtest.h" | |
18 #include "webrtc/base/buffer.h" | |
19 #include "webrtc/base/checks.h" | |
20 #include "webrtc/base/random.h" | |
21 #include "webrtc/call.h" | |
22 #include "webrtc/call/rtc_event_log.h" | |
23 #include "webrtc/call/rtc_event_log_parser.h" | |
24 #include "webrtc/call/rtc_event_log_unittest_helper.h" | |
25 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" | |
26 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h" | |
27 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h" | |
28 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h" | |
29 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" | |
30 #include "webrtc/system_wrappers/include/clock.h" | |
31 #include "webrtc/test/test_suite.h" | |
32 #include "webrtc/test/testsupport/fileutils.h" | |
33 | |
34 // Files generated at build-time by the protobuf compiler. | |
35 #ifdef WEBRTC_ANDROID_PLATFORM_BUILD | |
36 #include "external/webrtc/webrtc/call/rtc_event_log.pb.h" | |
37 #else | |
38 #include "webrtc/call/rtc_event_log.pb.h" | |
39 #endif | |
40 | |
41 namespace webrtc { | |
42 | |
43 namespace { | |
44 | |
45 const RTPExtensionType kExtensionTypes[] = { | |
46 RTPExtensionType::kRtpExtensionTransmissionTimeOffset, | |
47 RTPExtensionType::kRtpExtensionAudioLevel, | |
48 RTPExtensionType::kRtpExtensionAbsoluteSendTime, | |
49 RTPExtensionType::kRtpExtensionVideoRotation, | |
50 RTPExtensionType::kRtpExtensionTransportSequenceNumber}; | |
51 const char* kExtensionNames[] = { | |
52 RtpExtension::kTimestampOffsetUri, RtpExtension::kAudioLevelUri, | |
53 RtpExtension::kAbsSendTimeUri, RtpExtension::kVideoRotationUri, | |
54 RtpExtension::kTransportSequenceNumberUri}; | |
55 const size_t kNumExtensions = 5; | |
56 | |
57 void PrintActualEvents(const ParsedRtcEventLog& parsed_log) { | |
58 std::map<int, size_t> actual_event_counts; | |
59 for (size_t i = 0; i < parsed_log.GetNumberOfEvents(); i++) { | |
60 actual_event_counts[parsed_log.GetEventType(i)]++; | |
61 } | |
62 printf("Actual events: "); | |
63 for (auto kv : actual_event_counts) { | |
64 printf("%d_count = %zu, ", kv.first, kv.second); | |
65 } | |
66 printf("\n"); | |
67 for (size_t i = 0; i < parsed_log.GetNumberOfEvents(); i++) { | |
68 printf("%4d ", parsed_log.GetEventType(i)); | |
69 } | |
70 printf("\n"); | |
71 } | |
72 | |
73 void PrintExpectedEvents(size_t rtp_count, | |
74 size_t rtcp_count, | |
75 size_t playout_count, | |
76 size_t bwe_loss_count) { | |
77 printf( | |
78 "Expected events: rtp_count = %zu, rtcp_count = %zu," | |
79 "playout_count = %zu, bwe_loss_count = %zu\n", | |
80 rtp_count, rtcp_count, playout_count, bwe_loss_count); | |
81 size_t rtcp_index = 1, playout_index = 1, bwe_loss_index = 1; | |
82 printf("strt cfg cfg "); | |
83 for (size_t i = 1; i <= rtp_count; i++) { | |
84 printf(" rtp "); | |
85 if (i * rtcp_count >= rtcp_index * rtp_count) { | |
86 printf("rtcp "); | |
87 rtcp_index++; | |
88 } | |
89 if (i * playout_count >= playout_index * rtp_count) { | |
90 printf("play "); | |
91 playout_index++; | |
92 } | |
93 if (i * bwe_loss_count >= bwe_loss_index * rtp_count) { | |
94 printf("loss "); | |
95 bwe_loss_index++; | |
96 } | |
97 } | |
98 printf("end \n"); | |
99 } | |
100 } // namespace | |
101 | |
102 /* | |
103 * Bit number i of extension_bitvector is set to indicate the | |
104 * presence of extension number i from kExtensionTypes / kExtensionNames. | |
105 * The least significant bit extension_bitvector has number 0. | |
106 */ | |
107 RtpPacketToSend GenerateRtpPacket(const RtpHeaderExtensionMap* extensions, | |
108 uint32_t csrcs_count, | |
109 size_t packet_size, | |
110 Random* prng) { | |
111 RTC_CHECK_GE(packet_size, 16 + 4 * csrcs_count + 4 * kNumExtensions); | |
112 | |
113 std::vector<uint32_t> csrcs; | |
114 for (unsigned i = 0; i < csrcs_count; i++) { | |
115 csrcs.push_back(prng->Rand<uint32_t>()); | |
116 } | |
117 | |
118 RtpPacketToSend rtp_packet(extensions, packet_size); | |
119 rtp_packet.SetPayloadType(prng->Rand(127)); | |
120 rtp_packet.SetMarker(prng->Rand<bool>()); | |
121 rtp_packet.SetSequenceNumber(prng->Rand<uint16_t>()); | |
122 rtp_packet.SetSsrc(prng->Rand<uint32_t>()); | |
123 rtp_packet.SetTimestamp(prng->Rand<uint32_t>()); | |
124 rtp_packet.SetCsrcs(csrcs); | |
125 | |
126 rtp_packet.SetExtension<TransmissionOffset>(prng->Rand(0x00ffffff)); | |
127 rtp_packet.SetExtension<AudioLevel>(prng->Rand<bool>(), prng->Rand(127)); | |
128 rtp_packet.SetExtension<AbsoluteSendTime>(prng->Rand<int32_t>()); | |
129 rtp_packet.SetExtension<VideoOrientation>(prng->Rand(2)); | |
130 rtp_packet.SetExtension<TransportSequenceNumber>(prng->Rand<uint16_t>()); | |
131 | |
132 size_t payload_size = packet_size - rtp_packet.headers_size(); | |
133 uint8_t* payload = rtp_packet.AllocatePayload(payload_size); | |
134 for (size_t i = 0; i < payload_size; i++) { | |
135 payload[i] = prng->Rand<uint8_t>(); | |
136 } | |
137 return rtp_packet; | |
138 } | |
139 | |
140 rtc::Buffer GenerateRtcpPacket(Random* prng) { | |
141 rtcp::ReportBlock report_block; | |
142 report_block.SetMediaSsrc(prng->Rand<uint32_t>()); // Remote SSRC. | |
143 report_block.SetFractionLost(prng->Rand(50)); | |
144 | |
145 rtcp::SenderReport sender_report; | |
146 sender_report.SetSenderSsrc(prng->Rand<uint32_t>()); | |
147 sender_report.SetNtp(NtpTime(prng->Rand<uint32_t>(), prng->Rand<uint32_t>())); | |
148 sender_report.SetPacketCount(prng->Rand<uint32_t>()); | |
149 sender_report.AddReportBlock(report_block); | |
150 | |
151 return sender_report.Build(); | |
152 } | |
153 | |
154 void GenerateVideoReceiveConfig(uint32_t extensions_bitvector, | |
155 VideoReceiveStream::Config* config, | |
156 Random* prng) { | |
157 // Create a map from a payload type to an encoder name. | |
158 VideoReceiveStream::Decoder decoder; | |
159 decoder.payload_type = prng->Rand(0, 127); | |
160 decoder.payload_name = (prng->Rand<bool>() ? "VP8" : "H264"); | |
161 config->decoders.push_back(decoder); | |
162 // Add SSRCs for the stream. | |
163 config->rtp.remote_ssrc = prng->Rand<uint32_t>(); | |
164 config->rtp.local_ssrc = prng->Rand<uint32_t>(); | |
165 // Add extensions and settings for RTCP. | |
166 config->rtp.rtcp_mode = | |
167 prng->Rand<bool>() ? RtcpMode::kCompound : RtcpMode::kReducedSize; | |
168 config->rtp.remb = prng->Rand<bool>(); | |
169 // Add a map from a payload type to a new ssrc and a new payload type for RTX. | |
170 VideoReceiveStream::Config::Rtp::Rtx rtx_pair; | |
171 rtx_pair.ssrc = prng->Rand<uint32_t>(); | |
172 rtx_pair.payload_type = prng->Rand(0, 127); | |
173 config->rtp.rtx.insert(std::make_pair(prng->Rand(0, 127), rtx_pair)); | |
174 // Add header extensions. | |
175 for (unsigned i = 0; i < kNumExtensions; i++) { | |
176 if (extensions_bitvector & (1u << i)) { | |
177 config->rtp.extensions.push_back( | |
178 RtpExtension(kExtensionNames[i], prng->Rand<int>())); | |
179 } | |
180 } | |
181 } | |
182 | |
183 void GenerateVideoSendConfig(uint32_t extensions_bitvector, | |
184 VideoSendStream::Config* config, | |
185 Random* prng) { | |
186 // Create a map from a payload type to an encoder name. | |
187 config->encoder_settings.payload_type = prng->Rand(0, 127); | |
188 config->encoder_settings.payload_name = (prng->Rand<bool>() ? "VP8" : "H264"); | |
189 // Add SSRCs for the stream. | |
190 config->rtp.ssrcs.push_back(prng->Rand<uint32_t>()); | |
191 // Add a map from a payload type to new ssrcs and a new payload type for RTX. | |
192 config->rtp.rtx.ssrcs.push_back(prng->Rand<uint32_t>()); | |
193 config->rtp.rtx.payload_type = prng->Rand(0, 127); | |
194 // Add header extensions. | |
195 for (unsigned i = 0; i < kNumExtensions; i++) { | |
196 if (extensions_bitvector & (1u << i)) { | |
197 config->rtp.extensions.push_back( | |
198 RtpExtension(kExtensionNames[i], prng->Rand<int>())); | |
199 } | |
200 } | |
201 } | |
202 | |
203 // Test for the RtcEventLog class. Dumps some RTP packets and other events | |
204 // to disk, then reads them back to see if they match. | |
205 void LogSessionAndReadBack(size_t rtp_count, | |
206 size_t rtcp_count, | |
207 size_t playout_count, | |
208 size_t bwe_loss_count, | |
209 uint32_t extensions_bitvector, | |
210 uint32_t csrcs_count, | |
211 unsigned int random_seed) { | |
212 ASSERT_LE(rtcp_count, rtp_count); | |
213 ASSERT_LE(playout_count, rtp_count); | |
214 ASSERT_LE(bwe_loss_count, rtp_count); | |
215 std::vector<RtpPacketToSend> rtp_packets; | |
216 std::vector<rtc::Buffer> rtcp_packets; | |
217 std::vector<uint32_t> playout_ssrcs; | |
218 std::vector<std::pair<int32_t, uint8_t> > bwe_loss_updates; | |
219 | |
220 VideoReceiveStream::Config receiver_config(nullptr); | |
221 VideoSendStream::Config sender_config(nullptr); | |
222 | |
223 Random prng(random_seed); | |
224 | |
225 // Initialize rtp header extensions to be used in generated rtp packets. | |
226 RtpHeaderExtensionMap extensions; | |
227 for (unsigned i = 0; i < kNumExtensions; i++) { | |
228 if (extensions_bitvector & (1u << i)) { | |
229 extensions.Register(kExtensionTypes[i], i + 1); | |
230 } | |
231 } | |
232 // Create rtp_count RTP packets containing random data. | |
233 for (size_t i = 0; i < rtp_count; i++) { | |
234 size_t packet_size = prng.Rand(1000, 1100); | |
235 rtp_packets.push_back( | |
236 GenerateRtpPacket(&extensions, csrcs_count, packet_size, &prng)); | |
237 } | |
238 // Create rtcp_count RTCP packets containing random data. | |
239 for (size_t i = 0; i < rtcp_count; i++) { | |
240 rtcp_packets.push_back(GenerateRtcpPacket(&prng)); | |
241 } | |
242 // Create playout_count random SSRCs to use when logging AudioPlayout events. | |
243 for (size_t i = 0; i < playout_count; i++) { | |
244 playout_ssrcs.push_back(prng.Rand<uint32_t>()); | |
245 } | |
246 // Create bwe_loss_count random bitrate updates for BwePacketLoss. | |
247 for (size_t i = 0; i < bwe_loss_count; i++) { | |
248 bwe_loss_updates.push_back( | |
249 std::make_pair(prng.Rand<int32_t>(), prng.Rand<uint8_t>())); | |
250 } | |
251 // Create configurations for the video streams. | |
252 GenerateVideoReceiveConfig(extensions_bitvector, &receiver_config, &prng); | |
253 GenerateVideoSendConfig(extensions_bitvector, &sender_config, &prng); | |
254 const int config_count = 2; | |
255 | |
256 // Find the name of the current test, in order to use it as a temporary | |
257 // filename. | |
258 auto test_info = ::testing::UnitTest::GetInstance()->current_test_info(); | |
259 const std::string temp_filename = | |
260 test::OutputPath() + test_info->test_case_name() + test_info->name(); | |
261 | |
262 // When log_dumper goes out of scope, it causes the log file to be flushed | |
263 // to disk. | |
264 { | |
265 SimulatedClock fake_clock(prng.Rand<uint32_t>()); | |
266 std::unique_ptr<RtcEventLog> log_dumper(RtcEventLog::Create(&fake_clock)); | |
267 log_dumper->LogVideoReceiveStreamConfig(receiver_config); | |
268 fake_clock.AdvanceTimeMicroseconds(prng.Rand(1, 1000)); | |
269 log_dumper->LogVideoSendStreamConfig(sender_config); | |
270 fake_clock.AdvanceTimeMicroseconds(prng.Rand(1, 1000)); | |
271 size_t rtcp_index = 1; | |
272 size_t playout_index = 1; | |
273 size_t bwe_loss_index = 1; | |
274 for (size_t i = 1; i <= rtp_count; i++) { | |
275 log_dumper->LogRtpHeader( | |
276 (i % 2 == 0) ? kIncomingPacket : kOutgoingPacket, | |
277 (i % 3 == 0) ? MediaType::AUDIO : MediaType::VIDEO, | |
278 rtp_packets[i - 1].data(), rtp_packets[i - 1].size()); | |
279 fake_clock.AdvanceTimeMicroseconds(prng.Rand(1, 1000)); | |
280 if (i * rtcp_count >= rtcp_index * rtp_count) { | |
281 log_dumper->LogRtcpPacket( | |
282 (rtcp_index % 2 == 0) ? kIncomingPacket : kOutgoingPacket, | |
283 rtcp_index % 3 == 0 ? MediaType::AUDIO : MediaType::VIDEO, | |
284 rtcp_packets[rtcp_index - 1].data(), | |
285 rtcp_packets[rtcp_index - 1].size()); | |
286 rtcp_index++; | |
287 fake_clock.AdvanceTimeMicroseconds(prng.Rand(1, 1000)); | |
288 } | |
289 if (i * playout_count >= playout_index * rtp_count) { | |
290 log_dumper->LogAudioPlayout(playout_ssrcs[playout_index - 1]); | |
291 playout_index++; | |
292 fake_clock.AdvanceTimeMicroseconds(prng.Rand(1, 1000)); | |
293 } | |
294 if (i * bwe_loss_count >= bwe_loss_index * rtp_count) { | |
295 log_dumper->LogBwePacketLossEvent( | |
296 bwe_loss_updates[bwe_loss_index - 1].first, | |
297 bwe_loss_updates[bwe_loss_index - 1].second, i); | |
298 bwe_loss_index++; | |
299 fake_clock.AdvanceTimeMicroseconds(prng.Rand(1, 1000)); | |
300 } | |
301 if (i == rtp_count / 2) { | |
302 log_dumper->StartLogging(temp_filename, 10000000); | |
303 fake_clock.AdvanceTimeMicroseconds(prng.Rand(1, 1000)); | |
304 } | |
305 } | |
306 log_dumper->StopLogging(); | |
307 } | |
308 | |
309 // Read the generated file from disk. | |
310 ParsedRtcEventLog parsed_log; | |
311 | |
312 ASSERT_TRUE(parsed_log.ParseFile(temp_filename)); | |
313 | |
314 // Verify that what we read back from the event log is the same as | |
315 // what we wrote down. For RTCP we log the full packets, but for | |
316 // RTP we should only log the header. | |
317 const size_t event_count = config_count + playout_count + bwe_loss_count + | |
318 rtcp_count + rtp_count + 2; | |
319 EXPECT_GE(1000u, event_count); // The events must fit in the message queue. | |
320 EXPECT_EQ(event_count, parsed_log.GetNumberOfEvents()); | |
321 if (event_count != parsed_log.GetNumberOfEvents()) { | |
322 // Print the expected and actual event types for easier debugging. | |
323 PrintActualEvents(parsed_log); | |
324 PrintExpectedEvents(rtp_count, rtcp_count, playout_count, bwe_loss_count); | |
325 } | |
326 RtcEventLogTestHelper::VerifyLogStartEvent(parsed_log, 0); | |
327 RtcEventLogTestHelper::VerifyReceiveStreamConfig(parsed_log, 1, | |
328 receiver_config); | |
329 RtcEventLogTestHelper::VerifySendStreamConfig(parsed_log, 2, sender_config); | |
330 size_t event_index = config_count + 1; | |
331 size_t rtcp_index = 1; | |
332 size_t playout_index = 1; | |
333 size_t bwe_loss_index = 1; | |
334 for (size_t i = 1; i <= rtp_count; i++) { | |
335 RtcEventLogTestHelper::VerifyRtpEvent( | |
336 parsed_log, event_index, | |
337 (i % 2 == 0) ? kIncomingPacket : kOutgoingPacket, | |
338 (i % 3 == 0) ? MediaType::AUDIO : MediaType::VIDEO, | |
339 rtp_packets[i - 1].data(), rtp_packets[i - 1].headers_size(), | |
340 rtp_packets[i - 1].size()); | |
341 event_index++; | |
342 if (i * rtcp_count >= rtcp_index * rtp_count) { | |
343 RtcEventLogTestHelper::VerifyRtcpEvent( | |
344 parsed_log, event_index, | |
345 rtcp_index % 2 == 0 ? kIncomingPacket : kOutgoingPacket, | |
346 rtcp_index % 3 == 0 ? MediaType::AUDIO : MediaType::VIDEO, | |
347 rtcp_packets[rtcp_index - 1].data(), | |
348 rtcp_packets[rtcp_index - 1].size()); | |
349 event_index++; | |
350 rtcp_index++; | |
351 } | |
352 if (i * playout_count >= playout_index * rtp_count) { | |
353 RtcEventLogTestHelper::VerifyPlayoutEvent( | |
354 parsed_log, event_index, playout_ssrcs[playout_index - 1]); | |
355 event_index++; | |
356 playout_index++; | |
357 } | |
358 if (i * bwe_loss_count >= bwe_loss_index * rtp_count) { | |
359 RtcEventLogTestHelper::VerifyBweLossEvent( | |
360 parsed_log, event_index, bwe_loss_updates[bwe_loss_index - 1].first, | |
361 bwe_loss_updates[bwe_loss_index - 1].second, i); | |
362 event_index++; | |
363 bwe_loss_index++; | |
364 } | |
365 } | |
366 | |
367 // Clean up temporary file - can be pretty slow. | |
368 remove(temp_filename.c_str()); | |
369 } | |
370 | |
371 TEST(RtcEventLogTest, LogSessionAndReadBack) { | |
372 // Log 5 RTP, 2 RTCP, 0 playout events and 0 BWE events | |
373 // with no header extensions or CSRCS. | |
374 LogSessionAndReadBack(5, 2, 0, 0, 0, 0, 321); | |
375 | |
376 // Enable AbsSendTime and TransportSequenceNumbers. | |
377 uint32_t extensions = 0; | |
378 for (uint32_t i = 0; i < kNumExtensions; i++) { | |
379 if (kExtensionTypes[i] == RTPExtensionType::kRtpExtensionAbsoluteSendTime || | |
380 kExtensionTypes[i] == | |
381 RTPExtensionType::kRtpExtensionTransportSequenceNumber) { | |
382 extensions |= 1u << i; | |
383 } | |
384 } | |
385 LogSessionAndReadBack(8, 2, 0, 0, extensions, 0, 3141592653u); | |
386 | |
387 extensions = (1u << kNumExtensions) - 1; // Enable all header extensions. | |
388 LogSessionAndReadBack(9, 2, 3, 2, extensions, 2, 2718281828u); | |
389 | |
390 // Try all combinations of header extensions and up to 2 CSRCS. | |
391 for (extensions = 0; extensions < (1u << kNumExtensions); extensions++) { | |
392 for (uint32_t csrcs_count = 0; csrcs_count < 3; csrcs_count++) { | |
393 LogSessionAndReadBack(5 + extensions, // Number of RTP packets. | |
394 2 + csrcs_count, // Number of RTCP packets. | |
395 3 + csrcs_count, // Number of playout events. | |
396 1 + csrcs_count, // Number of BWE loss events. | |
397 extensions, // Bit vector choosing extensions. | |
398 csrcs_count, // Number of contributing sources. | |
399 extensions * 3 + csrcs_count + 1); // Random seed. | |
400 } | |
401 } | |
402 } | |
403 | |
404 TEST(RtcEventLogTest, LogEventAndReadBack) { | |
405 Random prng(987654321); | |
406 | |
407 // Create one RTP and one RTCP packet containing random data. | |
408 size_t packet_size = prng.Rand(1000, 1100); | |
409 RtpPacketToSend rtp_packet = | |
410 GenerateRtpPacket(nullptr, 0, packet_size, &prng); | |
411 rtc::Buffer rtcp_packet = GenerateRtcpPacket(&prng); | |
412 | |
413 // Find the name of the current test, in order to use it as a temporary | |
414 // filename. | |
415 auto test_info = ::testing::UnitTest::GetInstance()->current_test_info(); | |
416 const std::string temp_filename = | |
417 test::OutputPath() + test_info->test_case_name() + test_info->name(); | |
418 | |
419 // Add RTP, start logging, add RTCP and then stop logging | |
420 SimulatedClock fake_clock(prng.Rand<uint32_t>()); | |
421 std::unique_ptr<RtcEventLog> log_dumper(RtcEventLog::Create(&fake_clock)); | |
422 | |
423 log_dumper->LogRtpHeader(kIncomingPacket, MediaType::VIDEO, rtp_packet.data(), | |
424 rtp_packet.size()); | |
425 fake_clock.AdvanceTimeMicroseconds(prng.Rand(1, 1000)); | |
426 | |
427 log_dumper->StartLogging(temp_filename, 10000000); | |
428 fake_clock.AdvanceTimeMicroseconds(prng.Rand(1, 1000)); | |
429 | |
430 log_dumper->LogRtcpPacket(kOutgoingPacket, MediaType::VIDEO, | |
431 rtcp_packet.data(), rtcp_packet.size()); | |
432 fake_clock.AdvanceTimeMicroseconds(prng.Rand(1, 1000)); | |
433 | |
434 log_dumper->StopLogging(); | |
435 | |
436 // Read the generated file from disk. | |
437 ParsedRtcEventLog parsed_log; | |
438 ASSERT_TRUE(parsed_log.ParseFile(temp_filename)); | |
439 | |
440 // Verify that what we read back from the event log is the same as | |
441 // what we wrote down. | |
442 EXPECT_EQ(4u, parsed_log.GetNumberOfEvents()); | |
443 | |
444 RtcEventLogTestHelper::VerifyLogStartEvent(parsed_log, 0); | |
445 | |
446 RtcEventLogTestHelper::VerifyRtpEvent( | |
447 parsed_log, 1, kIncomingPacket, MediaType::VIDEO, rtp_packet.data(), | |
448 rtp_packet.headers_size(), rtp_packet.size()); | |
449 | |
450 RtcEventLogTestHelper::VerifyRtcpEvent(parsed_log, 2, kOutgoingPacket, | |
451 MediaType::VIDEO, rtcp_packet.data(), | |
452 rtcp_packet.size()); | |
453 | |
454 RtcEventLogTestHelper::VerifyLogEndEvent(parsed_log, 3); | |
455 | |
456 // Clean up temporary file - can be pretty slow. | |
457 remove(temp_filename.c_str()); | |
458 } | |
459 | |
460 } // namespace webrtc | |
OLD | NEW |