File: webrtc_video_encoder_wrapper.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (188 lines) | stat: -rw-r--r-- 8,582 bytes parent folder | download | duplicates (6)
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
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef REMOTING_PROTOCOL_WEBRTC_VIDEO_ENCODER_WRAPPER_H_
#define REMOTING_PROTOCOL_WEBRTC_VIDEO_ENCODER_WRAPPER_H_

#include <memory>
#include <optional>

#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/task/single_thread_task_runner.h"
#include "base/thread_annotations.h"
#include "remoting/base/constants.h"
#include "remoting/base/running_samples.h"
#include "remoting/base/session_options.h"
#include "remoting/codec/webrtc_video_encoder.h"
#include "third_party/webrtc/api/video/video_codec_type.h"
#include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
#include "third_party/webrtc/api/video_codecs/video_encoder.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_types.h"

namespace remoting::protocol {

class VideoStreamEventRouter;

// WebrtcVideoEncoderWrapper is a wrapper around the remoting codecs which
// implement the webrtc::VideoEncoder interface. This class is instantiated by
// WebRTC via the webrtc::VideoEncoderFactory, and all methods (including the
// c'tor) are called on WebRTC's foreground worker thread.
class WebrtcVideoEncoderWrapper : public webrtc::VideoEncoder {
 public:
  // Called by the VideoEncoderFactory. |video_channel_state_observer| is
  // notified of important events on the |main_task_runner| thread.
  WebrtcVideoEncoderWrapper(
      const webrtc::SdpVideoFormat& format,
      const SessionOptions& session_options,
      scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
      scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner,
      base::WeakPtr<VideoStreamEventRouter> video_stream_event_router);
  ~WebrtcVideoEncoderWrapper() override;

  void SetEncoderForTest(std::unique_ptr<WebrtcVideoEncoder> encoder);

  // webrtc::VideoEncoder interface.
  int32_t InitEncode(const webrtc::VideoCodec* codec_settings,
                     const webrtc::VideoEncoder::Settings& settings) override;
  int32_t RegisterEncodeCompleteCallback(
      webrtc::EncodedImageCallback* callback) override;
  int32_t Release() override;
  int32_t Encode(
      const webrtc::VideoFrame& frame,
      const std::vector<webrtc::VideoFrameType>* frame_types) override;
  void SetRates(const RateControlParameters& parameters) override;
  void OnRttUpdate(int64_t rtt_ms) override;
  webrtc::VideoEncoder::EncoderInfo GetEncoderInfo() const override;

 private:
  static constexpr int kStatsWindow = 5;

  // Returns an encoded frame to WebRTC's registered callback.
  webrtc::EncodedImageCallback::Result ReturnEncodedFrame(
      const WebrtcVideoEncoder::EncodedFrame& frame);

  // Called when |encoder_| has finished encoding a frame.
  void OnFrameEncoded(WebrtcVideoEncoder::EncodeResult encode_result,
                      std::unique_ptr<WebrtcVideoEncoder::EncodedFrame> frame);

  // Notifies WebRTC that this encoder has dropped a frame.
  void NotifyFrameDropped();

  // Returns whether the frame should be encoded at low quality, to reduce
  // latency for large frame updates. This is only done here for VP8, as VP9
  // automatically detects target-overshoot and re-encodes the frame at
  // lower quality. This calculation is based on |frame|'s update-region
  // (compared with recent history) and the current bandwidth-estimation.
  bool ShouldDropQualityForLargeFrame(const webrtc::DesktopFrame& frame);

  // Begins encoding |pending_frame_| if it contains valid frame data.
  void SchedulePendingFrame();

  // Clears |pending_frame_| and notifies WebRTC of the dropped frame when
  // |pending_frame_| contains valid frame data.
  void DropPendingFrame();

  std::unique_ptr<WebrtcVideoEncoder> encoder_
      GUARDED_BY_CONTEXT(sequence_checker_);

  // Callback registered by WebRTC to receive encoded frames.
  raw_ptr<webrtc::EncodedImageCallback> encoded_callback_
      GUARDED_BY_CONTEXT(sequence_checker_) = nullptr;

  // Timestamp to be added to the EncodedImage when sending it to
  // |encoded_callback_|. This value comes from the frame that WebRTC
  // passes to Encode().
  uint32_t rtp_timestamp_ GUARDED_BY_CONTEXT(sequence_checker_);

  // FrameStats taken from the input VideoFrameAdapter, then added to the
  // EncodedFrame when encoding is complete.
  std::unique_ptr<WebrtcVideoEncoder::FrameStats> frame_stats_;

  // Bandwidth estimate from SetRates(), which is expected to be called before
  // Encode().
  int bitrate_kbps_ GUARDED_BY_CONTEXT(sequence_checker_) = 0;

  // Latest RTT estimate provided by OnRttUpdate().
  base::TimeDelta rtt_estimate_ GUARDED_BY_CONTEXT(sequence_checker_){
      base::TimeDelta::Max()};

  // True when encoding unchanged frames for top-off.
  bool top_off_active_ GUARDED_BY_CONTEXT(sequence_checker_) = false;

  webrtc::VideoCodecType codec_type_ GUARDED_BY_CONTEXT(sequence_checker_);

  // True when a frame is being encoded. This guards against encoding multiple
  // frames in parallel, which the encoders are not prepared to handle.
  bool encode_pending_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
  std::unique_ptr<webrtc::VideoFrame> pending_frame_
      GUARDED_BY_CONTEXT(sequence_checker_);

  // Stores the expected id of the next incoming frame to be encoded. If this
  // does not match, it means that WebRTC dropped a frame, and the original
  // DesktopFrame's updated-region should not be passed to the encoder.
  // Consecutive frames have incrementing IDs, wrapping around to 0 (which can
  // happen many times during a connection - the unsigned type guarantees that
  // the '++' operator will wrap to 0 after overflow).
  uint16_t next_frame_id_ GUARDED_BY_CONTEXT(sequence_checker_) = 0;

  // Keeps track of any update-rectangles from dropped frames. When WebRTC
  // requests to encode a frame, this class will either:
  // * Send it to be encoded - if any prior frames were dropped, this
  //   accumulated update-rect will be added to the incoming frame, then it will
  //   be reset to empty.
  // * Drop the frame - the frame's update-rect will be stored and combined with
  //   this accumulated update-rect.
  // This tracking is similar to what WebRTC does whenever it drops frames
  // internally.  WebRTC will also detect resolution-changes and set the
  // frame's update-rect to the full area, so no special logic is needed here
  // for changes in resolution (except to make sure that any frame's update-rect
  // always lies within the frame's bounding rect).
  webrtc::VideoFrame::UpdateRect accumulated_update_rect_
      GUARDED_BY_CONTEXT(sequence_checker_){};

  // Used by ShouldDropQualityForLargeFrame(). This stores the most recent
  // update-region areas of previously-encoded frames, in order to detect an
  // unusually-large update.
  RunningSamples updated_region_area_ GUARDED_BY_CONTEXT(sequence_checker_){
      kStatsWindow};

  // Stores the time when the most recent frame was sent to the encoder. This is
  // used to rate-limit the encoding and sending of empty frames.
  base::TimeTicks latest_frame_encode_start_time_
      GUARDED_BY_CONTEXT(sequence_checker_);

  // If a key-frame is requested, but this class needs to drop the frame, this
  // flag remembers the request so it can be applied to the next frame.
  bool pending_key_frame_request_ GUARDED_BY_CONTEXT(sequence_checker_) = false;

  // TaskRunner used for notifying |video_channel_state_observer_|.
  scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;

  // TaskRunner used for scheduling encoding tasks.
  scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner_;

  // Stores the current frame interval, updated for each frame received.
  base::TimeDelta current_frame_interval_ = base::Hertz(kTargetFrameRate);

  // Stores the timestamp of the last frame that was sent for encoding.
  base::Time last_frame_received_timestamp_;

  // Represents the screen which is being encoded by this instance. Initialized
  // after the first captured frame has been received.
  std::optional<webrtc::ScreenId> screen_id_;

  base::WeakPtr<VideoStreamEventRouter> video_stream_event_router_;

  // This class lives on WebRTC's encoding thread. All methods (including ctor
  // and dtor) are expected to be called on the same thread.
  SEQUENCE_CHECKER(sequence_checker_);

  base::WeakPtrFactory<WebrtcVideoEncoderWrapper> weak_factory_{this};
};

}  // namespace remoting::protocol

#endif  // REMOTING_PROTOCOL_WEBRTC_VIDEO_ENCODER_WRAPPER_H_