webrtc_m130/video/video_analyzer.h
Per Kjellander 89870ffa95 Reland "Change CallTests to use new PacketReceiver::DeliverRtp and PacketReceiver::DeliverRtcp"
This reverts commit 3e61f881cd2ba9040a07371e0ba6dda902aa60ae.

Reason for revert: Issue fixed in https://webrtc-review.googlesource.com/c/src/+/291104

Original change's description:
> Revert "Change CallTests to use new PacketReceiver::DeliverRtp and PacketReceiver::DeliverRtcp"
>
> This reverts commit 3b96f2c770df7691df90c2cc1be40509a76ae425.
>
> Reason for revert: Seems to cause test failures and perf regressions in tests: webrtc:14833, and  CallPerfTest.Min_Bitrate_VideoAndAudio 
>
>
> Original change's description:
> > Change CallTests to use new PacketReceiver::DeliverRtp and PacketReceiver::DeliverRtcp
> >
> > PacketReceiver::DeliverRtp requires delivered packets to have extensions already mapped.
> > Therefore DirectTransport is provided with the extension mapping.
> >
> > CallTests and tests derived from CallTest create transports in different ways, this cl change CallTest to create tests in only one way to simplify how extensions are provided to the transport but at the same time still allows different network behaviour.
> >
> >
> > Change-Id: Ie8b3ad947c170be61e62c02dadf4adedbb3841f1
> > Bug: webrtc:7135, webrtc:14795
> > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/290980
> > Reviewed-by: Jakob Ivarsson‎ <jakobi@webrtc.org>
> > Commit-Queue: Per Kjellander <perkj@webrtc.org>
> > Reviewed-by: Erik Språng <sprang@webrtc.org>
> > Cr-Commit-Position: refs/heads/main@{#39137}
>
> Bug: webrtc:7135, webrtc:14795, webrtc:14833
> Change-Id: Ib6180a47cf7611ed2bc648acc3b9e5cfeec4d9cf
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/291220
> Owners-Override: Björn Terelius <terelius@webrtc.org>
> Auto-Submit: Per Kjellander <perkj@webrtc.org>
> Reviewed-by: Björn Terelius <terelius@webrtc.org>
> Commit-Queue: Björn Terelius <terelius@webrtc.org>
> Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com>
> Cr-Commit-Position: refs/heads/main@{#39146}

Bug: webrtc:7135, webrtc:14795, webrtc:14833
Change-Id: I3fb0210d7a33c600ead5719ce2acb8cc68ec20bd
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/291222
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Reviewed-by: Jakob Ivarsson‎ <jakobi@webrtc.org>
Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com>
Owners-Override: Per Kjellander <perkj@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#39157}
2023-01-20 06:32:29 +00:00

323 lines
13 KiB
C++

/*
* 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_