#include "v4lcapture.h"
#include "kdenlivesettings.h"
+#include <linux/videodev2.h>
+#include <sys/ioctl.h>
-static src_t v4lsrc;
-
-class MyDisplay : public QLabel
-{
-public:
- MyDisplay(QWidget *parent = 0);
- void setImage(QImage img);
- virtual void paintEvent(QPaintEvent *);
- virtual void resizeEvent(QResizeEvent *);
-
-private:
- QImage m_img;
- bool m_clear;
-};
-
-MyDisplay::MyDisplay(QWidget *parent):
- QLabel(parent)
- , m_clear(false)
+V4lCaptureHandler::V4lCaptureHandler()
{
- setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
- setAttribute(Qt::WA_PaintOnScreen);
- setAttribute(Qt::WA_OpaquePaintEvent);
}
-void MyDisplay::resizeEvent(QResizeEvent *)
-{
- m_clear = true;
-}
+//static
-void MyDisplay::paintEvent(QPaintEvent *)
+QStringList V4lCaptureHandler::getDeviceName(const QString &input)
{
- QPainter p(this);
- if (m_clear) {
- // widget resized, cleanup
- p.fillRect(0, 0, width(), height(), palette().background());
- m_clear = false;
- }
- if (m_img.isNull()) return;
- QImage img = m_img.scaled(width(), height(), Qt::KeepAspectRatio);
- p.drawImage((width() - img.width()) / 2, (height() - img.height()) / 2, img);
- p.end();
-}
-void MyDisplay::setImage(QImage img)
-{
- m_img = img;
- update();
-}
-
-
-
-V4lCaptureHandler::V4lCaptureHandler(QVBoxLayout *lay, QWidget *parent):
- CaptureHandler(lay, parent)
- , m_update(false)
-{
- if (lay == NULL) return;
- m_display = new MyDisplay;
- lay->addWidget(m_display);
-}
-
-QStringList V4lCaptureHandler::getDeviceName(QString input)
-{
- 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 QStringList() << input;
- }
-
- /* 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(input.toUtf8().constData());
- config->input = NULL;
- config->tuner = 0;
- config->frequency = 0;
- config->delay = 0;
- config->use_read = 0;
- config->list = 0;
- config->width = 384;
- config->height = 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;
- int width = 0;
- int height = 0;
- char *pixelformat;
- QString deviceName = src_query(&v4lsrc, source, &width, &height, &pixelformat);
- QStringList result;
- result << (deviceName.isEmpty() ? input : deviceName) << (width == 0 ? QString() : QString("%1x%2").arg(width).arg(height)) << QString(pixelformat);
- return result;
-}
-
-void V4lCaptureHandler::startPreview(int /*deviceId*/, int /*captureMode*/, bool)
-{
- 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;
+ char *src = strdup(input.toUtf8().constData());
+ QString pixelformatdescription;
+ int fd = open(src, O_RDWR | O_NONBLOCK);
+ if(fd < 0) {
+ free(src);
+ return QStringList();
}
+ struct v4l2_capability cap;
- /* 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
- CaptureHandler::yuv2rgb((uchar *)img, (uchar *)qimg.bits(), v4lsrc.width, v4lsrc.height);
- if (!m_captureFramePath.isEmpty()) {
- qimg.save(m_captureFramePath);
- emit frameSaved(m_captureFramePath);
- m_captureFramePath.clear();
+ char *devName = NULL;
+ int captureEnabled = 1;
+ if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) {
+ fprintf(stderr, "Cannot get capabilities.");
+ //return NULL;
}
- if (!m_overlayImage.isNull()) {
- // overlay image
- QPainter p(&qimg);
- p.setOpacity(0.5);
- p.drawImage(0, 0, m_overlayImage);
- p.end();
+ else {
+ devName = strdup((char*) cap.card);
+ if(!cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
+ // Device cannot capture
+ captureEnabled = 0;
+ }
}
- m_display->setImage(qimg);
- if (m_update) QTimer::singleShot(200, this, SLOT(slotUpdate()));
-}
-void V4lCaptureHandler::startCapture(const QString &/*path*/)
-{
-}
-
-void V4lCaptureHandler::stopCapture()
-{
-}
-
-void V4lCaptureHandler::captureFrame(const QString &fname)
-{
- m_captureFramePath = fname;
-}
+ 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);
-void V4lCaptureHandler::showOverlay(QImage img, bool /*transparent*/)
-{
- m_overlayImage = img;
+ QStringList result;
+ if (devName == NULL)
+ return result;
+ QString deviceName(devName);
+ result << (deviceName.isEmpty() ? input : deviceName) << pixelformatdescription;
+ return result;
}
-void V4lCaptureHandler::hideOverlay()
-{
- m_overlayImage = QImage();
-}
-void V4lCaptureHandler::hidePreview(bool hide)
-{
- m_display->setHidden(hide);
-}
-void V4lCaptureHandler::stopPreview()
-{
- if (!m_update) return;
- m_update = false;
- src_close(&v4lsrc);
-}