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
media / gpu / windows / mf_video_encoder_util.h [blame]
// Copyright 2024 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_WINDOWS_MF_VIDEO_ENCODER_UTIL_H_
#define MEDIA_GPU_WINDOWS_MF_VIDEO_ENCODER_UTIL_H_
#include <codecapi.h>
#include <mfapi.h>
#include <mfidl.h>
#include <stdint.h>
#include <wrl/client.h>
#include <vector>
#include "base/containers/fixed_flat_set.h"
#include "gpu/config/gpu_driver_bug_workarounds.h"
#include "media/base/video_codecs.h"
#include "media/base/video_types.h"
#include "media/gpu/buildflags.h"
#include "media/gpu/windows/d3d_com_defs.h"
#include "media/media_buildflags.h"
#include "ui/gfx/geometry/size.h"
namespace media {
struct FramerateAndResolution {
uint32_t frame_rate;
gfx::Size resolution;
};
enum class DriverVendor { kOther, kNvidia, kIntel, kAMD, kQualcomm };
static constexpr size_t kDefaultFrameRateNumerator = 30;
static constexpr size_t kDefaultFrameRateDenominator = 1;
// The default supported max framerate and resolution.
static constexpr FramerateAndResolution kDefaultMaxFramerateAndResolution = {
kDefaultFrameRateNumerator / kDefaultFrameRateDenominator,
gfx::Size(1920, 1080)};
// The default supported min resolution.
static constexpr gfx::Size kDefaultMinResolution(32, 32);
// For H.264, some NVIDIA GPUs may report `MF_VIDEO_MAX_MB_PER_SEC` value equals
// to `6799902`, resulting chromium think 8K & 30fps is supported, and some
// Intel GPUs only support level 5.2. Since most devices only support up to 4K,
// so we set level 5.2 as the max allowed level here to limit max resolution and
// framerate combination can only go up to 2K & 172fps, or 4K & 64fps.
static constexpr FramerateAndResolution kLegacy2KMaxFramerateAndResolution = {
172, gfx::Size(1920, 1080)};
static constexpr FramerateAndResolution kLegacy4KMaxFramerateAndResolution = {
64, gfx::Size(3840, 2160)};
// For H.265/AV1, some NVIDIA GPUs may report `MF_VIDEO_MAX_MB_PER_SEC` value
// equals to `7255273`, resulting chromium think 2K & 880fps is supported. Since
// the max level of H.265/AV1 (6.2/6.3) do not allow framerate >= 300fps, so we
// set level 6.2/6.3 as the max allowed level here and limit max resolution and
// framerate combination can only go up to 2K/4K & 300fps, 8K & 128fps.
static constexpr FramerateAndResolution kModern2KMaxFramerateAndResolution = {
300, gfx::Size(1920, 1080)};
static constexpr FramerateAndResolution kModern4KMaxFramerateAndResolution = {
300, gfx::Size(3840, 2160)};
static constexpr FramerateAndResolution kModern8KMaxFramerateAndResolution = {
128, gfx::Size(7680, 4320)};
static constexpr CLSID kIntelAV1HybridEncoderCLSID = {
0x62c053ce,
0x5357,
0x4794,
{0x8c, 0x5a, 0xfb, 0xef, 0xfe, 0xff, 0xb8, 0x2d}};
static constexpr auto kSupportedPixelFormats =
base::MakeFixedFlatSet<VideoPixelFormat>(
{PIXEL_FORMAT_I420, PIXEL_FORMAT_NV12});
static constexpr auto kSupportedPixelFormatsD3DVideoProcessing =
base::MakeFixedFlatSet<VideoPixelFormat>(
{PIXEL_FORMAT_I420, PIXEL_FORMAT_NV12, PIXEL_FORMAT_YV12,
PIXEL_FORMAT_NV21, PIXEL_FORMAT_ARGB, PIXEL_FORMAT_XRGB,
PIXEL_FORMAT_ABGR, PIXEL_FORMAT_XBGR});
static constexpr int kH26xMaxQp = 51;
static constexpr uint64_t kVP9MaxQIndex = 255;
static constexpr uint64_t kAV1MaxQIndex = 255;
// Quantizer parameter used in libvpx vp9 rate control, whose range is 0-63.
// These are based on WebRTC's defaults, cite from
// third_party/webrtc/media/engine/webrtc_video_engine.h.
static constexpr uint8_t kVP9MinQuantizer = 2;
static constexpr uint8_t kVP9MaxQuantizer = 56;
// Default value from
// //third_party/webrtc/modules/video_coding/codecs/av1/libaom_av1_encoder.cc,
static constexpr uint8_t kAV1MinQuantizer = 10;
// //third_party/webrtc/media/engine/webrtc_video_engine.h.
static constexpr uint8_t kAV1MaxQuantizer = 56;
// The range for the quantization parameter is determined by examining the
// estimated QP values from the SW bitrate controller in various encoding
// scenarios.
static constexpr uint8_t kH264MinQuantizer = 16;
static constexpr uint8_t kH264MaxQuantizer = 51;
#if BUILDFLAG(ENABLE_PLATFORM_HEVC)
// For H.265, ideally we may reuse Min/MaxQp for H.264 from
// media/gpu/vaapi/h264_vaapi_video_encoder_delegate.cc. However
// test shows most of the drivers require a min QP of 10 to reach
// target bitrate especially at low resolution.
static constexpr uint8_t kH265MinQuantizer = 10;
static constexpr uint8_t kH265MaxQuantizer = 42;
#endif // BUILDFLAG(ENABLE_PLATFORM_HEVC)
// Converts AV1/VP9 qindex (0-255) to the quantizer parameter input in MF
// AVEncVideoEncodeQP.
uint8_t QindextoAVEncQP(VideoCodec codec, uint8_t q_index);
// Converts AV1/VP9 AVEncVideoEncodeQP values to qindex (0-255) range.
uint8_t AVEncQPtoQindex(VideoCodec codec, uint8_t avenc_qp);
// Returns true if |qp| is a valid quantizer parameter for |codec|.
bool IsValidQp(VideoCodec codec, uint64_t qp);
// Returns the maximum quantizer value for |codec|.
uint8_t GetMaxQuantizer(VideoCodec codec);
// Converts VideoCodecProfile to eAVEncH264VProfile.
eAVEncH264VProfile GetH264VProfile(VideoCodecProfile profile,
bool is_constrained_h264);
// Converts VideoCodecProfile to eAVEncVP9VProfile.
eAVEncVP9VProfile GetVP9VProfile(VideoCodecProfile profile);
// Converts VideoCodecProfile to eAVEncAV1VProfile.
eAVEncH265VProfile GetHEVCProfile(VideoCodecProfile profile);
// Returns the driver vendor of the given |encoder|.
DriverVendor GetDriverVendor(IMFActivate* encoder);
// Get the maximum number of temporal layers supported by the given |encoder|
// from |vendor|, taking into account |workarounds|.
int GetMaxTemporalLayerVendorLimit(
DriverVendor vendor,
VideoCodec codec,
const gpu::GpuDriverBugWorkarounds& workarounds);
// Enumeration of HMFT without specifying LUID.
std::vector<Microsoft::WRL::ComPtr<IMFActivate>>
EnumerateHardwareEncodersLegacy(VideoCodec codec);
// Adapter-based enumeration of HMFT. The adapter with lower index is enumerated
// first.
std::vector<Microsoft::WRL::ComPtr<IMFActivate>> EnumerateHardwareEncoders(
VideoCodec codec);
// Get the maximum supported framerate and resolution combinations for the given
// codec and HMFT. If |allow_set_output_type| is true, it will try to set the
// output type to get the maximum supported framerate and resolution; otherwise,
// we merely query the maximum supported macroblocks per second for calculation.
std::vector<FramerateAndResolution> GetMaxFramerateAndResolutionsFromMFT(
VideoCodec codec,
IMFTransform* encoder,
bool allow_set_output_type);
// Get the minimum supported encoding resolution for the given codec and vendor.
gfx::Size GetMinResolution(VideoCodec codec, DriverVendor vendor);
// Get the hash of the CLSID of the IMFActivate instance.
size_t GetMFTGuidHash(IMFActivate* activate);
} // namespace media
#endif // MEDIA_GPU_WINDOWS_MF_VIDEO_ENCODER_UTIL_H_