diff --git a/libsrc/grabber/osx/OsxFrameGrabber.h b/include/grabber/OsxFrameGrabber.h similarity index 100% rename from libsrc/grabber/osx/OsxFrameGrabber.h rename to include/grabber/OsxFrameGrabber.h diff --git a/libsrc/grabber/osx/CMakeLists.txt b/libsrc/grabber/osx/CMakeLists.txt index 7f6c6325..ca72df4c 100644 --- a/libsrc/grabber/osx/CMakeLists.txt +++ b/libsrc/grabber/osx/CMakeLists.txt @@ -8,7 +8,7 @@ SET(OsxGrabberQT_HEADERS ) SET(OsxGrabberHEADERS - ${CURRENT_SOURCE_DIR}/OsxFrameGrabber.h + ${CURRENT_HEADER_DIR}/OsxFrameGrabber.h ) SET(OsxGrabberSOURCES @@ -17,9 +17,9 @@ SET(OsxGrabberSOURCES ) if(ENABLE_QT5) -QT5_WRAP_CPP(OsxGrabberHEADERS_MOC ${OsxGrabberQT_HEADERS}) + QT5_WRAP_CPP(OsxGrabberHEADERS_MOC ${OsxGrabberQT_HEADERS}) else(ENABLE_QT5) -QT4_WRAP_CPP(OsxGrabberHEADERS_MOC ${OsxGrabberQT_HEADERS}) + QT4_WRAP_CPP(OsxGrabberHEADERS_MOC ${OsxGrabberQT_HEADERS}) endif(ENABLE_QT5) add_library(osx-grabber diff --git a/libsrc/grabber/osx/OsxFrameGrabber.cpp b/libsrc/grabber/osx/OsxFrameGrabber.cpp index b6c7a2c9..0a8d23fc 100755 --- a/libsrc/grabber/osx/OsxFrameGrabber.cpp +++ b/libsrc/grabber/osx/OsxFrameGrabber.cpp @@ -3,7 +3,7 @@ #include // Local includes -#include "OsxFrameGrabber.h" +#include OsxFrameGrabber::OsxFrameGrabber(const unsigned display, const unsigned width, const unsigned height) : _screenIndex(display), diff --git a/libsrc/grabber/osx/OsxWrapper.cpp b/libsrc/grabber/osx/OsxWrapper.cpp index 8dec515d..4111ea0b 100644 --- a/libsrc/grabber/osx/OsxWrapper.cpp +++ b/libsrc/grabber/osx/OsxWrapper.cpp @@ -5,7 +5,7 @@ // Osx grabber includes #include -#include "OsxFrameGrabber.h" +#include OsxWrapper::OsxWrapper(const unsigned display, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority, Hyperion * hyperion) : _updateInterval_ms(1000/updateRate_Hz), diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 803cabf7..2626ba9b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,15 +3,15 @@ add_subdirectory(hyperion-remote) # The following clients depend on the protobuf library if(ENABLE_PROTOBUF) + if (ENABLE_AMLOGIC) add_subdirectory(hyperion-aml) endif() - # Add the 'Video 4 Linux' grabber if it is enabled + if(ENABLE_V4L2) add_subdirectory(hyperion-v4l2) endif() - # Add the X11 grabber if it is enabled if(ENABLE_X11) add_subdirectory(hyperion-x11) endif() @@ -24,4 +24,8 @@ if(ENABLE_PROTOBUF) add_subdirectory(hyperion-framebuffer) endif() + if(ENABLE_OSX) + add_subdirectory(hyperion-osx) + endif() + endif() diff --git a/src/hyperion-aml/hyperion-aml.cpp b/src/hyperion-aml/hyperion-aml.cpp index cca5e688..42870455 100644 --- a/src/hyperion-aml/hyperion-aml.cpp +++ b/src/hyperion-aml/hyperion-aml.cpp @@ -30,9 +30,9 @@ int main(int argc, char ** argv) OptionsParser optionParser("X11 capture application for Hyperion"); ParameterSet & parameters = optionParser.getParameters(); - IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default=10]"); - IntParameter & argWidth = parameters.add (0x0, "width", "Width of the captured image [default=128]"); - IntParameter & argHeight = parameters.add (0x0, "height", "Height of the captured image [default=128]"); + IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default: 10]"); + IntParameter & argWidth = parameters.add (0x0, "width", "Width of the captured image [default: 128]"); + IntParameter & argHeight = parameters.add (0x0, "height", "Height of the captured image [default: 128]"); SwitchParameter<> & argScreenshot = parameters.add> (0x0, "screenshot", "Take a single screenshot, save it to file and quit"); StringParameter & argAddress = parameters.add ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]"); IntParameter & argPriority = parameters.add ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]"); diff --git a/src/hyperion-dispmanx/hyperion-dispmanx.cpp b/src/hyperion-dispmanx/hyperion-dispmanx.cpp index abf78c8c..e5ebf429 100644 --- a/src/hyperion-dispmanx/hyperion-dispmanx.cpp +++ b/src/hyperion-dispmanx/hyperion-dispmanx.cpp @@ -29,7 +29,7 @@ int main(int argc, char ** argv) OptionsParser optionParser("Dispmanx capture application for Hyperion"); ParameterSet & parameters = optionParser.getParameters(); - IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default=10]"); + IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default: 10]"); IntParameter & argWidth = parameters.add (0x0, "width", "The width of the grabbed frames [pixels]"); IntParameter & argHeight = parameters.add (0x0, "height", "The height of the grabbed frames"); diff --git a/src/hyperion-framebuffer/hyperion-framebuffer.cpp b/src/hyperion-framebuffer/hyperion-framebuffer.cpp index 70f11d7d..b4c7f830 100644 --- a/src/hyperion-framebuffer/hyperion-framebuffer.cpp +++ b/src/hyperion-framebuffer/hyperion-framebuffer.cpp @@ -30,12 +30,12 @@ int main(int argc, char ** argv) OptionsParser optionParser("X11 capture application for Hyperion"); ParameterSet & parameters = optionParser.getParameters(); - IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default=10]"); - IntParameter & argWidth = parameters.add (0x0, "width", "Width of the captured image [default=128]"); - IntParameter & argHeight = parameters.add (0x0, "height", "Height of the captured image [default=128]"); + StringParameter & argDevice = parameters.add ('d', "device", "Set the video device [default: /dev/video0]"); + IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default: 10]"); + IntParameter & argWidth = parameters.add (0x0, "width", "Width of the captured image [default: 128]"); + IntParameter & argHeight = parameters.add (0x0, "height", "Height of the captured image [default: 128]"); SwitchParameter<> & argScreenshot = parameters.add> (0x0, "screenshot", "Take a single screenshot, save it to file and quit"); StringParameter & argAddress = parameters.add ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]"); - StringParameter & argDevice = parameters.add ('a', "device", "Set the video device (default: /dev/video0)"); IntParameter & argPriority = parameters.add ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]"); SwitchParameter<> & argSkipReply = parameters.add> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); SwitchParameter<> & argHelp = parameters.add> ('h', "help", "Show this help message and exit"); diff --git a/src/hyperion-osx/CMakeLists.txt b/src/hyperion-osx/CMakeLists.txt new file mode 100644 index 00000000..e7143042 --- /dev/null +++ b/src/hyperion-osx/CMakeLists.txt @@ -0,0 +1,57 @@ +# Configure minimum CMAKE version +cmake_minimum_required(VERSION 2.8) + +# Set the project name +project(hyperion-osx) + +# find QT +if(ENABLE_QT5) + find_package(Qt5Widgets REQUIRED) +else(ENABLE_QT5) + find_package(Qt4 REQUIRED QtCore QtGui QtNetwork ) +endif(ENABLE_QT5) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR}/../../libsrc/protoserver + ${QT_INCLUDES} + ${PROTOBUF_INCLUDE_DIRS} +) + +set(Hyperion_OSX_QT_HEADERS + OsxWrapper.h +) + +set(Hyperion_OSX_HEADERS +) + +set(Hyperion_OSX_SOURCES + hyperion-osx.cpp + OsxWrapper.cpp +) + +if(ENABLE_QT5) + QT5_WRAP_CPP(Hyperion_OSX_HEADERS_MOC ${Hyperion_OSX_QT_HEADERS}) +else(ENABLE_QT5) + QT4_WRAP_CPP(Hyperion_OSX_HEADERS_MOC ${Hyperion_OSX_QT_HEADERS}) +endif(ENABLE_QT5) + +add_executable( ${PROJECT_NAME} + ${Hyperion_OSX_HEADERS} + ${Hyperion_OSX_SOURCES} + ${Hyperion_OSX_HEADERS_MOC} +) + +target_link_libraries( ${PROJECT_NAME} + getoptPlusPlus + blackborder + hyperion-utils + protoserver + osx-grabber + pthread +) + +if(ENABLE_QT5) + qt5_use_modules(${PROJECT_NAME} Widgets Core Gui Network) +else(ENABLE_QT5) + qt4_use_modules(${PROJECT_NAME} Core Gui Network ) +endif(ENABLE_QT5) diff --git a/src/hyperion-osx/OsxWrapper.cpp b/src/hyperion-osx/OsxWrapper.cpp new file mode 100644 index 00000000..9f35084b --- /dev/null +++ b/src/hyperion-osx/OsxWrapper.cpp @@ -0,0 +1,36 @@ + +// Hyperion-AmLogic includes +#include "FramebufferWrapper.h" + +OsxWrapper::OsxWrapper(const unsigned display, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) : + _timer(this), + _grabber(display,grabWidth, grabHeight) +{ + _timer.setSingleShot(false); + _timer.setInterval(updateRate_Hz); + + // Connect capturing to the timeout signal of the timer + connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); +} + +const Image & OsxWrapper::getScreenshot() +{ + capture(); + return _screenshot; +} + +void OsxWrapper::start() +{ + _timer.start(); +} + +void OsxWrapper::stop() +{ + _timer.stop(); +} + +void OsxWrapper::capture() +{ + _grabber.grabFrame(_screenshot); + emit sig_screenshot(_screenshot); +} diff --git a/src/hyperion-osx/OsxWrapper.h b/src/hyperion-osx/OsxWrapper.h new file mode 100644 index 00000000..9ff4c956 --- /dev/null +++ b/src/hyperion-osx/OsxWrapper.h @@ -0,0 +1,42 @@ + +// QT includes +#include + +// Hyperion-Dispmanx includes +#include + +class OsxWrapper : public QObject +{ + Q_OBJECT +public: + OsxWrapper(const unsigned display, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz); + + const Image & getScreenshot(); + + /// + /// Starts the timed capturing of screenshots + /// + void start(); + + void stop(); + +signals: + void sig_screenshot(const Image & screenshot); + +private slots: + /// + /// Performs a single screenshot capture and publishes the capture screenshot on the screenshot signal. + /// + void capture(); + +private: + /// The QT timer to generate capture-publish events + QTimer _timer; + + /// The grabber for creating screenshots + OsxFrameGrabber _grabber; + + // image buffers + Image _screenshot; + +}; diff --git a/src/hyperion-osx/hyperion-osx.cpp b/src/hyperion-osx/hyperion-osx.cpp new file mode 100644 index 00000000..dbb51575 --- /dev/null +++ b/src/hyperion-osx/hyperion-osx.cpp @@ -0,0 +1,101 @@ + + +// QT includes +#include +#include + +// getoptPlusPLus includes +#include + +#include +#include "OsxWrapper.h" + +using namespace vlofgren; + +// save the image as screenshot +void saveScreenshot(const char * filename, const Image & image) +{ + // store as PNG + QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888); + pngImage.save(filename); +} + +int main(int argc, char ** argv) +{ + QCoreApplication app(argc, argv); + + try + { + // create the option parser and initialize all parameters + OptionsParser optionParser("X11 capture application for Hyperion"); + ParameterSet & parameters = optionParser.getParameters(); + + IntParameter & argDisplay = parameters.add ('d', "display", "Set the display to capture [default: 0]"); + IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default: 10]"); + IntParameter & argWidth = parameters.add (0x0, "width", "Width of the captured image [default: 128]"); + IntParameter & argHeight = parameters.add (0x0, "height", "Height of the captured image [default: 128]"); + SwitchParameter<> & argScreenshot = parameters.add> (0x0, "screenshot", "Take a single screenshot, save it to file and quit"); + StringParameter & argAddress = parameters.add ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]"); + IntParameter & argPriority = parameters.add ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]"); + SwitchParameter<> & argSkipReply = parameters.add> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); + SwitchParameter<> & argHelp = parameters.add> ('h', "help", "Show this help message and exit"); + + // set defaults + argFps.setDefault(10); + argWidth.setDefault(160); + argHeight.setDefault(160); + argAddress.setDefault("127.0.0.1:19445"); + argPriority.setDefault(800); + argDisplay.setDefault(0); + + // parse all options + optionParser.parse(argc, const_cast(argv)); + + // check if we need to display the usage. exit if we do. + if (argHelp.isSet()) + { + optionParser.usage(); + return 0; + } + + int width = argWidth.getValue(); + int height = argHeight.getValue(); + if (width < 160 || height < 160) + { + std::cout << "Minimum width and height is 160" << std::endl; + width = std::max(160, width); + height = std::max(160, height); + } + + int grabInterval = 1000 / argFps.getValue(); + OsxWrapper osxWrapper(argDisplay.getValue(), argWidth.getValue(), argHeight.getValue(), grabInterval); + + if (argScreenshot.isSet()) + { + // Capture a single screenshot and finish + const Image & screenshot = osxWrapper.getScreenshot(); + saveScreenshot("screenshot.png", screenshot); + } + else + { + // Create the Proto-connection with hyperiond + ProtoConnectionWrapper protoWrapper(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet()); + + // Connect the screen capturing to the proto processing + QObject::connect(&osxWrapper, SIGNAL(sig_screenshot(const Image &)), &protoWrapper, SLOT(receiveImage(Image))); + + // Start the capturing + osxWrapper.start(); + + // Start the application + app.exec(); + } + } + catch (const std::runtime_error & e) + { + // An error occured. Display error and quit + std::cerr << e.what() << std::endl; + return -1; + } + return 0; +} diff --git a/src/hyperion-v4l2/hyperion-v4l2.cpp b/src/hyperion-v4l2/hyperion-v4l2.cpp index fe011f6d..ed56dbb7 100644 --- a/src/hyperion-v4l2/hyperion-v4l2.cpp +++ b/src/hyperion-v4l2/hyperion-v4l2.cpp @@ -51,14 +51,14 @@ int main(int argc, char** argv) OptionsParser optionParser("V4L capture application for Hyperion"); ParameterSet & parameters = optionParser.getParameters(); - StringParameter & argDevice = parameters.add ('d', "device", "The device to use [default=/dev/video0]"); + StringParameter & argDevice = parameters.add ('d', "device", "The device to use [default: /dev/video0]"); VideoStandardParameter & argVideoStandard = parameters.add('v', "video-standard", "The used video standard. Valid values are PAL or NTSC (optional)"); PixelFormatParameter & argPixelFormat = parameters.add (0x0, "pixel-format", "The use pixel format. Valid values are YUYV, UYVY, and RGB32 (optional)"); IntParameter & argInput = parameters.add (0x0, "input", "Input channel (optional)"); IntParameter & argWidth = parameters.add (0x0, "width", "Try to set the width of the video input (optional)"); IntParameter & argHeight = parameters.add (0x0, "height", "Try to set the height of the video input (optional)"); - IntParameter & argCropWidth = parameters.add (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default=0]"); - IntParameter & argCropHeight = parameters.add (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default=0]"); + IntParameter & argCropWidth = parameters.add (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: 0]"); + IntParameter & argCropHeight = parameters.add (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: 0]"); IntParameter & argCropLeft = parameters.add (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)"); IntParameter & argCropRight = parameters.add (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation (overrides --crop-width)"); IntParameter & argCropTop = parameters.add (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation (overrides --crop-height)"); diff --git a/src/hyperion-x11/hyperion-x11.cpp b/src/hyperion-x11/hyperion-x11.cpp index 7815aa34..42853af1 100644 --- a/src/hyperion-x11/hyperion-x11.cpp +++ b/src/hyperion-x11/hyperion-x11.cpp @@ -29,9 +29,9 @@ int main(int argc, char ** argv) OptionsParser optionParser("X11 capture application for Hyperion"); ParameterSet & parameters = optionParser.getParameters(); - IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default=10]"); - IntParameter & argCropWidth = parameters.add (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default=0]"); - IntParameter & argCropHeight = parameters.add (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default=0]"); + IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default: 10]"); + IntParameter & argCropWidth = parameters.add (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: 0]"); + IntParameter & argCropHeight = parameters.add (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: 0]"); IntParameter & argCropLeft = parameters.add (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)"); IntParameter & argCropRight = parameters.add (0x0, "crop-right", "Number of pixels to crop from the right of the picture before decimation (overrides --crop-width)"); IntParameter & argCropTop = parameters.add (0x0, "crop-top", "Number of pixels to crop from the top of the picture before decimation (overrides --crop-height)");