From 2aa4df92a93e7ef78be82db1ca888eac4994341d Mon Sep 17 00:00:00 2001 From: redPanther Date: Fri, 1 Sep 2017 08:50:37 +0200 Subject: [PATCH] amlogic refactoring (#464) * - grabber auto off when not set as active prio - join aml and fb - on aml platform both grabbers are needed, so they joind in one module and share one prio. user don't the the nasty magic behind - aml: preparation for direct ge2d access * just save it, in the middle of ge2d impl * fix compile issues * now grabbing works basicly * add 3d support for ge2d * next step, we got some video from aml * switch back to rgba * remove unfinished ge2d stuff * commit missing changes * some urgent fixes, needs some beautifying, but it works now * fixes and refctoring --- CMakeLists.txt | 6 +- assets/webconfig/js/content_grabber.js | 6 +- include/grabber/AmlogicGrabber.h | 17 +- include/hyperion/Grabber.h | 2 + include/hyperion/GrabberWrapper.h | 10 +- include/hyperion/Hyperion.h | 7 + include/hyperion/PriorityMuxer.h | 6 +- include/utils/ColorBgr.h | 2 +- include/utils/Image.h | 8 + libsrc/grabber/amlogic/AmlogicGrabber.cpp | 184 ++++++++++-------- libsrc/grabber/amlogic/Amvideocap.h | 80 ++++++++ libsrc/grabber/amlogic/CMakeLists.txt | 5 - .../grabber/dispmanx/DispmanxFrameGrabber.cpp | 2 + .../framebuffer/FramebufferFrameGrabber.cpp | 4 +- libsrc/grabber/osx/OsxFrameGrabber.cpp | 2 + libsrc/grabber/v4l2/V4L2Wrapper.cpp | 18 +- libsrc/grabber/x11/X11Grabber.cpp | 2 + libsrc/hyperion/Grabber.cpp | 5 + libsrc/hyperion/GrabberWrapper.cpp | 25 ++- libsrc/hyperion/Hyperion.cpp | 5 + libsrc/hyperion/PriorityMuxer.cpp | 23 ++- libsrc/utils/ImageResampler.cpp | 4 +- src/hyperion-aml/CMakeLists.txt | 1 + src/hyperiond/hyperiond.cpp | 9 +- 24 files changed, 291 insertions(+), 142 deletions(-) create mode 100644 libsrc/grabber/amlogic/Amvideocap.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2af512c8..320b2286 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,7 +106,11 @@ message(STATUS "ENABLE_AMLOGIC = ${ENABLE_AMLOGIC}") option(ENABLE_DISPMANX "Enable the RPi dispmanx grabber" ${DEFAULT_DISPMANX} ) message(STATUS "ENABLE_DISPMANX = ${ENABLE_DISPMANX}") -option(ENABLE_FB "Enable the framebuffer grabber" ${DEFAULT_FB} ) +if (ENABLE_AMLOGIC) + SET(ENABLE_FB ON) +else() + option(ENABLE_FB "Enable the framebuffer grabber" ${DEFAULT_FB} ) +endif() message(STATUS "ENABLE_FB = ${ENABLE_FB}") option(ENABLE_OSX "Enable the osx grabber" ${DEFAULT_OSX} ) diff --git a/assets/webconfig/js/content_grabber.js b/assets/webconfig/js/content_grabber.js index cb966034..6f8f4cae 100644 --- a/assets/webconfig/js/content_grabber.js +++ b/assets/webconfig/js/content_grabber.js @@ -71,8 +71,10 @@ $(document).ready( function() { hideEl(["device","verticalPixelDecimation","horizontalPixelDecimation","useXGetImage"]); else if(grabbers.indexOf('x11') > -1) hideEl(["device","width","height"]); - else if(grabbers.indexOf('osx') > -1 || grabbers.indexOf('amlogic') > -1) - hideEl(["device","verticalPixelDecimation","horizontalPixelDecimation","useXGetImage","cropLeft","cropBottom","cropTop","cropRight"]); + else if(grabbers.indexOf('osx') > -1 ) + hideEl(["device","verticalPixelDecimation","horizontalPixelDecimation","useXGetImage"]); + else if(grabbers.indexOf('amlogic') > -1) + hideEl(["verticalPixelDecimation","horizontalPixelDecimation","useXGetImage"]); }); removeOverlay(); diff --git a/include/grabber/AmlogicGrabber.h b/include/grabber/AmlogicGrabber.h index acc731e7..5b74840a 100755 --- a/include/grabber/AmlogicGrabber.h +++ b/include/grabber/AmlogicGrabber.h @@ -3,10 +3,10 @@ // Utils includes #include #include +#include + /// -/// The DispmanxFrameGrabber is used for creating snapshots of the display (screenshots) with a -/// downsized and scaled resolution. /// class AmlogicGrabber : public Grabber { @@ -37,9 +37,18 @@ private: * @return True if video is playing else false */ bool isVideoPlaying(); + int grabFrame_amvideocap(Image & image); + void closeDev(int &fd); + bool openDev(int &fd, const char* dev, int flags); /** The snapshot/capture device of the amlogic video chip */ - int _amlogicCaptureDev; + int _captureDev; + int _videoDev; + + Image _image_bgr; - Image _image; + int _lastError; + bool _videoPlaying; + FramebufferFrameGrabber _fbGrabber; + int _grabbingModeNotification; }; diff --git a/include/hyperion/Grabber.h b/include/hyperion/Grabber.h index aa6ac941..70db49ba 100644 --- a/include/hyperion/Grabber.h +++ b/include/hyperion/Grabber.h @@ -33,6 +33,7 @@ public: /// gets resulting width of image virtual const int getImageHeight() { return _height; }; + void setEnabled(bool enable); protected: ImageResampler _imageResampler; @@ -51,6 +52,7 @@ protected: // number of pixels to crop after capturing int _cropLeft, _cropRight, _cropTop, _cropBottom; + bool _enabled; /// logger instance Logger * _log; diff --git a/include/hyperion/GrabberWrapper.h b/include/hyperion/GrabberWrapper.h index 9650b4ed..44b27442 100644 --- a/include/hyperion/GrabberWrapper.h +++ b/include/hyperion/GrabberWrapper.h @@ -40,10 +40,9 @@ public: static QStringList availableGrabbers(); - public: template - void transferFrame(Grabber_T &grabber) + bool transferFrame(Grabber_T &grabber) { unsigned w = grabber.getImageWidth(); unsigned h = grabber.getImageHeight(); @@ -53,12 +52,15 @@ public: _image.resize(w, h); } - if (grabber.grabFrame(_image) >= 0) + int ret = grabber.grabFrame(_image); + if (ret >= 0) { emit emitImage(_priority, _image, _timeout_ms); _processor->process(_image, _ledColors); setColors(_ledColors, _timeout_ms); + return true; } + return false; } @@ -70,6 +72,8 @@ public slots: /// virtual void action() = 0; + void actionWrapper(); + /// /// Set the grabbing mode /// @param[in] mode The new grabbing mode diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index 29ac5f90..2329ac0a 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -97,6 +97,13 @@ public: /// int getCurrentPriority() const; + /// + /// Returns true if current priority is given priority + /// + /// @return bool + /// + bool isCurrentPriority(const int priority) const; + /// /// Returns a list of active priorities /// diff --git a/include/hyperion/PriorityMuxer.h b/include/hyperion/PriorityMuxer.h index a0cc23b9..a3316940 100644 --- a/include/hyperion/PriorityMuxer.h +++ b/include/hyperion/PriorityMuxer.h @@ -2,14 +2,14 @@ // STL includes #include -#include #include -#include // QT includes #include #include #include +#include +#include // Utils includes #include @@ -50,7 +50,7 @@ public: }; /// The lowest possible priority, which is used when no priority channels are active - const static int LOWEST_PRIORITY = std::numeric_limits::max(); + const static int LOWEST_PRIORITY; /// /// Constructs the PriorityMuxer for the given number of leds (used to switch to black when diff --git a/include/utils/ColorBgr.h b/include/utils/ColorBgr.h index a92e1270..bfe55ec5 100644 --- a/include/utils/ColorBgr.h +++ b/include/utils/ColorBgr.h @@ -34,7 +34,7 @@ struct ColorBgr }; /// Assert to ensure that the size of the structure is 'only' 3 bytes -static_assert(sizeof(ColorBgr) == 3, "Incorrect size of ColorRgb"); +static_assert(sizeof(ColorBgr) == 3, "Incorrect size of ColorBgr"); /// /// Stream operator to write ColorRgb to an outputstream (format "'{'[red]','[green]','[blue]'}'") diff --git a/include/utils/Image.h b/include/utils/Image.h index f4c5183e..d2c427e5 100644 --- a/include/utils/Image.h +++ b/include/utils/Image.h @@ -205,6 +205,14 @@ public: } } + /// + /// get size of buffer + // + ssize_t size() + { + return _width * _height * sizeof(Pixel_T); + } + private: /// diff --git a/libsrc/grabber/amlogic/AmlogicGrabber.cpp b/libsrc/grabber/amlogic/AmlogicGrabber.cpp index 4d642cca..321bd423 100755 --- a/libsrc/grabber/amlogic/AmlogicGrabber.cpp +++ b/libsrc/grabber/amlogic/AmlogicGrabber.cpp @@ -1,8 +1,8 @@ - // STL includes #include #include #include +#include // Linux includes #include @@ -15,137 +15,157 @@ // Local includes #include #include +#include "Amvideocap.h" - -// Flags copied from 'include/linux/amlogic/amports/amvideocap.h' at https://github.com/codesnake/linux-amlogic -#define AMVIDEOCAP_IOC_MAGIC 'V' -#define AMVIDEOCAP_IOW_SET_WANTFRAME_WIDTH _IOW(AMVIDEOCAP_IOC_MAGIC, 0x02, int) -#define AMVIDEOCAP_IOW_SET_WANTFRAME_HEIGHT _IOW(AMVIDEOCAP_IOC_MAGIC, 0x03, int) - -#if HAVE_AML_HEADER - #include -#else - // Flags copied from 'include/linux/amlogic/amports/amvstream.h' at https://github.com/codesnake/linux-amlogic - #define AMSTREAM_IOC_MAGIC 'S' - #define AMSTREAM_IOC_GET_VIDEO_DISABLE _IOR(AMSTREAM_IOC_MAGIC, 0x48, unsigned long) -#endif +#define VIDEO_DEVICE "/dev/amvideo" +#define CAPTURE_DEVICE "/dev/amvideocap0" +#include AmlogicGrabber::AmlogicGrabber(const unsigned width, const unsigned height) : Grabber("AMLOGICGRABBER", qMax(160u, width), qMax(160u, height)) // Minimum required width or height is 160 - , _amlogicCaptureDev(-1) + , _captureDev(-1) + , _videoDev(-1) + , _lastError(0) + , _fbGrabber("/dev/fb0",width,height) + , _grabbingModeNotification(0) { Debug(_log, "constructed(%d x %d)",_width,_height); } AmlogicGrabber::~AmlogicGrabber() { - if (_amlogicCaptureDev != -1) + closeDev(_captureDev); + closeDev(_videoDev); +} + +bool AmlogicGrabber::openDev(int &fd, const char* dev, int flags) +{ + if (fd<0) { - if (close(_amlogicCaptureDev) == -1) - { - Error(_log, "Failed to close device (%d - %s)", errno, strerror(errno)); - } - _amlogicCaptureDev = -1; + fd = open(dev, flags); + } + return fd >= 0; +} + +void AmlogicGrabber::closeDev(int &fd) +{ + if (fd >= 0) + { + close(fd); + fd = -1; } } - bool AmlogicGrabber::isVideoPlaying() { - const QString videoDevice = "/dev/amvideo"; + if(!QFile::exists(VIDEO_DEVICE)) return false; - // Open the video device - int video_fd = open(QSTRING_CSTR(videoDevice), O_RDONLY); - if (video_fd < 0) + int videoDisabled = 1; + if (!openDev(_videoDev, VIDEO_DEVICE, O_RDWR)) { - Error(_log, "Failed to open video device(%s): %d - %s", QSTRING_CSTR(videoDevice), errno, strerror(errno)); + Error(_log, "Failed to open video device(%s): %d - %s", VIDEO_DEVICE, errno, strerror(errno)); return false; } - - // Check the video disabled flag - int videoDisabled; - if (ioctl(video_fd, AMSTREAM_IOC_GET_VIDEO_DISABLE, &videoDisabled) == -1) + else { - Error(_log, "Failed to retrieve video state from device: %d - %s", errno, strerror(errno)); - close(video_fd); - return false; + // Check the video disabled flag + if(ioctl(_videoDev, AMSTREAM_IOC_GET_VIDEO_DISABLE, &videoDisabled) < 0) + { + Error(_log, "Failed to retrieve video state from device: %d - %s", errno, strerror(errno)); + closeDev(_videoDev); + return false; + } } - // Make sure to close the device after use - close(video_fd); - return videoDisabled == 0; } int AmlogicGrabber::grabFrame(Image & image) { - // TODO crop resulting image accroding member _videoMode - // TODO add croping + if (!_enabled) return 0; + image.resize(_width,_height); // Make sure video is playing, else there is nothing to grab - if (!isVideoPlaying()) + if (isVideoPlaying()) { + if (_grabbingModeNotification!=1) + { + Info(_log, "VPU mode"); + _grabbingModeNotification = 1; + _lastError = 0; + } + + if (QFile::exists(CAPTURE_DEVICE)) + { + grabFrame_amvideocap(image); + } + } + else + { + if (_grabbingModeNotification!=2) + { + Info( _log, "FB mode"); + _grabbingModeNotification = 2; + _lastError = 0; + } + _fbGrabber.grabFrame(image); + } + + closeDev(_videoDev); + + return 0; +} + + +int AmlogicGrabber::grabFrame_amvideocap(Image & image) +{ + // If the device is not open, attempt to open it + if (! openDev(_captureDev, CAPTURE_DEVICE, O_RDWR)) + { + ErrorIf( _lastError != 1, _log,"Failed to open the AMLOGIC device (%d - %s):", errno, strerror(errno)); + _lastError = 1; return -1; } - // If the device is not open, attempt to open it - if (_amlogicCaptureDev == -1) + long r1 = ioctl(_captureDev, AMVIDEOCAP_IOW_SET_WANTFRAME_WIDTH, _width); + long r2 = ioctl(_captureDev, AMVIDEOCAP_IOW_SET_WANTFRAME_HEIGHT, _height); + + if (r1<0 || r2<0 || _height==0 || _width==0) { - _amlogicCaptureDev = open("/dev/amvideocap0", O_RDONLY, 0); - - // If the device is still not open, there is something wrong - if (_amlogicCaptureDev == -1) - { - Error(_log,"Failed to open the AMLOGIC device (%d - %s):", errno, strerror(errno)); - return -1; - } - } - - - if (ioctl(_amlogicCaptureDev, AMVIDEOCAP_IOW_SET_WANTFRAME_WIDTH, _width) == -1 || - ioctl(_amlogicCaptureDev, AMVIDEOCAP_IOW_SET_WANTFRAME_HEIGHT, _height) == -1) - { - // Failed to configure frame width - Error(_log,"Failed to configure capture size (%d - %s)", errno, strerror(errno)); - close(_amlogicCaptureDev); - _amlogicCaptureDev = -1; + ErrorIf(_lastError != 2,_log,"Failed to configure capture size (%d - %s)", errno, strerror(errno)); + closeDev(_captureDev); + _lastError = 2; return -1; } // Read the snapshot into the memory - void * image_ptr = _image.memptr(); - const ssize_t bytesToRead = _width * _height * sizeof(ColorBgr); + image.resize(_width, _height); + _image_bgr.resize(_width, _height); + const ssize_t bytesToRead = _image_bgr.size(); + void * image_ptr = _image_bgr.memptr(); + const ssize_t bytesRead = pread(_captureDev, image_ptr, bytesToRead, 0); - const ssize_t bytesRead = pread(_amlogicCaptureDev, image_ptr, bytesToRead, 0); - if (bytesRead == -1) + if (bytesRead < 0) { - Error(_log,"Read of device failed: %d - %s", errno, strerror(errno)); - close(_amlogicCaptureDev); - _amlogicCaptureDev = -1; + ErrorIf(_lastError != 3, _log,"Read of device failed: %d - %s", errno, strerror(errno)); + closeDev(_captureDev); + _lastError = 3; return -1; } else if (bytesToRead != bytesRead) { // Read of snapshot failed - Error(_log,"Capture failed to grab entire image [bytesToRead(%d) != bytesRead(%d)]", bytesToRead, bytesRead); - close(_amlogicCaptureDev); - _amlogicCaptureDev = -1; + ErrorIf(_lastError != 4, _log,"Capture failed to grab entire image [bytesToRead(%d) != bytesRead(%d)]", bytesToRead, bytesRead); + closeDev(_captureDev); return -1; } - // For now we always close the device now and again - static int readCnt = 0; - ++readCnt; - if (readCnt > 20) - { - close(_amlogicCaptureDev); - _amlogicCaptureDev = -1; - readCnt = 0; - } + closeDev(_captureDev); - _imageResampler.setHorizontalPixelDecimation(_width); - _imageResampler.setVerticalPixelDecimation(_height); - _imageResampler.processImage((const uint8_t*)image_ptr, _width, _height, 3, PIXELFORMAT_BGR24, image); + _imageResampler.processImage((const uint8_t*)image_ptr, _width, _height, _width*3, PIXELFORMAT_BGR24, image); + + _lastError = 0; return 0; } + diff --git a/libsrc/grabber/amlogic/Amvideocap.h b/libsrc/grabber/amlogic/Amvideocap.h new file mode 100644 index 00000000..577b843c --- /dev/null +++ b/libsrc/grabber/amlogic/Amvideocap.h @@ -0,0 +1,80 @@ +#pragma once + +#include +//#include + +#define AMVIDEOCAP_IOC_MAGIC 'V' +#define CAP_FLAG_AT_CURRENT 0 +#define CAP_FLAG_AT_TIME_WINDOW 1 +#define CAP_FLAG_AT_END 2 + +/* +format see linux/ge2d/ge2d.h +like: +GE2D_FORMAT_S24_RGB +*/ +#define GE2D_ENDIAN_SHIFT 24 +#define GE2D_LITTLE_ENDIAN (1 << GE2D_ENDIAN_SHIFT) +#define GE2D_COLOR_MAP_SHIFT 20 +#define GE2D_COLOR_MAP_BGR888 (5 << GE2D_COLOR_MAP_SHIFT) +#define GE2D_COLOR_MAP_RGB888 (0 << GE2D_COLOR_MAP_SHIFT) +#define GE2D_FMT_S24_RGB (GE2D_LITTLE_ENDIAN|0x00200) /* 10_00_0_00_0_00 */ +#define GE2D_FORMAT_S24_BGR (GE2D_FMT_S24_RGB | GE2D_COLOR_MAP_BGR888) +#define GE2D_FORMAT_S24_RGB (GE2D_FMT_S24_RGB | GE2D_COLOR_MAP_RGB888) + +#define AMVIDEOCAP_IOW_SET_WANTFRAME_FORMAT _IOW(AMVIDEOCAP_IOC_MAGIC, 0x01, int) +#define AMVIDEOCAP_IOW_SET_WANTFRAME_WIDTH _IOW(AMVIDEOCAP_IOC_MAGIC, 0x02, int) +#define AMVIDEOCAP_IOW_SET_WANTFRAME_HEIGHT _IOW(AMVIDEOCAP_IOC_MAGIC, 0x03, int) +#define AMVIDEOCAP_IOW_SET_WANTFRAME_TIMESTAMP_MS _IOW(AMVIDEOCAP_IOC_MAGIC, 0x04, unsigned long) +#define AMVIDEOCAP_IOW_SET_WANTFRAME_WAIT_MAX_MS _IOW(AMVIDEOCAP_IOC_MAGIC, 0x05, unsigned long) +#define AMVIDEOCAP_IOW_SET_WANTFRAME_AT_FLAGS _IOW(AMVIDEOCAP_IOC_MAGIC, 0x06, int) + + +#define AMVIDEOCAP_IOR_GET_FRAME_FORMAT _IOR(AMVIDEOCAP_IOC_MAGIC, 0x10, int) +#define AMVIDEOCAP_IOR_GET_FRAME_WIDTH _IOR(AMVIDEOCAP_IOC_MAGIC, 0x11, int) +#define AMVIDEOCAP_IOR_GET_FRAME_HEIGHT _IOR(AMVIDEOCAP_IOC_MAGIC, 0x12, int) +#define AMVIDEOCAP_IOR_GET_FRAME_TIMESTAMP_MS _IOR(AMVIDEOCAP_IOC_MAGIC, 0x13, unsigned long) + + +#define AMVIDEOCAP_IOR_GET_SRCFRAME_FORMAT _IOR(AMVIDEOCAP_IOC_MAGIC, 0x20, int) +#define AMVIDEOCAP_IOR_GET_SRCFRAME_WIDTH _IOR(AMVIDEOCAP_IOC_MAGIC, 0x21, int) +#define AMVIDEOCAP_IOR_GET_SRCFRAME_HEIGHT _IOR(AMVIDEOCAP_IOC_MAGIC, 0x22, int) + + +#define AMVIDEOCAP_IOR_GET_STATE _IOR(AMVIDEOCAP_IOC_MAGIC, 0x31, int) +#define AMVIDEOCAP_IOW_SET_START_CAPTURE _IOW(AMVIDEOCAP_IOC_MAGIC, 0x32, int) +#define AMVIDEOCAP_IOW_SET_CANCEL_CAPTURE _IOW(AMVIDEOCAP_IOC_MAGIC, 0x33, int) + +#define AMVIDEOCAP_IOR_SET_SRC_X _IOR(AMVIDEOCAP_IOC_MAGIC, 0x40, int) +#define AMVIDEOCAP_IOR_SET_SRC_Y _IOR(AMVIDEOCAP_IOC_MAGIC, 0x41, int) +#define AMVIDEOCAP_IOR_SET_SRC_WIDTH _IOR(AMVIDEOCAP_IOC_MAGIC, 0x42, int) +#define AMVIDEOCAP_IOR_SET_SRC_HEIGHT _IOR(AMVIDEOCAP_IOC_MAGIC, 0x43, int) + +enum amvideocap_state{ + AMVIDEOCAP_STATE_INIT=0, + AMVIDEOCAP_STATE_ON_CAPTURE=200, + AMVIDEOCAP_STATE_FINISHED_CAPTURE=300, + AMVIDEOCAP_STATE_ERROR=0xffff, +}; + + +#define AMVIDEO_MAGIC 'X' + +#define AMVIDEO_EXT_GET_CURRENT_VIDEOFRAME _IOR((AMVIDEO_MAGIC), 0x01, int32_t) +#define AMVIDEO_EXT_PUT_CURRENT_VIDEOFRAME _IO((AMVIDEO_MAGIC), 0x02) + +#define AMVIDEO_EXT_CURRENT_VIDEOFRAME_GET_GE2D_FORMAT _IOR((AMVIDEO_MAGIC), 0x03, uint32_t) +#define AMVIDEO_EXT_CURRENT_VIDEOFRAME_GET_SIZE _IOR((AMVIDEO_MAGIC), 0x04, uint64_t) +#define AMVIDEO_EXT_CURRENT_VIDEOFRAME_GET_CANVAS0ADDR _IOR((AMVIDEO_MAGIC), 0x05, uint32_t) + +#define _A_M 'S' +#define AMSTREAM_IOC_GET_VIDEO_DISABLE _IOR((_A_M), 0x48, int) +#define AMSTREAM_IOC_SET_VIDEO_DISABLE _IOW((_A_M), 0x49, int) +struct Rectangle +{ + int X; + int Y; + int Width; + int Height; +}; + diff --git a/libsrc/grabber/amlogic/CMakeLists.txt b/libsrc/grabber/amlogic/CMakeLists.txt index 40ce2d59..284f8b5f 100644 --- a/libsrc/grabber/amlogic/CMakeLists.txt +++ b/libsrc/grabber/amlogic/CMakeLists.txt @@ -6,11 +6,6 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/amlogic) FILE ( GLOB AmlogicSOURCES "${CURRENT_HEADER_DIR}/Amlogic*.h" "${CURRENT_SOURCE_DIR}/*.h" "${CURRENT_SOURCE_DIR}/*.cpp" ) -CHECK_INCLUDE_FILES ("amcodec/amports/amstream.h" HAVE_AML_HEADER) -IF (${HAVE_AML_HEADER}) - ADD_DEFINITIONS( -DHAVE_AML_HEADER ) -ENDIF() - add_library(amlogic-grabber ${AmlogicSOURCES} ) target_link_libraries(amlogic-grabber diff --git a/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp b/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp index 833fd1bb..ec7aacc3 100644 --- a/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp +++ b/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp @@ -69,6 +69,8 @@ void DispmanxFrameGrabber::setFlags(const int vc_flags) int DispmanxFrameGrabber::grabFrame(Image & image) { + if (!_enabled) return 0; + int ret; // vc_dispmanx_resource_read_data doesn't seem to work well diff --git a/libsrc/grabber/framebuffer/FramebufferFrameGrabber.cpp b/libsrc/grabber/framebuffer/FramebufferFrameGrabber.cpp index 4b1a15f8..3eec042c 100755 --- a/libsrc/grabber/framebuffer/FramebufferFrameGrabber.cpp +++ b/libsrc/grabber/framebuffer/FramebufferFrameGrabber.cpp @@ -37,7 +37,7 @@ FramebufferFrameGrabber::FramebufferFrameGrabber(const QString & device, const u } else { - Error(_log, "Display opened with resolution: %dx%d@%dbit", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel); + Info(_log, "Display opened with resolution: %dx%d@%dbit", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel); } close(_fbfd); } @@ -49,6 +49,8 @@ FramebufferFrameGrabber::~FramebufferFrameGrabber() int FramebufferFrameGrabber::grabFrame(Image & image) { + if (!_enabled) return 0; + struct fb_var_screeninfo vinfo; unsigned capSize, bytesPerPixel; PixelFormat pixelFormat; diff --git a/libsrc/grabber/osx/OsxFrameGrabber.cpp b/libsrc/grabber/osx/OsxFrameGrabber.cpp index 707292d2..97862f0f 100755 --- a/libsrc/grabber/osx/OsxFrameGrabber.cpp +++ b/libsrc/grabber/osx/OsxFrameGrabber.cpp @@ -39,6 +39,8 @@ OsxFrameGrabber::~OsxFrameGrabber() int OsxFrameGrabber::grabFrame(Image & image) { + if (!_enabled) return 0; + CGImageRef dispImage; CFDataRef imgData; unsigned char * pImgData; diff --git a/libsrc/grabber/v4l2/V4L2Wrapper.cpp b/libsrc/grabber/v4l2/V4L2Wrapper.cpp index 480899b6..0bbe3ed3 100644 --- a/libsrc/grabber/v4l2/V4L2Wrapper.cpp +++ b/libsrc/grabber/v4l2/V4L2Wrapper.cpp @@ -86,20 +86,14 @@ void V4L2Wrapper::readError(const char* err) void V4L2Wrapper::checkSources() { - QList activePriorities = _hyperion->getActivePriorities(); - - for (int x : activePriorities) + if ( _hyperion->isCurrentPriority(_priority)) { - if (x < _priority) - { - // found a higher priority source: grabber should be disabled - _grabber.stop(); - return; - } + _grabber.start(); + } + else + { + _grabber.stop(); } - - // no higher priority source was found: grabber should be enabled - _grabber.start(); } void V4L2Wrapper::action() diff --git a/libsrc/grabber/x11/X11Grabber.cpp b/libsrc/grabber/x11/X11Grabber.cpp index ce02a125..988ae4e2 100755 --- a/libsrc/grabber/x11/X11Grabber.cpp +++ b/libsrc/grabber/x11/X11Grabber.cpp @@ -117,6 +117,8 @@ bool X11Grabber::Setup() int X11Grabber::grabFrame(Image & image, bool forceUpdate) { + if (!_enabled) return 0; + if (forceUpdate) updateScreenDimensions(forceUpdate); diff --git a/libsrc/hyperion/Grabber.cpp b/libsrc/hyperion/Grabber.cpp index ce146898..bf0edd1b 100644 --- a/libsrc/hyperion/Grabber.cpp +++ b/libsrc/hyperion/Grabber.cpp @@ -11,6 +11,7 @@ Grabber::Grabber(QString grabberName, int width, int height, int cropLeft, int c , _cropRight(0) , _cropTop(0) , _cropBottom(0) + , _enabled(true) , _log(Logger::getInstance(grabberName)) { @@ -22,6 +23,10 @@ Grabber::~Grabber() { } +void Grabber::setEnabled(bool enable) +{ + _enabled = enable; +} void Grabber::setVideoMode(VideoMode mode) { diff --git a/libsrc/hyperion/GrabberWrapper.cpp b/libsrc/hyperion/GrabberWrapper.cpp index e9b7e5c0..88859a88 100644 --- a/libsrc/hyperion/GrabberWrapper.cpp +++ b/libsrc/hyperion/GrabberWrapper.cpp @@ -37,7 +37,7 @@ GrabberWrapper::GrabberWrapper(QString grabberName, Grabber * ggrabber, unsigned connect(_hyperion, SIGNAL(grabbingMode(GrabbingMode)), this, SLOT(setGrabbingMode(GrabbingMode))); connect(_hyperion, SIGNAL(videoMode(VideoMode)), this, SLOT(setVideoMode(VideoMode))); connect(this, SIGNAL(emitImage(int, const Image&, const int)), _hyperion, SLOT(setImage(int, const Image&, const int)) ); - connect(&_timer, SIGNAL(timeout()), this, SLOT(action())); + connect(&_timer, SIGNAL(timeout()), this, SLOT(actionWrapper())); } @@ -64,6 +64,12 @@ void GrabberWrapper::stop() _hyperion->unRegisterPriority(_grabberName); } +void GrabberWrapper::actionWrapper() +{ + _ggrabber->setEnabled(_hyperion->isCurrentPriority(_priority)); + action(); +} + void GrabberWrapper::componentStateChanged(const hyperion::Components component, bool enable) { if (component == _grabberComponentId) @@ -100,20 +106,13 @@ void GrabberWrapper::componentStateChanged(const hyperion::Components component, void GrabberWrapper::setGrabbingMode(const GrabbingMode mode) { - switch (mode) + if (mode == GRABBINGMODE_OFF) { - case GRABBINGMODE_VIDEO: - case GRABBINGMODE_PAUSE: - case GRABBINGMODE_AUDIO: - case GRABBINGMODE_PHOTO: - case GRABBINGMODE_MENU: - case GRABBINGMODE_SCREENSAVER: - case GRABBINGMODE_INVALID: - start(); - break; - case GRABBINGMODE_OFF: stop(); - break; + } + else + { + start(); } } diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index 18a566d2..a66b78e8 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -759,6 +759,11 @@ int Hyperion::getCurrentPriority() const return _sourceAutoSelectEnabled || !_muxer.hasPriority(_currentSourcePriority) ? _muxer.getCurrentPriority() : _currentSourcePriority; } +bool Hyperion::isCurrentPriority(const int priority) const +{ + return getCurrentPriority() == priority; +} + QList Hyperion::getActivePriorities() const { return _muxer.getPriorities(); diff --git a/libsrc/hyperion/PriorityMuxer.cpp b/libsrc/hyperion/PriorityMuxer.cpp index 33908917..d8443b92 100644 --- a/libsrc/hyperion/PriorityMuxer.cpp +++ b/libsrc/hyperion/PriorityMuxer.cpp @@ -1,16 +1,19 @@ // STL includes #include #include +#include // Hyperion includes #include +const int PriorityMuxer::LOWEST_PRIORITY = std::numeric_limits::max(); + PriorityMuxer::PriorityMuxer(int ledCount) - : _currentPriority(LOWEST_PRIORITY) + : _currentPriority(PriorityMuxer::LOWEST_PRIORITY) , _activeInputs() , _lowestPriorityInfo() { - _lowestPriorityInfo.priority = LOWEST_PRIORITY; + _lowestPriorityInfo.priority = PriorityMuxer::LOWEST_PRIORITY; _lowestPriorityInfo.timeoutTime_ms = 0; _lowestPriorityInfo.ledColors = std::vector(ledCount, {0, 0, 0}); _lowestPriorityInfo.componentId = hyperion::COMP_COLOR; @@ -40,7 +43,7 @@ QList PriorityMuxer::getPriorities() const bool PriorityMuxer::hasPriority(const int priority) const { - return (priority == LOWEST_PRIORITY) ? true : _activeInputs.contains(priority); + return (priority == PriorityMuxer::LOWEST_PRIORITY) ? true : _activeInputs.contains(priority); } const PriorityMuxer::InputInfo& PriorityMuxer::getInputInfo(const int priority) const @@ -48,7 +51,11 @@ const PriorityMuxer::InputInfo& PriorityMuxer::getInputInfo(const int priority) auto elemIt = _activeInputs.find(priority); if (elemIt == _activeInputs.end()) { - throw std::runtime_error("HYPERION (prioritymuxer) ERROR: no such priority"); + elemIt = _activeInputs.find(PriorityMuxer::LOWEST_PRIORITY); + if (elemIt == _activeInputs.end()) + { + throw std::runtime_error("HYPERION (prioritymuxer) ERROR: no such priority"); + } } return elemIt.value(); } @@ -67,7 +74,7 @@ void PriorityMuxer::setInput(const int priority, const std::vector& le void PriorityMuxer::clearInput(const int priority) { - if (priority < LOWEST_PRIORITY) + if (priority < PriorityMuxer::LOWEST_PRIORITY) { _activeInputs.remove(priority); if (_currentPriority == priority) @@ -83,14 +90,14 @@ void PriorityMuxer::clearAll(bool forceClearAll) if (forceClearAll) { _activeInputs.clear(); - _currentPriority = LOWEST_PRIORITY; + _currentPriority = PriorityMuxer::LOWEST_PRIORITY; _activeInputs[_currentPriority] = _lowestPriorityInfo; } else { for(auto key : _activeInputs.keys()) { - if (key < LOWEST_PRIORITY-1) + if (key < PriorityMuxer::LOWEST_PRIORITY-1) { _activeInputs.remove(key); } @@ -100,7 +107,7 @@ void PriorityMuxer::clearAll(bool forceClearAll) void PriorityMuxer::setCurrentTime(const int64_t& now) { - _currentPriority = LOWEST_PRIORITY; + _currentPriority = PriorityMuxer::LOWEST_PRIORITY; for (auto infoIt = _activeInputs.begin(); infoIt != _activeInputs.end();) { diff --git a/libsrc/utils/ImageResampler.cpp b/libsrc/utils/ImageResampler.cpp index 2c42941f..966e82dd 100755 --- a/libsrc/utils/ImageResampler.cpp +++ b/libsrc/utils/ImageResampler.cpp @@ -10,12 +10,10 @@ ImageResampler::ImageResampler() , _cropBottom(0) , _videoMode(VIDEO_2D) { - } ImageResampler::~ImageResampler() { - } void ImageResampler::setHorizontalPixelDecimation(int decimator) @@ -69,7 +67,7 @@ void ImageResampler::processImage(const uint8_t * data, int width, int height, i for (int yDest = 0, ySource = cropTop + _verticalDecimation/2; yDest < outputHeight; ySource += _verticalDecimation, ++yDest) { - for (int xDest = 0, xSource = cropLeft + _horizontalDecimation/2; xDest < outputWidth; xSource += _horizontalDecimation, ++xDest) + for (int xDest = 0, xSource = cropLeft + _horizontalDecimation/2; xDest < outputWidth; xSource += _horizontalDecimation, ++xDest) { ColorRgb & rgb = outputImage(xDest, yDest); diff --git a/src/hyperion-aml/CMakeLists.txt b/src/hyperion-aml/CMakeLists.txt index fe73267d..a5feeded 100644 --- a/src/hyperion-aml/CMakeLists.txt +++ b/src/hyperion-aml/CMakeLists.txt @@ -29,6 +29,7 @@ target_link_libraries(${PROJECT_NAME} hyperion-utils protoserver amlogic-grabber + framebuffer-grabber pthread Qt5::Core Qt5::Gui diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 5cbd2e1d..2a6763b5 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -410,7 +410,7 @@ void HyperionDaemon::createSystemFrameGrabber() QString type = grabberConfig["type"].toString("auto"); #endif - QFile amvideo("/dev/amvideo"); + // auto eval of type if ( type == "auto" ) { @@ -425,7 +425,7 @@ void HyperionDaemon::createSystemFrameGrabber() type = "dispmanx"; } // amlogic -> /dev/amvideo exists - else if ( amvideo.exists() ) + else if ( QFile::exists("/dev/amvideo") && ( QFile::exists("/dev/amvideocap0") || QFile::exists("/dev/ge2d") ) ) { type = "amlogic"; } @@ -446,7 +446,7 @@ void HyperionDaemon::createSystemFrameGrabber() if (type == "") { Info( _log, "screen capture device disabled"); grabberCompState = false; } else if (type == "framebuffer") createGrabberFramebuffer(grabberConfig); else if (type == "dispmanx") createGrabberDispmanx(); - else if (type == "amlogic") { createGrabberAmlogic(); createGrabberFramebuffer(grabberConfig); } + else if (type == "amlogic") createGrabberAmlogic(); else if (type == "osx") createGrabberOsx(grabberConfig); else if (type == "x11") createGrabberX11(grabberConfig); else { Warning( _log, "unknown framegrabber type '%s'", QSTRING_CSTR(type)); grabberCompState = false; } @@ -481,7 +481,8 @@ void HyperionDaemon::createGrabberDispmanx() void HyperionDaemon::createGrabberAmlogic() { #ifdef ENABLE_AMLOGIC - _amlGrabber = new AmlogicWrapper(_grabber_width, _grabber_height, _grabber_frequency, _grabber_priority-1); + _amlGrabber = new AmlogicWrapper(_grabber_width, _grabber_height, _grabber_frequency, _grabber_priority); + _amlGrabber->setCropping(_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom); QObject::connect(_amlGrabber, SIGNAL(emitImage(int, const Image&, const int)), _protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) );