From addff6f7efcd4db9dc27e1f33091c7687e75399c Mon Sep 17 00:00:00 2001 From: Markus <16664240+Paulchen-Panther@users.noreply.github.com> Date: Sun, 20 Mar 2022 14:42:21 +0100 Subject: [PATCH] Dynamic loading of the Dispmanx Grabber (#1440) * BCM dynamic loading * cleanup * better handle start of dispmanx * set GrabberWrapper pointer to null on exit * Update DispmanxFrameGrabber.cpp --- cmake/FindBCM.cmake | 40 +++- include/grabber/DispmanxFrameGrabber.h | 50 ++++- include/grabber/DispmanxFrameGrabberMock.h | 40 ---- include/grabber/DispmanxWrapper.h | 7 + libsrc/api/CMakeLists.txt | 11 - libsrc/api/JsonAPI.cpp | 9 +- libsrc/grabber/dispmanx/CMakeLists.txt | 29 ++- .../grabber/dispmanx/DispmanxFrameGrabber.cpp | 201 ++++++++++++------ .../dispmanx/DispmanxFrameGrabberMock.cpp | 109 ---------- libsrc/grabber/dispmanx/DispmanxWrapper.cpp | 10 +- libsrc/hyperion/GrabberWrapper.cpp | 6 +- src/hyperion-dispmanx/CMakeLists.txt | 12 +- src/hyperion-dispmanx/DispmanxWrapper.cpp | 14 +- src/hyperion-dispmanx/DispmanxWrapper.h | 2 + src/hyperiond/CMakeLists.txt | 7 - src/hyperiond/hyperiond.cpp | 18 +- 16 files changed, 278 insertions(+), 287 deletions(-) delete mode 100644 include/grabber/DispmanxFrameGrabberMock.h delete mode 100644 libsrc/grabber/dispmanx/DispmanxFrameGrabberMock.cpp diff --git a/cmake/FindBCM.cmake b/cmake/FindBCM.cmake index ea8d571c..9dc93cb4 100644 --- a/cmake/FindBCM.cmake +++ b/cmake/FindBCM.cmake @@ -2,21 +2,39 @@ # # This module defines # BCM_INCLUDE_DIR - The Broadcom VideoCore include directory -# BCM_LIBRARIES - The Broadcom VideoCore BCM_HOST library. +# BCM_LIBRARY - The Broadcom VideoCore BCM_HOST library. # BCM_FOUND - BCM_HOST is available # -FIND_PATH(BCM_INCLUDE_DIR - bcm_host.h +FIND_PATH(BCM_HOST_INCLUDE_DIR bcm_host.h + PATHS /usr/include /usr/local/include - /opt/vc/include) + /opt/vc/include +) -SET(BCM_INCLUDE_DIRS - ${BCM_INCLUDE_DIR} - ${BCM_INCLUDE_DIR}/interface/vcos/pthreads - ${BCM_INCLUDE_DIR}/interface/vmcs_host/linux) - -FIND_LIBRARY(BCM_LIBRARIES +FIND_LIBRARY(BCM_HOST_LIBRARY NAMES bcm_host - PATHS /usr/lib /usr/local/lib /opt/vc/lib) + PATHS + /usr/lib + /usr/local/lib + /opt/vc/lib +) + +if (BCM_HOST_INCLUDE_DIR AND BCM_HOST_LIBRARY) + set(BCM_FOUND TRUE) +endif (BCM_HOST_INCLUDE_DIR AND BCM_HOST_LIBRARY) + +if (BCM_FOUND) + SET (BCM_INCLUDE_DIR + ${BCM_HOST_INCLUDE_DIR} ${BCM_HOST_INCLUDE_DIR}/interface/vcos/pthreads/ + ${BCM_HOST_INCLUDE_DIR}/interface/vmcs_host/linux/ + ) + + SET (BCM_LIBRARY ${BCM_HOST_LIBRARY}) +else (BCM_FOUND) + SET (BCM_INCLUDE_DIR "") + SET (BCM_LIBRARY "") +endif (BCM_FOUND) + +mark_as_advanced(BCM_INCLUDE_DIR BCM_LIBRARY) diff --git a/include/grabber/DispmanxFrameGrabber.h b/include/grabber/DispmanxFrameGrabber.h index ace508ad..9d617ba9 100644 --- a/include/grabber/DispmanxFrameGrabber.h +++ b/include/grabber/DispmanxFrameGrabber.h @@ -1,18 +1,26 @@ #pragma once -// BCM includes -#ifdef PLATFORM_RPI - #pragma GCC system_header - #include -#else - #include -#endif - // Utils includes #include #include #include +// dynamic linking +#include + +// BCM includes +#ifdef BCM_FOUND + #include +#else + typedef int DISPMANX_DISPLAY_HANDLE_T; + typedef Image DISPMANX_RESOURCE; + typedef DISPMANX_RESOURCE* DISPMANX_RESOURCE_HANDLE_T; + typedef int VC_IMAGE_TYPE_T, DISPMANX_TRANSFORM_T; + const int VC_IMAGE_RGBA32 = 1, DISPMANX_SNAPSHOT_FILL = 1; + struct VC_RECT_T { int left, top, width, height; }; + struct DISPMANX_MODEINFO_T { int width, height; uint32_t display_num; }; +#endif + /// /// The DispmanxFrameGrabber is used for creating snapshots of the display (screenshots) with a downsized and scaled resolution. /// @@ -25,6 +33,18 @@ public: DispmanxFrameGrabber(); ~DispmanxFrameGrabber() override; + /// + /// @brief Determine if the bcm library is available. + /// + /// @return Zero, on success (i.e. library is present), else negative + /// + bool isAvailable(); + + /// + /// @brief Opens the input device. + /// + /// @return Zero, on success (i.e. device is ready), else negative + /// bool open(); /// @@ -71,6 +91,8 @@ private: /// void freeResources(); + void* _lib; + /// Handle to the display that is being captured DISPMANX_DISPLAY_HANDLE_T _vc_display; @@ -92,4 +114,16 @@ private: // rgba output buffer Image _image_rgba; + +private: + void (*wr_bcm_host_init)(void); + void (*wr_bcm_host_deinit)(void); + DISPMANX_DISPLAY_HANDLE_T (*wr_vc_dispmanx_display_open)(uint32_t device); + int (*wr_vc_dispmanx_display_close)(DISPMANX_DISPLAY_HANDLE_T display); + int (*wr_vc_dispmanx_display_get_info)(DISPMANX_DISPLAY_HANDLE_T display, DISPMANX_MODEINFO_T *pinfo); + DISPMANX_RESOURCE_HANDLE_T (*wr_vc_dispmanx_resource_create)(VC_IMAGE_TYPE_T type, uint32_t width, uint32_t height, uint32_t *native_image_handle); + int (*wr_vc_dispmanx_resource_delete)(DISPMANX_RESOURCE_HANDLE_T res); + int (*wr_vc_dispmanx_resource_read_data)(DISPMANX_RESOURCE_HANDLE_T handle, const VC_RECT_T *p_rect, void *dst_address, uint32_t dst_pitch); + void (*wr_vc_dispmanx_rect_set)(VC_RECT_T *rectangle, int left, int top, int width, int height); + int (*wr_vc_dispmanx_snapshot) (DISPMANX_DISPLAY_HANDLE_T display, DISPMANX_RESOURCE_HANDLE_T snapshot_resource, DISPMANX_TRANSFORM_T transform); }; diff --git a/include/grabber/DispmanxFrameGrabberMock.h b/include/grabber/DispmanxFrameGrabberMock.h deleted file mode 100644 index c5933207..00000000 --- a/include/grabber/DispmanxFrameGrabberMock.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#ifndef PLATFORM_RPI - -#include -#include -#include - -typedef int DISPMANX_DISPLAY_HANDLE_T; -typedef Image DISPMANX_RESOURCE; -typedef DISPMANX_RESOURCE* DISPMANX_RESOURCE_HANDLE_T; -const int VC_IMAGE_RGBA32 = 1; -const int DISPMANX_SNAPSHOT_FILL = 1; -typedef int DISPMANX_TRANSFORM_T; - - -struct DISPMANX_MODEINFO_T { - int width; - int height; - uint32_t display_num; -}; - -struct VC_RECT_T { - int left; - int top; - int width; - int height; -}; - -void bcm_host_init(); -void bcm_host_deinit(); -int vc_dispmanx_display_open(int); -void vc_dispmanx_display_close(int); -int vc_dispmanx_display_get_info(int, DISPMANX_MODEINFO_T *vc_info); -DISPMANX_RESOURCE_HANDLE_T vc_dispmanx_resource_create(int,int width,int height, uint32_t *); -void vc_dispmanx_resource_delete(DISPMANX_RESOURCE_HANDLE_T resource); -int vc_dispmanx_resource_read_data(DISPMANX_RESOURCE_HANDLE_T vc_resource, VC_RECT_T *rectangle, void* capturePtr, unsigned capturePitch); -void vc_dispmanx_rect_set(VC_RECT_T *rectangle, int left, int top, int width, int height); -int vc_dispmanx_snapshot(int, DISPMANX_RESOURCE_HANDLE_T resource, DISPMANX_TRANSFORM_T vc_flags); - -#endif diff --git a/include/grabber/DispmanxWrapper.h b/include/grabber/DispmanxWrapper.h index 3b4fb6bc..303391fa 100644 --- a/include/grabber/DispmanxWrapper.h +++ b/include/grabber/DispmanxWrapper.h @@ -25,6 +25,13 @@ public: bool screenInit(); + bool available = false; + + /// + /// Starts the grabber which produces led values with the specified update rate + /// + bool open() override; + public slots: /// /// Performs a single frame grab and computes the led-colors diff --git a/libsrc/api/CMakeLists.txt b/libsrc/api/CMakeLists.txt index 003e4bd7..3fd822ff 100644 --- a/libsrc/api/CMakeLists.txt +++ b/libsrc/api/CMakeLists.txt @@ -1,14 +1,3 @@ -# Find the BCM-package (VC control) -if (ENABLE_DISPMANX) - if ( "${PLATFORM}" MATCHES rpi) - find_package(BCM REQUIRED) - include_directories(${BCM_INCLUDE_DIRS}) - else() - set(BCM_INCLUDE_DIRS "") - set(BCM_LIBRARIES "") - endif() -endif (ENABLE_DISPMANX) - # Define the current source locations SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/api) diff --git a/libsrc/api/JsonAPI.cpp b/libsrc/api/JsonAPI.cpp index 67ba7317..1f39f6f0 100644 --- a/libsrc/api/JsonAPI.cpp +++ b/libsrc/api/JsonAPI.cpp @@ -1679,10 +1679,13 @@ void JsonAPI::handleInputSourceCommand(const QJsonObject& message, const QString #if defined(ENABLE_DISPMANX) DispmanxFrameGrabber* dispmanx = new DispmanxFrameGrabber(); - device = dispmanx->discover(params); - if (!device.isEmpty() ) + if (dispmanx->isAvailable()) { - videoInputs.append(device); + device = dispmanx->discover(params); + if (!device.isEmpty() ) + { + videoInputs.append(device); + } } delete dispmanx; #endif diff --git a/libsrc/grabber/dispmanx/CMakeLists.txt b/libsrc/grabber/dispmanx/CMakeLists.txt index 187de707..51292da1 100644 --- a/libsrc/grabber/dispmanx/CMakeLists.txt +++ b/libsrc/grabber/dispmanx/CMakeLists.txt @@ -1,22 +1,29 @@ # Find the BCM-package (VC control) -IF ( "${PLATFORM}" MATCHES rpi) - find_package(BCM REQUIRED) - include_directories(${BCM_INCLUDE_DIRS}) -ELSE() - SET(BCM_INCLUDE_DIRS "") - SET(BCM_LIBRARIES "") -ENDIF() +if( "${PLATFORM}" MATCHES rpi) + find_package(BCM) + if(BCM_FOUND) + add_definitions(-DBCM_FOUND) + endif() +else() + set(BCM_INCLUDE_DIR "") + set(BCM_LIBRARY "") +endif() # Define the current source locations -SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) -SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/dispmanx) +set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) +set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/dispmanx) FILE ( GLOB DispmanxGrabberSOURCES "${CURRENT_HEADER_DIR}/Dispmanx*.h" "${CURRENT_SOURCE_DIR}/*.h" "${CURRENT_SOURCE_DIR}/*.cpp" ) -add_library(dispmanx-grabber ${DispmanxGrabberSOURCES} ) +add_library(dispmanx-grabber ${DispmanxGrabberSOURCES}) +add_definitions(-DBCM_LIBRARY="${BCM_LIBRARY}") + +target_include_directories(dispmanx-grabber PUBLIC + ${BCM_INCLUDE_DIR} +) target_link_libraries(dispmanx-grabber hyperion ${QT_LIBRARIES} - ${BCM_LIBRARIES} + ${CMAKE_DL_LIBS} ) diff --git a/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp b/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp index 2a3f1783..b0a46fe4 100644 --- a/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp +++ b/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp @@ -11,9 +11,8 @@ // Constants namespace { -const bool verbose = false; -const int DEFAULT_DEVICE = 0; - + const bool verbose = false; + const int DEFAULT_DEVICE = 0; } //End of constants // Local includes @@ -21,24 +20,75 @@ const int DEFAULT_DEVICE = 0; DispmanxFrameGrabber::DispmanxFrameGrabber() : Grabber("DISPMANXGRABBER") - , _vc_display(0) - , _vc_resource(0) - , _vc_flags(DISPMANX_TRANSFORM_T(0)) - , _captureBuffer(new ColorRgba[0]) - , _captureBufferSize(0) - , _image_rgba() + , _lib(nullptr) + , _vc_display(0) + , _vc_resource(0) + , _vc_flags(DISPMANX_TRANSFORM_T(0)) + , _captureBuffer(new ColorRgba[0]) + , _captureBufferSize(0) + , _image_rgba() { _useImageResampler = true; - // Initialise BCM - bcm_host_init(); +} + +bool DispmanxFrameGrabber::isAvailable() +{ +#ifdef BCM_FOUND + void* bcm_host = dlopen(std::string("" BCM_LIBRARY).c_str(), RTLD_LAZY | RTLD_GLOBAL); + if (bcm_host != nullptr) + { + dlclose(bcm_host); + return true; + } + + return false; +#else + return false; +#endif +} + +bool DispmanxFrameGrabber::open() +{ +#ifdef BCM_FOUND + if (_lib != nullptr) + return true; + + std::string library = std::string("" BCM_LIBRARY); + _lib = dlopen(library.c_str(), RTLD_LAZY | RTLD_GLOBAL); + if (!_lib) + { + DebugIf(verbose, _log, "dlopen for %s failed, error = %s", library.c_str(), dlerror()); + return false; + } + + dlerror(); /* Clear any existing error */ + + if (!(*(void**)(&wr_bcm_host_init) = dlsym(_lib,"bcm_host_init"))) goto dlError; + if (!(*(void**)(&wr_bcm_host_deinit) = dlsym(_lib,"bcm_host_deinit"))) goto dlError; + if (!(*(void**)(&wr_vc_dispmanx_display_close) = dlsym(_lib,"vc_dispmanx_display_close"))) goto dlError; + if (!(*(void**)(&wr_vc_dispmanx_display_open) = dlsym(_lib,"vc_dispmanx_display_open"))) goto dlError; + if (!(*(void**)(&wr_vc_dispmanx_display_get_info) = dlsym(_lib, "vc_dispmanx_display_get_info"))) goto dlError; + if (!(*(void**)(&wr_vc_dispmanx_resource_create) = dlsym(_lib,"vc_dispmanx_resource_create"))) goto dlError; + if (!(*(void**)(&wr_vc_dispmanx_resource_delete) = dlsym(_lib, "vc_dispmanx_resource_delete"))) goto dlError; + if (!(*(void**)(&wr_vc_dispmanx_resource_read_data) = dlsym(_lib, "vc_dispmanx_resource_read_data"))) goto dlError; + if (!(*(void**)(&wr_vc_dispmanx_rect_set) = dlsym(_lib, "vc_dispmanx_rect_set"))) goto dlError; + if (!(*(void**)(&wr_vc_dispmanx_snapshot) = dlsym(_lib, "vc_dispmanx_snapshot"))) goto dlError; + + wr_bcm_host_init(); + return true; + +dlError: + DebugIf(verbose, _log, "dlsym for %s::%s failed, error = %s", library.c_str(), dlerror()); + dlclose(_lib); + return false; +#else + return false; +#endif } DispmanxFrameGrabber::~DispmanxFrameGrabber() { freeResources(); - - // De-init BCM - bcm_host_deinit(); } bool DispmanxFrameGrabber::setupScreen() @@ -66,22 +116,32 @@ bool DispmanxFrameGrabber::setupScreen() void DispmanxFrameGrabber::freeResources() { delete[] _captureBuffer; - // Clean up resources - vc_dispmanx_resource_delete(_vc_resource); + + if (_lib != nullptr) + { + // Clean up resources + wr_vc_dispmanx_resource_delete(_vc_resource); + // De-init BCM + wr_bcm_host_deinit(); + + dlclose(_lib); + _lib = nullptr; + } } bool DispmanxFrameGrabber::setWidthHeight(int width, int height) { bool rc = false; - if(Grabber::setWidthHeight(width, height)) + if(open() && Grabber::setWidthHeight(width, height)) { - if(_vc_resource != 0) { - vc_dispmanx_resource_delete(_vc_resource); + if(_vc_resource != 0) + { + wr_vc_dispmanx_resource_delete(_vc_resource); } Debug(_log,"Create the resources for capturing image"); uint32_t vc_nativeImageHandle; - _vc_resource = vc_dispmanx_resource_create( + _vc_resource = wr_vc_dispmanx_resource_create( VC_IMAGE_RGBA32, width, height, @@ -91,7 +151,7 @@ bool DispmanxFrameGrabber::setWidthHeight(int width, int height) if (_vc_resource != 0) { Debug(_log,"Define the capture rectangle with the same size"); - vc_dispmanx_rect_set(&_rectangle, 0, 0, width, height); + wr_vc_dispmanx_rect_set(&_rectangle, 0, 0, width, height); rc = true; } } @@ -137,7 +197,7 @@ int DispmanxFrameGrabber::grabFrame(Image & image) } // Open the connection to the display - _vc_display = vc_dispmanx_display_open(DEFAULT_DEVICE); + _vc_display = wr_vc_dispmanx_display_open(DEFAULT_DEVICE); if (_vc_display < 0) { Error(_log, "Cannot open display: %d", DEFAULT_DEVICE); @@ -146,7 +206,7 @@ int DispmanxFrameGrabber::grabFrame(Image & image) else { // Create the snapshot (incl down-scaling) - int ret = vc_dispmanx_snapshot(_vc_display, _vc_resource, _vc_flags); + int ret = wr_vc_dispmanx_snapshot(_vc_display, _vc_resource, _vc_flags); if (ret < 0) { Error(_log, "Snapshot failed: %d", ret); @@ -180,7 +240,7 @@ int DispmanxFrameGrabber::grabFrame(Image & image) capturePtr = &_captureBuffer[0]; } - ret = vc_dispmanx_resource_read_data(_vc_resource, &_rectangle, capturePtr, capturePitch); + ret = wr_vc_dispmanx_resource_read_data(_vc_resource, &_rectangle, capturePtr, capturePitch); if (ret < 0) { Error(_log, "vc_dispmanx_resource_read_data failed: %d", ret); @@ -196,7 +256,8 @@ int DispmanxFrameGrabber::grabFrame(Image & image) image); } } - vc_dispmanx_display_close(_vc_display); + + wr_vc_dispmanx_display_close(_vc_display); } } return rc; @@ -207,12 +268,12 @@ QSize DispmanxFrameGrabber::getScreenSize(int device) const int width (0); int height(0); - DISPMANX_DISPLAY_HANDLE_T vc_display = vc_dispmanx_display_open(device); + DISPMANX_DISPLAY_HANDLE_T vc_display = wr_vc_dispmanx_display_open(device); if ( vc_display > 0) { // Obtain the display information DISPMANX_MODEINFO_T vc_info; - int result = vc_dispmanx_display_get_info(vc_display, &vc_info); + int result = wr_vc_dispmanx_display_get_info(vc_display, &vc_info); (void)result; if (result == 0) @@ -223,7 +284,7 @@ QSize DispmanxFrameGrabber::getScreenSize(int device) const DebugIf(verbose, _log, "Display found with resolution: %dx%d", width, height); } // Close the display - vc_dispmanx_display_close(vc_display); + wr_vc_dispmanx_display_close(vc_display); } return QSize(width, height); @@ -234,61 +295,63 @@ QJsonObject DispmanxFrameGrabber::discover(const QJsonObject& params) DebugIf(verbose, _log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); QJsonObject inputsDiscovered; - - int deviceIdx (DEFAULT_DEVICE); - QJsonArray video_inputs; - - QSize screenSize = getScreenSize(deviceIdx); - if ( !screenSize.isEmpty() ) + if (open()) { - QJsonArray fps = { 1, 5, 10, 15, 20, 25, 30, 40, 50, 60 }; + int deviceIdx (DEFAULT_DEVICE); + QJsonArray video_inputs; - QJsonObject in; + QSize screenSize = getScreenSize(deviceIdx); + if ( !screenSize.isEmpty() ) + { + QJsonArray fps = { 1, 5, 10, 15, 20, 25, 30, 40, 50, 60 }; - QString displayName; - displayName = QString("Screen:%1").arg(deviceIdx); + QJsonObject in; - in["name"] = displayName; - in["inputIdx"] = deviceIdx; + QString displayName; + displayName = QString("Screen:%1").arg(deviceIdx); - QJsonArray formats; - QJsonObject format; + in["name"] = displayName; + in["inputIdx"] = deviceIdx; - QJsonArray resolutionArray; + QJsonArray formats; + QJsonObject format; - QJsonObject resolution; + QJsonArray resolutionArray; - resolution["width"] = screenSize.width(); - resolution["height"] = screenSize.height(); - resolution["fps"] = fps; + QJsonObject resolution; - resolutionArray.append(resolution); + resolution["width"] = screenSize.width(); + resolution["height"] = screenSize.height(); + resolution["fps"] = fps; - format["resolutions"] = resolutionArray; - formats.append(format); + resolutionArray.append(resolution); - in["formats"] = formats; - video_inputs.append(in); - } + format["resolutions"] = resolutionArray; + formats.append(format); - if (!video_inputs.isEmpty()) - { - inputsDiscovered["device"] = "dispmanx"; - inputsDiscovered["device_name"] = "DispmanX"; - inputsDiscovered["type"] = "screen"; - inputsDiscovered["video_inputs"] = video_inputs; + in["formats"] = formats; + video_inputs.append(in); + } - QJsonObject defaults, video_inputs_default, resolution_default; - resolution_default["fps"] = _fps; - video_inputs_default["resolution"] = resolution_default; - video_inputs_default["inputIdx"] = 0; - defaults["video_input"] = video_inputs_default; - inputsDiscovered["default"] = defaults; - } + if (!video_inputs.isEmpty()) + { + inputsDiscovered["device"] = "dispmanx"; + inputsDiscovered["device_name"] = "DispmanX"; + inputsDiscovered["type"] = "screen"; + inputsDiscovered["video_inputs"] = video_inputs; - if (inputsDiscovered.isEmpty()) - { - DebugIf(verbose, _log, "No displays found to capture from!"); + QJsonObject defaults, video_inputs_default, resolution_default; + resolution_default["fps"] = _fps; + video_inputs_default["resolution"] = resolution_default; + video_inputs_default["inputIdx"] = 0; + defaults["video_input"] = video_inputs_default; + inputsDiscovered["default"] = defaults; + } + + if (inputsDiscovered.isEmpty()) + { + DebugIf(verbose, _log, "No displays found to capture from!"); + } } DebugIf(verbose, _log, "device: [%s]", QString(QJsonDocument(inputsDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData()); diff --git a/libsrc/grabber/dispmanx/DispmanxFrameGrabberMock.cpp b/libsrc/grabber/dispmanx/DispmanxFrameGrabberMock.cpp deleted file mode 100644 index 5c27ec18..00000000 --- a/libsrc/grabber/dispmanx/DispmanxFrameGrabberMock.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef PLATFORM_RPI - -#include - -unsigned __bcm_frame_counter = 0; -const int __screenWidth = 800; -const int __screenHeight = 600; -const int __display_num = 0; - -void bcm_host_init() -{ -} - -void bcm_host_deinit() -{ -} - -int vc_dispmanx_display_open(int) -{ - return 1; -} - -void vc_dispmanx_display_close(int) -{ -} - -int vc_dispmanx_display_get_info(int, DISPMANX_MODEINFO_T *vc_info) -{ - vc_info->width = __screenWidth; - vc_info->height = __screenHeight; - vc_info->display_num = __display_num; - return 0; -} - -DISPMANX_RESOURCE_HANDLE_T vc_dispmanx_resource_create(int, int width, int height, uint32_t *) -{ - return new DISPMANX_RESOURCE(width,height); -} - -void vc_dispmanx_resource_delete(DISPMANX_RESOURCE_HANDLE_T resource) -{ - delete resource; -} - -int vc_dispmanx_resource_read_data(DISPMANX_RESOURCE_HANDLE_T resource, VC_RECT_T *rectangle, void* capturePtr, unsigned capturePitch) -{ - memcpy(capturePtr, resource->memptr(), resource->height()*resource->width() * sizeof(ColorRgba)); - return 0; -} - -void vc_dispmanx_rect_set(VC_RECT_T *rectangle, int left, int top, int width, int height) -{ - rectangle->width = width; - rectangle->height = height; - rectangle->left = left; - rectangle->top = top; -} - -int vc_dispmanx_snapshot(DISPMANX_DISPLAY_HANDLE_T /*display*/, DISPMANX_RESOURCE_HANDLE_T resource, DISPMANX_TRANSFORM_T /*vc_flags*/) -{ - __bcm_frame_counter++; - if (__bcm_frame_counter > 100) - { - __bcm_frame_counter = 0; - } - - ColorRgba color[4] = {ColorRgba::RED, ColorRgba::BLUE, ColorRgba::GREEN, ColorRgba::WHITE}; - if (__bcm_frame_counter < 25) - { - color[0] = ColorRgba::WHITE; - color[1] = ColorRgba::RED; - color[2] = ColorRgba::BLUE; - color[3] = ColorRgba::GREEN; - } - else if(__bcm_frame_counter < 50) - { - color[1] = ColorRgba::WHITE; - color[2] = ColorRgba::RED; - color[3] = ColorRgba::BLUE; - color[0] = ColorRgba::GREEN; - } - else if(__bcm_frame_counter < 75) - { - color[2] = ColorRgba::WHITE; - color[3] = ColorRgba::RED; - color[0] = ColorRgba::BLUE; - color[1] = ColorRgba::GREEN; - } - - unsigned w = resource->width(); - unsigned h = resource->height(); - for (unsigned y=0; y= h/2) id = 2; - if (x >= w/2 && y < h/2) id = 3; - - resource->memptr()[y*w + x] = color[id]; - } - } - - return 0; -} - -#endif - diff --git a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp index 915a4bdc..6ffe3354 100644 --- a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp +++ b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp @@ -6,7 +6,15 @@ DispmanxWrapper::DispmanxWrapper( int updateRate_Hz, : GrabberWrapper("Dispmanx", &_grabber, updateRate_Hz) , _grabber() { - _grabber.setPixelDecimation(pixelDecimation); + if (available = _grabber.isAvailable()) + { + _grabber.setPixelDecimation(pixelDecimation); + } +} + +bool DispmanxWrapper::open() +{ + return _grabber.open(); } void DispmanxWrapper::action() diff --git a/libsrc/hyperion/GrabberWrapper.cpp b/libsrc/hyperion/GrabberWrapper.cpp index eb4a3a62..a31e0339 100644 --- a/libsrc/hyperion/GrabberWrapper.cpp +++ b/libsrc/hyperion/GrabberWrapper.cpp @@ -48,7 +48,7 @@ GrabberWrapper::GrabberWrapper(const QString& grabberName, Grabber * ggrabber, i GrabberWrapper::~GrabberWrapper() { - Debug(_log,"Close grabber: %s", QSTRING_CSTR(_grabberName)); + GrabberWrapper::instance = nullptr; } bool GrabberWrapper::start() @@ -190,7 +190,7 @@ void GrabberWrapper::handleSettingsUpdate(settings::type type, const QJsonDocume { // extract settings const QJsonObject& obj = config.object(); - + // save current state bool isEnabled = getSysGrabberState(); @@ -218,7 +218,7 @@ void GrabberWrapper::handleSettingsUpdate(settings::type type, const QJsonDocume _ggrabber->setFramerate(obj["fps"].toInt(DEFAULT_RATE_HZ)); // eval new update time updateTimer(_ggrabber->getUpdateInterval()); - + // start if current state is not true if (!isEnabled) { diff --git a/src/hyperion-dispmanx/CMakeLists.txt b/src/hyperion-dispmanx/CMakeLists.txt index bc96cb35..bcf4b489 100644 --- a/src/hyperion-dispmanx/CMakeLists.txt +++ b/src/hyperion-dispmanx/CMakeLists.txt @@ -3,16 +3,8 @@ project(hyperion-dispmanx) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network Widgets REQUIRED) -IF ( "${PLATFORM}" MATCHES rpi) - find_package(BCM REQUIRED) -ELSE() - SET(BCM_INCLUDE_DIRS "") - SET(BCM_LIBRARIES "") -ENDIF() - include_directories( ${CMAKE_CURRENT_BINARY_DIR}/../../libsrc/flatbufserver - ${BCM_INCLUDE_DIRS} ${FLATBUFFERS_INCLUDE_DIRS} ) @@ -30,13 +22,15 @@ add_executable( ${PROJECT_NAME} ${Hyperion_Dispmanx_SOURCES} ) +SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-rdynamic") +SET(CMAKE_C_FLAGS ${CMAKE_CXX_FLAGS} "-rdynamic") + target_link_libraries( ${PROJECT_NAME} commandline hyperion-utils flatbufconnect flatbuffers dispmanx-grabber - ${Dispmanx_LIBRARIES} ssdp Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network diff --git a/src/hyperion-dispmanx/DispmanxWrapper.cpp b/src/hyperion-dispmanx/DispmanxWrapper.cpp index 89b91cec..95aabf84 100644 --- a/src/hyperion-dispmanx/DispmanxWrapper.cpp +++ b/src/hyperion-dispmanx/DispmanxWrapper.cpp @@ -27,6 +27,11 @@ const Image & DispmanxWrapper::getScreenshot() return _screenshot; } +bool DispmanxWrapper::open() +{ + return _grabber.open(); +} + void DispmanxWrapper::start() { _timer.start(); @@ -39,13 +44,16 @@ void DispmanxWrapper::stop() bool DispmanxWrapper::screenInit() { - return _grabber.setupScreen(); + return (open() && _grabber.setupScreen()); } void DispmanxWrapper::capture() { - _grabber.grabFrame(_screenshot); - emit sig_screenshot(_screenshot); + if ( open() ) + { + _grabber.grabFrame(_screenshot); + emit sig_screenshot(_screenshot); + } } void DispmanxWrapper::setVideoMode(VideoMode mode) diff --git a/src/hyperion-dispmanx/DispmanxWrapper.h b/src/hyperion-dispmanx/DispmanxWrapper.h index 15e489a6..e02e2c5f 100644 --- a/src/hyperion-dispmanx/DispmanxWrapper.h +++ b/src/hyperion-dispmanx/DispmanxWrapper.h @@ -16,6 +16,8 @@ public: ); const Image & getScreenshot(); + + bool open(); /// /// Starts the timed capturing of screenshots diff --git a/src/hyperiond/CMakeLists.txt b/src/hyperiond/CMakeLists.txt index 2473b053..b6c83f72 100644 --- a/src/hyperiond/CMakeLists.txt +++ b/src/hyperiond/CMakeLists.txt @@ -90,13 +90,6 @@ if (ENABLE_AMLOGIC) endif(ENABLE_AMLOGIC) if (ENABLE_DISPMANX) - IF ( "${PLATFORM}" MATCHES rpi) - find_package(BCM REQUIRED) - include_directories(${BCM_INCLUDE_DIRS}) - ELSE() - SET(BCM_INCLUDE_DIRS "") - SET(BCM_LIBRARIES "") - ENDIF() target_link_libraries(${PROJECT_NAME} dispmanx-grabber) endif (ENABLE_DISPMANX) diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index da63d678..ddc235f7 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -264,7 +264,8 @@ void HyperionDaemon::freeObjects() #endif delete _amlGrabber; - delete _dispmanx; + if (_dispmanx != nullptr) + delete _dispmanx; delete _fbGrabber; delete _osxGrabber; delete _qtGrabber; @@ -522,9 +523,13 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs { createGrabberDispmanx(grabberConfig); } + #ifdef ENABLE_DISPMANX + if (_dispmanx != nullptr) + { _dispmanx->handleSettingsUpdate(settings::SYSTEMCAPTURE, getSetting(settings::SYSTEMCAPTURE)); _dispmanx->tryStart(); + } #endif } else if (type == "amlogic") @@ -644,7 +649,16 @@ void HyperionDaemon::createGrabberDispmanx(const QJsonObject& /*grabberConfig*/) _dispmanx = new DispmanxWrapper( _grabber_frequency, _grabber_pixelDecimation - ); + ); + + if (!_dispmanx->available) + { + delete _dispmanx; + _dispmanx = nullptr; + Debug(_log, "The dispmanx framegrabber is not supported on this platform"); + return; + } + _dispmanx->setCropping(_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom); // connect to HyperionDaemon signal