v4l grabber wont crash hyperiond anymore (#168)

* v4l errors won't lead to crash hyperiond (exceptions are catched)
v4l auto device mode with better log messages
createV4l in hyperiond.cpp refactored, now v4l is always available as long as it is compiled in

* change back, code accidently altered

* fix compile of dispmanx grabber
This commit is contained in:
redPanther 2016-08-12 09:39:41 +02:00 committed by GitHub
parent f1cc82b8c7
commit 050ab11c8e
7 changed files with 82 additions and 57 deletions

View File

@ -62,8 +62,6 @@ private:
const int _updateInterval_ms;
/// The timeout of the led colors [ms]
const int _timeout_ms;
/// The priority of the led colors
const int _priority;
/// The image used for grabbing frames
Image<ColorRgba> _image;

View File

@ -57,6 +57,7 @@ public slots:
signals:
void newFrame(const Image<ColorRgb> & image);
void readError(const char* err);
private slots:
int read_frame();
@ -135,4 +136,5 @@ private:
Logger * _log;
bool _initialized;
bool _deviceAutoDiscoverEnabled;
};

View File

@ -44,6 +44,7 @@ public slots:
private slots:
void newFrame(const Image<ColorRgb> & image);
void readError(const char* err);
virtual void action();
void checkSources();

View File

@ -50,8 +50,9 @@ V4L2Grabber::V4L2Grabber(const std::string & device,
, _noSignalCounter(0)
, _streamNotifier(nullptr)
, _imageResampler()
, _log(Logger::getInstance("V4L2GRABBER"))
,_initialized(false)
, _log(Logger::getInstance("V4L2"))
, _initialized(false)
, _deviceAutoDiscoverEnabled(false)
{
_imageResampler.setHorizontalPixelDecimation(std::max(1, horizontalPixelDecimation));
_imageResampler.setVerticalPixelDecimation(std::max(1, verticalPixelDecimation));
@ -96,16 +97,20 @@ bool V4L2Grabber::init()
if ( _deviceName == "auto" )
{
_deviceAutoDiscoverEnabled = true;
_deviceName = "unknown";
Info( _log, "search for usable video devices" );
for (auto& dev: _v4lDevices)
{
_deviceName = dev.first;
if ( init() )
{
Info(_log, "found usable v4l2 device: %s (%s)",dev.first.c_str(), dev.second.c_str());
_deviceAutoDiscoverEnabled = false;
return _initialized;
}
}
Info( _log, "no usable device found" );
}
else if ( ! QString(_deviceName.c_str()).startsWith("/dev/") )
{
@ -121,7 +126,7 @@ bool V4L2Grabber::init()
}
else
{
Info(_log, "configured v4l device: %s", _deviceName.c_str());
Info(_log, "%s v4l device: %s", (_deviceAutoDiscoverEnabled? "test" : "configured"),_deviceName.c_str());
}
bool opened = false;
@ -139,7 +144,7 @@ bool V4L2Grabber::init()
uninit_device();
close_device();
}
Error( _log, "V4l2 init failed (%s)", e.what());
ErrorIf( !_deviceAutoDiscoverEnabled, _log, "V4l2 init failed (%s)", e.what());
}
}
@ -193,12 +198,19 @@ void V4L2Grabber::setSignalThreshold(double redSignalThreshold, double greenSign
bool V4L2Grabber::start()
{
if (init() && _streamNotifier != nullptr && !_streamNotifier->isEnabled())
try
{
_streamNotifier->setEnabled(true);
start_capturing();
Info(_log, "Started");
return true;
if (init() && _streamNotifier != nullptr && !_streamNotifier->isEnabled())
{
_streamNotifier->setEnabled(true);
start_capturing();
Info(_log, "Started");
return true;
}
}
catch(std::exception& e)
{
Error(_log, "start failed (%s)", e.what());
}
return false;
@ -507,7 +519,7 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
_height = fmt.fmt.pix.height;
// display the used width and height
Info(_log, "width=%d height=%d", _width, _height );
Debug(_log, "width=%d height=%d", _width, _height );
// check pixel format and frame size
@ -629,8 +641,7 @@ void V4L2Grabber::stop_capturing()
case IO_METHOD_MMAP:
case IO_METHOD_USERPTR:
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl(VIDIOC_STREAMOFF, &type))
throw_errno_exception("VIDIOC_STREAMOFF");
ErrorIf((xioctl(VIDIOC_STREAMOFF, &type) == -1), _log, "VIDIOC_STREAMOFF error code %d, %s", errno, strerror(errno));
break;
}
}
@ -639,6 +650,8 @@ int V4L2Grabber::read_frame()
{
bool rc = false;
try
{
struct v4l2_buffer buf;
switch (_ioMethod) {
@ -737,7 +750,13 @@ int V4L2Grabber::read_frame()
}
break;
}
}
catch (std::exception& e)
{
emit readError(e.what());
rc = false;
}
return rc ? 1 : 0;
}
@ -746,7 +765,6 @@ bool V4L2Grabber::process_image(const void *p, int size)
if (++_currentFrame >= _frameDecimation)
{
// We do want a new frame...
if (size != _frameByteSize)
{
Error(_log, "Frame too small: %d != %d", size, _frameByteSize);

View File

@ -37,10 +37,9 @@ V4L2Wrapper::V4L2Wrapper(const std::string &device,
qRegisterMetaType<std::vector<ColorRgb>>("std::vector<ColorRgb>");
// Handle the image in the captured thread using a direct connection
QObject::connect(
&_grabber, SIGNAL(newFrame(Image<ColorRgb>)),
this, SLOT(newFrame(Image<ColorRgb>)),
Qt::DirectConnection);
QObject::connect(&_grabber, SIGNAL(newFrame(Image<ColorRgb>)), this, SLOT(newFrame(Image<ColorRgb>)), Qt::DirectConnection);
QObject::connect(&_grabber, SIGNAL(readError(const char*)), this, SLOT(readError(const char*)), Qt::DirectConnection);
// send color data to Hyperion using a queued connection to handle the data over to the main event loop
// QObject::connect(
@ -92,6 +91,12 @@ void V4L2Wrapper::newFrame(const Image<ColorRgb> &image)
_hyperion->setColors(_priority, _ledColors, _timeout_ms);
}
void V4L2Wrapper::readError(const char* err)
{
Error(_log, "stop grabber, because reading device failed. (%s)", err);
stop();
}
void V4L2Wrapper::checkSources()
{
QList<int> activePriorities = _hyperion->getActivePriorities();

View File

@ -51,7 +51,14 @@ void GrabberWrapper::componentStateChanged(const hyperion::Components component,
_forward = _hyperion->getForwarder()->protoForwardingEnabled();
Info(_log, "grabber change state to %s", (enable ? "enabled" : "disabled") );
if ( enable == _timer.isActive() )
{
Info(_log, "grabber change state to %s", (_timer.isActive() ? "enabled" : "disabled") );
}
else
{
WarningIf( enable, _log, "enable grabber failed");
}
}
if (component == hyperion::COMP_BLACKBORDER && _processor->blackBorderDetectorEnabled() != enable)

View File

@ -535,42 +535,36 @@ void HyperionDaemon::createGrabberOsx(const QJsonObject & grabberConfig)
void HyperionDaemon::createGrabberV4L2()
{
// construct and start the v4l2 grabber if the configuration is present
if (_qconfig.contains("grabber-v4l2"))
{
const QJsonObject & grabberConfig = _qconfig["grabber-v4l2"].toObject();
#ifdef ENABLE_V4L2
_v4l2Grabber = new V4L2Wrapper(
grabberConfig["device"].toString("/dev/video0").toStdString(),
grabberConfig["input"].toInt(0),
parseVideoStandard(grabberConfig["standard"].toString("no-change").toStdString()),
parsePixelFormat(grabberConfig["pixelFormat"].toString("no-change").toStdString()),
grabberConfig["width"].toInt(-1),
grabberConfig["height"].toInt(-1),
grabberConfig["frameDecimation"].toInt(2),
grabberConfig["sizeDecimation"].toInt(8),
grabberConfig["redSignalThreshold"].toDouble(0.0),
grabberConfig["greenSignalThreshold"].toDouble(0.0),
grabberConfig["blueSignalThreshold"].toDouble(0.0),
grabberConfig["priority"].toInt(890));
_v4l2Grabber->set3D(parse3DMode(grabberConfig["mode"].toString("2D").toStdString()));
_v4l2Grabber->setCropping(
grabberConfig["cropLeft"].toInt(0),
grabberConfig["cropRight"].toInt(0),
grabberConfig["cropTop"].toInt(0),
grabberConfig["cropBottom"].toInt(0));
Debug(_log, "V4L2 grabber created");
bool v4lConfigured = _qconfig.contains("grabber-v4l2");
const QJsonObject & grabberConfig = _qconfig["grabber-v4l2"].toObject();
bool enableV4l = v4lConfigured && grabberConfig["enable"].toBool(true);
QObject::connect(_v4l2Grabber, SIGNAL(emitImage(int,
const Image<ColorRgb>&, const int)), _protoServer,
SLOT(sendImageToProtoSlaves(int,
const Image<ColorRgb>&, const int)));
if (grabberConfig["enable"].toBool(true) && _v4l2Grabber->start()) {
Info(_log, "V4L2 grabber started");
}
#else
if (grabberConfig["enable"].toBool(true)) {
Error(_log, "The v4l2 grabber can not be instantiated, because it has been left out from the build");
}
#ifdef ENABLE_V4L2
_v4l2Grabber = new V4L2Wrapper(
grabberConfig["device"].toString("auto").toStdString(),
grabberConfig["input"].toInt(0),
parseVideoStandard(grabberConfig["standard"].toString("no-change").toStdString()),
parsePixelFormat(grabberConfig["pixelFormat"].toString("no-change").toStdString()),
grabberConfig["width"].toInt(-1),
grabberConfig["height"].toInt(-1),
grabberConfig["frameDecimation"].toInt(2),
grabberConfig["sizeDecimation"].toInt(8),
grabberConfig["redSignalThreshold"].toDouble(0.0),
grabberConfig["greenSignalThreshold"].toDouble(0.0),
grabberConfig["blueSignalThreshold"].toDouble(0.0),
grabberConfig["priority"].toInt(890));
_v4l2Grabber->set3D(parse3DMode(grabberConfig["mode"].toString("2D").toStdString()));
_v4l2Grabber->setCropping(
grabberConfig["cropLeft"].toInt(0),
grabberConfig["cropRight"].toInt(0),
grabberConfig["cropTop"].toInt(0),
grabberConfig["cropBottom"].toInt(0));
Debug(_log, "V4L2 grabber created");
QObject::connect(_v4l2Grabber, SIGNAL(emitImage(int, const Image<ColorRgb>&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image<ColorRgb>&, const int)));
InfoIf( enableV4l && _v4l2Grabber->start(), _log, "V4L2 grabber started");
#endif
}
ErrorIf(enableV4l && _v4l2Grabber==nullptr, _log, "The v4l2 grabber can not be instantiated, because it has been left out from the build");
}