101
98
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
106
103
int shmdt(const void *shmaddr)
112
109
/* YUV formats in preferred order. */
113
110
fourcc_t fourcc_list[] = {
114
/* YUV 4:2:2 formats: */
118
/* YUV 4:1:1 formats: */
121
{ FOURCC_IYUV }, /* IYUV is a duplicate of I420. */
111
/* YUV 4:2:2 formats: */
115
/* YUV 4:1:1 formats: */
118
{ FOURCC_IYUV }, /* IYUV is a duplicate of I420. */
124
121
int find_yuv_port(Display* display, XvPortID* port, fourcc_t* format)
128
/* XvQueryExtension */
129
unsigned int version, release, request_base, event_base, error_base;
131
/* XvQueryAdaptors */
132
unsigned int num_adaptors;
133
XvAdaptorInfo* adaptor_info = NULL;
136
/* XvListImageFormats */
138
XvImageFormatValues* format_list = NULL;
140
switch (XvQueryExtension(display, &version, &release,
141
&request_base, &event_base, &error_base))
146
printf("XvQueryExtension returned XvBadExtension.\n");
149
printf("XvQueryExtension returned XvBadAlloc.\n");
152
printf("XvQueryExtension returned unknown error.\n");
156
switch (XvQueryAdaptors(display, DefaultRootWindow(display),
157
&num_adaptors, &adaptor_info))
162
printf("XvQueryAdaptors returned XvBadExtension.\n");
165
printf("XvQueryAdaptors returned XvBadAlloc.\n");
168
printf("XvQueryAdaptors returned unknown error.\n");
172
/* Find YUV capable adaptor. */
173
for (i = 0; i < (int)num_adaptors; i++) {
174
if (!(adaptor_info[i].type & XvInputMask
175
&& adaptor_info[i].type & XvImageMask))
180
format_list = XvListImageFormats(display, adaptor_info[i].base_id,
183
for (j = 0; j < (int)(sizeof(fourcc_list) / sizeof(*fourcc_list)); j++) {
184
if (format->id && fourcc_list[j].id != format->id) {
187
for (k = 0; k < num_formats; k++) {
188
if (format_list[k].id != fourcc_list[j].id) {
192
for (port_id = adaptor_info[i].base_id;
193
port_id < adaptor_info[i].base_id + adaptor_info[i].num_ports;
196
if (XvGrabPort(display, port_id, CurrentTime) != Success) {
200
*format = fourcc_list[j];
202
XvFreeAdaptorInfo(adaptor_info);
211
XvFreeAdaptorInfo(adaptor_info);
212
printf("No suitable Xv YUV adaptor/port available.\n");
217
XvImage* create_yuv_image(Display* display, XvPortID port, fourcc_t format,
218
int width, int height, XShmSegmentInfo* shminfo)
223
if (!(image = XvShmCreateImage(display, port, format.id, NULL,
224
width, height, shminfo)))
226
printf("Unable to create shm XvImage\n");
230
if ((shminfo->shmid = shmget(IPC_PRIVATE, image->data_size, IPC_CREAT | 0777)) == -1)
232
printf("Unable to allocate shared memory\n");
236
if (!(shminfo->shmaddr = shmat(shminfo->shmid, 0, 0))) {
237
printf("Unable to attach shared memory\n");
239
shmctl(shminfo->shmid, IPC_RMID, 0);
242
shminfo->readOnly = False;
244
image->data = shminfo->shmaddr;
246
if (!XShmAttach(display, shminfo)) {
247
printf("XShmAttach failed\n");
249
shmctl(shminfo->shmid, IPC_RMID, 0);
250
shmdt(shminfo->shmaddr);
254
/* Send image to X server. This instruction is required, since having
255
* built a Shm XImage and not using it causes an error on XCloseDisplay. */
256
XSync(display, False);
258
/* Mark the segment to be automatically removed when the last
259
attachment is broken (i.e. on shmdt or process exit). */
260
shmctl(shminfo->shmid, IPC_RMID, 0);
263
if (!(image = XvCreateImage(display, port, format.id, NULL,
266
printf("Unable to create XvImage\n");
269
image->data = malloc(image->data_size);
276
void destroy_yuv_image(Display* display, XvImage* image,
277
XShmSegmentInfo* shminfo)
280
XShmDetach(display, shminfo);
282
shmdt(shminfo->shmaddr);
290
void display_yuv_image(Display* display, XvPortID port, Drawable d, GC gc,
292
XShmSegmentInfo* shminfo,
293
int src_x, int src_y,
294
unsigned int src_w, unsigned int src_h,
295
unsigned int dest_w, unsigned int dest_h,
298
int dest_x = 0, dest_y = 0;
300
/* Keep aspect ratio of src image. */
301
if (dest_w*src_h < src_w*aspect_ratio*dest_h) {
303
dest_h = dest_w*src_h/(src_w*aspect_ratio);
304
dest_y = (dest_y - dest_h)/2;
308
dest_w = dest_h*src_w*aspect_ratio/src_h;
309
dest_x = (dest_x - dest_w)/2;
313
XvShmPutImage(display, port, d, gc, image,
314
src_x, src_y, src_w, src_h,
315
dest_x, dest_y, dest_w, dest_h, False);
318
XvPutImage(display, port, d, gc, image,
319
src_x, src_y, src_w, src_h,
320
dest_x, dest_y, dest_w, dest_h);
125
/* XvQueryExtension */
126
unsigned int version, release, request_base, event_base, error_base;
128
/* XvQueryAdaptors */
129
unsigned int num_adaptors;
130
XvAdaptorInfo* adaptor_info = NULL;
133
/* XvListImageFormats */
135
XvImageFormatValues* format_list = NULL;
137
switch (XvQueryExtension(display, &version, &release, &request_base, &event_base, &error_base)) {
141
printf("XvQueryExtension returned XvBadExtension.\n");
144
printf("XvQueryExtension returned XvBadAlloc.\n");
147
printf("XvQueryExtension returned unknown error.\n");
151
switch (XvQueryAdaptors(display, DefaultRootWindow(display), &num_adaptors, &adaptor_info)) {
155
printf("XvQueryAdaptors returned XvBadExtension.\n");
158
printf("XvQueryAdaptors returned XvBadAlloc.\n");
161
printf("XvQueryAdaptors returned unknown error.\n");
165
/* Find YUV capable adaptor. */
166
for (i = 0; i < (int)num_adaptors; i++) {
167
if (!(adaptor_info[i].type & XvInputMask && adaptor_info[i].type & XvImageMask)) {
171
format_list = XvListImageFormats(display, adaptor_info[i].base_id, &num_formats);
173
for (j = 0; j < (int)(sizeof(fourcc_list) / sizeof(*fourcc_list)); j++) {
174
if (format->id && fourcc_list[j].id != format->id) {
177
for (k = 0; k < num_formats; k++) {
178
if (format_list[k].id != fourcc_list[j].id) {
182
for (port_id = adaptor_info[i].base_id; port_id < adaptor_info[i].base_id + adaptor_info[i].num_ports; port_id++) {
183
if (XvGrabPort(display, port_id, CurrentTime) != Success) {
187
*format = fourcc_list[j];
189
XvFreeAdaptorInfo(adaptor_info);
198
XvFreeAdaptorInfo(adaptor_info);
199
printf("No suitable Xv YUV adaptor/port available.\n");
203
XvImage* create_yuv_image(Display* display, XvPortID port, fourcc_t format, int width, int height, XShmSegmentInfo* shminfo)
208
if (!(image = XvShmCreateImage(display, port, format.id, NULL, width, height, shminfo))) {
209
printf("Unable to create shm XvImage\n");
213
if ((shminfo->shmid = shmget(IPC_PRIVATE, image->data_size, IPC_CREAT | 0777)) == -1) {
214
printf("Unable to allocate shared memory\n");
218
if (!(shminfo->shmaddr = shmat(shminfo->shmid, 0, 0))) {
219
printf("Unable to attach shared memory\n");
221
shmctl(shminfo->shmid, IPC_RMID, 0);
224
shminfo->readOnly = False;
226
image->data = shminfo->shmaddr;
228
if (!XShmAttach(display, shminfo)) {
229
printf("XShmAttach failed\n");
231
shmctl(shminfo->shmid, IPC_RMID, 0);
232
shmdt(shminfo->shmaddr);
236
/* Send image to X server. This instruction is required, since having
237
* built a Shm XImage and not using it causes an error on XCloseDisplay. */
238
XSync(display, False);
240
/* Mark the segment to be automatically removed when the last
241
attachment is broken (i.e. on shmdt or process exit). */
242
shmctl(shminfo->shmid, IPC_RMID, 0);
244
if (!(image = XvCreateImage(display, port, format.id, NULL, width, height))) {
245
printf("Unable to create XvImage\n");
248
image->data = malloc(image->data_size);
254
void destroy_yuv_image(Display* display, XvImage* image, XShmSegmentInfo* shminfo)
257
XShmDetach(display, shminfo);
259
shmdt(shminfo->shmaddr);
265
void display_yuv_image(Display* display, XvPortID port, Drawable d, GC gc, XvImage* image, XShmSegmentInfo* shminfo,
266
int src_x, int src_y, unsigned int src_w, unsigned int src_h, unsigned int dest_w, unsigned int dest_h,
269
int dest_x = 0, dest_y = 0;
271
/* Keep aspect ratio of src image. */
272
if (dest_w * src_h < src_w * aspect_ratio * dest_h) {
274
dest_h = dest_w * src_h / (src_w * aspect_ratio);
275
dest_y = (dest_y - dest_h) / 2;
278
dest_w = dest_h * src_w * aspect_ratio / src_h;
279
dest_x = (dest_x - dest_w) / 2;
283
XvShmPutImage(display, port, d, gc, image, src_x, src_y, src_w, src_h, dest_x, dest_y, dest_w, dest_h, False);
285
XvPutImage(display, port, d, gc, image, src_x, src_y, src_w, src_h, dest_x, dest_y, dest_w, dest_h);
324
289
#endif /* HAVE_XVIDEO */