mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
Bug fixes and new implementations
- Video format MJPEG implemented (libjpeg/qimage) - Inactive priorities are now skipped correctly (PriorityMuxer.cpp line 297) - v4l configuration section replaced with an object (preparation for #542)
This commit is contained in:
parent
4aab0ad55c
commit
0a8af60726
@ -268,6 +268,18 @@ find_package(libusb-1.0 REQUIRED)
|
||||
find_package(Threads REQUIRED)
|
||||
add_definitions(${QT_DEFINITIONS})
|
||||
|
||||
# Add jpeg library
|
||||
if (ENABLE_V4L2)
|
||||
find_package(JPEG)
|
||||
if (JPEG_FOUND)
|
||||
add_definitions(-DHAVE_JPEG)
|
||||
message( STATUS "Using JPEG library: ${JPEG_LIBRARIES}")
|
||||
include_directories(${JPEG_INCLUDE_DIR})
|
||||
else()
|
||||
message( STATUS "JPEG library not found, MJPEG camera format won't work in V4L2 grabber.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# TODO[TvdZ]: This linking directory should only be added if we are cross compiling
|
||||
#if(NOT APPLE)
|
||||
# link_directories(${CMAKE_FIND_ROOT_PATH}/lib/arm-linux-gnueabihf)
|
||||
|
@ -26,7 +26,7 @@ Note: call the script with `./docker-compile.sh -h` for more options
|
||||
|
||||
```
|
||||
sudo apt-get update
|
||||
sudo apt-get install git cmake build-essential qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python3-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev
|
||||
sudo apt-get install git cmake build-essential qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python3-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev libjpeg-dev
|
||||
```
|
||||
|
||||
**on RPI you need the videocore IV headers**
|
||||
|
@ -27,7 +27,7 @@ $(document).ready( function() {
|
||||
//v4l
|
||||
$('#conf_cont').append(createRow('conf_cont_v4l'))
|
||||
$('#conf_cont_v4l').append(createOptPanel('fa-camera', $.i18n("edt_conf_v4l2_heading_title"), 'editor_container_v4l2', 'btn_submit_v4l2'));
|
||||
$('#conf_cont_v4l').append(createHelpTable(schema.grabberV4L2.items.properties, $.i18n("edt_conf_v4l2_heading_title")));
|
||||
$('#conf_cont_v4l').append(createHelpTable(schema.grabberV4L2.properties, $.i18n("edt_conf_v4l2_heading_title")));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -114,26 +114,24 @@
|
||||
/// * sDHOffsetMax : area for signal detection - horizontal maximum offset value. Values between 0.0 and 1.0
|
||||
/// * sDVOffsetMax : area for signal detection - vertical maximum offset value. Values between 0.0 and 1.0
|
||||
"grabberV4L2" :
|
||||
[
|
||||
{
|
||||
"device" : "auto",
|
||||
"standard" : "NO_CHANGE",
|
||||
"sizeDecimation" : 8,
|
||||
"priority" : 240,
|
||||
"cropLeft" : 0,
|
||||
"cropRight" : 0,
|
||||
"cropTop" : 0,
|
||||
"cropBottom" : 0,
|
||||
"redSignalThreshold" : 5,
|
||||
"greenSignalThreshold" : 5,
|
||||
"blueSignalThreshold" : 5,
|
||||
"signalDetection" : false,
|
||||
"sDVOffsetMin" : 0.25,
|
||||
"sDHOffsetMin" : 0.25,
|
||||
"sDVOffsetMax" : 0.75,
|
||||
"sDHOffsetMax" : 0.75
|
||||
}
|
||||
],
|
||||
{
|
||||
"device" : "auto",
|
||||
"standard" : "NO_CHANGE",
|
||||
"sizeDecimation" : 8,
|
||||
"priority" : 240,
|
||||
"cropLeft" : 0,
|
||||
"cropRight" : 0,
|
||||
"cropTop" : 0,
|
||||
"cropBottom" : 0,
|
||||
"redSignalThreshold" : 5,
|
||||
"greenSignalThreshold" : 5,
|
||||
"blueSignalThreshold" : 5,
|
||||
"signalDetection" : false,
|
||||
"sDVOffsetMin" : 0.25,
|
||||
"sDHOffsetMin" : 0.25,
|
||||
"sDVOffsetMax" : 0.75,
|
||||
"sDHOffsetMax" : 0.75
|
||||
},
|
||||
|
||||
/// The configuration for the frame-grabber, contains the following items:
|
||||
/// * type : type of grabber. (auto|osx|dispmanx|amlogic|x11|framebuffer|qt) [auto]
|
||||
|
@ -57,25 +57,23 @@
|
||||
},
|
||||
|
||||
"grabberV4L2" :
|
||||
[
|
||||
{
|
||||
"device" : "auto",
|
||||
"standard" : "NO_CHANGE",
|
||||
"sizeDecimation" : 8,
|
||||
"cropLeft" : 0,
|
||||
"cropRight" : 0,
|
||||
"cropTop" : 0,
|
||||
"cropBottom" : 0,
|
||||
"redSignalThreshold" : 5,
|
||||
"greenSignalThreshold" : 5,
|
||||
"blueSignalThreshold" : 5,
|
||||
"signalDetection" : false,
|
||||
"sDVOffsetMin" : 0.25,
|
||||
"sDHOffsetMin" : 0.25,
|
||||
"sDVOffsetMax" : 0.75,
|
||||
"sDHOffsetMax" : 0.75
|
||||
}
|
||||
],
|
||||
{
|
||||
"device" : "auto",
|
||||
"standard" : "NO_CHANGE",
|
||||
"sizeDecimation" : 8,
|
||||
"cropLeft" : 0,
|
||||
"cropRight" : 0,
|
||||
"cropTop" : 0,
|
||||
"cropBottom" : 0,
|
||||
"redSignalThreshold" : 5,
|
||||
"greenSignalThreshold" : 5,
|
||||
"blueSignalThreshold" : 5,
|
||||
"signalDetection" : false,
|
||||
"sDVOffsetMin" : 0.25,
|
||||
"sDHOffsetMin" : 0.25,
|
||||
"sDVOffsetMax" : 0.75,
|
||||
"sDHOffsetMax" : 0.75
|
||||
},
|
||||
|
||||
"framegrabber" :
|
||||
{
|
||||
|
@ -13,6 +13,13 @@
|
||||
#include <utils/PixelFormat.h>
|
||||
#include <hyperion/Grabber.h>
|
||||
#include <grabber/VideoStandard.h>
|
||||
#include <utils/Components.h>
|
||||
|
||||
#ifdef HAVE_JPEG
|
||||
#include <QImage>
|
||||
#include <jpeglib.h>
|
||||
#include <csetjmp>
|
||||
#endif
|
||||
|
||||
/// Capture class for V4L2 devices
|
||||
///
|
||||
@ -78,6 +85,8 @@ public slots:
|
||||
|
||||
void stop();
|
||||
|
||||
void componentStateChanged(const hyperion::Components component, bool enable);
|
||||
|
||||
signals:
|
||||
void newFrame(const Image<ColorRgb> & image);
|
||||
void readError(const char* err);
|
||||
@ -111,7 +120,7 @@ private:
|
||||
|
||||
bool process_image(const void *p, int size);
|
||||
|
||||
void process_image(const uint8_t *p);
|
||||
void process_image(const uint8_t *p, int size);
|
||||
|
||||
int xioctl(int request, void *arg);
|
||||
|
||||
@ -120,17 +129,41 @@ private:
|
||||
void throw_errno_exception(const QString &error);
|
||||
|
||||
private:
|
||||
enum io_method {
|
||||
enum io_method
|
||||
{
|
||||
IO_METHOD_READ,
|
||||
IO_METHOD_MMAP,
|
||||
IO_METHOD_USERPTR
|
||||
};
|
||||
|
||||
struct buffer {
|
||||
struct buffer
|
||||
{
|
||||
void *start;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
#ifdef HAVE_JPEG
|
||||
struct errorManager
|
||||
{
|
||||
jpeg_error_mgr pub;
|
||||
jmp_buf setjmp_buffer;
|
||||
};
|
||||
|
||||
static void errorHandler(j_common_ptr cInfo)
|
||||
{
|
||||
errorManager* mgr = reinterpret_cast<errorManager*>(cInfo->err);
|
||||
longjmp(mgr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
static void outputHandler(j_common_ptr cInfo)
|
||||
{
|
||||
// Suppress fprintf warnings.
|
||||
}
|
||||
|
||||
jpeg_decompress_struct* _decompress;
|
||||
errorManager* _error;
|
||||
#endif
|
||||
|
||||
private:
|
||||
QString _deviceName;
|
||||
std::map<QString,QString> _v4lDevices;
|
||||
@ -156,7 +189,7 @@ private:
|
||||
double _x_frac_max;
|
||||
double _y_frac_max;
|
||||
|
||||
QSocketNotifier * _streamNotifier;
|
||||
QSocketNotifier *_streamNotifier;
|
||||
|
||||
bool _initialized;
|
||||
bool _deviceAutoDiscoverEnabled;
|
||||
|
@ -12,6 +12,9 @@ enum PixelFormat {
|
||||
PIXELFORMAT_BGR24,
|
||||
PIXELFORMAT_RGB32,
|
||||
PIXELFORMAT_BGR32,
|
||||
#ifdef HAVE_JPEG
|
||||
PIXELFORMAT_MJPEG,
|
||||
#endif
|
||||
PIXELFORMAT_NO_CHANGE
|
||||
};
|
||||
|
||||
@ -44,6 +47,12 @@ inline PixelFormat parsePixelFormat(QString pixelFormat)
|
||||
{
|
||||
return PIXELFORMAT_BGR32;
|
||||
}
|
||||
#ifdef HAVE_JPEG
|
||||
else if (pixelFormat == "mjpeg")
|
||||
{
|
||||
return PIXELFORMAT_MJPEG;
|
||||
}
|
||||
#endif
|
||||
|
||||
// return the default NO_CHANGE
|
||||
return PIXELFORMAT_NO_CHANGE;
|
||||
|
@ -10,3 +10,7 @@ target_link_libraries(v4l2-grabber
|
||||
hyperion
|
||||
${QT_LIBRARIES}
|
||||
)
|
||||
|
||||
if (JPEG_FOUND)
|
||||
target_link_libraries(v4l2-grabber ${JPEG_LIBRARY})
|
||||
endif()
|
||||
|
@ -16,11 +16,15 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include <hyperion/Hyperion.h>
|
||||
|
||||
#include <QDirIterator>
|
||||
#include <QFileInfo>
|
||||
|
||||
#include "grabber/V4L2Grabber.h"
|
||||
|
||||
using namespace hyperion;
|
||||
|
||||
#define CLEAR(x) memset(&(x), 0, sizeof(x))
|
||||
|
||||
V4L2Grabber::V4L2Grabber(const QString & device
|
||||
@ -55,6 +59,10 @@ V4L2Grabber::V4L2Grabber(const QString & device
|
||||
setPixelDecimation(pixelDecimation);
|
||||
getV4Ldevices();
|
||||
|
||||
// listen for component change for build-in grabber only
|
||||
if (Hyperion::_hyperion)
|
||||
connect(Hyperion::getInstance(), &Hyperion::componentStateChanged, this, &V4L2Grabber::componentStateChanged);
|
||||
|
||||
// init
|
||||
setDeviceVideoStandard(device, videoStandard);
|
||||
}
|
||||
@ -70,11 +78,7 @@ void V4L2Grabber::uninit()
|
||||
if (_initialized)
|
||||
{
|
||||
Debug(_log,"uninit grabber: %s", QSTRING_CSTR(_deviceName));
|
||||
|
||||
stop();
|
||||
uninit_device();
|
||||
close_device();
|
||||
_initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -233,6 +237,9 @@ void V4L2Grabber::stop()
|
||||
{
|
||||
stop_capturing();
|
||||
_streamNotifier->setEnabled(false);
|
||||
uninit_device();
|
||||
close_device();
|
||||
_initialized = false;
|
||||
Info(_log, "Stopped");
|
||||
}
|
||||
}
|
||||
@ -518,74 +525,109 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
|
||||
// set the requested pixel format
|
||||
switch (_pixelFormat)
|
||||
{
|
||||
case PIXELFORMAT_UYVY:
|
||||
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
|
||||
case PIXELFORMAT_UYVY:
|
||||
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
|
||||
break;
|
||||
case PIXELFORMAT_YUYV:
|
||||
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
|
||||
case PIXELFORMAT_YUYV:
|
||||
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
|
||||
break;
|
||||
case PIXELFORMAT_RGB32:
|
||||
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;
|
||||
case PIXELFORMAT_RGB32:
|
||||
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;
|
||||
break;
|
||||
case PIXELFORMAT_NO_CHANGE:
|
||||
default:
|
||||
// No change to device settings
|
||||
#ifdef HAVE_JPEG
|
||||
case PIXELFORMAT_MJPEG:
|
||||
{
|
||||
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
|
||||
fmt.fmt.pix.field = V4L2_FIELD_ANY;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case PIXELFORMAT_NO_CHANGE:
|
||||
default:
|
||||
// No change to device settings
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO Does never accept own sizes? use always _imageResampler instead
|
||||
/*
|
||||
|
||||
// calc the size based on pixelDecimation
|
||||
fmt.fmt.pix.width = fmt.fmt.pix.width / _pixelDecimation;
|
||||
fmt.fmt.pix.height = fmt.fmt.pix.height / _pixelDecimation;
|
||||
|
||||
// set the settings
|
||||
fmt.fmt.pix.width = _width;
|
||||
fmt.fmt.pix.height = _height;
|
||||
|
||||
if (-1 == xioctl(VIDIOC_S_FMT, &fmt))
|
||||
{
|
||||
throw_errno_exception("VIDIOC_S_FMT");
|
||||
return;
|
||||
}
|
||||
|
||||
// get the format settings again
|
||||
// (the size may not have been accepted without an error)
|
||||
if (-1 == xioctl(VIDIOC_G_FMT, &fmt))
|
||||
{
|
||||
throw_errno_exception("VIDIOC_G_FMT");
|
||||
return;
|
||||
}
|
||||
*/
|
||||
// set the line length
|
||||
_lineLength = fmt.fmt.pix.bytesperline;
|
||||
|
||||
// store width & height
|
||||
// initialize current width and height
|
||||
_width = fmt.fmt.pix.width;
|
||||
_height = fmt.fmt.pix.height;
|
||||
|
||||
// display the used width and height
|
||||
Debug(_log, "width=%d height=%d", _width, _height );
|
||||
|
||||
// Trying to set frame rate
|
||||
struct v4l2_streamparm streamparms;
|
||||
CLEAR(streamparms);
|
||||
streamparms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
if (-1 == xioctl(VIDIOC_G_PARM, &streamparms))
|
||||
{
|
||||
throw_errno_exception("VIDIOC_G_PARM");
|
||||
// continue
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check the capability flag is set to V4L2_CAP_TIMEPERFRAME
|
||||
if (streamparms.parm.capture.capability == V4L2_CAP_TIMEPERFRAME)
|
||||
{
|
||||
// Driver supports the feature. Set required framerate
|
||||
streamparms.parm.capture.capturemode = V4L2_MODE_HIGHQUALITY;
|
||||
streamparms.parm.capture.timeperframe.numerator = 1;
|
||||
streamparms.parm.capture.timeperframe.denominator = 30;
|
||||
if(-1 == xioctl(VIDIOC_S_PARM, &streamparms))
|
||||
{
|
||||
throw_errno_exception("VIDIOC_S_PARM");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set the line length
|
||||
_lineLength = fmt.fmt.pix.bytesperline;
|
||||
|
||||
// check pixel format and frame size
|
||||
switch (fmt.fmt.pix.pixelformat)
|
||||
{
|
||||
case V4L2_PIX_FMT_UYVY:
|
||||
_pixelFormat = PIXELFORMAT_UYVY;
|
||||
_frameByteSize = _width * _height * 2;
|
||||
Debug(_log, "Pixel format=UYVY");
|
||||
case V4L2_PIX_FMT_UYVY:
|
||||
{
|
||||
_pixelFormat = PIXELFORMAT_UYVY;
|
||||
_frameByteSize = _width * _height * 2;
|
||||
Debug(_log, "Pixel format=UYVY");
|
||||
}
|
||||
break;
|
||||
case V4L2_PIX_FMT_YUYV:
|
||||
_pixelFormat = PIXELFORMAT_YUYV;
|
||||
_frameByteSize = _width * _height * 2;
|
||||
Debug(_log, "Pixel format=YUYV");
|
||||
case V4L2_PIX_FMT_YUYV:
|
||||
{
|
||||
_pixelFormat = PIXELFORMAT_YUYV;
|
||||
_frameByteSize = _width * _height * 2;
|
||||
Debug(_log, "Pixel format=YUYV");
|
||||
}
|
||||
break;
|
||||
case V4L2_PIX_FMT_RGB32:
|
||||
_pixelFormat = PIXELFORMAT_RGB32;
|
||||
_frameByteSize = _width * _height * 4;
|
||||
Debug(_log, "Pixel format=RGB32");
|
||||
case V4L2_PIX_FMT_RGB32:
|
||||
{
|
||||
_pixelFormat = PIXELFORMAT_RGB32;
|
||||
_frameByteSize = _width * _height * 4;
|
||||
Debug(_log, "Pixel format=RGB32");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw_exception("Only pixel formats UYVY, YUYV, and RGB32 are supported");
|
||||
#ifdef HAVE_JPEG
|
||||
case V4L2_PIX_FMT_MJPEG:
|
||||
{
|
||||
_pixelFormat = PIXELFORMAT_MJPEG;
|
||||
Debug(_log, "Pixel format=MJPEG");
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
throw_exception("Only pixel formats UYVY, YUYV, and RGB32 are supported");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -714,107 +756,108 @@ int V4L2Grabber::read_frame()
|
||||
{
|
||||
struct v4l2_buffer buf;
|
||||
|
||||
switch (_ioMethod) {
|
||||
case IO_METHOD_READ:
|
||||
int size;
|
||||
if ((size = read(_fileDescriptor, _buffers[0].start, _buffers[0].length)) == -1)
|
||||
{
|
||||
switch (errno)
|
||||
switch (_ioMethod)
|
||||
{
|
||||
case IO_METHOD_READ:
|
||||
int size;
|
||||
if ((size = read(_fileDescriptor, _buffers[0].start, _buffers[0].length)) == -1)
|
||||
{
|
||||
case EAGAIN:
|
||||
return 0;
|
||||
switch (errno)
|
||||
{
|
||||
case EAGAIN:
|
||||
return 0;
|
||||
|
||||
case EIO:
|
||||
/* Could ignore EIO, see spec. */
|
||||
case EIO:
|
||||
/* Could ignore EIO, see spec. */
|
||||
|
||||
/* fall through */
|
||||
/* fall through */
|
||||
|
||||
default:
|
||||
throw_errno_exception("read");
|
||||
default:
|
||||
throw_errno_exception("read");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
rc = process_image(_buffers[0].start, size);
|
||||
break;
|
||||
|
||||
case IO_METHOD_MMAP:
|
||||
CLEAR(buf);
|
||||
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
|
||||
if (-1 == xioctl(VIDIOC_DQBUF, &buf))
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case EAGAIN:
|
||||
return 0;
|
||||
|
||||
case EIO:
|
||||
/* Could ignore EIO, see spec. */
|
||||
|
||||
/* fall through */
|
||||
|
||||
default:
|
||||
throw_errno_exception("VIDIOC_DQBUF");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
assert(buf.index < _buffers.size());
|
||||
|
||||
rc = process_image(_buffers[buf.index].start, buf.bytesused);
|
||||
|
||||
if (-1 == xioctl(VIDIOC_QBUF, &buf))
|
||||
{
|
||||
throw_errno_exception("VIDIOC_QBUF");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
rc = process_image(_buffers[0].start, size);
|
||||
break;
|
||||
break;
|
||||
|
||||
case IO_METHOD_MMAP:
|
||||
CLEAR(buf);
|
||||
case IO_METHOD_USERPTR:
|
||||
CLEAR(buf);
|
||||
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.memory = V4L2_MEMORY_USERPTR;
|
||||
|
||||
if (-1 == xioctl(VIDIOC_DQBUF, &buf))
|
||||
{
|
||||
switch (errno)
|
||||
if (-1 == xioctl(VIDIOC_DQBUF, &buf))
|
||||
{
|
||||
case EAGAIN:
|
||||
return 0;
|
||||
switch (errno)
|
||||
{
|
||||
case EAGAIN:
|
||||
return 0;
|
||||
|
||||
case EIO:
|
||||
/* Could ignore EIO, see spec. */
|
||||
case EIO:
|
||||
/* Could ignore EIO, see spec. */
|
||||
|
||||
/* fall through */
|
||||
/* fall through */
|
||||
|
||||
default:
|
||||
throw_errno_exception("VIDIOC_DQBUF");
|
||||
default:
|
||||
throw_errno_exception("VIDIOC_DQBUF");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < _buffers.size(); ++i)
|
||||
{
|
||||
if (buf.m.userptr == (unsigned long)_buffers[i].start && buf.length == _buffers[i].length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rc = process_image((void *)buf.m.userptr, buf.bytesused);
|
||||
|
||||
if (-1 == xioctl(VIDIOC_QBUF, &buf))
|
||||
{
|
||||
throw_errno_exception("VIDIOC_QBUF");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
assert(buf.index < _buffers.size());
|
||||
|
||||
rc = process_image(_buffers[buf.index].start, buf.bytesused);
|
||||
|
||||
if (-1 == xioctl(VIDIOC_QBUF, &buf))
|
||||
{
|
||||
throw_errno_exception("VIDIOC_QBUF");
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IO_METHOD_USERPTR:
|
||||
CLEAR(buf);
|
||||
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.memory = V4L2_MEMORY_USERPTR;
|
||||
|
||||
if (-1 == xioctl(VIDIOC_DQBUF, &buf))
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case EAGAIN:
|
||||
return 0;
|
||||
|
||||
case EIO:
|
||||
/* Could ignore EIO, see spec. */
|
||||
|
||||
/* fall through */
|
||||
|
||||
default:
|
||||
throw_errno_exception("VIDIOC_DQBUF");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < _buffers.size(); ++i)
|
||||
{
|
||||
if (buf.m.userptr == (unsigned long)_buffers[i].start && buf.length == _buffers[i].length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rc = process_image((void *)buf.m.userptr, buf.bytesused);
|
||||
|
||||
if (-1 == xioctl(VIDIOC_QBUF, &buf))
|
||||
{
|
||||
throw_errno_exception("VIDIOC_QBUF");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
@ -828,23 +871,101 @@ int V4L2Grabber::read_frame()
|
||||
bool V4L2Grabber::process_image(const void *p, int size)
|
||||
{
|
||||
// We do want a new frame...
|
||||
#ifdef HAVE_JPEG
|
||||
if (size != _frameByteSize && _pixelFormat != PIXELFORMAT_MJPEG)
|
||||
#else
|
||||
if (size != _frameByteSize)
|
||||
#endif
|
||||
{
|
||||
Error(_log, "Frame too small: %d != %d", size, _frameByteSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
process_image(reinterpret_cast<const uint8_t *>(p));
|
||||
process_image(reinterpret_cast<const uint8_t *>(p), size);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void V4L2Grabber::process_image(const uint8_t * data)
|
||||
void V4L2Grabber::process_image(const uint8_t * data, int size)
|
||||
{
|
||||
Image<ColorRgb> image(0, 0);
|
||||
_imageResampler.processImage(data, _width, _height, _lineLength, _pixelFormat, image);
|
||||
Image<ColorRgb> image(_width, _height);
|
||||
|
||||
#ifdef HAVE_JPEG
|
||||
if (_pixelFormat == PIXELFORMAT_MJPEG)
|
||||
{
|
||||
_decompress = new jpeg_decompress_struct;
|
||||
_error = new errorManager;
|
||||
|
||||
_decompress->err = jpeg_std_error(&_error->pub);
|
||||
_error->pub.error_exit = &errorHandler;
|
||||
_error->pub.output_message = &outputHandler;
|
||||
|
||||
jpeg_create_decompress(_decompress);
|
||||
|
||||
if (setjmp(_error->setjmp_buffer))
|
||||
{
|
||||
jpeg_abort_decompress(_decompress);
|
||||
jpeg_destroy_decompress(_decompress);
|
||||
delete _decompress;
|
||||
delete _error;
|
||||
return;
|
||||
}
|
||||
|
||||
jpeg_mem_src(_decompress, const_cast<uint8_t*>(data), size);
|
||||
|
||||
if (jpeg_read_header(_decompress, (bool) TRUE) != JPEG_HEADER_OK)
|
||||
{
|
||||
jpeg_abort_decompress(_decompress);
|
||||
jpeg_destroy_decompress(_decompress);
|
||||
delete _decompress;
|
||||
delete _error;
|
||||
return;
|
||||
}
|
||||
|
||||
jpeg_start_decompress(_decompress);
|
||||
|
||||
QImage imageFrame = QImage(_decompress->output_width, _decompress->output_height, QImage::Format_RGB888);
|
||||
|
||||
int y = 0;
|
||||
while (_decompress->output_scanline < _decompress->output_height)
|
||||
{
|
||||
uchar *row = imageFrame.scanLine(_decompress->output_scanline);
|
||||
jpeg_read_scanlines(_decompress, &row, 1);
|
||||
y++;
|
||||
}
|
||||
|
||||
jpeg_finish_decompress(_decompress);
|
||||
jpeg_destroy_decompress(_decompress);
|
||||
delete _decompress;
|
||||
delete _error;
|
||||
|
||||
if (imageFrame.isNull())
|
||||
return;
|
||||
|
||||
QRect rect(_cropLeft, _cropTop, imageFrame.width() - _cropLeft - _cropRight, imageFrame.height() - _cropTop - _cropBottom);
|
||||
imageFrame = imageFrame.copy(rect);
|
||||
imageFrame = imageFrame.scaled(imageFrame.width() / _pixelDecimation, imageFrame.height() / _pixelDecimation,Qt::KeepAspectRatio);
|
||||
|
||||
if ((image.width() != unsigned(imageFrame.width())) && (image.height() != unsigned(imageFrame.height())))
|
||||
image.resize(imageFrame.width(), imageFrame.height());
|
||||
|
||||
for (int y=0; y<imageFrame.height(); ++y)
|
||||
{
|
||||
for (int x=0; x<imageFrame.width(); ++x)
|
||||
{
|
||||
const QRgb inPixel = imageFrame.pixel(x,y);
|
||||
ColorRgb & outPixel = image(x,y);
|
||||
outPixel.red = (inPixel & 0xff0000) >> 16;
|
||||
outPixel.green = (inPixel & 0xff00) >> 8;
|
||||
outPixel.blue = (inPixel & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
_imageResampler.processImage(data, _width, _height, _lineLength, _pixelFormat, image);
|
||||
|
||||
if (_signalDetectionEnabled)
|
||||
{
|
||||
@ -963,3 +1084,19 @@ void V4L2Grabber::setDeviceVideoStandard(QString device, VideoStandard videoStan
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
void V4L2Grabber::componentStateChanged(const hyperion::Components component, bool enable)
|
||||
{
|
||||
if (component == COMP_V4L)
|
||||
{
|
||||
if (_initialized != enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
if(init()) start();
|
||||
}
|
||||
else
|
||||
uninit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -294,7 +294,7 @@ void PriorityMuxer::setCurrentTime(void)
|
||||
else
|
||||
{
|
||||
// timeoutTime of -100 is awaiting data (inactive); skip
|
||||
if(infoIt->timeoutTime_ms >= -100)
|
||||
if(infoIt->timeoutTime_ms > -100)
|
||||
newPriority = qMin(newPriority, infoIt->priority);
|
||||
|
||||
// call timeTrigger when effect or color is running with timeout > 0, blacklist prio 255
|
||||
|
@ -1,208 +1,200 @@
|
||||
{
|
||||
"type":"array",
|
||||
"type" : "object",
|
||||
"required" : true,
|
||||
"title" : "edt_conf_v4l2_heading_title",
|
||||
"minItems": 1,
|
||||
"maxItems": 1,
|
||||
"items":
|
||||
"properties" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : true,
|
||||
"title" : "edt_conf_v4l2_heading_title",
|
||||
"properties" :
|
||||
"device" :
|
||||
{
|
||||
"device" :
|
||||
{
|
||||
"type" : "string",
|
||||
"title" : "edt_conf_v4l2_device_title",
|
||||
"default" : "auto",
|
||||
"minLength" : 4,
|
||||
"required" : true,
|
||||
"propertyOrder" : 1
|
||||
},
|
||||
"standard" :
|
||||
{
|
||||
"type" : "string",
|
||||
"title" : "edt_conf_v4l2_standard_title",
|
||||
"enum" : ["PAL","NTSC","SECAM","NO_CHANGE"],
|
||||
"default" : "NO_CHANGE",
|
||||
"options" : {
|
||||
"enum_titles" : ["edt_conf_enum_PAL", "edt_conf_enum_NTSC", "edt_conf_enum_SECAM", "edt_conf_enum_NO_CHANGE"]
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 2
|
||||
},
|
||||
"sizeDecimation" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"title" : "edt_conf_v4l2_sizeDecimation_title",
|
||||
"minimum" : 1,
|
||||
"maximum" : 30,
|
||||
"default" : 6,
|
||||
"required" : true,
|
||||
"propertyOrder" : 3
|
||||
},
|
||||
"cropLeft" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"title" : "edt_conf_v4l2_cropLeft_title",
|
||||
"minimum" : 0,
|
||||
"default" : 0,
|
||||
"append" : "edt_append_pixel",
|
||||
"required" : true,
|
||||
"propertyOrder" : 4
|
||||
},
|
||||
"cropRight" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"title" : "edt_conf_v4l2_cropRight_title",
|
||||
"minimum" : 0,
|
||||
"default" : 0,
|
||||
"append" : "edt_append_pixel",
|
||||
"required" : true,
|
||||
"propertyOrder" : 5
|
||||
},
|
||||
"cropTop" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"title" : "edt_conf_v4l2_cropTop_title",
|
||||
"minimum" : 0,
|
||||
"default" : 0,
|
||||
"append" : "edt_append_pixel",
|
||||
"required" : true,
|
||||
"propertyOrder" : 6
|
||||
},
|
||||
"cropBottom" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"title" : "edt_conf_v4l2_cropBottom_title",
|
||||
"minimum" : 0,
|
||||
"default" : 0,
|
||||
"append" : "edt_append_pixel",
|
||||
"required" : true,
|
||||
"propertyOrder" : 7
|
||||
},
|
||||
"signalDetection" :
|
||||
{
|
||||
"type" : "boolean",
|
||||
"title" : "edt_conf_v4l2_signalDetection_title",
|
||||
"default" : false,
|
||||
"required" : true,
|
||||
"propertyOrder" : 8
|
||||
},
|
||||
"redSignalThreshold" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"title" : "edt_conf_v4l2_redSignalThreshold_title",
|
||||
"minimum" : 0,
|
||||
"maximum" : 100,
|
||||
"default" : 5,
|
||||
"append" : "edt_append_percent",
|
||||
"options": {
|
||||
"dependencies": {
|
||||
"signalDetection": true
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 9
|
||||
},
|
||||
"greenSignalThreshold" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"title" : "edt_conf_v4l2_greenSignalThreshold_title",
|
||||
"minimum" : 0,
|
||||
"maximum" : 100,
|
||||
"default" : 5,
|
||||
"append" : "edt_append_percent",
|
||||
"options": {
|
||||
"dependencies": {
|
||||
"signalDetection": true
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 10
|
||||
},
|
||||
"blueSignalThreshold" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"title" : "edt_conf_v4l2_blueSignalThreshold_title",
|
||||
"minimum" : 0,
|
||||
"maximum" : 100,
|
||||
"default" : 5,
|
||||
"append" : "edt_append_percent",
|
||||
"options": {
|
||||
"dependencies": {
|
||||
"signalDetection": true
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 11
|
||||
},
|
||||
"sDVOffsetMin" :
|
||||
{
|
||||
"type" : "number",
|
||||
"title" : "edt_conf_v4l2_sDVOffsetMin_title",
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0,
|
||||
"default" : 0.25,
|
||||
"step" : 0.01,
|
||||
"options": {
|
||||
"dependencies": {
|
||||
"signalDetection": true
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 12
|
||||
},
|
||||
"sDVOffsetMax" :
|
||||
{
|
||||
"type" : "number",
|
||||
"title" : "edt_conf_v4l2_sDVOffsetMax_title",
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0,
|
||||
"default" : 0.75,
|
||||
"step" : 0.01,
|
||||
"options": {
|
||||
"dependencies": {
|
||||
"signalDetection": true
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 13
|
||||
},
|
||||
"sDHOffsetMin" :
|
||||
{
|
||||
"type" : "number",
|
||||
"title" : "edt_conf_v4l2_sDHOffsetMin_title",
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0,
|
||||
"default" : 0.25,
|
||||
"step" : 0.01,
|
||||
"options": {
|
||||
"dependencies": {
|
||||
"signalDetection": true
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 14
|
||||
},
|
||||
"sDHOffsetMax" :
|
||||
{
|
||||
"type" : "number",
|
||||
"title" : "edt_conf_v4l2_sDHOffsetMax_title",
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0,
|
||||
"default" : 0.75,
|
||||
"step" : 0.01,
|
||||
"options": {
|
||||
"dependencies": {
|
||||
"signalDetection": true
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 15
|
||||
}
|
||||
"type" : "string",
|
||||
"title" : "edt_conf_v4l2_device_title",
|
||||
"default" : "auto",
|
||||
"minLength" : 4,
|
||||
"required" : true,
|
||||
"propertyOrder" : 1
|
||||
},
|
||||
"standard" :
|
||||
{
|
||||
"type" : "string",
|
||||
"title" : "edt_conf_v4l2_standard_title",
|
||||
"enum" : ["PAL","NTSC","SECAM","NO_CHANGE"],
|
||||
"default" : "NO_CHANGE",
|
||||
"options" : {
|
||||
"enum_titles" : ["edt_conf_enum_PAL", "edt_conf_enum_NTSC", "edt_conf_enum_SECAM", "edt_conf_enum_NO_CHANGE"]
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 2
|
||||
},
|
||||
"sizeDecimation" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"title" : "edt_conf_v4l2_sizeDecimation_title",
|
||||
"minimum" : 1,
|
||||
"maximum" : 30,
|
||||
"default" : 6,
|
||||
"required" : true,
|
||||
"propertyOrder" : 3
|
||||
},
|
||||
"cropLeft" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"title" : "edt_conf_v4l2_cropLeft_title",
|
||||
"minimum" : 0,
|
||||
"default" : 0,
|
||||
"append" : "edt_append_pixel",
|
||||
"required" : true,
|
||||
"propertyOrder" : 4
|
||||
},
|
||||
"cropRight" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"title" : "edt_conf_v4l2_cropRight_title",
|
||||
"minimum" : 0,
|
||||
"default" : 0,
|
||||
"append" : "edt_append_pixel",
|
||||
"required" : true,
|
||||
"propertyOrder" : 5
|
||||
},
|
||||
"cropTop" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"title" : "edt_conf_v4l2_cropTop_title",
|
||||
"minimum" : 0,
|
||||
"default" : 0,
|
||||
"append" : "edt_append_pixel",
|
||||
"required" : true,
|
||||
"propertyOrder" : 6
|
||||
},
|
||||
"cropBottom" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"title" : "edt_conf_v4l2_cropBottom_title",
|
||||
"minimum" : 0,
|
||||
"default" : 0,
|
||||
"append" : "edt_append_pixel",
|
||||
"required" : true,
|
||||
"propertyOrder" : 7
|
||||
},
|
||||
"signalDetection" :
|
||||
{
|
||||
"type" : "boolean",
|
||||
"title" : "edt_conf_v4l2_signalDetection_title",
|
||||
"default" : false,
|
||||
"required" : true,
|
||||
"propertyOrder" : 8
|
||||
},
|
||||
"redSignalThreshold" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"title" : "edt_conf_v4l2_redSignalThreshold_title",
|
||||
"minimum" : 0,
|
||||
"maximum" : 100,
|
||||
"default" : 5,
|
||||
"append" : "edt_append_percent",
|
||||
"options": {
|
||||
"dependencies": {
|
||||
"signalDetection": true
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 9
|
||||
},
|
||||
"greenSignalThreshold" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"title" : "edt_conf_v4l2_greenSignalThreshold_title",
|
||||
"minimum" : 0,
|
||||
"maximum" : 100,
|
||||
"default" : 5,
|
||||
"append" : "edt_append_percent",
|
||||
"options": {
|
||||
"dependencies": {
|
||||
"signalDetection": true
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 10
|
||||
},
|
||||
"blueSignalThreshold" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"title" : "edt_conf_v4l2_blueSignalThreshold_title",
|
||||
"minimum" : 0,
|
||||
"maximum" : 100,
|
||||
"default" : 5,
|
||||
"append" : "edt_append_percent",
|
||||
"options": {
|
||||
"dependencies": {
|
||||
"signalDetection": true
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 11
|
||||
},
|
||||
"sDVOffsetMin" :
|
||||
{
|
||||
"type" : "number",
|
||||
"title" : "edt_conf_v4l2_sDVOffsetMin_title",
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0,
|
||||
"default" : 0.25,
|
||||
"step" : 0.01,
|
||||
"options": {
|
||||
"dependencies": {
|
||||
"signalDetection": true
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 12
|
||||
},
|
||||
"sDVOffsetMax" :
|
||||
{
|
||||
"type" : "number",
|
||||
"title" : "edt_conf_v4l2_sDVOffsetMax_title",
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0,
|
||||
"default" : 0.75,
|
||||
"step" : 0.01,
|
||||
"options": {
|
||||
"dependencies": {
|
||||
"signalDetection": true
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 13
|
||||
},
|
||||
"sDHOffsetMin" :
|
||||
{
|
||||
"type" : "number",
|
||||
"title" : "edt_conf_v4l2_sDHOffsetMin_title",
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0,
|
||||
"default" : 0.25,
|
||||
"step" : 0.01,
|
||||
"options": {
|
||||
"dependencies": {
|
||||
"signalDetection": true
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 14
|
||||
},
|
||||
"sDHOffsetMax" :
|
||||
{
|
||||
"type" : "number",
|
||||
"title" : "edt_conf_v4l2_sDHOffsetMax_title",
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0,
|
||||
"default" : 0.75,
|
||||
"step" : 0.01,
|
||||
"options": {
|
||||
"dependencies": {
|
||||
"signalDetection": true
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 15
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
}
|
||||
|
@ -121,6 +121,10 @@ void ImageResampler::processImage(const uint8_t * data, int width, int height, i
|
||||
rgb.red = data[index+2];
|
||||
}
|
||||
break;
|
||||
#ifdef HAVE_JPEG
|
||||
case PIXELFORMAT_MJPEG:
|
||||
break;
|
||||
#endif
|
||||
case PIXELFORMAT_NO_CHANGE:
|
||||
Error(Logger::getInstance("ImageResampler"), "Invalid pixel format given");
|
||||
break;
|
||||
|
@ -60,7 +60,7 @@ int main(int argc, char** argv)
|
||||
|
||||
Option & argDevice = parser.add<Option> ('d', "device", "The device to use, can be /dev/video0 [default: %1 (auto detected)]", "auto");
|
||||
SwitchOption<VideoStandard> & argVideoStandard= parser.add<SwitchOption<VideoStandard>>('v', "video-standard", "The used video standard. Valid values are PAL, NTSC, SECAM or no-change. [default: %1]", "no-change");
|
||||
SwitchOption<PixelFormat> & argPixelFormat = parser.add<SwitchOption<PixelFormat>> (0x0, "pixel-format", "The use pixel format. Valid values are YUYV, UYVY, RGB32 or no-change. [default: %1]", "no-change");
|
||||
SwitchOption<PixelFormat> & argPixelFormat = parser.add<SwitchOption<PixelFormat>> (0x0, "pixel-format", "The use pixel format. Valid values are YUYV, UYVY, RGB32, MJPEG or no-change. [default: %1]", "no-change");
|
||||
IntOption & argCropWidth = parser.add<IntOption> (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: %1]", "0");
|
||||
IntOption & argCropHeight = parser.add<IntOption> (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: %1]", "0");
|
||||
IntOption & argCropLeft = parser.add<IntOption> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)");
|
||||
@ -96,6 +96,9 @@ int main(int argc, char** argv)
|
||||
argPixelFormat.addSwitch("yuyv", PIXELFORMAT_YUYV);
|
||||
argPixelFormat.addSwitch("uyvy", PIXELFORMAT_UYVY);
|
||||
argPixelFormat.addSwitch("rgb32", PIXELFORMAT_RGB32);
|
||||
#ifdef HAVE_JPEG
|
||||
argPixelFormat.addSwitch("mjpeg", PIXELFORMAT_MJPEG);
|
||||
#endif
|
||||
argPixelFormat.addSwitch("no-change", PIXELFORMAT_NO_CHANGE);
|
||||
|
||||
// parse all options
|
||||
@ -212,9 +215,11 @@ int main(int argc, char** argv)
|
||||
// Connect the screen capturing to flatbuf connection processing
|
||||
QObject::connect(&grabber, SIGNAL(newFrame(const Image<ColorRgb> &)), &flatbuf, SLOT(setImage(Image<ColorRgb>)));
|
||||
|
||||
if (grabber.start())
|
||||
QCoreApplication::exec();
|
||||
grabber.stop();
|
||||
// Start the capturing
|
||||
grabber.start();
|
||||
|
||||
// Start the application
|
||||
app.exec();
|
||||
}
|
||||
}
|
||||
catch (const std::runtime_error & e)
|
||||
|
@ -57,7 +57,7 @@ HyperionDaemon::HyperionDaemon(QString configFile, const QString rootPath, QObje
|
||||
, _webserver(nullptr)
|
||||
, _jsonServer(nullptr)
|
||||
, _udpListener(nullptr)
|
||||
, _v4l2Grabbers()
|
||||
, _v4l2Grabbers(nullptr)
|
||||
, _dispmanx(nullptr)
|
||||
, _x11Grabber(nullptr)
|
||||
, _amlGrabber(nullptr)
|
||||
@ -162,14 +162,10 @@ void HyperionDaemon::freeObjects()
|
||||
delete _fbGrabber;
|
||||
delete _osxGrabber;
|
||||
delete _qtGrabber;
|
||||
|
||||
for(V4L2Wrapper* grabber : _v4l2Grabbers)
|
||||
{
|
||||
delete grabber;
|
||||
}
|
||||
delete _v4l2Grabbers;
|
||||
delete _stats;
|
||||
|
||||
_v4l2Grabbers.clear();
|
||||
_v4l2Grabbers = nullptr;
|
||||
_bonjourBrowserWrapper = nullptr;
|
||||
_amlGrabber = nullptr;
|
||||
_dispmanx = nullptr;
|
||||
@ -386,19 +382,9 @@ void HyperionDaemon::handleSettingsUpdate(const settings::type& type, const QJso
|
||||
}
|
||||
else if(type == settings::V4L2)
|
||||
{
|
||||
// stop
|
||||
if(_v4l2Grabbers.size()>0)
|
||||
return;
|
||||
|
||||
unsigned v4lEnableCount = 0;
|
||||
|
||||
const QJsonArray & v4lArray = config.array();
|
||||
for ( signed idx=0; idx<v4lArray.size(); idx++)
|
||||
{
|
||||
#ifdef ENABLE_V4L2
|
||||
|
||||
const QJsonObject & grabberConfig = v4lArray.at(idx).toObject();
|
||||
bool enableV4l = grabberConfig["enable"].toBool(true);
|
||||
#ifdef ENABLE_V4L2
|
||||
const QJsonObject & grabberConfig = config.object();
|
||||
|
||||
V4L2Wrapper* grabber = new V4L2Wrapper(
|
||||
grabberConfig["device"].toString("auto"),
|
||||
@ -425,15 +411,9 @@ void HyperionDaemon::handleSettingsUpdate(const settings::type& type, const QJso
|
||||
// connect to HyperionDaemon signal
|
||||
connect(this, &HyperionDaemon::videoMode, grabber, &V4L2Wrapper::setVideoMode);
|
||||
connect(this, &HyperionDaemon::settingsChanged, grabber, &V4L2Wrapper::handleSettingsUpdate);
|
||||
|
||||
if (enableV4l)
|
||||
v4lEnableCount++;
|
||||
|
||||
_v4l2Grabbers.push_back(grabber);
|
||||
#endif
|
||||
}
|
||||
|
||||
ErrorIf( (v4lEnableCount>0 && _v4l2Grabbers.size()==0), _log, "The v4l2 grabber can not be instantiated, because it has been left out from the build");
|
||||
#else
|
||||
Error(_log, "The v4l2 grabber can not be instantiated, because it has been left out from the build");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -449,7 +429,7 @@ void HyperionDaemon::createGrabberDispmanx()
|
||||
|
||||
Info(_log, "DISPMANX frame grabber created");
|
||||
#else
|
||||
Error( _log, "The dispmanx framegrabber can not be instantiated, because it has been left out from the build");
|
||||
Error(_log, "The dispmanx framegrabber can not be instantiated, because it has been left out from the build");
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -466,7 +446,7 @@ void HyperionDaemon::createGrabberAmlogic()
|
||||
|
||||
Info(_log, "AMLOGIC grabber created");
|
||||
#else
|
||||
Error( _log, "The AMLOGIC grabber can not be instantiated, because it has been left out from the build");
|
||||
Error(_log, "The AMLOGIC grabber can not be instantiated, because it has been left out from the build");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -137,7 +137,7 @@ private:
|
||||
WebServer* _webserver;
|
||||
JsonServer* _jsonServer;
|
||||
UDPListener* _udpListener;
|
||||
std::vector<V4L2Wrapper*> _v4l2Grabbers;
|
||||
V4L2Wrapper* _v4l2Grabbers;
|
||||
DispmanxWrapper* _dispmanx;
|
||||
X11Wrapper* _x11Grabber;
|
||||
AmlogicWrapper* _amlGrabber;
|
||||
|
Loading…
Reference in New Issue
Block a user