910e62b5创建于 1月15日历史提交
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MEDIA_GPU_VAAPI_H264_VAAPI_VIDEO_ENCODER_DELEGATE_H_
#define MEDIA_GPU_VAAPI_H264_VAAPI_VIDEO_ENCODER_DELEGATE_H_

#include <optional>

#include "base/containers/circular_deque.h"
#include "media/filters/h26x_annex_b_bitstream_builder.h"
#include "media/gpu/h264_dpb.h"
#include "media/gpu/h264_ratectrl_rtc.h"
#include "media/gpu/vaapi/vaapi_video_encoder_delegate.h"

namespace media {
class VaapiWrapper;

struct H264RateControllerSettings;
typedef H264RateControllerSettings H264RateControlConfigRTC;
struct H264FrameParamsRTC;
// Wrapper for the H264RateCtrlRTC that allows us to override methods for unit
// testing.
class H264RateControlWrapper {
 public:
  static std::unique_ptr<H264RateControlWrapper> Create(
      const H264RateControlConfigRTC& config);

  virtual ~H264RateControlWrapper();

  virtual void UpdateRateControl(const H264RateControlConfigRTC& config);
  virtual H264RateCtrlRTC::FrameDropDecision ComputeQP(
      const H264FrameParamsRTC& frame_params);
  //  GetQP() needs to be called after ComputeQP() to get the current frame's
  //  computed QP.
  virtual int GetQP() const;
  virtual void PostEncodeUpdate(uint64_t encoded_frame_size,
                                const H264FrameParamsRTC& frame_params);

 protected:
  explicit H264RateControlWrapper(std::unique_ptr<H264RateCtrlRTC> impl);
  // For a mock class in unit tests.
  H264RateControlWrapper();

 private:
  const std::unique_ptr<H264RateCtrlRTC> impl_;
};

// This class provides an H264 encoder functionality, generating stream headers,
// managing encoder state, reference frames, and other codec parameters, while
// requiring support from an Accelerator to encode frame data based on these
// parameters.
//
// This class must be created, called and destroyed on a single sequence.
//
// Names used in documentation of this class refer directly to naming used
// in the H.264 specification (http://www.itu.int/rec/T-REC-H.264).
class H264VaapiVideoEncoderDelegate : public VaapiVideoEncoderDelegate {
 public:
  struct EncodeParams {
    EncodeParams();

    VideoBitrateAllocation bitrate_allocation;

    // Framerate in FPS.
    uint32_t framerate;

    // Bitrate window size in ms.
    uint32_t cpb_window_size_ms;

    // Bitrate window size in bits.
    unsigned int cpb_size_bits;

    // Quantization parameter. Their ranges are 0-51.
    uint8_t initial_qp;
    uint8_t min_qp;
    uint8_t max_qp;

    // Maximum Number of Reference frames.
    size_t max_num_ref_frames;

    // Maximum size of reference picture list 0.
    size_t max_ref_pic_list0_size;

    // Type of content being encoded.
    VideoEncodeAccelerator::Config::ContentType content_type =
        VideoEncodeAccelerator::Config::ContentType::kCamera;
  };

  H264VaapiVideoEncoderDelegate(scoped_refptr<VaapiWrapper> vaapi_wrapper,
                                base::RepeatingClosure error_cb);

  H264VaapiVideoEncoderDelegate(const H264VaapiVideoEncoderDelegate&) = delete;
  H264VaapiVideoEncoderDelegate& operator=(
      const H264VaapiVideoEncoderDelegate&) = delete;

  ~H264VaapiVideoEncoderDelegate() override;

  // VaapiVideoEncoderDelegate implementation.
  bool Initialize(const VideoEncodeAccelerator::Config& config,
                  const VaapiVideoEncoderDelegate::Config& ave_config) override;
  bool UpdateRates(const VideoBitrateAllocation& bitrate_allocation,
                   uint32_t framerate) override;
  gfx::Size GetCodedSize() const override;
  size_t GetMaxNumOfRefFrames() const override;
  std::vector<gfx::Size> GetSVCLayerResolutions() override;

  static bool UseSoftwareRateController(
      const VideoEncodeAccelerator::Config& config);

 private:
  class TemporalLayers;

  friend class H264VaapiVideoEncoderDelegateTest;

  PrepareEncodeJobResult PrepareEncodeJob(EncodeJob& encode_job) override;
  BitstreamBufferMetadata GetMetadata(const EncodeJob& encode_job,
                                      size_t payload_size) override;
  void BitrateControlUpdate(const BitstreamBufferMetadata& metadata) override;

  // Fill current_sps_ and current_pps_ with current encoding state parameters.
  void UpdateSPS();
  void UpdatePPS();

  // Generate packed slice header from |pic_param|, |slice_param| and |pic|.
  void GeneratePackedSliceHeader(
      H26xAnnexBBitstreamBuilder& packed_slice_header,
      const VAEncPictureParameterBufferH264& pic_param,
      const VAEncSliceParameterBufferH264& sliice_param,
      const H264Picture& pic);

  // Check if |bitrate| and |framerate| and current coded size are supported by
  // current profile and level.
  bool CheckConfigValidity(uint32_t bitrate, uint32_t framerate);

  bool SubmitPackedHeaders(const H26xAnnexBBitstreamBuilder& packed_sps,
                           const H26xAnnexBBitstreamBuilder& packed_pps);

  bool SubmitFrameParameters(
      EncodeJob& job,
      const H264VaapiVideoEncoderDelegate::EncodeParams& encode_params,
      const H264SPS& sps,
      const H264PPS& pps,
      scoped_refptr<H264Picture> pic,
      const base::circular_deque<scoped_refptr<H264Picture>>& ref_pic_list0,
      const std::optional<size_t>& ref_frame_index,
      const std::optional<int>& qp);

  // Inject instance of |rate_ctrl_| for testing purposes.
  void set_rate_ctrl_for_testing(
      std::unique_ptr<H264RateControlWrapper> rate_ctrl);

  // Current SPS, PPS and their packed versions. Packed versions are NALUs
  // in AnnexB format *without* emulation prevention three-byte sequences
  // (those are expected to be added by the client as needed).
  H264SPS current_sps_;
  std::optional<H26xAnnexBBitstreamBuilder> packed_sps_;
  H264PPS current_pps_;
  std::optional<H26xAnnexBBitstreamBuilder> packed_pps_;
  bool submit_packed_headers_;

  // Current encoding parameters being used.
  EncodeParams curr_params_;

  // H264 profile currently used.
  VideoCodecProfile profile_ = VIDEO_CODEC_PROFILE_UNKNOWN;

  // H264 level currently used.
  uint8_t level_ = 0;

  // Current visible and coded sizes in pixels.
  gfx::Size visible_size_;
  gfx::Size coded_size_;

  // Width/height in macroblocks.
  unsigned int mb_width_ = 0;
  unsigned int mb_height_ = 0;

  // The number of encoded frames. Resets to 0 on IDR frame.
  unsigned int num_encoded_frames_ = 0;
  // frame_num (spec section 7.4.3).
  unsigned int frame_num_ = 0;

  // idr_pic_id (spec section 7.4.3) to be used for the next frame.
  unsigned int idr_pic_id_ = 0;

  // True if encoding parameters have changed that affect decoder process, then
  // we need to submit a keyframe with updated parameters.
  bool encoding_parameters_changed_ = false;

  // Currently active reference frames.
  // RefPicList0 per spec (spec section 8.2.4.2).
  base::circular_deque<scoped_refptr<H264Picture>> ref_pic_list0_;

  uint8_t num_temporal_layers_ = 1;

  std::unique_ptr<H264RateControlWrapper> rate_ctrl_;
};

}  // namespace media

#endif  // MEDIA_GPU_VAAPI_H264_VAAPI_VIDEO_ENCODER_DELEGATE_H_