summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/video/video_analyzer.h
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/video/video_analyzer.h')
-rw-r--r--third_party/libwebrtc/video/video_analyzer.h322
1 files changed, 322 insertions, 0 deletions
diff --git a/third_party/libwebrtc/video/video_analyzer.h b/third_party/libwebrtc/video/video_analyzer.h
new file mode 100644
index 0000000000..448af7ebb7
--- /dev/null
+++ b/third_party/libwebrtc/video/video_analyzer.h
@@ -0,0 +1,322 @@
+/*
+ * 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 VIDEO_VIDEO_ANALYZER_H_
+#define VIDEO_VIDEO_ANALYZER_H_
+
+#include <deque>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/numerics/samples_stats_counter.h"
+#include "api/task_queue/task_queue_base.h"
+#include "api/test/metrics/metric.h"
+#include "api/video/video_source_interface.h"
+#include "modules/rtp_rtcp/source/rtp_packet.h"
+#include "modules/rtp_rtcp/source/video_rtp_depacketizer.h"
+#include "rtc_base/event.h"
+#include "rtc_base/numerics/running_statistics.h"
+#include "rtc_base/numerics/sequence_number_unwrapper.h"
+#include "rtc_base/platform_thread.h"
+#include "rtc_base/synchronization/mutex.h"
+#include "test/layer_filtering_transport.h"
+#include "test/rtp_file_writer.h"
+
+namespace webrtc {
+
+class VideoAnalyzer : public PacketReceiver,
+ public Transport,
+ public rtc::VideoSinkInterface<VideoFrame> {
+ public:
+ VideoAnalyzer(test::LayerFilteringTransport* transport,
+ const std::string& test_label,
+ double avg_psnr_threshold,
+ double avg_ssim_threshold,
+ int duration_frames,
+ TimeDelta test_duration,
+ FILE* graph_data_output_file,
+ const std::string& graph_title,
+ uint32_t ssrc_to_analyze,
+ uint32_t rtx_ssrc_to_analyze,
+ size_t selected_stream,
+ int selected_sl,
+ int selected_tl,
+ bool is_quick_test_enabled,
+ Clock* clock,
+ std::string rtp_dump_name,
+ TaskQueueBase* task_queue);
+ ~VideoAnalyzer();
+
+ virtual void SetReceiver(PacketReceiver* receiver);
+ void SetSource(rtc::VideoSourceInterface<VideoFrame>* video_source,
+ bool respect_sink_wants);
+ void SetCall(Call* call);
+ void SetSendStream(VideoSendStream* stream);
+ void SetReceiveStream(VideoReceiveStreamInterface* stream);
+ void SetAudioReceiveStream(AudioReceiveStreamInterface* recv_stream);
+
+ rtc::VideoSinkInterface<VideoFrame>* InputInterface();
+ rtc::VideoSourceInterface<VideoFrame>* OutputInterface();
+
+ void DeliverRtcpPacket(rtc::CopyOnWriteBuffer packet) override;
+ void DeliverRtpPacket(MediaType media_type,
+ RtpPacketReceived packet,
+ PacketReceiver::OnUndemuxablePacketHandler
+ undemuxable_packet_handler) override;
+
+ void PreEncodeOnFrame(const VideoFrame& video_frame);
+ void PostEncodeOnFrame(size_t stream_id, uint32_t timestamp);
+
+ bool SendRtp(const uint8_t* packet,
+ size_t length,
+ const PacketOptions& options) override;
+
+ bool SendRtcp(const uint8_t* packet, size_t length) override;
+ void OnFrame(const VideoFrame& video_frame) override;
+ void Wait();
+
+ void StartMeasuringCpuProcessTime();
+ void StopMeasuringCpuProcessTime();
+ void StartExcludingCpuThreadTime() RTC_LOCKS_EXCLUDED(cpu_measurement_lock_);
+ void StopExcludingCpuThreadTime() RTC_LOCKS_EXCLUDED(cpu_measurement_lock_);
+ double GetCpuUsagePercent() RTC_LOCKS_EXCLUDED(cpu_measurement_lock_);
+
+ test::LayerFilteringTransport* const transport_;
+ PacketReceiver* receiver_;
+
+ private:
+ struct FrameComparison {
+ FrameComparison();
+ FrameComparison(const VideoFrame& reference,
+ const VideoFrame& render,
+ bool dropped,
+ int64_t input_time_ms,
+ int64_t send_time_ms,
+ int64_t recv_time_ms,
+ int64_t render_time_ms,
+ size_t encoded_frame_size);
+ FrameComparison(bool dropped,
+ int64_t input_time_ms,
+ int64_t send_time_ms,
+ int64_t recv_time_ms,
+ int64_t render_time_ms,
+ size_t encoded_frame_size);
+
+ absl::optional<VideoFrame> reference;
+ absl::optional<VideoFrame> render;
+ bool dropped;
+ int64_t input_time_ms;
+ int64_t send_time_ms;
+ int64_t recv_time_ms;
+ int64_t render_time_ms;
+ size_t encoded_frame_size;
+ };
+
+ struct Sample {
+ Sample(int dropped,
+ int64_t input_time_ms,
+ int64_t send_time_ms,
+ int64_t recv_time_ms,
+ int64_t render_time_ms,
+ size_t encoded_frame_size,
+ double psnr,
+ double ssim);
+
+ int dropped;
+ int64_t input_time_ms;
+ int64_t send_time_ms;
+ int64_t recv_time_ms;
+ int64_t render_time_ms;
+ size_t encoded_frame_size;
+ double psnr;
+ double ssim;
+ };
+
+ // Implements VideoSinkInterface to receive captured frames from a
+ // FrameGeneratorCapturer. Implements VideoSourceInterface to be able to act
+ // as a source to VideoSendStream.
+ // It forwards all input frames to the VideoAnalyzer for later comparison and
+ // forwards the captured frames to the VideoSendStream.
+ class CapturedFrameForwarder : public rtc::VideoSinkInterface<VideoFrame>,
+ public rtc::VideoSourceInterface<VideoFrame> {
+ public:
+ CapturedFrameForwarder(VideoAnalyzer* analyzer,
+ Clock* clock,
+ int frames_to_capture,
+ TimeDelta test_duration);
+ void SetSource(rtc::VideoSourceInterface<VideoFrame>* video_source);
+
+ private:
+ void OnFrame(const VideoFrame& video_frame)
+ RTC_LOCKS_EXCLUDED(lock_) override;
+
+ // Called when `send_stream_.SetSource()` is called.
+ void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
+ const rtc::VideoSinkWants& wants)
+ RTC_LOCKS_EXCLUDED(lock_) override;
+
+ // Called by `send_stream_` when `send_stream_.SetSource()` is called.
+ void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink)
+ RTC_LOCKS_EXCLUDED(lock_) override;
+
+ VideoAnalyzer* const analyzer_;
+ Mutex lock_;
+ rtc::VideoSinkInterface<VideoFrame>* send_stream_input_
+ RTC_GUARDED_BY(lock_);
+ VideoSourceInterface<VideoFrame>* video_source_;
+ Clock* clock_;
+ int captured_frames_ RTC_GUARDED_BY(lock_);
+ const int frames_to_capture_;
+ const Timestamp test_end_;
+ };
+
+ struct FrameWithPsnr {
+ double psnr;
+ VideoFrame frame;
+ };
+
+ bool IsInSelectedSpatialAndTemporalLayer(const RtpPacket& rtp_packet);
+
+ void AddFrameComparison(const VideoFrame& reference,
+ const VideoFrame& render,
+ bool dropped,
+ int64_t render_time_ms)
+ RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_);
+
+ void PollStats() RTC_LOCKS_EXCLUDED(comparison_lock_);
+ static void FrameComparisonThread(void* obj);
+ bool CompareFrames();
+ bool PopComparison(FrameComparison* comparison);
+ // Increment counter for number of frames received for comparison.
+ void FrameRecorded() RTC_EXCLUSIVE_LOCKS_REQUIRED(comparison_lock_);
+ // Returns true if all frames to be compared have been taken from the queue.
+ bool AllFramesRecorded() RTC_LOCKS_EXCLUDED(comparison_lock_);
+ bool AllFramesRecordedLocked() RTC_EXCLUSIVE_LOCKS_REQUIRED(comparison_lock_);
+ // Increase count of number of frames processed. Returns true if this was the
+ // last frame to be processed.
+ bool FrameProcessed() RTC_LOCKS_EXCLUDED(comparison_lock_);
+ void PrintResults() RTC_LOCKS_EXCLUDED(lock_, comparison_lock_);
+ void PerformFrameComparison(const FrameComparison& comparison)
+ RTC_LOCKS_EXCLUDED(comparison_lock_);
+ void PrintResult(absl::string_view result_type,
+ const SamplesStatsCounter& stats,
+ webrtc::test::Unit unit,
+ webrtc::test::ImprovementDirection improvement_direction);
+ void PrintResultWithExternalMean(
+ absl::string_view result_type,
+ double mean,
+ const SamplesStatsCounter& stats,
+ webrtc::test::Unit unit,
+ webrtc::test::ImprovementDirection improvement_direction);
+ void PrintSamplesToFile(void) RTC_LOCKS_EXCLUDED(comparison_lock_);
+ void AddCapturedFrameForComparison(const VideoFrame& video_frame)
+ RTC_LOCKS_EXCLUDED(lock_, comparison_lock_);
+
+ Call* call_;
+ VideoSendStream* send_stream_;
+ VideoReceiveStreamInterface* receive_stream_;
+ AudioReceiveStreamInterface* audio_receive_stream_;
+ CapturedFrameForwarder captured_frame_forwarder_;
+ const std::string test_label_;
+ FILE* const graph_data_output_file_;
+ const std::string graph_title_;
+ const uint32_t ssrc_to_analyze_;
+ const uint32_t rtx_ssrc_to_analyze_;
+ const size_t selected_stream_;
+ const int selected_sl_;
+ const int selected_tl_;
+
+ Mutex comparison_lock_;
+ std::vector<Sample> samples_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter sender_time_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter receiver_time_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter network_time_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter psnr_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter ssim_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter end_to_end_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter rendered_delta_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter encoded_frame_size_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter encode_frame_rate_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter encode_time_ms_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter encode_usage_percent_ RTC_GUARDED_BY(comparison_lock_);
+ double mean_decode_time_ms_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter decode_time_ms_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter decode_time_max_ms_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter media_bitrate_bps_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter fec_bitrate_bps_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter send_bandwidth_bps_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter memory_usage_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter audio_expand_rate_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter audio_accelerate_rate_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter audio_jitter_buffer_ms_ RTC_GUARDED_BY(comparison_lock_);
+ SamplesStatsCounter pixels_ RTC_GUARDED_BY(comparison_lock_);
+ // Rendered frame with worst PSNR is saved for further analysis.
+ absl::optional<FrameWithPsnr> worst_frame_ RTC_GUARDED_BY(comparison_lock_);
+ // Freeze metrics.
+ SamplesStatsCounter time_between_freezes_ RTC_GUARDED_BY(comparison_lock_);
+ uint32_t freeze_count_ RTC_GUARDED_BY(comparison_lock_);
+ uint32_t total_freezes_duration_ms_ RTC_GUARDED_BY(comparison_lock_);
+ double total_inter_frame_delay_ RTC_GUARDED_BY(comparison_lock_);
+ double total_squared_inter_frame_delay_ RTC_GUARDED_BY(comparison_lock_);
+
+ double decode_frame_rate_ RTC_GUARDED_BY(comparison_lock_);
+ double render_frame_rate_ RTC_GUARDED_BY(comparison_lock_);
+
+ size_t last_fec_bytes_;
+
+ Mutex lock_ RTC_ACQUIRED_BEFORE(comparison_lock_)
+ RTC_ACQUIRED_BEFORE(cpu_measurement_lock_);
+ const int frames_to_process_;
+ const Timestamp test_end_;
+ int frames_recorded_ RTC_GUARDED_BY(comparison_lock_);
+ int frames_processed_ RTC_GUARDED_BY(comparison_lock_);
+ int captured_frames_ RTC_GUARDED_BY(comparison_lock_);
+ int dropped_frames_ RTC_GUARDED_BY(comparison_lock_);
+ int dropped_frames_before_first_encode_ RTC_GUARDED_BY(lock_);
+ int dropped_frames_before_rendering_ RTC_GUARDED_BY(lock_);
+ int64_t last_render_time_ RTC_GUARDED_BY(comparison_lock_);
+ int64_t last_render_delta_ms_ RTC_GUARDED_BY(comparison_lock_);
+ int64_t last_unfreeze_time_ms_ RTC_GUARDED_BY(comparison_lock_);
+ uint32_t rtp_timestamp_delta_ RTC_GUARDED_BY(lock_);
+
+ Mutex cpu_measurement_lock_;
+ int64_t cpu_time_ RTC_GUARDED_BY(cpu_measurement_lock_);
+ int64_t wallclock_time_ RTC_GUARDED_BY(cpu_measurement_lock_);
+
+ std::deque<VideoFrame> frames_ RTC_GUARDED_BY(lock_);
+ absl::optional<VideoFrame> last_rendered_frame_ RTC_GUARDED_BY(lock_);
+ RtpTimestampUnwrapper wrap_handler_ RTC_GUARDED_BY(lock_);
+ std::map<int64_t, int64_t> send_times_ RTC_GUARDED_BY(lock_);
+ std::map<int64_t, int64_t> recv_times_ RTC_GUARDED_BY(lock_);
+ std::map<int64_t, size_t> encoded_frame_sizes_ RTC_GUARDED_BY(lock_);
+ absl::optional<uint32_t> first_encoded_timestamp_ RTC_GUARDED_BY(lock_);
+ absl::optional<uint32_t> first_sent_timestamp_ RTC_GUARDED_BY(lock_);
+ const double avg_psnr_threshold_;
+ const double avg_ssim_threshold_;
+ bool is_quick_test_enabled_;
+
+ std::vector<rtc::PlatformThread> comparison_thread_pool_;
+ rtc::Event comparison_available_event_;
+ std::deque<FrameComparison> comparisons_ RTC_GUARDED_BY(comparison_lock_);
+ bool quit_ RTC_GUARDED_BY(comparison_lock_);
+ rtc::Event done_;
+
+ std::unique_ptr<VideoRtpDepacketizer> vp8_depacketizer_;
+ std::unique_ptr<VideoRtpDepacketizer> vp9_depacketizer_;
+ std::unique_ptr<test::RtpFileWriter> rtp_file_writer_;
+ Clock* const clock_;
+ const int64_t start_ms_;
+ TaskQueueBase* task_queue_;
+};
+
+} // namespace webrtc
+#endif // VIDEO_VIDEO_ANALYZER_H_