#include "camera.h" #include "device.h" #include "mode.h" #include #include #include #include #include double get_time() { struct timeval t; struct timezone tzp; gettimeofday(&t, &tzp); return t.tv_sec + t.tv_usec * 1e-6; } int main(int argc, char *argv[]) { if (argc != 3) { printf("Usage: %s \n", argv[0]); return 1; } char *video_name = argv[1]; char *subdev_name = argv[2]; double find_start = get_time(); // First find the device MPDevice *device = mp_device_find(video_name, subdev_name); if (!device) { printf("Device not found\n"); return 1; } double find_end = get_time(); printf("Finding the device took %fms\n", (find_end - find_start) * 1000); int video_fd; uint32_t video_entity_id; { const struct media_v2_entity *entity = mp_device_find_entity_type(device, MEDIA_ENT_F_IO_V4L); if (!entity) { printf("Unable to find video device interface\n"); return 1; } video_entity_id = entity->id; const struct media_v2_interface *iface = mp_device_find_entity_interface(device, video_entity_id); char buf[256]; if (!mp_find_device_path(iface->devnode, buf, 256)) { printf("Unable to find video device path\n"); return 1; } video_fd = open(buf, O_RDWR); if (video_fd == -1) { printf("Unable to open video device\n"); return 1; } } int bridge_fd = -1; const struct media_v2_entity *bridge = mp_device_find_entity_type(device, MEDIA_ENT_F_VID_IF_BRIDGE); if (bridge) { video_entity_id = bridge->id; const struct media_v2_interface *iface = mp_device_find_entity_interface(device, bridge->id); char buf[256]; if (!mp_find_device_path(iface->devnode, buf, 256)) { printf("Unable to find bridge device path\n"); return 1; } bridge_fd = open(buf, O_RDWR); if (bridge_fd == -1) { printf("Unable to open bridge device\n"); return 1; } } int subdev_fd = -1; const struct media_v2_entity *entity = mp_device_find_entity(device, subdev_name); if (!entity) { printf("Unable to find sub-device\n"); return 1; } const struct media_v2_pad *source_pad = mp_device_get_pad_from_entity(device, entity->id); const struct media_v2_pad *sink_pad = mp_device_get_pad_from_entity(device, video_entity_id); // Disable other links const struct media_v2_entity *entities = mp_device_get_entities(device); for (int i = 0; i < mp_device_get_num_entities(device); ++i) { if (entities[i].id != video_entity_id && entities[i].id != entity->id) { const struct media_v2_pad *pad = mp_device_get_pad_from_entity(device, entities[i].id); mp_device_setup_link(device, pad->id, sink_pad->id, false); } } // Then enable ours mp_device_setup_link(device, source_pad->id, sink_pad->id, true); const struct media_v2_interface *iface = mp_device_find_entity_interface(device, entity->id); char buf[256]; if (!mp_find_device_path(iface->devnode, buf, 256)) { printf("Unable to find sub-device path\n"); return 1; } subdev_fd = open(buf, O_RDWR); if (subdev_fd == -1) { printf("Unable to open sub-device\n"); return 1; } double open_end = get_time(); printf("Opening the device took %fms\n", (open_end - find_end) * 1000); MPCamera *camera = mp_camera_new(video_fd, subdev_fd, bridge_fd); MPControlList *controls = mp_camera_list_controls(camera); double control_list_end = get_time(); printf("Available controls: (took %fms)\n", (control_list_end - open_end) * 1000); for (MPControlList *list = controls; list; list = mp_control_list_next(list)) { MPControl *c = mp_control_list_get(list); printf(" %32s id:%s type:%s default:%d\n", c->name, mp_control_id_to_str(c->id), mp_control_type_to_str(c->type), c->default_value); } double mode_list_begin = get_time(); MPModeList *modes = mp_camera_list_available_modes(camera); double mode_list_end = get_time(); printf("Available modes: (took %fms)\n", (mode_list_end - mode_list_begin) * 1000); for (MPModeList *list = modes; list; list = mp_camera_mode_list_next(list)) { MPMode *m = mp_camera_mode_list_get(list); printf(" %dx%d interval:%d/%d fmt:%s\n", m->width, m->height, m->frame_interval.numerator, m->frame_interval.denominator, mp_pixel_format_to_str(m->pixel_format)); // Skip really slow framerates if (m->frame_interval.denominator < 15) { printf(" Skipping…\n"); continue; } double start_capture = get_time(); mp_camera_set_mode(camera, m); mp_camera_start_capture(camera); double last = get_time(); printf(" Testing 10 captures, starting took %fms\n", (last - start_capture) * 1000); for (int i = 0; i < 10; ++i) { MPBuffer buffer; if (!mp_camera_capture_buffer(camera, &buffer)) { printf(" Failed to capture buffer\n"); } size_t num_bytes = mp_pixel_format_width_to_bytes( m->pixel_format, m->width) * m->height; uint8_t *data = malloc(num_bytes); memcpy(data, buffer.data, num_bytes); printf(" first byte: %d.", data[0]); free(data); mp_camera_release_buffer(camera, buffer.index); double now = get_time(); printf(" capture took %fms\n", (now - last) * 1000); last = now; } mp_camera_stop_capture(camera); } double cleanup_start = get_time(); mp_camera_free(camera); close(video_fd); if (subdev_fd != -1) close(subdev_fd); if (bridge_fd != -1) close(bridge_fd); mp_device_close(device); double cleanup_end = get_time(); printf("Cleanup took %fms\n", (cleanup_end - cleanup_start) * 1000); }