From 2799df3165a1dcbd2a525e22c71fe27cdf8ee852 Mon Sep 17 00:00:00 2001 From: venkat0907 Date: Thu, 13 Jul 2023 12:58:49 +0530 Subject: [PATCH 1/3] added two features create window, switch displays --- base/include/ApraNvEglRenderer.h | 4 +- base/include/Command.h | 49 ++++++++++++++++ base/include/EglRenderer.h | 7 ++- base/src/EglRenderer.cpp | 60 +++++++++++++++++--- base/src/NvEglRenderer.cpp | 42 ++++++++++++-- base/test/eglrenderer_test.cpp | 95 ++++++++++++++++++++++++++++++++ 6 files changed, 242 insertions(+), 15 deletions(-) diff --git a/base/include/ApraNvEglRenderer.h b/base/include/ApraNvEglRenderer.h index 1e39adf2c..3526c4dd1 100644 --- a/base/include/ApraNvEglRenderer.h +++ b/base/include/ApraNvEglRenderer.h @@ -95,7 +95,7 @@ class NvEglRenderer */ static NvEglRenderer *createEglRenderer(const char *name, uint32_t width, uint32_t height, uint32_t x_offset, - uint32_t y_offset); + uint32_t y_offset , bool displayOnTop); ~NvEglRenderer(); /** @@ -213,7 +213,7 @@ class NvEglRenderer * Constructor called by the wrapper createEglRenderer. */ NvEglRenderer(const char *name, uint32_t width, uint32_t height, - uint32_t x_offset, uint32_t y_offset); + uint32_t x_offset, uint32_t y_offset , bool displayOnTop); /** * Gets the pointers to the required EGL methods. */ diff --git a/base/include/Command.h b/base/include/Command.h index 7103c9a8d..cd55313fd 100755 --- a/base/include/Command.h +++ b/base/include/Command.h @@ -14,6 +14,8 @@ class Command ValvePassThrough, MultimediaQueueXform, Seek, + DeleteWindow, + CreateWindow }; Command() @@ -196,6 +198,53 @@ class ValvePassThroughCommand : public Command } }; +class EglRendererCloseWindow : public Command +{ +public: + EglRendererCloseWindow() : Command(Command::CommandType::DeleteWindow) + { + } + + size_t getSerializeSize() + { + return Command::getSerializeSize(); + } + + +private: + friend class boost::serialization::access; + template + void serialize(Archive& ar, const unsigned int /* file_version */) + { + ar& boost::serialization::base_object(*this); + } +}; + +class EglRendererCreateWindow : public Command +{ +public: + EglRendererCreateWindow() : Command(Command::CommandType::CreateWindow) + { + } + + size_t getSerializeSize() + { + return Command::getSerializeSize() + sizeof(width) + sizeof(height) ; + } + int width; + int height; + +private: + friend class boost::serialization::access; + template + void serialize(Archive &ar, const unsigned int /* file_version */) + { + ar &boost::serialization::base_object(*this); + ar &width; + ar &height; + } +}; + class MultimediaQueueXformCommand : public Command { public: diff --git a/base/include/EglRenderer.h b/base/include/EglRenderer.h index 287377ecf..3858091e3 100644 --- a/base/include/EglRenderer.h +++ b/base/include/EglRenderer.h @@ -12,17 +12,19 @@ class EglRendererProps : public ModuleProps height = _height; width = _width; } - EglRendererProps(uint32_t _x_offset,uint32_t _y_offset) : ModuleProps() + EglRendererProps(uint32_t _x_offset,uint32_t _y_offset,bool _displayOnTop = true) : ModuleProps() { x_offset = _x_offset; y_offset = _y_offset; height = 0; width = 0; + displayOnTop = _displayOnTop ? 1 : 0; } uint32_t x_offset; uint32_t y_offset; uint32_t height; uint32_t width; + bool displayOnTop; }; class EglRenderer : public Module @@ -33,11 +35,14 @@ class EglRenderer : public Module bool init(); bool term(); + bool closeWindow(); + bool createWindow(int width, int height); protected: bool process(frame_container& frames); bool processSOS(frame_sp& frame); bool validateInputPins(); bool shouldTriggerSOS(); + bool handleCommand(Command::CommandType type, frame_sp& frame); private: class Detail; boost::shared_ptr mDetail; diff --git a/base/src/EglRenderer.cpp b/base/src/EglRenderer.cpp index 1201f0350..050235a84 100644 --- a/base/src/EglRenderer.cpp +++ b/base/src/EglRenderer.cpp @@ -2,12 +2,13 @@ #include "EglRenderer.h" #include "ApraNvEglRenderer.h" #include "DMAFDWrapper.h" +#include "Command.h" class EglRenderer::Detail { public: - Detail(uint32_t _x_offset, uint32_t _y_offset, uint32_t _width, uint32_t _height): x_offset(_x_offset), y_offset(_y_offset), width(_width), height(_height) {} + Detail(uint32_t _x_offset, uint32_t _y_offset, uint32_t _width, uint32_t _height , bool _displayOnTop): x_offset(_x_offset), y_offset(_y_offset), width(_width), height(_height), displayOnTop(_displayOnTop) {} ~Detail() { @@ -17,17 +18,17 @@ class EglRenderer::Detail } } - bool init(uint32_t _height, uint32_t _width){ + bool init(uint32_t _height, uint32_t _width , bool _displayOnTop){ uint32_t displayHeight, displayWidth; NvEglRenderer::getDisplayResolution(displayWidth,displayHeight); if(height!=0 && width!=0){ x_offset += (displayWidth-width)/2; y_offset += (displayHeight-height)/2; - renderer = NvEglRenderer::createEglRenderer(__TIMESTAMP__, width, height, x_offset, y_offset); + renderer = NvEglRenderer::createEglRenderer(__TIMESTAMP__, width, height, x_offset, y_offset,displayOnTop); }else{ x_offset += (displayWidth-_width)/2; y_offset += (displayHeight-_height)/2; - renderer = NvEglRenderer::createEglRenderer(__TIMESTAMP__, _width, _height, x_offset, y_offset); + renderer = NvEglRenderer::createEglRenderer(__TIMESTAMP__, _width, _height, x_offset, y_offset, _displayOnTop); } if (!renderer) { @@ -38,6 +39,14 @@ class EglRenderer::Detail return true; } + bool destroyWindow() + { + if(renderer) + { + delete renderer; + } + } + bool shouldTriggerSOS() { return !renderer; @@ -45,11 +54,12 @@ class EglRenderer::Detail NvEglRenderer *renderer = nullptr; uint32_t x_offset,y_offset,width,height; + bool displayOnTop; }; EglRenderer::EglRenderer(EglRendererProps props) : Module(SINK, "EglRenderer", props) { - mDetail.reset(new Detail(props.x_offset,props.y_offset, props.width, props.height)); + mDetail.reset(new Detail(props.x_offset,props.y_offset, props.width, props.height,props.displayOnTop)); } EglRenderer::~EglRenderer() {} @@ -103,7 +113,7 @@ bool EglRenderer::processSOS(frame_sp& frame) auto frameType = inputMetadata->getFrameType(); int width = 0; int height =0; - + switch (frameType) { case FrameMetadata::FrameType::RAW_IMAGE: @@ -124,11 +134,45 @@ bool EglRenderer::processSOS(frame_sp& frame) throw AIPException(AIP_FATAL, "Unsupported FrameType<" + std::to_string(frameType) + ">"); } - mDetail->init(height, width); + mDetail->init(height,width,mDetail->displayOnTop); return true; } bool EglRenderer::shouldTriggerSOS() { return mDetail->shouldTriggerSOS(); -} \ No newline at end of file +} + +bool EglRenderer::handleCommand(Command::CommandType type, frame_sp &frame) +{ + if (type == Command::CommandType::DeleteWindow) + { + EglRendererCloseWindow cmd; + getCommand(cmd, frame); + mDetail->destroyWindow(); + return true; + } + else if (type == Command::CommandType::CreateWindow) + { + EglRendererCreateWindow cmd; + getCommand(cmd, frame); + mDetail->init(cmd.width, cmd.height,mDetail->displayOnTop); + return true; + } + return Module::handleCommand(type, frame); +} + +bool EglRenderer::closeWindow() +{ + EglRendererCloseWindow cmd; + return queueCommand(cmd); +} + +bool EglRenderer::createWindow(int width, int height) +{ + EglRendererCreateWindow cmd; + cmd.width = width; + cmd.height = height; + return queueCommand(cmd); +} + diff --git a/base/src/NvEglRenderer.cpp b/base/src/NvEglRenderer.cpp index 26e948734..052364311 100644 --- a/base/src/NvEglRenderer.cpp +++ b/base/src/NvEglRenderer.cpp @@ -30,6 +30,7 @@ #include "NvLogging.h" #include "nvbuf_utils.h" #include "NvElement.h" +#include "Logger.h" #include #include @@ -52,7 +53,7 @@ PFNGLEGLIMAGETARGETTEXTURE2DOESPROC NvEglRenderer::glEGLImageTargetTexture2D using namespace std; -NvEglRenderer::NvEglRenderer(const char *name, uint32_t width, uint32_t height, uint32_t x_offset, uint32_t y_offset) +NvEglRenderer::NvEglRenderer(const char *name, uint32_t width, uint32_t height, uint32_t x_offset, uint32_t y_offset , bool displayOnTop) { int depth; int screen_num; @@ -109,7 +110,21 @@ NvEglRenderer::NvEglRenderer(const char *name, uint32_t width, uint32_t height, window_attributes.background_pixel = BlackPixel(x_display, DefaultScreen(x_display)); - window_attributes.override_redirect = 1; + window_attributes.override_redirect = displayOnTop; + Atom WM_HINTS; + if(window_attributes.override_redirect == 0) + { + struct + { + unsigned long flags; + unsigned long functions; + unsigned long decorations; + long inputMode; + unsigned long status; + } WM_HINTS = { (1L << 1), 0, 0, 0, 0 }; // this we added to remove title bar + } + + LOG_ERROR << "X_OFFSET " << x_offset << "Y_OFFSET "<< y_offset << "========================>>>>"; x_window = XCreateWindow(x_display, DefaultRootWindow(x_display), x_offset, @@ -120,6 +135,25 @@ NvEglRenderer::NvEglRenderer(const char *name, uint32_t width, uint32_t height, (CWBackPixel | CWOverrideRedirect), &window_attributes); + + if(window_attributes.override_redirect == 0) + { + XStoreName(x_display, x_window, "ApraEglRenderer"); + XFlush(x_display); + + XSizeHints hints; + hints.x = x_offset; + hints.y = y_offset; + hints.width = width; + hints.height = height; + hints.flags = PPosition | PSize; + XSetWMNormalHints(x_display, x_window, &hints); + + WM_HINTS = XInternAtom(x_display, "_MOTIF_WM_HINTS", True); + XChangeProperty(x_display, x_window, WM_HINTS, WM_HINTS, 32, + PropModeReplace, (unsigned char *)&WM_HINTS, 5); + } + XSelectInput(x_display, (int32_t) x_window, ExposureMask); XMapWindow(x_display, (int32_t) x_window); gc = XCreateGC(x_display, x_window, 0, NULL); @@ -445,10 +479,10 @@ NvEglRenderer::setFPS(float fps) NvEglRenderer * NvEglRenderer::createEglRenderer(const char *name, uint32_t width, uint32_t height, uint32_t x_offset, - uint32_t y_offset) + uint32_t y_offset , bool displayOnTop) { NvEglRenderer* renderer = new NvEglRenderer(name, width, height, - x_offset, y_offset); + x_offset, y_offset , displayOnTop); return renderer; } diff --git a/base/test/eglrenderer_test.cpp b/base/test/eglrenderer_test.cpp index f6ac0b2bc..64c48dff8 100644 --- a/base/test/eglrenderer_test.cpp +++ b/base/test/eglrenderer_test.cpp @@ -3,6 +3,10 @@ #include "FileReaderModule.h" #include "EglRenderer.h" #include "PipeLine.h" +#include "ApraNvEglRenderer.h" +#include "NvV4L2Camera.h" +#include "NvTransform.h" + BOOST_AUTO_TEST_SUITE(eglrenderer_tests) @@ -38,4 +42,95 @@ BOOST_AUTO_TEST_CASE(basic, *boost::unit_test::disabled()) p.wait_for_all(); } +BOOST_AUTO_TEST_CASE(displayOnTop, *boost::unit_test::disabled()) +{ + NvV4L2CameraProps nvCamProps(640,360, 10); + auto source = boost::shared_ptr(new NvV4L2Camera(nvCamProps)); + + NvTransformProps nvprops(ImageMetadata::RGBA); + auto transform = boost::shared_ptr(new NvTransform(nvprops)); + source->setNext(transform); + + auto sink = boost::shared_ptr(new EglRenderer(EglRendererProps(0,0,1))); + transform->setNext(sink); + + PipeLine p("test"); + p.appendModule(source); + BOOST_TEST(p.init()); + + Logger::setLogLevel(boost::log::trivial::severity_level::info); + + p.run_all_threaded(); + + boost::this_thread::sleep_for(boost::chrono::seconds(120)); + Logger::setLogLevel(boost::log::trivial::severity_level::error); + + p.stop(); + p.term(); + + p.wait_for_all(); +} + +BOOST_AUTO_TEST_CASE(switch_display, *boost::unit_test::disabled()) +{ + NvV4L2CameraProps nvCamProps(640,360, 10); + auto source = boost::shared_ptr(new NvV4L2Camera(nvCamProps)); + + NvTransformProps nvprops(ImageMetadata::RGBA); + auto transform = boost::shared_ptr(new NvTransform(nvprops)); + source->setNext(transform); + + auto sink = boost::shared_ptr(new EglRenderer(EglRendererProps(0,0,0))); + transform->setNext(sink); + + PipeLine p("test"); + p.appendModule(source); + BOOST_TEST(p.init()); + + Logger::setLogLevel(boost::log::trivial::severity_level::info); + + p.run_all_threaded(); + + boost::this_thread::sleep_for(boost::chrono::seconds(120)); + Logger::setLogLevel(boost::log::trivial::severity_level::error); + + p.stop(); + p.term(); + + p.wait_for_all(); +} + +BOOST_AUTO_TEST_CASE(open_close_window, *boost::unit_test::disabled()) +{ + NvV4L2CameraProps nvCamProps(640,360, 10); + auto source = boost::shared_ptr(new NvV4L2Camera(nvCamProps)); + + NvTransformProps nvprops(ImageMetadata::RGBA); + auto transform = boost::shared_ptr(new NvTransform(nvprops)); + source->setNext(transform); + + auto sink = boost::shared_ptr(new EglRenderer(EglRendererProps(0,0,0))); + transform->setNext(sink); + + PipeLine p("test"); + p.appendModule(source); + BOOST_TEST(p.init()); + + Logger::setLogLevel(boost::log::trivial::severity_level::info); + + p.run_all_threaded(); + + boost::this_thread::sleep_for(boost::chrono::seconds(5)); + sink->closeWindow(); + sink->createWindow(200,200); + + boost::this_thread::sleep_for(boost::chrono::seconds(120)); + Logger::setLogLevel(boost::log::trivial::severity_level::error); + + p.stop(); + p.term(); + + p.wait_for_all(); +} + BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file From 494e59542e65a4cd235c3c8b0eda0791e6360c11 Mon Sep 17 00:00:00 2001 From: venkat0907 Date: Thu, 13 Jul 2023 14:59:04 +0530 Subject: [PATCH 2/3] addressed PR comments --- base/src/NvEglRenderer.cpp | 2 -- base/test/eglrenderer_test.cpp | 1 - 2 files changed, 3 deletions(-) diff --git a/base/src/NvEglRenderer.cpp b/base/src/NvEglRenderer.cpp index 052364311..f1d5c12e7 100644 --- a/base/src/NvEglRenderer.cpp +++ b/base/src/NvEglRenderer.cpp @@ -124,8 +124,6 @@ NvEglRenderer::NvEglRenderer(const char *name, uint32_t width, uint32_t height, } WM_HINTS = { (1L << 1), 0, 0, 0, 0 }; // this we added to remove title bar } - LOG_ERROR << "X_OFFSET " << x_offset << "Y_OFFSET "<< y_offset << "========================>>>>"; - x_window = XCreateWindow(x_display, DefaultRootWindow(x_display), x_offset, y_offset, width, height, diff --git a/base/test/eglrenderer_test.cpp b/base/test/eglrenderer_test.cpp index 64c48dff8..9d0abef30 100644 --- a/base/test/eglrenderer_test.cpp +++ b/base/test/eglrenderer_test.cpp @@ -3,7 +3,6 @@ #include "FileReaderModule.h" #include "EglRenderer.h" #include "PipeLine.h" -#include "ApraNvEglRenderer.h" #include "NvV4L2Camera.h" #include "NvTransform.h" From b52ea6406950387e38901dfa808e9923c5423f1f Mon Sep 17 00:00:00 2001 From: venkat0907 Date: Mon, 17 Jul 2023 14:57:54 +0530 Subject: [PATCH 3/3] addressed PR comments --- base/src/EglRenderer.cpp | 2 +- base/test/eglrenderer_test.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/base/src/EglRenderer.cpp b/base/src/EglRenderer.cpp index 050235a84..50a563191 100644 --- a/base/src/EglRenderer.cpp +++ b/base/src/EglRenderer.cpp @@ -28,7 +28,7 @@ class EglRenderer::Detail }else{ x_offset += (displayWidth-_width)/2; y_offset += (displayHeight-_height)/2; - renderer = NvEglRenderer::createEglRenderer(__TIMESTAMP__, _width, _height, x_offset, y_offset, _displayOnTop); + renderer = NvEglRenderer::createEglRenderer(__TIMESTAMP__, _width, _height, x_offset, y_offset, displayOnTop); } if (!renderer) { diff --git a/base/test/eglrenderer_test.cpp b/base/test/eglrenderer_test.cpp index 9d0abef30..e6733257c 100644 --- a/base/test/eglrenderer_test.cpp +++ b/base/test/eglrenderer_test.cpp @@ -121,6 +121,8 @@ BOOST_AUTO_TEST_CASE(open_close_window, *boost::unit_test::disabled()) boost::this_thread::sleep_for(boost::chrono::seconds(5)); sink->closeWindow(); + + boost::this_thread::sleep_for(boost::chrono::seconds(10)); sink->createWindow(200,200); boost::this_thread::sleep_for(boost::chrono::seconds(120));