1 /* 2 * Copyright (c) 2022 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 #include "test/pc/e2e/analyzer/video/video_dumping.h" 11 12 #include <stdio.h> 13 14 #include <memory> 15 #include <string> 16 #include <utility> 17 #include <vector> 18 19 #include "absl/strings/string_view.h" 20 #include "api/test/video/video_frame_writer.h" 21 #include "api/video/video_frame.h" 22 #include "rtc_base/logging.h" 23 #include "system_wrappers/include/clock.h" 24 #include "test/testsupport/video_frame_writer.h" 25 26 namespace webrtc { 27 namespace webrtc_pc_e2e { 28 namespace { 29 30 class VideoFrameIdsWriter final : public test::VideoFrameWriter { 31 public: VideoFrameIdsWriter(absl::string_view file_name)32 explicit VideoFrameIdsWriter(absl::string_view file_name) 33 : file_name_(file_name) { 34 output_file_ = fopen(file_name_.c_str(), "wb"); 35 RTC_LOG(LS_INFO) << "Writing VideoFrame IDs into " << file_name_; 36 RTC_CHECK(output_file_ != nullptr) 37 << "Failed to open file to dump frame ids for writing: " << file_name_; 38 } ~VideoFrameIdsWriter()39 ~VideoFrameIdsWriter() override { Close(); } 40 WriteFrame(const VideoFrame & frame)41 bool WriteFrame(const VideoFrame& frame) override { 42 RTC_CHECK(output_file_ != nullptr) << "Writer is already closed"; 43 int chars_written = fprintf(output_file_, "%d\n", frame.id()); 44 if (chars_written < 2) { 45 RTC_LOG(LS_ERROR) << "Failed to write frame id to the output file: " 46 << file_name_; 47 return false; 48 } 49 return true; 50 } 51 Close()52 void Close() override { 53 if (output_file_ != nullptr) { 54 RTC_LOG(LS_INFO) << "Closing file for VideoFrame IDs: " << file_name_; 55 fclose(output_file_); 56 output_file_ = nullptr; 57 } 58 } 59 60 private: 61 const std::string file_name_; 62 FILE* output_file_; 63 }; 64 65 // Broadcast received frame to multiple underlying frame writers. 66 class BroadcastingFrameWriter final : public test::VideoFrameWriter { 67 public: BroadcastingFrameWriter(std::vector<std::unique_ptr<test::VideoFrameWriter>> delegates)68 explicit BroadcastingFrameWriter( 69 std::vector<std::unique_ptr<test::VideoFrameWriter>> delegates) 70 : delegates_(std::move(delegates)) {} ~BroadcastingFrameWriter()71 ~BroadcastingFrameWriter() override { Close(); } 72 WriteFrame(const webrtc::VideoFrame & frame)73 bool WriteFrame(const webrtc::VideoFrame& frame) override { 74 for (auto& delegate : delegates_) { 75 if (!delegate->WriteFrame(frame)) { 76 return false; 77 } 78 } 79 return true; 80 } 81 Close()82 void Close() override { 83 for (auto& delegate : delegates_) { 84 delegate->Close(); 85 } 86 } 87 88 private: 89 std::vector<std::unique_ptr<test::VideoFrameWriter>> delegates_; 90 }; 91 92 } // namespace 93 VideoWriter(test::VideoFrameWriter * video_writer,int sampling_modulo)94VideoWriter::VideoWriter(test::VideoFrameWriter* video_writer, 95 int sampling_modulo) 96 : video_writer_(video_writer), sampling_modulo_(sampling_modulo) {} 97 OnFrame(const VideoFrame & frame)98void VideoWriter::OnFrame(const VideoFrame& frame) { 99 if (frames_counter_++ % sampling_modulo_ != 0) { 100 return; 101 } 102 bool result = video_writer_->WriteFrame(frame); 103 RTC_CHECK(result) << "Failed to write frame"; 104 } 105 CreateVideoFrameWithIdsWriter(std::unique_ptr<test::VideoFrameWriter> video_writer_delegate,absl::string_view frame_ids_dump_file_name)106std::unique_ptr<test::VideoFrameWriter> CreateVideoFrameWithIdsWriter( 107 std::unique_ptr<test::VideoFrameWriter> video_writer_delegate, 108 absl::string_view frame_ids_dump_file_name) { 109 std::vector<std::unique_ptr<test::VideoFrameWriter>> requested_writers; 110 requested_writers.push_back(std::move(video_writer_delegate)); 111 requested_writers.push_back( 112 std::make_unique<VideoFrameIdsWriter>(frame_ids_dump_file_name)); 113 return std::make_unique<BroadcastingFrameWriter>( 114 std::move(requested_writers)); 115 } 116 117 } // namespace webrtc_pc_e2e 118 } // namespace webrtc 119