1 #include "va_display.h"
15 VADisplayWithCleanup::~VADisplayWithCleanup()
17 if (va_dpy != nullptr) {
20 if (x11_display != nullptr) {
21 XCloseDisplay(x11_display);
28 unique_ptr<VADisplayWithCleanup> va_open_display(const string &va_display)
30 if (va_display.empty() || va_display[0] != '/') { // An X display.
31 Display *x11_display = XOpenDisplay(va_display.empty() ? nullptr : va_display.c_str());
32 if (x11_display == nullptr) {
33 fprintf(stderr, "error: can't connect to X server!\n");
37 unique_ptr<VADisplayWithCleanup> ret(new VADisplayWithCleanup);
38 ret->x11_display = x11_display;
39 ret->can_use_zerocopy = true;
40 ret->va_dpy = vaGetDisplay(x11_display);
41 if (ret->va_dpy == nullptr) {
45 } else { // A DRM node on the filesystem (e.g. /dev/dri/renderD128).
46 int drm_fd = open(va_display.c_str(), O_RDWR);
48 perror(va_display.c_str());
51 unique_ptr<VADisplayWithCleanup> ret(new VADisplayWithCleanup);
53 ret->can_use_zerocopy = false;
54 ret->va_dpy = vaGetDisplayDRM(drm_fd);
55 if (ret->va_dpy == nullptr) {
62 unique_ptr<VADisplayWithCleanup> try_open_va(
63 const string &va_display, const vector<VAProfile> &desired_profiles, VAEntrypoint entrypoint,
64 const vector<ConfigRequest> &desired_configs, VAProfile *chosen_profile, string *error)
66 unique_ptr<VADisplayWithCleanup> va_dpy = va_open_display(va_display);
67 if (va_dpy == nullptr) {
68 if (error) *error = "Opening VA display failed";
71 int major_ver, minor_ver;
72 VAStatus va_status = vaInitialize(va_dpy->va_dpy, &major_ver, &minor_ver);
73 if (va_status != VA_STATUS_SUCCESS) {
75 snprintf(buf, sizeof(buf), "vaInitialize() failed with status %d\n", va_status);
76 if (error != nullptr) *error = buf;
80 int num_entrypoints = vaMaxNumEntrypoints(va_dpy->va_dpy);
81 unique_ptr<VAEntrypoint[]> entrypoints(new VAEntrypoint[num_entrypoints]);
82 if (entrypoints == nullptr) {
83 if (error != nullptr) *error = "Failed to allocate memory for VA entry points";
87 // Try the profiles from highest to lowest until we find one that can be used.
88 VAProfile found_profile = VAProfileNone;
89 for (VAProfile profile : desired_profiles) {
90 vaQueryConfigEntrypoints(va_dpy->va_dpy, profile, entrypoints.get(), &num_entrypoints);
91 for (int slice_entrypoint = 0; slice_entrypoint < num_entrypoints; slice_entrypoint++) {
92 if (entrypoints[slice_entrypoint] != entrypoint) {
96 // We found a usable encoder/decoder, so return it.
97 if (chosen_profile != nullptr) {
98 *chosen_profile = profile;
100 found_profile = profile;
103 if (found_profile != VAProfileNone) {
107 if (found_profile == VAProfileNone) {
108 if (error != nullptr) *error = "Can't find entry points for suitable codec profile";
112 int num_formats = vaMaxNumImageFormats(va_dpy->va_dpy);
113 assert(num_formats > 0);
115 unique_ptr<VAImageFormat[]> formats(new VAImageFormat[num_formats]);
116 va_status = vaQueryImageFormats(va_dpy->va_dpy, formats.get(), &num_formats);
117 if (va_status != VA_STATUS_SUCCESS) {
119 snprintf(buf, sizeof(buf), "vaQueryImageFormats() failed with status %d\n", va_status);
120 if (error != nullptr) *error = buf;
124 for (const ConfigRequest &request : desired_configs) {
125 // Create the config.
126 VAConfigAttrib attr = { VAConfigAttribRTFormat, request.rt_format };
127 va_status = vaCreateConfig(va_dpy->va_dpy, found_profile, entrypoint,
128 &attr, 1, request.config_id);
129 if (va_status == VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT) {
130 if (error != nullptr) *error = "No " + request.name + " hardware support";
132 } else if (va_status != VA_STATUS_SUCCESS) {
134 snprintf(buf, sizeof(buf), "vaCreateConfig() for %s failed with status %d\n", request.name.c_str(), va_status);
135 if (error != nullptr) *error = buf;
139 // Find out which image format we're going to be using.
140 bool format_found = false;
141 for (int i = 0; i < num_formats; ++i) {
142 if (formats[i].fourcc == request.fourcc) {
143 memcpy(request.image_format, &formats[i], sizeof(VAImageFormat));
149 if (error != nullptr) *error = "Format for " + request.name + " not found";