1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
|
/*
* Copyright (c) 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 API_TEST_VIDEO_QUALITY_ANALYZER_INTERFACE_H_
#define API_TEST_VIDEO_QUALITY_ANALYZER_INTERFACE_H_
#include <cstdint>
#include <optional>
#include <string>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "api/scoped_refptr.h"
#include "api/stats/rtc_stats_report.h"
#include "api/test/stats_observer_interface.h"
#include "api/video/encoded_image.h"
#include "api/video/video_frame.h"
#include "api/video_codecs/video_encoder.h"
#include "rtc_base/checks.h"
namespace webrtc {
// API is in development and can be changed without notice.
// Base interface for video quality analyzer for peer connection level end-2-end
// tests. Interface has only one abstract method, which have to return frame id.
// Other methods have empty implementation by default, so user can override only
// required parts.
//
// VideoQualityAnalyzerInterface will be injected into WebRTC pipeline on both
// sides of the call. Here is video data flow in WebRTC pipeline
//
// Alice:
// ___________ ________ _________
// | | | | | |
// | Frame |-(A)→| WebRTC |-(B)→| Video |-(C)┐
// | Generator | | Stack | | Encoder | |
// ¯¯¯¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯ |
// __↓________
// | Transport |
// | & |
// | Network |
// ¯¯|¯¯¯¯¯¯¯¯
// Bob: |
// _______ ________ _________ |
// | | | | | | |
// | Video |←(F)-| WebRTC |←(E)-| Video |←(D)----┘
// | Sink | | Stack | | Decoder |
// ¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯
// The analyzer will be injected in all points from A to F.
class VideoQualityAnalyzerInterface
: public webrtc_pc_e2e::StatsObserverInterface {
public:
// Contains extra statistic provided by video encoder.
struct EncoderStats {
std::string encoder_name = "unknown";
// TODO(hbos) https://crbug.com/webrtc/9547,
// https://crbug.com/webrtc/11443: improve stats API to make available
// there.
uint32_t target_encode_bitrate = 0;
// Encoder quantizer value.
int qp = -1;
};
// Contains extra statistic provided by video decoder.
struct DecoderStats {
std::string decoder_name = "unknown";
// Decode time provided by decoder itself. If decoder doesn’t produce such
// information can be omitted.
std::optional<int32_t> decode_time_ms = std::nullopt;
// Decoder quantizer value.
std::optional<uint8_t> qp = std::nullopt;
};
~VideoQualityAnalyzerInterface() override = default;
// Will be called by framework before test.
// `test_case_name` is name of test case, that should be used to report all
// video metrics.
// `threads_count` is number of threads that analyzer can use for heavy
// calculations. Analyzer can perform simple calculations on the calling
// thread in each method, but should remember, that it is the same thread,
// that is used in video pipeline.
virtual void Start(std::string /* test_case_name */,
ArrayView<const std::string> /* peer_names */,
int /* max_threads_count */) {}
// Will be called when frame was generated from the input stream.
// `peer_name` is name of the peer on which side frame was captured.
// Returns frame id, that will be set by framework to the frame.
virtual uint16_t OnFrameCaptured(absl::string_view peer_name,
const std::string& stream_label,
const VideoFrame& frame) = 0;
// Will be called before calling the encoder.
// `peer_name` is name of the peer on which side frame came to encoder.
virtual void OnFramePreEncode(absl::string_view /* peer_name */,
const VideoFrame& /* frame */) {}
// Will be called for each EncodedImage received from encoder. Single
// VideoFrame can produce multiple EncodedImages. Each encoded image will
// have id from VideoFrame.
// `peer_name` is name of the peer on which side frame was encoded.
virtual void OnFrameEncoded(absl::string_view /* peer_name */,
uint16_t /* frame_id */,
const EncodedImage& /* encoded_image */,
const EncoderStats& /* stats */,
bool /* discarded */) {}
// Will be called for each frame dropped by encoder.
// `peer_name` is name of the peer on which side frame drop was detected.
virtual void OnFrameDropped(absl::string_view /* peer_name */,
EncodedImageCallback::DropReason /* reason */) {}
// Will be called before calling the decoder.
// `peer_name` is name of the peer on which side frame was received.
virtual void OnFramePreDecode(absl::string_view /* peer_name */,
uint16_t /* frame_id */,
const EncodedImage& /* encoded_image */) {}
// Will be called after decoding the frame.
// `peer_name` is name of the peer on which side frame was decoded.
virtual void OnFrameDecoded(absl::string_view /* peer_name */,
const VideoFrame& /* frame */,
const DecoderStats& /* stats */) {}
// Will be called when frame will be obtained from PeerConnection stack.
// `peer_name` is name of the peer on which side frame was rendered.
virtual void OnFrameRendered(absl::string_view /* peer_name */,
const VideoFrame& /* frame */) {}
// Will be called if encoder return not WEBRTC_VIDEO_CODEC_OK.
// All available codes are listed in
// modules/video_coding/include/video_error_codes.h
// `peer_name` is name of the peer on which side error acquired.
virtual void OnEncoderError(absl::string_view /* peer_name */,
const VideoFrame& /* frame */,
int32_t /* error_code */) {}
// Will be called if decoder return not WEBRTC_VIDEO_CODEC_OK.
// All available codes are listed in
// modules/video_coding/include/video_error_codes.h
// `peer_name` is name of the peer on which side error acquired.
virtual void OnDecoderError(absl::string_view /* peer_name */,
uint16_t /* frame_id */,
int32_t /* error_code */,
const DecoderStats& /* stats */) {}
// Will be called every time new stats reports are available for the
// Peer Connection identified by `pc_label`.
void OnStatsReports(
absl::string_view /* pc_label */,
const scoped_refptr<const RTCStatsReport>& /* report */) override {}
// Will be called before test adds new participant in the middle of a call.
virtual void RegisterParticipantInCall(absl::string_view /* peer_name */) {}
// Will be called after test removed existing participant in the middle of the
// call.
virtual void UnregisterParticipantInCall(absl::string_view /* peer_name */) {}
// Informs analyzer that peer `receiver_peer_name` should not receive any
// stream from sender `sender_peer_name`.
// This method is a no-op if the sender or the receiver does not exist.
virtual void OnPauseAllStreamsFrom(
absl::string_view /* sender_peer_name */,
absl::string_view /* receiver_peer_name */) {}
// Informs analyzer that peer `receiver_peer_name` is expected to receive all
// streams from `sender_peer_name`.
// This method is a no-op if the sender or the receiver does not exist.
virtual void OnResumeAllStreamsFrom(
absl::string_view /* sender_peer_name */,
absl::string_view /* receiver_peer_name */) {}
// Tells analyzer that analysis complete and it should calculate final
// statistics.
virtual void Stop() {}
// Returns the last stream where this frame was captured. It means that if
// frame ids space wraps around, then stream label for frame id may change.
// It will crash, if the specified `frame_id` wasn't captured.
virtual std::string GetStreamLabel(uint16_t frame_id) = 0;
// Returns the sender peer name of the last stream where this frame was
// captured. The sender for this frame id may change when the frame ids wrap
// around. Also it will crash, if the specified `frame_id` wasn't captured.
virtual std::string GetSenderPeerName(uint16_t /* frame_id */) const {
RTC_CHECK(false) << "Not implemented.";
}
};
} // namespace webrtc
#endif // API_TEST_VIDEO_QUALITY_ANALYZER_INTERFACE_H_
|