|
1 | 1 | #pragma once |
2 | 2 |
|
3 | 3 | #include <map> |
4 | | -#include <memory> |
| 4 | +#include <memory> |
| 5 | +#include <vector> |
5 | 6 |
|
6 | 7 | // DRM |
7 | 8 | #include <drm_fourcc.h> |
@@ -37,75 +38,211 @@ struct Encoder |
37 | 38 | std::map<std::string, DrmProperty, std::less<>> props; |
38 | 39 | }; |
39 | 40 |
|
| 41 | +struct DrmResources { |
| 42 | + using drmModeConnectorPtr_unique = std::unique_ptr<drmModeConnector, decltype(&drmModeFreeConnector)>; |
| 43 | + using drmModeCrtcPtr_unique = std::unique_ptr<drmModeCrtc, decltype(&drmModeFreeCrtc)>; |
| 44 | + |
| 45 | + std::vector<drmModeConnectorPtr_unique> connectors; |
| 46 | + std::vector<drmModeCrtcPtr_unique> crtcs; |
| 47 | +}; |
| 48 | + |
40 | 49 | /// |
41 | 50 | /// The DRMFrameGrabber is used for creating snapshots of the display (screenshots) |
42 | 51 | /// |
43 | 52 | class DRMFrameGrabber : public Grabber |
| 53 | +/** |
| 54 | + * @brief The DRMFrameGrabber class is a screen grabber that uses the Linux Direct Rendering Manager (DRM) |
| 55 | + * API to capture the screen content. This method is generally faster and more efficient than X11-based |
| 56 | + * methods, as it operates at a lower level. It is suitable for systems without a running X server, |
| 57 | + * such as dedicated media centers. |
| 58 | + */ |
44 | 59 | { |
45 | 60 | public: |
46 | | - /// |
47 | | - /// Construct a DRMFrameGrabber that will capture snapshots with specified dimensions. |
48 | | - /// |
49 | | - /// @param[in] device The framebuffer device name/path |
50 | | - /// |
| 61 | + /** |
| 62 | + * @brief Constructs a DRMFrameGrabber. |
| 63 | + * |
| 64 | + * @param deviceIdx The index of the DRM device to use (e.g., 0 for /dev/dri/card0). |
| 65 | + * @param cropLeft Number of pixels to crop from the left of the screen. |
| 66 | + * @param cropRight Number of pixels to crop from the right of the screen. |
| 67 | + * @param cropTop Number of pixels to crop from the top of the screen. |
| 68 | + * @param cropBottom Number of pixels to crop from the bottom of the screen. |
| 69 | + */ |
51 | 70 | explicit DRMFrameGrabber(int deviceIdx = 0, int cropLeft=0, int cropRight=0, int cropTop=0, int cropBottom=0); |
52 | 71 |
|
| 72 | + /** |
| 73 | + * @brief Destructor for the DRMFrameGrabber. |
| 74 | + * Ensures that all DRM resources are properly released by calling freeResources(). |
| 75 | + */ |
53 | 76 | ~DRMFrameGrabber() override; |
54 | 77 |
|
| 78 | + /** |
| 79 | + * @brief Releases all allocated DRM resources. |
| 80 | + * This includes closing the device file descriptor and freeing memory associated with |
| 81 | + * connectors, encoders, CRTCs, planes, and framebuffers. |
| 82 | + */ |
55 | 83 | void freeResources(); |
56 | 84 |
|
57 | | - /// |
58 | | - /// Captures a single snapshot of the display and writes the data to the given image. The |
59 | | - /// provided image should have the same dimensions as the configured values (_width and |
60 | | - /// _height) |
61 | | - /// |
62 | | - /// @param[out] image The snapped screenshot (should be initialized with correct width and |
63 | | - /// height) |
64 | | - /// |
| 85 | + /** |
| 86 | + * @brief Captures a single frame from the configured DRM device. |
| 87 | + * The captured frame is processed (cropped and scaled) and stored in the provided image object. |
| 88 | + * |
| 89 | + * @param[out] image The Image object to store the captured frame. It must be initialized |
| 90 | + * with the correct dimensions before calling this function. |
| 91 | + * @return 0 on success, a negative value on failure. |
| 92 | + */ |
65 | 93 | int grabFrame(Image<ColorRgb> & image) override; |
66 | 94 |
|
67 | | - /// |
68 | | - /// @brief Setup a new capture screen, will free the previous one |
69 | | - /// @return True on success, false if no screen is found |
70 | | - /// |
| 95 | + /** |
| 96 | + * @brief Initializes the DRM device for screen capturing. |
| 97 | + * This involves opening the device, identifying active connectors, CRTCs, and planes, |
| 98 | + * and setting up the necessary resources for grabbing frames. |
| 99 | + * |
| 100 | + * @return True if the screen was set up successfully, false otherwise. |
| 101 | + */ |
71 | 102 | bool setupScreen() override; |
72 | 103 |
|
| 104 | + /** |
| 105 | + * @brief Gets the resolution of the currently configured screen. |
| 106 | + * |
| 107 | + * @return A QSize object containing the width and height of the screen. |
| 108 | + */ |
73 | 109 | QSize getScreenSize() const override; |
| 110 | + |
| 111 | + /** |
| 112 | + * @brief Gets the resolution of a specific DRM device. |
| 113 | + * |
| 114 | + * @param device The name of the device (e.g., "card0"). |
| 115 | + * @return A QSize object containing the width and height of the specified screen. |
| 116 | + */ |
74 | 117 | QSize getScreenSize(const QString& device) const; |
75 | 118 |
|
76 | | - /// |
77 | | - ///@brief Set new width and height for the DRM-grabber, overwrite Grabber.h implementation |
| 119 | + /** |
| 120 | + * @brief Sets the desired capture width and height. |
| 121 | + * This will affect the dimensions of the image returned by grabFrame(). |
| 122 | + * |
| 123 | + * @param width The desired capture width. |
| 124 | + * @param height The desired capture height. |
| 125 | + * @return True on success, false on failure. |
| 126 | + */ |
78 | 127 | bool setWidthHeight(int width, int height) override; |
79 | 128 |
|
| 129 | + /** |
| 130 | + * @brief Returns the full device path for the current DRM grabber instance. |
| 131 | + * For example, "/dev/dri/card0". |
| 132 | + * |
| 133 | + * @return A QString containing the device name. |
| 134 | + */ |
80 | 135 | QString getDeviceName() const {return QString("%1/%2%3").arg(DRM_DIR_NAME, DRM_PRIMARY_MINOR_NAME).arg(_input);} |
81 | 136 |
|
| 137 | + /** |
| 138 | + * @brief Retrieves a list of available DRM input devices. |
| 139 | + * |
| 140 | + * @return A QJsonArray where each element is a QJsonObject describing a found device. |
| 141 | + */ |
82 | 142 | QJsonArray getInputDeviceDetails() const override; |
83 | 143 |
|
84 | | - /// |
85 | | - /// @brief Discover DRM screens available (for configuration). |
86 | | - /// |
87 | | - /// @param[in] params Parameters used to overwrite discovery default behaviour |
88 | | - /// |
89 | | - /// @return A JSON structure holding a list of devices found |
90 | | - /// |
| 144 | + /** |
| 145 | + * @brief Discovers available DRM devices and their properties. |
| 146 | + * This is used for configuration purposes, allowing a user to see available screens. |
| 147 | + * |
| 148 | + * @param params JSON object with parameters to customize the discovery process. |
| 149 | + * @return A QJsonObject containing a list of discovered devices and their details. |
| 150 | + */ |
91 | 151 | QJsonObject discover(const QJsonObject& params); |
92 | 152 |
|
93 | 153 | private: |
94 | 154 |
|
| 155 | + /** |
| 156 | + * @brief Opens the DRM device file descriptor. |
| 157 | + * @return True on success, false on failure. |
| 158 | + */ |
95 | 159 | bool openDevice(); |
| 160 | + |
| 161 | + /** |
| 162 | + * @brief Closes the DRM device file descriptor. |
| 163 | + * @return True on success, false on failure. |
| 164 | + */ |
96 | 165 | bool closeDevice(); |
| 166 | + |
| 167 | + /** |
| 168 | + * @brief Gathers information about the active screen configuration. |
| 169 | + * This includes enumerating connectors, encoders, finding the active CRTC and primary plane. |
| 170 | + * @return True on success, false on failure. |
| 171 | + */ |
97 | 172 | bool getScreenInfo(); |
98 | 173 |
|
| 174 | + /** |
| 175 | + * @brief Helper function to discover DRM resources for a given device. |
| 176 | + * @param[in] device The device path (e.g., "/dev/dri/card0"). |
| 177 | + * @param[out] resources A struct to be filled with the discovered resource information. |
| 178 | + * @return True on success, false on failure. |
| 179 | + */ |
| 180 | + bool discoverDrmResources(const QString& device, DrmResources& resources) const; |
| 181 | + |
| 182 | + /** |
| 183 | + * @brief Sets the client capabilities for the DRM device connection. |
| 184 | + * Specifically, it requests universal plane support. |
| 185 | + */ |
| 186 | + void setDrmClientCaps(); |
| 187 | + |
| 188 | + /** |
| 189 | + * @brief Enumerates all available connectors and encoders for the device. |
| 190 | + * @param resources The DRM resources structure obtained from the device. |
| 191 | + */ |
| 192 | + void enumerateConnectorsAndEncoders(const drmModeRes* resources); |
| 193 | + |
| 194 | + /** |
| 195 | + * @brief Finds the active CRTC (CRT Controller) that is connected to a display. |
| 196 | + * @param resources The DRM resources structure obtained from the device. |
| 197 | + */ |
| 198 | + void findActiveCrtc(const drmModeRes* resources); |
| 199 | + |
| 200 | + /** |
| 201 | + * @brief Checks if a given plane is the primary plane for the active CRTC. |
| 202 | + * @param planeId The ID of the plane to check. |
| 203 | + * @param properties The properties of the plane object. |
| 204 | + * @return True if it is the primary plane, false otherwise. |
| 205 | + */ |
| 206 | + bool isPrimaryPlaneForCrtc(uint32_t planeId, const drmModeObjectProperties* properties); |
| 207 | + |
| 208 | + /** |
| 209 | + * @brief Finds the primary display plane associated with the active CRTC. |
| 210 | + * The primary plane is the one that holds the main desktop image. |
| 211 | + * @param planeResources The list of available planes. |
| 212 | + */ |
| 213 | + void findPrimaryPlane(const drmModePlaneRes* planeResources); |
| 214 | + |
| 215 | + /** |
| 216 | + * @brief Retrieves properties for various DRM objects like connectors and planes. |
| 217 | + * This is currently a placeholder and not fully implemented. |
| 218 | + */ |
| 219 | + void getDrmObjectProperties() const; |
| 220 | + |
| 221 | + /** |
| 222 | + * @brief Retrieves the framebuffer(s) associated with the primary plane. |
| 223 | + * This is necessary to get a handle to the screen's pixel data. |
| 224 | + */ |
| 225 | + void getFramebuffers(); |
| 226 | + |
| 227 | + /// The file descriptor for the opened DRM device. |
99 | 228 | int _deviceFd; |
100 | | - /// Map of available connectors |
| 229 | + |
| 230 | + /// Map of available connectors (e.g., HDMI, DP), keyed by connector ID. |
101 | 231 | std::map<uint32_t, std::unique_ptr<Connector>> _connectors; |
102 | 232 |
|
103 | | - /// Map of available encoders |
| 233 | + /// Map of available encoders, keyed by encoder ID. |
104 | 234 | std::map<uint32_t, std::unique_ptr<Encoder>> _encoders; |
105 | | - drmModeCrtcPtr _crtc; |
106 | | - std::map<uint32_t, drmModePlanePtr> _planes; |
| 235 | + |
| 236 | + /// Pointer to the active CRTC (CRT Controller). |
| 237 | + drmModeCrtcPtr _crtc; |
| 238 | + |
| 239 | + /// Map of available display planes, keyed by plane ID. |
| 240 | + std::map<uint32_t, drmModePlanePtr> _planes; |
| 241 | + |
| 242 | + /// Map of framebuffers attached to the CRTC, keyed by framebuffer ID. |
107 | 243 | std::map<uint32_t, drmModeFB2Ptr> _framebuffers; |
108 | 244 |
|
| 245 | + /// The pixel format of the captured framebuffer. |
109 | 246 | PixelFormat _pixelFormat; |
110 | 247 | }; |
111 | 248 |
|
0 commit comments