mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
Moved test/v4l2_to_png to src/hyperion-v4l2; Added json backend temporarily
Former-commit-id: 8c4e0ef7add8016c522d0b4c6f4df8886b905e36
This commit is contained in:
parent
1981f6e307
commit
6723c7bf2b
@ -120,7 +120,7 @@ void OptionsParser::usage() const {
|
||||
for(i = parameters.parameters.begin();
|
||||
i != parameters.parameters.end(); i++)
|
||||
{
|
||||
cerr.width(30);
|
||||
cerr.width(31);
|
||||
cerr << std::left << " " + (*i)->usageLine();
|
||||
|
||||
cerr.width(40);
|
||||
|
@ -3,9 +3,6 @@
|
||||
set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/protoserver)
|
||||
set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/protoserver)
|
||||
|
||||
# add protocol buffers
|
||||
find_package(Protobuf REQUIRED)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${PROTOBUF_INCLUDE_DIRS})
|
||||
|
@ -1,2 +1,5 @@
|
||||
add_subdirectory(hyperiond)
|
||||
add_subdirectory(hyperion-remote)
|
||||
if (ENABLE_V4L2)
|
||||
add_subdirectory(hyperion-v4l2)
|
||||
endif (ENABLE_V4L2)
|
||||
|
54
src/hyperion-v4l2/CMakeLists.txt
Normal file
54
src/hyperion-v4l2/CMakeLists.txt
Normal file
@ -0,0 +1,54 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(hyperion-v4l2)
|
||||
|
||||
# add protocol buffers
|
||||
find_package(Protobuf REQUIRED)
|
||||
|
||||
# find Qt4
|
||||
find_package(Qt4 REQUIRED QtCore QtGui QtNetwork)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${PROTOBUF_INCLUDE_DIRS}
|
||||
${QT_INCLUDES}
|
||||
)
|
||||
|
||||
set(Hyperion_V4L2_HEADERS
|
||||
V4L2Grabber.h
|
||||
ProtoConnection.h
|
||||
)
|
||||
|
||||
set(Hyperion_V4L2_SOURCES
|
||||
hyperion-v4l2.cpp
|
||||
V4L2Grabber.cpp
|
||||
ProtoConnection.cpp
|
||||
)
|
||||
|
||||
set(Hyperion_V4L2_PROTOS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../libsrc/protoserver/message.proto
|
||||
)
|
||||
|
||||
protobuf_generate_cpp(Hyperion_V4L2_PROTO_SRCS Hyperion_V4L2_PROTO_HDRS
|
||||
${Hyperion_V4L2_PROTOS}
|
||||
)
|
||||
|
||||
add_executable(hyperion-v4l2
|
||||
${Hyperion_V4L2_HEADERS}
|
||||
${Hyperion_V4L2_SOURCES}
|
||||
${Hyperion_V4L2_PROTO_SRCS}
|
||||
${Hyperion_V4L2_PROTO_HDRS}
|
||||
)
|
||||
|
||||
target_link_libraries(hyperion-v4l2
|
||||
getoptPlusPlus
|
||||
jsoncpp
|
||||
hyperion-utils
|
||||
${PROTOBUF_LIBRARIES}
|
||||
pthread
|
||||
)
|
||||
|
||||
qt4_use_modules(hyperion-v4l2
|
||||
Core
|
||||
Gui
|
||||
Network)
|
181
src/hyperion-v4l2/ProtoConnection.cpp
Normal file
181
src/hyperion-v4l2/ProtoConnection.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
// stl includes
|
||||
#include <stdexcept>
|
||||
|
||||
// Qt includes
|
||||
#include <QRgb>
|
||||
|
||||
// hyperion-v4l2 includes
|
||||
#include "ProtoConnection.h"
|
||||
|
||||
ProtoConnection::ProtoConnection(const std::string & a) :
|
||||
_socket()
|
||||
{
|
||||
QString address(a.c_str());
|
||||
QStringList parts = address.split(":");
|
||||
if (parts.size() != 2)
|
||||
{
|
||||
throw std::runtime_error(QString("Wrong address: unable to parse address (%1)").arg(address).toStdString());
|
||||
}
|
||||
|
||||
bool ok;
|
||||
uint16_t port = parts[1].toUShort(&ok);
|
||||
if (!ok)
|
||||
{
|
||||
throw std::runtime_error(QString("Wrong address: Unable to parse the port number (%1)").arg(parts[1]).toStdString());
|
||||
}
|
||||
|
||||
_socket.connectToHost(parts[0], port);
|
||||
if (!_socket.waitForConnected())
|
||||
{
|
||||
throw std::runtime_error("Unable to connect to host");
|
||||
}
|
||||
|
||||
std::cout << "Connected to " << a << std::endl;
|
||||
}
|
||||
|
||||
ProtoConnection::~ProtoConnection()
|
||||
{
|
||||
_socket.close();
|
||||
}
|
||||
|
||||
void ProtoConnection::setColor(std::vector<QColor> colors, int priority, int duration)
|
||||
{
|
||||
// create command
|
||||
Json::Value command;
|
||||
command["command"] = "color";
|
||||
command["priority"] = priority;
|
||||
Json::Value & rgbValue = command["color"];
|
||||
for (const QColor & color : colors)
|
||||
{
|
||||
rgbValue.append(color.red());
|
||||
rgbValue.append(color.green());
|
||||
rgbValue.append(color.blue());
|
||||
}
|
||||
if (duration > 0)
|
||||
{
|
||||
command["duration"] = duration;
|
||||
}
|
||||
|
||||
// send command message
|
||||
Json::Value reply = sendMessage(command);
|
||||
|
||||
// parse reply message
|
||||
parseReply(reply);
|
||||
}
|
||||
|
||||
void ProtoConnection::setImage(const Image<ColorRgb> &image, int priority, int duration)
|
||||
{
|
||||
// ensure the image has RGB888 format
|
||||
QByteArray binaryImage = QByteArray::fromRawData(reinterpret_cast<const char *>(image.memptr()), image.width() * image.height() * 3);
|
||||
const QByteArray base64Image = binaryImage.toBase64();
|
||||
|
||||
// create command
|
||||
Json::Value command;
|
||||
command["command"] = "image";
|
||||
command["priority"] = priority;
|
||||
command["imagewidth"] = image.width();
|
||||
command["imageheight"] = image.height();
|
||||
command["imagedata"] = std::string(base64Image.data(), base64Image.size());
|
||||
if (duration > 0)
|
||||
{
|
||||
command["duration"] = duration;
|
||||
}
|
||||
|
||||
// send command message
|
||||
Json::Value reply = sendMessage(command);
|
||||
|
||||
// parse reply message
|
||||
parseReply(reply);
|
||||
}
|
||||
|
||||
void ProtoConnection::clear(int priority)
|
||||
{
|
||||
std::cout << "Clear priority channel " << priority << std::endl;
|
||||
|
||||
// create command
|
||||
Json::Value command;
|
||||
command["command"] = "clear";
|
||||
command["priority"] = priority;
|
||||
|
||||
// send command message
|
||||
Json::Value reply = sendMessage(command);
|
||||
|
||||
// parse reply message
|
||||
parseReply(reply);
|
||||
}
|
||||
|
||||
void ProtoConnection::clearAll()
|
||||
{
|
||||
std::cout << "Clear all priority channels" << std::endl;
|
||||
|
||||
// create command
|
||||
Json::Value command;
|
||||
command["command"] = "clearall";
|
||||
|
||||
// send command message
|
||||
Json::Value reply = sendMessage(command);
|
||||
|
||||
// parse reply message
|
||||
parseReply(reply);
|
||||
}
|
||||
|
||||
Json::Value ProtoConnection::sendMessage(const Json::Value & message)
|
||||
{
|
||||
// serialize message (FastWriter already appends a newline)
|
||||
std::string serializedMessage = Json::FastWriter().write(message);
|
||||
|
||||
// write message
|
||||
_socket.write(serializedMessage.c_str());
|
||||
if (!_socket.waitForBytesWritten())
|
||||
{
|
||||
throw std::runtime_error("Error while writing data to host");
|
||||
}
|
||||
|
||||
// read reply data
|
||||
QByteArray serializedReply;
|
||||
while (!serializedReply.contains('\n'))
|
||||
{
|
||||
// receive reply
|
||||
if (!_socket.waitForReadyRead())
|
||||
{
|
||||
throw std::runtime_error("Error while reading data from host");
|
||||
}
|
||||
|
||||
serializedReply += _socket.readAll();
|
||||
}
|
||||
int bytes = serializedReply.indexOf('\n') + 1; // Find the end of message
|
||||
|
||||
// parse reply data
|
||||
Json::Reader jsonReader;
|
||||
Json::Value reply;
|
||||
if (!jsonReader.parse(serializedReply.constData(), serializedReply.constData() + bytes, reply))
|
||||
{
|
||||
throw std::runtime_error("Error while parsing reply: invalid json");
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
bool ProtoConnection::parseReply(const Json::Value &reply)
|
||||
{
|
||||
bool success = false;
|
||||
std::string reason = "No error info";
|
||||
|
||||
try
|
||||
{
|
||||
success = reply.get("success", false).asBool();
|
||||
if (!success)
|
||||
reason = reply.get("error", reason).asString();
|
||||
}
|
||||
catch (const std::runtime_error &)
|
||||
{
|
||||
// Some json parsing error: ignore and set parsing error
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
throw std::runtime_error("Error: " + reason);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
89
src/hyperion-v4l2/ProtoConnection.h
Normal file
89
src/hyperion-v4l2/ProtoConnection.h
Normal file
@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
|
||||
// stl includes
|
||||
#include <string>
|
||||
|
||||
// Qt includes
|
||||
#include <QColor>
|
||||
#include <QImage>
|
||||
#include <QTcpSocket>
|
||||
#include <QMap>
|
||||
|
||||
// hyperion util
|
||||
#include <utils/Image.h>
|
||||
#include <utils/ColorRgb.h>
|
||||
|
||||
// jsoncpp includes
|
||||
#include <json/json.h>
|
||||
|
||||
///
|
||||
/// Connection class to setup an connection to the hyperion server and execute commands
|
||||
///
|
||||
class ProtoConnection
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
/// @param address The address of the Hyperion server (for example "192.168.0.32:19444)
|
||||
///
|
||||
ProtoConnection(const std::string & address);
|
||||
|
||||
///
|
||||
/// Destructor
|
||||
///
|
||||
~ProtoConnection();
|
||||
|
||||
///
|
||||
/// Set all leds to the specified color
|
||||
///
|
||||
/// @param color The color
|
||||
/// @param priority The priority
|
||||
/// @param duration The duration in milliseconds
|
||||
///
|
||||
void setColor(std::vector<QColor> color, int priority, int duration);
|
||||
|
||||
///
|
||||
/// Set the leds according to the given image (assume the image is stretched to the display size)
|
||||
///
|
||||
/// @param image The image
|
||||
/// @param priority The priority
|
||||
/// @param duration The duration in milliseconds
|
||||
///
|
||||
void setImage(const Image<ColorRgb> & image, int priority, int duration);
|
||||
|
||||
///
|
||||
/// Clear the given priority channel
|
||||
///
|
||||
/// @param priority The priority
|
||||
///
|
||||
void clear(int priority);
|
||||
|
||||
///
|
||||
/// Clear all priority channels
|
||||
///
|
||||
void clearAll();
|
||||
|
||||
private:
|
||||
///
|
||||
/// Send a json command message and receive its reply
|
||||
///
|
||||
/// @param message The message to send
|
||||
///
|
||||
/// @return The returned reply
|
||||
///
|
||||
Json::Value sendMessage(const Json::Value & message);
|
||||
|
||||
///
|
||||
/// Parse a reply message
|
||||
///
|
||||
/// @param reply The received reply
|
||||
///
|
||||
/// @return true if the reply indicates success
|
||||
///
|
||||
bool parseReply(const Json::Value & reply);
|
||||
|
||||
private:
|
||||
/// The TCP-Socket with the connection to the server
|
||||
QTcpSocket _socket;
|
||||
};
|
@ -12,9 +12,6 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include <QImage>
|
||||
#include <QRgb>
|
||||
|
||||
#include "V4L2Grabber.h"
|
||||
|
||||
#define CLEAR(x) memset(&(x), 0, sizeof(x))
|
||||
@ -37,18 +34,20 @@ static void yuv2rgb(uint8_t y, uint8_t u, uint8_t v, uint8_t & r, uint8_t & g, u
|
||||
}
|
||||
|
||||
|
||||
V4L2Grabber::V4L2Grabber(const std::string &device, int input, VideoStandard videoStandard, int cropHorizontal, int cropVertical, int frameDecimation, int pixelDecimation) :
|
||||
V4L2Grabber::V4L2Grabber(const std::string &device, int input, VideoStandard videoStandard, int width, int height, int cropHorizontal, int cropVertical, int frameDecimation, int pixelDecimation) :
|
||||
_deviceName(device),
|
||||
_ioMethod(IO_METHOD_MMAP),
|
||||
_fileDescriptor(-1),
|
||||
_buffers(),
|
||||
_width(0),
|
||||
_height(0),
|
||||
_width(width),
|
||||
_height(height),
|
||||
_cropWidth(cropHorizontal),
|
||||
_cropHeight(cropVertical),
|
||||
_frameDecimation(std::max(1, frameDecimation)),
|
||||
_pixelDecimation(std::max(1, pixelDecimation)),
|
||||
_currentFrame(0)
|
||||
_currentFrame(0),
|
||||
_callback(nullptr),
|
||||
_callbackArg(nullptr)
|
||||
{
|
||||
open_device();
|
||||
init_device(videoStandard, input);
|
||||
@ -60,6 +59,12 @@ V4L2Grabber::~V4L2Grabber()
|
||||
close_device();
|
||||
}
|
||||
|
||||
void V4L2Grabber::setCallback(V4L2Grabber::ImageCallback callback, void *arg)
|
||||
{
|
||||
_callback = callback;
|
||||
_callbackArg = arg;
|
||||
}
|
||||
|
||||
void V4L2Grabber::start()
|
||||
{
|
||||
start_capturing();
|
||||
@ -343,6 +348,7 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// get the current settings
|
||||
struct v4l2_format fmt;
|
||||
CLEAR(fmt);
|
||||
@ -358,6 +364,32 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (_width > 0 || _height > 0)
|
||||
{
|
||||
if (_width > 0)
|
||||
{
|
||||
fmt.fmt.pix.width = _width;
|
||||
}
|
||||
|
||||
if (fmt.fmt.pix.height > 0)
|
||||
{
|
||||
fmt.fmt.pix.height = _height;
|
||||
}
|
||||
|
||||
// set the settings
|
||||
if (-1 == xioctl(VIDIOC_S_FMT, &fmt))
|
||||
{
|
||||
errno_exit("VIDIOC_S_FMT");
|
||||
}
|
||||
|
||||
// get the format settings again
|
||||
// (the size may not have been accepted without an error)
|
||||
if (-1 == xioctl(VIDIOC_G_FMT, &fmt))
|
||||
{
|
||||
errno_exit("VIDIOC_G_FMT");
|
||||
}
|
||||
}
|
||||
|
||||
// store width & height
|
||||
_width = fmt.fmt.pix.width;
|
||||
_height = fmt.fmt.pix.height;
|
||||
@ -468,6 +500,8 @@ void V4L2Grabber::stop_capturing()
|
||||
|
||||
int V4L2Grabber::read_frame()
|
||||
{
|
||||
bool rc = false;
|
||||
|
||||
struct v4l2_buffer buf;
|
||||
|
||||
switch (_ioMethod) {
|
||||
@ -490,7 +524,7 @@ int V4L2Grabber::read_frame()
|
||||
}
|
||||
}
|
||||
|
||||
process_image(_buffers[0].start, size);
|
||||
rc = process_image(_buffers[0].start, size);
|
||||
break;
|
||||
|
||||
case IO_METHOD_MMAP:
|
||||
@ -518,7 +552,7 @@ int V4L2Grabber::read_frame()
|
||||
|
||||
assert(buf.index < _buffers.size());
|
||||
|
||||
process_image(_buffers[buf.index].start, buf.bytesused);
|
||||
rc = process_image(_buffers[buf.index].start, buf.bytesused);
|
||||
|
||||
if (-1 == xioctl(VIDIOC_QBUF, &buf))
|
||||
{
|
||||
@ -558,7 +592,7 @@ int V4L2Grabber::read_frame()
|
||||
}
|
||||
}
|
||||
|
||||
process_image((void *)buf.m.userptr, buf.bytesused);
|
||||
rc = process_image((void *)buf.m.userptr, buf.bytesused);
|
||||
|
||||
if (-1 == xioctl(VIDIOC_QBUF, &buf))
|
||||
{
|
||||
@ -567,10 +601,10 @@ int V4L2Grabber::read_frame()
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return rc ? 1 : 0;
|
||||
}
|
||||
|
||||
void V4L2Grabber::process_image(const void *p, int size)
|
||||
bool V4L2Grabber::process_image(const void *p, int size)
|
||||
{
|
||||
if (++_currentFrame >= _frameDecimation)
|
||||
{
|
||||
@ -584,14 +618,15 @@ void V4L2Grabber::process_image(const void *p, int size)
|
||||
{
|
||||
process_image(reinterpret_cast<const uint8_t *>(p));
|
||||
_currentFrame = 0; // restart counting
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void V4L2Grabber::process_image(const uint8_t * data)
|
||||
{
|
||||
std::cout << "process image" << std::endl;
|
||||
|
||||
int width = (_width - 2 * _cropWidth + _pixelDecimation/2) / _pixelDecimation;
|
||||
int height = (_height - 2 * _cropHeight + _pixelDecimation/2) / _pixelDecimation;
|
||||
|
||||
@ -611,9 +646,10 @@ void V4L2Grabber::process_image(const uint8_t * data)
|
||||
}
|
||||
}
|
||||
|
||||
// store as PNG
|
||||
QImage pngImage((const uint8_t *) image.memptr(), width, height, 3*width, QImage::Format_RGB888);
|
||||
pngImage.save("screenshot.png");
|
||||
if (_callback != nullptr)
|
||||
{
|
||||
(*_callback)(_callbackArg, image);
|
||||
}
|
||||
}
|
||||
|
||||
int V4L2Grabber::xioctl(int request, void *arg)
|
@ -14,14 +14,18 @@
|
||||
class V4L2Grabber
|
||||
{
|
||||
public:
|
||||
typedef void (*ImageCallback)(void * arg, const Image<ColorRgb> & image);
|
||||
|
||||
enum VideoStandard {
|
||||
PAL, NTSC, NO_CHANGE
|
||||
};
|
||||
|
||||
public:
|
||||
V4L2Grabber(const std::string & device, int input, VideoStandard videoStandard, int cropHorizontal, int cropVertical, int frameDecimation, int pixelDecimation);
|
||||
V4L2Grabber(const std::string & device, int input, VideoStandard videoStandard, int width, int height, int cropHorizontal, int cropVertical, int frameDecimation, int pixelDecimation);
|
||||
virtual ~V4L2Grabber();
|
||||
|
||||
void setCallback(ImageCallback callback, void * arg);
|
||||
|
||||
void start();
|
||||
|
||||
void capture(int frameCount = -1);
|
||||
@ -49,7 +53,7 @@ private:
|
||||
|
||||
int read_frame();
|
||||
|
||||
void process_image(const void *p, int size);
|
||||
bool process_image(const void *p, int size);
|
||||
|
||||
void process_image(const uint8_t *p);
|
||||
|
||||
@ -83,4 +87,7 @@ private:
|
||||
const int _pixelDecimation;
|
||||
|
||||
int _currentFrame;
|
||||
|
||||
ImageCallback _callback;
|
||||
void * _callbackArg;
|
||||
};
|
143
src/hyperion-v4l2/hyperion-v4l2.cpp
Normal file
143
src/hyperion-v4l2/hyperion-v4l2.cpp
Normal file
@ -0,0 +1,143 @@
|
||||
|
||||
// STL includes
|
||||
#include <csignal>
|
||||
#include <iomanip>
|
||||
|
||||
// QT includes
|
||||
#include <QImage>
|
||||
|
||||
// getoptPlusPLus includes
|
||||
#include <getoptPlusPlus/getoptpp.h>
|
||||
|
||||
#include "V4L2Grabber.h"
|
||||
#include "ProtoConnection.h"
|
||||
|
||||
using namespace vlofgren;
|
||||
|
||||
/// Data parameter for the video standard
|
||||
typedef vlofgren::PODParameter<V4L2Grabber::VideoStandard> VideoStandardParameter;
|
||||
|
||||
namespace vlofgren {
|
||||
/// Translates a string (as passed on the commandline) to a color standard
|
||||
///
|
||||
/// @param[in] s The string (as passed on the commandline)
|
||||
/// @return The color standard
|
||||
/// @throws Parameter::ParameterRejected If the string did not result in a video standard
|
||||
template<>
|
||||
V4L2Grabber::VideoStandard VideoStandardParameter::validate(const std::string& s) throw (Parameter::ParameterRejected)
|
||||
{
|
||||
QString input = QString::fromStdString(s).toLower();
|
||||
|
||||
if (input == "pal")
|
||||
{
|
||||
return V4L2Grabber::PAL;
|
||||
}
|
||||
else if (input == "ntsc")
|
||||
{
|
||||
return V4L2Grabber::NTSC;
|
||||
}
|
||||
else if (input == "no-change")
|
||||
{
|
||||
return V4L2Grabber::NO_CHANGE;
|
||||
}
|
||||
|
||||
throw Parameter::ParameterRejected("Invalid value for video standard. Valid values are: PAL, NTSC, and NO-CHANGE");
|
||||
return V4L2Grabber::NO_CHANGE;
|
||||
}
|
||||
}
|
||||
|
||||
// save the image as screenshot
|
||||
void saveScreenshot(void *, 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("screenshot.png");
|
||||
}
|
||||
|
||||
// send the image to Hyperion
|
||||
void sendImage(void * arg, const Image<ColorRgb> & image)
|
||||
{
|
||||
ProtoConnection * connection = static_cast<ProtoConnection *>(arg);
|
||||
connection->setImage(image, 50, 200);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
try
|
||||
{
|
||||
// create the option parser and initialize all parameters
|
||||
OptionsParser optionParser("Simple application to send a command to hyperion using the Json interface");
|
||||
ParameterSet & parameters = optionParser.getParameters();
|
||||
|
||||
StringParameter & argDevice = parameters.add<StringParameter> ('d', "device", "The device to use [default=/dev/video0]");
|
||||
VideoStandardParameter & argVideoStandard = parameters.add<VideoStandardParameter>('v', "video-standard", "The used video standard. Valid values are PAL. NYSC, or NO-CHANGE [default=PAL]");
|
||||
IntParameter & argInput = parameters.add<IntParameter> (0x0, "input", "Input channel (optional)");
|
||||
IntParameter & argWidth = parameters.add<IntParameter> (0x0, "width", "Try to set the width of the video input (optional)");
|
||||
IntParameter & argHeight = parameters.add<IntParameter> (0x0, "height", "Try to set the height of the video input (optional)");
|
||||
IntParameter & argCropWidth = parameters.add<IntParameter> (0x0, "crop-width", "Number of pixels to crop from the left and right sides in the picture before decimation [default=0]");
|
||||
IntParameter & argCropHeight = parameters.add<IntParameter> (0x0, "crop-height", "Number of pixels to crop from the top and the bottom in the picture before decimation [default=0]");
|
||||
IntParameter & argSizeDecimation = parameters.add<IntParameter> ('s', "size-decimator", "Decimation factor for the output size [default=1]");
|
||||
IntParameter & argFrameDecimation = parameters.add<IntParameter> ('f', "frame-decimator","Decimation factor for the video frames [default=1]");
|
||||
SwitchParameter<> & argScreenshot = parameters.add<SwitchParameter<>> (0x0, "screenshot", "Take a single screenshot, save it to file and quit");
|
||||
StringParameter & argAddress = parameters.add<StringParameter> ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]");
|
||||
IntParameter & argPriority = parameters.add<IntParameter> ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]");
|
||||
SwitchParameter<> & argHelp = parameters.add<SwitchParameter<>> ('h', "help", "Show this help message and exit");
|
||||
|
||||
// set defaults
|
||||
argDevice.setDefault("/dev/video0");
|
||||
argVideoStandard.setDefault(V4L2Grabber::PAL);
|
||||
argInput.setDefault(-1);
|
||||
argWidth.setDefault(-1);
|
||||
argHeight.setDefault(-1);
|
||||
argCropWidth.setDefault(0);
|
||||
argCropHeight.setDefault(0);
|
||||
argSizeDecimation.setDefault(1);
|
||||
argFrameDecimation.setDefault(1);
|
||||
argAddress.setDefault("127.0.0.1:19445");
|
||||
argPriority.setDefault(800);
|
||||
|
||||
// parse all options
|
||||
optionParser.parse(argc, const_cast<const char **>(argv));
|
||||
|
||||
// check if we need to display the usage. exit if we do.
|
||||
if (argHelp.isSet())
|
||||
{
|
||||
optionParser.usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
V4L2Grabber grabber(
|
||||
argDevice.getValue(),
|
||||
argInput.getValue(),
|
||||
argVideoStandard.getValue(),
|
||||
argWidth.getValue(),
|
||||
argHeight.getValue(),
|
||||
std::max(0, argCropWidth.getValue()),
|
||||
std::max(0, argCropHeight.getValue()),
|
||||
std::max(1, argFrameDecimation.getValue()),
|
||||
std::max(1, argSizeDecimation.getValue()));
|
||||
|
||||
grabber.start();
|
||||
if (argScreenshot.isSet())
|
||||
{
|
||||
grabber.setCallback(&saveScreenshot, nullptr);
|
||||
grabber.capture(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProtoConnection connection(argAddress.getValue());
|
||||
|
||||
grabber.setCallback(&sendImage, &connection);
|
||||
grabber.capture();
|
||||
}
|
||||
grabber.stop();
|
||||
}
|
||||
catch (const std::runtime_error & e)
|
||||
{
|
||||
// An error occured. Display error and quit
|
||||
std::cerr << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -35,10 +35,6 @@ if (ENABLE_DISPMANX)
|
||||
add_subdirectory(dispmanx2png)
|
||||
endif (ENABLE_DISPMANX)
|
||||
|
||||
if (ENABLE_V4L2)
|
||||
add_subdirectory(v4l2_to_png)
|
||||
endif (ENABLE_V4L2)
|
||||
|
||||
add_executable(test_blackborderdetector
|
||||
TestBlackBorderDetector.cpp)
|
||||
target_link_libraries(test_blackborderdetector
|
||||
|
@ -1,17 +0,0 @@
|
||||
|
||||
# find Qt4
|
||||
find_package(Qt4 REQUIRED QtCore QtGui)
|
||||
|
||||
include_directories(${QT_INCLUDES})
|
||||
|
||||
add_executable(v4l2_to_png
|
||||
v4l2_to_png.cpp
|
||||
V4L2Grabber.h
|
||||
V4L2Grabber.cpp)
|
||||
|
||||
target_link_libraries(v4l2_to_png
|
||||
getoptPlusPlus)
|
||||
|
||||
qt4_use_modules(v4l2_to_png
|
||||
Core
|
||||
Gui)
|
@ -1,104 +0,0 @@
|
||||
|
||||
// STL includes
|
||||
#include <csignal>
|
||||
#include <iomanip>
|
||||
|
||||
// QT includes
|
||||
#include <QImage>
|
||||
|
||||
// getoptPlusPLus includes
|
||||
#include <getoptPlusPlus/getoptpp.h>
|
||||
|
||||
#include "V4L2Grabber.h"
|
||||
|
||||
using namespace vlofgren;
|
||||
|
||||
/// Data parameter for the video standard
|
||||
typedef vlofgren::PODParameter<V4L2Grabber::VideoStandard> VideoStandardParameter;
|
||||
|
||||
namespace vlofgren {
|
||||
/// Translates a string (as passed on the commandline) to a color standard
|
||||
///
|
||||
/// @param[in] s The string (as passed on the commandline)
|
||||
/// @return The color standard
|
||||
/// @throws Parameter::ParameterRejected If the string did not result in a video standard
|
||||
template<>
|
||||
V4L2Grabber::VideoStandard VideoStandardParameter::validate(const std::string& s) throw (Parameter::ParameterRejected)
|
||||
{
|
||||
QString input = QString::fromStdString(s).toLower();
|
||||
|
||||
if (input == "pal")
|
||||
{
|
||||
return V4L2Grabber::PAL;
|
||||
}
|
||||
else if (input == "ntsc")
|
||||
{
|
||||
return V4L2Grabber::NTSC;
|
||||
}
|
||||
else if (input == "no-change")
|
||||
{
|
||||
return V4L2Grabber::NO_CHANGE;
|
||||
}
|
||||
|
||||
throw Parameter::ParameterRejected("Invalid value for video standard. Valid values are: PAL, NTSC, and NO-CHANGE");
|
||||
return V4L2Grabber::NO_CHANGE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
try
|
||||
{
|
||||
// create the option parser and initialize all parameters
|
||||
OptionsParser optionParser("Simple application to send a command to hyperion using the Json interface");
|
||||
ParameterSet & parameters = optionParser.getParameters();
|
||||
|
||||
StringParameter & argDevice = parameters.add<StringParameter> ('d', "device", "The device to use [default=/dev/video0]");
|
||||
VideoStandardParameter & argVideoStandard = parameters.add<VideoStandardParameter>('v', "video-standard", "The used video standard. Valid values are PAL. NYSC, or NO-CHANGE [default=PAL]");
|
||||
IntParameter & argInput = parameters.add<IntParameter> ('i', "input", "Input channel [default=0]");
|
||||
IntParameter & argCropWidth = parameters.add<IntParameter> (0x0, "crop-width", "Number of pixels to crop from the left and right sides in the picture before decimation [default=0]");
|
||||
IntParameter & argCropHeight = parameters.add<IntParameter> (0x0, "crop-height", "Number of pixels to crop from the top and the bottom in the picture before decimation [default=0]");
|
||||
IntParameter & argSizeDecimation = parameters.add<IntParameter> ('s', "size-decimator", "Decimation factor for the output size [default=1]");
|
||||
SwitchParameter<> & argHelp = parameters.add<SwitchParameter<> > ('h', "help", "Show this help message and exit");
|
||||
|
||||
// set defaults
|
||||
argDevice.setDefault("/dev/video0");
|
||||
argVideoStandard.setDefault(V4L2Grabber::PAL);
|
||||
argInput.setDefault(0);
|
||||
argCropWidth.setDefault(0);
|
||||
argCropHeight.setDefault(0);
|
||||
argSizeDecimation.setDefault(1);
|
||||
|
||||
// parse all options
|
||||
optionParser.parse(argc, const_cast<const char **>(argv));
|
||||
|
||||
// check if we need to display the usage. exit if we do.
|
||||
if (argHelp.isSet())
|
||||
{
|
||||
optionParser.usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
V4L2Grabber grabber(
|
||||
argDevice.getValue(),
|
||||
argInput.getValue(),
|
||||
argVideoStandard.getValue(),
|
||||
std::max(0, argCropWidth.getValue()),
|
||||
std::max(0, argCropHeight.getValue()),
|
||||
1,
|
||||
argSizeDecimation.getValue());
|
||||
|
||||
grabber.start();
|
||||
grabber.capture(1);
|
||||
grabber.stop();
|
||||
}
|
||||
catch (const std::runtime_error & e)
|
||||
{
|
||||
// An error occured. Display error and quit
|
||||
std::cerr << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user