7#include "vaapiutils_p.h"
8#include <logging_vaapi.h>
13#include <drm_fourcc.h>
20VaapiUtils::VaapiUtils(VaapiUtils::Private)
22 int max_devices = drmGetDevices2(0,
nullptr, 0);
23 if (max_devices <= 0) {
24 qCWarning(PIPEWIREVAAPI_LOGGING) <<
"drmGetDevices2() has not found any devices (errno=" << -max_devices <<
")";
28 std::vector<drmDevicePtr> devices(max_devices);
29 int ret = drmGetDevices2(0, devices.data(), max_devices);
31 qCWarning(PIPEWIREVAAPI_LOGGING) <<
"drmGetDevices2() returned an error " << ret;
35 for (
const drmDevicePtr &device : devices) {
36 if (device->available_nodes & (1 << DRM_NODE_RENDER)) {
37 QByteArray fullPath = device->nodes[DRM_NODE_RENDER];
38 if (supportsH264(fullPath)) {
39 m_devicePath = fullPath;
45 drmFreeDevices(devices.data(), ret);
47 if (m_devicePath.isEmpty()) {
48 qCWarning(PIPEWIREVAAPI_LOGGING) <<
"DRM device not found";
52VaapiUtils::~VaapiUtils()
56bool VaapiUtils::supportsProfile(VAProfile profile)
58 if (m_devicePath.isEmpty()) {
65 VADisplay vaDpy = openDevice(&drmFd, m_devicePath);
70 ret = supportsProfile(profile, vaDpy, m_devicePath);
72 closeDevice(&drmFd, vaDpy);
77bool VaapiUtils::supportsH264(
const QByteArray &path)
const
86 VADisplay vaDpy = openDevice(&drmFd, path);
91 const char *driver = vaQueryVendorString(vaDpy);
92 qCWarning(PIPEWIREVAAPI_LOGGING) <<
"VAAPI:" << driver <<
"in use for device" <<
path;
94 ret = supportsProfile(VAProfileH264ConstrainedBaseline, vaDpy, path) || supportsProfile(VAProfileH264Main, vaDpy, path)
95 || supportsProfile(VAProfileH264High, vaDpy, path);
97 querySizeConstraints(vaDpy);
99 closeDevice(&drmFd, vaDpy);
109QSize VaapiUtils::minimumSize()
const
114QSize VaapiUtils::maximumSize()
const
119bool VaapiUtils::supportsModifier(uint32_t , uint64_t modifier)
134 return modifier == DRM_FORMAT_MOD_LINEAR;
137std::shared_ptr<VaapiUtils> VaapiUtils::instance()
139 static std::shared_ptr<VaapiUtils> instance = std::make_shared<VaapiUtils>(VaapiUtils::Private{});
143VADisplay VaapiUtils::openDevice(
int *fd,
const QByteArray &path)
153 qCWarning(PIPEWIREVAAPI_LOGGING) <<
"VAAPI: Failed to open device" <<
path;
157 vaDpy = vaGetDisplayDRM(*fd);
159 qCWarning(PIPEWIREVAAPI_LOGGING) <<
"VAAPI: Failed to initialize DRM display";
163 if (vaDisplayIsValid(vaDpy) == 0) {
164 qCWarning(PIPEWIREVAAPI_LOGGING) <<
"Invalid VA display";
170 VAStatus va_status = vaInitialize(vaDpy, &major, &minor);
172 if (va_status != VA_STATUS_SUCCESS) {
173 qCWarning(PIPEWIREVAAPI_LOGGING) <<
"VAAPI: Failed to initialize display";
177 qCInfo(PIPEWIREVAAPI_LOGGING) <<
"VAAPI: API version" << major <<
"." << minor;
178 qCInfo(PIPEWIREVAAPI_LOGGING) <<
"VAAPI: Display initialized";
183void VaapiUtils::closeDevice(
int *fd, VADisplay dpy)
194bool VaapiUtils::supportsProfile(VAProfile profile, VADisplay dpy,
const QByteArray &path)
196 uint32_t ret = rateControlForProfile(profile, VAEntrypointEncSlice, dpy, path);
198 if (ret & VA_RC_CBR || ret & VA_RC_CQP || ret & VA_RC_VBR) {
201 ret = rateControlForProfile(profile, VAEntrypointEncSliceLP, dpy, path);
203 if (ret & VA_RC_CBR || ret & VA_RC_CQP || ret & VA_RC_VBR) {
211uint32_t VaapiUtils::rateControlForProfile(VAProfile profile, VAEntrypoint entrypoint, VADisplay dpy,
const QByteArray &path)
214 VAConfigAttrib attrib[1];
215 attrib->type = VAConfigAttribRateControl;
217 va_status = vaGetConfigAttributes(dpy, profile, entrypoint, attrib, 1);
220 case VA_STATUS_SUCCESS:
221 return attrib->value;
222 case VA_STATUS_ERROR_UNSUPPORTED_PROFILE:
223 qCWarning(PIPEWIREVAAPI_LOGGING) <<
"VAAPI: profile" << profile <<
"is not supported by the device" <<
path;
225 case VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT:
226 qCWarning(PIPEWIREVAAPI_LOGGING) <<
"VAAPI: entrypoint" << entrypoint <<
"of profile" << profile <<
"is not supported by the device" <<
path;
229 qCWarning(PIPEWIREVAAPI_LOGGING) <<
"VAAPI: Fail to get RC attribute from the" << profile << entrypoint <<
"of the device" <<
path;
234void VaapiUtils::querySizeConstraints(VADisplay dpy)
const
237 if (
auto status = vaCreateConfig(dpy, VAProfileH264ConstrainedBaseline, VAEntrypointEncSlice,
nullptr, 0, &config);
status != VA_STATUS_SUCCESS) {
241 VASurfaceAttrib attrib[8];
242 uint32_t attribCount = 8;
244 auto status = vaQuerySurfaceAttributes(dpy, config, attrib, &attribCount);
245 if (
status == VA_STATUS_SUCCESS) {
246 for (uint32_t i = 0; i < attribCount; ++i) {
247 switch (attrib[i].type) {
248 case VASurfaceAttribMinWidth:
249 m_minSize.setWidth(attrib[i].value.value.i);
251 case VASurfaceAttribMinHeight:
252 m_minSize.setHeight(attrib[i].value.value.i);
254 case VASurfaceAttribMaxWidth:
255 m_maxSize.setWidth(attrib[i].value.value.i);
257 case VASurfaceAttribMaxHeight:
258 m_maxSize.setHeight(attrib[i].value.value.i);
266 vaDestroyConfig(dpy, config);
Q_SCRIPTABLE CaptureState status()
QString path(const QString &relativePath)
const QList< QKeySequence > & close()
const QList< QKeySequence > & open()
bool isEmpty() const const