mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2025-03-01 10:33:28 +00:00
Added image flipping ability to MF Grabber
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
#include "MFSourceReaderCB.h"
|
||||
#include "grabber/MFGrabber.h"
|
||||
|
||||
MFGrabber::MFGrabber(const QString & device, unsigned width, unsigned height, unsigned fps, unsigned input, int pixelDecimation)
|
||||
// Constants
|
||||
namespace { const bool verbose = false; }
|
||||
|
||||
MFGrabber::MFGrabber(const QString & device, unsigned width, unsigned height, unsigned fps, unsigned input, int pixelDecimation, QString flipMode)
|
||||
: Grabber("V4L2:"+device)
|
||||
, _deviceName(device)
|
||||
, _hr(S_FALSE)
|
||||
@@ -30,6 +33,7 @@ MFGrabber::MFGrabber(const QString & device, unsigned width, unsigned height, un
|
||||
setInput(input);
|
||||
setWidthHeight(width, height);
|
||||
setFramerate(fps);
|
||||
setFlipMode(flipMode);
|
||||
// setDeviceVideoStandard(device, videoStandard); // TODO
|
||||
|
||||
CoInitializeEx(0, COINIT_MULTITHREADED);
|
||||
@@ -467,8 +471,8 @@ void MFGrabber::enumVideoCaptureDevices()
|
||||
if (pixelformat != PixelFormat::NO_CHANGE)
|
||||
{
|
||||
int framerate = fr1/fr2;
|
||||
QString sFrame = QString::number(framerate).rightJustified(2,' ');
|
||||
QString displayResolutions = QString::number(w).rightJustified(4,' ') +"x"+ QString::number(h).rightJustified(4,' ');
|
||||
QString sFrame = QString::number(framerate).rightJustified(2,' ').trimmed();
|
||||
QString displayResolutions = QString::number(w).rightJustified(4,' ').trimmed() +"x"+ QString::number(h).rightJustified(4,' ').trimmed();
|
||||
|
||||
if (!properties.displayResolutions.contains(displayResolutions))
|
||||
properties.displayResolutions << displayResolutions;
|
||||
@@ -486,7 +490,7 @@ void MFGrabber::enumVideoCaptureDevices()
|
||||
di.guid = format;
|
||||
properties.valid.append(di);
|
||||
|
||||
Debug(_log, "%s %d x %d @ %d fps (%s)", QSTRING_CSTR(dev), di.x, di.y, di.fps, QSTRING_CSTR(pixelFormatToString(di.pf)));
|
||||
DebugIf(verbose, _log, "%s %d x %d @ %d fps (%s)", QSTRING_CSTR(dev), di.x, di.y, di.fps, QSTRING_CSTR(pixelFormatToString(di.pf)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -553,12 +557,12 @@ void MFGrabber::process_image(const void *frameImageBuffer, int size)
|
||||
|
||||
for (unsigned int i=0; i < _threadManager._maxThreads && _threadManager._threads != nullptr; i++)
|
||||
{
|
||||
MFThread* _thread=_threadManager._threads[i];
|
||||
MFThread* _thread = _threadManager._threads[i];
|
||||
connect(_thread, SIGNAL(newFrame(unsigned int, const Image<ColorRgb> &,unsigned int)), this , SLOT(newThreadFrame(unsigned int, const Image<ColorRgb> &, unsigned int)));
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i=0;_threadManager.isActive() && i < _threadManager._maxThreads && _threadManager._threads != nullptr; i++)
|
||||
for (unsigned int i = 0;_threadManager.isActive() && i < _threadManager._maxThreads && _threadManager._threads != nullptr; i++)
|
||||
{
|
||||
if ((_threadManager._threads[i]->isFinished() || !_threadManager._threads[i]->isRunning()))
|
||||
{
|
||||
@@ -566,11 +570,8 @@ void MFGrabber::process_image(const void *frameImageBuffer, int size)
|
||||
if ( _threadManager._threads[i]->isBusy() == false)
|
||||
{
|
||||
MFThread* _thread = _threadManager._threads[i];
|
||||
_thread->setup(i, _pixelFormat, (uint8_t *)frameImageBuffer, size, _width, _height, _lineLength, _subsamp, _cropLeft, _cropTop, _cropBottom, _cropRight, _videoMode, processFrameIndex, _pixelDecimation);
|
||||
|
||||
if (_threadManager._maxThreads > 1)
|
||||
_threadManager._threads[i]->start();
|
||||
|
||||
_thread->setup(i, _pixelFormat, (uint8_t *)frameImageBuffer, size, _width, _height, _lineLength, _subsamp, _cropLeft, _cropTop, _cropBottom, _cropRight, _videoMode, _flipMode, processFrameIndex, _pixelDecimation);
|
||||
_threadManager._threads[i]->start();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -586,7 +587,8 @@ void MFGrabber::setSignalThreshold(double redSignalThreshold, double greenSignal
|
||||
_noSignalThresholdColor.blue = uint8_t(255*blueSignalThreshold);
|
||||
_noSignalCounterThreshold = qMax(1, noSignalCounterThreshold);
|
||||
|
||||
Info(_log, "Signal threshold set to: {%d, %d, %d} and frames: %d", _noSignalThresholdColor.red, _noSignalThresholdColor.green, _noSignalThresholdColor.blue, _noSignalCounterThreshold );
|
||||
if(_signalDetectionEnabled)
|
||||
Info(_log, "Signal threshold set to: {%d, %d, %d} and frames: %d", _noSignalThresholdColor.red, _noSignalThresholdColor.green, _noSignalThresholdColor.blue, _noSignalCounterThreshold );
|
||||
}
|
||||
|
||||
void MFGrabber::setSignalDetectionOffset(double horizontalMin, double verticalMin, double horizontalMax, double verticalMax)
|
||||
@@ -599,7 +601,8 @@ void MFGrabber::setSignalDetectionOffset(double horizontalMin, double verticalMi
|
||||
_x_frac_max = horizontalMax;
|
||||
_y_frac_max = verticalMax;
|
||||
|
||||
Info(_log, "Signal detection area set to: %f,%f x %f,%f", _x_frac_min, _y_frac_min, _x_frac_max, _y_frac_max );
|
||||
if(_signalDetectionEnabled)
|
||||
Info(_log, "Signal detection area set to: %f,%f x %f,%f", _x_frac_min, _y_frac_min, _x_frac_max, _y_frac_max );
|
||||
}
|
||||
|
||||
bool MFGrabber::start()
|
||||
@@ -744,6 +747,12 @@ void MFGrabber::setPixelDecimation(int pixelDecimation)
|
||||
_pixelDecimation = pixelDecimation;
|
||||
}
|
||||
|
||||
void MFGrabber::setFlipMode(QString flipMode)
|
||||
{
|
||||
if(_flipMode != parseFlipMode(flipMode))
|
||||
Grabber::setFlipMode(parseFlipMode(flipMode));
|
||||
}
|
||||
|
||||
void MFGrabber::setDeviceVideoStandard(QString device, VideoStandard videoStandard)
|
||||
{
|
||||
if(_deviceName != device)
|
||||
|
@@ -3,26 +3,31 @@
|
||||
volatile bool MFThread::_isActive = false;
|
||||
|
||||
MFThread::MFThread()
|
||||
: _localData(nullptr)
|
||||
: _isBusy(false)
|
||||
, _semaphore(1)
|
||||
, _localData(nullptr)
|
||||
, _localDataSize(0)
|
||||
, _decompress(nullptr)
|
||||
, _scalingFactorsCount(0)
|
||||
, _scalingFactors(nullptr)
|
||||
, _isBusy(false)
|
||||
, _semaphore(1)
|
||||
, _transform(nullptr)
|
||||
, _decompress(nullptr)
|
||||
, _xform(nullptr)
|
||||
, _imageResampler()
|
||||
{
|
||||
}
|
||||
|
||||
MFThread::~MFThread()
|
||||
{
|
||||
if (_decompress == nullptr)
|
||||
if (_transform)
|
||||
tjDestroy(_transform);
|
||||
|
||||
if (_decompress)
|
||||
tjDestroy(_decompress);
|
||||
|
||||
if (_localData != NULL)
|
||||
if (_localData)
|
||||
{
|
||||
free(_localData);
|
||||
_localData = NULL;
|
||||
_localData = nullptr;
|
||||
_localDataSize = 0;
|
||||
}
|
||||
}
|
||||
@@ -31,9 +36,9 @@ void MFThread::setup(
|
||||
unsigned int threadIndex, PixelFormat pixelFormat, uint8_t* sharedData,
|
||||
int size, int width, int height, int lineLength,
|
||||
int subsamp, unsigned cropLeft, unsigned cropTop, unsigned cropBottom, unsigned cropRight,
|
||||
VideoMode videoMode, int currentFrame, int pixelDecimation)
|
||||
VideoMode videoMode, FlipMode flipMode, int currentFrame, int pixelDecimation)
|
||||
{
|
||||
_workerIndex = threadIndex;
|
||||
_threadIndex = threadIndex;
|
||||
_lineLength = lineLength;
|
||||
_pixelFormat = pixelFormat;
|
||||
_size = size;
|
||||
@@ -44,26 +49,25 @@ void MFThread::setup(
|
||||
_cropTop = cropTop;
|
||||
_cropBottom = cropBottom;
|
||||
_cropRight = cropRight;
|
||||
_flipMode = flipMode;
|
||||
_currentFrame = currentFrame;
|
||||
_pixelDecimation = pixelDecimation;
|
||||
|
||||
_imageResampler.setVideoMode(videoMode);
|
||||
_imageResampler.setFlipMode(_flipMode);
|
||||
_imageResampler.setCropping(cropLeft, cropRight, cropTop, cropBottom);
|
||||
_imageResampler.setHorizontalPixelDecimation(_pixelDecimation);
|
||||
_imageResampler.setVerticalPixelDecimation(_pixelDecimation);
|
||||
_imageResampler.setFlipMode(FlipMode::NO_CHANGE);
|
||||
|
||||
if (size > _localDataSize)
|
||||
{
|
||||
if (_localData != NULL)
|
||||
{
|
||||
free(_localData);
|
||||
_localData = NULL;
|
||||
_localDataSize = 0;
|
||||
}
|
||||
_localData = (uint8_t *) malloc(size+1);
|
||||
if (_localData)
|
||||
tjFree(_localData);
|
||||
|
||||
_localData = (uint8_t*)tjAlloc(size + 1);
|
||||
_localDataSize = size;
|
||||
}
|
||||
|
||||
memcpy(_localData, sharedData, size);
|
||||
}
|
||||
|
||||
@@ -79,7 +83,7 @@ void MFThread::run()
|
||||
{
|
||||
Image<ColorRgb> image = Image<ColorRgb>();
|
||||
_imageResampler.processImage(_localData, _width, _height, _lineLength, PixelFormat::BGR24, image);
|
||||
emit newFrame(_workerIndex, image, _currentFrame);
|
||||
emit newFrame(_threadIndex, image, _currentFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,11 +112,36 @@ void MFThread::noBusy()
|
||||
|
||||
void MFThread::processImageMjpeg()
|
||||
{
|
||||
if (_decompress == nullptr)
|
||||
if (!_transform && _flipMode != FlipMode::NO_CHANGE)
|
||||
{
|
||||
_transform = tjInitTransform();
|
||||
_xform = new tjtransform();
|
||||
}
|
||||
|
||||
if (_flipMode == FlipMode::BOTH || _flipMode == FlipMode::HORIZONTAL)
|
||||
{
|
||||
_xform->op = TJXOP_HFLIP;
|
||||
uint8_t* dstBuf = nullptr;
|
||||
unsigned long dstSize = 0;
|
||||
tjTransform(_transform, _localData, _size, 1, &dstBuf, &dstSize, _xform, TJFLAG_FASTDCT | TJFLAG_FASTUPSAMPLE);
|
||||
_localData = dstBuf;
|
||||
_size = dstSize;
|
||||
}
|
||||
|
||||
if (_flipMode == FlipMode::BOTH || _flipMode == FlipMode::VERTICAL)
|
||||
{
|
||||
_xform->op = TJXOP_VFLIP;
|
||||
uint8_t *dstBuf = nullptr;
|
||||
unsigned long dstSize = 0;
|
||||
tjTransform(_transform, _localData, _size, 1, &dstBuf, &dstSize, _xform, TJFLAG_FASTDCT | TJFLAG_FASTUPSAMPLE);
|
||||
_localData = dstBuf;
|
||||
_size = dstSize;
|
||||
}
|
||||
|
||||
if (!_decompress)
|
||||
{
|
||||
_decompress = tjInitDecompress();
|
||||
_scalingFactors = tjGetScalingFactors (&_scalingFactorsCount);
|
||||
tjhandle handle=NULL;
|
||||
_scalingFactors = tjGetScalingFactors(&_scalingFactorsCount);
|
||||
}
|
||||
|
||||
if (tjDecompressHeader2(_decompress, _localData, _size, &_width, &_height, &_subsamp) != 0)
|
||||
@@ -153,10 +182,10 @@ void MFThread::processImageMjpeg()
|
||||
|
||||
// got image, process it
|
||||
if ( !(_cropLeft > 0 || _cropTop > 0 || _cropBottom > 0 || _cropRight > 0))
|
||||
emit newFrame(_workerIndex, srcImage, _currentFrame);
|
||||
emit newFrame(_threadIndex, srcImage, _currentFrame);
|
||||
else
|
||||
{
|
||||
// calculate the output size
|
||||
// calculate the output size
|
||||
int outputWidth = (_width - _cropLeft - _cropRight);
|
||||
int outputHeight = (_height - _cropTop - _cropBottom);
|
||||
|
||||
@@ -171,10 +200,12 @@ void MFThread::processImageMjpeg()
|
||||
unsigned char* dest = (unsigned char*)destImage.memptr() + y*destImage.width()*3;
|
||||
memcpy(dest, source, destImage.width()*3);
|
||||
free(source);
|
||||
source = nullptr;
|
||||
free(dest);
|
||||
dest = nullptr;
|
||||
}
|
||||
|
||||
// emit
|
||||
emit newFrame(_workerIndex, destImage, _currentFrame);
|
||||
emit newFrame(_threadIndex, destImage, _currentFrame);
|
||||
}
|
||||
}
|
||||
|
@@ -5,9 +5,9 @@
|
||||
// qt
|
||||
#include <QTimer>
|
||||
|
||||
MFWrapper::MFWrapper(const QString &device, unsigned grabWidth, unsigned grabHeight, unsigned fps, unsigned input, int pixelDecimation )
|
||||
MFWrapper::MFWrapper(const QString &device, unsigned grabWidth, unsigned grabHeight, unsigned fps, unsigned input, int pixelDecimation, QString flipMode)
|
||||
: GrabberWrapper("V4L2:"+device, &_grabber, grabWidth, grabHeight, 10)
|
||||
, _grabber(device, grabWidth, grabHeight, fps, input, pixelDecimation)
|
||||
, _grabber(device, grabWidth, grabHeight, fps, input, pixelDecimation, flipMode)
|
||||
{
|
||||
_ggrabber = &_grabber;
|
||||
|
||||
@@ -123,6 +123,9 @@ void MFWrapper::handleSettingsUpdate(settings::type type, const QJsonDocument& c
|
||||
// image size decimation
|
||||
_grabber.setPixelDecimation(obj["sizeDecimation"].toInt(8));
|
||||
|
||||
// flip mode
|
||||
_grabber.setFlipMode(obj["flip"].toString("no-change"));
|
||||
|
||||
// image cropping
|
||||
_grabber.setCropping(
|
||||
obj["cropLeft"].toInt(0),
|
||||
|
Reference in New Issue
Block a user