summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/api/test/video_quality_analyzer_interface.h
blob: d35be8ca1a855982f5fca806837eef1d6e1066b7 (plain)
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
/*
 *  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 <memory>
#include <string>

#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/array_view.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"

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  |     | Decoder |    |
//  ¯¯¯¯¯¯¯¯¯¯¯       ¯¯¯¯¯¯¯¯       ¯¯¯¯¯¯¯¯¯     |
//                                               __↓________
//                                              | 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.
    absl::optional<int32_t> decode_time_ms = absl::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,
                     rtc::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 rtc::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) {}

  // 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;
};

}  // namespace webrtc

#endif  // API_TEST_VIDEO_QUALITY_ANALYZER_INTERFACE_H_