V4L2/MF changes

This commit is contained in:
Paulchen Panther
2021-05-16 15:47:25 +02:00
parent bf32557a8a
commit cfb34e6bfc
19 changed files with 426 additions and 537 deletions

View File

@@ -7,25 +7,26 @@
#include <utils/PixelFormat.h>
#include <utils/ImageResampler.h>
// TurboJPEG decoder
// Determine the cmake options
#include <HyperionConfig.h>
// Turbo JPEG decoder
#ifdef HAVE_TURBO_JPEG
#include <QImage>
#include <QColor>
#include <turbojpeg.h>
#endif
/// Encoder thread for USB devices
class MFThread : public QObject
class EncoderThread : public QObject
{
Q_OBJECT
public:
explicit MFThread();
~MFThread();
explicit EncoderThread();
~EncoderThread();
void setup(
PixelFormat pixelFormat, uint8_t* sharedData,
int size, int width, int height, int lineLength,
int subsamp, unsigned cropLeft, unsigned cropTop, unsigned cropBottom, unsigned cropRight,
unsigned cropLeft, unsigned cropTop, unsigned cropBottom, unsigned cropRight,
VideoMode videoMode, FlipMode flipMode, int pixelDecimation);
void process();
@@ -37,15 +38,6 @@ signals:
void newFrame(const Image<ColorRgb>& data);
private:
void processImageMjpeg();
#ifdef HAVE_TURBO_JPEG
tjhandle _transform,
_decompress;
tjscalingfactor* _scalingFactors;
tjtransform* _xform;
#endif
PixelFormat _pixelFormat;
uint8_t* _localData,
*_flipBuffer;
@@ -53,7 +45,6 @@ private:
_width,
_height,
_lineLength,
_subsamp,
_currentFrame,
_pixelDecimation;
unsigned long _size;
@@ -63,6 +54,14 @@ private:
_cropRight;
FlipMode _flipMode;
ImageResampler _imageResampler;
#ifdef HAVE_TURBO_JPEG
tjhandle _transform, _decompress;
tjscalingfactor* _scalingFactors;
tjtransform* _xform;
void processImageMjpeg();
#endif
};
template <typename TThread> class Thread : public QThread
@@ -83,36 +82,36 @@ public:
wait();
}
MFThread* thread() const { return qobject_cast<MFThread*>(_thread); }
EncoderThread* thread() const { return qobject_cast<EncoderThread*>(_thread); }
void setup(
PixelFormat pixelFormat, uint8_t* sharedData,
int size, int width, int height, int lineLength,
int subsamp, unsigned cropLeft, unsigned cropTop, unsigned cropBottom, unsigned cropRight,
unsigned cropLeft, unsigned cropTop, unsigned cropBottom, unsigned cropRight,
VideoMode videoMode, FlipMode flipMode, int pixelDecimation)
{
auto mfthread = qobject_cast<MFThread*>(_thread);
if (mfthread != nullptr)
mfthread->setup(pixelFormat, sharedData,
auto encThread = qobject_cast<EncoderThread*>(_thread);
if (encThread != nullptr)
encThread->setup(pixelFormat, sharedData,
size, width, height, lineLength,
subsamp, cropLeft, cropTop, cropBottom, cropRight,
cropLeft, cropTop, cropBottom, cropRight,
videoMode, flipMode, pixelDecimation);
}
bool isBusy()
{
auto mfthread = qobject_cast<MFThread*>(_thread);
if (mfthread != nullptr)
return mfthread->isBusy();
auto encThread = qobject_cast<EncoderThread*>(_thread);
if (encThread != nullptr)
return encThread->isBusy();
return true;
}
void process()
{
auto mfthread = qobject_cast<MFThread*>(_thread);
if (mfthread != nullptr)
mfthread->process();
auto encThread = qobject_cast<EncoderThread*>(_thread);
if (encThread != nullptr)
encThread->process();
}
protected:
@@ -123,24 +122,24 @@ protected:
}
};
class MFThreadManager : public QObject
class EncoderThreadManager : public QObject
{
Q_OBJECT
public:
explicit MFThreadManager(QObject *parent = nullptr)
explicit EncoderThreadManager(QObject *parent = nullptr)
: QObject(parent)
, _threadCount(qMax(QThread::idealThreadCount(), 1))
, _threads(nullptr)
{
_threads = new Thread<MFThread>*[_threadCount];
_threads = new Thread<EncoderThread>*[_threadCount];
for (int i = 0; i < _threadCount; i++)
{
_threads[i] = new Thread<MFThread>(new MFThread, this);
_threads[i]->setObjectName("MFThread " + i);
_threads[i] = new Thread<EncoderThread>(new EncoderThread, this);
_threads[i]->setObjectName("Encoder " + i);
}
}
~MFThreadManager()
~EncoderThreadManager()
{
if (_threads != nullptr)
{
@@ -159,7 +158,7 @@ public:
{
if (_threads != nullptr)
for (int i = 0; i < _threadCount; i++)
connect(_threads[i]->thread(), &MFThread::newFrame, this, &MFThreadManager::newFrame);
connect(_threads[i]->thread(), &EncoderThread::newFrame, this, &EncoderThreadManager::newFrame);
}
void stop()
@@ -170,7 +169,7 @@ public:
}
int _threadCount;
Thread<MFThread>** _threads;
Thread<EncoderThread>** _threads;
signals:
void newFrame(const Image<ColorRgb>& data);

View File

@@ -21,12 +21,7 @@
#include <hyperion/Grabber.h>
// decoder thread includes
#include <grabber/MFThread.h>
// TurboJPEG decoder
#ifdef HAVE_TURBO_JPEG
#include <turbojpeg.h>
#endif
#include <grabber/EncoderThread.h>
/// Forward class declaration
class SourceReaderCB;
@@ -99,7 +94,7 @@ private:
HRESULT _hr;
IMFSourceReader* _sourceReader;
SourceReaderCB* _sourceReaderCB;
MFThreadManager* _threadManager;
EncoderThreadManager* _threadManager;
PixelFormat _pixelFormat,
_pixelFormatConfig;
int _lineLength,
@@ -120,8 +115,4 @@ private:
_y_frac_min,
_x_frac_max,
_y_frac_max;
#ifdef HAVE_TURBO_JPEG
int _subsamp;
#endif
};

View File

@@ -17,29 +17,16 @@
#include <utils/VideoStandard.h>
#include <utils/Components.h>
#include <HyperionConfig.h> // Required to determine the cmake options
// decoder thread includes
#include <grabber/EncoderThread.h>
// Determine the cmake options
#include <HyperionConfig.h>
#if defined(ENABLE_CEC)
#include <cec/CECEvent.h>
#endif
// general JPEG decoder includes
#ifdef HAVE_JPEG_DECODER
#include <QImage>
#include <QColor>
#endif
// System JPEG decoder
#ifdef HAVE_JPEG
#include <jpeglib.h>
#include <csetjmp>
#endif
// TurboJPEG decoder
#ifdef HAVE_TURBO_JPEG
#include <turbojpeg.h>
#endif
///
/// Capture class for V4L2 devices
///
@@ -71,7 +58,7 @@ public:
~V4L2Grabber() override;
int grabFrame(Image<ColorRgb> &);
void setDevice(const QString& device);
void setDevice(const QString& devicePath, const QString& deviceName);
bool setInput(int input) override;
bool setWidthHeight(int width, int height) override;
void setEncoding(QString enc);
@@ -94,9 +81,10 @@ public:
QJsonArray discover(const QJsonObject& params);
public slots:
bool prepare() { return true; }
bool prepare();
bool start();
void stop();
void newThreadFrame(Image<ColorRgb> image);
#if defined(ENABLE_CEC)
void handleCecEvent(CECEvent event);
@@ -110,7 +98,6 @@ private slots:
int read_frame();
private:
void enumVideoCaptureDevices();
bool init();
void uninit();
bool open_device();
@@ -123,7 +110,6 @@ private:
void start_capturing();
void stop_capturing();
bool process_image(const void *p, int size);
void process_image(const uint8_t *p, int size);
int xioctl(int request, void *arg);
int xioctl(int fileDescriptor, int request, void *arg);
@@ -151,35 +137,9 @@ private:
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
#ifdef HAVE_TURBO_JPEG
tjhandle _decompress = nullptr;
int _subsamp;
#endif
private:
QString _currentDeviceName, _newDeviceName;
QString _currentDevicePath, _currentDeviceName;
EncoderThreadManager* _threadManager;
QMap<QString, V4L2Grabber::DeviceProperties> _deviceProperties;
io_method _ioMethod;
@@ -187,10 +147,11 @@ private:
std::vector<buffer> _buffers;
PixelFormat _pixelFormat, _pixelFormatConfig;
int _pixelDecimation;
int _lineLength;
int _frameByteSize;
QAtomicInt _currentFrame;
// signal detection
int _noSignalCounterThreshold;
ColorRgb _noSignalThresholdColor;
@@ -206,5 +167,6 @@ private:
bool _initialized, _reload;
protected:
void enumVideoCaptureDevices();
void enumFrameIntervals(QList<int> &framerates, int fileDescriptor, int pixelformat, int width, int height);
};