File indexing completed on 2024-04-21 04:51:18
0001 /* 0002 SPDX-FileCopyrightText: 2010 Jean-Baptiste Mardelle <jb@kdenlive.org> 0003 0004 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "v4lcapture.h" 0008 #include "kdenlivesettings.h" 0009 0010 #include <cstdio> 0011 #include <cstdlib> 0012 #include <cstring> 0013 #include <fcntl.h> 0014 #include <pthread.h> 0015 #include <unistd.h> 0016 0017 #include <linux/videodev2.h> 0018 #include <sys/ioctl.h> 0019 0020 V4lCaptureHandler::V4lCaptureHandler() = default; 0021 0022 // static 0023 0024 QStringList V4lCaptureHandler::getDeviceName(const QString &input) 0025 { 0026 0027 char *src = strdup(input.toUtf8().constData()); 0028 QString pixelformatdescription; 0029 int fd = open(src, O_RDWR | O_NONBLOCK); 0030 if (fd < 0) { 0031 free(src); 0032 return QStringList(); 0033 } 0034 struct v4l2_capability cap 0035 { 0036 }; 0037 0038 char *devName = nullptr; 0039 int captureEnabled = 1; 0040 if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) { 0041 fprintf(stderr, "Cannot get capabilities."); 0042 // return nullptr; 0043 } else { 0044 devName = strdup(reinterpret_cast<char *>(cap.card)); 0045 if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0u) { 0046 // Device cannot capture 0047 captureEnabled = 0; 0048 } 0049 } 0050 0051 if (captureEnabled != 0) { 0052 struct v4l2_format format 0053 { 0054 }; 0055 memset(&format, 0, sizeof(format)); 0056 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 0057 0058 struct v4l2_fmtdesc fmt 0059 { 0060 }; 0061 memset(&fmt, 0, sizeof(fmt)); 0062 fmt.index = 0; 0063 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 0064 0065 struct v4l2_frmsizeenum sizes 0066 { 0067 }; 0068 memset(&sizes, 0, sizeof(sizes)); 0069 0070 struct v4l2_frmivalenum rates 0071 { 0072 }; 0073 memset(&rates, 0, sizeof(rates)); 0074 char value[200]; 0075 0076 while (ioctl(fd, VIDIOC_ENUM_FMT, &fmt) != -1) { 0077 if (pixelformatdescription.length() > 2000) { 0078 break; 0079 } 0080 if (snprintf(value, sizeof(value), ">%c%c%c%c", fmt.pixelformat >> 0, fmt.pixelformat >> 8, fmt.pixelformat >> 16, fmt.pixelformat >> 24) > 0) { 0081 pixelformatdescription.append(value); 0082 } 0083 fprintf(stderr, "detected format: %s: %c%c%c%c\n", fmt.description, fmt.pixelformat >> 0, fmt.pixelformat >> 8, fmt.pixelformat >> 16, 0084 fmt.pixelformat >> 24); 0085 0086 sizes.pixel_format = fmt.pixelformat; 0087 sizes.index = 0; 0088 // Query supported frame size 0089 while (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &sizes) != -1) { 0090 struct v4l2_frmsize_discrete image_size = sizes.discrete; 0091 // Query supported frame rates 0092 rates.index = 0; 0093 rates.pixel_format = fmt.pixelformat; 0094 rates.width = image_size.width; 0095 rates.height = image_size.height; 0096 if (pixelformatdescription.length() > 2000) { 0097 break; 0098 } 0099 if (snprintf(value, sizeof(value), ":%dx%d=", image_size.width, image_size.height) > 0) { 0100 pixelformatdescription.append(value); 0101 } 0102 fprintf(stderr, "Size: %dx%d: ", image_size.width, image_size.height); 0103 while (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &rates) != -1) { 0104 if (pixelformatdescription.length() > 2000) { 0105 break; 0106 } 0107 if (snprintf(value, sizeof(value), "%d/%d,", rates.discrete.denominator, rates.discrete.numerator) > 0) { 0108 pixelformatdescription.append(value); 0109 } 0110 fprintf(stderr, "%d/%d, ", rates.discrete.numerator, rates.discrete.denominator); 0111 rates.index++; 0112 } 0113 fprintf(stderr, "\n"); 0114 sizes.index++; 0115 } 0116 fmt.index++; 0117 } 0118 } 0119 close(fd); 0120 free(src); 0121 0122 QStringList result; 0123 if (devName == nullptr) { 0124 return result; 0125 } 0126 QString deviceName(devName); 0127 free(devName); 0128 result << (deviceName.isEmpty() ? input : deviceName) << pixelformatdescription; 0129 return result; 0130 }