当前位置: 首页 > article >正文

【WebRTC】视频编码链路中各个类的简单分析——VideoStreamEncoder

目录

  • 1.视频流编码器(VideoStreamEncoder)
    • 1.1 视频流编码器接口(VideoStreamEncoderInterface)
    • 1.2 资源类(Resource)
    • 1.3 已编码图像的回调(EncodedImageCallback)
    • 1.4 视频资源监听器(VideoSourceRestrictionsListener)

1.视频流编码器(VideoStreamEncoder)

VideoStreamEncoder是编码流程当中至关重要的一个类,它实现的功能包括:
(1)开始编码器,暂停编码器,停止编码器
(2)设置编码器(根据config)
(3)调控编码参数,如码控参数,帧率等等
(4)调控前向纠错器
(5)视频帧的传输和接收
(6)根据网络环境,调控丢帧
(7)根据编码情况,调控屯帧
(8)根据情况,调控编码质量(因为网络环境,编码器情况,可能会调整编码策略,影响编码质量)
(9)对已编码图像进行后处理
(10)统计编码信息

可以说,在视频编码流程中,VideoStreamEncoder是获取了视频帧之后,第一个会使用到的类。这个类十分综合,大多数的编码过程都与这个类相关,所以其声明比较长,这里做简单记录,深入到每个模块之后再分析。

// VideoStreamEncoder represent a video encoder that accepts raw video frames as
// input and produces an encoded bit stream.
// Usage:
//  Instantiate.
//  Call SetSink.
//  Call SetSource.
//  Call ConfigureEncoder with the codec settings.
//  Call Stop() when done.
/*
	VideoStreamEncoder表示了一个视频编码器,它接收原始视频帧作为输入并且产生编码后的比特流
	用法:
	(1) 创建实例
	(2) SetSink,设置接收器
	(3) SetSource,设置资源
	(4) ConfigureEncoder,配置编码器参数
	(5) Stop(),结束流程
*/
class VideoStreamEncoder : public VideoStreamEncoderInterface,
                           private EncodedImageCallback,
                           public VideoSourceRestrictionsListener {
 public:
  // TODO(bugs.webrtc.org/12000): Reporting of VideoBitrateAllocation is being
  // deprecated. Instead VideoLayersAllocation should be reported.
  enum class BitrateAllocationCallbackType {
    kVideoBitrateAllocation,
    kVideoBitrateAllocationWhenScreenSharing,
    kVideoLayersAllocation
  };
  VideoStreamEncoder(
      const Environment& env,
      uint32_t number_of_cores,
      VideoStreamEncoderObserver* encoder_stats_observer,
      const VideoStreamEncoderSettings& settings,
      std::unique_ptr<OveruseFrameDetector> overuse_detector,
      std::unique_ptr<FrameCadenceAdapterInterface> frame_cadence_adapter,
      std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter>
          encoder_queue,
      BitrateAllocationCallbackType allocation_cb_type,
      webrtc::VideoEncoderFactory::EncoderSelectorInterface* encoder_selector =
          nullptr);
  ~VideoStreamEncoder() override;

  VideoStreamEncoder(const VideoStreamEncoder&) = delete;
  VideoStreamEncoder& operator=(const VideoStreamEncoder&) = delete;
  // 添加自适应资源
  void AddAdaptationResource(rtc::scoped_refptr<Resource> resource) override;
  // 获取自适应资源
  std::vector<rtc::scoped_refptr<Resource>> GetAdaptationResources() override;
  // 设置资源
  void SetSource(rtc::VideoSourceInterface<VideoFrame>* source,
                 const DegradationPreference& degradation_preference) override;
  // 设置接收器
  void SetSink(EncoderSink* sink, bool rotation_applied) override;

  // TODO(perkj): Can we remove VideoCodec.startBitrate ?
  // 设置起始码率
  void SetStartBitrate(int start_bitrate_bps) override;
  // 设置前向纠错控制器
  void SetFecControllerOverride(
      FecControllerOverride* fec_controller_override) override;
  // 配置编码器
  void ConfigureEncoder(VideoEncoderConfig config,
                        size_t max_data_payload_length) override;
  void ConfigureEncoder(VideoEncoderConfig config,
                        size_t max_data_payload_length,
                        SetParametersCallback callback) override;

  // Permanently stop encoding. After this method has returned, it is
  // guaranteed that no encoded frames will be delivered to the sink.
  // 永久性停止编码,此方法返回后,保证不会有编码后的帧传递给接收器
  void Stop() override;
  // 传递关键帧
  void SendKeyFrame(const std::vector<VideoFrameType>& layers = {}) override;
  // 检测到丢包,需要调整编码策略,例如降低分辨率或帧率
  void OnLossNotification(
      const VideoEncoder::LossNotification& loss_notification) override;
  // 检测到码率变化,需要调整编码参数
  void OnBitrateUpdated(DataRate target_bitrate,
                        DataRate stable_target_bitrate,
                        DataRate target_headroom,
                        uint8_t fraction_lost,
                        int64_t round_trip_time_ms,
                        double cwnd_reduce_ratio) override;
  // 根据拥塞窗口减少比例,来调整目标比特率,避免丢包和网络拥塞
  DataRate UpdateTargetBitrate(DataRate target_bitrate,
                               double cwnd_reduce_ratio);

 protected:
  friend class VideoStreamEncoderFrameCadenceRestrictionTest;

  // Used for testing. For example the `ScalingObserverInterface` methods must
  // be called on `encoder_queue_`.
  TaskQueueBase* encoder_queue() { return encoder_queue_.get(); }
  // 检测到视频限制性资源发生变化
  void OnVideoSourceRestrictionsUpdated(
      VideoSourceRestrictions restrictions,
      const VideoAdaptationCounters& adaptation_counters,
      rtc::scoped_refptr<Resource> reason,
      const VideoSourceRestrictions& unfiltered_restrictions) override;

  // Used for injected test resources.
  // TODO(eshr): Move all adaptation tests out of VideoStreamEncoder tests.
  // 注入自适应资源,这里与AddAdaptationResource不同,还需要入参reason,即更加
  // 精准的调控
  void InjectAdaptationResource(rtc::scoped_refptr<Resource> resource,
                                VideoAdaptationReason reason);
  // 注入自适应限制
  void InjectAdaptationConstraint(AdaptationConstraint* adaptation_constraint);

  void AddRestrictionsListenerForTesting(
      VideoSourceRestrictionsListener* restrictions_listener);
  void RemoveRestrictionsListenerForTesting(
      VideoSourceRestrictionsListener* restrictions_listener);

 private:
  class CadenceCallback : public FrameCadenceAdapterInterface::Callback {
   public:
    explicit CadenceCallback(VideoStreamEncoder& video_stream_encoder)
        : video_stream_encoder_(video_stream_encoder) {}
    // FrameCadenceAdapterInterface::Callback overrides.
    // 下面是对FrameCadenceAdapterInterface::Callback当中函数的重载
    void OnFrame(Timestamp post_time,
                 bool queue_overload,
                 const VideoFrame& frame) override {
      // 使用VideoStreamEncoder当中的OnFrame()函数重载
      video_stream_encoder_.OnFrame(post_time, queue_overload, frame);
    }
    void OnDiscardedFrame() override {
      video_stream_encoder_.OnDiscardedFrame();
    }
    void RequestRefreshFrame() override {
      video_stream_encoder_.RequestRefreshFrame();
    }

   private:
    VideoStreamEncoder& video_stream_encoder_;
  };
  // VideoFrameInfo记录长宽,是否是纹理等信息
  class VideoFrameInfo {
   public:
    VideoFrameInfo(int width, int height, bool is_texture)
        : width(width), height(height), is_texture(is_texture) {}
    int width;
    int height;
    bool is_texture;
    int pixel_count() const { return width * height; }
  };
  // 编码速率设定
  struct EncoderRateSettings {
    EncoderRateSettings();
    EncoderRateSettings(const VideoBitrateAllocation& bitrate,
                        double framerate_fps,
                        DataRate bandwidth_allocation,
                        DataRate encoder_target,
                        DataRate stable_encoder_target);
    bool operator==(const EncoderRateSettings& rhs) const;
    bool operator!=(const EncoderRateSettings& rhs) const;
    // 码率控制参数
    VideoEncoder::RateControlParameters rate_control;
    // This is the scalar target bitrate before the VideoBitrateAllocator, i.e.
    // the `target_bitrate` argument of the OnBitrateUpdated() method. This is
    // needed because the bitrate allocator may truncate the total bitrate and a
    // later call to the same allocator instance, e.g.
    // |using last_encoder_rate_setings_->bitrate.get_sum_bps()|, may trick it
    // into thinking the available bitrate has decreased since the last call.
    /*
		这是`VideoBitrateAllocator`之前的标量目标比特率,即`OnBitrateUpdated()`方法
		的`target_bitrate`参数。这是因为比特率分配器可能会截断总比特率,而在稍后对同一
		分配器实例的调用中,例如`|using last_encoder_rate_setings_->bitrate.get_sum_bps()|`,
		可能会误导它认为自上次调用以来可用的比特率已经减少。
	*/
    DataRate encoder_target;
    DataRate stable_encoder_target;
  };

  class DegradationPreferenceManager;
  // 重新配置编码器
  void ReconfigureEncoder() RTC_RUN_ON(encoder_queue_);
  // 检测到编码器配置发生变化
  void OnEncoderSettingsChanged() RTC_RUN_ON(encoder_queue_);
  // 检测到帧
  void OnFrame(Timestamp post_time,
               bool queue_overload,
               const VideoFrame& video_frame);
  // 检测到丢弃帧
  void OnDiscardedFrame();
  // 需要刷新帧
  void RequestRefreshFrame();
  // 可能会编码视频帧
  void MaybeEncodeVideoFrame(const VideoFrame& frame,
                             int64_t time_when_posted_in_ms);
  // 编码视频帧
  void EncodeVideoFrame(const VideoFrame& frame,
                        int64_t time_when_posted_in_ms);
  // Indicates whether frame should be dropped because the pixel count is too
  // large for the current bitrate configuration.
  // 在当前码率配置下,根据pixle count来检查当前帧是否需要被丢弃
  bool DropDueToSize(uint32_t pixel_count) const RTC_RUN_ON(encoder_queue_);

  // Implements EncodedImageCallback.
  // 接收编码器编码之后的图像
  EncodedImageCallback::Result OnEncodedImage(
      const EncodedImage& encoded_image,
      const CodecSpecificInfo* codec_specific_info) override;
  // 丢帧的回调函数,需要给出reason
  void OnDroppedFrame(EncodedImageCallback::DropReason reason) override;
  // 暂停编码器
  bool EncoderPaused() const;
  // 标记丢帧开始
  void TraceFrameDropStart();
  // 标记丢帧结束
  void TraceFrameDropEnd();

  // Returns a copy of `rate_settings` with the `bitrate` field updated using
  // the current VideoBitrateAllocator.
  // 返回一个`rate_settings`的副本,其中`bitrate`字段已使用当前的`VideoBitrateAllocator`更新。
  EncoderRateSettings UpdateBitrateAllocation(
      const EncoderRateSettings& rate_settings) RTC_RUN_ON(encoder_queue_);
  // 获取输入帧率Fps
  uint32_t GetInputFramerateFps() RTC_RUN_ON(encoder_queue_);
  // 设置编码器速率
  void SetEncoderRates(const EncoderRateSettings& rate_settings)
      RTC_RUN_ON(encoder_queue_);
  // 进行编码后处理
  void RunPostEncode(const EncodedImage& encoded_image,
                     int64_t time_sent_us,
                     int temporal_index,
                     DataSize frame_size);
  // 释放编码器
  void ReleaseEncoder() RTC_RUN_ON(encoder_queue_);
  // After calling this function `resource_adaptation_processor_` will be null.
  // 关闭资源自适应队列,resource_adaptation_processor会设置为null
  void ShutdownResourceAdaptationQueue();
  // 申请更换编码器
  void RequestEncoderSwitch() RTC_RUN_ON(encoder_queue_);

  // Augments an EncodedImage received from an encoder with parsable
  // information.
  // 修改或增强已编码图像
  EncodedImage AugmentEncodedImage(
      const EncodedImage& encoded_image,
      const CodecSpecificInfo* codec_specific_info);
  // 处理已丢弃的帧
  void ProcessDroppedFrame(const VideoFrame& frame,
                           VideoStreamEncoderObserver::DropReason reason)
      RTC_RUN_ON(encoder_queue_);

  const Environment env_;
  TaskQueueBase* const worker_queue_;

  const int number_of_cores_;
  // sink是接收器
  EncoderSink* sink_ = nullptr;
  // VideoStreamEncoder配置
  const VideoStreamEncoderSettings settings_;
  // 比特分配回调的类型
  const BitrateAllocationCallbackType allocation_cb_type_;
  // 码率控制配置
  const RateControlSettings rate_control_settings_;

  webrtc::VideoEncoderFactory::EncoderSelectorInterface* const
      encoder_selector_from_constructor_;
  std::unique_ptr<VideoEncoderFactory::EncoderSelectorInterface> const
      encoder_selector_from_factory_;
  // Pointing to either encoder_selector_from_constructor_ or
  // encoder_selector_from_factory_ but can be nullptr.
  // 编码器选择器
  VideoEncoderFactory::EncoderSelectorInterface* const encoder_selector_;
  // 视频流编码器观察者的行为
  VideoStreamEncoderObserver* const encoder_stats_observer_;
  // Adapter that avoids public inheritance of the cadence adapter's callback
  // interface.
  // 适配器,避免了公开继承节拍适配器的回调接口。
  CadenceCallback cadence_callback_{*this};
  // Frame cadence encoder adapter. Frames enter this adapter first, and it then
  // forwards them to our OnFrame method.
  // 帧节拍编码器适配器。帧首先进入这个适配器,然后它将帧转发到我们的OnFrame方法。
  std::unique_ptr<FrameCadenceAdapterInterface> frame_cadence_adapter_
      RTC_GUARDED_BY(encoder_queue_) RTC_PT_GUARDED_BY(encoder_queue_);
  // 编码器配置项
  VideoEncoderConfig encoder_config_ RTC_GUARDED_BY(encoder_queue_);
  // 编码器
  std::unique_ptr<VideoEncoder> encoder_ RTC_GUARDED_BY(encoder_queue_)
      RTC_PT_GUARDED_BY(encoder_queue_);
  bool encoder_initialized_ = false;
  // 码率分配器
  std::unique_ptr<VideoBitrateAllocator> rate_allocator_
      RTC_GUARDED_BY(encoder_queue_) RTC_PT_GUARDED_BY(encoder_queue_);
  int max_framerate_ RTC_GUARDED_BY(encoder_queue_) = -1;

  // Set when ConfigureEncoder has been called in order to lazy reconfigure the
  // encoder on the next frame.
  // 当调用了ConfigureEncoder时设置,以便在下一帧上延迟重新配置编码器。
  bool pending_encoder_reconfiguration_ RTC_GUARDED_BY(encoder_queue_) = false;
  // Set when configuration must create a new encoder object, e.g.,
  // because of a codec change.
  // 当配置必须创建一个新的编码器对象时设置,例如,由于编解码器变更。
  bool pending_encoder_creation_ RTC_GUARDED_BY(encoder_queue_) = false;
  // 编码器配置的回调函数
  absl::InlinedVector<SetParametersCallback, 2> encoder_configuration_callbacks_
      RTC_GUARDED_BY(encoder_queue_);
  // 上一帧的信息
  std::optional<VideoFrameInfo> last_frame_info_ RTC_GUARDED_BY(encoder_queue_);
  // 边界裁剪的width和height
  int crop_width_ RTC_GUARDED_BY(encoder_queue_) = 0;
  int crop_height_ RTC_GUARDED_BY(encoder_queue_) = 0;
  // 编码器目标比特率
  std::optional<uint32_t> encoder_target_bitrate_bps_
      RTC_GUARDED_BY(encoder_queue_);
  // 最大数据负载长度
  size_t max_data_payload_length_ RTC_GUARDED_BY(encoder_queue_) = 0;
  // 上一个编码器的码率设定
  std::optional<EncoderRateSettings> last_encoder_rate_settings_
      RTC_GUARDED_BY(encoder_queue_);
  // 编码器是否停止并丢帧
  bool encoder_paused_and_dropped_frame_ RTC_GUARDED_BY(encoder_queue_) = false;

  // Set to true if at least one frame was sent to encoder since last encoder
  // initialization.
  // 如果自上次编码器初始化以来至少有一帧已发送到编码器,则设置为true
  bool was_encode_called_since_last_initialization_
      RTC_GUARDED_BY(encoder_queue_) = false;
  // 编码器是否失败
  bool encoder_failed_ RTC_GUARDED_BY(encoder_queue_) = false;

  // Used to make sure incoming time stamp is increasing for every frame.
  // 用于确保每个帧的到达时间戳都在增加。
  int64_t last_captured_timestamp_ RTC_GUARDED_BY(encoder_queue_) = 0;
  // Delta used for translating between NTP and internal timestamps.
  // 用于在NTP时间戳和内部时间戳之间转换的差值。
  const int64_t delta_ntp_internal_ms_ RTC_GUARDED_BY(encoder_queue_);
  // 最后一次记录帧日志的时间戳
  int64_t last_frame_log_ms_ RTC_GUARDED_BY(encoder_queue_);
  // 已捕捉帧的数量
  int captured_frame_count_ RTC_GUARDED_BY(encoder_queue_) = 0;
  // 由于网络阻塞丢弃的帧数量
  int dropped_frame_cwnd_pushback_count_ RTC_GUARDED_BY(encoder_queue_) = 0;
  // 由于编码器阻塞丢弃的帧数量
  int dropped_frame_encoder_block_count_ RTC_GUARDED_BY(encoder_queue_) = 0;
  // 屯帧的数量(待编码帧数量)
  std::optional<VideoFrame> pending_frame_ RTC_GUARDED_BY(encoder_queue_);
  // 屯帧的时间
  int64_t pending_frame_post_time_us_ RTC_GUARDED_BY(encoder_queue_) = 0;
  // 存储了视频帧中自上次更新以来发生变化的区域
  VideoFrame::UpdateRect accumulated_update_rect_
      RTC_GUARDED_BY(encoder_queue_);
  // 指示accumulated_update_rect_是否包含有效的更新区域信息
  bool accumulated_update_rect_is_valid_ RTC_GUARDED_BY(encoder_queue_) = true;
  // 前向纠错控制
  FecControllerOverride* fec_controller_override_
      RTC_GUARDED_BY(encoder_queue_) = nullptr;
  // 记录最近一次参数更新的时间
  std::optional<int64_t> last_parameters_update_ms_
      RTC_GUARDED_BY(encoder_queue_);
  // 记录最近一次编码操作的时间戳
  std::optional<int64_t> last_encode_info_ms_ RTC_GUARDED_BY(encoder_queue_);
  // 编码器信息
  VideoEncoder::EncoderInfo encoder_info_ RTC_GUARDED_BY(encoder_queue_);
  // 编码器,存储视频编解码器的相关配置信息,包括编解码器类型、编码设置、分辨率、帧率、比特率等参数
  VideoCodec send_codec_ RTC_GUARDED_BY(encoder_queue_);
  // 帧丢弃器
  FrameDropper frame_dropper_ RTC_GUARDED_BY(encoder_queue_);
  // If frame dropper is not force disabled, frame dropping might still be
  // disabled if VideoEncoder::GetEncoderInfo() indicates that the encoder has a
  // trusted rate controller. This is determined on a per-frame basis, as the
  // encoder behavior might dynamically change.
  /*
	如果帧丢弃器没有被强制禁用,那么即使 VideoEncoder::GetEncoderInfo() 表示编码器
	拥有一个可信的速率控制器,帧丢弃可能仍然被禁用。这是逐帧决定的,因为编码器的行为可能会动态变化。
  */
  // 强制禁用frameDropper
  bool force_disable_frame_dropper_ RTC_GUARDED_BY(encoder_queue_) = false;
  // Incremented on worker thread whenever `frame_dropper_` determines that a
  // frame should be dropped. Decremented on whichever thread runs
  // OnEncodedImage(), which is only called by one thread but not necessarily
  // the worker thread.
  /*
	每当 `frame_dropper_` 确定应该丢弃一帧时,在工作线程上增加。在运行 `OnEncodedImage()` 
	的线程上减少,这个函数只由一个线程调用,但不一定是工作线程。
  */
  std::atomic<int> pending_frame_drops_{0};

  // Congestion window frame drop ratio (drop 1 in every
  // cwnd_frame_drop_interval_ frames).
  // 拥塞窗口帧丢弃比例(每 cwnd_frame_drop_interval_ 帧丢弃 1 帧)。
  std::optional<int> cwnd_frame_drop_interval_ RTC_GUARDED_BY(encoder_queue_);
  // Frame counter for congestion window frame drop.
  // 用于拥塞窗口帧丢弃的帧计数器
  int cwnd_frame_counter_ RTC_GUARDED_BY(encoder_queue_) = 0;
  // 码率调节器
  std::unique_ptr<EncoderBitrateAdjuster> bitrate_adjuster_
      RTC_GUARDED_BY(encoder_queue_);

  // TODO(sprang): Change actually support keyframe per simulcast stream, or
  // turn this into a simple bool `pending_keyframe_request_`.
  // 下一帧的类型
  std::vector<VideoFrameType> next_frame_types_ RTC_GUARDED_BY(encoder_queue_);
  // 用于处理和写入与视频帧编码相关的元数据
  FrameEncodeMetadataWriter frame_encode_metadata_writer_{this};

  // Provides video stream input states: current resolution and frame rate.
  // 处理视频流输入状态
  VideoStreamInputStateProvider input_state_provider_;
  // 视频流适应器,用于适配不同的视频流需求,包括分辨率、帧率和比特率
  const std::unique_ptr<VideoStreamAdapter> video_stream_adapter_
      RTC_GUARDED_BY(encoder_queue_);
  // Responsible for adapting input resolution or frame rate to ensure resources
  // (e.g. CPU or bandwidth) are not overused. Adding resources can occur on any
  // thread.
  // 负责调整输入分辨率或帧率,以确保资源(如CPU或带宽)不被过度使用。增加资源可以在任何线程上进行。
  // 资源自适应处理器
  std::unique_ptr<ResourceAdaptationProcessorInterface>
      resource_adaptation_processor_ RTC_GUARDED_BY(encoder_queue_);
  // 管理质量下降的偏好设置,因为在调控编码策略时,很有可能会带来视频质量的下降,例如快速算法等
  std::unique_ptr<DegradationPreferenceManager> degradation_preference_manager_
      RTC_GUARDED_BY(encoder_queue_);
  // 自适应限制
  std::vector<AdaptationConstraint*> adaptation_constraints_
      RTC_GUARDED_BY(encoder_queue_);
  // Handles input, output and stats reporting related to VideoStreamEncoder
  // specific resources, such as "encode usage percent" measurements and "QP
  // scaling". Also involved with various mitigations such as initial frame
  // dropping.
  // The manager primarily operates on the `encoder_queue_` but its lifetime is
  // tied to the VideoStreamEncoder (which is destroyed off the encoder queue)
  // and its resource list is accessible from any thread.
  /*
	处理与VideoStreamEncoder相关的输入、输出和统计报告,特别是“编码使用百分比”测量和
	“QP缩放”等资源。还涉及各种缓解措施,如初始帧丢弃。该管理器主要在`encoder_queue_`
	上操作,但其生命周期与VideoStreamEncoder(在编码器队列外销毁)相关联,其资源列表
	可以从任何线程访问。
  */
  VideoStreamEncoderResourceManager stream_resource_manager_
      RTC_GUARDED_BY(encoder_queue_);
  // 额外的资源
  std::vector<rtc::scoped_refptr<Resource>> additional_resources_
      RTC_GUARDED_BY(encoder_queue_);
  // Carries out the VideoSourceRestrictions provided by the
  // ResourceAdaptationProcessor, i.e. reconfigures the source of video frames
  // to provide us with different resolution or frame rate.
  // This class is thread-safe.
  /*
    执行由ResourceAdaptationProcessor提供的VideoSourceRestrictions,
    即重新配置视频帧的源,为我们提供不同的分辨率或帧率。这个类是线程安全的。
  */
  VideoSourceSinkController video_source_sink_controller_
      RTC_GUARDED_BY(worker_queue_);

  // Default bitrate limits in EncoderInfoSettings allowed.
  // 默认的比特率限制
  const bool default_limits_allowed_;

  // QP parser is used to extract QP value from encoded frame when that is not
  // provided by encoder.
  // QP解析器用于在编码器未提供QP值时,从编码帧中提取QP值。
  QpParser qp_parser_;
  const bool qp_parsing_allowed_;

  // The quality convergence controller is used to determine if a codec has
  // reached its target quality. This is used for screenshare to determine when
  // there's no need to continue encoding the same repeated frame.
  /*
    质量收敛控制器用于确定一个编解码器是否已经达到了其目标质量。
    这在屏幕共享中用于判断何时不需要继续编码相同的重复帧。
  */
  QualityConvergenceController quality_convergence_controller_
      RTC_GUARDED_BY(encoder_queue_);

  // Enables encoder switching on initialization failures.
  // 在初始化失败时启用编码器切换。
  bool switch_encoder_on_init_failures_;

  const std::optional<int> vp9_low_tier_core_threshold_;
  const std::optional<int> experimental_encoder_thread_limit_;

  // This is a copy of restrictions (glorified max_pixel_count) set by
  // OnVideoSourceRestrictionsUpdated. It is used to scale down encoding
  // resolution if needed when using requested_resolution.
  //
  // TODO(webrtc:14451) Split video_source_sink_controller_
  // so that ownership on restrictions/wants is kept on &encoder_queue_, that
  // these extra copies would not be needed.
  /*
	这是由OnVideoSourceRestrictionsUpdated设置的限制(实际上是最大像素计数)的副本。
	当使用requested_resolution时,如果需要,它被用来降低编码分辨率。
	
	TODO(webrtc:14451) 分离video_source_sink_controller_,以便将限制/需求的所有权
	保留在&encoder_queue_上,这样就不需要这些额外的副本了。
  */
  std::optional<VideoSourceRestrictions> latest_restrictions_
      RTC_GUARDED_BY(encoder_queue_);

  // Used to cancel any potentially pending tasks to the worker thread.
  // Refrenced by tasks running on `encoder_queue_` so need to be destroyed
  // after stopping that queue. Must be created and destroyed on
  // `worker_queue_`.
  /*
	用于取消任何可能挂起的工作任务线程任务。被在`encoder_queue_`上运行的任务引用,
	因此需要在停止该队列后销毁。必须在`worker_queue_`上创建和销毁。
  */
  ScopedTaskSafety task_safety_;
  // 编码队列
  std::unique_ptr<TaskQueueBase, TaskQueueDeleter> encoder_queue_;

  //  Required for automatic corruption detection.
  // 自动检测数据损坏
  std::unique_ptr<FrameInstrumentationGenerator>
      frame_instrumentation_generator_;
};

1.1 视频流编码器接口(VideoStreamEncoderInterface)

VideoStreamEncoder的父类是VideoStreamEncoderInterface,这里定义了一些基础的函数。类的声明位于video/video_stream_encoder_interface.h中

// This interface represents a class responsible for creating and driving the
// encoder(s) for a single video stream. It is also responsible for adaptation
// decisions related to video quality, requesting reduced frame rate or
// resolution from the VideoSource when needed.
// TODO(bugs.webrtc.org/8830): This interface is under development. Changes
// under consideration include:
//
// 1. Taking out responsibility for adaptation decisions, instead only reporting
//    per-frame measurements to the decision maker.
//
// 2. Moving responsibility for simulcast and for software fallback into this
//    class.
/*
  这个接口代表一个负责创建和驱动单个视频流的编码器(encoder)的类。
  它还负责与视频质量相关的适应性决策,例如在需要时从 VideoSource 请求降低帧率或分辨率。
  
  TODO(bugs.webrtc.org/8830): 此接口正在开发中。正在考虑的变更包括:
  1. 移除适应性决策的责任,改为仅向决策者报告每帧的测量数据。
  2. 将simulcast(同时向多个接收者发送不同质量的视频流)和软件回退的责任转移到这个类中。
*/
class VideoStreamEncoderInterface {
 public:
  // Interface for receiving encoded video frames and notifications about
  // configuration changes.
  // 接收编码后的视频帧以及关于配置变更通知的接口
  class EncoderSink : public EncodedImageCallback {
   public:
    // 检测到编码器配置发生变化
    virtual void OnEncoderConfigurationChanged(
        std::vector<VideoStream> streams,
        bool is_svc,
        VideoEncoderConfig::ContentType content_type,
        int min_transmit_bitrate_bps) = 0;
    // 检测到码率分配发生变化
    virtual void OnBitrateAllocationUpdated(
        const VideoBitrateAllocation& allocation) = 0;
    // 检测到视频层级分配发生变化
    virtual void OnVideoLayersAllocationUpdated(
        VideoLayersAllocation allocation) = 0;
  };

  virtual ~VideoStreamEncoderInterface() = default;

  // If the resource is overusing, the VideoStreamEncoder will try to reduce
  // resolution or frame rate until no resource is overusing.
  // TODO(https://crbug.com/webrtc/11565): When the ResourceAdaptationProcessor
  // is moved to Call this method could be deleted altogether in favor of
  // Call-level APIs only
  
  // 如果资源使用过量,VideoStreamEncoder 将尝试降低分辨率或帧率,直到没有资源使用过量为止。
  // TODO(https://crbug.com/webrtc/11565): 当 ResourceAdaptationProcessor 被移动到 
  // Call 时,这个方法可能会被完全删除,转而只使用 Call 级别的 API。
  virtual void AddAdaptationResource(rtc::scoped_refptr<Resource> resource) = 0;
  virtual std::vector<rtc::scoped_refptr<Resource>>
  GetAdaptationResources() = 0;

  // Sets the source that will provide video frames to the VideoStreamEncoder's
  // OnFrame method. `degradation_preference` control whether or not resolution
  // or frame rate may be reduced. The VideoStreamEncoder registers itself with
  // `source`, and signals adaptation decisions to the source in the form of
  // VideoSinkWants.
  // TODO(bugs.webrtc.org/14246): When adaptation logic is extracted from this
  // class, it no longer needs to know the source.
  /*
	设置提供视频帧给 VideoStreamEncoder 的 OnFrame 方法的源。`degradation_preference` 
	控制是否允许降低分辨率或帧率。VideoStreamEncoder 在 `source` 中注册自己,并以 
	VideoSinkWants 的形式向源发出适应性决策信号。
    
    TODO(bugs.webrtc.org/14246): 当适应性逻辑从这个类中提取出来时,它就不再需要知道源。
  */
  virtual void SetSource(
      rtc::VideoSourceInterface<VideoFrame>* source,
      const DegradationPreference& degradation_preference) = 0;

  // Sets the `sink` that gets the encoded frames. `rotation_applied` means
  // that the source must support rotation. Only set `rotation_applied` if the
  // remote side does not support the rotation extension.
  /*
	设置接收编码帧的 `sink`。`rotation_applied` 表示源必须支持旋转。
	只有在远端不支持旋转扩展时才设置 `rotation_applied`。
  */
  virtual void SetSink(EncoderSink* sink, bool rotation_applied) = 0;

  // Sets an initial bitrate, later overriden by OnBitrateUpdated. Mainly
  // affects the resolution of the initial key frame: If incoming frames are
  // larger than reasonable for the start bitrate, and scaling is enabled,
  // VideoStreamEncoder asks the source to scale down and drops a few initial
  // frames.
  // TODO(nisse): This is a poor interface, and mixes bandwidth estimation and
  // codec configuration in an undesired way. For the actual send bandwidth, we
  // should always be somewhat conservative, but we may nevertheless want to let
  // the application configure a more optimistic quality for the initial
  // resolution. Should be replaced by a construction time setting.
  /*
	设置初始比特率,后续会被 OnBitrateUpdated 方法覆盖。主要影响初始关键帧的分辨率:
	如果传入的帧比初始比特率合理的大小要大,并且缩放被启用,VideoStreamEncoder 
	会请求源缩小尺寸并丢弃一些初始帧。
	
	TODO(nisse): 这是一个设计不佳的接口,它以不期望的方式混合了带宽估计和编解码器配置。
	对于实际的发送带宽,我们应该始终保持一定的保守性,但我们可能仍然希望允许应用程序为
	初始分辨率配置一个更乐观的质量。应该被构造时的设置所取代。
  */
  virtual void SetStartBitrate(int start_bitrate_bps) = 0;

  // Request a key frame. Used for signalling from the remote receiver with
  // no arguments and for RTCRtpSender.generateKeyFrame with a list of
  // rids/layers.
  /*
	请求一个关键帧。用于从远程接收方发出信号,无需参数,
	以及用于 RTCRtpSender.generateKeyFrame 方法,该方法带有一系列 rids/layers。
  */
  virtual void SendKeyFrame(const std::vector<VideoFrameType>& layers = {}) = 0;

  // Inform the encoder that a loss has occurred.
  // 通知编码器发生了丢包
  virtual void OnLossNotification(
      const VideoEncoder::LossNotification& loss_notification) = 0;

  // Set the currently estimated network properties. A `target_bitrate`
  // of zero pauses the encoder.
  // `stable_target_bitrate` is a filtered version of `target_bitrate`. It  is
  // always less or equal to it. It can be used to avoid rapid changes of
  // expensive encoding settings, such as resolution.
  // `link_allocation` is the bandwidth available for this video stream on the
  // network link. It is always at least `target_bitrate` but may be higher
  // if we are not network constrained.
  /*
	设置当前估计的网络属性。`target_bitrate` 为零时会暂停编码器。 `stable_target_bitrate` 
	是 `target_bitrate` 的一个过滤版本。它总是小于或等于 `target_bitrate`。它可以用来避免
	昂贵编码设置(如分辨率)的快速变化。`link_allocation` 是网络链路上可用于此视频流的带宽。
	它总是至少为 `target_bitrate`,但如果我们不受网络限制,可能会更高。
  */
  virtual void OnBitrateUpdated(DataRate target_bitrate,
                                DataRate stable_target_bitrate,
                                DataRate link_allocation,
                                uint8_t fraction_lost,
                                int64_t round_trip_time_ms,
                                double cwnd_reduce_ratio) = 0;

  // Set a FecControllerOverride, through which the encoder may override
  // decisions made by FecController.
  /*
	设置一个 FecControllerOverride,通过它编码器可以覆盖 FecController 所做的决策
  */
  virtual void SetFecControllerOverride(
      FecControllerOverride* fec_controller_override) = 0;

  // Creates and configures an encoder with the given `config`. The
  // `max_data_payload_length` is used to support single NAL unit
  // packetization for H.264.
  /*
	使用给定的 `config` 创建并配置一个编码器。`max_data_payload_length` 用于支持 H.264 
	的单个 NAL 单元打包。
  */ 
  virtual void ConfigureEncoder(VideoEncoderConfig config,
                                size_t max_data_payload_length) = 0;
  virtual void ConfigureEncoder(VideoEncoderConfig config,
                                size_t max_data_payload_length,
                                SetParametersCallback callback) = 0;

  // Permanently stop encoding. After this method has returned, it is
  // guaranteed that no encoded frames will be delivered to the sink.
  virtual void Stop() = 0;
};

1.2 资源类(Resource)

上面关于Resource类的声明位于api/adaptation/resource.h中,这里的可以表示帧率,码率等编码信息,这个类存在的意义是对这些信息进行监控,如果某个资源超出了预期范围,需要将这个资源进行调控。

// A Resource monitors an implementation-specific resource. It may report
// kOveruse or kUnderuse when resource usage is high or low enough that we
// should perform some sort of mitigation to fulfil the resource's constraints.
//
// The methods on this interface are invoked on the adaptation task queue.
// Resource usage measurements may be performed on an any task queue.
//
// The Resource is reference counted to prevent use-after-free when posting
// between task queues. As such, the implementation MUST NOT make any
// assumptions about which task queue Resource is destructed on.
/*
  1.一个资源监控特定实现的资源。当资源使用量足够高或足够低,以至于我们应该执行某种缓解
  措施以满足资源的约束时,它可能会报告kOveruse(过载)或kUnderuse(欠载)。

  2.这个接口上的方法在适应性任务队列上被调用。资源使用量的测量可以在任何任务队列上执行。

  3.资源被引用计数,以防止在任务队列之间发布时出现使用后释放的问题。因此,
  实现必须不对资源被销毁的任务队列做任何假设。
*/
class RTC_EXPORT Resource : public RefCountInterface {
 public:
  Resource();
  // Destruction may happen on any task queue.
  ~Resource() override;

  virtual std::string Name() const = 0;
  // The `listener` may be informed of resource usage measurements on any task
  // queue, but not after this method is invoked with the null argument.
  virtual void SetResourceListener(ResourceListener* listener) = 0;
};

// ResourceListenter和ResourceUsageState的声明如下
enum class ResourceUsageState {
  // Action is needed to minimze the load on this resource.
  // 过载,需要降低这个资源
  kOveruse,
  // Increasing the load on this resource is desired, if possible.
  // 欠载,需要增加这个资源
  kUnderuse,
};

RTC_EXPORT const char* ResourceUsageStateToString(
    ResourceUsageState usage_state);

class RTC_EXPORT ResourceListener {
 public:
  virtual ~ResourceListener();
  // 评估当前资源的状态
  virtual void OnResourceUsageStateMeasured(
      rtc::scoped_refptr<Resource> resource,
      ResourceUsageState usage_state) = 0;
};

1.3 已编码图像的回调(EncodedImageCallback)

EncodedImageCallback用于图像已经编码之后的回调,声明位于api/video_codecs/video_encoder.h中

class RTC_EXPORT EncodedImageCallback {
 public:
  virtual ~EncodedImageCallback() {}

  struct Result {
    enum Error {
      OK,

      // Failed to send the packet.
      ERROR_SEND_FAILED,
    };

    explicit Result(Error error) : error(error) {}
    Result(Error error, uint32_t frame_id) : error(error), frame_id(frame_id) {}

    Error error;

    // Frame ID assigned to the frame. The frame ID should be the same as the ID
    // seen by the receiver for this frame. RTP timestamp of the frame is used
    // as frame ID when RTP is used to send video. Must be used only when
    // error=OK.
    /*
		分配给帧的帧ID。该帧ID应与接收方看到的该帧的ID相同。当使用RTP发送视频时,
		帧的RTP时间戳被用作帧ID。仅当错误为OK时必须使用。
	*/
    uint32_t frame_id = 0;

    // Tells the encoder that the next frame is should be dropped.
    // 告诉编码器下一个帧应该被丢弃。
    bool drop_next_frame = false;
  };

  // Used to signal the encoder about reason a frame is dropped.
  // kDroppedByMediaOptimizations - dropped by MediaOptimizations (for rate
  // limiting purposes).
  // kDroppedByEncoder - dropped by encoder's internal rate limiter.
  // TODO(bugs.webrtc.org/10164): Delete this enum? It duplicates the more
  // general VideoStreamEncoderObserver::DropReason. Also,
  // kDroppedByMediaOptimizations is not produced by any encoder, but by
  // VideoStreamEncoder.
  /*
	用于向编码器发出信号,说明帧被丢弃的原因。
    kDroppedByMediaOptimizations: 由 MediaOptimizations 丢弃(出于速率限制的目的)。
    kDroppedByEncoder: 由编码器的内部速率限制器丢弃。
    
    TODO(bugs.webrtc.org/10164): 删除这个枚举?它与更通用的 VideoStreamEncoderObserver::DropReason 重复。此外,
  	kDroppedByMediaOptimizations 不是由任何编码器产生的,而是由 VideoStreamEncoder 产生的。
  */
  enum class DropReason : uint8_t {
    kDroppedByMediaOptimizations,
    kDroppedByEncoder
  };

  // Callback function which is called when an image has been encoded.
  // 在一帧被编码之后会被调用
  virtual Result OnEncodedImage(
      const EncodedImage& encoded_image,
      const CodecSpecificInfo* codec_specific_info) = 0;
  // 丢弃一帧
  virtual void OnDroppedFrame(DropReason /* reason */) {}
};

1.4 视频资源监听器(VideoSourceRestrictionsListener)

// The listener is responsible for carrying out the reconfiguration of the video
// source such that the VideoSourceRestrictions are fulfilled.
// 监听器负责执行视频源的重新配置,以满足 VideoSourceRestrictions 的要求。
class VideoSourceRestrictionsListener {
 public:
  virtual ~VideoSourceRestrictionsListener();

  // The `restrictions` are filtered by degradation preference but not the
  // `adaptation_counters`, which are currently only reported for legacy stats
  // calculation purposes.
  /*
	`restrictions` 会根据降级偏好进行过滤,但 `adaptation_counters` 不会,
	它们目前仅用于传统统计计算目的的报告。
  */
  virtual void OnVideoSourceRestrictionsUpdated(
      VideoSourceRestrictions restrictions,
      const VideoAdaptationCounters& adaptation_counters,
      rtc::scoped_refptr<Resource> reason,
      const VideoSourceRestrictions& unfiltered_restrictions) = 0;
};

总体来讲,VideoStreamEncoder完成了进行视频编码的第一道工序,包括获取视频帧,根据编码情况进行码率调整,根据网络情况丢帧等等,由于涵盖内容太广泛,一些其他很重要的类没有分析,例如DegradationPreferenceManager、QpParser等,后续单独记录


http://www.kler.cn/a/383896.html

相关文章:

  • 软件开发项目管理:实现目标的实用指南
  • GPT原理;ChatGPT 等类似的问答系统工作流程如下;当用户向 ChatGPT 输入一个问题后:举例说明;ChatGPT不是通过索引搜索的传统知识库
  • 【简信CRM-注册安全分析报告】
  • 使用亚马逊 S3 连接器为 PyTorch 和 MinIO 创建地图式数据集
  • HTML 标签属性——<a>、<img>、<form>、<input>、<table> 标签属性详解
  • 边缘计算网关如何打造智慧变电站
  • 【深度学习滑坡制图|论文解读3】基于融合CNN-Transformer网络和深度迁移学习的遥感影像滑坡制图方法
  • C语言 -- qsort的简单使用
  • 【WPF】把一个Window放在左上角/右上角顶格显示
  • c# 深度模型入门
  • 【K8S问题系列 |1 】Kubernetes 中 NodePort 类型的 Service 无法访问【已解决】
  • Docker compose 部署MongoDB
  • Python OpenCV图片读取和保存
  • CSS弹性布局:灵活布局的终极指南
  • 使用Python多线程抓取某图网数据并下载图片
  • Ubuntu 安装 redis
  • 前端基础-html-注册界面
  • 前端Web用户 token 持久化
  • java的类加载机制的学习
  • 最新kubernetes搭建(k8s)(已成功搭建)
  • CSS中的 BFC,是啥呀?
  • NetCore使用Aop和内存缓存对接口、方法进行数据缓存
  • SpringSecurity(三)SpringBoot集成SpringSecurity实现认证授权
  • 软考:性能测试的几个方面
  • 组态软件的概念
  • 基于单片机的变频空调系统设计(论文+源码)