1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#include <X11/X.h>
6#include <X11/Xlib.h>
7#include <X11/extensions/Xvlib.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <ctype.h>
12
13static char *progname;
14
15static void _X_NORETURN _X_COLD
16PrintUsage(void)
17{
18    fprintf(stderr, "Usage: %s [-display host:dpy] [-short] [-version]\n",
19            progname);
20    exit(0);
21}
22
23int
24main(int argc, char *argv[])
25{
26    Display *dpy;
27    unsigned int ver, rev, eventB, reqB, errorB;
28    int nscreens;
29    char *disname = NULL;
30    char shortmode = 0;
31
32    progname = argv[0];
33
34    if ((argc > 4))
35        PrintUsage();
36
37    if (argc != 1) {
38        for (int i = 1; i < argc; i++) {
39            if (!strcmp(argv[i], "-display")) {
40                if (++i >= argc) {
41                    fprintf (stderr, "%s: missing argument to -display\n",
42                             progname);
43                    PrintUsage();
44                }
45                disname = argv[i];
46            }
47            else if (!strcmp(argv[i], "-short"))
48                shortmode = 1;
49            else if (!strcmp(argv[i], "-version")) {
50                printf("%s\n", PACKAGE_STRING);
51                exit(0);
52            }
53            else {
54                fprintf (stderr, "%s: unrecognized argument '%s'\n",
55                         progname, argv[i]);
56                PrintUsage();
57            }
58        }
59    }
60
61    if (!(dpy = XOpenDisplay(disname))) {
62        fprintf(stderr, "%s:  Unable to open display %s\n", progname,
63                (disname != NULL) ? disname : XDisplayName(NULL));
64        exit(-1);
65    }
66
67    if (Success != XvQueryExtension(dpy, &ver, &rev, &reqB, &eventB, &errorB)) {
68        fprintf(stderr, "%s: No X-Video Extension on %s\n", progname,
69                (disname != NULL) ? disname : XDisplayName(NULL));
70        exit(0);
71    }
72    else {
73        fprintf(stdout, "X-Video Extension version %i.%i\n", ver, rev);
74    }
75
76    nscreens = ScreenCount(dpy);
77
78    for (int i = 0; i < nscreens; i++) {
79        unsigned int nadaptors;
80        XvAdaptorInfo *ainfo;
81
82        fprintf(stdout, "screen #%i\n", i);
83        if (Success != XvQueryAdaptors(dpy, RootWindow(dpy, i), &nadaptors,
84                                       &ainfo)) {
85            fprintf(stderr, "%s:  Failed to query adaptors on display %s\n",
86                    progname, (disname != NULL) ? disname : XDisplayName(NULL));
87            exit(-1);
88        }
89
90        if (!nadaptors) {
91            fprintf(stdout, " no adaptors present\n");
92            continue;
93        }
94
95        for (unsigned int j = 0; j < nadaptors; j++) {
96            XvFormat *format;
97            int  nattr;
98            XvAttribute *attributes;
99            unsigned int nencode;
100            XvEncodingInfo *encodings;
101
102            fprintf(stdout, "  Adaptor #%i: \"%s\"\n", j, ainfo[j].name);
103            fprintf(stdout, "    number of ports: %li\n", ainfo[j].num_ports);
104            fprintf(stdout, "    port base: %li\n", ainfo[j].base_id);
105            fprintf(stdout, "    operations supported: ");
106            switch (ainfo[j].type & (XvInputMask | XvOutputMask)) {
107            case XvInputMask:
108                if (ainfo[j].type & XvVideoMask)
109                    fprintf(stdout, "PutVideo ");
110                if (ainfo[j].type & XvStillMask)
111                    fprintf(stdout, "PutStill ");
112                if (ainfo[j].type & XvImageMask)
113                    fprintf(stdout, "PutImage ");
114                break;
115            case XvOutputMask:
116                if (ainfo[j].type & XvVideoMask)
117                    fprintf(stdout, "GetVideo ");
118                if (ainfo[j].type & XvStillMask)
119                    fprintf(stdout, "GetStill ");
120                break;
121            default:
122                fprintf(stdout, "none ");
123                break;
124            }
125            fprintf(stdout, "\n");
126
127            format = ainfo[j].formats;
128
129            if (!shortmode) {
130                fprintf(stdout, "    supported visuals:\n");
131                for (unsigned long k = 0; k < ainfo[j].num_formats; k++, format++) {
132                    fprintf(stdout, "      depth %i, visualID 0x%2lx\n",
133                            format->depth, format->visual_id);
134                }
135            }
136
137            attributes = XvQueryPortAttributes(dpy, ainfo[j].base_id, &nattr);
138
139            if (attributes && nattr) {
140                fprintf(stdout, "    number of attributes: %i\n", nattr);
141
142                for (int k = 0; k < nattr; k++) {
143                    fprintf(stdout, "      \"%s\" (range %i to %i)\n",
144                            attributes[k].name,
145                            attributes[k].min_value, attributes[k].max_value);
146
147                    if (attributes[k].flags & XvSettable) {
148                        if (!shortmode)
149                            fprintf(stdout,
150                                    "              client settable attribute\n");
151                        else
152                            fprintf(stdout, "              settable");
153                    }
154
155                    if (attributes[k].flags & XvGettable) {
156                        Atom the_atom;
157
158                        int value;
159
160                        if (!shortmode)
161                            fprintf(stdout,
162                                    "              client gettable attribute");
163                        else
164                            fprintf(stdout, ", gettable");
165
166                        the_atom = XInternAtom(dpy, attributes[k].name, True);
167
168                        if (the_atom != None) {
169                            if ((Success == XvGetPortAttribute(dpy,
170                                                               ainfo[j].base_id,
171                                                               the_atom,
172                                                               &value)))
173                                fprintf(stdout, " (current value is %i)",
174                                        value);
175                        }
176                        fprintf(stdout, "\n");
177                    }
178                    else if (shortmode)
179                        fprintf(stdout, "\n");
180
181                }
182                XFree(attributes);
183            }
184            else {
185                fprintf(stdout, "    no port attributes defined\n");
186            }
187
188            if (Success != XvQueryEncodings(dpy, ainfo[j].base_id, &nencode,
189                                            &encodings)) {
190                fprintf(stderr,
191                        "%s:  Failed to query encodings on display %s\n",
192                        progname,
193                        (disname != NULL) ? disname : XDisplayName(NULL));
194                exit(-1);
195            }
196
197            if (encodings && nencode) {
198                unsigned int ImageEncodings = 0;
199
200                for (unsigned int n = 0; n < nencode; n++) {
201                    if (!strcmp(encodings[n].name, "XV_IMAGE"))
202                        ImageEncodings++;
203                }
204
205                if (nencode - ImageEncodings) {
206                    fprintf(stdout, "    number of encodings: %i\n",
207                            nencode - ImageEncodings);
208
209                    for (unsigned int n = 0; n < nencode; n++) {
210                        if (strcmp(encodings[n].name, "XV_IMAGE")) {
211                            fprintf(stdout, "      encoding ID #%li: \"%s\"\n",
212                                    encodings[n].encoding_id,
213                                    encodings[n].name);
214                            fprintf(stdout, "        size: %li x %li\n",
215                                    encodings[n].width, encodings[n].height);
216                            fprintf(stdout, "        rate: %f\n",
217                                    (double) encodings[n].rate.numerator /
218                                    (double) encodings[n].rate.denominator);
219                        }
220                    }
221                }
222
223                if (ImageEncodings && (ainfo[j].type & XvImageMask)) {
224                    int numImages;
225                    XvImageFormatValues *formats;
226
227                    for (unsigned int n = 0; n < nencode; n++) {
228                        if (!strcmp(encodings[n].name, "XV_IMAGE")) {
229                            fprintf(stdout,
230                                    "    maximum XvImage size: %li x %li\n",
231                                    encodings[n].width, encodings[n].height);
232                            break;
233                        }
234                    }
235
236                    formats =
237                        XvListImageFormats(dpy, ainfo[j].base_id, &numImages);
238
239                    fprintf(stdout, "    Number of image formats: %i\n",
240                            numImages);
241
242                    for (int n = 0; n < numImages; n++) {
243                        char imageName[5];
244
245                        snprintf(imageName, sizeof(imageName), "%c%c%c%c",
246                                 formats[n].id & 0xff,
247                                (formats[n].id >> 8) & 0xff,
248                                (formats[n].id >> 16) & 0xff,
249                                (formats[n].id >> 24) & 0xff);
250                        fprintf(stdout, "      id: 0x%x", formats[n].id);
251                        if (isprint(imageName[0]) && isprint(imageName[1]) &&
252                            isprint(imageName[2]) && isprint(imageName[3])) {
253                            fprintf(stdout, " (%s)\n", imageName);
254                        }
255                        else {
256                            fprintf(stdout, "\n");
257                        }
258                        if (!shortmode) {
259                            fprintf(stdout, "        guid: ");
260                            fprintf(stdout, "%02x", (unsigned char)
261                                    formats[n].guid[0]);
262                            fprintf(stdout, "%02x", (unsigned char)
263                                    formats[n].guid[1]);
264                            fprintf(stdout, "%02x", (unsigned char)
265                                    formats[n].guid[2]);
266                            fprintf(stdout, "%02x-", (unsigned char)
267                                    formats[n].guid[3]);
268                            fprintf(stdout, "%02x", (unsigned char)
269                                    formats[n].guid[4]);
270                            fprintf(stdout, "%02x-", (unsigned char)
271                                    formats[n].guid[5]);
272                            fprintf(stdout, "%02x", (unsigned char)
273                                    formats[n].guid[6]);
274                            fprintf(stdout, "%02x-", (unsigned char)
275                                    formats[n].guid[7]);
276                            fprintf(stdout, "%02x", (unsigned char)
277                                    formats[n].guid[8]);
278                            fprintf(stdout, "%02x-", (unsigned char)
279                                    formats[n].guid[9]);
280                            fprintf(stdout, "%02x", (unsigned char)
281                                    formats[n].guid[10]);
282                            fprintf(stdout, "%02x", (unsigned char)
283                                    formats[n].guid[11]);
284                            fprintf(stdout, "%02x", (unsigned char)
285                                    formats[n].guid[12]);
286                            fprintf(stdout, "%02x", (unsigned char)
287                                    formats[n].guid[13]);
288                            fprintf(stdout, "%02x", (unsigned char)
289                                    formats[n].guid[14]);
290                            fprintf(stdout, "%02x\n", (unsigned char)
291                                    formats[n].guid[15]);
292
293                            fprintf(stdout, "        bits per pixel: %i\n",
294                                    formats[n].bits_per_pixel);
295                            fprintf(stdout, "        number of planes: %i\n",
296                                    formats[n].num_planes);
297                            fprintf(stdout, "        type: %s (%s)\n",
298                                    (formats[n].type == XvRGB) ? "RGB" : "YUV",
299                                    (formats[n].format ==
300                                     XvPacked) ? "packed" : "planar");
301
302                            if (formats[n].type == XvRGB) {
303                                fprintf(stdout, "        depth: %i\n",
304                                        formats[n].depth);
305
306                                fprintf(stdout,
307                                        "        red, green, blue masks: "
308                                        "0x%x, 0x%x, 0x%x\n",
309                                        formats[n].red_mask,
310                                        formats[n].green_mask,
311                                        formats[n].blue_mask);
312                            }
313                            else {
314
315                            }
316                        }
317
318                    }
319                    if (formats)
320                        XFree(formats);
321                }
322
323                XvFreeEncodingInfo(encodings);
324            }
325
326        }
327
328        XvFreeAdaptorInfo(ainfo);
329    }
330    return 0;
331}
332