xref: /aosp_15_r20/external/webrtc/test/testsupport/fixed_fps_video_frame_writer_adapter.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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