|
8 | 8 | #include <string.h> |
9 | 9 | #include <sys/ioctl.h> |
10 | 10 | #include <unistd.h> |
| 11 | +#include <linux/v4l2-subdev.h> |
| 12 | +#include <linux/media.h> |
11 | 13 |
|
12 | 14 | bool |
13 | 15 | mp_find_device_path(struct media_v2_intf_devnode devnode, char *path, int length) |
@@ -73,6 +75,46 @@ xioctl(int fd, int request, void *arg) |
73 | 75 | return r; |
74 | 76 | } |
75 | 77 |
|
| 78 | +static int |
| 79 | +mp_device_get_fd_by_name(const MPDevice *device, const char *driver_name) |
| 80 | +{ |
| 81 | + struct media_entity_desc desc = {}; |
| 82 | + |
| 83 | + desc.id |= MEDIA_ENT_ID_FLAG_NEXT; |
| 84 | + |
| 85 | + while(true) { |
| 86 | + desc.id |= MEDIA_ENT_ID_FLAG_NEXT; |
| 87 | + if(xioctl(device->fd, MEDIA_IOC_ENUM_ENTITIES, &desc) == -1) { |
| 88 | + errno_printerr("MEDIA_IOC_ENUM_ENTITIES"); |
| 89 | + return -1; |
| 90 | + } |
| 91 | + |
| 92 | + if(strncmp(desc.name, driver_name, 32) == 0) { |
| 93 | + const uint32_t major = desc.dev.major; |
| 94 | + const uint32_t minor = desc.dev.minor; |
| 95 | + char path[256]; |
| 96 | + int rc = snprintf(path, 256, "/dev/char/%u:%u", major, minor); |
| 97 | + |
| 98 | + return rc > 0 ? open(path, O_RDWR) : -1; |
| 99 | + } |
| 100 | + } |
| 101 | + |
| 102 | + return -1; |
| 103 | +} |
| 104 | + |
| 105 | +static bool |
| 106 | +mp_xioctl(const MPDevice *device, const char *driver_name, unsigned long request, void *argp) |
| 107 | +{ |
| 108 | + int fd = mp_device_get_fd_by_name(device, driver_name); |
| 109 | + |
| 110 | + if(fd < 0) |
| 111 | + { |
| 112 | + printf("ERROR: device with driver name %s not found\n", driver_name); |
| 113 | + } |
| 114 | + |
| 115 | + return fd >= 0 && xioctl(fd, request, argp) != -1; |
| 116 | +} |
| 117 | + |
76 | 118 | MPDevice * |
77 | 119 | mp_device_find(const char *driver_name, const char *dev_name) |
78 | 120 | { |
@@ -183,6 +225,42 @@ mp_device_setup_entity_link(MPDevice *device, |
183 | 225 | return true; |
184 | 226 | } |
185 | 227 |
|
| 228 | +void |
| 229 | +mp_device_setup_media_link(MPDevice *device, |
| 230 | + const struct mp_media_link_config *cfg, |
| 231 | + bool enable) |
| 232 | +{ |
| 233 | + const struct media_v2_entity *source_entity = |
| 234 | + mp_device_find_entity(device, cfg->source_name); |
| 235 | + |
| 236 | + const struct media_v2_entity *target_entity = |
| 237 | + mp_device_find_entity(device, cfg->target_name); |
| 238 | + |
| 239 | + mp_device_setup_entity_link(device, |
| 240 | + source_entity->id, |
| 241 | + target_entity->id, |
| 242 | + cfg->source_port, |
| 243 | + cfg->target_port, |
| 244 | + enable); |
| 245 | +} |
| 246 | + |
| 247 | +void |
| 248 | +mp_device_setup_media_link_pad_crop(MPDevice *device, |
| 249 | + const struct mp_media_crop_config *crop) |
| 250 | +{ |
| 251 | + struct v4l2_subdev_crop v4l2_crop = {}; |
| 252 | + v4l2_crop.pad = crop->pad; |
| 253 | + v4l2_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE; |
| 254 | + v4l2_crop.rect.top = crop->top; |
| 255 | + v4l2_crop.rect.left = crop->left; |
| 256 | + v4l2_crop.rect.width = crop->width; |
| 257 | + v4l2_crop.rect.height = crop->height; |
| 258 | + |
| 259 | + if(!mp_xioctl(device, crop->name, VIDIOC_SUBDEV_S_CROP, &v4l2_crop)) { |
| 260 | + errno_printerr("VIDIOC_SUBDEV_S_CROP"); |
| 261 | + } |
| 262 | +} |
| 263 | + |
186 | 264 | bool |
187 | 265 | mp_device_setup_link(MPDevice *device, |
188 | 266 | uint32_t source_pad_id, |
@@ -237,6 +315,46 @@ mp_entity_pad_set_format(MPDevice *device, |
237 | 315 | return true; |
238 | 316 | } |
239 | 317 |
|
| 318 | +const struct media_v2_pad * |
| 319 | +mp_device_get_pad_at_index_from_entity(const MPDevice *device, uint32_t entity_id, uint32_t index) |
| 320 | +{ |
| 321 | + for (int i = 0; i < device->num_pads; ++i) { |
| 322 | + if (device->pads[i].entity_id == entity_id && index-- == 0) { |
| 323 | + return &device->pads[i]; |
| 324 | + } |
| 325 | + } |
| 326 | + return NULL; |
| 327 | +} |
| 328 | + |
| 329 | +bool |
| 330 | +mp_device_setup_link_by_name(MPDevice *device, |
| 331 | + const char *source_entity_name, |
| 332 | + uint32_t source_pad_index, |
| 333 | + const char *sink_entity_name, |
| 334 | + uint32_t sink_pad_index, |
| 335 | + bool enabled) |
| 336 | +{ |
| 337 | + const struct media_v2_entity *source_entity = |
| 338 | + mp_device_find_entity |
| 339 | + (device, source_entity_name); |
| 340 | + const struct media_v2_entity *sink_entity = |
| 341 | + mp_device_find_entity |
| 342 | + (device, sink_entity_name); |
| 343 | + |
| 344 | + struct media_link_desc link = {}; |
| 345 | + link.flags = enabled ? MEDIA_LNK_FL_ENABLED : 0; |
| 346 | + link.source.entity = source_entity->id; |
| 347 | + link.source.index = source_pad_index; |
| 348 | + link.sink.entity = sink_entity->id; |
| 349 | + link.sink.index = sink_pad_index; |
| 350 | + if (xioctl(device->fd, MEDIA_IOC_SETUP_LINK, &link) == -1) { |
| 351 | + errno_printerr("MEDIA_IOC_SETUP_LINK"); |
| 352 | + return false; |
| 353 | + } |
| 354 | + |
| 355 | + return true; |
| 356 | +} |
| 357 | + |
240 | 358 | const struct media_v2_entity * |
241 | 359 | mp_device_find_entity(const MPDevice *device, const char *driver_name) |
242 | 360 | { |
|
0 commit comments