/* * 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 #include #include #include #include #include #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> 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 frame; rtc::scoped_refptr thumb; int repeat_count = 0; }; using DecodedFrame = rtc::RefCountedObject; struct CapturedFrame { int id; Timestamp capture_time = Timestamp::PlusInfinity(); rtc::scoped_refptr frame; rtc::scoped_refptr thumb; double best_score = INFINITY; rtc::scoped_refptr best_decode; bool matched = false; }; struct VideoLayer { int layer_id; std::deque captured_frames; rtc::scoped_refptr last_decode; int next_decoded_id = 1; }; void HandleMatch(CapturedFrame captured, int layer_id); void Finalize(); int next_capture_id_ = 1; std::vector> frame_pair_handlers_; std::map layers_; TaskQueueForTest task_queue_; }; class CapturedFrameTap : public rtc::VideoSinkInterface { 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, public rtc::VideoSourceInterface { public: ForwardingCapturedFrameTap(Clock* clock, VideoFrameMatcher* matcher, rtc::VideoSourceInterface* source); ForwardingCapturedFrameTap(ForwardingCapturedFrameTap&) = delete; ForwardingCapturedFrameTap& operator=(ForwardingCapturedFrameTap&) = delete; // VideoSinkInterface interface void OnFrame(const VideoFrame& frame) override; void OnDiscardedFrame() override; // VideoSourceInterface interface void AddOrUpdateSink(VideoSinkInterface* sink, const rtc::VideoSinkWants& wants) override; void RemoveSink(VideoSinkInterface* sink) override; private: Clock* const clock_; VideoFrameMatcher* const matcher_; rtc::VideoSourceInterface* const source_; VideoSinkInterface* sink_ = nullptr; int discarded_count_ = 0; }; class DecodedFrameTap : public rtc::VideoSinkInterface { 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_