xref: /aosp_15_r20/external/webrtc/rtc_tools/video_replay.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2014 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 <stdio.h>
12 
13 #include <fstream>
14 #include <map>
15 #include <memory>
16 
17 #include "absl/flags/flag.h"
18 #include "absl/flags/parse.h"
19 #include "api/field_trials.h"
20 #include "api/rtc_event_log/rtc_event_log.h"
21 #include "api/task_queue/default_task_queue_factory.h"
22 #include "api/test/video/function_video_decoder_factory.h"
23 #include "api/transport/field_trial_based_config.h"
24 #include "api/video/video_codec_type.h"
25 #include "api/video_codecs/video_decoder.h"
26 #include "call/call.h"
27 #include "common_video/libyuv/include/webrtc_libyuv.h"
28 #include "media/engine/internal_decoder_factory.h"
29 #include "modules/rtp_rtcp/source/rtp_packet.h"
30 #include "modules/rtp_rtcp/source/rtp_util.h"
31 #include "modules/video_coding/utility/ivf_file_writer.h"
32 #include "rtc_base/checks.h"
33 #include "rtc_base/string_to_number.h"
34 #include "rtc_base/strings/json.h"
35 #include "rtc_base/time_utils.h"
36 #include "system_wrappers/include/clock.h"
37 #include "system_wrappers/include/sleep.h"
38 #include "test/call_config_utils.h"
39 #include "test/call_test.h"
40 #include "test/encoder_settings.h"
41 #include "test/fake_decoder.h"
42 #include "test/gtest.h"
43 #include "test/null_transport.h"
44 #include "test/rtp_file_reader.h"
45 #include "test/run_loop.h"
46 #include "test/run_test.h"
47 #include "test/test_video_capturer.h"
48 #include "test/testsupport/frame_writer.h"
49 #include "test/time_controller/simulated_time_controller.h"
50 #include "test/video_renderer.h"
51 
52 // Flag for payload type.
53 ABSL_FLAG(int,
54           media_payload_type,
55           webrtc::test::CallTest::kPayloadTypeVP8,
56           "Media payload type");
57 
58 // Flag for RED payload type.
59 ABSL_FLAG(int,
60           red_payload_type,
61           webrtc::test::CallTest::kRedPayloadType,
62           "RED payload type");
63 
64 // Flag for ULPFEC payload type.
65 ABSL_FLAG(int,
66           ulpfec_payload_type,
67           webrtc::test::CallTest::kUlpfecPayloadType,
68           "ULPFEC payload type");
69 
70 // Flag for FLEXFEC payload type.
71 ABSL_FLAG(int,
72           flexfec_payload_type,
73           webrtc::test::CallTest::kFlexfecPayloadType,
74           "FLEXFEC payload type");
75 
76 ABSL_FLAG(int,
77           media_payload_type_rtx,
78           webrtc::test::CallTest::kSendRtxPayloadType,
79           "Media over RTX payload type");
80 
81 ABSL_FLAG(int,
82           red_payload_type_rtx,
83           webrtc::test::CallTest::kRtxRedPayloadType,
84           "RED over RTX payload type");
85 
86 // Flag for SSRC and RTX SSRC.
87 ABSL_FLAG(uint32_t,
88           ssrc,
89           webrtc::test::CallTest::kVideoSendSsrcs[0],
90           "Incoming SSRC");
91 ABSL_FLAG(uint32_t,
92           ssrc_rtx,
93           webrtc::test::CallTest::kSendRtxSsrcs[0],
94           "Incoming RTX SSRC");
95 
96 ABSL_FLAG(uint32_t,
97           ssrc_flexfec,
98           webrtc::test::CallTest::kFlexfecSendSsrc,
99           "Incoming FLEXFEC SSRC");
100 
101 // Flag for abs-send-time id.
102 ABSL_FLAG(int, abs_send_time_id, -1, "RTP extension ID for abs-send-time");
103 
104 // Flag for transmission-offset id.
105 ABSL_FLAG(int,
106           transmission_offset_id,
107           -1,
108           "RTP extension ID for transmission-offset");
109 
110 // Flag for rtpdump input file.
111 ABSL_FLAG(std::string, input_file, "", "input file");
112 
113 ABSL_FLAG(std::string, config_file, "", "config file");
114 
115 // Flag for raw output files.
116 ABSL_FLAG(std::string,
117           out_base,
118           "",
119           "Basename (excluding .jpg) for raw output");
120 
121 ABSL_FLAG(std::string,
122           decoder_bitstream_filename,
123           "",
124           "Decoder bitstream output file");
125 
126 ABSL_FLAG(std::string, decoder_ivf_filename, "", "Decoder ivf output file");
127 
128 // Flag for video codec.
129 ABSL_FLAG(std::string, codec, "VP8", "Video codec");
130 
131 // Flags for rtp start and stop timestamp.
132 ABSL_FLAG(uint32_t,
133           start_timestamp,
134           0,
135           "RTP start timestamp, packets with smaller timestamp will be ignored "
136           "(no wraparound)");
137 ABSL_FLAG(uint32_t,
138           stop_timestamp,
139           4294967295,
140           "RTP stop timestamp, packets with larger timestamp will be ignored "
141           "(no wraparound)");
142 
143 // Flags for render window width and height
144 ABSL_FLAG(uint32_t, render_width, 640, "Width of render window");
145 ABSL_FLAG(uint32_t, render_height, 480, "Height of render window");
146 
147 ABSL_FLAG(
148     std::string,
149     force_fieldtrials,
150     "",
151     "Field trials control experimental feature code which can be forced. "
152     "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enabled/"
153     " will assign the group Enable to field trial WebRTC-FooFeature. Multiple "
154     "trials are separated by \"/\"");
155 
156 ABSL_FLAG(bool, simulated_time, false, "Run in simulated time");
157 
158 ABSL_FLAG(bool, disable_preview, false, "Disable decoded video preview.");
159 
160 ABSL_FLAG(bool, disable_decoding, false, "Disable video decoding.");
161 
162 ABSL_FLAG(int,
163           extend_run_time_duration,
164           0,
165           "Extends the run time of the receiving client after the last RTP "
166           "packet has been delivered. Typically useful to let the last few "
167           "frames be decoded and rendered. Duration given in seconds.");
168 
169 namespace {
ValidatePayloadType(int32_t payload_type)170 bool ValidatePayloadType(int32_t payload_type) {
171   return payload_type > 0 && payload_type <= 127;
172 }
173 
ValidateOptionalPayloadType(int32_t payload_type)174 bool ValidateOptionalPayloadType(int32_t payload_type) {
175   return payload_type == -1 || ValidatePayloadType(payload_type);
176 }
177 
ValidateRtpHeaderExtensionId(int32_t extension_id)178 bool ValidateRtpHeaderExtensionId(int32_t extension_id) {
179   return extension_id >= -1 && extension_id < 15;
180 }
181 
ValidateInputFilenameNotEmpty(const std::string & string)182 bool ValidateInputFilenameNotEmpty(const std::string& string) {
183   return !string.empty();
184 }
185 }  // namespace
186 
187 namespace webrtc {
188 namespace {
189 
190 const uint32_t kReceiverLocalSsrc = 0x123456;
191 
192 class NullRenderer : public rtc::VideoSinkInterface<VideoFrame> {
193  public:
OnFrame(const VideoFrame & frame)194   void OnFrame(const VideoFrame& frame) override {}
195 };
196 
197 class FileRenderPassthrough : public rtc::VideoSinkInterface<VideoFrame> {
198  public:
FileRenderPassthrough(const std::string & basename,rtc::VideoSinkInterface<VideoFrame> * renderer)199   FileRenderPassthrough(const std::string& basename,
200                         rtc::VideoSinkInterface<VideoFrame>* renderer)
201       : basename_(basename), renderer_(renderer), file_(nullptr), count_(0) {}
202 
~FileRenderPassthrough()203   ~FileRenderPassthrough() override {
204     if (file_)
205       fclose(file_);
206   }
207 
208  private:
OnFrame(const VideoFrame & video_frame)209   void OnFrame(const VideoFrame& video_frame) override {
210     if (renderer_)
211       renderer_->OnFrame(video_frame);
212 
213     if (basename_.empty())
214       return;
215 
216     std::stringstream filename;
217     filename << basename_ << count_++ << "_" << video_frame.timestamp()
218              << ".jpg";
219 
220     test::JpegFrameWriter frame_writer(filename.str());
221     RTC_CHECK(frame_writer.WriteFrame(video_frame, 100));
222   }
223 
224   const std::string basename_;
225   rtc::VideoSinkInterface<VideoFrame>* const renderer_;
226   FILE* file_;
227   size_t count_;
228 };
229 
230 class DecoderBitstreamFileWriter : public test::FakeDecoder {
231  public:
DecoderBitstreamFileWriter(const char * filename)232   explicit DecoderBitstreamFileWriter(const char* filename)
233       : file_(fopen(filename, "wb")) {
234     RTC_DCHECK(file_);
235   }
~DecoderBitstreamFileWriter()236   ~DecoderBitstreamFileWriter() override { fclose(file_); }
237 
Decode(const EncodedImage & encoded_frame,bool,int64_t)238   int32_t Decode(const EncodedImage& encoded_frame,
239                  bool /* missing_frames */,
240                  int64_t /* render_time_ms */) override {
241     if (fwrite(encoded_frame.data(), 1, encoded_frame.size(), file_) <
242         encoded_frame.size()) {
243       RTC_LOG_ERR(LS_ERROR) << "fwrite of encoded frame failed.";
244       return WEBRTC_VIDEO_CODEC_ERROR;
245     }
246     return WEBRTC_VIDEO_CODEC_OK;
247   }
248 
249  private:
250   FILE* file_;
251 };
252 
253 class DecoderIvfFileWriter : public test::FakeDecoder {
254  public:
DecoderIvfFileWriter(const char * filename,const std::string & codec)255   explicit DecoderIvfFileWriter(const char* filename, const std::string& codec)
256       : file_writer_(
257             IvfFileWriter::Wrap(FileWrapper::OpenWriteOnly(filename), 0)) {
258     RTC_DCHECK(file_writer_.get());
259     if (codec == "VP8") {
260       video_codec_type_ = VideoCodecType::kVideoCodecVP8;
261     } else if (codec == "VP9") {
262       video_codec_type_ = VideoCodecType::kVideoCodecVP9;
263     } else if (codec == "H264") {
264       video_codec_type_ = VideoCodecType::kVideoCodecH264;
265     } else if (codec == "AV1") {
266       video_codec_type_ = VideoCodecType::kVideoCodecAV1;
267     } else {
268       RTC_LOG(LS_ERROR) << "Unsupported video codec " << codec;
269       RTC_DCHECK_NOTREACHED();
270     }
271   }
~DecoderIvfFileWriter()272   ~DecoderIvfFileWriter() override { file_writer_->Close(); }
273 
Decode(const EncodedImage & encoded_frame,bool,int64_t render_time_ms)274   int32_t Decode(const EncodedImage& encoded_frame,
275                  bool /* missing_frames */,
276                  int64_t render_time_ms) override {
277     if (!file_writer_->WriteFrame(encoded_frame, video_codec_type_)) {
278       return WEBRTC_VIDEO_CODEC_ERROR;
279     }
280     return WEBRTC_VIDEO_CODEC_OK;
281   }
282 
283  private:
284   std::unique_ptr<IvfFileWriter> file_writer_;
285   VideoCodecType video_codec_type_;
286 };
287 
288 // Holds all the shared memory structures required for a receive stream. This
289 // structure is used to prevent members being deallocated before the replay
290 // has been finished.
291 struct StreamState {
292   test::NullTransport transport;
293   std::vector<std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>>> sinks;
294   std::vector<VideoReceiveStreamInterface*> receive_streams;
295   std::vector<FlexfecReceiveStream*> flexfec_streams;
296   std::unique_ptr<VideoDecoderFactory> decoder_factory;
297 };
298 
299 // Loads multiple configurations from the provided configuration file.
ConfigureFromFile(const std::string & config_path,Call * call)300 std::unique_ptr<StreamState> ConfigureFromFile(const std::string& config_path,
301                                                Call* call) {
302   auto stream_state = std::make_unique<StreamState>();
303   // Parse the configuration file.
304   std::ifstream config_file(config_path);
305   std::stringstream raw_json_buffer;
306   raw_json_buffer << config_file.rdbuf();
307   std::string raw_json = raw_json_buffer.str();
308   Json::CharReaderBuilder builder;
309   Json::Value json_configs;
310   std::string error_message;
311   std::unique_ptr<Json::CharReader> json_reader(builder.newCharReader());
312   if (!json_reader->parse(raw_json.data(), raw_json.data() + raw_json.size(),
313                           &json_configs, &error_message)) {
314     fprintf(stderr, "Error parsing JSON config\n");
315     fprintf(stderr, "%s\n", error_message.c_str());
316     return nullptr;
317   }
318 
319   if (absl::GetFlag(FLAGS_disable_decoding)) {
320     stream_state->decoder_factory =
321         std::make_unique<test::FunctionVideoDecoderFactory>(
322             []() { return std::make_unique<test::FakeDecoder>(); });
323   } else {
324     stream_state->decoder_factory = std::make_unique<InternalDecoderFactory>();
325   }
326   size_t config_count = 0;
327   for (const auto& json : json_configs) {
328     // Create the configuration and parse the JSON into the config.
329     auto receive_config =
330         ParseVideoReceiveStreamJsonConfig(&(stream_state->transport), json);
331     // Instantiate the underlying decoder.
332     for (auto& decoder : receive_config.decoders) {
333       decoder = test::CreateMatchingDecoder(decoder.payload_type,
334                                             decoder.video_format.name);
335     }
336     // Create a window for this config.
337     std::stringstream window_title;
338     window_title << "Playback Video (" << config_count++ << ")";
339     if (absl::GetFlag(FLAGS_disable_preview)) {
340       stream_state->sinks.emplace_back(std::make_unique<NullRenderer>());
341     } else {
342       stream_state->sinks.emplace_back(test::VideoRenderer::Create(
343           window_title.str().c_str(), absl::GetFlag(FLAGS_render_width),
344           absl::GetFlag(FLAGS_render_height)));
345     }
346     // Create a receive stream for this config.
347     receive_config.renderer = stream_state->sinks.back().get();
348     receive_config.decoder_factory = stream_state->decoder_factory.get();
349     stream_state->receive_streams.emplace_back(
350         call->CreateVideoReceiveStream(std::move(receive_config)));
351   }
352   return stream_state;
353 }
354 
355 // Loads the base configuration from flags passed in on the commandline.
ConfigureFromFlags(const std::string & rtp_dump_path,Call * call)356 std::unique_ptr<StreamState> ConfigureFromFlags(
357     const std::string& rtp_dump_path,
358     Call* call) {
359   auto stream_state = std::make_unique<StreamState>();
360   // Create the video renderers. We must add both to the stream state to keep
361   // them from deallocating.
362   std::stringstream window_title;
363   window_title << "Playback Video (" << rtp_dump_path << ")";
364   std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>> playback_video;
365   if (absl::GetFlag(FLAGS_disable_preview)) {
366     playback_video = std::make_unique<NullRenderer>();
367   } else {
368     playback_video.reset(test::VideoRenderer::Create(
369         window_title.str().c_str(), absl::GetFlag(FLAGS_render_width),
370         absl::GetFlag(FLAGS_render_height)));
371   }
372   auto file_passthrough = std::make_unique<FileRenderPassthrough>(
373       absl::GetFlag(FLAGS_out_base), playback_video.get());
374   stream_state->sinks.push_back(std::move(playback_video));
375   stream_state->sinks.push_back(std::move(file_passthrough));
376   // Setup the configuration from the flags.
377   VideoReceiveStreamInterface::Config receive_config(
378       &(stream_state->transport));
379   receive_config.rtp.remote_ssrc = absl::GetFlag(FLAGS_ssrc);
380   receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
381   receive_config.rtp.rtx_ssrc = absl::GetFlag(FLAGS_ssrc_rtx);
382   receive_config.rtp.rtx_associated_payload_types[absl::GetFlag(
383       FLAGS_media_payload_type_rtx)] = absl::GetFlag(FLAGS_media_payload_type);
384   receive_config.rtp
385       .rtx_associated_payload_types[absl::GetFlag(FLAGS_red_payload_type_rtx)] =
386       absl::GetFlag(FLAGS_red_payload_type);
387   receive_config.rtp.ulpfec_payload_type =
388       absl::GetFlag(FLAGS_ulpfec_payload_type);
389   receive_config.rtp.red_payload_type = absl::GetFlag(FLAGS_red_payload_type);
390   receive_config.rtp.nack.rtp_history_ms = 1000;
391 
392   if (absl::GetFlag(FLAGS_flexfec_payload_type) != -1) {
393     receive_config.rtp.protected_by_flexfec = true;
394     FlexfecReceiveStream::Config flexfec_config(&(stream_state->transport));
395     flexfec_config.payload_type = absl::GetFlag(FLAGS_flexfec_payload_type);
396     flexfec_config.protected_media_ssrcs.push_back(absl::GetFlag(FLAGS_ssrc));
397     flexfec_config.rtp.remote_ssrc = absl::GetFlag(FLAGS_ssrc_flexfec);
398     FlexfecReceiveStream* flexfec_stream =
399         call->CreateFlexfecReceiveStream(flexfec_config);
400     receive_config.rtp.packet_sink_ = flexfec_stream;
401     stream_state->flexfec_streams.push_back(flexfec_stream);
402   }
403 
404   if (absl::GetFlag(FLAGS_transmission_offset_id) != -1) {
405     receive_config.rtp.extensions.push_back(
406         RtpExtension(RtpExtension::kTimestampOffsetUri,
407                      absl::GetFlag(FLAGS_transmission_offset_id)));
408   }
409   if (absl::GetFlag(FLAGS_abs_send_time_id) != -1) {
410     receive_config.rtp.extensions.push_back(RtpExtension(
411         RtpExtension::kAbsSendTimeUri, absl::GetFlag(FLAGS_abs_send_time_id)));
412   }
413   receive_config.renderer = stream_state->sinks.back().get();
414 
415   // Setup the receiving stream
416   VideoReceiveStreamInterface::Decoder decoder;
417   decoder = test::CreateMatchingDecoder(absl::GetFlag(FLAGS_media_payload_type),
418                                         absl::GetFlag(FLAGS_codec));
419   if (!absl::GetFlag(FLAGS_decoder_bitstream_filename).empty()) {
420     // Replace decoder with file writer if we're writing the bitstream to a
421     // file instead.
422     stream_state->decoder_factory =
423         std::make_unique<test::FunctionVideoDecoderFactory>([]() {
424           return std::make_unique<DecoderBitstreamFileWriter>(
425               absl::GetFlag(FLAGS_decoder_bitstream_filename).c_str());
426         });
427   } else if (!absl::GetFlag(FLAGS_decoder_ivf_filename).empty()) {
428     // Replace decoder with file writer if we're writing the ivf to a
429     // file instead.
430     stream_state->decoder_factory =
431         std::make_unique<test::FunctionVideoDecoderFactory>([]() {
432           return std::make_unique<DecoderIvfFileWriter>(
433               absl::GetFlag(FLAGS_decoder_ivf_filename).c_str(),
434               absl::GetFlag(FLAGS_codec));
435         });
436   } else if (absl::GetFlag(FLAGS_disable_decoding)) {
437     stream_state->decoder_factory =
438         std::make_unique<test::FunctionVideoDecoderFactory>(
439             []() { return std::make_unique<test::FakeDecoder>(); });
440   } else {
441     stream_state->decoder_factory = std::make_unique<InternalDecoderFactory>();
442   }
443   receive_config.decoder_factory = stream_state->decoder_factory.get();
444   receive_config.decoders.push_back(decoder);
445 
446   stream_state->receive_streams.emplace_back(
447       call->CreateVideoReceiveStream(std::move(receive_config)));
448   return stream_state;
449 }
450 
CreateRtpReader(const std::string & rtp_dump_path)451 std::unique_ptr<test::RtpFileReader> CreateRtpReader(
452     const std::string& rtp_dump_path) {
453   std::unique_ptr<test::RtpFileReader> rtp_reader(test::RtpFileReader::Create(
454       test::RtpFileReader::kRtpDump, rtp_dump_path));
455   if (!rtp_reader) {
456     rtp_reader.reset(
457         test::RtpFileReader::Create(test::RtpFileReader::kPcap, rtp_dump_path));
458     if (!rtp_reader) {
459       fprintf(stderr,
460               "Couldn't open input file as either a rtpdump or .pcap. Note "
461               "that .pcapng is not supported.\nTrying to interpret the file as "
462               "length/packet interleaved.\n");
463       rtp_reader.reset(test::RtpFileReader::Create(
464           test::RtpFileReader::kLengthPacketInterleaved, rtp_dump_path));
465       if (!rtp_reader) {
466         fprintf(stderr,
467                 "Unable to open input file with any supported format\n");
468         return nullptr;
469       }
470     }
471   }
472   return rtp_reader;
473 }
474 
475 // The RtpReplayer is responsible for parsing the configuration provided by
476 // the user, setting up the windows, receive streams and decoders and then
477 // replaying the provided RTP dump.
478 class RtpReplayer final {
479  public:
RtpReplayer(absl::string_view replay_config_path,absl::string_view rtp_dump_path,std::unique_ptr<FieldTrialsView> field_trials,bool simulated_time)480   RtpReplayer(absl::string_view replay_config_path,
481               absl::string_view rtp_dump_path,
482               std::unique_ptr<FieldTrialsView> field_trials,
483               bool simulated_time)
484       : replay_config_path_(replay_config_path),
485         rtp_dump_path_(rtp_dump_path),
486         field_trials_(std::move(field_trials)),
487         rtp_reader_(CreateRtpReader(rtp_dump_path_)) {
488     TaskQueueFactory* task_queue_factory;
489     if (simulated_time) {
490       time_sim_ = std::make_unique<GlobalSimulatedTimeController>(
491           Timestamp::Millis(1 << 30));
492       task_queue_factory = time_sim_->GetTaskQueueFactory();
493     } else {
494       task_queue_factory_ = CreateDefaultTaskQueueFactory(field_trials_.get()),
495       task_queue_factory = task_queue_factory_.get();
496     }
497     worker_thread_ =
498         std::make_unique<rtc::TaskQueue>(task_queue_factory->CreateTaskQueue(
499             "worker_thread", TaskQueueFactory::Priority::NORMAL));
500     rtc::Event event;
501     worker_thread_->PostTask([&]() {
502       Call::Config call_config(&event_log_);
503       call_config.trials = field_trials_.get();
504       call_config.task_queue_factory = task_queue_factory;
505       call_.reset(Call::Create(call_config));
506 
507       // Creation of the streams must happen inside a task queue because it is
508       // resued as a worker thread.
509       if (replay_config_path_.empty()) {
510         stream_state_ = ConfigureFromFlags(rtp_dump_path_, call_.get());
511       } else {
512         stream_state_ = ConfigureFromFile(replay_config_path_, call_.get());
513       }
514       event.Set();
515     });
516     event.Wait(/*give_up_after=*/TimeDelta::Seconds(10));
517 
518     RTC_CHECK(stream_state_);
519     RTC_CHECK(rtp_reader_);
520   }
521 
~RtpReplayer()522   ~RtpReplayer() {
523     // Destruction of streams and the call must happen on the same thread as
524     // their creation.
525     rtc::Event event;
526     worker_thread_->PostTask([&]() {
527       for (const auto& receive_stream : stream_state_->receive_streams) {
528         call_->DestroyVideoReceiveStream(receive_stream);
529       }
530       for (const auto& flexfec_stream : stream_state_->flexfec_streams) {
531         call_->DestroyFlexfecReceiveStream(flexfec_stream);
532       }
533       call_.reset();
534       event.Set();
535     });
536     event.Wait(/*give_up_after=*/TimeDelta::Seconds(10));
537   }
538 
Run()539   void Run() {
540     rtc::Event event;
541     worker_thread_->PostTask([&]() {
542       // Start replaying the provided stream now that it has been configured.
543       // VideoReceiveStreams must be started on the same thread as they were
544       // created on.
545       for (const auto& receive_stream : stream_state_->receive_streams) {
546         receive_stream->Start();
547       }
548       event.Set();
549     });
550     event.Wait(/*give_up_after=*/TimeDelta::Seconds(10));
551 
552     ReplayPackets();
553   }
554 
555  private:
ReplayPackets()556   void ReplayPackets() {
557     int64_t replay_start_ms = -1;
558     int num_packets = 0;
559     std::map<uint32_t, int> unknown_packets;
560     rtc::Event event(/*manual_reset=*/false, /*initially_signalled=*/false);
561     uint32_t start_timestamp = absl::GetFlag(FLAGS_start_timestamp);
562     uint32_t stop_timestamp = absl::GetFlag(FLAGS_stop_timestamp);
563     while (true) {
564       int64_t now_ms = CurrentTimeMs();
565       if (replay_start_ms == -1) {
566         replay_start_ms = now_ms;
567       }
568 
569       test::RtpPacket packet;
570       if (!rtp_reader_->NextPacket(&packet)) {
571         break;
572       }
573       rtc::CopyOnWriteBuffer packet_buffer(packet.data, packet.length);
574       RtpPacket header;
575       header.Parse(packet_buffer);
576       if (header.Timestamp() < start_timestamp ||
577           header.Timestamp() > stop_timestamp) {
578         continue;
579       }
580 
581       int64_t deliver_in_ms = replay_start_ms + packet.time_ms - now_ms;
582       SleepOrAdvanceTime(deliver_in_ms);
583 
584       ++num_packets;
585       PacketReceiver::DeliveryStatus result = PacketReceiver::DELIVERY_OK;
586       worker_thread_->PostTask([&]() {
587         MediaType media_type =
588             IsRtcpPacket(packet_buffer) ? MediaType::ANY : MediaType::VIDEO;
589         result = call_->Receiver()->DeliverPacket(media_type,
590                                                   std::move(packet_buffer),
591                                                   /* packet_time_us */ -1);
592         event.Set();
593       });
594       event.Wait(/*give_up_after=*/TimeDelta::Seconds(10));
595 
596       switch (result) {
597         case PacketReceiver::DELIVERY_OK:
598           break;
599         case PacketReceiver::DELIVERY_UNKNOWN_SSRC: {
600           if (unknown_packets[header.Ssrc()] == 0)
601             fprintf(stderr, "Unknown SSRC: %u!\n", header.Ssrc());
602           ++unknown_packets[header.Ssrc()];
603           break;
604         }
605         case PacketReceiver::DELIVERY_PACKET_ERROR: {
606           fprintf(stderr,
607                   "Packet error, corrupt packets or incorrect setup?\n");
608           fprintf(stderr, "Packet len=%zu pt=%u seq=%u ts=%u ssrc=0x%8x\n",
609                   packet.length, header.PayloadType(), header.SequenceNumber(),
610                   header.Timestamp(), header.Ssrc());
611           break;
612         }
613       }
614     }
615     // Note that even when `extend_run_time_duration` is zero
616     // `SleepOrAdvanceTime` should still be called in order to process the last
617     // delivered packet when running in simulated time.
618     SleepOrAdvanceTime(absl::GetFlag(FLAGS_extend_run_time_duration) * 1000);
619 
620     fprintf(stderr, "num_packets: %d\n", num_packets);
621 
622     for (std::map<uint32_t, int>::const_iterator it = unknown_packets.begin();
623          it != unknown_packets.end(); ++it) {
624       fprintf(stderr, "Packets for unknown ssrc '%u': %d\n", it->first,
625               it->second);
626     }
627   }
628 
CurrentTimeMs()629   int64_t CurrentTimeMs() {
630     return time_sim_ ? time_sim_->GetClock()->TimeInMilliseconds()
631                      : rtc::TimeMillis();
632   }
633 
SleepOrAdvanceTime(int64_t duration_ms)634   void SleepOrAdvanceTime(int64_t duration_ms) {
635     if (time_sim_) {
636       time_sim_->AdvanceTime(TimeDelta::Millis(duration_ms));
637     } else if (duration_ms > 0) {
638       SleepMs(duration_ms);
639     }
640   }
641 
642   const std::string replay_config_path_;
643   const std::string rtp_dump_path_;
644   RtcEventLogNull event_log_;
645   std::unique_ptr<FieldTrialsView> field_trials_;
646   std::unique_ptr<GlobalSimulatedTimeController> time_sim_;
647   std::unique_ptr<TaskQueueFactory> task_queue_factory_;
648   std::unique_ptr<rtc::TaskQueue> worker_thread_;
649   std::unique_ptr<Call> call_;
650   std::unique_ptr<test::RtpFileReader> rtp_reader_;
651   std::unique_ptr<StreamState> stream_state_;
652 };
653 
RtpReplay()654 void RtpReplay() {
655   RtpReplayer replayer(
656       absl::GetFlag(FLAGS_config_file), absl::GetFlag(FLAGS_input_file),
657       std::make_unique<FieldTrials>(absl::GetFlag(FLAGS_force_fieldtrials)),
658       absl::GetFlag(FLAGS_simulated_time));
659   replayer.Run();
660 }
661 
662 }  // namespace
663 }  // namespace webrtc
664 
main(int argc,char * argv[])665 int main(int argc, char* argv[]) {
666   ::testing::InitGoogleTest(&argc, argv);
667   absl::ParseCommandLine(argc, argv);
668 
669   RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_media_payload_type)));
670   RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_media_payload_type_rtx)));
671   RTC_CHECK(ValidateOptionalPayloadType(absl::GetFlag(FLAGS_red_payload_type)));
672   RTC_CHECK(
673       ValidateOptionalPayloadType(absl::GetFlag(FLAGS_red_payload_type_rtx)));
674   RTC_CHECK(
675       ValidateOptionalPayloadType(absl::GetFlag(FLAGS_ulpfec_payload_type)));
676   RTC_CHECK(
677       ValidateOptionalPayloadType(absl::GetFlag(FLAGS_flexfec_payload_type)));
678   RTC_CHECK(
679       ValidateRtpHeaderExtensionId(absl::GetFlag(FLAGS_abs_send_time_id)));
680   RTC_CHECK(ValidateRtpHeaderExtensionId(
681       absl::GetFlag(FLAGS_transmission_offset_id)));
682   RTC_CHECK(ValidateInputFilenameNotEmpty(absl::GetFlag(FLAGS_input_file)));
683   RTC_CHECK_GE(absl::GetFlag(FLAGS_extend_run_time_duration), 0);
684 
685   rtc::ThreadManager::Instance()->WrapCurrentThread();
686   webrtc::test::RunTest(webrtc::RtpReplay);
687   return 0;
688 }
689