Merge pull request #20244 from alalek:update_ffmpeg_4.x
[platform/upstream/opencv.git] / samples / va_intel / display.cpp.inc
1 #include <dirent.h>
2 #include <fcntl.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <sys/stat.h>
7 #include <sys/types.h>
8 #include <unistd.h>
9
10 #include <va/va.h>
11 # include <va/va_drm.h>
12
13 #include "opencv2/core.hpp"  // cv::format()
14
15 namespace va {
16
17 bool openDisplay();
18 void closeDisplay();
19
20 VADisplay display = NULL;
21 bool initialized = false;
22
23 #define VA_INTEL_PCI_DIR "/sys/bus/pci/devices"
24 #define VA_INTEL_DRI_DIR "/dev/dri/"
25 #define VA_INTEL_PCI_DISPLAY_CONTROLLER_CLASS 0x03
26
27 static unsigned readId(const char* devName, const char* idName);
28 static int findAdapter(unsigned desiredVendorId);
29
30 int drmfd = -1;
31
32 class Directory
33 {
34     typedef int (*fsort)(const struct dirent**, const struct dirent**);
35 public:
36     Directory(const char* path)
37         {
38             dirEntries = 0;
39             numEntries = scandir(path, &dirEntries, filterFunc, (fsort)alphasort);
40         }
41     ~Directory()
42         {
43             if (numEntries && dirEntries)
44             {
45                 for (int i = 0;  i < numEntries;  ++i)
46                     free(dirEntries[i]);
47                 free(dirEntries);
48             }
49         }
50     int count() const
51         {
52             return numEntries;
53         }
54     const struct dirent* operator[](int index) const
55         {
56             return ((dirEntries != 0) && (index >= 0) && (index < numEntries)) ? dirEntries[index] : 0;
57         }
58 protected:
59     static int filterFunc(const struct dirent* dir)
60         {
61             if (!dir) return 0;
62             if (!strcmp(dir->d_name, ".")) return 0;
63             if (!strcmp(dir->d_name, "..")) return 0;
64             return 1;
65         }
66 private:
67     int numEntries;
68     struct dirent** dirEntries;
69 };
70
71 static unsigned readId(const char* devName, const char* idName)
72 {
73     long int id = 0;
74
75     std::string fileName = cv::format("%s/%s/%s", VA_INTEL_PCI_DIR, devName, idName);
76
77     FILE* file = fopen(fileName.c_str(), "r");
78     if (file)
79     {
80         char str[16] = "";
81         if (fgets(str, sizeof(str), file))
82             id = strtol(str, NULL, 16);
83         fclose(file);
84     }
85     return (unsigned)id;
86 }
87
88 static int findAdapter(unsigned desiredVendorId)
89 {
90     int adapterIndex = -1;
91
92     Directory dir(VA_INTEL_PCI_DIR);
93
94     for (int i = 0;  i < dir.count();  ++i)
95     {
96         const char* name = dir[i]->d_name;
97
98         unsigned classId = readId(name, "class");
99         if ((classId >> 16) == VA_INTEL_PCI_DISPLAY_CONTROLLER_CLASS)
100         {
101             unsigned vendorId = readId(name, "vendor");
102             if (vendorId == desiredVendorId)
103             {
104                 std::string subdirName = cv::format("%s/%s/%s", VA_INTEL_PCI_DIR, name, "drm");
105                 Directory subdir(subdirName.c_str());
106                 for (int j = 0; j < subdir.count(); ++j)
107                 {
108                     if (!strncmp(subdir[j]->d_name, "card", 4))
109                     {
110                         adapterIndex = strtoul(subdir[j]->d_name + 4, NULL, 10);
111                     }
112                 }
113                 break;
114             }
115         }
116     }
117
118     return adapterIndex;
119 }
120
121 class NodeInfo
122 {
123     enum { NUM_NODES = 2 };
124 public:
125     NodeInfo(int adapterIndex)
126         {
127             const char* names[NUM_NODES] = { "renderD", "card" };
128             int numbers[NUM_NODES];
129             numbers[0] = adapterIndex+128;
130             numbers[1] = adapterIndex;
131             for (int i = 0;  i < NUM_NODES;  ++i)
132             {
133                 paths[i] = cv::format("%s%s%d", VA_INTEL_DRI_DIR, names[i], numbers[i]);
134             }
135         }
136     ~NodeInfo()
137         {
138             // nothing
139         }
140     int count() const
141         {
142             return NUM_NODES;
143         }
144     const char* path(int index) const
145         {
146             return ((index >= 0) && (index < NUM_NODES)) ? paths[index].c_str() : 0;
147         }
148 private:
149     std::string paths[NUM_NODES];
150 };
151
152 static bool openDeviceIntel();
153 static bool openDeviceGeneric();
154
155 static bool openDeviceIntel()
156 {
157     const unsigned IntelVendorID = 0x8086;
158
159     int adapterIndex = findAdapter(IntelVendorID);
160     if (adapterIndex >= 0)
161     {
162         NodeInfo nodes(adapterIndex);
163
164         for (int i = 0; i < nodes.count(); ++i)
165         {
166             drmfd = open(nodes.path(i), O_RDWR);
167             if (drmfd >= 0)
168             {
169                 display = vaGetDisplayDRM(drmfd);
170                 if (display)
171                     return true;
172                 close(drmfd);
173                 drmfd = -1;
174             }
175         }
176     }
177     return false;
178 }
179
180 static bool openDeviceGeneric()
181 {
182     static const char* device_paths[] = { "/dev/dri/renderD128", "/dev/dri/card0" };
183     static const int num_devices = sizeof(device_paths) / sizeof(device_paths[0]);
184
185     for (int i = 0; i < num_devices; ++i)
186     {
187         drmfd = open(device_paths[i], O_RDWR);
188         if (drmfd >= 0)
189         {
190             display = vaGetDisplayDRM(drmfd);
191             if (display)
192                 return true;
193             close(drmfd);
194             drmfd = -1;
195         }
196     }
197     return false;
198 }
199
200 bool openDisplay()
201 {
202     if (!initialized)
203     {
204         drmfd = -1;
205         display = 0;
206
207         if (openDeviceIntel() || openDeviceGeneric())
208         {
209             int majorVersion = 0, minorVersion = 0;
210             if (vaInitialize(display, &majorVersion, &minorVersion) == VA_STATUS_SUCCESS)
211             {
212                 initialized = true;
213                 return true;
214             }
215             close(drmfd);
216             display = 0;
217             drmfd = -1;
218         }
219         return false; // Can't open VA display
220     }
221     return true;
222 }
223
224 void closeDisplay()
225 {
226     if (initialized)
227     {
228         if (display)
229             vaTerminate(display);
230         if (drmfd >= 0)
231             close(drmfd);
232         display = 0;
233         drmfd = -1;
234         initialized = false;
235     }
236 }
237
238 } // namespace va