]> git.sesse.net Git - kdenlive/blobdiff - src/v4l/v4lcapture.cpp
Integrate with the required MLT hooks for getting Movit to work.
[kdenlive] / src / v4l / v4lcapture.cpp
index be7b22be04d1e2d7ca03c8835ca62fc13eeaae17..8e6a63b42329a70d35a96ee8420a400a5f73f8e0 100644 (file)
 #include <QDebug>
 #include <QImage>
 #include <QTimer>
+#include <QPainter>
 
 #include <KDebug>
-#include <KLocale>
+#include <KLocalizedString>
 
 #include "v4lcapture.h"
 #include "kdenlivesettings.h"
 
+#include <linux/videodev2.h>
+#include <sys/ioctl.h>
 
-static src_t v4lsrc;
-
-void yuv2rgb_int3(unsigned char *yuv_buffer, unsigned char *rgb_buffer, int width, int height)
+V4lCaptureHandler::V4lCaptureHandler()
 {
-    int len;
-    int r, g, b;
-    int Y, U, V, Y2;
-    int rgb_ptr, y_ptr, t;
-
-    len = width * height / 2;
-
-    rgb_ptr = 0;
-    y_ptr = 0;
-
-    for(t = 0; t < len; t++) { /* process 2 pixels at a time */
-        /* Compute parts of the UV components */
-
-        U = yuv_buffer[y_ptr];
-        Y = yuv_buffer[y_ptr+1];
-        V = yuv_buffer[y_ptr+2];
-        Y2 = yuv_buffer[y_ptr+3];
-        y_ptr += 4;
-
-
-        /*r = 1.164*(Y-16) + 1.596*(V-128);
-        g = 1.164*(Y-16) - 0.813*(V-128) - 0.391*(U-128);
-        b = 1.164*(Y-16) + 2.018*(U-128);*/
-
-
-        r = ((298 * (Y - 16)               + 409 * (V - 128) + 128) >> 8);
-
-        g = ((298 * (Y - 16) - 100 * (U - 128) - 208 * (V - 128) + 128) >> 8);
-
-        b = ((298 * (Y - 16) + 516 * (U - 128)               + 128) >> 8);
-
-        if(r > 255) r = 255;
-        if(g > 255) g = 255;
-        if(b > 255) b = 255;
-
-        if(r < 0) r = 0;
-        if(g < 0) g = 0;
-        if(b < 0) b = 0;
-
-        rgb_buffer[rgb_ptr] = b;
-        rgb_buffer[rgb_ptr+1] = g;
-        rgb_buffer[rgb_ptr+2] = r;
-        rgb_buffer[rgb_ptr+3] = 255;
-
-        rgb_ptr += 4;
-        /*r = 1.164*(Y2-16) + 1.596*(V-128);
-        g = 1.164*(Y2-16) - 0.813*(V-128) - 0.391*(U-128);
-        b = 1.164*(Y2-16) + 2.018*(U-128);*/
-
-
-        r = ((298 * (Y2 - 16)               + 409 * (V - 128) + 128) >> 8);
-
-        g = ((298 * (Y2 - 16) - 100 * (U - 128) - 208 * (V - 128) + 128) >> 8);
-
-        b = ((298 * (Y2 - 16) + 516 * (U - 128)               + 128) >> 8);
-
-        if(r > 255) r = 255;
-        if(g > 255) g = 255;
-        if(b > 255) b = 255;
-
-        if(r < 0) r = 0;
-        if(g < 0) g = 0;
-        if(b < 0) b = 0;
-
-        rgb_buffer[rgb_ptr] = b;
-        rgb_buffer[rgb_ptr+1] = g;
-        rgb_buffer[rgb_ptr+2] = r;
-        rgb_buffer[rgb_ptr+3] = 255;
-        rgb_ptr += 4;
-    }
 }
 
-V4lCaptureHandler::V4lCaptureHandler(QVBoxLayout *lay, QWidget *parent):
-    CaptureHandler(lay, parent)
-    , m_update(false)
-{
-    m_display = new QLabel;
-    lay->addWidget(m_display);
-}
+//static
 
-void V4lCaptureHandler::startPreview(int /*deviceId*/, int /*captureMode*/)
+QStringList V4lCaptureHandler::getDeviceName(const QString &input)
 {
-    m_display->setHidden(false);
-    fswebcam_config_t *config;
-    /* Prepare the configuration structure. */
-    config = (fswebcam_config_t *) calloc(sizeof(fswebcam_config_t), 1);
-    if(!config) {
-        /*WARN("Out of memory.");*/
-        fprintf(stderr, "Out of MEM....");
-        return;
-    }
 
-    /* Set the defaults. */
-    config->loop = 0;
-    config->offset = 0;
-    config->background = 0;
-    config->pidfile = NULL;
-    config->logfile = NULL;
-    config->gmt = 0;
-    config->start = 0;
-    config->device = strdup(KdenliveSettings::video4vdevice().toUtf8().constData());
-    config->input = NULL;
-    config->tuner = 0;
-    config->frequency = 0;
-    config->delay = 0;
-    config->use_read = 0;
-    config->list = 0;
-    config->width = KdenliveSettings::video4size().section("x", 0, 0).toInt();/*384;*/
-    config->height = KdenliveSettings::video4size().section("x", -1).toInt();/*288;*/
-    config->fps = 0;
-    config->frames = 1;
-    config->skipframes = 0;
-    config->palette = SRC_PAL_ANY;
-    config->option = NULL;
-    config->dumpframe = NULL;
-    config->jobs = 0;
-    config->job = NULL;
-
-    /* Set defaults and parse the command line. */
-    /*if(fswc_getopts(config, argc, argv)) return(-1);*/
-
-
-    /* Record the start time. */
-    config->start = time(NULL);
-    /* Set source options... */
-    memset(&v4lsrc, 0, sizeof(v4lsrc));
-    v4lsrc.input      = config->input;
-    v4lsrc.tuner      = config->tuner;
-    v4lsrc.frequency  = config->frequency;
-    v4lsrc.delay      = config->delay;
-    v4lsrc.timeout    = 10; /* seconds */
-    v4lsrc.use_read   = config->use_read;
-    v4lsrc.list       = config->list;
-    v4lsrc.palette    = config->palette;
-    v4lsrc.width      = config->width;
-    v4lsrc.height     = config->height;
-    v4lsrc.fps        = config->fps;
-    v4lsrc.option     = config->option;
-    char *source = config->device;
-
-    if(src_open(&v4lsrc, source) != 0) return;
-    m_update = true;
-    QTimer::singleShot(200, this, SLOT(slotUpdate()));
-}
-
-V4lCaptureHandler::~V4lCaptureHandler()
-{
-    stopCapture();
-}
-
-void V4lCaptureHandler::slotUpdate()
-{
-    if(!m_update) return;
-    src_grab(&v4lsrc);
-    uint8_t *img = (uint8_t *) v4lsrc.img;
-    uint32_t i = v4lsrc.width * v4lsrc.height;
-
-    if(v4lsrc.length << 2 < i) return;
-
-    QImage qimg(v4lsrc.width, v4lsrc.height, QImage::Format_RGB32);
-    //Format_ARGB32_Premultiplied
-    //convert from uyvy422 to rgba
-    yuv2rgb_int3((uchar *)img, (uchar *)qimg.bits(), v4lsrc.width, v4lsrc.height);
-    if(!m_captureFramePath.isEmpty()) {
-        qimg.save(m_captureFramePath);
-        m_captureFramePath.clear();
+    char *src = strdup(input.toUtf8().constData());
+    QString pixelformatdescription;
+    int fd = open(src, O_RDWR | O_NONBLOCK);
+    if(fd < 0) {
+        free(src);
+        return QStringList();
     }
-    m_display->setPixmap(QPixmap::fromImage(qimg));
-    if(m_update) QTimer::singleShot(200, this, SLOT(slotUpdate()));
-}
-
-void V4lCaptureHandler::startCapture(const QString &/*path*/)
-{
-}
-
-void V4lCaptureHandler::stopCapture()
-{
-}
+    struct v4l2_capability cap;
 
-void V4lCaptureHandler::captureFrame(const QString &fname)
-{
-    m_captureFramePath = fname;
-}
+    char *devName = NULL;
+    int captureEnabled = 1;
+    if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) {
+        fprintf(stderr, "Cannot get capabilities.");
+        //return NULL;
+    }
+    else {
+        devName = strdup((char*) cap.card);
+        if(!cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
+            // Device cannot capture
+            captureEnabled = 0;
+        }
+    }
 
-void V4lCaptureHandler::showOverlay(QImage /*img*/, bool /*transparent*/)
-{
+    if (captureEnabled) {
+        struct v4l2_format format;
+        memset(&format,0,sizeof(format));
+        format.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+        struct v4l2_fmtdesc fmt;
+        memset(&fmt,0,sizeof(fmt));
+        fmt.index = 0;
+        fmt.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+        struct v4l2_frmsizeenum sizes;
+        memset(&sizes,0,sizeof(sizes));
+
+        struct v4l2_frmivalenum rates;
+        memset(&rates,0,sizeof(rates));
+        char value[200];
+
+        while (ioctl(fd, VIDIOC_ENUM_FMT, &fmt) != -1)
+        {
+            if (pixelformatdescription.length() > 2000) break;
+            if (snprintf( value, sizeof(value), ">%c%c%c%c", fmt.pixelformat >> 0,  fmt.pixelformat >> 8, fmt.pixelformat >> 16, fmt.pixelformat >> 24 ) > 0)
+                pixelformatdescription.append(value);
+            fprintf(stderr, "detected format: %s: %c%c%c%c\n", fmt.description, fmt.pixelformat >> 0,  fmt.pixelformat >> 8, fmt.pixelformat >> 16, fmt.pixelformat >> 24);
+
+            sizes.pixel_format = fmt.pixelformat;
+            sizes.index = 0;
+            // Query supported frame size
+            while (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &sizes) != -1) {
+                struct v4l2_frmsize_discrete image_size = sizes.discrete;
+                // Query supported frame rates
+                rates.index = 0;
+                rates.pixel_format = fmt.pixelformat;
+                rates.width = image_size.width;
+                rates.height = image_size.height;
+                if (pixelformatdescription.length() > 2000) break;
+                if (snprintf( value, sizeof(value), ":%dx%d=", image_size.width, image_size.height ) > 0)
+                    pixelformatdescription.append(value);
+                fprintf(stderr, "Size: %dx%d: ", image_size.width, image_size.height);
+                while (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &rates) != -1) {
+                    if (pixelformatdescription.length() > 2000) break;
+                    if (snprintf( value, sizeof(value), "%d/%d,", rates.discrete.denominator, rates.discrete.numerator ) > 0)
+                        pixelformatdescription.append(value);
+                    fprintf(stderr, "%d/%d, ", rates.discrete.numerator, rates.discrete.denominator);
+                    rates.index ++;
+                }
+                fprintf(stderr, "\n");
+                sizes.index++;
+            }
+            fmt.index++;
+        }
+    }
+    close(fd);
+    free(src);
+
+    QStringList result;
+    if (devName == NULL)
+        return result;
+    QString deviceName(devName);
+    result << (deviceName.isEmpty() ? input : deviceName) << pixelformatdescription;
+    return result;
 }
 
-void V4lCaptureHandler::hideOverlay()
-{
-}
 
-void V4lCaptureHandler::hidePreview(bool hide)
-{
-    m_display->setHidden(hide);
-}
 
-void V4lCaptureHandler::stopPreview()
-{
-    if(!m_update) return;
-    m_update = false;
-    src_close(&v4lsrc);
-}