mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
Create image callback using Qt signal
Former-commit-id: cf469ba01ffd26d286e6fb8d9f081cf126042e50
This commit is contained in:
parent
f0c35071da
commit
69d6e47328
@ -4,26 +4,27 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Qt includes
|
||||
#include <QObject>
|
||||
#include <QSocketNotifier>
|
||||
|
||||
// util includes
|
||||
#include <utils/Image.h>
|
||||
#include <utils/ColorRgb.h>
|
||||
#include <utils/VideoMode.h>
|
||||
|
||||
/// Capture class for V4L2 devices
|
||||
///
|
||||
/// @see http://linuxtv.org/downloads/v4l-dvb-apis/capture-example.html
|
||||
class V4L2Grabber
|
||||
class V4L2Grabber : public QObject
|
||||
{
|
||||
public:
|
||||
typedef void (*ImageCallback)(void * arg, const Image<ColorRgb> & image);
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum VideoStandard {
|
||||
PAL, NTSC, NO_CHANGE
|
||||
};
|
||||
|
||||
enum Mode3D {
|
||||
MODE_NONE, MODE_3DSBS, MODE_3DTAB
|
||||
};
|
||||
|
||||
public:
|
||||
V4L2Grabber(
|
||||
const std::string & device,
|
||||
@ -36,21 +37,24 @@ public:
|
||||
int verticalPixelDecimation);
|
||||
virtual ~V4L2Grabber();
|
||||
|
||||
public slots:
|
||||
void setCropping(int cropLeft,
|
||||
int cropRight,
|
||||
int cropTop,
|
||||
int cropBottom);
|
||||
|
||||
void set3D(Mode3D mode);
|
||||
|
||||
void setCallback(ImageCallback callback, void * arg);
|
||||
void set3D(VideoMode mode);
|
||||
|
||||
void start();
|
||||
|
||||
void capture(int frameCount = -1);
|
||||
|
||||
void stop();
|
||||
|
||||
signals:
|
||||
void newFrame(const Image<ColorRgb> & image);
|
||||
|
||||
private slots:
|
||||
int read_frame();
|
||||
|
||||
private:
|
||||
void open_device();
|
||||
|
||||
@ -70,8 +74,6 @@ private:
|
||||
|
||||
void stop_capturing();
|
||||
|
||||
int read_frame();
|
||||
|
||||
bool process_image(const void *p, int size);
|
||||
|
||||
void process_image(const uint8_t *p);
|
||||
@ -111,10 +113,9 @@ private:
|
||||
int _horizontalPixelDecimation;
|
||||
int _verticalPixelDecimation;
|
||||
|
||||
Mode3D _mode3D;
|
||||
VideoMode _mode3D;
|
||||
|
||||
int _currentFrame;
|
||||
|
||||
ImageCallback _callback;
|
||||
void * _callbackArg;
|
||||
QSocketNotifier * _streamNotifier;
|
||||
};
|
||||
|
@ -2,18 +2,27 @@
|
||||
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber)
|
||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/v4l2)
|
||||
|
||||
SET(V4L2_HEADERS
|
||||
SET(V4L2_QT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/V4L2Grabber.h
|
||||
)
|
||||
|
||||
SET(V4L2_HEADERS
|
||||
)
|
||||
|
||||
SET(V4L2_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/V4L2Grabber.cpp
|
||||
)
|
||||
|
||||
QT4_WRAP_CPP(V4L2_HEADERS_MOC ${V4L2_QT_HEADERS})
|
||||
|
||||
add_library(v4l2-grabber
|
||||
${V4L2_HEADERS}
|
||||
${V4L2_SOURCES}
|
||||
${V4L2_QT_HEADERS}
|
||||
${V4L2_HEADERS_MOC}
|
||||
)
|
||||
|
||||
target_link_libraries(v4l2-grabber
|
||||
hyperion-utils)
|
||||
hyperion
|
||||
${QT_LIBRARIES}
|
||||
)
|
||||
|
@ -59,10 +59,9 @@ V4L2Grabber::V4L2Grabber(
|
||||
_frameDecimation(std::max(1, frameDecimation)),
|
||||
_horizontalPixelDecimation(std::max(1, horizontalPixelDecimation)),
|
||||
_verticalPixelDecimation(std::max(1, verticalPixelDecimation)),
|
||||
_mode3D(MODE_NONE),
|
||||
_mode3D(VIDEO_2D),
|
||||
_currentFrame(0),
|
||||
_callback(nullptr),
|
||||
_callbackArg(nullptr)
|
||||
_streamNotifier(nullptr)
|
||||
{
|
||||
open_device();
|
||||
init_device(videoStandard, input);
|
||||
@ -82,66 +81,21 @@ void V4L2Grabber::setCropping(int cropLeft, int cropRight, int cropTop, int crop
|
||||
_cropBottom = cropBottom;
|
||||
}
|
||||
|
||||
void V4L2Grabber::set3D(Mode3D mode)
|
||||
void V4L2Grabber::set3D(VideoMode mode)
|
||||
{
|
||||
_mode3D = mode;
|
||||
}
|
||||
|
||||
void V4L2Grabber::setCallback(V4L2Grabber::ImageCallback callback, void *arg)
|
||||
{
|
||||
_callback = callback;
|
||||
_callbackArg = arg;
|
||||
}
|
||||
|
||||
void V4L2Grabber::start()
|
||||
{
|
||||
_streamNotifier->setEnabled(true);
|
||||
start_capturing();
|
||||
}
|
||||
|
||||
void V4L2Grabber::capture(int frameCount)
|
||||
{
|
||||
for (int count = 0; count < frameCount || frameCount < 0; ++count)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
// the set of file descriptors for select
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(_fileDescriptor, &fds);
|
||||
|
||||
// timeout
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 2;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
// block until data is available
|
||||
int r = select(_fileDescriptor + 1, &fds, NULL, NULL, &tv);
|
||||
|
||||
if (-1 == r)
|
||||
{
|
||||
if (EINTR == errno)
|
||||
continue;
|
||||
throw_errno_exception("select");
|
||||
}
|
||||
|
||||
if (0 == r)
|
||||
{
|
||||
throw_exception("select timeout");
|
||||
}
|
||||
|
||||
if (read_frame())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* EAGAIN - continue select loop. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void V4L2Grabber::stop()
|
||||
{
|
||||
stop_capturing();
|
||||
_streamNotifier->setEnabled(false);
|
||||
}
|
||||
|
||||
void V4L2Grabber::open_device()
|
||||
@ -170,6 +124,10 @@ void V4L2Grabber::open_device()
|
||||
oss << "Cannot open '" << _deviceName << "'";
|
||||
throw_errno_exception(oss.str());
|
||||
}
|
||||
|
||||
// create the notifier for when a new frame is available
|
||||
_streamNotifier = new QSocketNotifier(_fileDescriptor, QSocketNotifier::Read);
|
||||
connect(_streamNotifier, SIGNAL(activated(int)), this, SLOT(read_frame()));
|
||||
}
|
||||
|
||||
void V4L2Grabber::close_device()
|
||||
@ -178,6 +136,12 @@ void V4L2Grabber::close_device()
|
||||
throw_errno_exception("close");
|
||||
|
||||
_fileDescriptor = -1;
|
||||
|
||||
if (_streamNotifier != nullptr)
|
||||
{
|
||||
delete _streamNotifier;
|
||||
_streamNotifier = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void V4L2Grabber::init_read(unsigned int buffer_size)
|
||||
@ -674,10 +638,10 @@ void V4L2Grabber::process_image(const uint8_t * data)
|
||||
|
||||
switch (_mode3D)
|
||||
{
|
||||
case MODE_3DSBS:
|
||||
case VIDEO_3DSBS:
|
||||
width = _width/2;
|
||||
break;
|
||||
case MODE_3DTAB:
|
||||
case VIDEO_3DTAB:
|
||||
height = _height/2;
|
||||
break;
|
||||
default:
|
||||
@ -717,10 +681,7 @@ void V4L2Grabber::process_image(const uint8_t * data)
|
||||
}
|
||||
}
|
||||
|
||||
if (_callback != nullptr)
|
||||
{
|
||||
(*_callback)(_callbackArg, image);
|
||||
}
|
||||
emit newFrame(image);
|
||||
}
|
||||
|
||||
int V4L2Grabber::xioctl(int request, void *arg)
|
||||
|
@ -14,16 +14,21 @@ include_directories(
|
||||
${QT_INCLUDES}
|
||||
)
|
||||
|
||||
set(Hyperion_V4L2_HEADERS
|
||||
ProtoConnection.h
|
||||
set(Hyperion_V4L2_QT_HEADERS
|
||||
ImageHandler.h
|
||||
ScreenshotHandler.h
|
||||
)
|
||||
|
||||
set(Hyperion_V4L2_HEADERS
|
||||
VideoStandardParameter.h
|
||||
ProtoConnection.h
|
||||
)
|
||||
|
||||
set(Hyperion_V4L2_SOURCES
|
||||
hyperion-v4l2.cpp
|
||||
ProtoConnection.cpp
|
||||
ImageHandler.cpp
|
||||
ScreenshotHandler.cpp
|
||||
)
|
||||
|
||||
set(Hyperion_V4L2_PROTOS
|
||||
@ -34,9 +39,13 @@ protobuf_generate_cpp(Hyperion_V4L2_PROTO_SRCS Hyperion_V4L2_PROTO_HDRS
|
||||
${Hyperion_V4L2_PROTOS}
|
||||
)
|
||||
|
||||
QT4_WRAP_CPP(Hyperion_V4L2_MOC_SOURCES ${Hyperion_V4L2_QT_HEADERS})
|
||||
|
||||
add_executable(hyperion-v4l2
|
||||
${Hyperion_V4L2_HEADERS}
|
||||
${Hyperion_V4L2_SOURCES}
|
||||
${Hyperion_V4L2_QT_HEADERS}
|
||||
${Hyperion_V4L2_MOC_SOURCES}
|
||||
${Hyperion_V4L2_PROTO_SRCS}
|
||||
${Hyperion_V4L2_PROTO_HDRS}
|
||||
)
|
||||
@ -48,5 +57,5 @@ target_link_libraries(hyperion-v4l2
|
||||
hyperion-utils
|
||||
${PROTOBUF_LIBRARIES}
|
||||
pthread
|
||||
${QT_LIBRARIES}
|
||||
${QT_LIBRARIES}
|
||||
)
|
||||
|
@ -10,6 +10,10 @@ ImageHandler::ImageHandler(const std::string & address, int priority, double sig
|
||||
_connection.setSkipReply(skipProtoReply);
|
||||
}
|
||||
|
||||
ImageHandler::~ImageHandler()
|
||||
{
|
||||
}
|
||||
|
||||
void ImageHandler::receiveImage(const Image<ColorRgb> & image)
|
||||
{
|
||||
// check if we should do signal detection
|
||||
@ -32,10 +36,3 @@ void ImageHandler::receiveImage(const Image<ColorRgb> & image)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ImageHandler::imageCallback(void *arg, const Image<ColorRgb> &image)
|
||||
{
|
||||
ImageHandler * handler = static_cast<ImageHandler *>(arg);
|
||||
handler->receiveImage(image);
|
||||
}
|
||||
|
||||
|
@ -1,24 +1,30 @@
|
||||
// Qt includes
|
||||
#include <QObject>
|
||||
|
||||
// hyperion includes
|
||||
#include <utils/Image.h>
|
||||
#include <utils/ColorRgb.h>
|
||||
|
||||
// blackborder includes
|
||||
#include <blackborder/BlackBorderProcessor.h>
|
||||
|
||||
// hyperion-v4l includes
|
||||
// hyperion v4l2 includes
|
||||
#include "ProtoConnection.h"
|
||||
|
||||
/// This class handles callbacks from the V4L2 grabber
|
||||
class ImageHandler
|
||||
class ImageHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ImageHandler(const std::string & address, int priority, double signalThreshold, bool skipProtoReply);
|
||||
virtual ~ImageHandler();
|
||||
|
||||
public slots:
|
||||
/// Handle a single image
|
||||
/// @param image The image to process
|
||||
void receiveImage(const Image<ColorRgb> & image);
|
||||
|
||||
/// static function used to direct callbacks to a ImageHandler object
|
||||
/// @param arg This should be an ImageHandler instance
|
||||
/// @param image The image to process
|
||||
static void imageCallback(void * arg, const Image<ColorRgb> & image);
|
||||
|
||||
private:
|
||||
/// Priority for calls to Hyperion
|
||||
const int _priority;
|
||||
|
25
src/hyperion-v4l2/ScreenshotHandler.cpp
Normal file
25
src/hyperion-v4l2/ScreenshotHandler.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
// Qt includes
|
||||
#include <QImage>
|
||||
#include <QCoreApplication>
|
||||
|
||||
// hyperion-v4l2 includes
|
||||
#include "ScreenshotHandler.h"
|
||||
|
||||
ScreenshotHandler::ScreenshotHandler(const std::string & filename) :
|
||||
_filename(filename)
|
||||
{
|
||||
}
|
||||
|
||||
ScreenshotHandler::~ScreenshotHandler()
|
||||
{
|
||||
}
|
||||
|
||||
void ScreenshotHandler::receiveImage(const Image<ColorRgb> & image)
|
||||
{
|
||||
// store as PNG
|
||||
QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888);
|
||||
pngImage.save(_filename.c_str());
|
||||
|
||||
// Quit the application after the first image
|
||||
QCoreApplication::quit();
|
||||
}
|
24
src/hyperion-v4l2/ScreenshotHandler.h
Normal file
24
src/hyperion-v4l2/ScreenshotHandler.h
Normal file
@ -0,0 +1,24 @@
|
||||
// Qt includes
|
||||
#include <QObject>
|
||||
|
||||
// hyperionincludes
|
||||
#include <utils/Image.h>
|
||||
#include <utils/ColorRgb.h>
|
||||
|
||||
/// This class handles callbacks from the V4L2 grabber
|
||||
class ScreenshotHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ScreenshotHandler(const std::string & filename);
|
||||
virtual ~ScreenshotHandler();
|
||||
|
||||
public slots:
|
||||
/// Handle a single image
|
||||
/// @param image The image to process
|
||||
void receiveImage(const Image<ColorRgb> & image);
|
||||
|
||||
private:
|
||||
const std::string _filename;
|
||||
};
|
@ -4,7 +4,7 @@
|
||||
#include <clocale>
|
||||
|
||||
// QT includes
|
||||
#include <QImage>
|
||||
#include <QCoreApplication>
|
||||
|
||||
// getoptPlusPLus includes
|
||||
#include <getoptPlusPlus/getoptpp.h>
|
||||
@ -19,6 +19,7 @@
|
||||
#include "ProtoConnection.h"
|
||||
#include "VideoStandardParameter.h"
|
||||
#include "ImageHandler.h"
|
||||
#include "ScreenshotHandler.h"
|
||||
|
||||
using namespace vlofgren;
|
||||
|
||||
@ -32,8 +33,11 @@ void saveScreenshot(void *, const Image<ColorRgb> & image)
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
// force the locale
|
||||
setlocale(LC_ALL, "C");
|
||||
QLocale::setDefault(QLocale::c());
|
||||
|
||||
try
|
||||
{
|
||||
@ -113,31 +117,30 @@ int main(int argc, char** argv)
|
||||
// set 3D mode if applicable
|
||||
if (arg3DSBS.isSet())
|
||||
{
|
||||
grabber.set3D(V4L2Grabber::MODE_3DSBS);
|
||||
grabber.set3D(VIDEO_3DSBS);
|
||||
}
|
||||
else if (arg3DTAB.isSet())
|
||||
{
|
||||
grabber.set3D(V4L2Grabber::MODE_3DTAB);
|
||||
grabber.set3D(VIDEO_3DTAB);
|
||||
}
|
||||
|
||||
// start the grabber
|
||||
grabber.start();
|
||||
|
||||
// run the grabber
|
||||
if (argScreenshot.isSet())
|
||||
{
|
||||
grabber.setCallback(&saveScreenshot, nullptr);
|
||||
grabber.capture(1);
|
||||
ScreenshotHandler handler("screenshot.png");
|
||||
QObject::connect(&grabber, SIGNAL(newFrame(Image<ColorRgb>)), &handler, SLOT(receiveImage(Image<ColorRgb>)));
|
||||
grabber.start();
|
||||
QCoreApplication::exec();
|
||||
grabber.stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
ImageHandler handler(argAddress.getValue(), argPriority.getValue(), argSignalThreshold.getValue(), argSkipReply.isSet());
|
||||
grabber.setCallback(&ImageHandler::imageCallback, &handler);
|
||||
grabber.capture();
|
||||
QObject::connect(&grabber, SIGNAL(newFrame(Image<ColorRgb>)), &handler, SLOT(receiveImage(Image<ColorRgb>)));
|
||||
grabber.start();
|
||||
QCoreApplication::exec();
|
||||
grabber.stop();
|
||||
}
|
||||
|
||||
// stop the grabber
|
||||
grabber.stop();
|
||||
}
|
||||
catch (const std::runtime_error & e)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user