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 11 #ifndef TEST_TESTSUPPORT_FIXED_FPS_VIDEO_FRAME_WRITER_ADAPTER_H_ 12 #define TEST_TESTSUPPORT_FIXED_FPS_VIDEO_FRAME_WRITER_ADAPTER_H_ 13 14 #include <memory> 15 16 #include "absl/types/optional.h" 17 #include "api/test/video/video_frame_writer.h" 18 #include "api/video/video_sink_interface.h" 19 #include "system_wrappers/include/clock.h" 20 #include "test/testsupport/video_frame_writer.h" 21 22 namespace webrtc { 23 namespace test { 24 25 // Writes video to the specified video writer with specified fixed frame rate. 26 // If at the point in time X no new frames are passed to the writer, the 27 // previous frame is used to fill the gap and preserve frame rate. 28 // 29 // This adaptor uses next algorithm: 30 // There are output "slots" at a fixed frame rate (starting at the time of the 31 // first received frame). Each incoming frame is assigned to the closest output 32 // slot. Then empty slots are filled by repeating the closest filled slot before 33 // empty one. If there are multiple frames closest to the same slot, the latest 34 // received one is used. 35 // 36 // The frames are outputted for the whole duration of the class life after the 37 // first frame was written or until it will be closed. 38 // 39 // For example if frames from A to F were received, then next output sequence 40 // will be generated: 41 // Received frames: A B C D EF Destructor called 42 // | | | | || | 43 // v v v v vv v 44 // X----X----X----X----X----X----X----X----X----+----+-- 45 // | | | | | | | | | 46 // Produced frames: A A A B C C F F F 47 // 48 // This class is not thread safe. 49 class FixedFpsVideoFrameWriterAdapter : public VideoFrameWriter { 50 public: 51 FixedFpsVideoFrameWriterAdapter(int fps, 52 Clock* clock, 53 std::unique_ptr<VideoFrameWriter> delegate); 54 ~FixedFpsVideoFrameWriterAdapter() override; 55 56 bool WriteFrame(const webrtc::VideoFrame& frame) override; 57 58 // Closes adapter and underlying delegate. User mustn't call to the WriteFrame 59 // after calling this method. 60 void Close() override; 61 62 private: 63 // Writes `last_frame_` for each "slot" from `last_frame_time_` up to now 64 // excluding the last one. 65 // Updates `last_frame_time_` to the position of the last NOT WRITTEN frame. 66 // Returns true if all writes were successful, otherwise retuns false. In such 67 // case it is not guranteed how many frames were actually written. 68 bool WriteMissedSlotsExceptLast(Timestamp now); 69 Timestamp Now() const; 70 71 // Because `TimeDelta` stores time with microseconds precision 72 // `last_frame_time_` may have a small drift and for very long streams it 73 // must be updated to use double for time. 74 const TimeDelta inter_frame_interval_; 75 Clock* const clock_; 76 std::unique_ptr<VideoFrameWriter> delegate_; 77 bool is_closed_ = false; 78 79 // Expected time slot for the last frame. 80 Timestamp last_frame_time_ = Timestamp::MinusInfinity(); 81 absl::optional<VideoFrame> last_frame_ = absl::nullopt; 82 }; 83 84 } // namespace test 85 } // namespace webrtc 86 87 #endif // TEST_TESTSUPPORT_FIXED_FPS_VIDEO_FRAME_WRITER_ADAPTER_H_ 88