* Get rid of custom video4linux header, use system header

* get rid of GPL2 files / rewrite v4l queries
parent 05a2c84d
# cmake macro to find LibV4L2
#
# Copyright (c) 2009, Jaroslav Reznik <jreznik@redhat.com>
#
# Once done this will define:
#
# LIBV4L2_FOUND - System has LibV4L2
# LIBV4L2_INCLUDE_DIR - The LibV4L2 include directory
# LIBV4L2_LIBRARY - The libraries needed to use LibV4L2
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
IF (LIBV4L2_INCLUDE_DIR AND LIBV4L2_LIBRARY)
# Already in cache, be silent
SET (LIBV4L2_FIND_QUIETLY TRUE)
ENDIF (LIBV4L2_INCLUDE_DIR AND LIBV4L2_LIBRARY)
FIND_PATH (LIBV4L2_INCLUDE_DIR libv4l2.h)
FIND_LIBRARY (LIBV4L2_LIBRARY v4l2)
INCLUDE (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS (LibV4L2 DEFAULT_MSG LIBV4L2_INCLUDE_DIR LIBV4L2_LIBRARY)
MARK_AS_ADVANCED(LIBV4L2_INCLUDE_DIR LIBV4L2_LIBRARY)
\ No newline at end of file
......@@ -14,13 +14,16 @@ macro_optional_find_package(QJSON)
option(WITH_V4L "Build capture support with Video4Linux" ON)
option(WITH_JogShuttle "Build Jog/Shuttle support" ON)
if(WITH_V4L)
# This can be changed to support FreeBSD as soon as we move to a newer V4L2
# header.
check_include_files(linux/ioctl.h HAVE_LINUX_IOCTL_H)
if(HAVE_LINUX_IOCTL_H)
find_package(LibV4L2)
macro_log_feature(LIBV4L2_FOUND "libv4l" "Collection of video4linux support libraries" "http://hansdegoede.livejournal.com, http://linuxtv.org/hg/~hgoede/libv4l/" FALSE "" "Required for better webcam support")
if(LIBV4L2_FOUND)
set(BUILD_V4L TRUE)
endif(HAVE_LINUX_IOCTL_H)
endif(LIBV4L2_FOUND)
endif(WITH_V4L)
if(WITH_JogShuttle)
......@@ -300,6 +303,7 @@ include_directories(
${LIBMLTPLUS_INCLUDE_DIR}
)
# Adds Qt definitions and include directories, and sets QT_LIBRARIES according
# to the components requested in find_package().
include(${QT_USE_FILE})
......@@ -351,6 +355,8 @@ if(QJSON_FOUND)
endif(QJSON_FOUND)
if(BUILD_V4L)
include_directories(${LIBV4L2_INCLUDE_DIR})
target_link_libraries(kdenlive ${LIBV4L2_LIBRARY})
add_definitions(-DUSE_V4L)
endif(BUILD_V4L)
......
......@@ -104,7 +104,7 @@ KdenliveSettingsDialog::KdenliveSettingsDialog(const QMap<QString, QString>& map
for (int i = 0; i < 10; i++) {
QString path = "/dev/video" + QString::number(i);
if (QFile::exists(path)) {
QStringList deviceInfo = V4lCaptureHandler::getDeviceName(path.toUtf8().constData());
QStringList deviceInfo = V4lCaptureHandler::getDeviceName(path);
if (!deviceInfo.isEmpty()) {
m_configCapture.kcfg_detectedv4ldevices->addItem(deviceInfo.at(0), path);
m_configCapture.kcfg_detectedv4ldevices->setItemData(m_configCapture.kcfg_detectedv4ldevices->count() - 1, deviceInfo.at(1), Qt::UserRole + 1);
......
set(kdenlive_SRCS
${kdenlive_SRCS}
v4l/v4lcapture.cpp
v4l/src.c
PARENT_SCOPE
)
/* fswebcam - Small and simple webcam for *nix */
/*============================================================*/
/* Copyright (C)2005-2010 Philip Heron <phil@sanslogic.co.uk> */
/* */
/* This program is distributed under the terms of the GNU */
/* General Public License, version 2. You may use, modify, */
/* and redistribute it under the terms of this license. A */
/* copy should be included with this source. */
#ifdef __cplusplus
extern "C" {
#endif
#ifndef INC_DEC_H
#define INC_DEC_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
extern int fswc_add_image_bayer(avgbmp_t *dst, uint8_t *img, uint32_t length, uint32_t w, uint32_t h, int palette);
extern int fswc_add_image_y16(src_t *src, avgbmp_t *abitmap);
extern int fswc_add_image_grey(src_t *src, avgbmp_t *abitmap);
extern int verify_jpeg_dht(uint8_t *src, uint32_t lsrc, uint8_t **dst, uint32_t *ldst);
extern int fswc_add_image_png(src_t *src, avgbmp_t *abitmap);
extern int fswc_add_image_rgb32(src_t *src, avgbmp_t *abitmap);
extern int fswc_add_image_bgr32(src_t *src, avgbmp_t *abitmap);
extern int fswc_add_image_rgb24(src_t *src, avgbmp_t *abitmap);
extern int fswc_add_image_bgr24(src_t *src, avgbmp_t *abitmap);
extern int fswc_add_image_rgb565(src_t *src, avgbmp_t *abitmap);
extern int fswc_add_image_rgb555(src_t *src, avgbmp_t *abitmap);
extern int fswc_add_image_yuyv(src_t *src, avgbmp_t *abitmap);
extern int fswc_add_image_yuv420p(src_t *src, avgbmp_t *abitmap);
extern int fswc_add_image_nv12mb(src_t *src, avgbmp_t *abitmap);
extern int fswc_add_image_s561(avgbmp_t *dst, uint8_t *img, uint32_t length, uint32_t width, uint32_t height, int palette);
#endif
#ifdef __cplusplus
}
#endif
/* fswebcam - FireStorm.cx's webcam generator */
/*============================================================*/
/* Copyright (C)2005-2010 Philip Heron <phil@sanslogic.co.uk> */
/* */
/* This program is distributed under the terms of the GNU */
/* General Public License, version 2. You may use, modify, */
/* and redistribute it under the terms of this license. A */
/* copy should be included with this source. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <sys/stat.h>
#include <errno.h>
#include <sys/mman.h>
#include "src.h"
#include <sys/ioctl.h>
int v4l2_free_mmap(src_t *src)
{
src_v4l2_t *s = (src_v4l2_t *) src->state;
uint i;
for(i = 0; i < s->req.count; i++)
munmap(s->buffer[i].start, s->buffer[i].length);
return(0);
}
static int close_v4l2(src_t *src)
{
src_v4l2_t *s = (src_v4l2_t *) src->state;
if(s->buffer)
{
if(!s->map) free(s->buffer[0].start);
else v4l2_free_mmap(src);
free(s->buffer);
}
if(s->fd >= 0) close(s->fd);
free(s);
return(0);
}
//static
const char *query_v4ldevice(src_t *src, char **pixelformatdescription)
{
if(!src->source)
{
/*ERROR("No device name specified.");*/
fprintf(stderr, "No device name specified.");
return NULL;
}
src_v4l2_t *s;
/* Allocate memory for the state structure. */
s = calloc(sizeof(src_v4l2_t), 1);
if(!s)
{
fprintf(stderr, "Out of memory.");
return NULL;
}
src->state = (void *) s;
char value[200];
//snprintf( value, sizeof(value), '\0' );
//strcpy(*pixelformatdescription, (char*) value);
/* Open the device. */
s->fd = open(src->source, O_RDWR | O_NONBLOCK);
if(s->fd < 0)
{
fprintf(stderr, "Cannot open device.");
free(s);
return NULL;
}
char *res = NULL;
int captureEnabled = 1;
if(ioctl(s->fd, VIDIOC_QUERYCAP, &s->cap) < 0) {
fprintf(stderr, "Cannot get capabilities.");
//return NULL;
}
else {
res = strdup((char*) s->cap.card);
if(!s->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
// Device cannot capture
captureEnabled = 0;
}
}
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));
while (ioctl(s->fd, VIDIOC_ENUM_FMT, &fmt) != -1)
{
if (strlen(*pixelformatdescription) > 2000) break;
if (snprintf( value, sizeof(value), ">%c%c%c%c", fmt.pixelformat >> 0, fmt.pixelformat >> 8, fmt.pixelformat >> 16, fmt.pixelformat >> 24 ) > 0)
strcat(*pixelformatdescription, (char *) 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(s->fd, VIDIOC_ENUM_FRAMESIZES, &sizes) != -1) {
struct v4l2_frmsize_discrete image_size = sizes.un.discrete;
// Query supported frame rates
rates.index = 0;
rates.pixel_format = fmt.pixelformat;
rates.width = image_size.width;
rates.height = image_size.height;
if (strlen(*pixelformatdescription) > 2000) break;
if (snprintf( value, sizeof(value), ":%dx%d=", image_size.width, image_size.height ) > 0)
strcat(*pixelformatdescription, (char *) value);
fprintf(stderr, "Size: %dx%d: ", image_size.width, image_size.height);
while (ioctl(s->fd, VIDIOC_ENUM_FRAMEINTERVALS, &rates) != -1) {
if (strlen(*pixelformatdescription) > 2000) break;
if (snprintf( value, sizeof(value), "%d/%d,", rates.un.discrete.denominator, rates.un.discrete.numerator ) > 0)
strcat(*pixelformatdescription, (char *) value);
fprintf(stderr, "%d/%d, ", rates.un.discrete.numerator, rates.un.discrete.denominator);
rates.index ++;
}
fprintf(stderr, "\n");
sizes.index++;
}
/*[0x%08X] '%c%c%c%c' (%s)", v4l2_pal,
fmt.pixelformat,
fmt.pixelformat >> 0, fmt.pixelformat >> 8,
fmt.pixelformat >> 16, fmt.pixelformat >> 24*/
fmt.index++;
}
/*else {
*pixelformatdescription = '\0';
}*/
}
close_v4l2(src);
return res;
}
/* fswebcam - FireStorm.cx's webcam generator */
/*============================================================*/
/* Copyright (C)2005-2010 Philip Heron <phil@sanslogic.co.uk> */
/* */
/* This program is distributed under the terms of the GNU */
/* General Public License, version 2. You may use, modify, */
/* and redistribute it under the terms of this license. A */
/* copy should be included with this source. */
#ifdef __cplusplus
extern "C" {
#endif
#ifndef INC_SRC_H
#define INC_SRC_H
#include <stdint.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include "videodev2.h"
typedef unsigned char avgbmp_t;
#define CLIP(val, min, max) (((val) > (max)) ? (max) : (((val) < (min)) ? (min) : (val)))
#define SRC_TYPE_NONE (0)
#define SRC_TYPE_DEVICE (1 << 0) /* Can capture from a device */
#define SRC_TYPE_FILE (1 << 1) /* Can capture from a file */
/* When updating the palette list remember to update src_palette[] in src.c */
#define SRC_PAL_ANY (-1)
#define SRC_PAL_PNG (0)
#define SRC_PAL_JPEG (1)
#define SRC_PAL_MJPEG (2)
#define SRC_PAL_S561 (3)
#define SRC_PAL_RGB32 (4)
#define SRC_PAL_BGR32 (5)
#define SRC_PAL_RGB24 (6)
#define SRC_PAL_BGR24 (7)
#define SRC_PAL_YUYV (8)
#define SRC_PAL_UYVY (9)
#define SRC_PAL_YUV420P (10)
#define SRC_PAL_NV12MB (11)
#define SRC_PAL_BAYER (12)
#define SRC_PAL_SGBRG8 (13)
#define SRC_PAL_SGRBG8 (14)
#define SRC_PAL_RGB565 (15)
#define SRC_PAL_RGB555 (16)
#define SRC_PAL_Y16 (17)
#define SRC_PAL_GREY (18)
#define SRC_LIST_INPUTS (1 << 1)
#define SRC_LIST_TUNERS (1 << 2)
#define SRC_LIST_FORMATS (1 << 3)
#define SRC_LIST_CONTROLS (1 << 4)
#define SRC_LIST_FRAMESIZES (1 << 5)
#define SRC_LIST_FRAMERATES (1 << 6)
/* The SCALE macro converts a value (sv) from one range (sf -> sr)
to another (df -> dr). */
#define SCALE(df, dr, sf, sr, sv) (((sv - sf) * (dr - df) / (sr - sf)) + df)
typedef struct {
char *name;
char *value;
} src_option_t;
typedef struct {
/* Source Options */
char *source;
uint8_t type;
void *state;
/* Last captured image */
uint32_t length;
void *img;
/* Input Options */
char *input;
uint8_t tuner;
uint32_t frequency;
uint32_t delay;
uint32_t timeout;
char use_read;
/* List Options */
uint8_t list;
/* Image Options */
int palette;
uint32_t width;
uint32_t height;
uint32_t fps;
src_option_t **option;
/* For calculating capture FPS */
uint32_t captured_frames;
struct timeval tv_first;
struct timeval tv_last;
} src_t;
typedef struct {
/* List of options. */
char *opts;
const struct option *long_opts;
/* When reading from the command line. */
int opt_index;
/* When reading from a configuration file. */
char *filename;
FILE *f;
size_t line;
} fswc_getopt_t;
typedef struct {
uint16_t id;
char *options;
} fswebcam_job_t;
typedef struct {
/* General options. */
unsigned long loop;
signed long offset;
unsigned char background;
char *pidfile;
char *logfile;
char gmt;
/* Capture start time. */
time_t start;
/* Device options. */
char *device;
char *input;
unsigned char tuner;
unsigned long frequency;
unsigned long delay;
char use_read;
uint8_t list;
/* Image capture options. */
unsigned int width;
unsigned int height;
unsigned int frames;
unsigned int fps;
unsigned int skipframes;
int palette;
src_option_t **option;
char *dumpframe;
/* Job queue. */
uint8_t jobs;
fswebcam_job_t **job;
/* Banner options. */
char banner;
uint32_t bg_colour;
uint32_t bl_colour;
uint32_t fg_colour;
char *title;
char *subtitle;
char *timestamp;
char *info;
char *font;
int fontsize;
char shadow;
/* Overlay options. */
char *underlay;
char *overlay;
/* Output options. */
char *filename;
char format;
char compression;
} fswebcam_config_t;
typedef struct {
void *start;
size_t length;
} v4l2_buffer_t;
typedef struct {
int fd;
char map;
struct v4l2_capability cap;
struct v4l2_format fmt;
struct v4l2_requestbuffers req;
struct v4l2_buffer buf;
v4l2_buffer_t *buffer;
int pframe;
} src_v4l2_t;
const char *query_v4ldevice(src_t *src, char **pixelformatdescription);
#endif
#ifdef __cplusplus
}
#endif
......@@ -35,6 +35,8 @@
#include "v4lcapture.h"
#include "kdenlivesettings.h"
#include <linux/videodev2.h>
#include <sys/ioctl.h>
V4lCaptureHandler::V4lCaptureHandler()
{
......@@ -44,32 +46,87 @@ V4lCaptureHandler::V4lCaptureHandler()
QStringList V4lCaptureHandler::getDeviceName(QString input)
{
src_t v4lsrc;
/* Set source options... */
memset(&v4lsrc, 0, sizeof(v4lsrc));
v4lsrc.input = NULL;
v4lsrc.tuner = 0;
v4lsrc.frequency = 0;
v4lsrc.delay = 0;
v4lsrc.timeout = 10; /* seconds */
v4lsrc.use_read = 0;
v4lsrc.list = 0;
v4lsrc.palette = SRC_PAL_ANY;
v4lsrc.width = 384;
v4lsrc.height = 288;
v4lsrc.fps = 0;
v4lsrc.option = NULL;
v4lsrc.source = strdup(input.toUtf8().constData());
char *pixelformatdescription;
pixelformatdescription = (char *) calloc(2048, sizeof(char));
char *src = strdup(input.toUtf8().constData());
QString pixelformatdescription;
int fd = open(src, O_RDWR | O_NONBLOCK);
if(fd < 0) {
delete[] src;
return QStringList();
}
struct v4l2_capability cap;
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;
}
}
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++;
}