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
This commit is contained in:
Markus 2022-03-20 14:42:21 +01:00 committed by GitHub
parent f32db90c12
commit addff6f7ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 278 additions and 287 deletions

View File

@ -2,21 +2,39 @@
# #
# This module defines # This module defines
# BCM_INCLUDE_DIR - The Broadcom VideoCore include directory # 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 # BCM_FOUND - BCM_HOST is available
# #
FIND_PATH(BCM_INCLUDE_DIR FIND_PATH(BCM_HOST_INCLUDE_DIR bcm_host.h
bcm_host.h PATHS
/usr/include /usr/include
/usr/local/include /usr/local/include
/opt/vc/include) /opt/vc/include
)
SET(BCM_INCLUDE_DIRS FIND_LIBRARY(BCM_HOST_LIBRARY
${BCM_INCLUDE_DIR}
${BCM_INCLUDE_DIR}/interface/vcos/pthreads
${BCM_INCLUDE_DIR}/interface/vmcs_host/linux)
FIND_LIBRARY(BCM_LIBRARIES
NAMES bcm_host 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)

View File

@ -1,18 +1,26 @@
#pragma once #pragma once
// BCM includes
#ifdef PLATFORM_RPI
#pragma GCC system_header
#include <bcm_host.h>
#else
#include <grabber/DispmanxFrameGrabberMock.h>
#endif
// Utils includes // Utils includes
#include <utils/Image.h> #include <utils/Image.h>
#include <utils/ColorRgba.h> #include <utils/ColorRgba.h>
#include <hyperion/Grabber.h> #include <hyperion/Grabber.h>
// dynamic linking
#include <dlfcn.h>
// BCM includes
#ifdef BCM_FOUND
#include <bcm_host.h>
#else
typedef int DISPMANX_DISPLAY_HANDLE_T;
typedef Image<ColorRgba> 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. /// The DispmanxFrameGrabber is used for creating snapshots of the display (screenshots) with a downsized and scaled resolution.
/// ///
@ -25,6 +33,18 @@ public:
DispmanxFrameGrabber(); DispmanxFrameGrabber();
~DispmanxFrameGrabber() override; ~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(); bool open();
/// ///
@ -71,6 +91,8 @@ private:
/// ///
void freeResources(); void freeResources();
void* _lib;
/// Handle to the display that is being captured /// Handle to the display that is being captured
DISPMANX_DISPLAY_HANDLE_T _vc_display; DISPMANX_DISPLAY_HANDLE_T _vc_display;
@ -92,4 +114,16 @@ private:
// rgba output buffer // rgba output buffer
Image<ColorRgba> _image_rgba; Image<ColorRgba> _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);
}; };

View File

@ -1,40 +0,0 @@
#pragma once
#ifndef PLATFORM_RPI
#include <QRect>
#include <utils/Image.h>
#include <utils/ColorRgba.h>
typedef int DISPMANX_DISPLAY_HANDLE_T;
typedef Image<ColorRgba> 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

View File

@ -25,6 +25,13 @@ public:
bool screenInit(); bool screenInit();
bool available = false;
///
/// Starts the grabber which produces led values with the specified update rate
///
bool open() override;
public slots: public slots:
/// ///
/// Performs a single frame grab and computes the led-colors /// Performs a single frame grab and computes the led-colors

View File

@ -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 # Define the current source locations
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/api) SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/api)

View File

@ -1679,10 +1679,13 @@ void JsonAPI::handleInputSourceCommand(const QJsonObject& message, const QString
#if defined(ENABLE_DISPMANX) #if defined(ENABLE_DISPMANX)
DispmanxFrameGrabber* dispmanx = new DispmanxFrameGrabber(); DispmanxFrameGrabber* dispmanx = new DispmanxFrameGrabber();
device = dispmanx->discover(params); if (dispmanx->isAvailable())
if (!device.isEmpty() )
{ {
videoInputs.append(device); device = dispmanx->discover(params);
if (!device.isEmpty() )
{
videoInputs.append(device);
}
} }
delete dispmanx; delete dispmanx;
#endif #endif

View File

@ -1,22 +1,29 @@
# Find the BCM-package (VC control) # Find the BCM-package (VC control)
IF ( "${PLATFORM}" MATCHES rpi) if( "${PLATFORM}" MATCHES rpi)
find_package(BCM REQUIRED) find_package(BCM)
include_directories(${BCM_INCLUDE_DIRS}) if(BCM_FOUND)
ELSE() add_definitions(-DBCM_FOUND)
SET(BCM_INCLUDE_DIRS "") endif()
SET(BCM_LIBRARIES "") else()
ENDIF() set(BCM_INCLUDE_DIR "")
set(BCM_LIBRARY "")
endif()
# Define the current source locations # Define the current source locations
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber)
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/dispmanx) 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" ) 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 target_link_libraries(dispmanx-grabber
hyperion hyperion
${QT_LIBRARIES} ${QT_LIBRARIES}
${BCM_LIBRARIES} ${CMAKE_DL_LIBS}
) )

View File

@ -11,9 +11,8 @@
// Constants // Constants
namespace { namespace {
const bool verbose = false; const bool verbose = false;
const int DEFAULT_DEVICE = 0; const int DEFAULT_DEVICE = 0;
} //End of constants } //End of constants
// Local includes // Local includes
@ -21,24 +20,75 @@ const int DEFAULT_DEVICE = 0;
DispmanxFrameGrabber::DispmanxFrameGrabber() DispmanxFrameGrabber::DispmanxFrameGrabber()
: Grabber("DISPMANXGRABBER") : Grabber("DISPMANXGRABBER")
, _vc_display(0) , _lib(nullptr)
, _vc_resource(0) , _vc_display(0)
, _vc_flags(DISPMANX_TRANSFORM_T(0)) , _vc_resource(0)
, _captureBuffer(new ColorRgba[0]) , _vc_flags(DISPMANX_TRANSFORM_T(0))
, _captureBufferSize(0) , _captureBuffer(new ColorRgba[0])
, _image_rgba() , _captureBufferSize(0)
, _image_rgba()
{ {
_useImageResampler = true; _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() DispmanxFrameGrabber::~DispmanxFrameGrabber()
{ {
freeResources(); freeResources();
// De-init BCM
bcm_host_deinit();
} }
bool DispmanxFrameGrabber::setupScreen() bool DispmanxFrameGrabber::setupScreen()
@ -66,22 +116,32 @@ bool DispmanxFrameGrabber::setupScreen()
void DispmanxFrameGrabber::freeResources() void DispmanxFrameGrabber::freeResources()
{ {
delete[] _captureBuffer; 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 DispmanxFrameGrabber::setWidthHeight(int width, int height)
{ {
bool rc = false; bool rc = false;
if(Grabber::setWidthHeight(width, height)) if(open() && Grabber::setWidthHeight(width, height))
{ {
if(_vc_resource != 0) { if(_vc_resource != 0)
vc_dispmanx_resource_delete(_vc_resource); {
wr_vc_dispmanx_resource_delete(_vc_resource);
} }
Debug(_log,"Create the resources for capturing image"); Debug(_log,"Create the resources for capturing image");
uint32_t vc_nativeImageHandle; uint32_t vc_nativeImageHandle;
_vc_resource = vc_dispmanx_resource_create( _vc_resource = wr_vc_dispmanx_resource_create(
VC_IMAGE_RGBA32, VC_IMAGE_RGBA32,
width, width,
height, height,
@ -91,7 +151,7 @@ bool DispmanxFrameGrabber::setWidthHeight(int width, int height)
if (_vc_resource != 0) if (_vc_resource != 0)
{ {
Debug(_log,"Define the capture rectangle with the same size"); 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; rc = true;
} }
} }
@ -137,7 +197,7 @@ int DispmanxFrameGrabber::grabFrame(Image<ColorRgb> & image)
} }
// Open the connection to the display // 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) if (_vc_display < 0)
{ {
Error(_log, "Cannot open display: %d", DEFAULT_DEVICE); Error(_log, "Cannot open display: %d", DEFAULT_DEVICE);
@ -146,7 +206,7 @@ int DispmanxFrameGrabber::grabFrame(Image<ColorRgb> & image)
else { else {
// Create the snapshot (incl down-scaling) // 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) if (ret < 0)
{ {
Error(_log, "Snapshot failed: %d", ret); Error(_log, "Snapshot failed: %d", ret);
@ -180,7 +240,7 @@ int DispmanxFrameGrabber::grabFrame(Image<ColorRgb> & image)
capturePtr = &_captureBuffer[0]; 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) if (ret < 0)
{ {
Error(_log, "vc_dispmanx_resource_read_data failed: %d", ret); Error(_log, "vc_dispmanx_resource_read_data failed: %d", ret);
@ -196,7 +256,8 @@ int DispmanxFrameGrabber::grabFrame(Image<ColorRgb> & image)
image); image);
} }
} }
vc_dispmanx_display_close(_vc_display);
wr_vc_dispmanx_display_close(_vc_display);
} }
} }
return rc; return rc;
@ -207,12 +268,12 @@ QSize DispmanxFrameGrabber::getScreenSize(int device) const
int width (0); int width (0);
int height(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) if ( vc_display > 0)
{ {
// Obtain the display information // Obtain the display information
DISPMANX_MODEINFO_T vc_info; 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; (void)result;
if (result == 0) if (result == 0)
@ -223,7 +284,7 @@ QSize DispmanxFrameGrabber::getScreenSize(int device) const
DebugIf(verbose, _log, "Display found with resolution: %dx%d", width, height); DebugIf(verbose, _log, "Display found with resolution: %dx%d", width, height);
} }
// Close the display // Close the display
vc_dispmanx_display_close(vc_display); wr_vc_dispmanx_display_close(vc_display);
} }
return QSize(width, height); 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()); DebugIf(verbose, _log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData());
QJsonObject inputsDiscovered; QJsonObject inputsDiscovered;
if (open())
int deviceIdx (DEFAULT_DEVICE);
QJsonArray video_inputs;
QSize screenSize = getScreenSize(deviceIdx);
if ( !screenSize.isEmpty() )
{ {
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; QJsonObject in;
displayName = QString("Screen:%1").arg(deviceIdx);
in["name"] = displayName; QString displayName;
in["inputIdx"] = deviceIdx; displayName = QString("Screen:%1").arg(deviceIdx);
QJsonArray formats; in["name"] = displayName;
QJsonObject format; in["inputIdx"] = deviceIdx;
QJsonArray resolutionArray; QJsonArray formats;
QJsonObject format;
QJsonObject resolution; QJsonArray resolutionArray;
resolution["width"] = screenSize.width(); QJsonObject resolution;
resolution["height"] = screenSize.height();
resolution["fps"] = fps;
resolutionArray.append(resolution); resolution["width"] = screenSize.width();
resolution["height"] = screenSize.height();
resolution["fps"] = fps;
format["resolutions"] = resolutionArray; resolutionArray.append(resolution);
formats.append(format);
in["formats"] = formats; format["resolutions"] = resolutionArray;
video_inputs.append(in); formats.append(format);
}
if (!video_inputs.isEmpty()) in["formats"] = formats;
{ video_inputs.append(in);
inputsDiscovered["device"] = "dispmanx"; }
inputsDiscovered["device_name"] = "DispmanX";
inputsDiscovered["type"] = "screen";
inputsDiscovered["video_inputs"] = video_inputs;
QJsonObject defaults, video_inputs_default, resolution_default; if (!video_inputs.isEmpty())
resolution_default["fps"] = _fps; {
video_inputs_default["resolution"] = resolution_default; inputsDiscovered["device"] = "dispmanx";
video_inputs_default["inputIdx"] = 0; inputsDiscovered["device_name"] = "DispmanX";
defaults["video_input"] = video_inputs_default; inputsDiscovered["type"] = "screen";
inputsDiscovered["default"] = defaults; inputsDiscovered["video_inputs"] = video_inputs;
}
if (inputsDiscovered.isEmpty()) QJsonObject defaults, video_inputs_default, resolution_default;
{ resolution_default["fps"] = _fps;
DebugIf(verbose, _log, "No displays found to capture from!"); 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()); DebugIf(verbose, _log, "device: [%s]", QString(QJsonDocument(inputsDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData());

View File

@ -1,109 +0,0 @@
#ifndef PLATFORM_RPI
#include <grabber/DispmanxFrameGrabberMock.h>
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; y++)
{
for (unsigned x=0; x<w; x++)
{
unsigned id = 0;
if (x < w/2 && y < h/2) id = 1;
if (x < w/2 && y >= h/2) id = 2;
if (x >= w/2 && y < h/2) id = 3;
resource->memptr()[y*w + x] = color[id];
}
}
return 0;
}
#endif

View File

@ -6,7 +6,15 @@ DispmanxWrapper::DispmanxWrapper( int updateRate_Hz,
: GrabberWrapper("Dispmanx", &_grabber, updateRate_Hz) : GrabberWrapper("Dispmanx", &_grabber, updateRate_Hz)
, _grabber() , _grabber()
{ {
_grabber.setPixelDecimation(pixelDecimation); if (available = _grabber.isAvailable())
{
_grabber.setPixelDecimation(pixelDecimation);
}
}
bool DispmanxWrapper::open()
{
return _grabber.open();
} }
void DispmanxWrapper::action() void DispmanxWrapper::action()

View File

@ -48,7 +48,7 @@ GrabberWrapper::GrabberWrapper(const QString& grabberName, Grabber * ggrabber, i
GrabberWrapper::~GrabberWrapper() GrabberWrapper::~GrabberWrapper()
{ {
Debug(_log,"Close grabber: %s", QSTRING_CSTR(_grabberName)); GrabberWrapper::instance = nullptr;
} }
bool GrabberWrapper::start() bool GrabberWrapper::start()
@ -190,7 +190,7 @@ void GrabberWrapper::handleSettingsUpdate(settings::type type, const QJsonDocume
{ {
// extract settings // extract settings
const QJsonObject& obj = config.object(); const QJsonObject& obj = config.object();
// save current state // save current state
bool isEnabled = getSysGrabberState(); bool isEnabled = getSysGrabberState();
@ -218,7 +218,7 @@ void GrabberWrapper::handleSettingsUpdate(settings::type type, const QJsonDocume
_ggrabber->setFramerate(obj["fps"].toInt(DEFAULT_RATE_HZ)); _ggrabber->setFramerate(obj["fps"].toInt(DEFAULT_RATE_HZ));
// eval new update time // eval new update time
updateTimer(_ggrabber->getUpdateInterval()); updateTimer(_ggrabber->getUpdateInterval());
// start if current state is not true // start if current state is not true
if (!isEnabled) if (!isEnabled)
{ {

View File

@ -3,16 +3,8 @@ project(hyperion-dispmanx)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network Widgets REQUIRED) 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( include_directories(
${CMAKE_CURRENT_BINARY_DIR}/../../libsrc/flatbufserver ${CMAKE_CURRENT_BINARY_DIR}/../../libsrc/flatbufserver
${BCM_INCLUDE_DIRS}
${FLATBUFFERS_INCLUDE_DIRS} ${FLATBUFFERS_INCLUDE_DIRS}
) )
@ -30,13 +22,15 @@ add_executable( ${PROJECT_NAME}
${Hyperion_Dispmanx_SOURCES} ${Hyperion_Dispmanx_SOURCES}
) )
SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-rdynamic")
SET(CMAKE_C_FLAGS ${CMAKE_CXX_FLAGS} "-rdynamic")
target_link_libraries( ${PROJECT_NAME} target_link_libraries( ${PROJECT_NAME}
commandline commandline
hyperion-utils hyperion-utils
flatbufconnect flatbufconnect
flatbuffers flatbuffers
dispmanx-grabber dispmanx-grabber
${Dispmanx_LIBRARIES}
ssdp ssdp
Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Network

View File

@ -27,6 +27,11 @@ const Image<ColorRgb> & DispmanxWrapper::getScreenshot()
return _screenshot; return _screenshot;
} }
bool DispmanxWrapper::open()
{
return _grabber.open();
}
void DispmanxWrapper::start() void DispmanxWrapper::start()
{ {
_timer.start(); _timer.start();
@ -39,13 +44,16 @@ void DispmanxWrapper::stop()
bool DispmanxWrapper::screenInit() bool DispmanxWrapper::screenInit()
{ {
return _grabber.setupScreen(); return (open() && _grabber.setupScreen());
} }
void DispmanxWrapper::capture() void DispmanxWrapper::capture()
{ {
_grabber.grabFrame(_screenshot); if ( open() )
emit sig_screenshot(_screenshot); {
_grabber.grabFrame(_screenshot);
emit sig_screenshot(_screenshot);
}
} }
void DispmanxWrapper::setVideoMode(VideoMode mode) void DispmanxWrapper::setVideoMode(VideoMode mode)

View File

@ -16,6 +16,8 @@ public:
); );
const Image<ColorRgb> & getScreenshot(); const Image<ColorRgb> & getScreenshot();
bool open();
/// ///
/// Starts the timed capturing of screenshots /// Starts the timed capturing of screenshots

View File

@ -90,13 +90,6 @@ if (ENABLE_AMLOGIC)
endif(ENABLE_AMLOGIC) endif(ENABLE_AMLOGIC)
if (ENABLE_DISPMANX) 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) target_link_libraries(${PROJECT_NAME} dispmanx-grabber)
endif (ENABLE_DISPMANX) endif (ENABLE_DISPMANX)

View File

@ -264,7 +264,8 @@ void HyperionDaemon::freeObjects()
#endif #endif
delete _amlGrabber; delete _amlGrabber;
delete _dispmanx; if (_dispmanx != nullptr)
delete _dispmanx;
delete _fbGrabber; delete _fbGrabber;
delete _osxGrabber; delete _osxGrabber;
delete _qtGrabber; delete _qtGrabber;
@ -522,9 +523,13 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
{ {
createGrabberDispmanx(grabberConfig); createGrabberDispmanx(grabberConfig);
} }
#ifdef ENABLE_DISPMANX #ifdef ENABLE_DISPMANX
if (_dispmanx != nullptr)
{
_dispmanx->handleSettingsUpdate(settings::SYSTEMCAPTURE, getSetting(settings::SYSTEMCAPTURE)); _dispmanx->handleSettingsUpdate(settings::SYSTEMCAPTURE, getSetting(settings::SYSTEMCAPTURE));
_dispmanx->tryStart(); _dispmanx->tryStart();
}
#endif #endif
} }
else if (type == "amlogic") else if (type == "amlogic")
@ -644,7 +649,16 @@ void HyperionDaemon::createGrabberDispmanx(const QJsonObject& /*grabberConfig*/)
_dispmanx = new DispmanxWrapper( _dispmanx = new DispmanxWrapper(
_grabber_frequency, _grabber_frequency,
_grabber_pixelDecimation _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); _dispmanx->setCropping(_grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom);
// connect to HyperionDaemon signal // connect to HyperionDaemon signal