Skip to content
This repository was archived by the owner on May 6, 2021. It is now read-only.

Commit cf469ba

Browse files
committed
Create image callback using Qt signal
1 parent f3003eb commit cf469ba

File tree

9 files changed

+141
-106
lines changed

9 files changed

+141
-106
lines changed

include/grabber/V4L2Grabber.h

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,27 @@
44
#include <string>
55
#include <vector>
66

7+
// Qt includes
8+
#include <QObject>
9+
#include <QSocketNotifier>
10+
711
// util includes
812
#include <utils/Image.h>
913
#include <utils/ColorRgb.h>
14+
#include <utils/VideoMode.h>
1015

1116
/// Capture class for V4L2 devices
1217
///
1318
/// @see http://linuxtv.org/downloads/v4l-dvb-apis/capture-example.html
14-
class V4L2Grabber
19+
class V4L2Grabber : public QObject
1520
{
16-
public:
17-
typedef void (*ImageCallback)(void * arg, const Image<ColorRgb> & image);
21+
Q_OBJECT
1822

23+
public:
1924
enum VideoStandard {
2025
PAL, NTSC, NO_CHANGE
2126
};
2227

23-
enum Mode3D {
24-
MODE_NONE, MODE_3DSBS, MODE_3DTAB
25-
};
26-
2728
public:
2829
V4L2Grabber(
2930
const std::string & device,
@@ -36,21 +37,24 @@ class V4L2Grabber
3637
int verticalPixelDecimation);
3738
virtual ~V4L2Grabber();
3839

40+
public slots:
3941
void setCropping(int cropLeft,
4042
int cropRight,
4143
int cropTop,
4244
int cropBottom);
4345

44-
void set3D(Mode3D mode);
45-
46-
void setCallback(ImageCallback callback, void * arg);
46+
void set3D(VideoMode mode);
4747

4848
void start();
4949

50-
void capture(int frameCount = -1);
51-
5250
void stop();
5351

52+
signals:
53+
void newFrame(const Image<ColorRgb> & image);
54+
55+
private slots:
56+
int read_frame();
57+
5458
private:
5559
void open_device();
5660

@@ -70,8 +74,6 @@ class V4L2Grabber
7074

7175
void stop_capturing();
7276

73-
int read_frame();
74-
7577
bool process_image(const void *p, int size);
7678

7779
void process_image(const uint8_t *p);
@@ -111,10 +113,9 @@ class V4L2Grabber
111113
int _horizontalPixelDecimation;
112114
int _verticalPixelDecimation;
113115

114-
Mode3D _mode3D;
116+
VideoMode _mode3D;
115117

116118
int _currentFrame;
117119

118-
ImageCallback _callback;
119-
void * _callbackArg;
120+
QSocketNotifier * _streamNotifier;
120121
};

libsrc/grabber/v4l2/CMakeLists.txt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,27 @@
22
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber)
33
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/v4l2)
44

5-
SET(V4L2_HEADERS
5+
SET(V4L2_QT_HEADERS
66
${CURRENT_HEADER_DIR}/V4L2Grabber.h
77
)
88

9+
SET(V4L2_HEADERS
10+
)
11+
912
SET(V4L2_SOURCES
1013
${CURRENT_SOURCE_DIR}/V4L2Grabber.cpp
1114
)
1215

16+
QT4_WRAP_CPP(V4L2_HEADERS_MOC ${V4L2_QT_HEADERS})
17+
1318
add_library(v4l2-grabber
1419
${V4L2_HEADERS}
1520
${V4L2_SOURCES}
21+
${V4L2_QT_HEADERS}
22+
${V4L2_HEADERS_MOC}
1623
)
1724

1825
target_link_libraries(v4l2-grabber
19-
hyperion-utils)
26+
hyperion
27+
${QT_LIBRARIES}
28+
)

libsrc/grabber/v4l2/V4L2Grabber.cpp

Lines changed: 18 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,9 @@ V4L2Grabber::V4L2Grabber(
5959
_frameDecimation(std::max(1, frameDecimation)),
6060
_horizontalPixelDecimation(std::max(1, horizontalPixelDecimation)),
6161
_verticalPixelDecimation(std::max(1, verticalPixelDecimation)),
62-
_mode3D(MODE_NONE),
62+
_mode3D(VIDEO_2D),
6363
_currentFrame(0),
64-
_callback(nullptr),
65-
_callbackArg(nullptr)
64+
_streamNotifier(nullptr)
6665
{
6766
open_device();
6867
init_device(videoStandard, input);
@@ -82,66 +81,21 @@ void V4L2Grabber::setCropping(int cropLeft, int cropRight, int cropTop, int crop
8281
_cropBottom = cropBottom;
8382
}
8483

85-
void V4L2Grabber::set3D(Mode3D mode)
84+
void V4L2Grabber::set3D(VideoMode mode)
8685
{
8786
_mode3D = mode;
8887
}
8988

90-
void V4L2Grabber::setCallback(V4L2Grabber::ImageCallback callback, void *arg)
91-
{
92-
_callback = callback;
93-
_callbackArg = arg;
94-
}
95-
9689
void V4L2Grabber::start()
9790
{
91+
_streamNotifier->setEnabled(true);
9892
start_capturing();
9993
}
10094

101-
void V4L2Grabber::capture(int frameCount)
102-
{
103-
for (int count = 0; count < frameCount || frameCount < 0; ++count)
104-
{
105-
for (;;)
106-
{
107-
// the set of file descriptors for select
108-
fd_set fds;
109-
FD_ZERO(&fds);
110-
FD_SET(_fileDescriptor, &fds);
111-
112-
// timeout
113-
struct timeval tv;
114-
tv.tv_sec = 2;
115-
tv.tv_usec = 0;
116-
117-
// block until data is available
118-
int r = select(_fileDescriptor + 1, &fds, NULL, NULL, &tv);
119-
120-
if (-1 == r)
121-
{
122-
if (EINTR == errno)
123-
continue;
124-
throw_errno_exception("select");
125-
}
126-
127-
if (0 == r)
128-
{
129-
throw_exception("select timeout");
130-
}
131-
132-
if (read_frame())
133-
{
134-
break;
135-
}
136-
137-
/* EAGAIN - continue select loop. */
138-
}
139-
}
140-
}
141-
14295
void V4L2Grabber::stop()
14396
{
14497
stop_capturing();
98+
_streamNotifier->setEnabled(false);
14599
}
146100

147101
void V4L2Grabber::open_device()
@@ -170,6 +124,10 @@ void V4L2Grabber::open_device()
170124
oss << "Cannot open '" << _deviceName << "'";
171125
throw_errno_exception(oss.str());
172126
}
127+
128+
// create the notifier for when a new frame is available
129+
_streamNotifier = new QSocketNotifier(_fileDescriptor, QSocketNotifier::Read);
130+
connect(_streamNotifier, SIGNAL(activated(int)), this, SLOT(read_frame()));
173131
}
174132

175133
void V4L2Grabber::close_device()
@@ -178,6 +136,12 @@ void V4L2Grabber::close_device()
178136
throw_errno_exception("close");
179137

180138
_fileDescriptor = -1;
139+
140+
if (_streamNotifier != nullptr)
141+
{
142+
delete _streamNotifier;
143+
_streamNotifier = nullptr;
144+
}
181145
}
182146

183147
void V4L2Grabber::init_read(unsigned int buffer_size)
@@ -674,10 +638,10 @@ void V4L2Grabber::process_image(const uint8_t * data)
674638

675639
switch (_mode3D)
676640
{
677-
case MODE_3DSBS:
641+
case VIDEO_3DSBS:
678642
width = _width/2;
679643
break;
680-
case MODE_3DTAB:
644+
case VIDEO_3DTAB:
681645
height = _height/2;
682646
break;
683647
default:
@@ -717,10 +681,7 @@ void V4L2Grabber::process_image(const uint8_t * data)
717681
}
718682
}
719683

720-
if (_callback != nullptr)
721-
{
722-
(*_callback)(_callbackArg, image);
723-
}
684+
emit newFrame(image);
724685
}
725686

726687
int V4L2Grabber::xioctl(int request, void *arg)

src/hyperion-v4l2/CMakeLists.txt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,21 @@ include_directories(
1414
${QT_INCLUDES}
1515
)
1616

17-
set(Hyperion_V4L2_HEADERS
18-
ProtoConnection.h
17+
set(Hyperion_V4L2_QT_HEADERS
1918
ImageHandler.h
19+
ScreenshotHandler.h
20+
)
21+
22+
set(Hyperion_V4L2_HEADERS
2023
VideoStandardParameter.h
24+
ProtoConnection.h
2125
)
2226

2327
set(Hyperion_V4L2_SOURCES
2428
hyperion-v4l2.cpp
2529
ProtoConnection.cpp
2630
ImageHandler.cpp
31+
ScreenshotHandler.cpp
2732
)
2833

2934
set(Hyperion_V4L2_PROTOS
@@ -34,9 +39,13 @@ protobuf_generate_cpp(Hyperion_V4L2_PROTO_SRCS Hyperion_V4L2_PROTO_HDRS
3439
${Hyperion_V4L2_PROTOS}
3540
)
3641

42+
QT4_WRAP_CPP(Hyperion_V4L2_MOC_SOURCES ${Hyperion_V4L2_QT_HEADERS})
43+
3744
add_executable(hyperion-v4l2
3845
${Hyperion_V4L2_HEADERS}
3946
${Hyperion_V4L2_SOURCES}
47+
${Hyperion_V4L2_QT_HEADERS}
48+
${Hyperion_V4L2_MOC_SOURCES}
4049
${Hyperion_V4L2_PROTO_SRCS}
4150
${Hyperion_V4L2_PROTO_HDRS}
4251
)
@@ -48,5 +57,5 @@ target_link_libraries(hyperion-v4l2
4857
hyperion-utils
4958
${PROTOBUF_LIBRARIES}
5059
pthread
51-
${QT_LIBRARIES}
60+
${QT_LIBRARIES}
5261
)

src/hyperion-v4l2/ImageHandler.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ ImageHandler::ImageHandler(const std::string & address, int priority, double sig
1010
_connection.setSkipReply(skipProtoReply);
1111
}
1212

13+
ImageHandler::~ImageHandler()
14+
{
15+
}
16+
1317
void ImageHandler::receiveImage(const Image<ColorRgb> & image)
1418
{
1519
// check if we should do signal detection
@@ -32,10 +36,3 @@ void ImageHandler::receiveImage(const Image<ColorRgb> & image)
3236
}
3337
}
3438
}
35-
36-
void ImageHandler::imageCallback(void *arg, const Image<ColorRgb> &image)
37-
{
38-
ImageHandler * handler = static_cast<ImageHandler *>(arg);
39-
handler->receiveImage(image);
40-
}
41-

src/hyperion-v4l2/ImageHandler.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,30 @@
1+
// Qt includes
2+
#include <QObject>
3+
4+
// hyperion includes
5+
#include <utils/Image.h>
6+
#include <utils/ColorRgb.h>
7+
18
// blackborder includes
29
#include <blackborder/BlackBorderProcessor.h>
310

4-
// hyperion-v4l includes
11+
// hyperion v4l2 includes
512
#include "ProtoConnection.h"
613

714
/// This class handles callbacks from the V4L2 grabber
8-
class ImageHandler
15+
class ImageHandler : public QObject
916
{
17+
Q_OBJECT
18+
1019
public:
1120
ImageHandler(const std::string & address, int priority, double signalThreshold, bool skipProtoReply);
21+
virtual ~ImageHandler();
1222

23+
public slots:
1324
/// Handle a single image
1425
/// @param image The image to process
1526
void receiveImage(const Image<ColorRgb> & image);
1627

17-
/// static function used to direct callbacks to a ImageHandler object
18-
/// @param arg This should be an ImageHandler instance
19-
/// @param image The image to process
20-
static void imageCallback(void * arg, const Image<ColorRgb> & image);
21-
2228
private:
2329
/// Priority for calls to Hyperion
2430
const int _priority;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Qt includes
2+
#include <QImage>
3+
#include <QCoreApplication>
4+
5+
// hyperion-v4l2 includes
6+
#include "ScreenshotHandler.h"
7+
8+
ScreenshotHandler::ScreenshotHandler(const std::string & filename) :
9+
_filename(filename)
10+
{
11+
}
12+
13+
ScreenshotHandler::~ScreenshotHandler()
14+
{
15+
}
16+
17+
void ScreenshotHandler::receiveImage(const Image<ColorRgb> & image)
18+
{
19+
// store as PNG
20+
QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888);
21+
pngImage.save(_filename.c_str());
22+
23+
// Quit the application after the first image
24+
QCoreApplication::quit();
25+
}

0 commit comments

Comments
 (0)