feat: SchemaChecker & V4L2 enhancement (#734)

* libjpeg-turbo, QJsonSchemaChecker, V4L2 width/height/fps

Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com>

* Implement hyperion-v4l cli args

* Apply v4l2 settings during runtime

* feat: Provide minimum values for input restriction

* fix: merge mess

Co-authored-by: brindosch <edeltraud70@gmx.de>
This commit is contained in:
Paulchen Panther
2020-03-27 23:13:58 +01:00
committed by GitHub
parent 20a5e5dc06
commit 662872dafe
26 changed files with 363 additions and 121 deletions

View File

@@ -11,6 +11,8 @@ target_link_libraries(v4l2-grabber
${QT_LIBRARIES}
)
if (JPEG_FOUND)
target_link_libraries(v4l2-grabber ${JPEG_LIBRARY})
endif()
if(TURBOJPEG_FOUND)
target_link_libraries(v4l2-grabber ${TurboJPEG_LIBRARY})
elseif (JPEG_FOUND)
target_link_libraries(v4l2-grabber ${JPEG_LIBRARY})
endif(TURBOJPEG_FOUND)

View File

@@ -27,6 +27,9 @@
#define CLEAR(x) memset(&(x), 0, sizeof(x))
V4L2Grabber::V4L2Grabber(const QString & device
, const unsigned width
, const unsigned height
, const unsigned fps
, VideoStandard videoStandard
, PixelFormat pixelFormat
, int pixelDecimation
@@ -59,6 +62,8 @@ V4L2Grabber::V4L2Grabber(const QString & device
getV4Ldevices();
// init
setWidthHeight(width, height);
setFramerate(fps);
setDeviceVideoStandard(device, videoStandard);
}
@@ -561,7 +566,7 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;
break;
#ifdef HAVE_JPEG
#ifdef HAVE_JPEG_DECODER
case PIXELFORMAT_MJPEG:
{
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
@@ -576,53 +581,41 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
break;
}
// get maximum video devices resolution
__u32 max_width = 0, max_height = 0;
struct v4l2_fmtdesc fmtdesc;
CLEAR(fmtdesc);
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmtdesc.index = 0;
while (xioctl(VIDIOC_ENUM_FMT, &fmtdesc) >= 0)
// collect available device resolutions
QString v4lDevice_res;
v4l2_frmsizeenum frmsizeenum;
CLEAR(frmsizeenum);
frmsizeenum.index = 0;
frmsizeenum.pixel_format = fmt.fmt.pix.pixelformat;
while (xioctl(VIDIOC_ENUM_FRAMESIZES, &frmsizeenum) >= 0)
{
v4l2_frmsizeenum frmsizeenum;
CLEAR(frmsizeenum);
frmsizeenum.pixel_format = fmtdesc.pixelformat;
frmsizeenum.index = 0;
while (xioctl(VIDIOC_ENUM_FRAMESIZES, &frmsizeenum) >= 0)
switch (frmsizeenum.type)
{
switch (frmsizeenum.type)
case V4L2_FRMSIZE_TYPE_DISCRETE:
v4lDevice_res += "\t"+ QString::number(frmsizeenum.discrete.width) + "x" + QString::number(frmsizeenum.discrete.height) + "\n";
break;
case V4L2_FRMSIZE_TYPE_CONTINUOUS:
case V4L2_FRMSIZE_TYPE_STEPWISE:
{
case V4L2_FRMSIZE_TYPE_DISCRETE:
for(unsigned int y = frmsizeenum.stepwise.min_height; y <= frmsizeenum.stepwise.max_height; y += frmsizeenum.stepwise.step_height)
{
max_width = std::max(max_width, frmsizeenum.discrete.width);
max_height = std::max(max_height, frmsizeenum.discrete.height);
}
break;
case V4L2_FRMSIZE_TYPE_CONTINUOUS:
case V4L2_FRMSIZE_TYPE_STEPWISE:
{
max_width = std::max(max_width, frmsizeenum.stepwise.max_width);
max_height = std::max(max_height, frmsizeenum.stepwise.max_height);
for(unsigned int x = frmsizeenum.stepwise.min_width; x <= frmsizeenum.stepwise.max_width; x += frmsizeenum.stepwise.step_width)
{
v4lDevice_res += "\t"+ QString::number(x) + "x" + QString::number(y) + "\n";
}
}
}
frmsizeenum.index++;
}
fmtdesc.index++;
frmsizeenum.index++;
}
// print available device resolutions in debug mode
if (!v4lDevice_res.isEmpty())
Debug(_log, "available V4L2 resolutions:\n%s", QSTRING_CSTR(v4lDevice_res));
// set the settings
if (max_width != 0 || max_height != 0)
{
fmt.fmt.pix.width = max_width;
fmt.fmt.pix.height = max_height;
}
else
{
fmt.fmt.pix.width = _width;
fmt.fmt.pix.height = _height;
}
fmt.fmt.pix.width = _width;
fmt.fmt.pix.height = _height;
if (-1 == xioctl(VIDIOC_S_FMT, &fmt))
{
@@ -652,14 +645,18 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
if (streamparms.parm.capture.capability == V4L2_CAP_TIMEPERFRAME)
{
// Driver supports the feature. Set required framerate
streamparms.parm.capture.capturemode = V4L2_MODE_HIGHQUALITY;
CLEAR(streamparms);
streamparms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
streamparms.parm.capture.timeperframe.numerator = 1;
streamparms.parm.capture.timeperframe.denominator = 30;
streamparms.parm.capture.timeperframe.denominator = _fps;
if(-1 == xioctl(VIDIOC_S_PARM, &streamparms))
{
throw_errno_exception("VIDIOC_S_PARM");
// continue
}
else
// display the used framerate
Debug(_log, "Set framerate to %d fps", _fps);
}
}
@@ -693,7 +690,7 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
}
break;
#ifdef HAVE_JPEG
#ifdef HAVE_JPEG_DECODER
case V4L2_PIX_FMT_MJPEG:
{
_pixelFormat = PIXELFORMAT_MJPEG;
@@ -703,7 +700,7 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
#endif
default:
#ifdef HAVE_JPEG
#ifdef HAVE_JPEG_DECODER
throw_exception("Only pixel formats UYVY, YUYV, RGB32 and MJPEG are supported");
#else
throw_exception("Only pixel formats UYVY, YUYV, and RGB32 are supported");
@@ -955,7 +952,7 @@ int V4L2Grabber::read_frame()
bool V4L2Grabber::process_image(const void *p, int size)
{
// We do want a new frame...
#ifdef HAVE_JPEG
#ifdef HAVE_JPEG_DECODER
if (size != _frameByteSize && _pixelFormat != PIXELFORMAT_MJPEG)
#else
if (size != _frameByteSize)
@@ -976,9 +973,15 @@ void V4L2Grabber::process_image(const uint8_t * data, int size)
{
Image<ColorRgb> image(_width, _height);
#ifdef HAVE_JPEG
/* ----------------------------------------------------------
* ----------- BEGIN of JPEG decoder related code -----------
* --------------------------------------------------------*/
#ifdef HAVE_JPEG_DECODER
if (_pixelFormat == PIXELFORMAT_MJPEG)
{
#endif
#ifdef HAVE_JPEG
_decompress = new jpeg_decompress_struct;
_error = new errorManager;
@@ -1048,7 +1051,31 @@ void V4L2Grabber::process_image(const uint8_t * data, int size)
if (imageFrame.isNull() || _error->pub.num_warnings > 0)
return;
#endif
#ifdef HAVE_TURBO_JPEG
_decompress = tjInitDecompress();
if (_decompress == nullptr)
return;
if (tjDecompressHeader2(_decompress, const_cast<uint8_t*>(data), size, &_width, &_height, &_subsamp) != 0)
{
tjDestroy(_decompress);
return;
}
QImage imageFrame = QImage(_width, _height, QImage::Format_RGB888);
if (tjDecompress2(_decompress, const_cast<uint8_t*>(data), size, imageFrame.bits(), _width, 0, _height, TJPF_RGB, TJFLAG_FASTDCT | TJFLAG_FASTUPSAMPLE) != 0)
{
tjDestroy(_decompress);
return;
}
tjDestroy(_decompress);
if (imageFrame.isNull())
return;
#endif
#ifdef HAVE_JPEG_DECODER
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);
@@ -1068,6 +1095,11 @@ void V4L2Grabber::process_image(const uint8_t * data, int size)
}
else
#endif
/* ----------------------------------------------------------
* ------------ END of JPEG decoder related code ------------
* --------------------------------------------------------*/
_imageResampler.processImage(data, _width, _height, _lineLength, _pixelFormat, image);
if (_signalDetectionEnabled)
@@ -1171,3 +1203,27 @@ void V4L2Grabber::setDeviceVideoStandard(QString device, VideoStandard videoStan
if(started) start();
}
}
bool V4L2Grabber::setFramerate(int fps)
{
if(Grabber::setFramerate(fps))
{
bool started = _initialized;
uninit();
if(started) start();
return true;
}
return false;
}
bool V4L2Grabber::setWidthHeight(int width, int height)
{
if(Grabber::setWidthHeight(width,height))
{
bool started = _initialized;
uninit();
if(started) start();
return true;
}
return false;
}

View File

@@ -6,11 +6,17 @@
#include <QTimer>
V4L2Wrapper::V4L2Wrapper(const QString &device,
const unsigned grabWidth,
const unsigned grabHeight,
const unsigned fps,
VideoStandard videoStandard,
PixelFormat pixelFormat,
int pixelDecimation )
: GrabberWrapper("V4L2:"+device, &_grabber, 0, 0, 10)
: GrabberWrapper("V4L2:"+device, &_grabber, grabWidth, grabHeight, 10)
, _grabber(device,
grabWidth,
grabHeight,
fps,
videoStandard,
pixelFormat,
pixelDecimation)