Artem Titov | b6c6201 | 2019-01-08 14:58:23 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license |
| 5 | * that can be found in the LICENSE file in the root of the source |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
Artem Titov | d57628f | 2019-03-22 12:34:25 +0100 | [diff] [blame] | 11 | #ifndef API_TEST_VIDEO_QUALITY_ANALYZER_INTERFACE_H_ |
| 12 | #define API_TEST_VIDEO_QUALITY_ANALYZER_INTERFACE_H_ |
Artem Titov | b6c6201 | 2019-01-08 14:58:23 +0100 | [diff] [blame] | 13 | |
| 14 | #include <memory> |
| 15 | #include <string> |
| 16 | |
Artem Titov | 8a0284e | 2020-05-29 15:49:44 +0200 | [diff] [blame] | 17 | #include "absl/strings/string_view.h" |
Artem Titov | b6c6201 | 2019-01-08 14:58:23 +0100 | [diff] [blame] | 18 | #include "absl/types/optional.h" |
Artem Titov | 3b64167 | 2020-06-02 17:18:17 +0200 | [diff] [blame] | 19 | #include "api/array_view.h" |
Artem Titov | d57628f | 2019-03-22 12:34:25 +0100 | [diff] [blame] | 20 | #include "api/test/stats_observer_interface.h" |
Artem Titov | b6c6201 | 2019-01-08 14:58:23 +0100 | [diff] [blame] | 21 | #include "api/video/encoded_image.h" |
| 22 | #include "api/video/video_frame.h" |
| 23 | #include "api/video_codecs/video_encoder.h" |
| 24 | |
| 25 | namespace webrtc { |
| 26 | |
Artem Titov | d57628f | 2019-03-22 12:34:25 +0100 | [diff] [blame] | 27 | // API is in development and can be changed without notice. |
| 28 | |
Artem Titov | ebd9770 | 2019-01-09 17:55:36 +0100 | [diff] [blame] | 29 | // Base interface for video quality analyzer for peer connection level end-2-end |
| 30 | // tests. Interface has only one abstract method, which have to return frame id. |
| 31 | // Other methods have empty implementation by default, so user can override only |
| 32 | // required parts. |
| 33 | // |
| 34 | // VideoQualityAnalyzerInterface will be injected into WebRTC pipeline on both |
| 35 | // sides of the call. Here is video data flow in WebRTC pipeline |
| 36 | // |
| 37 | // Alice: |
| 38 | // ___________ ________ _________ |
| 39 | // | | | | | | |
| 40 | // | Frame |-(A)→| WebRTC |-(B)→| Video |-(C)┐ |
| 41 | // | Generator | | Stack | | Decoder | | |
| 42 | // ¯¯¯¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯ | |
| 43 | // __↓________ |
| 44 | // | Transport | |
| 45 | // | & | |
| 46 | // | Network | |
| 47 | // ¯¯|¯¯¯¯¯¯¯¯ |
| 48 | // Bob: | |
| 49 | // _______ ________ _________ | |
| 50 | // | | | | | | | |
| 51 | // | Video |←(F)-| WebRTC |←(E)-| Video |←(D)----┘ |
| 52 | // | Sink | | Stack | | Decoder | |
| 53 | // ¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯ |
| 54 | // The analyzer will be injected in all points from A to F. |
Artem Titov | 4c4c744 | 2021-08-19 22:11:33 +0200 | [diff] [blame] | 55 | class VideoQualityAnalyzerInterface |
| 56 | : public webrtc_pc_e2e::StatsObserverInterface { |
Artem Titov | b6c6201 | 2019-01-08 14:58:23 +0100 | [diff] [blame] | 57 | public: |
Artem Titov | d19513f | 2020-03-25 11:53:41 +0100 | [diff] [blame] | 58 | // Contains extra statistic provided by video encoder. |
| 59 | struct EncoderStats { |
Artem Titov | 647d326 | 2021-08-11 18:27:36 +0200 | [diff] [blame] | 60 | std::string encoder_name = "unknown"; |
Artem Titov | d19513f | 2020-03-25 11:53:41 +0100 | [diff] [blame] | 61 | // TODO(hbos) https://crbug.com/webrtc/9547, |
| 62 | // https://crbug.com/webrtc/11443: improve stats API to make available |
| 63 | // there. |
Artem Titov | 647d326 | 2021-08-11 18:27:36 +0200 | [diff] [blame] | 64 | uint32_t target_encode_bitrate = 0; |
Artem Titov | d19513f | 2020-03-25 11:53:41 +0100 | [diff] [blame] | 65 | }; |
| 66 | // Contains extra statistic provided by video decoder. |
| 67 | struct DecoderStats { |
Artem Titov | 647d326 | 2021-08-11 18:27:36 +0200 | [diff] [blame] | 68 | std::string decoder_name = "unknown"; |
Artem Titov | d19513f | 2020-03-25 11:53:41 +0100 | [diff] [blame] | 69 | // Decode time provided by decoder itself. If decoder doesn’t produce such |
| 70 | // information can be omitted. |
Artem Titov | 647d326 | 2021-08-11 18:27:36 +0200 | [diff] [blame] | 71 | absl::optional<int32_t> decode_time_ms = absl::nullopt; |
Artem Titov | d19513f | 2020-03-25 11:53:41 +0100 | [diff] [blame] | 72 | }; |
| 73 | |
Mirko Bonadei | 12ae4f4 | 2019-02-26 15:19:07 +0100 | [diff] [blame] | 74 | ~VideoQualityAnalyzerInterface() override = default; |
Artem Titov | b6c6201 | 2019-01-08 14:58:23 +0100 | [diff] [blame] | 75 | |
Artem Titov | 5983585 | 2019-02-27 17:44:13 +0100 | [diff] [blame] | 76 | // Will be called by framework before test. |
Artem Titov | 0e61fdd | 2021-07-25 21:50:14 +0200 | [diff] [blame] | 77 | // `test_case_name` is name of test case, that should be used to report all |
Artem Titov | 5983585 | 2019-02-27 17:44:13 +0100 | [diff] [blame] | 78 | // video metrics. |
Artem Titov | 0e61fdd | 2021-07-25 21:50:14 +0200 | [diff] [blame] | 79 | // `threads_count` is number of threads that analyzer can use for heavy |
Artem Titov | 5983585 | 2019-02-27 17:44:13 +0100 | [diff] [blame] | 80 | // calculations. Analyzer can perform simple calculations on the calling |
| 81 | // thread in each method, but should remember, that it is the same thread, |
| 82 | // that is used in video pipeline. |
Artem Titov | 3b64167 | 2020-06-02 17:18:17 +0200 | [diff] [blame] | 83 | virtual void Start(std::string test_case_name, |
| 84 | rtc::ArrayView<const std::string> peer_names, |
| 85 | int max_threads_count) {} |
Artem Titov | b6c6201 | 2019-01-08 14:58:23 +0100 | [diff] [blame] | 86 | |
| 87 | // Will be called when frame was generated from the input stream. |
Artem Titov | 0e61fdd | 2021-07-25 21:50:14 +0200 | [diff] [blame] | 88 | // `peer_name` is name of the peer on which side frame was captured. |
Artem Titov | b6c6201 | 2019-01-08 14:58:23 +0100 | [diff] [blame] | 89 | // Returns frame id, that will be set by framework to the frame. |
Andrey Logvin | 8dbbd64 | 2020-12-02 18:42:34 +0000 | [diff] [blame] | 90 | virtual uint16_t OnFrameCaptured(absl::string_view peer_name, |
| 91 | const std::string& stream_label, |
| 92 | const VideoFrame& frame) = 0; |
Artem Titov | ebd9770 | 2019-01-09 17:55:36 +0100 | [diff] [blame] | 93 | // Will be called before calling the encoder. |
Artem Titov | 0e61fdd | 2021-07-25 21:50:14 +0200 | [diff] [blame] | 94 | // `peer_name` is name of the peer on which side frame came to encoder. |
Artem Titov | 8a0284e | 2020-05-29 15:49:44 +0200 | [diff] [blame] | 95 | virtual void OnFramePreEncode(absl::string_view peer_name, |
| 96 | const VideoFrame& frame) {} |
Artem Titov | b6c6201 | 2019-01-08 14:58:23 +0100 | [diff] [blame] | 97 | // Will be called for each EncodedImage received from encoder. Single |
| 98 | // VideoFrame can produce multiple EncodedImages. Each encoded image will |
| 99 | // have id from VideoFrame. |
Artem Titov | 0e61fdd | 2021-07-25 21:50:14 +0200 | [diff] [blame] | 100 | // `peer_name` is name of the peer on which side frame was encoded. |
Artem Titov | 8a0284e | 2020-05-29 15:49:44 +0200 | [diff] [blame] | 101 | virtual void OnFrameEncoded(absl::string_view peer_name, |
| 102 | uint16_t frame_id, |
Artem Titov | d19513f | 2020-03-25 11:53:41 +0100 | [diff] [blame] | 103 | const EncodedImage& encoded_image, |
| 104 | const EncoderStats& stats) {} |
Artem Titov | b6c6201 | 2019-01-08 14:58:23 +0100 | [diff] [blame] | 105 | // Will be called for each frame dropped by encoder. |
Artem Titov | 0e61fdd | 2021-07-25 21:50:14 +0200 | [diff] [blame] | 106 | // `peer_name` is name of the peer on which side frame drop was detected. |
Artem Titov | 8a0284e | 2020-05-29 15:49:44 +0200 | [diff] [blame] | 107 | virtual void OnFrameDropped(absl::string_view peer_name, |
| 108 | EncodedImageCallback::DropReason reason) {} |
Artem Titov | ebd9770 | 2019-01-09 17:55:36 +0100 | [diff] [blame] | 109 | // Will be called before calling the decoder. |
Artem Titov | 0e61fdd | 2021-07-25 21:50:14 +0200 | [diff] [blame] | 110 | // `peer_name` is name of the peer on which side frame was received. |
Artem Titov | 8a0284e | 2020-05-29 15:49:44 +0200 | [diff] [blame] | 111 | virtual void OnFramePreDecode(absl::string_view peer_name, |
| 112 | uint16_t frame_id, |
Johannes Kron | c12db81 | 2019-09-19 13:20:01 +0200 | [diff] [blame] | 113 | const EncodedImage& encoded_image) {} |
Artem Titov | d19513f | 2020-03-25 11:53:41 +0100 | [diff] [blame] | 114 | // Will be called after decoding the frame. |
Artem Titov | 0e61fdd | 2021-07-25 21:50:14 +0200 | [diff] [blame] | 115 | // `peer_name` is name of the peer on which side frame was decoded. |
Artem Titov | 8a0284e | 2020-05-29 15:49:44 +0200 | [diff] [blame] | 116 | virtual void OnFrameDecoded(absl::string_view peer_name, |
| 117 | const VideoFrame& frame, |
Artem Titov | d19513f | 2020-03-25 11:53:41 +0100 | [diff] [blame] | 118 | const DecoderStats& stats) {} |
Artem Titov | b6c6201 | 2019-01-08 14:58:23 +0100 | [diff] [blame] | 119 | // Will be called when frame will be obtained from PeerConnection stack. |
Artem Titov | 0e61fdd | 2021-07-25 21:50:14 +0200 | [diff] [blame] | 120 | // `peer_name` is name of the peer on which side frame was rendered. |
Artem Titov | 8a0284e | 2020-05-29 15:49:44 +0200 | [diff] [blame] | 121 | virtual void OnFrameRendered(absl::string_view peer_name, |
| 122 | const VideoFrame& frame) {} |
Artem Titov | ebd9770 | 2019-01-09 17:55:36 +0100 | [diff] [blame] | 123 | // Will be called if encoder return not WEBRTC_VIDEO_CODEC_OK. |
| 124 | // All available codes are listed in |
| 125 | // modules/video_coding/include/video_error_codes.h |
Artem Titov | 0e61fdd | 2021-07-25 21:50:14 +0200 | [diff] [blame] | 126 | // `peer_name` is name of the peer on which side error acquired. |
Artem Titov | 8a0284e | 2020-05-29 15:49:44 +0200 | [diff] [blame] | 127 | virtual void OnEncoderError(absl::string_view peer_name, |
| 128 | const VideoFrame& frame, |
| 129 | int32_t error_code) {} |
Artem Titov | ebd9770 | 2019-01-09 17:55:36 +0100 | [diff] [blame] | 130 | // Will be called if decoder return not WEBRTC_VIDEO_CODEC_OK. |
| 131 | // All available codes are listed in |
| 132 | // modules/video_coding/include/video_error_codes.h |
Artem Titov | 0e61fdd | 2021-07-25 21:50:14 +0200 | [diff] [blame] | 133 | // `peer_name` is name of the peer on which side error acquired. |
Artem Titov | 8a0284e | 2020-05-29 15:49:44 +0200 | [diff] [blame] | 134 | virtual void OnDecoderError(absl::string_view peer_name, |
| 135 | uint16_t frame_id, |
| 136 | int32_t error_code) {} |
Artem Titov | a854921 | 2019-08-19 14:38:06 +0200 | [diff] [blame] | 137 | // Will be called every time new stats reports are available for the |
Artem Titov | 0e61fdd | 2021-07-25 21:50:14 +0200 | [diff] [blame] | 138 | // Peer Connection identified by `pc_label`. |
Andrey Logvin | 9b52618 | 2020-06-15 16:14:07 +0000 | [diff] [blame] | 139 | void OnStatsReports( |
| 140 | absl::string_view pc_label, |
| 141 | const rtc::scoped_refptr<const RTCStatsReport>& report) override {} |
Artem Titov | b6c6201 | 2019-01-08 14:58:23 +0100 | [diff] [blame] | 142 | |
Andrey Logvin | d7808f1 | 2020-12-08 15:21:27 +0000 | [diff] [blame] | 143 | // Will be called before test adds new participant in the middle of a call. |
| 144 | virtual void RegisterParticipantInCall(absl::string_view peer_name) {} |
Artem Titov | 86ebbdb | 2022-06-21 00:24:41 +0200 | [diff] [blame] | 145 | // Will be called after test removed existing participant in the middle of the |
| 146 | // call. |
| 147 | virtual void UnregisterParticipantInCall(absl::string_view peer_name) {} |
Andrey Logvin | d7808f1 | 2020-12-08 15:21:27 +0000 | [diff] [blame] | 148 | |
Artem Titov | ebd9770 | 2019-01-09 17:55:36 +0100 | [diff] [blame] | 149 | // Tells analyzer that analysis complete and it should calculate final |
Artem Titov | b6c6201 | 2019-01-08 14:58:23 +0100 | [diff] [blame] | 150 | // statistics. |
| 151 | virtual void Stop() {} |
Artem Titov | 32232e9 | 2019-02-20 21:13:14 +0100 | [diff] [blame] | 152 | |
Artem Titov | be9c40f | 2021-11-17 11:56:43 +0100 | [diff] [blame] | 153 | // Returns the last stream where this frame was captured. It means that if |
| 154 | // frame ids space wraps around, then stream label for frame id may change. |
| 155 | // It will crash, if the specified `frame_id` wasn't captured. |
Artem Titov | 32232e9 | 2019-02-20 21:13:14 +0100 | [diff] [blame] | 156 | virtual std::string GetStreamLabel(uint16_t frame_id) = 0; |
Artem Titov | b6c6201 | 2019-01-08 14:58:23 +0100 | [diff] [blame] | 157 | }; |
| 158 | |
Artem Titov | b6c6201 | 2019-01-08 14:58:23 +0100 | [diff] [blame] | 159 | } // namespace webrtc |
| 160 | |
Artem Titov | d57628f | 2019-03-22 12:34:25 +0100 | [diff] [blame] | 161 | #endif // API_TEST_VIDEO_QUALITY_ANALYZER_INTERFACE_H_ |