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
media / gpu / vaapi / vp9_vaapi_video_encoder_delegate.h [blame]
// Copyright 2019 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_VP9_VAAPI_VIDEO_ENCODER_DELEGATE_H_
#define MEDIA_GPU_VAAPI_VP9_VAAPI_VIDEO_ENCODER_DELEGATE_H_
#include <memory>
#include <utility>
#include <vector>
#include "media/base/video_bitrate_allocation.h"
#include "media/gpu/vaapi/vaapi_video_encoder_delegate.h"
#include "media/gpu/vp9_picture.h"
#include "media/gpu/vp9_reference_frame_vector.h"
#include "media/parsers/vp9_parser.h"
#include "third_party/libvpx/source/libvpx/vp9/ratectrl_rtc.h"
namespace media {
class VaapiWrapper;
class SVCLayers;
// Wrapper for the libVPX VP9 rate controller that allows us to override methods
// for unit testing.
class VP9RateControlWrapper {
public:
static std::unique_ptr<VP9RateControlWrapper> Create(
const libvpx::VP9RateControlRtcConfig& config);
VP9RateControlWrapper();
explicit VP9RateControlWrapper(
std::unique_ptr<libvpx::VP9RateControlRTC> impl);
virtual ~VP9RateControlWrapper();
virtual void UpdateRateControl(
const libvpx::VP9RateControlRtcConfig& rate_control_config);
virtual libvpx::FrameDropDecision ComputeQP(
const libvpx::VP9FrameParamsQpRTC& frame_params);
virtual int GetQP() const;
// GetLoopfilterLevel() needs to be called after ComputeQP().
virtual int GetLoopfilterLevel() const;
virtual void PostEncodeUpdate(
uint64_t encoded_frame_size,
const libvpx::VP9FrameParamsQpRTC& frame_params);
private:
const std::unique_ptr<libvpx::VP9RateControlRTC> impl_;
};
class VP9VaapiVideoEncoderDelegate : public VaapiVideoEncoderDelegate {
public:
struct EncodeParams {
EncodeParams();
// Produce a keyframe at least once per this many frames.
size_t kf_period_frames;
// Bitrate allocation in bps.
VideoBitrateAllocation bitrate_allocation;
// Framerate in FPS.
uint32_t framerate;
// Quantization parameter. They are vp9 ac/dc indices and their ranges are
// 0-255.
uint8_t min_qp;
uint8_t max_qp;
// The rate controller drop frame threshold. 0-100 as this is percentage.
uint8_t drop_frame_thresh = 0;
// The encoding content is a screen content.
bool is_screen = false;
bool error_resilident_mode = false;
};
VP9VaapiVideoEncoderDelegate(scoped_refptr<VaapiWrapper> vaapi_wrapper,
base::RepeatingClosure error_cb);
VP9VaapiVideoEncoderDelegate(const VP9VaapiVideoEncoderDelegate&) = delete;
VP9VaapiVideoEncoderDelegate& operator=(const VP9VaapiVideoEncoderDelegate&) =
delete;
~VP9VaapiVideoEncoderDelegate() 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;
private:
friend class VP9VaapiVideoEncoderDelegateTest;
friend class VaapiVideoEncodeAcceleratorTest;
void set_rate_ctrl_for_testing(
std::unique_ptr<VP9RateControlWrapper> rate_ctrl);
bool ApplyPendingUpdateRates();
PrepareEncodeJobResult PrepareEncodeJob(EncodeJob& encode_job) override;
BitstreamBufferMetadata GetMetadata(const EncodeJob& encode_job,
size_t payload_size) override;
void BitrateControlUpdate(const BitstreamBufferMetadata& metadata) override;
Vp9FrameHeader GetDefaultFrameHeader(const bool keyframe) const;
PrepareEncodeJobResult SetFrameHeader(
bool keyframe,
VP9Picture* picture,
std::array<bool, kVp9NumRefsPerFrame>* ref_frames_used);
void UpdateReferenceFrames(scoped_refptr<VP9Picture> picture);
bool SubmitFrameParameters(
EncodeJob& job,
const EncodeParams& encode_params,
scoped_refptr<VP9Picture> pic,
const Vp9ReferenceFrameVector& ref_frames,
const std::array<bool, kVp9NumRefsPerFrame>& ref_frames_used);
gfx::Size visible_size_;
gfx::Size coded_size_; // Macroblock-aligned.
// Frame count since last keyframe, reset to 0 every keyframe period.
size_t frame_num_ = 0;
size_t ref_frame_index_ = 0;
EncodeParams current_params_;
Vp9ReferenceFrameVector reference_frames_;
std::unique_ptr<SVCLayers> svc_layers_;
std::optional<std::pair<VideoBitrateAllocation, uint32_t>>
pending_update_rates_;
std::unique_ptr<VP9RateControlWrapper> rate_ctrl_;
std::optional<base::TimeDelta> dropped_superframe_timestamp_;
// TODO(b/297226972): Remove the workaround once the iHD driver is fixed.
bool is_last_encoded_key_frame_ = false;
};
} // namespace media
#endif // MEDIA_GPU_VAAPI_VP9_VAAPI_VIDEO_ENCODER_DELEGATE_H_