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 }