| /* |
| * Copyright 2018 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| #ifndef TEST_SCENARIO_VIDEO_FRAME_MATCHER_H_ |
| #define TEST_SCENARIO_VIDEO_FRAME_MATCHER_H_ |
| |
| #include <deque> |
| #include <map> |
| #include <memory> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "api/units/timestamp.h" |
| #include "api/video/video_frame.h" |
| #include "api/video/video_sink_interface.h" |
| #include "api/video/video_source_interface.h" |
| #include "rtc_base/ref_counted_object.h" |
| #include "rtc_base/task_queue_for_test.h" |
| #include "system_wrappers/include/clock.h" |
| #include "test/scenario/performance_stats.h" |
| |
| namespace webrtc { |
| namespace test { |
| |
| class VideoFrameMatcher { |
| public: |
| explicit VideoFrameMatcher( |
| std::vector<std::function<void(const VideoFramePair&)>> |
| frame_pair_handlers); |
| ~VideoFrameMatcher(); |
| void RegisterLayer(int layer_id); |
| void OnCapturedFrame(const VideoFrame& frame, Timestamp at_time); |
| void OnDecodedFrame(const VideoFrame& frame, |
| int layer_id, |
| Timestamp render_time, |
| Timestamp at_time); |
| bool Active() const; |
| |
| private: |
| struct DecodedFrameBase { |
| int id; |
| Timestamp decoded_time = Timestamp::PlusInfinity(); |
| Timestamp render_time = Timestamp::PlusInfinity(); |
| rtc::scoped_refptr<VideoFrameBuffer> frame; |
| rtc::scoped_refptr<VideoFrameBuffer> thumb; |
| int repeat_count = 0; |
| }; |
| using DecodedFrame = rtc::RefCountedObject<DecodedFrameBase>; |
| struct CapturedFrame { |
| int id; |
| Timestamp capture_time = Timestamp::PlusInfinity(); |
| rtc::scoped_refptr<VideoFrameBuffer> frame; |
| rtc::scoped_refptr<VideoFrameBuffer> thumb; |
| double best_score = INFINITY; |
| rtc::scoped_refptr<DecodedFrame> best_decode; |
| bool matched = false; |
| }; |
| struct VideoLayer { |
| int layer_id; |
| std::deque<CapturedFrame> captured_frames; |
| rtc::scoped_refptr<DecodedFrame> last_decode; |
| int next_decoded_id = 1; |
| }; |
| void HandleMatch(CapturedFrame captured, int layer_id); |
| void Finalize(); |
| int next_capture_id_ = 1; |
| std::vector<std::function<void(const VideoFramePair&)>> frame_pair_handlers_; |
| std::map<int, VideoLayer> layers_; |
| TaskQueueForTest task_queue_; |
| }; |
| |
| class CapturedFrameTap : public rtc::VideoSinkInterface<VideoFrame> { |
| public: |
| CapturedFrameTap(Clock* clock, VideoFrameMatcher* matcher); |
| CapturedFrameTap(CapturedFrameTap&) = delete; |
| CapturedFrameTap& operator=(CapturedFrameTap&) = delete; |
| |
| void OnFrame(const VideoFrame& frame) override; |
| void OnDiscardedFrame() override; |
| |
| private: |
| Clock* const clock_; |
| VideoFrameMatcher* const matcher_; |
| int discarded_count_ = 0; |
| }; |
| |
| class ForwardingCapturedFrameTap |
| : public rtc::VideoSinkInterface<VideoFrame>, |
| public rtc::VideoSourceInterface<VideoFrame> { |
| public: |
| ForwardingCapturedFrameTap(Clock* clock, |
| VideoFrameMatcher* matcher, |
| rtc::VideoSourceInterface<VideoFrame>* source); |
| ForwardingCapturedFrameTap(ForwardingCapturedFrameTap&) = delete; |
| ForwardingCapturedFrameTap& operator=(ForwardingCapturedFrameTap&) = delete; |
| |
| // VideoSinkInterface interface |
| void OnFrame(const VideoFrame& frame) override; |
| void OnDiscardedFrame() override; |
| |
| // VideoSourceInterface interface |
| void AddOrUpdateSink(VideoSinkInterface<VideoFrame>* sink, |
| const rtc::VideoSinkWants& wants) override; |
| void RemoveSink(VideoSinkInterface<VideoFrame>* sink) override; |
| |
| private: |
| Clock* const clock_; |
| VideoFrameMatcher* const matcher_; |
| rtc::VideoSourceInterface<VideoFrame>* const source_; |
| VideoSinkInterface<VideoFrame>* sink_ = nullptr; |
| int discarded_count_ = 0; |
| }; |
| |
| class DecodedFrameTap : public rtc::VideoSinkInterface<VideoFrame> { |
| public: |
| DecodedFrameTap(Clock* clock, VideoFrameMatcher* matcher, int layer_id); |
| // VideoSinkInterface interface |
| void OnFrame(const VideoFrame& frame) override; |
| |
| private: |
| Clock* const clock_; |
| VideoFrameMatcher* const matcher_; |
| int layer_id_; |
| }; |
| } // namespace test |
| } // namespace webrtc |
| #endif // TEST_SCENARIO_VIDEO_FRAME_MATCHER_H_ |