diff --git a/cmake/FindBCM.cmake b/cmake/FindBCM.cmake index 116dfbca..5e9ce645 100644 --- a/cmake/FindBCM.cmake +++ b/cmake/FindBCM.cmake @@ -17,7 +17,7 @@ SET(BCM_INCLUDE_DIRS ${BCM_INCLUDE_DIR} ${BCM_INCLUDE_DIR}/interface/vcos/pthreads ${BCM_INCLUDE_DIR}/interface/vmcs_host/linux) - -FIND_LIBRARY(BCM_LIBS + +FIND_LIBRARY(BCM_LIBRARIES NAMES bcm_host PATHS /usr/lib /usr/local/lib /opt/vc/lib) diff --git a/include/hyperionpng/HyperionPng.h b/include/hyperionpng/HyperionPng.h new file mode 100644 index 00000000..610d59e4 --- /dev/null +++ b/include/hyperionpng/HyperionPng.h @@ -0,0 +1,47 @@ + +#pragma once + +// Utils includes +#include + +// Forward class declaration +class pngwriter; + +/** + * @brief The HyperionPng class implements the same interface + */ +class HyperionPng +{ +public: + HyperionPng(); + + ~HyperionPng(); + + void setInputSize(const unsigned width, const unsigned height); + + RgbImage& image(); + + void commit(); + + void operator() (const RgbImage& inputImage); + + +private: + RgbImage* mBuffer; + + unsigned mFrameCnt; + unsigned mWriteFrequency; + + pngwriter *mWriter; + unsigned long mFileIndex; + + HyperionPng(const HyperionPng&) + { + // empty + } + + HyperionPng& operator=(const HyperionPng&) + { + return *this; + } +}; diff --git a/include/utils/RgbImage.h b/include/utils/RgbImage.h index 0500a2a2..776ab0f4 100644 --- a/include/utils/RgbImage.h +++ b/include/utils/RgbImage.h @@ -47,6 +47,16 @@ private: return y*mWidth + x; } + RgbImage(const RgbImage&) + { + // empty + } + + RgbImage& operator=(const RgbImage& other) + { + return *this; + } + private: unsigned mWidth; unsigned mHeight; diff --git a/libsrc/CMakeLists.txt b/libsrc/CMakeLists.txt index 2708724d..06ea26d4 100644 --- a/libsrc/CMakeLists.txt +++ b/libsrc/CMakeLists.txt @@ -10,6 +10,18 @@ target_link_libraries(bob2hyperion hyperion hyperion-utils) +# Find the libPNG +find_package(PNG REQUIRED QUIET) + +# Add additional includes dirs +include_directories(${PNG_INCLUDE_DIR}) + +add_library(bob2hyperion-png SHARED + hyperion-png.cpp) + +target_link_libraries(bob2hyperion-png + hyperion-png) + add_subdirectory(hyperion) add_subdirectory(hyperionpng) add_subdirectory(utils) diff --git a/libsrc/hyperionpng/hyperion-png.cpp b/libsrc/hyperion-png.cpp similarity index 99% rename from libsrc/hyperionpng/hyperion-png.cpp rename to libsrc/hyperion-png.cpp index f28d3cb3..318431e1 100644 --- a/libsrc/hyperionpng/hyperion-png.cpp +++ b/libsrc/hyperion-png.cpp @@ -9,7 +9,7 @@ // PNGWriter includes #define NO_FREETYPE -#include "pngwriter.h" +#include "hyperionpng/pngwriter.h" struct RaspiPng { diff --git a/libsrc/hyperionpng/CMakeLists.txt b/libsrc/hyperionpng/CMakeLists.txt index 0b7d19b9..7c56a9c9 100644 --- a/libsrc/hyperionpng/CMakeLists.txt +++ b/libsrc/hyperionpng/CMakeLists.txt @@ -11,9 +11,11 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperionpng) # Create the 'rasplight-png' library add_library(hyperion-png SHARED - ${CURRENT_SOURCE_DIR}/hyperion-png.cpp + ${CURRENT_HEADER_DIR}/HyperionPng.h + ${CURRENT_SOURCE_DIR}/HyperionPng.cpp ${CURRENT_SOURCE_DIR}/pngwriter.h ${CURRENT_SOURCE_DIR}/pngwriter.cc) target_link_libraries(hyperion-png + hyperion-utils ${PNG_LIBRARIES}) diff --git a/libsrc/hyperionpng/HyperionPng.cpp b/libsrc/hyperionpng/HyperionPng.cpp new file mode 100644 index 00000000..3646217d --- /dev/null +++ b/libsrc/hyperionpng/HyperionPng.cpp @@ -0,0 +1,71 @@ +// PNG includes +#ifndef NO_FREETYPE +#define NO_FREETYPE +#endif +#include "pngwriter.h" + + +#include + +HyperionPng::HyperionPng() : + mBuffer(nullptr), + mFrameCnt(0), + mWriter(new pngwriter()), + mFileIndex(0) +{ + // empty +} + +HyperionPng::~HyperionPng() +{ + std::cout << "HyperionPng is being deleted" << std::endl; + delete mBuffer; + +// mWriter->close(); +// delete mWriter; +} + +void HyperionPng::setInputSize(const unsigned width, const unsigned height) +{ + delete mBuffer; + mBuffer = new RgbImage(width, height); +} + +RgbImage& HyperionPng::image() +{ + return *mBuffer; +} + +void HyperionPng::commit() +{ + this->operator ()(*mBuffer); +} + +void HyperionPng::operator() (const RgbImage& inputImage) +{ + // Write only every n'th frame + if (mFrameCnt%mWriteFrequency == 0) + { + // Set the filename for the PNG + char filename[64]; + sprintf(filename, "/home/pi/RASPI_%04ld.png", mFileIndex); + mWriter->pngwriter_rename(filename); + + // Plot the pixels from the image to the PNG-Writer + for (unsigned y=0; yplot(x+1, inputImage.height()-y, color.red/255.0, color.green/255.0, color.blue/255.0); + } + } + + // Write-out the current frame and prepare for the next + mWriter->write_png(); + + ++mFileIndex; + } + ++mFrameCnt; +} + diff --git a/libsrc/utils/RgbImage.cpp b/libsrc/utils/RgbImage.cpp index 0b7bdd6b..aaf8a71a 100644 --- a/libsrc/utils/RgbImage.cpp +++ b/libsrc/utils/RgbImage.cpp @@ -10,7 +10,7 @@ RgbImage::RgbImage(const unsigned width, const unsigned height, const RgbColor background) : mWidth(width), mHeight(height), - mColors(NULL) + mColors(nullptr) { mColors = new RgbColor[width*height]; for (RgbColor* color = mColors; color <= mColors+(mWidth*mHeight); ++color) @@ -21,6 +21,8 @@ RgbImage::RgbImage(const unsigned width, const unsigned height, const RgbColor b RgbImage::~RgbImage() { + std::cout << "RgbImage(" << this << ") is being deleted" << std::endl; + delete[] mColors; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 255b1a7b..dbf76456 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -25,14 +25,14 @@ include_directories(${BCM_INCLUDE_DIRS}) target_link_libraries(boblight-dispmanx # hyperion-png bob2hyperion - ${BCM_LIBS}) + ${BCM_LIBRARIES}) add_executable(HyperionDispmanX HyperionDispmanX.cpp) target_link_libraries(HyperionDispmanX hyperion - ${BCM_LIBS}) + ${BCM_LIBRARIES}) # Find the libPNG @@ -50,3 +50,5 @@ if(PNG_FOUND) hyperion-utils ${PNG_LIBRARIES}) endif(PNG_FOUND) + +add_subdirectory(dispmanx-png) diff --git a/src/HyperionDispmanX.cpp b/src/HyperionDispmanX.cpp index 1d64cca1..833e5306 100644 --- a/src/HyperionDispmanX.cpp +++ b/src/HyperionDispmanX.cpp @@ -55,16 +55,15 @@ int main(int /*argc*/, char** /*argv*/) RgbImage* image_ptr = &(hyperion.image()); void* image_vp = reinterpret_cast(image_ptr); - const unsigned imageSize_bytes = width*height*3; + const uint32_t pitch = width * 3; timespec updateInterval; updateInterval.tv_sec = 0; - updateInterval.tv_nsec = 100000000000; - + updateInterval.tv_nsec = 100000000; while(running) { vc_dispmanx_snapshot(display, resource, VC_IMAGE_ROT0); - vc_dispmanx_resource_read_data(resource, &rectangle, image_vp, imageSize_bytes); + vc_dispmanx_resource_read_data(resource, &rectangle, image_vp, pitch); hyperion.commit(); diff --git a/src/dispmanx-png/CMakeLists.txt b/src/dispmanx-png/CMakeLists.txt new file mode 100644 index 00000000..8d4a75b6 --- /dev/null +++ b/src/dispmanx-png/CMakeLists.txt @@ -0,0 +1,13 @@ + +# Find the BCM-package (VC control) +find_package(BCM REQUIRED) + +# Add the include dirs to the search path +include_directories(${BCM_INCLUDE_DIRS}) + +add_executable(dispmanx-png + dispmanx-png.cpp) + +target_link_libraries(dispmanx-png + hyperion-png + ${BCM_LIBRARIES}) diff --git a/src/dispmanx-png/dispmanx-png.cpp b/src/dispmanx-png/dispmanx-png.cpp new file mode 100644 index 00000000..27ef568b --- /dev/null +++ b/src/dispmanx-png/dispmanx-png.cpp @@ -0,0 +1,91 @@ + +// STL includes +#include + +// VC includes +#include + +// Hyperion includes +#include + +static volatile bool sRunning = true; + +void signal_handler(int signum) +{ + std::cout << "RECEIVED SIGNAL: " << signum << std::endl; + sRunning = false; +} + +template +int dispmanx_process(Hyperion_T& hyperion, volatile bool& running) +{ + // Configure the used image size + const unsigned width = 64; + const unsigned height = 64; + hyperion.setInputSize(width, height); + + // Initiase BCM + bcm_host_init(); + + // Open the connection to the displaydisplay + DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open(0); + DISPMANX_MODEINFO_T info; + int ret = vc_dispmanx_display_get_info(display, &info); + assert(ret == 0); + + // Create the resources for capturing image + uint32_t vc_image_ptr; + DISPMANX_RESOURCE_HANDLE_T resource = vc_dispmanx_resource_create( + VC_IMAGE_RGB888, + width, + height, + &vc_image_ptr); + assert(resource); + + VC_RECT_T rectangle; + vc_dispmanx_rect_set(&rectangle, 0, 0, width, height); + + RgbImage* image_ptr = &(hyperion.image()); + void* image_vp = reinterpret_cast(image_ptr); + const uint32_t pitch = width * 3; + + timespec updateInterval; + updateInterval.tv_sec = 0; + updateInterval.tv_nsec = 100000000; + while(running) + { + std::cout << "Grabbing a frame from display" << std::endl; + vc_dispmanx_snapshot(display, resource, VC_IMAGE_ROT0); + vc_dispmanx_resource_read_data(resource, &rectangle, image_vp, pitch); + + std::cout << "Commiting the frame to Hyperion" << std::endl; +// hyperion.commit(); + + std::cout << "Waiting for next grab" << std::endl; + nanosleep(&updateInterval, NULL); + } + + std::cout << "Cleaning VC resources" << std::endl; + // Clean up resources + vc_dispmanx_resource_delete(resource); + vc_dispmanx_display_close(display); + + std::cout << "Uninitialising BCM-Host" << std::endl; + // De-init BCM + bcm_host_deinit(); + + std::cout << "Exit success" << std::endl; + + return 0; +} + +int main(int /*argc*/, char** /*argv*/) +{ + // Install signal-handlers to exit the processing loop + signal(SIGTERM, signal_handler); + signal(SIGINT, signal_handler); + + // Construct and initialise the PNG creator with preset size + HyperionPng hyperion; + return dispmanx_process(hyperion, sRunning); +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 97b317d1..b3f9e97d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -33,5 +33,5 @@ if(PNG_FOUND) TestHyperionPng.cpp) target_link_libraries(TestHyperionPng - hyperion-png) + bob2hyperion-png) endif(PNG_FOUND)