1405c8079Smrg#ifdef HAVE_CONFIG_H
2405c8079Smrg# include "config.h"
3405c8079Smrg#endif
4405c8079Smrg
58ae04fa6Smrg#include <X11/X.h>
68ae04fa6Smrg#include <X11/Xlib.h>
78ae04fa6Smrg#include <X11/extensions/Xvlib.h>
88ae04fa6Smrg#include <stdio.h>
98ae04fa6Smrg#include <stdlib.h>
108ae04fa6Smrg#include <string.h>
118ae04fa6Smrg#include <ctype.h>
128ae04fa6Smrg
1380f56f3aSmrgstatic char *progname;
1480f56f3aSmrg
1580f56f3aSmrgstatic void _X_NORETURN _X_COLD
168ae04fa6SmrgPrintUsage(void)
178ae04fa6Smrg{
1880f56f3aSmrg    fprintf(stderr, "Usage: %s [-display host:dpy] [-short] [-version]\n",
1980f56f3aSmrg            progname);
20405c8079Smrg    exit(0);
218ae04fa6Smrg}
228ae04fa6Smrg
23405c8079Smrgint
24405c8079Smrgmain(int argc, char *argv[])
258ae04fa6Smrg{
268ae04fa6Smrg    Display *dpy;
27405c8079Smrg    unsigned int ver, rev, eventB, reqB, errorB;
28138a9f8aSmrg    int nscreens;
29405c8079Smrg    char *disname = NULL;
3044af7230Smrg    char shortmode = 0;
318ae04fa6Smrg
3280f56f3aSmrg    progname = argv[0];
3380f56f3aSmrg
34405c8079Smrg    if ((argc > 4))
35405c8079Smrg        PrintUsage();
36405c8079Smrg
37405c8079Smrg    if (argc != 1) {
38d71d4977Smrg        for (int i = 1; i < argc; i++) {
39405c8079Smrg            if (!strcmp(argv[i], "-display")) {
4080f56f3aSmrg                if (++i >= argc) {
4180f56f3aSmrg                    fprintf (stderr, "%s: missing argument to -display\n",
4280f56f3aSmrg                             progname);
4380f56f3aSmrg                    PrintUsage();
4480f56f3aSmrg                }
4580f56f3aSmrg                disname = argv[i];
46405c8079Smrg            }
47405c8079Smrg            else if (!strcmp(argv[i], "-short"))
48405c8079Smrg                shortmode = 1;
49405c8079Smrg            else if (!strcmp(argv[i], "-version")) {
50405c8079Smrg                printf("%s\n", PACKAGE_STRING);
51405c8079Smrg                exit(0);
52405c8079Smrg            }
53405c8079Smrg            else {
5480f56f3aSmrg                fprintf (stderr, "%s: unrecognized argument '%s'\n",
5580f56f3aSmrg                         progname, argv[i]);
56405c8079Smrg                PrintUsage();
57405c8079Smrg            }
58405c8079Smrg        }
598ae04fa6Smrg    }
608ae04fa6Smrg
61405c8079Smrg    if (!(dpy = XOpenDisplay(disname))) {
6280f56f3aSmrg        fprintf(stderr, "%s:  Unable to open display %s\n", progname,
63405c8079Smrg                (disname != NULL) ? disname : XDisplayName(NULL));
64405c8079Smrg        exit(-1);
658ae04fa6Smrg    }
668ae04fa6Smrg
67d71d4977Smrg    if (Success != XvQueryExtension(dpy, &ver, &rev, &reqB, &eventB, &errorB)) {
6880f56f3aSmrg        fprintf(stderr, "%s: No X-Video Extension on %s\n", progname,
69405c8079Smrg                (disname != NULL) ? disname : XDisplayName(NULL));
70405c8079Smrg        exit(0);
71405c8079Smrg    }
72405c8079Smrg    else {
73405c8079Smrg        fprintf(stdout, "X-Video Extension version %i.%i\n", ver, rev);
748ae04fa6Smrg    }
758ae04fa6Smrg
768ae04fa6Smrg    nscreens = ScreenCount(dpy);
778ae04fa6Smrg
78d71d4977Smrg    for (int i = 0; i < nscreens; i++) {
79138a9f8aSmrg        unsigned int nadaptors;
80138a9f8aSmrg        XvAdaptorInfo *ainfo;
81138a9f8aSmrg
82405c8079Smrg        fprintf(stdout, "screen #%i\n", i);
83d71d4977Smrg        if (Success != XvQueryAdaptors(dpy, RootWindow(dpy, i), &nadaptors,
84d71d4977Smrg                                       &ainfo)) {
85d71d4977Smrg            fprintf(stderr, "%s:  Failed to query adaptors on display %s\n",
86d71d4977Smrg                    progname, (disname != NULL) ? disname : XDisplayName(NULL));
87d71d4977Smrg            exit(-1);
88d71d4977Smrg        }
89405c8079Smrg
90405c8079Smrg        if (!nadaptors) {
91405c8079Smrg            fprintf(stdout, " no adaptors present\n");
92405c8079Smrg            continue;
93405c8079Smrg        }
94405c8079Smrg
95d71d4977Smrg        for (unsigned int j = 0; j < nadaptors; j++) {
96138a9f8aSmrg            XvFormat *format;
97138a9f8aSmrg            int  nattr;
98138a9f8aSmrg            XvAttribute *attributes;
99138a9f8aSmrg            unsigned int nencode;
100138a9f8aSmrg            XvEncodingInfo *encodings;
101138a9f8aSmrg
102405c8079Smrg            fprintf(stdout, "  Adaptor #%i: \"%s\"\n", j, ainfo[j].name);
103405c8079Smrg            fprintf(stdout, "    number of ports: %li\n", ainfo[j].num_ports);
104405c8079Smrg            fprintf(stdout, "    port base: %li\n", ainfo[j].base_id);
105405c8079Smrg            fprintf(stdout, "    operations supported: ");
106405c8079Smrg            switch (ainfo[j].type & (XvInputMask | XvOutputMask)) {
107405c8079Smrg            case XvInputMask:
108405c8079Smrg                if (ainfo[j].type & XvVideoMask)
109405c8079Smrg                    fprintf(stdout, "PutVideo ");
110405c8079Smrg                if (ainfo[j].type & XvStillMask)
111405c8079Smrg                    fprintf(stdout, "PutStill ");
112405c8079Smrg                if (ainfo[j].type & XvImageMask)
113405c8079Smrg                    fprintf(stdout, "PutImage ");
114405c8079Smrg                break;
115405c8079Smrg            case XvOutputMask:
116405c8079Smrg                if (ainfo[j].type & XvVideoMask)
117405c8079Smrg                    fprintf(stdout, "GetVideo ");
118405c8079Smrg                if (ainfo[j].type & XvStillMask)
119405c8079Smrg                    fprintf(stdout, "GetStill ");
120405c8079Smrg                break;
121405c8079Smrg            default:
122405c8079Smrg                fprintf(stdout, "none ");
123405c8079Smrg                break;
124405c8079Smrg            }
125405c8079Smrg            fprintf(stdout, "\n");
126405c8079Smrg
127405c8079Smrg            format = ainfo[j].formats;
128405c8079Smrg
129405c8079Smrg            if (!shortmode) {
130405c8079Smrg                fprintf(stdout, "    supported visuals:\n");
131d71d4977Smrg                for (unsigned long k = 0; k < ainfo[j].num_formats; k++, format++) {
132405c8079Smrg                    fprintf(stdout, "      depth %i, visualID 0x%2lx\n",
133405c8079Smrg                            format->depth, format->visual_id);
134405c8079Smrg                }
135405c8079Smrg            }
136405c8079Smrg
137405c8079Smrg            attributes = XvQueryPortAttributes(dpy, ainfo[j].base_id, &nattr);
138405c8079Smrg
139405c8079Smrg            if (attributes && nattr) {
140405c8079Smrg                fprintf(stdout, "    number of attributes: %i\n", nattr);
141405c8079Smrg
142d71d4977Smrg                for (int k = 0; k < nattr; k++) {
143405c8079Smrg                    fprintf(stdout, "      \"%s\" (range %i to %i)\n",
144405c8079Smrg                            attributes[k].name,
145405c8079Smrg                            attributes[k].min_value, attributes[k].max_value);
146405c8079Smrg
147405c8079Smrg                    if (attributes[k].flags & XvSettable) {
148405c8079Smrg                        if (!shortmode)
149405c8079Smrg                            fprintf(stdout,
150405c8079Smrg                                    "              client settable attribute\n");
151405c8079Smrg                        else
152405c8079Smrg                            fprintf(stdout, "              settable");
153405c8079Smrg                    }
154405c8079Smrg
155405c8079Smrg                    if (attributes[k].flags & XvGettable) {
156405c8079Smrg                        Atom the_atom;
157405c8079Smrg
158405c8079Smrg                        int value;
159405c8079Smrg
160405c8079Smrg                        if (!shortmode)
161405c8079Smrg                            fprintf(stdout,
162405c8079Smrg                                    "              client gettable attribute");
163405c8079Smrg                        else
164405c8079Smrg                            fprintf(stdout, ", gettable");
165405c8079Smrg
166405c8079Smrg                        the_atom = XInternAtom(dpy, attributes[k].name, True);
167405c8079Smrg
168405c8079Smrg                        if (the_atom != None) {
169405c8079Smrg                            if ((Success == XvGetPortAttribute(dpy,
170405c8079Smrg                                                               ainfo[j].base_id,
171405c8079Smrg                                                               the_atom,
172405c8079Smrg                                                               &value)))
173405c8079Smrg                                fprintf(stdout, " (current value is %i)",
174405c8079Smrg                                        value);
175405c8079Smrg                        }
176405c8079Smrg                        fprintf(stdout, "\n");
177405c8079Smrg                    }
178405c8079Smrg                    else if (shortmode)
179405c8079Smrg                        fprintf(stdout, "\n");
180405c8079Smrg
181405c8079Smrg                }
182405c8079Smrg                XFree(attributes);
183405c8079Smrg            }
184405c8079Smrg            else {
185405c8079Smrg                fprintf(stdout, "    no port attributes defined\n");
186405c8079Smrg            }
187405c8079Smrg
188d71d4977Smrg            if (Success != XvQueryEncodings(dpy, ainfo[j].base_id, &nencode,
189d71d4977Smrg                                            &encodings)) {
190d71d4977Smrg                fprintf(stderr,
191d71d4977Smrg                        "%s:  Failed to query encodings on display %s\n",
192d71d4977Smrg                        progname,
193d71d4977Smrg                        (disname != NULL) ? disname : XDisplayName(NULL));
194d71d4977Smrg                exit(-1);
195d71d4977Smrg            }
196405c8079Smrg
197405c8079Smrg            if (encodings && nencode) {
19880f56f3aSmrg                unsigned int ImageEncodings = 0;
199405c8079Smrg
200d71d4977Smrg                for (unsigned int n = 0; n < nencode; n++) {
201405c8079Smrg                    if (!strcmp(encodings[n].name, "XV_IMAGE"))
202405c8079Smrg                        ImageEncodings++;
203405c8079Smrg                }
204405c8079Smrg
205405c8079Smrg                if (nencode - ImageEncodings) {
206405c8079Smrg                    fprintf(stdout, "    number of encodings: %i\n",
207405c8079Smrg                            nencode - ImageEncodings);
208405c8079Smrg
209d71d4977Smrg                    for (unsigned int n = 0; n < nencode; n++) {
210405c8079Smrg                        if (strcmp(encodings[n].name, "XV_IMAGE")) {
211405c8079Smrg                            fprintf(stdout, "      encoding ID #%li: \"%s\"\n",
212405c8079Smrg                                    encodings[n].encoding_id,
213405c8079Smrg                                    encodings[n].name);
214405c8079Smrg                            fprintf(stdout, "        size: %li x %li\n",
215405c8079Smrg                                    encodings[n].width, encodings[n].height);
216405c8079Smrg                            fprintf(stdout, "        rate: %f\n",
217138a9f8aSmrg                                    (double) encodings[n].rate.numerator /
218138a9f8aSmrg                                    (double) encodings[n].rate.denominator);
219405c8079Smrg                        }
220405c8079Smrg                    }
221405c8079Smrg                }
222405c8079Smrg
223405c8079Smrg                if (ImageEncodings && (ainfo[j].type & XvImageMask)) {
224138a9f8aSmrg                    int numImages;
225138a9f8aSmrg                    XvImageFormatValues *formats;
226138a9f8aSmrg
227d71d4977Smrg                    for (unsigned int n = 0; n < nencode; n++) {
228405c8079Smrg                        if (!strcmp(encodings[n].name, "XV_IMAGE")) {
229405c8079Smrg                            fprintf(stdout,
230405c8079Smrg                                    "    maximum XvImage size: %li x %li\n",
231405c8079Smrg                                    encodings[n].width, encodings[n].height);
232405c8079Smrg                            break;
233405c8079Smrg                        }
234405c8079Smrg                    }
235405c8079Smrg
236405c8079Smrg                    formats =
237405c8079Smrg                        XvListImageFormats(dpy, ainfo[j].base_id, &numImages);
238405c8079Smrg
239405c8079Smrg                    fprintf(stdout, "    Number of image formats: %i\n",
240405c8079Smrg                            numImages);
241405c8079Smrg
242d71d4977Smrg                    for (int n = 0; n < numImages; n++) {
24380f56f3aSmrg                        char imageName[5];
24480f56f3aSmrg
24580f56f3aSmrg                        snprintf(imageName, sizeof(imageName), "%c%c%c%c",
24680f56f3aSmrg                                 formats[n].id & 0xff,
247405c8079Smrg                                (formats[n].id >> 8) & 0xff,
248405c8079Smrg                                (formats[n].id >> 16) & 0xff,
249405c8079Smrg                                (formats[n].id >> 24) & 0xff);
250405c8079Smrg                        fprintf(stdout, "      id: 0x%x", formats[n].id);
251405c8079Smrg                        if (isprint(imageName[0]) && isprint(imageName[1]) &&
252405c8079Smrg                            isprint(imageName[2]) && isprint(imageName[3])) {
253405c8079Smrg                            fprintf(stdout, " (%s)\n", imageName);
254405c8079Smrg                        }
255405c8079Smrg                        else {
256405c8079Smrg                            fprintf(stdout, "\n");
257405c8079Smrg                        }
258405c8079Smrg                        if (!shortmode) {
259405c8079Smrg                            fprintf(stdout, "        guid: ");
260405c8079Smrg                            fprintf(stdout, "%02x", (unsigned char)
261405c8079Smrg                                    formats[n].guid[0]);
262405c8079Smrg                            fprintf(stdout, "%02x", (unsigned char)
263405c8079Smrg                                    formats[n].guid[1]);
264405c8079Smrg                            fprintf(stdout, "%02x", (unsigned char)
265405c8079Smrg                                    formats[n].guid[2]);
266405c8079Smrg                            fprintf(stdout, "%02x-", (unsigned char)
267405c8079Smrg                                    formats[n].guid[3]);
268405c8079Smrg                            fprintf(stdout, "%02x", (unsigned char)
269405c8079Smrg                                    formats[n].guid[4]);
270405c8079Smrg                            fprintf(stdout, "%02x-", (unsigned char)
271405c8079Smrg                                    formats[n].guid[5]);
272405c8079Smrg                            fprintf(stdout, "%02x", (unsigned char)
273405c8079Smrg                                    formats[n].guid[6]);
274405c8079Smrg                            fprintf(stdout, "%02x-", (unsigned char)
275405c8079Smrg                                    formats[n].guid[7]);
276405c8079Smrg                            fprintf(stdout, "%02x", (unsigned char)
277405c8079Smrg                                    formats[n].guid[8]);
278405c8079Smrg                            fprintf(stdout, "%02x-", (unsigned char)
279405c8079Smrg                                    formats[n].guid[9]);
280405c8079Smrg                            fprintf(stdout, "%02x", (unsigned char)
281405c8079Smrg                                    formats[n].guid[10]);
282405c8079Smrg                            fprintf(stdout, "%02x", (unsigned char)
283405c8079Smrg                                    formats[n].guid[11]);
284405c8079Smrg                            fprintf(stdout, "%02x", (unsigned char)
285405c8079Smrg                                    formats[n].guid[12]);
286405c8079Smrg                            fprintf(stdout, "%02x", (unsigned char)
287405c8079Smrg                                    formats[n].guid[13]);
288405c8079Smrg                            fprintf(stdout, "%02x", (unsigned char)
289405c8079Smrg                                    formats[n].guid[14]);
290405c8079Smrg                            fprintf(stdout, "%02x\n", (unsigned char)
291405c8079Smrg                                    formats[n].guid[15]);
292405c8079Smrg
293405c8079Smrg                            fprintf(stdout, "        bits per pixel: %i\n",
294405c8079Smrg                                    formats[n].bits_per_pixel);
295405c8079Smrg                            fprintf(stdout, "        number of planes: %i\n",
296405c8079Smrg                                    formats[n].num_planes);
297405c8079Smrg                            fprintf(stdout, "        type: %s (%s)\n",
298405c8079Smrg                                    (formats[n].type == XvRGB) ? "RGB" : "YUV",
299405c8079Smrg                                    (formats[n].format ==
300405c8079Smrg                                     XvPacked) ? "packed" : "planar");
301405c8079Smrg
302405c8079Smrg                            if (formats[n].type == XvRGB) {
303405c8079Smrg                                fprintf(stdout, "        depth: %i\n",
3048ae04fa6Smrg                                        formats[n].depth);
3058ae04fa6Smrg
306405c8079Smrg                                fprintf(stdout,
307405c8079Smrg                                        "        red, green, blue masks: "
308405c8079Smrg                                        "0x%x, 0x%x, 0x%x\n",
309405c8079Smrg                                        formats[n].red_mask,
310405c8079Smrg                                        formats[n].green_mask,
311405c8079Smrg                                        formats[n].blue_mask);
312405c8079Smrg                            }
313405c8079Smrg                            else {
314405c8079Smrg
315405c8079Smrg                            }
316405c8079Smrg                        }
317405c8079Smrg
318405c8079Smrg                    }
319405c8079Smrg                    if (formats)
320405c8079Smrg                        XFree(formats);
321405c8079Smrg                }
322405c8079Smrg
323405c8079Smrg                XvFreeEncodingInfo(encodings);
324405c8079Smrg            }
325405c8079Smrg
326405c8079Smrg        }
327405c8079Smrg
328405c8079Smrg        XvFreeAdaptorInfo(ainfo);
3298ae04fa6Smrg    }
330d71d4977Smrg    return 0;
3318ae04fa6Smrg}
332