1 // Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <Python.h>
6
7 #if !defined(USE_DRM)
8 #include <X11/Xlib.h>
9 #include <va/va.h>
10 #include <va/va_x11.h>
11 #else
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <fcntl.h>
15 #include <va/va.h>
16 #include <va/va_drm.h>
17 #endif
18
19 static PyObject *VaapiError;
20
21 namespace {
22
23 struct DisplayBundle {
24 #if !defined(USE_DRM)
25 Display *x11_display;
26 #else
27 int drm_fd;
28 #endif
29 VADisplay va_display;
30 };
31
destroy_display_bundle(PyObject * object)32 static void destroy_display_bundle(PyObject* object) {
33 DisplayBundle* bundle = (DisplayBundle*) PyCapsule_GetPointer(object, NULL);
34 vaTerminate(bundle->va_display);
35 #if !defined(USE_DRM)
36 XCloseDisplay(bundle->x11_display);
37 #else
38 close(bundle->drm_fd);
39 #endif
40 delete bundle;
41 }
42
va_create_display(PyObject * self,PyObject * args)43 static PyObject* va_create_display(PyObject* self, PyObject* args) {
44 #if !defined(USE_DRM)
45 const char* display_name;
46 if (!PyArg_ParseTuple(args, "s", &display_name))
47 return NULL;
48
49 Display *x11_display = XOpenDisplay(display_name);
50
51 if (x11_display == NULL) {
52 PyErr_SetString(VaapiError, "Cannot connect X server!");
53 return NULL;
54 }
55
56 VADisplay va_display = vaGetDisplay(x11_display);
57 #else
58 const char* drm_card_path;
59 if (!PyArg_ParseTuple(args, "s", &drm_card_path))
60 return NULL;
61
62 int drm_fd = open(drm_card_path, O_RDWR);
63 if (drm_fd < 0) {
64 PyErr_SetString(VaapiError, "Cannot open drm card path");
65 return NULL;
66 }
67
68 VADisplay va_display = vaGetDisplayDRM(drm_fd);
69 #endif
70 if (!vaDisplayIsValid(va_display)) {
71 PyErr_SetString(VaapiError, "Cannot get a valid display");
72 return NULL;
73 }
74
75 int major_ver, minor_ver;
76
77 VAStatus va_status = vaInitialize(va_display, &major_ver, &minor_ver);
78 if (va_status != VA_STATUS_SUCCESS) {
79 PyErr_SetString(VaapiError, "vaInitialize fail");
80 return NULL;
81 }
82
83 DisplayBundle* bundle = new DisplayBundle();
84 #if !defined(USE_DRM)
85 bundle->x11_display = x11_display;
86 #else
87 bundle->drm_fd = drm_fd;
88 #endif
89 bundle->va_display = va_display;
90
91 return PyCapsule_New(bundle, NULL, destroy_display_bundle);
92 }
93
get_va_display(PyObject * object)94 static VADisplay get_va_display(PyObject* object) {
95 if (!PyCapsule_CheckExact(object)) {
96 PyErr_SetString(VaapiError, "invalid display object");
97 return NULL;
98 }
99
100 DisplayBundle* bundle = (DisplayBundle*) PyCapsule_GetPointer(object, NULL);
101
102 if (bundle == NULL)
103 return NULL;
104
105 return bundle->va_display;
106 }
107
va_query_profiles(PyObject * self,PyObject * args)108 static PyObject* va_query_profiles(PyObject* self, PyObject* args) {
109 PyObject* bundle;
110 if (!PyArg_ParseTuple(args, "O", &bundle))
111 return NULL;
112
113 VADisplay va_display = get_va_display(bundle);
114
115 if (va_display == NULL)
116 return NULL;
117
118 int num_profiles = vaMaxNumProfiles(va_display);
119 VAProfile *profile = new VAProfile[num_profiles];
120
121 VAStatus status = vaQueryConfigProfiles(va_display, profile, &num_profiles);
122
123 if (status != VA_STATUS_SUCCESS) {
124 delete [] profile;
125 PyErr_SetString(VaapiError, "vaQueryConfigProfiles fail");
126 return NULL;
127 }
128
129 PyObject *result = PyList_New(0);
130 for (int i = 0; i < num_profiles; ++i) {
131 size_t value = static_cast<size_t>(profile[i]);
132 PyList_Append(result, PyInt_FromSize_t(value));
133 }
134 delete [] profile;
135 return result;
136 }
137
va_query_entrypoints(PyObject * self,PyObject * args)138 static PyObject* va_query_entrypoints(PyObject* self, PyObject* args) {
139 PyObject* bundle;
140 int profile;
141 if (!PyArg_ParseTuple(args, "Oi", &bundle, &profile))
142 return NULL;
143
144 VADisplay va_display = get_va_display(bundle);
145 if (va_display == NULL)
146 return NULL;
147
148 int num_entrypoints = vaMaxNumEntrypoints(va_display);
149 VAEntrypoint* entrypoint = new VAEntrypoint[num_entrypoints];
150
151 VAStatus status = vaQueryConfigEntrypoints(va_display,
152 static_cast<VAProfile>(profile),
153 entrypoint,
154 &num_entrypoints);
155 if (status != VA_STATUS_SUCCESS) {
156 PyErr_SetString(VaapiError, "vaQueryConfigEntryPoints fail");
157 return NULL;
158 }
159
160 PyObject *result = PyList_New(0);
161 for (int i = 0; i < num_entrypoints; ++i) {
162 size_t value = static_cast<size_t>(entrypoint[i]);
163 PyList_Append(result, PyInt_FromSize_t(value));
164 }
165 return result;
166 }
167
va_get_rt_format(PyObject * self,PyObject * args)168 static PyObject* va_get_rt_format(PyObject* self, PyObject* args) {
169 PyObject* bundle;
170 int profile;
171 int entrypoint;
172 if (!PyArg_ParseTuple(args, "Oii", &bundle, &profile, &entrypoint))
173 return NULL;
174
175 VADisplay va_display = get_va_display(bundle);
176 if (va_display == NULL)
177 return NULL;
178
179 VAConfigAttrib attrib;
180 attrib.type = VAConfigAttribRTFormat;
181 VAStatus status = vaGetConfigAttributes(va_display,
182 static_cast<VAProfile>(profile),
183 static_cast<VAEntrypoint>(entrypoint),
184 &attrib,
185 1);
186 if (status != VA_STATUS_SUCCESS) {
187 PyErr_SetString(VaapiError, "vaGetConfgAttributes fail");
188 return NULL;
189 }
190
191 return PyInt_FromSize_t(attrib.value);
192 }
193
194 /*
195 * Bind Python function names to our C functions
196 */
197 static PyMethodDef vaapi_methods[] = {
198 {"create_display", va_create_display, METH_VARARGS},
199 {"query_profiles", va_query_profiles, METH_VARARGS},
200 {"query_entrypoints", va_query_entrypoints, METH_VARARGS},
201 {"get_rt_format", va_get_rt_format, METH_VARARGS},
202 {NULL, NULL}
203 };
204
205 } // end of namespace
206
207 /*
208 * Python calls this to let us initialize our module
209 */
initvaapi()210 PyMODINIT_FUNC initvaapi() {
211 PyObject *m = Py_InitModule("vaapi", vaapi_methods);
212 if (m == NULL)
213 return;
214
215 VaapiError = PyErr_NewException((char*)"vaapi.error", NULL, NULL);
216 Py_INCREF(VaapiError);
217 PyModule_AddObject(m, "error", VaapiError);
218 }
219