├── CMakeLists.txt ├── README.md ├── drm_bo.cpp ├── drm_bo.h ├── drm_dev.cpp ├── drm_dev.h ├── drm_modeset.cpp ├── drm_modeset.h ├── drm_test_1.cpp ├── drm_test_2.cpp ├── v4l2.cpp └── v4l2.h /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | project(drm_test) 3 | 4 | #set(CMAKE_CXX_STANDARD 11) 5 | set(CMAKE_SYSTEM_NAME Linux) 6 | set(CMAKE_BUILD_TYPE Release) 7 | 8 | set(CMAKE_C_COMPILER gcc) 9 | set(CMAKE_CXX_COMPILER g++) 10 | 11 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") 12 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -march=native -O3 -pthread") 13 | SET(CMAKE_BUILD_TYPE "Debug") 14 | SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g2 -ggdb") 15 | SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall") 16 | 17 | include_directories(${CMAKE_SOURCE_DIR}/ 18 | #/usr/include 19 | /usr/include/libdrm) 20 | #../samples-rklinux-opengl-master/native/include) 21 | 22 | #link_directories(#/usr/lib 23 | #/usr/lib/aarch64-linux-gnu 24 | # ../samples-rklinux-opengl-master/native/lib) 25 | set(link_libs /usr/lib/aarch64-linux-gnu/libdrm.so 26 | pthread 27 | ) 28 | #/usr/lib/aarch64-linux-gnu/libdrm_amdgpu.so 29 | #/usr/lib/aarch64-linux-gnu/libdrm_freedreno.so 30 | #/usr/lib/aarch64-linux-gnu/libdrm_nouveau.so) 31 | #/usr/lib/aarch64-linux-gnu/libdrm_radeon.so) 32 | #/usr/lib/aarch64-linux-gnu/libdrm_tegra.so) 33 | 34 | aux_source_directory(${CMAKE_SOURCE_DIR}/ _FILE) 35 | add_executable(drm_test drm_test.cpp ${_FILE}) 36 | target_link_libraries(drm_test ${link_libs}) 37 | #target_include_directories(glsample_gbm PUBLIC ./native/include/EGLs/winsys_gbm) 38 | 39 | #target_link_libraries(glsample_gbm mali-gbm drm) 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # v4l2_drm 2 | drm_test_2.cpp 是单摄单屏代码,对于demo中的 crtl_index 、plane_index 注意一下,这里很容易出 bug,如果你们不幸出错了,换个数字试一下,这个和你们硬件有关的; 3 | drm_test_1.cpp 是 多线程、绑定CPU、双摄双显示窗口 的版本; 4 | 个人觉得代码还有优化空间,欢迎各位兄贵伸出援手。 5 | QQ : 1094504629 有需要加我,回复 DRM 。 6 | -------------------------------------------------------------------------------- /drm_bo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "drm_bo.h" 14 | #include "drm_dev.h" 15 | 16 | static int add_fb_sp_bo(struct sp_bo *bo, uint32_t format) 17 | { 18 | int ret; 19 | uint32_t handles[4], pitches[4], offsets[4]; 20 | 21 | handles[0] = bo->handle; 22 | pitches[0] = bo->pitch; // pitch = width * (bpp / 8) 23 | offsets[0] = 0; 24 | 25 | handles[1] = bo->handle; 26 | pitches[1] = pitches[0]; 27 | offsets[1] = pitches[0] * bo->height; // offsets[1] equal to a image's size --> width*height*channel 28 | 29 | ret = drmModeAddFB2(bo->dev->fd, bo->width, bo->height, 30 | format, handles, pitches, offsets, 31 | &bo->fb_id, bo->flags); 32 | if (ret) { 33 | printf("failed to create fb ret=%d\n", ret); 34 | return ret; 35 | } 36 | return 0; 37 | } 38 | 39 | static int map_sp_bo(struct sp_bo *bo) 40 | { 41 | int ret; 42 | struct drm_mode_map_dumb md; 43 | 44 | if (bo->map_addr) 45 | return 0; 46 | 47 | md.handle = bo->handle; 48 | ret = drmIoctl(bo->dev->fd, DRM_IOCTL_MODE_MAP_DUMB, &md); 49 | if (ret) { 50 | printf("failed to map sp_bo ret=%d\n", ret); 51 | return ret; 52 | } 53 | 54 | bo->map_addr = mmap(NULL, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, 55 | bo->dev->fd, md.offset); 56 | if (bo->map_addr == MAP_FAILED) { 57 | printf("failed to map bo ret=%d\n", -errno); 58 | return -errno; 59 | } 60 | return 0; 61 | } 62 | 63 | struct sp_bo *create_sp_bo(struct sp_dev *dev, uint32_t width, uint32_t height, 64 | uint32_t depth,uint32_t _bpp, uint32_t format, uint32_t flags) 65 | { 66 | int ret; 67 | struct drm_mode_create_dumb cd; 68 | struct sp_bo *bo; 69 | 70 | bo = (sp_bo *)calloc(1, sizeof(*bo)); 71 | if (!bo) 72 | return NULL; 73 | 74 | cd.height = height; 75 | cd.width = width; 76 | cd.bpp = _bpp; 77 | cd.flags = flags; 78 | 79 | ret = drmIoctl(dev->fd, DRM_IOCTL_MODE_CREATE_DUMB, &cd); 80 | if (ret) { 81 | printf("failed to create sp_bo %d\n", ret); 82 | goto err; 83 | } 84 | 85 | bo->dev = dev; 86 | bo->width = width; 87 | bo->height = height; 88 | bo->depth = depth; 89 | bo->bpp = _bpp; 90 | bo->format = format; 91 | //printf("format = %d\n",format); 92 | bo->flags = flags; 93 | 94 | bo->handle = cd.handle; 95 | bo->pitch = cd.pitch; 96 | bo->size = cd.size; 97 | 98 | ret = add_fb_sp_bo(bo, format); 99 | if (ret) { 100 | printf("failed to add fb ret=%d\n", ret); 101 | goto err; 102 | } 103 | 104 | ret = map_sp_bo(bo); 105 | if (ret) { 106 | printf("failed to map bo ret=%d\n", ret); 107 | goto err; 108 | } 109 | 110 | return bo; 111 | 112 | err: 113 | free_sp_bo(bo); 114 | return NULL; 115 | } 116 | 117 | void free_sp_bo(struct sp_bo *bo) 118 | { 119 | int ret; 120 | struct drm_mode_destroy_dumb dd; 121 | 122 | if (!bo) 123 | return; 124 | 125 | if (bo->map_addr) 126 | munmap(bo->map_addr, bo->size); 127 | 128 | if (bo->fb_id) { 129 | ret = drmModeRmFB(bo->dev->fd, bo->fb_id); 130 | if (ret) 131 | printf("Failed to rmfb ret=%d!\n", ret); 132 | } 133 | 134 | if (bo->handle) { 135 | dd.handle = bo->handle; 136 | ret = drmIoctl(bo->dev->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dd); 137 | if (ret) 138 | printf("Failed to destroy buffer ret=%d\n", ret); 139 | } 140 | 141 | free(bo); 142 | } 143 | 144 | -------------------------------------------------------------------------------- /drm_bo.h: -------------------------------------------------------------------------------- 1 | #ifndef __DRM_BO_H__ 2 | #define __DRM_BO_H__ 3 | 4 | #include 5 | #include "drm_dev.h" 6 | 7 | struct sp_dev; 8 | 9 | struct sp_bo { 10 | struct sp_dev *dev; 11 | 12 | uint32_t width; 13 | uint32_t height; 14 | uint32_t depth; 15 | uint32_t bpp; 16 | uint32_t format; 17 | uint32_t flags; 18 | 19 | uint32_t fb_id; 20 | uint32_t handle; 21 | void *map_addr; 22 | uint32_t pitch; 23 | uint32_t size; 24 | }; 25 | 26 | extern "C" 27 | { 28 | struct sp_bo *create_sp_bo(struct sp_dev *dev, uint32_t width, uint32_t height, 29 | uint32_t depth,uint32_t _bpp, uint32_t format, uint32_t flags); 30 | void fill_bo(struct sp_bo *bo, uint8_t a, uint8_t r, uint8_t g, uint8_t b); 31 | void draw_rect(struct sp_bo *bo, uint32_t x, uint32_t y, uint32_t width, 32 | uint32_t height, uint8_t a, uint8_t r, uint8_t g, uint8_t b); 33 | void free_sp_bo(struct sp_bo *bo); 34 | } 35 | 36 | #endif 37 | 38 | -------------------------------------------------------------------------------- /drm_dev.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "drm_bo.h" 15 | #include "drm_dev.h" 16 | #include "drm_modeset.h" 17 | 18 | static void show_usage(char *name) 19 | { 20 | printf("Usage: %s [OPTION]\n", name); 21 | printf(" -c, --card Index of dri card (ie: /dev/dri/cardN)\n"); 22 | printf(" -r, --crtc Index of crtc to use for test\n"); 23 | printf("\n\n"); 24 | } 25 | 26 | void parse_arguments(int argc, char *argv[], int *card, int *crtc) 27 | { 28 | static struct option options[] = { 29 | { "card", required_argument, NULL, 'c' }, 30 | { "crtc", required_argument, NULL, 'r' }, 31 | { "help", no_argument, NULL, 'h' }, 32 | }; 33 | int option_index = 0; 34 | int c; 35 | 36 | *card = -1; 37 | *crtc = -1; 38 | do { 39 | c = getopt_long(argc, argv, "c:r:h", options, &option_index); 40 | switch (c) { 41 | case 0: 42 | case 'h': 43 | show_usage(argv[0]); 44 | exit(0); 45 | case -1: 46 | break; 47 | case 'c': 48 | if (optarg[0] < '0' || optarg[0] > '9') { 49 | printf("Invalid card value '%s'!\n", optarg); 50 | show_usage(argv[0]); 51 | exit(-1); 52 | } 53 | *card = optarg[0] - '0'; 54 | break; 55 | case 'r': 56 | if (optarg[0] < '0' || optarg[0] > '9') { 57 | printf("Invalid crtc value '%s'!\n", optarg); 58 | show_usage(argv[0]); 59 | exit(-1); 60 | } 61 | *crtc = optarg[0] - '0'; 62 | break; 63 | } 64 | } while (c != -1); 65 | 66 | if (*card < 0 || *crtc < 0) { 67 | show_usage(argv[0]); 68 | exit(-1); 69 | } 70 | } 71 | 72 | static uint32_t get_prop_id(struct sp_dev *dev, 73 | drmModeObjectPropertiesPtr props, const char *name) 74 | { 75 | drmModePropertyPtr p; 76 | uint32_t i, prop_id = 0; /* Property ID should always be > 0 */ 77 | 78 | for (i = 0; !prop_id && i < props->count_props; i++) { 79 | p = drmModeGetProperty(dev->fd, props->props[i]); 80 | if (!strcmp(p->name, name)) 81 | prop_id = p->prop_id; 82 | drmModeFreeProperty(p); 83 | } 84 | if (!prop_id) 85 | printf("Could not find %s property\n", name); 86 | return prop_id; 87 | } 88 | 89 | static int get_supported_format(struct sp_plane *plane, uint32_t *format, uint32_t _format) 90 | { 91 | uint32_t i; 92 | 93 | for (i = 0; i < plane->plane->count_formats; i++) { 94 | if (plane->plane->formats[i] == _format) { 95 | *format = plane->plane->formats[i]; 96 | return 0; 97 | } 98 | } 99 | printf("No suitable formats found!\n"); 100 | return -ENOENT; 101 | } 102 | 103 | struct sp_dev *create_sp_dev(int card, uint32_t _format) 104 | { 105 | struct sp_dev *dev; 106 | int ret, fd, i, j; 107 | drmModeRes *r = NULL; 108 | drmModePlaneRes *pr = NULL; 109 | char card_path[256]; 110 | 111 | snprintf(card_path, sizeof(card_path), "/dev/dri/card%d", card); 112 | 113 | fd = open(card_path, O_RDWR); 114 | if (fd < 0) { 115 | printf("failed to open card0\n"); 116 | return NULL; 117 | } 118 | 119 | dev = (sp_dev *)calloc(1, sizeof(*dev)); 120 | if (!dev) { 121 | printf("failed to allocate dev\n"); 122 | return NULL; 123 | } 124 | 125 | dev->fd = fd; 126 | 127 | ret = drmSetClientCap(dev->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); 128 | if (ret) { 129 | printf("failed to set client cap\n"); 130 | goto err; 131 | } 132 | 133 | ret = drmSetClientCap(dev->fd, DRM_CLIENT_CAP_ATOMIC, 1); 134 | if (ret) { 135 | printf("Failed to set atomic cap %d", ret); 136 | goto err; 137 | } 138 | 139 | r = drmModeGetResources(dev->fd); 140 | if (!r) { 141 | printf("failed to get r\n"); 142 | goto err; 143 | } 144 | 145 | dev->num_connectors = r->count_connectors; 146 | dev->connectors = (sp_connector *)calloc(dev->num_connectors, 147 | sizeof(struct sp_connector)); 148 | if (!dev->connectors) { 149 | printf("failed to allocate connectors\n"); 150 | goto err; 151 | } 152 | for (i = 0; i < dev->num_connectors; i++) { 153 | drmModeObjectPropertiesPtr props; 154 | dev->connectors[i].conn = drmModeGetConnector(dev->fd, 155 | r->connectors[i]); 156 | if (!dev->connectors[i].conn) { 157 | printf("failed to get connector %d\n", i); 158 | goto err; 159 | } 160 | 161 | props = drmModeObjectGetProperties(dev->fd, r->connectors[i], 162 | DRM_MODE_OBJECT_CONNECTOR); 163 | if (!props) { 164 | printf("failed to get connector properties\n"); 165 | goto err; 166 | } 167 | 168 | dev->connectors[i].crtc_id_pid = get_prop_id(dev, props, 169 | "CRTC_ID"); 170 | drmModeFreeObjectProperties(props); 171 | if (!dev->connectors[i].crtc_id_pid) 172 | goto err; 173 | } 174 | 175 | dev->num_encoders = r->count_encoders; 176 | dev->encoders = (_drmModeEncoder **)calloc(dev->num_encoders, sizeof(*dev->encoders)); 177 | if (!dev->encoders) { 178 | printf("failed to allocate encoders\n"); 179 | goto err; 180 | } 181 | for (i = 0; i < dev->num_encoders; i++) { 182 | dev->encoders[i] = drmModeGetEncoder(dev->fd, r->encoders[i]); 183 | if (!dev->encoders[i]) { 184 | printf("failed to get encoder %d\n", i); 185 | goto err; 186 | } 187 | } 188 | 189 | dev->num_crtcs = r->count_crtcs; 190 | dev->crtcs = (sp_crtc *)calloc(dev->num_crtcs, sizeof(struct sp_crtc)); 191 | if (!dev->crtcs) { 192 | printf("failed to allocate crtcs\n"); 193 | goto err; 194 | } 195 | for (i = 0; i < dev->num_crtcs; i++) { 196 | drmModeObjectPropertiesPtr props; 197 | 198 | dev->crtcs[i].crtc = drmModeGetCrtc(dev->fd, r->crtcs[i]); 199 | if (!dev->crtcs[i].crtc) { 200 | printf("failed to get crtc %d\n", i); 201 | goto err; 202 | } 203 | dev->crtcs[i].pipe = i; 204 | dev->crtcs[i].num_planes = 0; 205 | 206 | props = drmModeObjectGetProperties(dev->fd, r->crtcs[i], 207 | DRM_MODE_OBJECT_CRTC); 208 | if (!props) { 209 | printf("failed to get crtc properties\n"); 210 | goto err; 211 | } 212 | 213 | dev->crtcs[i].mode_pid = get_prop_id(dev, props, "MODE_ID"); 214 | dev->crtcs[i].active_pid = get_prop_id(dev, props, "ACTIVE"); 215 | drmModeFreeObjectProperties(props); 216 | if (!dev->crtcs[i].mode_pid || !dev->crtcs[i].active_pid) 217 | goto err; 218 | } 219 | 220 | pr = drmModeGetPlaneResources(dev->fd); 221 | if (!pr) { 222 | printf("failed to get plane resources\n"); 223 | goto err; 224 | } 225 | dev->num_planes = pr->count_planes; 226 | dev->planes = (sp_plane *)calloc(dev->num_planes, sizeof(struct sp_plane)); 227 | for(i = 0; i < dev->num_planes; i++) { 228 | drmModeObjectPropertiesPtr props; 229 | struct sp_plane *plane = &dev->planes[i]; 230 | 231 | plane->dev = dev; 232 | plane->plane = drmModeGetPlane(dev->fd, pr->planes[i]); 233 | if (!plane->plane) { 234 | printf("failed to get plane %d\n", i); 235 | goto err; 236 | } 237 | plane->bo = NULL; 238 | plane->in_use = 0; 239 | 240 | ret = get_supported_format(plane, &plane->format, _format); 241 | if (ret) { 242 | printf("failed to get supported format: %d\n", ret); 243 | goto err; 244 | } 245 | 246 | for (j = 0; j < dev->num_crtcs; j++) { 247 | if (plane->plane->possible_crtcs & (1 << j)) 248 | dev->crtcs[j].num_planes++; 249 | } 250 | 251 | props = drmModeObjectGetProperties(dev->fd, pr->planes[i], 252 | DRM_MODE_OBJECT_PLANE); 253 | if (!props) { 254 | printf("failed to get plane properties\n"); 255 | goto err; 256 | } 257 | plane->crtc_pid = get_prop_id(dev, props, "CRTC_ID"); 258 | if (!plane->crtc_pid) { 259 | drmModeFreeObjectProperties(props); 260 | goto err; 261 | } 262 | plane->fb_pid = get_prop_id(dev, props, "FB_ID"); 263 | if (!plane->fb_pid) { 264 | drmModeFreeObjectProperties(props); 265 | goto err; 266 | } 267 | plane->crtc_x_pid = get_prop_id(dev, props, "CRTC_X"); 268 | if (!plane->crtc_x_pid) { 269 | drmModeFreeObjectProperties(props); 270 | goto err; 271 | } 272 | plane->crtc_y_pid = get_prop_id(dev, props, "CRTC_Y"); 273 | if (!plane->crtc_y_pid) { 274 | drmModeFreeObjectProperties(props); 275 | goto err; 276 | } 277 | plane->crtc_w_pid = get_prop_id(dev, props, "CRTC_W"); 278 | if (!plane->crtc_w_pid) { 279 | drmModeFreeObjectProperties(props); 280 | goto err; 281 | } 282 | plane->crtc_h_pid = get_prop_id(dev, props, "CRTC_H"); 283 | if (!plane->crtc_h_pid) { 284 | drmModeFreeObjectProperties(props); 285 | goto err; 286 | } 287 | plane->src_x_pid = get_prop_id(dev, props, "SRC_X"); 288 | if (!plane->src_x_pid) { 289 | drmModeFreeObjectProperties(props); 290 | goto err; 291 | } 292 | plane->src_y_pid = get_prop_id(dev, props, "SRC_Y"); 293 | if (!plane->src_y_pid) { 294 | drmModeFreeObjectProperties(props); 295 | goto err; 296 | } 297 | plane->src_w_pid = get_prop_id(dev, props, "SRC_W"); 298 | if (!plane->src_w_pid) { 299 | drmModeFreeObjectProperties(props); 300 | goto err; 301 | } 302 | plane->src_h_pid = get_prop_id(dev, props, "SRC_H"); 303 | if (!plane->src_h_pid) { 304 | drmModeFreeObjectProperties(props); 305 | goto err; 306 | } 307 | drmModeFreeObjectProperties(props); 308 | } 309 | 310 | if (pr) 311 | drmModeFreePlaneResources(pr); 312 | if (r) 313 | drmModeFreeResources(r); 314 | 315 | return dev; 316 | err: 317 | if (pr) 318 | drmModeFreePlaneResources(pr); 319 | if (r) 320 | drmModeFreeResources(r); 321 | destroy_sp_dev(dev); 322 | return NULL; 323 | } 324 | 325 | void destroy_sp_dev(struct sp_dev *dev) 326 | { 327 | int i; 328 | 329 | if (dev->planes) { 330 | for (i = 0; i< dev->num_planes; i++) { 331 | if (dev->planes[i].in_use) 332 | put_sp_plane(&dev->planes[i]); 333 | if (dev->planes[i].plane) 334 | drmModeFreePlane(dev->planes[i].plane); 335 | if (dev->planes[i].bo) 336 | free_sp_bo(dev->planes[i].bo); 337 | } 338 | free(dev->planes); 339 | } 340 | if (dev->crtcs) { 341 | for (i = 0; i< dev->num_crtcs; i++) { 342 | if (dev->crtcs[i].crtc) 343 | drmModeFreeCrtc(dev->crtcs[i].crtc); 344 | } 345 | free(dev->crtcs); 346 | } 347 | if (dev->encoders) { 348 | for (i = 0; i< dev->num_encoders; i++) { 349 | if (dev->encoders[i]) 350 | drmModeFreeEncoder(dev->encoders[i]); 351 | } 352 | free(dev->encoders); 353 | } 354 | if (dev->connectors) { 355 | for (i = 0; i< dev->num_connectors; i++) { 356 | if (dev->connectors[i].conn) 357 | drmModeFreeConnector(dev->connectors[i].conn); 358 | } 359 | free(dev->connectors); 360 | } 361 | 362 | close(dev->fd); 363 | free(dev); 364 | } 365 | -------------------------------------------------------------------------------- /drm_dev.h: -------------------------------------------------------------------------------- 1 | #ifndef __DRM_DEV_H__ 2 | #define __DRM_DEV_H__ 3 | 4 | #include 5 | #include 6 | 7 | struct sp_bo; 8 | struct sp_dev; 9 | 10 | struct sp_plane { 11 | struct sp_dev *dev; 12 | drmModePlanePtr plane; 13 | struct sp_bo *bo; 14 | int in_use; 15 | uint32_t format; 16 | 17 | /* Property ID's */ 18 | uint32_t crtc_pid; 19 | uint32_t fb_pid; 20 | uint32_t zpos_pid; 21 | uint32_t crtc_x_pid; 22 | uint32_t crtc_y_pid; 23 | uint32_t crtc_w_pid; 24 | uint32_t crtc_h_pid; 25 | uint32_t src_x_pid; 26 | uint32_t src_y_pid; 27 | uint32_t src_w_pid; 28 | uint32_t src_h_pid; 29 | }; 30 | 31 | struct sp_connector { 32 | drmModeConnectorPtr conn; 33 | uint32_t crtc_id_pid; 34 | }; 35 | 36 | struct sp_crtc { 37 | drmModeCrtcPtr crtc; 38 | int pipe; 39 | int num_planes; 40 | uint32_t mode_pid; 41 | uint32_t active_pid; 42 | }; 43 | 44 | struct sp_dev { 45 | int fd; 46 | 47 | int num_connectors; 48 | struct sp_connector *connectors; 49 | 50 | int num_encoders; 51 | drmModeEncoderPtr *encoders; 52 | 53 | int num_crtcs; 54 | struct sp_crtc *crtcs; 55 | 56 | int num_planes; 57 | struct sp_plane *planes; 58 | }; 59 | 60 | extern "C" 61 | { 62 | void parse_arguments(int argc, char *argv[], int *card, int *crtc); 63 | 64 | struct sp_dev *create_sp_dev(int card,uint32_t _format); 65 | void destroy_sp_dev(struct sp_dev *dev); 66 | } 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /drm_modeset.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "drm_modeset.h" 10 | #include "drm_bo.h" 11 | #include "drm_dev.h" 12 | 13 | static int set_crtc_mode(struct sp_dev *dev, struct sp_crtc *crtc, 14 | struct sp_connector *conn, drmModeModeInfoPtr mode) 15 | { 16 | int ret; 17 | struct drm_mode_create_blob create_blob; 18 | drmModeAtomicReqPtr pset; 19 | 20 | memset(&create_blob, 0, sizeof(create_blob)); 21 | create_blob.length = sizeof(struct drm_mode_modeinfo); 22 | create_blob.data = (__u64)(uintptr_t)mode; 23 | 24 | ret = drmIoctl(dev->fd, DRM_IOCTL_MODE_CREATEPROPBLOB, &create_blob); 25 | if (ret) { 26 | printf("Failed to create mode property blob %d", ret); 27 | return ret; 28 | } 29 | 30 | pset = drmModeAtomicAlloc(); // instead of drmModeSetCrtc(crtc_id, fb_id, conn_id, &mode) begin: 31 | if (!pset) { 32 | printf("Failed to allocate property set"); 33 | return -1; 34 | } 35 | 36 | ret = drmModeAtomicAddProperty(pset, crtc->crtc->crtc_id, 37 | crtc->mode_pid, create_blob.blob_id) || 38 | drmModeAtomicAddProperty(pset, crtc->crtc->crtc_id, 39 | crtc->active_pid, 1) || 40 | drmModeAtomicAddProperty(pset, conn->conn->connector_id, 41 | conn->crtc_id_pid, crtc->crtc->crtc_id); 42 | if (ret) { 43 | printf("Failed to add blob %d to pset", create_blob.blob_id); 44 | drmModeAtomicFree(pset); 45 | return ret; 46 | } 47 | 48 | ret = drmModeAtomicCommit(dev->fd, pset, DRM_MODE_ATOMIC_ALLOW_MODESET, 49 | NULL); 50 | 51 | drmModeAtomicFree(pset); // end 52 | 53 | if (ret) { 54 | printf("Failed to commit pset ret=%d\n", ret); 55 | return ret; 56 | } 57 | 58 | memcpy(&crtc->crtc->mode, mode, sizeof(struct drm_mode_modeinfo)); 59 | crtc->crtc->mode_valid = 1; 60 | return 0; 61 | } 62 | 63 | int initialize_screens(struct sp_dev *dev) 64 | { 65 | int ret, i, j; 66 | unsigned crtc_mask = 0; // unsigned int ? 67 | 68 | for (i = 0; i < dev->num_connectors; i++) { 69 | struct sp_connector *c = &dev->connectors[i]; 70 | drmModeModeInfoPtr m = NULL; 71 | drmModeEncoderPtr e = NULL; 72 | struct sp_crtc *cr = NULL; 73 | 74 | if (c->conn->connection != DRM_MODE_CONNECTED) 75 | continue; 76 | 77 | if (!c->conn->count_modes) { 78 | printf("connector has no modes, skipping\n"); 79 | continue; 80 | } 81 | 82 | /* Take the first unless there's a preferred mode */ 83 | m = &c->conn->modes[0]; 84 | for (j = 0; j < c->conn->count_modes; j++) { 85 | drmModeModeInfoPtr tmp_m = &c->conn->modes[j]; 86 | 87 | if (!(tmp_m->type & DRM_MODE_TYPE_PREFERRED)) 88 | continue; 89 | 90 | m = tmp_m; 91 | break; 92 | } 93 | 94 | if (!c->conn->count_encoders) { 95 | printf("no possible encoders for connector\n"); 96 | continue; 97 | } 98 | 99 | for (j = 0; j < dev->num_encoders; j++) { 100 | e = dev->encoders[j]; 101 | if (e->encoder_id == c->conn->encoders[0]) 102 | break; 103 | } 104 | if (j == dev->num_encoders) { 105 | printf("could not find encoder for the connector\n"); 106 | continue; 107 | } 108 | 109 | for (j = 0; j < dev->num_crtcs; j++) { 110 | if ((1 << j) & crtc_mask) 111 | continue; 112 | 113 | cr = &dev->crtcs[j]; 114 | 115 | if ((1 << j) & e->possible_crtcs) 116 | break; 117 | } 118 | if (j == dev->num_crtcs) { 119 | printf("could not find crtc for the encoder\n"); 120 | continue; 121 | } 122 | 123 | ret = set_crtc_mode(dev, cr, c, m); // here ok then we can display FB 124 | if (ret) { 125 | printf("failed to set mode!\n"); 126 | continue; 127 | } 128 | crtc_mask |= 1 << j; 129 | } 130 | return 0; 131 | } 132 | 133 | struct sp_plane *get_sp_plane(struct sp_dev *dev, struct sp_crtc *crtc) 134 | { 135 | int i; 136 | 137 | for(i = 0; i < dev->num_planes; i++) { 138 | struct sp_plane *p = &dev->planes[i]; 139 | 140 | if (p->in_use) 141 | continue; 142 | 143 | if (!(p->plane->possible_crtcs & (1 << crtc->pipe))) 144 | continue; 145 | 146 | p->in_use = 1; 147 | return p; 148 | } 149 | return NULL; 150 | } 151 | 152 | void put_sp_plane(struct sp_plane *plane) 153 | { 154 | drmModePlanePtr p; 155 | 156 | /* Get the latest plane information (most notably the crtc_id) */ 157 | p = drmModeGetPlane(plane->dev->fd, plane->plane->plane_id); 158 | if (p) 159 | plane->plane = p; 160 | 161 | if (plane->bo) { 162 | free_sp_bo(plane->bo); 163 | plane->bo = NULL; 164 | } 165 | plane->in_use = 0; 166 | } 167 | 168 | int set_sp_plane(struct sp_dev *dev,struct sp_plane *plane,struct sp_crtc *crtc,uint32_t _x,uint32_t _y,uint32_t _w,uint32_t _h) 169 | { 170 | int ret; 171 | uint32_t w, h; 172 | 173 | w = plane->bo->width; 174 | h = plane->bo->height; 175 | 176 | ret = drmModeSetPlane(dev->fd, plane->plane->plane_id, // display FrameBuffer 177 | crtc->crtc->crtc_id, plane->bo->fb_id, 0, _x, _y, _w, _h, 178 | 0, 0, w << 16, h << 16); 179 | if (ret) { 180 | printf("failed to set plane to crtc ret=%d\n", ret); 181 | return ret; 182 | } 183 | 184 | return ret; 185 | } 186 | int set_sp_plane_pset(struct sp_dev *dev, struct sp_plane *plane, 187 | drmModeAtomicReqPtr pset, struct sp_crtc *crtc, int x, int y) 188 | { 189 | int ret; 190 | uint32_t w, h; 191 | 192 | w = plane->bo->width; 193 | h = plane->bo->height; 194 | 195 | if ((w + x) > crtc->crtc->mode.hdisplay) 196 | w = crtc->crtc->mode.hdisplay - x; 197 | if ((h + y) > crtc->crtc->mode.vdisplay) 198 | h = crtc->crtc->mode.vdisplay - y; 199 | 200 | ret = drmModeAtomicAddProperty(pset, plane->plane->plane_id, 201 | plane->crtc_pid, crtc->crtc->crtc_id) 202 | || drmModeAtomicAddProperty(pset, plane->plane->plane_id, 203 | plane->fb_pid, plane->bo->fb_id) 204 | || drmModeAtomicAddProperty(pset, plane->plane->plane_id, 205 | plane->crtc_x_pid, x) 206 | || drmModeAtomicAddProperty(pset, plane->plane->plane_id, 207 | plane->crtc_y_pid, y) 208 | || drmModeAtomicAddProperty(pset, plane->plane->plane_id, 209 | plane->crtc_w_pid, w) 210 | || drmModeAtomicAddProperty(pset, plane->plane->plane_id, 211 | plane->crtc_h_pid, h) 212 | || drmModeAtomicAddProperty(pset, plane->plane->plane_id, 213 | plane->src_x_pid, 0) 214 | || drmModeAtomicAddProperty(pset, plane->plane->plane_id, 215 | plane->src_y_pid, 0) 216 | || drmModeAtomicAddProperty(pset, plane->plane->plane_id, 217 | plane->src_w_pid, w << 16) 218 | || drmModeAtomicAddProperty(pset, plane->plane->plane_id, 219 | plane->src_h_pid, h << 16); 220 | if (ret) { 221 | printf("failed to add properties to the set\n"); 222 | return -1; 223 | } 224 | 225 | return ret; 226 | } 227 | -------------------------------------------------------------------------------- /drm_modeset.h: -------------------------------------------------------------------------------- 1 | #ifndef __DRM_MODESET_H__ 2 | #define __DRM_MODESET_H__ 3 | 4 | #include "drm_dev.h" 5 | 6 | struct sp_dev; 7 | struct sp_crtc; 8 | 9 | extern "C" 10 | { 11 | int initialize_screens(struct sp_dev *dev); 12 | struct sp_plane *get_sp_plane(struct sp_dev *dev, struct sp_crtc *crtc); 13 | void put_sp_plane(struct sp_plane *plane); 14 | 15 | int set_sp_plane(struct sp_dev *dev, struct sp_plane *plane, 16 | struct sp_crtc *crtc, uint32_t _x, uint32_t _y, uint32_t _w, uint32_t _h); 17 | 18 | int set_sp_plane_pset(struct sp_dev *dev, struct sp_plane *plane, 19 | drmModeAtomicReqPtr pset, struct sp_crtc *crtc, int x, int y); 20 | } 21 | 22 | #endif 23 | 24 | -------------------------------------------------------------------------------- /drm_test_1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "v4l2.h" 19 | #include "drm_dev.h" 20 | #include "drm_bo.h" 21 | #include "drm_modeset.h" 22 | 23 | using namespace std; 24 | static int _terminate = 0; 25 | 26 | static void sigint_handler(int arg) 27 | { 28 | _terminate = 1; 29 | } 30 | 31 | int video_display(int cpuid, int video_index, int crtc_index, int plane_index, uint32_t display_x, uint32_t display_y, uint32_t display_w, uint32_t display_h) 32 | { 33 | cpu_set_t mask; 34 | CPU_ZERO(&mask); 35 | CPU_SET(cpuid, &mask); 36 | 37 | if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) 38 | { 39 | printf("set thread affinity failed"); 40 | return(FALSE); 41 | } 42 | printf("Bind CameraCapture process to CPU %d\n", cpuid); 43 | /************************* V4L2 parameter *************************/ 44 | char video[25]; 45 | snprintf(video, sizeof(video), "/dev/video%d", video_index); 46 | unsigned char *srcBuffer = (unsigned char*)malloc(sizeof(unsigned char) * BUFFER_SIZE_src); // yuyv 47 | unsigned char *dstBuffer = (unsigned char*)malloc(sizeof(unsigned char) * BUFFER_SIZE_det); // RGB 48 | /************************* DRM parameter *************************/ 49 | struct sp_dev *dev = NULL; 50 | struct sp_plane **plane = NULL; 51 | struct sp_crtc *test_crtc = NULL; 52 | 53 | int card = 0 ; 54 | uint32_t video_format = DRM_FORMAT_BGR888 ; 55 | printf("video_format = %d\n",video_format); 56 | uint32_t frame_depth = 16, frame_bpp = 24 ; 57 | /************************* V4L2 function *************************/ 58 | printf("***** v4l2 function start *****\n"); 59 | BUF *buffer = v4l2(video) ; 60 | /************************* DRM function *************************/ 61 | printf("***** drm function start *****\n"); 62 | dev = create_sp_dev(card, video_format); 63 | if (!dev) { 64 | printf("Failed to create sp_dev\n"); 65 | return (FALSE); 66 | } 67 | 68 | if (crtc_index >= dev->num_crtcs) { 69 | printf("Invalid crtc %d (num=%d)\n", crtc_index, dev->num_crtcs); 70 | return (FALSE); 71 | } 72 | 73 | int ret = initialize_screens(dev); // ready to display FB 74 | if (ret) { 75 | printf("Failed to initialize screens\n"); 76 | return (FALSE); 77 | } 78 | test_crtc = &dev->crtcs[crtc_index]; // crtc_index is a parameter , i used to set it equal to 0 . 79 | drmModeCrtcPtr save_crtc = test_crtc->crtc ; 80 | drmModeConnector *save_connector = dev->connectors[0].conn; 81 | 82 | plane = (sp_plane **)calloc(dev->num_planes, sizeof(*plane)); 83 | if (!plane) { 84 | printf("Failed to allocate plane array\n"); 85 | return (FALSE); 86 | } 87 | 88 | /* Create our planes */ 89 | int num_test_planes = test_crtc->num_planes; 90 | for (int i = 0; i < num_test_planes; i++) { 91 | plane[i] = get_sp_plane(dev, test_crtc); 92 | if (!plane[i]) { 93 | printf("no unused planes available\n"); 94 | return (FALSE); 95 | } 96 | 97 | plane[i]->bo = create_sp_bo(dev, IMAGE_WIDTH, IMAGE_HEIGHT, frame_depth, frame_bpp, 98 | plane[i]->format, 0); 99 | if (!plane[i]->bo) { 100 | printf("failed to create plane bo\n"); 101 | return (FALSE); 102 | } 103 | 104 | memset(plane[i]->bo->map_addr ,255 ,plane[i]->bo->size) ; 105 | } 106 | printf("plane size = %d\n",plane[plane_index]->bo->size); 107 | printf("plane format = %d\n",plane[plane_index]->bo->format); 108 | /************************* loop start *************************/ 109 | printf("/***************** loop start *****************/\n"); 110 | while(!_terminate) 111 | { 112 | srcBuffer = get_img(buffer, srcBuffer); 113 | yuyv2bgr24(srcBuffer, dstBuffer); 114 | 115 | //memcpy(plane[plane_index]->bo->map_addr, (void *)dstBuffer, plane[plane_index]->bo->size ); 116 | memcpy(plane[plane_index]->bo->map_addr, (void *)dstBuffer, BUFFER_SIZE_det ); 117 | ret = set_sp_plane(dev, plane[plane_index], test_crtc, display_x, display_y, display_w, display_h); 118 | if (ret) { 119 | printf("failed to set plane %d %d\n",plane_index, ret); 120 | return (FALSE); 121 | } 122 | usleep(15 * 1000); 123 | } 124 | 125 | ret = drmModeSetCrtc(dev->fd, save_crtc->crtc_id, save_crtc->buffer_id, 126 | save_crtc->x, save_crtc->y, 127 | &save_connector->connector_id, 1, &save_crtc->mode); 128 | if (ret) { 129 | printf("failed to restore crtc .\n"); 130 | } 131 | 132 | for (int i = 0; i < num_test_planes; i++){ 133 | put_sp_plane(plane[i]); 134 | } 135 | printf("Display is closed !\n"); 136 | free(srcBuffer); 137 | free(dstBuffer); 138 | close_v4l2(buffer); 139 | 140 | destroy_sp_dev(dev); 141 | free(plane); 142 | 143 | return(TRUE); 144 | } 145 | 146 | int main() 147 | { 148 | signal(SIGINT, sigint_handler); 149 | array threads; 150 | threads = {thread(video_display, 0, 10, 0, 0, 128, 0, 1280, 960), 151 | thread(video_display, 1, 12, 0, 2, 128, 1088, 1280, 960), 152 | }; 153 | for (int i = 0; i < 2; i++){ 154 | threads[i].join(); 155 | } 156 | return(TRUE); 157 | } 158 | -------------------------------------------------------------------------------- /drm_test_2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "v4l2.h" 18 | #include "drm_dev.h" 19 | #include "drm_bo.h" 20 | #include "drm_modeset.h" 21 | 22 | static int terminate = 0; 23 | 24 | static void sigint_handler(int arg) 25 | { 26 | terminate = 1; 27 | } 28 | 29 | int main() 30 | { 31 | /************************* V4L2 parameter *************************/ 32 | char video_1[] = "/dev/video10" ; 33 | unsigned char *srcBuffer_1 = (unsigned char*)malloc(sizeof(unsigned char) * BUFFER_SIZE_src); // yuyv 34 | unsigned char *dstBuffer_1 = (unsigned char*)malloc(sizeof(unsigned char) * BUFFER_SIZE_det); // RGB 35 | /************************* DRM parameter *************************/ 36 | struct sp_dev *dev = NULL; 37 | struct sp_plane **plane = NULL; 38 | struct sp_crtc *test_crtc = NULL; 39 | 40 | int card = 0, crtc_index = 0, plane_index = 0; 41 | uint32_t video_format = DRM_FORMAT_BGR888 ; 42 | printf("video_format = %d\n",video_format); 43 | uint32_t display_x = 128 , display_y = 0 ; 44 | uint32_t display_w = 1280 , display_h = 960 ; // display frame width height 45 | uint32_t frame_depth = 16, frame_bpp = 24 ; 46 | /************************* V4L2 function *************************/ 47 | printf("***** v4l2 function start *****\n"); 48 | BUF *buffer_1 = v4l2(video_1) ; 49 | /************************* DRM function *************************/ 50 | printf("***** drm function start *****\n"); 51 | 52 | signal(SIGINT, sigint_handler); 53 | 54 | dev = create_sp_dev(card, video_format); 55 | if (!dev) { 56 | printf("Failed to create sp_dev\n"); 57 | return (FALSE); 58 | } 59 | 60 | if (crtc_index >= dev->num_crtcs) { 61 | printf("Invalid crtc %d (num=%d)\n", crtc_index, dev->num_crtcs); 62 | return (FALSE); 63 | } 64 | 65 | int ret = initialize_screens(dev); // ready to display FB 66 | if (ret) { 67 | printf("Failed to initialize screens\n"); 68 | return (FALSE); 69 | } 70 | test_crtc = &dev->crtcs[crtc_index]; // crtc_index is a parameter , i used to set it equal to 0 . 71 | drmModeCrtcPtr save_crtc = test_crtc->crtc ; 72 | drmModeConnector *save_connector = dev->connectors[0].conn; 73 | 74 | plane = (sp_plane **)calloc(dev->num_planes, sizeof(*plane)); 75 | if (!plane) { 76 | printf("Failed to allocate plane array\n"); 77 | return (FALSE); 78 | } 79 | 80 | /* Create our planes */ 81 | 82 | int num_test_planes = test_crtc->num_planes; // num_test_planes = 4 83 | for (int i = 0; i < num_test_planes; i++) { 84 | plane[i] = get_sp_plane(dev, test_crtc); // get planes that isn't used 85 | if (!plane[i]) { 86 | printf("no unused planes available\n"); 87 | return (FALSE); 88 | } 89 | 90 | plane[i]->bo = create_sp_bo(dev, IMAGE_WIDTH, IMAGE_HEIGHT, frame_depth, frame_bpp, 91 | plane[i]->format, 0); 92 | if (!plane[i]->bo) { 93 | printf("failed to create plane bo\n"); 94 | return (FALSE); 95 | } 96 | 97 | memset(plane[i]->bo->map_addr ,255 ,plane[i]->bo->size) ; // initialize to 0 98 | } 99 | 100 | printf("plane size = %d\n",plane[plane_index]->bo->size); 101 | printf("plane format = %d\n",plane[plane_index]->bo->format); 102 | /************************* loop start *************************/ 103 | printf("/***************** loop start *****************/\n"); 104 | while(!terminate) 105 | { 106 | srcBuffer_1 = get_img(buffer_1, srcBuffer_1); 107 | yuyv2bgr24(srcBuffer_1, dstBuffer_1); 108 | 109 | memcpy(plane[plane_index]->bo->map_addr, (void *)dstBuffer_1, plane[plane_index]->bo->size ); 110 | ret = set_sp_plane(dev, plane[plane_index], test_crtc, display_x, display_y, display_w, display_h); 111 | if (ret) { 112 | printf("failed to set plane 0 %d\n", ret); 113 | return (FALSE); 114 | } 115 | usleep(15 * 1000); 116 | } 117 | 118 | ret = drmModeSetCrtc(dev->fd, save_crtc->crtc_id, save_crtc->buffer_id, 119 | save_crtc->x, save_crtc->y, 120 | &save_connector->connector_id, 1, &save_crtc->mode); 121 | if (ret) { 122 | printf("failed to restore crtc \n"); 123 | } 124 | 125 | for (int i = 0; i < num_test_planes; i++) 126 | put_sp_plane(plane[i]); 127 | //put_sp_plane(plane[plane_index]); 128 | 129 | free(srcBuffer_1); 130 | free(dstBuffer_1); 131 | close_v4l2(buffer_1); 132 | 133 | destroy_sp_dev(dev); 134 | free(plane); 135 | 136 | return(TRUE); 137 | } 138 | 139 | -------------------------------------------------------------------------------- /v4l2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "v4l2.h" 14 | #if 0 15 | void unchar_to_Mat(unsigned char *_buffer,cv::Mat& img) 16 | { 17 | for (int i = 0;i < (BUFFER_SIZE_det);i++) 18 | { 19 | img.at((IMAGE_HEIGHT-1-(i / (IMAGE_WIDTH*CHANNEL))),((i % (IMAGE_WIDTH*CHANNEL))/CHANNEL))[i%CHANNEL] = _buffer[i]; // BGR Mat 20 | } 21 | } 22 | #endif 23 | void yuyv2bgr24(unsigned char*yuyv, unsigned char*rgb) 24 | { unsigned int width = IMAGE_WIDTH; 25 | unsigned int height = IMAGE_HEIGHT; 26 | unsigned int i, in, rgb_index = 0; 27 | unsigned char y0, u0, y1, v1; 28 | int r, g, b; 29 | unsigned int x , y; 30 | 31 | for(in = 0; in < width * height * 2; in += 4) 32 | { 33 | y0 = yuyv[in+0]; 34 | u0 = yuyv[in+1]; 35 | y1 = yuyv[in+2]; 36 | v1 = yuyv[in+3]; 37 | 38 | for (i = 0; i < 2; i++) 39 | { 40 | if (i) 41 | y = y1; 42 | else 43 | y = y0; 44 | r = y + (140 * (v1-128))/100; //r 45 | g = y - (34 * (u0-128))/100 - (71 * (v1-128))/100; //g 46 | b = y + (177 * (u0-128))/100; //b 47 | if(r > 255) r = 255; 48 | if(g > 255) g = 255; 49 | if(b > 255) b = 255; 50 | if(r < 0) r = 0; 51 | if(g < 0) g = 0; 52 | if(b < 0) b = 0; 53 | 54 | y = height - rgb_index/width -1; 55 | x = rgb_index%width; 56 | rgb[(y*width+x)*3+0] = b; 57 | rgb[(y*width+x)*3+1] = g; 58 | rgb[(y*width+x)*3+2] = r; 59 | rgb_index++; 60 | } 61 | } 62 | } 63 | 64 | void yuyv2bgra32(unsigned char*yuyv, unsigned char*bgra) 65 | { unsigned int width = IMAGE_WIDTH; 66 | unsigned int height = IMAGE_HEIGHT; 67 | unsigned int i, in, bgra_index = 0; 68 | unsigned char y0, u0, y1, v1; 69 | int a = 0xFF, r, g, b; 70 | unsigned int x , y; 71 | 72 | for(in = 0; in < width * height * 2; in += 4) 73 | { 74 | y0 = yuyv[in+0]; 75 | u0 = yuyv[in+1]; 76 | y1 = yuyv[in+2]; 77 | v1 = yuyv[in+3]; 78 | 79 | for (i = 0; i < 2; i++) 80 | { 81 | if (i) 82 | y = y1; 83 | else 84 | y = y0; 85 | 86 | r = y + (140 * (v1-128))/100; //r 87 | g = y - (34 * (u0-128))/100 - (71 * (v1-128))/100; //g 88 | b = y + (177 * (u0-128))/100; //b 89 | 90 | if(r > 255) r = 255; 91 | if(g > 255) g = 255; 92 | if(b > 255) b = 255; 93 | if(r < 0) r = 0; 94 | if(g < 0) g = 0; 95 | if(b < 0) b = 0; 96 | 97 | y = height - bgra_index/width -1; 98 | x = bgra_index%width; 99 | bgra[(y*width+x)*4+0] = b; 100 | bgra[(y*width+x)*4+1] = g; 101 | bgra[(y*width+x)*4+2] = r; 102 | bgra[(y*width+x)*4+3] = a; 103 | bgra_index++; 104 | } 105 | } 106 | } 107 | 108 | BUF *v4l2(char *FILE_VIDEO) 109 | { 110 | //int i; 111 | //int ret = 0; 112 | BUF *buffers = (BUF *)malloc(sizeof (BUF)); 113 | //open dev 114 | if ((buffers->fd = open(FILE_VIDEO, O_RDWR)) == -1) 115 | { 116 | printf("Error opening V4L interface\n"); 117 | return (FALSE); 118 | } 119 | 120 | struct v4l2_capability cap; 121 | memset(&cap, 0, sizeof(cap)); 122 | //query cap 123 | if (ioctl(buffers->fd, VIDIOC_QUERYCAP, &cap) == -1) 124 | { 125 | printf("Error opening device %s: unable to query device.\n",FILE_VIDEO); 126 | return (FALSE); 127 | } 128 | else 129 | { 130 | //printf("driver:\t\t%s\n",cap.driver); 131 | //printf("card:\t\t%s\n",cap.card); 132 | //printf("bus_info:\t%s\n",cap.bus_info); 133 | //printf("version:\t%d\n",cap.version); 134 | //printf("capabilities:\t%x\n",cap.capabilities); 135 | 136 | if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == V4L2_CAP_VIDEO_CAPTURE) 137 | { 138 | printf("Device %s: supports capture.\n",FILE_VIDEO); 139 | } 140 | 141 | if ((cap.capabilities & V4L2_CAP_STREAMING) == V4L2_CAP_STREAMING) 142 | { 143 | printf("Device %s: supports streaming.\n",FILE_VIDEO); 144 | } 145 | } 146 | 147 | //emu all support fmt 148 | struct v4l2_fmtdesc fmtdesc; 149 | fmtdesc.index=0; 150 | fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE; 151 | printf("Support format:\n"); 152 | while(ioctl(buffers->fd,VIDIOC_ENUM_FMT,&fmtdesc)!=-1) 153 | { 154 | printf("\t%d.%s\n",fmtdesc.index+1,fmtdesc.description); // get camera all support format here 155 | fmtdesc.index++; 156 | } 157 | 158 | struct v4l2_format fmt; 159 | memset(&fmt, 0, sizeof(fmt)); 160 | //set fmt 161 | fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 162 | fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; // output format 163 | fmt.fmt.pix.height = IMAGE_HEIGHT; 164 | fmt.fmt.pix.width = IMAGE_WIDTH; 165 | fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; 166 | //fmt.fmt.pix.priv = 1; 167 | 168 | if(ioctl(buffers->fd, VIDIOC_S_FMT, &fmt) == -1) 169 | { 170 | printf("Unable to set format\n"); 171 | return FALSE; 172 | } 173 | if(ioctl(buffers->fd, VIDIOC_G_FMT, &fmt) == -1) 174 | { 175 | printf("Unable to get format\n"); 176 | return FALSE; 177 | } 178 | { 179 | //printf("fmt.type:\t\t%d\n",fmt.type); 180 | printf("pix.pixelformat:\t%c%c%c%c\n",fmt.fmt.pix.pixelformat & 0xFF, (fmt.fmt.pix.pixelformat >> 8) & 0xFF,(fmt.fmt.pix.pixelformat >> 16) & 0xFF, (fmt.fmt.pix.pixelformat >> 24) & 0xFF); 181 | printf("pix.height:\t\t%d\n",fmt.fmt.pix.height); 182 | printf("pix.width:\t\t%d\n",fmt.fmt.pix.width); 183 | printf("pix.field:\t\t%d\n",fmt.fmt.pix.field); 184 | } 185 | //set fps 186 | struct v4l2_streamparm setfps; 187 | setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 188 | setfps.parm.capture.timeperframe.numerator = 1; // Per numerator seconds show denominator fps . 189 | setfps.parm.capture.timeperframe.denominator = 2; 190 | setfps.parm.capture.capturemode = 0; 191 | if(ioctl(buffers->fd, VIDIOC_S_PARM, &setfps) == -1) 192 | { 193 | printf("set fps fail !\n"); 194 | return FALSE; 195 | } 196 | 197 | if(ioctl(buffers->fd, VIDIOC_G_PARM, &setfps) == -1) 198 | { 199 | printf("get fps fail !\n"); 200 | return FALSE; 201 | }else 202 | { 203 | printf("True video fps = %d\n",(setfps.parm.capture.timeperframe.denominator)/(setfps.parm.capture.timeperframe.numerator)); 204 | } 205 | 206 | printf("init %s \t[OK]\n",FILE_VIDEO); 207 | /***************************************************/ 208 | unsigned int n_buffers; 209 | struct v4l2_requestbuffers req; 210 | memset(&req, 0, sizeof(req)); 211 | //request for 4 buffers 212 | req.count = COUNT; 213 | req.type=V4L2_BUF_TYPE_VIDEO_CAPTURE; 214 | req.memory=V4L2_MEMORY_MMAP; 215 | if(ioctl(buffers->fd,VIDIOC_REQBUFS,&req)==-1) 216 | { 217 | printf("request for buffers error\n"); 218 | } 219 | 220 | //mmap for buffers 221 | if (!buffers) 222 | { 223 | printf ("Out of memory\n"); 224 | return(FALSE); 225 | } 226 | 227 | struct v4l2_buffer buf ; 228 | memset( &buf, 0, sizeof(buf) ); 229 | 230 | for (n_buffers = 0; n_buffers < COUNT; n_buffers++) 231 | { 232 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 233 | buf.memory = V4L2_MEMORY_MMAP; 234 | buf.index = n_buffers; 235 | 236 | //query buffers 237 | if (ioctl (buffers->fd, VIDIOC_QUERYBUF, &buf) == -1) 238 | { 239 | printf("query buffer error\n"); 240 | return(FALSE); 241 | } 242 | 243 | //map 244 | buffers->start[n_buffers] = mmap(NULL,buf.length,PROT_READ |PROT_WRITE, MAP_SHARED, buffers->fd, buf.m.offset); 245 | if (buffers->start[n_buffers] == MAP_FAILED) 246 | { 247 | printf("buffer map error\n"); 248 | return(FALSE); 249 | } 250 | //queue 251 | ioctl(buffers->fd, VIDIOC_QBUF, &buf) ; 252 | } 253 | /***************************************************/ 254 | 255 | int type = 1; 256 | ioctl (buffers->fd, VIDIOC_STREAMON, &type) ; 257 | 258 | return buffers ; 259 | } 260 | 261 | unsigned char *get_img(BUF *buffers, unsigned char *srcBuffer) 262 | { 263 | // loop start 264 | struct v4l2_buffer dequeue ; 265 | dequeue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ; 266 | dequeue.memory = V4L2_MEMORY_MMAP ; 267 | 268 | ioctl(buffers->fd, VIDIOC_DQBUF, &dequeue) ; // get frame 269 | 270 | srcBuffer = (unsigned char *)buffers->start[dequeue.index]; 271 | 272 | ioctl(buffers->fd, VIDIOC_QBUF, &dequeue) ; 273 | return srcBuffer; 274 | } 275 | 276 | int close_v4l2(BUF *buffers) 277 | { 278 | int type = 0; 279 | ioctl(buffers->fd, VIDIOC_STREAMOFF, &type); 280 | 281 | for(int i=0;istart[i],BUFFER_SIZE_src); 284 | } 285 | if(buffers->fd != -1) 286 | { 287 | close(buffers->fd); 288 | free(buffers); 289 | return (TRUE); 290 | } 291 | free(buffers); 292 | return (FALSE); 293 | } 294 | -------------------------------------------------------------------------------- /v4l2.h: -------------------------------------------------------------------------------- 1 | #ifndef __V4L2_H__ 2 | #define __V4L2_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define TRUE 1 9 | #define FALSE 0 10 | #define IMAGE_WIDTH 640 11 | #define IMAGE_HEIGHT 480 12 | #define COUNT 4 13 | 14 | #define CHANNEL 3 15 | #define BUFFER_SIZE_src IMAGE_WIDTH*IMAGE_HEIGHT*2 16 | #define BUFFER_SIZE_det IMAGE_WIDTH*IMAGE_HEIGHT*CHANNEL 17 | 18 | typedef struct buffer 19 | { 20 | int fd; 21 | void * start[COUNT]; 22 | } BUF ; 23 | 24 | extern "C" 25 | { 26 | void yuyv2bgr24(unsigned char*yuyv, unsigned char*rgb); 27 | void yuyv2bgra32(unsigned char*yuyv, unsigned char*bgra); 28 | BUF *v4l2(char *FILE_VIDEO); 29 | unsigned char *get_img(BUF *buffers, unsigned char *srcBuffer); 30 | int close_v4l2(BUF *buffers); 31 | 32 | } 33 | 34 | 35 | #endif 36 | --------------------------------------------------------------------------------