From 5f8d5f4f6ab233aec44fb2105a2437d83ee5a737 Mon Sep 17 00:00:00 2001 From: Robert Stanley Judka Date: Sun, 22 Mar 2020 16:08:44 -0500 Subject: [PATCH 1/7] add interfaces to dynamically adjust video size (#1) * adding interfaces for toggling fullscreen * passing in destrect to omx * adding flag for deffering video update * remove skipUpdate option for video output * fixing omx player stop deadlock; setting omx alpha in constructor * jk not setting opacity in constructor for omx * removing unsed function --- .../autoapp/Projection/InputDevice.hpp | 1 + .../autoapp/Projection/OMXVideoOutput.hpp | 1 + .../autoapp/Projection/QtVideoOutput.hpp | 1 + .../autoapp/Service/ServiceFactory.hpp | 6 ++++ src/autoapp/Projection/InputDevice.cpp | 5 +++ src/autoapp/Projection/OMXVideoOutput.cpp | 33 +++++++++++-------- src/autoapp/Projection/QtVideoOutput.cpp | 5 +++ src/autoapp/Service/ServiceFactory.cpp | 25 +++++++++++--- 8 files changed, 59 insertions(+), 18 deletions(-) diff --git a/include/f1x/openauto/autoapp/Projection/InputDevice.hpp b/include/f1x/openauto/autoapp/Projection/InputDevice.hpp index b6197a1..7d119bb 100644 --- a/include/f1x/openauto/autoapp/Projection/InputDevice.hpp +++ b/include/f1x/openauto/autoapp/Projection/InputDevice.hpp @@ -45,6 +45,7 @@ public: bool eventFilter(QObject* obj, QEvent* event) override; bool hasTouchscreen() const override; QRect getTouchscreenGeometry() const override; + void setTouchscreenGeometry(QRect& touchscreenGeometry); private: void setVideoGeometry(); diff --git a/include/f1x/openauto/autoapp/Projection/OMXVideoOutput.hpp b/include/f1x/openauto/autoapp/Projection/OMXVideoOutput.hpp index 30d0888..028f7ee 100644 --- a/include/f1x/openauto/autoapp/Projection/OMXVideoOutput.hpp +++ b/include/f1x/openauto/autoapp/Projection/OMXVideoOutput.hpp @@ -62,6 +62,7 @@ public: void write(uint64_t timestamp, const aasdk::common::DataConstBuffer& buffer) override; void stop() override; void setOpacity(OMX_U32 alpha); + void setDestRect(DestRect destRect); private: bool createComponents(); diff --git a/include/f1x/openauto/autoapp/Projection/QtVideoOutput.hpp b/include/f1x/openauto/autoapp/Projection/QtVideoOutput.hpp index 5800351..4a18319 100644 --- a/include/f1x/openauto/autoapp/Projection/QtVideoOutput.hpp +++ b/include/f1x/openauto/autoapp/Projection/QtVideoOutput.hpp @@ -43,6 +43,7 @@ public: bool init() override; void write(uint64_t timestamp, const aasdk::common::DataConstBuffer& buffer) override; void stop() override; + void resize(); signals: void startPlayback(); diff --git a/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp b/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp index 2c4475c..61d2223 100644 --- a/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp +++ b/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp @@ -20,7 +20,9 @@ #include #include +#include #include +#include namespace f1x { @@ -37,6 +39,7 @@ public: ServiceFactory(boost::asio::io_service& ioService, configuration::IConfiguration::Pointer configuration, QWidget* activeArea=nullptr, std::function activeCallback=nullptr); ServiceList create(aasdk::messenger::IMessenger::Pointer messenger) override; void setOpacity(unsigned int alpha); + void resize(); static QRect mapActiveAreaToGlobal(QWidget* activeArea); #ifdef USE_OMX static projection::DestRect QRectToDestRect(QRect rect); @@ -53,8 +56,11 @@ private: QWidget* activeArea_; QRect screenGeometry_; std::function activeCallback_; + std::shared_ptr inputDevice_; #ifdef USE_OMX std::shared_ptr omxVideoOutput_; +#else + projection::QtVideoOutput *qtVideoOutput_; #endif }; diff --git a/src/autoapp/Projection/InputDevice.cpp b/src/autoapp/Projection/InputDevice.cpp index 95d2a97..ec7c3a9 100644 --- a/src/autoapp/Projection/InputDevice.cpp +++ b/src/autoapp/Projection/InputDevice.cpp @@ -225,6 +225,11 @@ QRect InputDevice::getTouchscreenGeometry() const return touchscreenGeometry_; } +void InputDevice::setTouchscreenGeometry(QRect& touchscreenGeometry) +{ + touchscreenGeometry_ = touchscreenGeometry; +} + IInputDevice::ButtonCodes InputDevice::getSupportedButtonCodes() const { return configuration_->getButtonCodes(); diff --git a/src/autoapp/Projection/OMXVideoOutput.cpp b/src/autoapp/Projection/OMXVideoOutput.cpp index 4b4f75a..cd700fe 100644 --- a/src/autoapp/Projection/OMXVideoOutput.cpp +++ b/src/autoapp/Projection/OMXVideoOutput.cpp @@ -114,10 +114,12 @@ bool OMXVideoOutput::open() } isActive_ = true; - if(this->activeCallback_ != nullptr) + + if(activeCallback_ != nullptr) { - this->activeCallback_(isActive_); + activeCallback_(true); } + return true; } @@ -214,15 +216,16 @@ void OMXVideoOutput::stop() { OPENAUTO_LOG(info) << "[OMXVideoOutput] stop."; + if(activeCallback_ != nullptr) + { + activeCallback_(false); + } + std::lock_guard lock(mutex_); if(isActive_) { isActive_ = false; - if(this->activeCallback_ != nullptr) - { - this->activeCallback_(isActive_); - } ilclient_disable_tunnel(&tunnels_[0]); ilclient_disable_tunnel(&tunnels_[1]); @@ -249,14 +252,18 @@ void OMXVideoOutput::setOpacity(OMX_U32 alpha) alpha_ = alpha; if(isActive_) { - OMX_CONFIG_DISPLAYREGIONTYPE displayRegion; - displayRegion.nSize = sizeof(OMX_CONFIG_DISPLAYREGIONTYPE); - displayRegion.nVersion.nVersion = OMX_VERSION; - displayRegion.nPortIndex = 90; - displayRegion.alpha = alpha_; - displayRegion.set = static_cast(OMX_DISPLAY_SET_ALPHA); + this->setupDisplayRegion(); + } +} - OMX_SetConfig(ilclient_get_handle(components_[VideoComponent::RENDERER]), OMX_IndexConfigDisplayRegion, &displayRegion) == OMX_ErrorNone; +void OMXVideoOutput::setDestRect(DestRect destRect) +{ + std::lock_guard lock(mutex_); + + destRect_ = destRect; + if(isActive_) + { + this->setupDisplayRegion(); } } diff --git a/src/autoapp/Projection/QtVideoOutput.cpp b/src/autoapp/Projection/QtVideoOutput.cpp index ec7c349..68ceddf 100644 --- a/src/autoapp/Projection/QtVideoOutput.cpp +++ b/src/autoapp/Projection/QtVideoOutput.cpp @@ -69,6 +69,11 @@ void QtVideoOutput::write(uint64_t, const aasdk::common::DataConstBuffer& buffer videoBuffer_.write(reinterpret_cast(buffer.cdata), buffer.size); } +void QtVideoOutput::resize() +{ + if (videoWidget_ != nullptr && videoContainer_ != nullptr) videoWidget_->resize(videoContainer_->size()); +} + void QtVideoOutput::onStartPlayback() { if (videoContainer_ == nullptr) diff --git a/src/autoapp/Service/ServiceFactory.cpp b/src/autoapp/Service/ServiceFactory.cpp index ceead5e..dca6f65 100644 --- a/src/autoapp/Service/ServiceFactory.cpp +++ b/src/autoapp/Service/ServiceFactory.cpp @@ -82,8 +82,12 @@ IService::Pointer ServiceFactory::createVideoService(aasdk::messenger::IMessenge #ifdef USE_OMX auto videoOutput(omxVideoOutput_); #else - auto qtVideoOutput = new projection::QtVideoOutput(configuration_, activeArea_); - projection::IVideoOutput::Pointer videoOutput(qtVideoOutput, std::bind(&QObject::deleteLater, std::placeholders::_1)); + qtVideoOutput_ = new projection::QtVideoOutput(configuration_, activeArea_); + if (activeCallback_ != nullptr) { + QObject::connect(qtVideoOutput_, &projection::QtVideoOutput::startPlayback, [callback = activeCallback_]() { callback(true); }); + QObject::connect(qtVideoOutput_, &projection::QtVideoOutput::stopPlayback, [callback = activeCallback_]() { callback(false); }); + } + projection::IVideoOutput::Pointer videoOutput(qtVideoOutput_, std::bind(&QObject::deleteLater, std::placeholders::_1)); #endif return std::make_shared(ioService_, messenger, std::move(videoOutput)); } @@ -128,9 +132,9 @@ IService::Pointer ServiceFactory::createInputService(aasdk::messenger::IMessenge } QObject* inputObject = activeArea_ == nullptr ? qobject_cast(QApplication::instance()) : qobject_cast(activeArea_); - projection::IInputDevice::Pointer inputDevice(std::make_shared(*inputObject, configuration_, std::move(screenGeometry_), std::move(videoGeometry))); + inputDevice_ = std::make_shared(*inputObject, configuration_, std::move(screenGeometry_), std::move(videoGeometry)); - return std::make_shared(ioService_, messenger, std::move(inputDevice)); + return std::make_shared(ioService_, messenger, std::move(projection::IInputDevice::Pointer(inputDevice_))); } void ServiceFactory::createAudioServices(ServiceList& serviceList, aasdk::messenger::IMessenger::Pointer messenger) @@ -163,7 +167,18 @@ void ServiceFactory::createAudioServices(ServiceList& serviceList, aasdk::messen void ServiceFactory::setOpacity(unsigned int alpha) { #ifdef USE_OMX - omxVideoOutput_->setOpacity(alpha); + if (omxVideoOutput_ != nullptr) omxVideoOutput_->setOpacity(alpha); +#endif +} + +void ServiceFactory::resize() +{ + screenGeometry_ = this->mapActiveAreaToGlobal(activeArea_); + if (inputDevice_ != nullptr) inputDevice_->setTouchscreenGeometry(screenGeometry_); +#ifdef USE_OMX + if (omxVideoOutput_ != nullptr) omxVideoOutput_->setDestRect(this->QRectToDestRect(screenGeometry_)); +#else + if (qtVideoOutput_ != nullptr) qtVideoOutput_->resize(); #endif } From 464da85686a35ae62b37c9bd75bbb33a0b06bfdb Mon Sep 17 00:00:00 2001 From: Robert Stanley Judka Date: Sat, 25 Apr 2020 23:49:33 -0500 Subject: [PATCH 2/7] add interface to allow for night mode control (#2) --- .../f1x/openauto/autoapp/Service/SensorService.hpp | 4 +++- .../f1x/openauto/autoapp/Service/ServiceFactory.hpp | 6 +++++- src/autoapp/Service/SensorService.cpp | 11 +++++++++-- src/autoapp/Service/ServiceFactory.cpp | 12 ++++++++++-- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/include/f1x/openauto/autoapp/Service/SensorService.hpp b/include/f1x/openauto/autoapp/Service/SensorService.hpp index 5dfd8e5..8006065 100644 --- a/include/f1x/openauto/autoapp/Service/SensorService.hpp +++ b/include/f1x/openauto/autoapp/Service/SensorService.hpp @@ -33,7 +33,7 @@ namespace service class SensorService: public aasdk::channel::sensor::ISensorServiceChannelEventHandler, public IService, public std::enable_shared_from_this { public: - SensorService(boost::asio::io_service& ioService, aasdk::messenger::IMessenger::Pointer messenger); + SensorService(boost::asio::io_service& ioService, aasdk::messenger::IMessenger::Pointer messenger, bool nightMode = false); void start() override; void stop() override; @@ -41,6 +41,7 @@ public: void onChannelOpenRequest(const aasdk::proto::messages::ChannelOpenRequest& request) override; void onSensorStartRequest(const aasdk::proto::messages::SensorStartRequestMessage& request) override; void onChannelError(const aasdk::error::Error& e) override; + void setNightMode(bool nightMode); private: using std::enable_shared_from_this::shared_from_this; @@ -49,6 +50,7 @@ private: boost::asio::io_service::strand strand_; aasdk::channel::sensor::SensorServiceChannel::Pointer channel_; + bool nightMode_; }; } diff --git a/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp b/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp index 61d2223..9d79b84 100644 --- a/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp +++ b/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp @@ -23,6 +23,7 @@ #include #include #include +#include namespace f1x { @@ -36,10 +37,11 @@ namespace service class ServiceFactory: public IServiceFactory { public: - ServiceFactory(boost::asio::io_service& ioService, configuration::IConfiguration::Pointer configuration, QWidget* activeArea=nullptr, std::function activeCallback=nullptr); + ServiceFactory(boost::asio::io_service& ioService, configuration::IConfiguration::Pointer configuration, QWidget* activeArea=nullptr, std::function activeCallback=nullptr, bool nightMode = false); ServiceList create(aasdk::messenger::IMessenger::Pointer messenger) override; void setOpacity(unsigned int alpha); void resize(); + void setNightMode(bool nightMode); static QRect mapActiveAreaToGlobal(QWidget* activeArea); #ifdef USE_OMX static projection::DestRect QRectToDestRect(QRect rect); @@ -62,6 +64,8 @@ private: #else projection::QtVideoOutput *qtVideoOutput_; #endif + bool nightMode_; + std::shared_ptr sensorService_; }; } diff --git a/src/autoapp/Service/SensorService.cpp b/src/autoapp/Service/SensorService.cpp index f6c05ef..c2b4ada 100644 --- a/src/autoapp/Service/SensorService.cpp +++ b/src/autoapp/Service/SensorService.cpp @@ -29,9 +29,10 @@ namespace autoapp namespace service { -SensorService::SensorService(boost::asio::io_service& ioService, aasdk::messenger::IMessenger::Pointer messenger) +SensorService::SensorService(boost::asio::io_service& ioService, aasdk::messenger::IMessenger::Pointer messenger, bool nightMode) : strand_(ioService) , channel_(std::make_shared(strand_, std::move(messenger))) + , nightMode_(nightMode) { } @@ -121,7 +122,7 @@ void SensorService::sendDrivingStatusUnrestricted() void SensorService::sendNightData() { aasdk::proto::messages::SensorEventIndication indication; - indication.add_night_mode()->set_is_night(false); + indication.add_night_mode()->set_is_night(nightMode_); auto promise = aasdk::channel::SendPromise::defer(strand_); promise->then([]() {}, std::bind(&SensorService::onChannelError, this->shared_from_this(), std::placeholders::_1)); @@ -133,6 +134,12 @@ void SensorService::onChannelError(const aasdk::error::Error& e) OPENAUTO_LOG(error) << "[SensorService] channel error: " << e.what(); } +void SensorService::setNightMode(bool nightMode) +{ + nightMode_ = nightMode; + this->sendNightData(); +} + } } } diff --git a/src/autoapp/Service/ServiceFactory.cpp b/src/autoapp/Service/ServiceFactory.cpp index dca6f65..461751f 100644 --- a/src/autoapp/Service/ServiceFactory.cpp +++ b/src/autoapp/Service/ServiceFactory.cpp @@ -49,7 +49,7 @@ namespace autoapp namespace service { -ServiceFactory::ServiceFactory(boost::asio::io_service& ioService, configuration::IConfiguration::Pointer configuration, QWidget *activeArea, std::function activeCallback) +ServiceFactory::ServiceFactory(boost::asio::io_service& ioService, configuration::IConfiguration::Pointer configuration, QWidget *activeArea, std::function activeCallback, bool nightMode) : ioService_(ioService) , configuration_(std::move(configuration)) , activeArea_(activeArea) @@ -58,6 +58,7 @@ ServiceFactory::ServiceFactory(boost::asio::io_service& ioService, configuration #ifdef USE_OMX , omxVideoOutput_(std::make_shared(configuration_, this->QRectToDestRect(screenGeometry_), activeCallback_)) #endif + , nightMode_(nightMode) { } @@ -69,7 +70,8 @@ ServiceList ServiceFactory::create(aasdk::messenger::IMessenger::Pointer messeng projection::IAudioInput::Pointer audioInput(new projection::QtAudioInput(1, 16, 16000), std::bind(&QObject::deleteLater, std::placeholders::_1)); serviceList.emplace_back(std::make_shared(ioService_, messenger, std::move(audioInput))); this->createAudioServices(serviceList, messenger); - serviceList.emplace_back(std::make_shared(ioService_, messenger)); + sensorService_ = std::make_shared(ioService_, messenger, nightMode_); + serviceList.emplace_back(sensorService_); serviceList.emplace_back(this->createVideoService(messenger)); serviceList.emplace_back(this->createBluetoothService(messenger)); serviceList.emplace_back(this->createInputService(messenger)); @@ -182,6 +184,12 @@ void ServiceFactory::resize() #endif } +void ServiceFactory::setNightMode(bool nightMode) +{ + nightMode_ = nightMode; + if (sensorService_ != nullptr) sensorService_->setNightMode(nightMode_); +} + QRect ServiceFactory::mapActiveAreaToGlobal(QWidget* activeArea) { if (activeArea == nullptr) From 6cda29433af8af686d93fbce9d45388d6afd0e74 Mon Sep 17 00:00:00 2001 From: Robert Judka Date: Sun, 26 Apr 2020 00:46:57 -0500 Subject: [PATCH 3/7] use weak pointer for sensor service to track actual lifetime --- .../f1x/openauto/autoapp/Service/ServiceFactory.hpp | 2 +- src/autoapp/Service/ServiceFactory.cpp | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp b/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp index 9d79b84..464cc12 100644 --- a/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp +++ b/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp @@ -65,7 +65,7 @@ private: projection::QtVideoOutput *qtVideoOutput_; #endif bool nightMode_; - std::shared_ptr sensorService_; + std::weak_ptr sensorService_; }; } diff --git a/src/autoapp/Service/ServiceFactory.cpp b/src/autoapp/Service/ServiceFactory.cpp index 461751f..55ef7cf 100644 --- a/src/autoapp/Service/ServiceFactory.cpp +++ b/src/autoapp/Service/ServiceFactory.cpp @@ -58,7 +58,7 @@ ServiceFactory::ServiceFactory(boost::asio::io_service& ioService, configuration #ifdef USE_OMX , omxVideoOutput_(std::make_shared(configuration_, this->QRectToDestRect(screenGeometry_), activeCallback_)) #endif - , nightMode_(nightMode) + , nightMode_(nightMode) { } @@ -70,8 +70,11 @@ ServiceList ServiceFactory::create(aasdk::messenger::IMessenger::Pointer messeng projection::IAudioInput::Pointer audioInput(new projection::QtAudioInput(1, 16, 16000), std::bind(&QObject::deleteLater, std::placeholders::_1)); serviceList.emplace_back(std::make_shared(ioService_, messenger, std::move(audioInput))); this->createAudioServices(serviceList, messenger); - sensorService_ = std::make_shared(ioService_, messenger, nightMode_); - serviceList.emplace_back(sensorService_); + + std::shared_ptr sensorService = std::make_shared(ioService_, messenger, nightMode_); + sensorService_ = sensorService; + serviceList.emplace_back(sensorService); + serviceList.emplace_back(this->createVideoService(messenger)); serviceList.emplace_back(this->createBluetoothService(messenger)); serviceList.emplace_back(this->createInputService(messenger)); @@ -187,7 +190,7 @@ void ServiceFactory::resize() void ServiceFactory::setNightMode(bool nightMode) { nightMode_ = nightMode; - if (sensorService_ != nullptr) sensorService_->setNightMode(nightMode_); + if (std::shared_ptr sensorService = sensorService_.lock()) sensorService->setNightMode(nightMode_); } QRect ServiceFactory::mapActiveAreaToGlobal(QWidget* activeArea) From 254382acf640b1b32404ef66aa2a3fe98ead68ae Mon Sep 17 00:00:00 2001 From: Robert Stanley Judka Date: Sat, 16 May 2020 19:14:48 -0500 Subject: [PATCH 4/7] fix fragile qtvideooutput (#3) --- src/autoapp/Service/ServiceFactory.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/autoapp/Service/ServiceFactory.cpp b/src/autoapp/Service/ServiceFactory.cpp index 55ef7cf..cee69a9 100644 --- a/src/autoapp/Service/ServiceFactory.cpp +++ b/src/autoapp/Service/ServiceFactory.cpp @@ -57,6 +57,8 @@ ServiceFactory::ServiceFactory(boost::asio::io_service& ioService, configuration , activeCallback_(activeCallback) #ifdef USE_OMX , omxVideoOutput_(std::make_shared(configuration_, this->QRectToDestRect(screenGeometry_), activeCallback_)) +#else + , qtVideoOutput_(nullptr) #endif , nightMode_(nightMode) { @@ -90,7 +92,11 @@ IService::Pointer ServiceFactory::createVideoService(aasdk::messenger::IMessenge qtVideoOutput_ = new projection::QtVideoOutput(configuration_, activeArea_); if (activeCallback_ != nullptr) { QObject::connect(qtVideoOutput_, &projection::QtVideoOutput::startPlayback, [callback = activeCallback_]() { callback(true); }); - QObject::connect(qtVideoOutput_, &projection::QtVideoOutput::stopPlayback, [callback = activeCallback_]() { callback(false); }); + QObject::connect(qtVideoOutput_, &projection::QtVideoOutput::stopPlayback, [this]() { + activeCallback_(false); + qtVideoOutput_->disconnect(); + qtVideoOutput_ = nullptr; + }); } projection::IVideoOutput::Pointer videoOutput(qtVideoOutput_, std::bind(&QObject::deleteLater, std::placeholders::_1)); #endif From 5b0543ac10981500abae05a0e1e0ea4f6e3ba41d Mon Sep 17 00:00:00 2001 From: Robert Stanley Judka Date: Mon, 25 May 2020 21:27:32 -0500 Subject: [PATCH 5/7] add gstreamer support (#4) * Implementing Gstreamer projection * Moved back to QtQuick video sink, still no display * "works" but spikes cpu * merge upstream develop * Missed a merge conflict * added resize * GSTVideoOutput works within ia openauto frame now * Fixed up cmake for gst * Add destructor for GST * Added PI4 support * Accidently added a bad cmake run at some point * Stylistic changes * Cleaning up unused variables * Stylistic update * Stylistic Changes * Quick merge fix * Review feedback * Post review feedback * Left handed pointers/CMake fix Co-authored-by: Cole Brinsfield --- CMakeLists.txt | 45 +++- assets/aa_video.qml | 9 + assets/resources.qrc | 1 + cmake_modules/FindGObject.cmake | 80 ++++++ cmake_modules/FindGStreamer.cmake | 135 ++++++++++ cmake_modules/functions.cmake | 15 ++ .../autoapp/Projection/GSTVideoOutput.hpp | 92 +++++++ .../autoapp/Service/ServiceFactory.hpp | 4 + src/autoapp/Projection/GSTVideoOutput.cpp | 233 ++++++++++++++++++ src/autoapp/Service/ServiceFactory.cpp | 7 + 10 files changed, 614 insertions(+), 7 deletions(-) create mode 100644 assets/aa_video.qml create mode 100644 cmake_modules/FindGObject.cmake create mode 100644 cmake_modules/FindGStreamer.cmake create mode 100644 cmake_modules/functions.cmake create mode 100644 include/f1x/openauto/autoapp/Projection/GSTVideoOutput.hpp create mode 100644 src/autoapp/Projection/GSTVideoOutput.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 03e73dd..28b4376 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ set(base_directory ${CMAKE_CURRENT_SOURCE_DIR}) set(resources_directory ${base_directory}/assets) set(sources_directory ${base_directory}/src) set(include_directory ${base_directory}/include) +include(${base_directory}/cmake_modules/functions.cmake) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${base_directory}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${base_directory}/lib) @@ -29,28 +30,46 @@ add_definitions(-DBOOST_ALL_DYN_LINK) find_package(Boost REQUIRED COMPONENTS system log OPTIONAL_COMPONENTS unit_test_framework) find_package(libusb-1.0 REQUIRED) -find_package(Qt5 COMPONENTS Multimedia MultimediaWidgets Bluetooth) +find_package(Qt5 COMPONENTS Multimedia MultimediaWidgets Bluetooth Qml Quick QuickWidgets REQUIRED) find_package(Protobuf REQUIRED) find_package(OpenSSL REQUIRED) find_package(rtaudio REQUIRED) - +find_package(GObject) if(WIN32) set(WINSOCK2_LIBRARIES "ws2_32") endif(WIN32) -if(RPI_BUILD) +if(RPI_BUILD AND NOT GST_BUILD) add_definitions(-DUSE_OMX -DOMX_SKIP64BIT) set(BCM_HOST_LIBRARIES "/opt/vc/lib/libbcm_host.so") set(BCM_HOST_INCLUDE_DIRS "/opt/vc/include") set(ILCLIENT_INCLUDE_DIRS "/opt/vc/src/hello_pi/libs/ilclient") set(ILCLIENT_LIBRARIES "/opt/vc/src/hello_pi/libs/ilclient/libilclient.a;/opt/vc/lib/libvcos.so;/opt/vc/lib/libvcilcs.a;/opt/vc/lib/libvchiq_arm.so") -endif(RPI_BUILD) +endif(RPI_BUILD AND NOT GST_BUILD) +if(GST_BUILD) + find_package(Qt5GStreamer) + find_package(PkgConfig REQUIRED) + pkg_check_modules(GST REQUIRED gstreamer-1.0>=1.4 + gstreamer-sdp-1.0>=1.4 + gstreamer-video-1.0>=1.4 + gstreamer-app-1.0>=1.4) + add_definitions(-DUSE_GST) + if(RPI_BUILD) + add_definitions(-DRPI) + findRpiRevision( RPI_REVISION ) + if(RPI_REVISION MATCHES "a03111" OR RPI_REVISION MATCHES "b03111" OR RPI_REVISION MATCHES "a03111") + message("Raspberry Pi 4 Found") + add_definitions(-DPI4) + endif(RPI_REVISION MATCHES "a03111" OR RPI_REVISION MATCHES "b03111" OR RPI_REVISION MATCHES "a03111") + endif(RPI_BUILD) +endif(GST_BUILD) include_directories(${CMAKE_CURRENT_BINARY_DIR} ${Qt5Multimedia_INCLUDE_DIRS} ${Qt5MultimediaWidgets_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Bluetooth_INCLUDE_DIRS} + ${QTGSTREAMER_INCLUDE_DIR} ${Boost_INCLUDE_DIRS} ${LIBUSB_1_INCLUDE_DIRS} ${PROTOBUF_INCLUDE_DIR} @@ -60,8 +79,9 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR} ${AASDK_INCLUDE_DIRS} ${BCM_HOST_INCLUDE_DIRS} ${ILCLIENT_INCLUDE_DIRS} + ${GST_INCLUDE_DIRS} ${include_directory}) - + link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) set(common_include_directory ${include_directory}/f1x/openauto/Common) @@ -75,11 +95,13 @@ add_executable(autoapp ${autoapp_source_files}) file(GLOB_RECURSE autoapp_lib_source_files ${autoapp_sources_directory}/App.cpp ${autoapp_sources_directory}/Configuration/*.cpp ${autoapp_sources_directory}/Projection/*.cpp ${autoapp_sources_directory}/Service/*.cpp) file(GLOB_RECURSE autoapp_lib_inlcude_files ${autoapp_include_directory}/App.hpp ${autoapp_include_directory}/Configuration/*.hpp ${autoapp_include_directory}/Projection/*.hpp ${autoapp_include_directory}/Service/*.hpp) add_library(auto SHARED ${autoapp_lib_source_files} ${autoapp_lib_inlcude_files}) - +message(STATUS "${GST_LIBRARIES}") target_link_libraries(autoapp + ${GST_LIBRARIES} ${Boost_LIBRARIES} ${Qt5Multimedia_LIBRARIES} ${Qt5MultimediaWidgets_LIBRARIES} + ${Qt5QuickWidgets_LIBRARIES} ${Qt5Bluetooth_LIBRARIES} ${LIBUSB_1_LIBRARIES} ${PROTOBUF_LIBRARIES} @@ -88,7 +110,16 @@ target_link_libraries(autoapp ${WINSOCK2_LIBRARIES} ${RTAUDIO_LIBRARIES} ${AASDK_PROTO_LIBRARIES} - ${AASDK_LIBRARIES}) + ${AASDK_LIBRARIES} + ${QTGLIB_LIBRARY} + ${QTGLIB_LIBRARIES} + ${QTGSTREAMER_LIBRARY} + ${QTGSTREAMER_LIBRARIES} + ${QTGSTREAMER_UI_LIBRARY} + ${QTGSTREAMER_UI_LIBRARIES} + ${QTGSTREAMER_QUICK_LIBRARIES} + ${QTGSTREAMER_QUICK_LIBRARY} + ${GOBJECT_LIBRARIES}) set(btservice_sources_directory ${sources_directory}/btservice) set(btservice_include_directory ${include_directory}/f1x/openauto/btservice) diff --git a/assets/aa_video.qml b/assets/aa_video.qml new file mode 100644 index 0000000..f0f7dc7 --- /dev/null +++ b/assets/aa_video.qml @@ -0,0 +1,9 @@ +import QtQuick 2.0 +import QtGStreamer 1.0 + +VideoItem { + id: aaVideo + width: 300 + height: 300 + surface: videoSurface +} diff --git a/assets/resources.qrc b/assets/resources.qrc index 1070e2d..c159d57 100644 --- a/assets/resources.qrc +++ b/assets/resources.qrc @@ -4,5 +4,6 @@ ico_warning.png ico_setting.png ico_info.png + aa_video.qml diff --git a/cmake_modules/FindGObject.cmake b/cmake_modules/FindGObject.cmake new file mode 100644 index 0000000..d9e8df9 --- /dev/null +++ b/cmake_modules/FindGObject.cmake @@ -0,0 +1,80 @@ +# - Try to find GObject +# Once done this will define +# +# GOBJECT_FOUND - system has GObject +# GOBJECT_INCLUDE_DIR - the GObject include directory +# GOBJECT_LIBRARIES - the libraries needed to use GObject +# GOBJECT_DEFINITIONS - Compiler switches required for using GObject + +# Copyright (c) 2006, Tim Beaulen +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + + +IF (GOBJECT_INCLUDE_DIR AND GOBJECT_LIBRARIES) + # in cache already + SET(GObject_FIND_QUIETLY TRUE) +ELSE (GOBJECT_INCLUDE_DIR AND GOBJECT_LIBRARIES) + SET(GObject_FIND_QUIETLY FALSE) +ENDIF (GOBJECT_INCLUDE_DIR AND GOBJECT_LIBRARIES) + +IF (NOT WIN32) + # use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + FIND_PACKAGE(PkgConfig) + PKG_CHECK_MODULES(PC_GOBJECT gobject-2.0) + #MESSAGE(STATUS "DEBUG: GObject include directory = ${GOBJECT_INCLUDE_DIRS}") + #MESSAGE(STATUS "DEBUG: GObject link directory = ${GOBJECT_LIBRARY_DIRS}") + #MESSAGE(STATUS "DEBUG: GObject CFlags = ${GOBJECT_CFLAGS}") + SET(GOBJECT_DEFINITIONS ${PC_GOBJECT_CFLAGS_OTHER}) +ENDIF (NOT WIN32) + +FIND_PATH(GOBJECT_INCLUDE_DIR gobject.h + PATHS + ${PC_GOBJECT_INCLUDEDIR} + ${PC_GOBJECT_INCLUDE_DIRS} + PATH_SUFFIXES glib-2.0/gobject/ + ) + +FIND_LIBRARY(_GObjectLibs NAMES gobject-2.0 + PATHS + ${PC_GOBJECT_LIBDIR} + ${PC_GOBJECT_LIBRARY_DIRS} + ) +FIND_LIBRARY(_GModuleLibs NAMES gmodule-2.0 + PATHS + ${PC_GOBJECT_LIBDIR} + ${PC_GOBJECT_LIBRARY_DIRS} + ) +FIND_LIBRARY(_GThreadLibs NAMES gthread-2.0 + PATHS + ${PC_GOBJECT_LIBDIR} + ${PC_GOBJECT_LIBRARY_DIRS} + ) +FIND_LIBRARY(_GLibs NAMES glib-2.0 + PATHS + ${PC_GOBJECT_LIBDIR} + ${PC_GOBJECT_LIBRARY_DIRS} + ) + +SET( GOBJECT_LIBRARIES ${_GObjectLibs} ${_GModuleLibs} ${_GThreadLibs} ${_GLibs} ) + +IF (GOBJECT_INCLUDE_DIR AND GOBJECT_LIBRARIES) + SET(GOBJECT_FOUND TRUE) +ELSE (GOBJECT_INCLUDE_DIR AND GOBJECT_LIBRARIES) + SET(GOBJECT_FOUND FALSE) +ENDIF (GOBJECT_INCLUDE_DIR AND GOBJECT_LIBRARIES) + +IF (GOBJECT_FOUND) + IF (NOT GObject_FIND_QUIETLY) + MESSAGE(STATUS "Found GObject libraries: ${GOBJECT_LIBRARIES}") + MESSAGE(STATUS "Found GObject includes : ${GOBJECT_INCLUDE_DIR}") + ENDIF (NOT GObject_FIND_QUIETLY) +ELSE (GOBJECT_FOUND) + IF (GObject_FIND_REQUIRED) + MESSAGE(STATUS "Could NOT find GObject") + ENDIF(GObject_FIND_REQUIRED) +ENDIF (GOBJECT_FOUND) + +MARK_AS_ADVANCED(GOBJECT_INCLUDE_DIR _GObjectLibs _GModuleLibs _GThreadLibs _GLibs) diff --git a/cmake_modules/FindGStreamer.cmake b/cmake_modules/FindGStreamer.cmake new file mode 100644 index 0000000..b508efe --- /dev/null +++ b/cmake_modules/FindGStreamer.cmake @@ -0,0 +1,135 @@ +# - Try to find GStreamer and its plugins +# Once done, this will define +# +# GSTREAMER_FOUND - system has GStreamer +# GSTREAMER_INCLUDE_DIRS - the GStreamer include directories +# GSTREAMER_LIBRARIES - link these to use GStreamer +# +# Additionally, gstreamer-base is always looked for and required, and +# the following related variables are defined: +# +# GSTREAMER_BASE_INCLUDE_DIRS - gstreamer-base's include directory +# GSTREAMER_BASE_LIBRARIES - link to these to use gstreamer-base +# +# Optionally, the COMPONENTS keyword can be passed to find_package() +# and GStreamer plugins can be looked for. Currently, the following +# plugins can be searched, and they define the following variables if +# found: +# +# gstreamer-app: GSTREAMER_APP_INCLUDE_DIRS and GSTREAMER_APP_LIBRARIES +# gstreamer-audio: GSTREAMER_AUDIO_INCLUDE_DIRS and GSTREAMER_AUDIO_LIBRARIES +# gstreamer-fft: GSTREAMER_FFT_INCLUDE_DIRS and GSTREAMER_FFT_LIBRARIES +# gstreamer-gl: GSTREAMER_GL_INCLUDE_DIRS and GSTREAMER_GL_LIBRARIES +# gstreamer-mpegts: GSTREAMER_MPEGTS_INCLUDE_DIRS and GSTREAMER_MPEGTS_LIBRARIES +# gstreamer-pbutils: GSTREAMER_PBUTILS_INCLUDE_DIRS and GSTREAMER_PBUTILS_LIBRARIES +# gstreamer-tag: GSTREAMER_TAG_INCLUDE_DIRS and GSTREAMER_TAG_LIBRARIES +# gstreamer-video: GSTREAMER_VIDEO_INCLUDE_DIRS and GSTREAMER_VIDEO_LIBRARIES +# gstreamer-codecparser:GSTREAMER_CODECPARSERS_INCLUDE_DIRS and GSTREAMER_CODECPARSERS_LIBRARIES +# +# Copyright (C) 2012 Raphael Kubo da Costa +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS +# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +find_package(PkgConfig QUIET) + +# Helper macro to find a GStreamer plugin (or GStreamer itself) +# _component_prefix is prepended to the _INCLUDE_DIRS and _LIBRARIES variables (eg. "GSTREAMER_AUDIO") +# _pkgconfig_name is the component's pkg-config name (eg. "gstreamer-1.0", or "gstreamer-video-1.0"). +# _library is the component's library name (eg. "gstreamer-1.0" or "gstvideo-1.0") +macro(FIND_GSTREAMER_COMPONENT _component_prefix _pkgconfig_name _library) + + string(REGEX MATCH "(.*)>=(.*)" _dummy "${_pkgconfig_name}") + if ("${CMAKE_MATCH_2}" STREQUAL "") + pkg_check_modules(PC_${_component_prefix} "${_pkgconfig_name} >= ${GStreamer_FIND_VERSION}") + else () + pkg_check_modules(PC_${_component_prefix} ${_pkgconfig_name}) + endif () + set(${_component_prefix}_INCLUDE_DIRS ${PC_${_component_prefix}_INCLUDE_DIRS}) + + find_library(${_component_prefix}_LIBRARIES + NAMES ${_library} + HINTS ${PC_${_component_prefix}_LIBRARY_DIRS} ${PC_${_component_prefix}_LIBDIR} + ) +endmacro() + +# ------------------------ +# 1. Find GStreamer itself +# ------------------------ + +# 1.1. Find headers and libraries +FIND_GSTREAMER_COMPONENT(GSTREAMER gstreamer-1.0 gstreamer-1.0) +FIND_GSTREAMER_COMPONENT(GSTREAMER_BASE gstreamer-base-1.0 gstbase-1.0) + +# ------------------------- +# 2. Find GStreamer plugins +# ------------------------- + +FIND_GSTREAMER_COMPONENT(GSTREAMER_APP gstreamer-app-1.0 gstapp-1.0) +FIND_GSTREAMER_COMPONENT(GSTREAMER_AUDIO gstreamer-audio-1.0 gstaudio-1.0) +FIND_GSTREAMER_COMPONENT(GSTREAMER_FFT gstreamer-fft-1.0 gstfft-1.0) +FIND_GSTREAMER_COMPONENT(GSTREAMER_GL gstreamer-gl-1.0 gstgl-1.0) +FIND_GSTREAMER_COMPONENT(GSTREAMER_MPEGTS gstreamer-mpegts-1.0>=1.4.0 gstmpegts-1.0) +FIND_GSTREAMER_COMPONENT(GSTREAMER_PBUTILS gstreamer-pbutils-1.0 gstpbutils-1.0) +FIND_GSTREAMER_COMPONENT(GSTREAMER_TAG gstreamer-tag-1.0 gsttag-1.0) +FIND_GSTREAMER_COMPONENT(GSTREAMER_VIDEO gstreamer-video-1.0 gstvideo-1.0) +FIND_GSTREAMER_COMPONENT(GSTREAMER_CODECPARSERS gstreamer-codecparsers-1.0 gstcodecparsers-1.0) + +# ------------------------------------------------ +# 3. Process the COMPONENTS passed to FIND_PACKAGE +# ------------------------------------------------ +set(_GSTREAMER_REQUIRED_VARS GSTREAMER_INCLUDE_DIRS GSTREAMER_LIBRARIES GSTREAMER_VERSION GSTREAMER_BASE_INCLUDE_DIRS GSTREAMER_BASE_LIBRARIES) + +foreach (_component ${GStreamer_FIND_COMPONENTS}) + set(_gst_component "GSTREAMER_${_component}") + string(TOUPPER ${_gst_component} _UPPER_NAME) + + list(APPEND _GSTREAMER_REQUIRED_VARS ${_UPPER_NAME}_INCLUDE_DIRS ${_UPPER_NAME}_LIBRARIES) +endforeach () + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(GStreamer REQUIRED_VARS _GSTREAMER_REQUIRED_VARS + VERSION_VAR GSTREAMER_VERSION) + +mark_as_advanced( + GSTREAMER_APP_INCLUDE_DIRS + GSTREAMER_APP_LIBRARIES + GSTREAMER_AUDIO_INCLUDE_DIRS + GSTREAMER_AUDIO_LIBRARIES + GSTREAMER_BASE_INCLUDE_DIRS + GSTREAMER_BASE_LIBRARIES + GSTREAMER_FFT_INCLUDE_DIRS + GSTREAMER_FFT_LIBRARIES + GSTREAMER_GL_INCLUDE_DIRS + GSTREAMER_GL_LIBRARIES + GSTREAMER_INCLUDE_DIRS + GSTREAMER_LIBRARIES + GSTREAMER_MPEGTS_INCLUDE_DIRS + GSTREAMER_MPEGTS_LIBRARIES + GSTREAMER_PBUTILS_INCLUDE_DIRS + GSTREAMER_PBUTILS_LIBRARIES + GSTREAMER_TAG_INCLUDE_DIRS + GSTREAMER_TAG_LIBRARIES + GSTREAMER_VIDEO_INCLUDE_DIRS + GSTREAMER_VIDEO_LIBRARIES + GSTREAMER_CODECPARSERS_INCLUDE_DIRS + GSTREAMER_CODECPARSERS_LIBRARIES +) diff --git a/cmake_modules/functions.cmake b/cmake_modules/functions.cmake new file mode 100644 index 0000000..b01988e --- /dev/null +++ b/cmake_modules/functions.cmake @@ -0,0 +1,15 @@ + +function( findRpiRevision OUTPUT ) + # Find it with an automated script + execute_process( COMMAND grep -Po "^Revision\\s*:\\s*\\K[[:xdigit:]]+" /proc/cpuinfo OUTPUT_VARIABLE TMP ) + + # If have not found the Revision number, use the last version + if ( TMP ) + message( "-- Detecting Raspberry Pi Revision Number: ${TMP}" ) + else() + set( TMP "0006" ) + message( WARNING "-- Could NOT find Raspberry Pi revision!" ) + endif() + + set( ${OUTPUT} "${TMP}" PARENT_SCOPE ) +endfunction() diff --git a/include/f1x/openauto/autoapp/Projection/GSTVideoOutput.hpp b/include/f1x/openauto/autoapp/Projection/GSTVideoOutput.hpp new file mode 100644 index 0000000..33bb2f8 --- /dev/null +++ b/include/f1x/openauto/autoapp/Projection/GSTVideoOutput.hpp @@ -0,0 +1,92 @@ +/* +* This file is part of openauto project. +* Copyright (C) 2018 f1x.studio (Michal Szwaj) +* +* openauto is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 3 of the License, or +* (at your option) any later version. + +* openauto is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with openauto. If not, see . +*/ +#ifdef USE_GST + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace f1x +{ +namespace openauto +{ +namespace autoapp +{ +namespace projection +{ + +class GSTVideoOutput: public QObject, public VideoOutput, boost::noncopyable +{ + Q_OBJECT + +public: + GSTVideoOutput(configuration::IConfiguration::Pointer configuration, QWidget* videoContainer=nullptr, std::function activeCallback=nullptr); + ~GSTVideoOutput(); + bool open() override; + bool init() override; + void write(uint64_t timestamp, const aasdk::common::DataConstBuffer& buffer) override; + void stop() override; + void resize(); +signals: + void startPlayback(); + void stopPlayback(); +protected slots: + void onStartPlayback(); + void onStopPlayback(); +private: + static GstPadProbeReturn convert_probe(GstPad* pad, GstPadProbeInfo* info, void* user_data); + static gboolean bus_callback(GstBus* bus, GstMessage* message, gpointer* ptr); + + QGst::ElementPtr videoSink_; + QQuickWidget* videoWidget_; + GstElement* vidPipeline_ = nullptr; + GstAppSrc* vidSrc_ = nullptr; + QWidget* videoContainer_; + QGst::Quick::VideoSurface* surface_; + std::function activeCallback_; +}; + +} +} +} +} + +#endif diff --git a/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp b/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp index 464cc12..8a1d02e 100644 --- a/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp +++ b/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include @@ -61,6 +63,8 @@ private: std::shared_ptr inputDevice_; #ifdef USE_OMX std::shared_ptr omxVideoOutput_; +#elif defined USE_GST + std::shared_ptr gstVideoOutput_; #else projection::QtVideoOutput *qtVideoOutput_; #endif diff --git a/src/autoapp/Projection/GSTVideoOutput.cpp b/src/autoapp/Projection/GSTVideoOutput.cpp new file mode 100644 index 0000000..b29d260 --- /dev/null +++ b/src/autoapp/Projection/GSTVideoOutput.cpp @@ -0,0 +1,233 @@ +/* +* This file is part of openauto project. +* Copyright (C) 2018 f1x.studio (Michal Szwaj) +* +* openauto is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 3 of the License, or +* (at your option) any later version. + +* openauto is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with openauto. If not, see . +*/ + +#ifdef USE_GST + +#include +#include +#include + +namespace f1x +{ +namespace openauto +{ +namespace autoapp +{ +namespace projection +{ + +GSTVideoOutput::GSTVideoOutput(configuration::IConfiguration::Pointer configuration, QWidget* videoContainer, std::function activeCallback) + : VideoOutput(std::move(configuration)) + , videoContainer_(videoContainer) + , activeCallback_(activeCallback) +{ + this->moveToThread(QApplication::instance()->thread()); + videoWidget_ = new QQuickWidget(videoContainer_); + + surface_ = new QGst::Quick::VideoSurface; + videoWidget_->rootContext()->setContextProperty(QLatin1String("videoSurface"), surface_); + videoWidget_->setSource(QUrl("qrc:/aa_video.qml")); + videoWidget_->setResizeMode(QQuickWidget::SizeRootObjectToView); + + videoSink_ = surface_->videoSink(); + GstBus* bus; + + GError* error = NULL; + const char* vidLaunchStr = "appsrc name=mysrc is-live=true block=false max-latency=100 do-timestamp=true stream-type=stream ! " + "queue ! " + + "h264parse ! " + #ifdef RPI + #ifdef PI4 + " v4l2h264dec !" + #else + " omxh264dec ! " + #endif + #else + "avdec_h264 ! " + #endif + "capsfilter caps=video/x-raw name=mycapsfilter"; + #ifdef RPI + OPENAUTO_LOG(info) << "[GSTVideoOutput] RPI Build, running with " << + #ifdef PI4 + "v4l2h264dec"; + #else + "omxh264dec"; + #endif + #endif + + vidPipeline_ = gst_parse_launch(vidLaunchStr, &error); + bus = gst_pipeline_get_bus(GST_PIPELINE(vidPipeline_)); + gst_bus_add_watch(bus, (GstBusFunc)GSTVideoOutput::bus_callback, this); + gst_object_unref(bus); + + GstElement* sink = QGlib::RefPointer(videoSink_); + g_object_set (sink, "force-aspect-ratio", false, nullptr); + + g_object_set (sink, "sync", false, nullptr); + g_object_set (sink, "async", false, nullptr); + GstElement* capsFilter = gst_bin_get_by_name(GST_BIN(vidPipeline_), "mycapsfilter"); + gst_bin_add(GST_BIN(vidPipeline_), GST_ELEMENT(sink)); + gst_element_link(capsFilter, GST_ELEMENT(sink)); + + vidSrc_ = GST_APP_SRC(gst_bin_get_by_name(GST_BIN(vidPipeline_), "mysrc")); + gst_app_src_set_stream_type(vidSrc_, GST_APP_STREAM_TYPE_STREAM); + + connect(this, &GSTVideoOutput::startPlayback, this, &GSTVideoOutput::onStartPlayback, Qt::QueuedConnection); + connect(this, &GSTVideoOutput::stopPlayback, this, &GSTVideoOutput::onStopPlayback, Qt::QueuedConnection); +} + + +GSTVideoOutput::~GSTVideoOutput() +{ + gst_object_unref(vidPipeline_); + gst_object_unref(vidSrc_); +} + +gboolean GSTVideoOutput::bus_callback(GstBus* /* unused*/, GstMessage* message, gpointer* ptr) +{ + gchar* debug; + GError* err; + gchar* name; + + switch(GST_MESSAGE_TYPE(message)) + { + case GST_MESSAGE_ERROR: + gst_message_parse_error(message, &err, &debug); + OPENAUTO_LOG(info) << "[GSTVideoOutput] Error " << err->message; + g_error_free(err); + g_free(debug); + break; + case GST_MESSAGE_WARNING: + gst_message_parse_warning(message, &err, &debug); + OPENAUTO_LOG(info) << "[GSTVideoOutput] Warning " << err->message<<" | Debug " << debug; + name = (gchar*)GST_MESSAGE_SRC_NAME(message); + OPENAUTO_LOG(info) << "[GSTVideoOutput] Name of src " << name ? name : "nil"; + g_error_free(err); + g_free(debug); + break; + case GST_MESSAGE_EOS: + OPENAUTO_LOG(info) << "[GSTVideoOutput] End of stream"; + break; + case GST_MESSAGE_STATE_CHANGED: + break; + default: + break; + } + + return TRUE; +} + +bool GSTVideoOutput::open() +{ + GstElement* capsFilter = gst_bin_get_by_name(GST_BIN(vidPipeline_), "mycapsfilter"); + GstPad* convertPad = gst_element_get_static_pad(capsFilter, "sink"); + gst_pad_add_probe (convertPad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, convert_probe, this, NULL); + gst_element_set_state(vidPipeline_, GST_STATE_PLAYING); + return true; +} + +GstPadProbeReturn GSTVideoOutput::convert_probe(GstPad* pad, GstPadProbeInfo* info, void* user_data) +{ + GstEvent* event = GST_PAD_PROBE_INFO_EVENT(info); + if(GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) { + if(GST_EVENT_TYPE(event) == GST_EVENT_SEGMENT) { + GstCaps* caps = gst_pad_get_current_caps(pad); + if(caps != NULL) + { + GstVideoInfo* vinfo = gst_video_info_new(); + gst_video_info_from_caps(vinfo, caps); + OPENAUTO_LOG(info) << "[GSTVideoOutput] Video Width: "<< vinfo->width; + OPENAUTO_LOG(info) << "[GSTVideoOutput] Video Height: "<< vinfo->height; + + + } + return GST_PAD_PROBE_REMOVE; + } + } + return GST_PAD_PROBE_OK; +} + +bool GSTVideoOutput::init() +{ + OPENAUTO_LOG(info) << "[GSTVideoOutput] init"; + emit startPlayback(); + return true; +} + +void GSTVideoOutput::write(uint64_t timestamp, const aasdk::common::DataConstBuffer& buffer) +{ + GstBuffer* buffer_ = gst_buffer_new_and_alloc(buffer.size); + gst_buffer_fill(buffer_, 0, buffer.cdata, buffer.size); + int ret = gst_app_src_push_buffer((GstAppSrc*)vidSrc_, buffer_); + if(ret != GST_FLOW_OK) + { + OPENAUTO_LOG(info) << "[GSTVideoOutput] push buffer returned " << ret << " for " << buffer.size << "bytes"; + } +} + +void GSTVideoOutput::onStartPlayback() +{ + if(activeCallback_ != nullptr) + { + activeCallback_(true); + } + if(videoContainer_ == nullptr) + { + OPENAUTO_LOG(info) << "[GSTVideoOutput] No video container, setting projection fullscreen"; + videoWidget_->setFocus(); + videoWidget_->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint); + videoWidget_->showFullScreen(); + } + else + { + OPENAUTO_LOG(info) << "[GSTVideoOutput] Resizing to video container"; + videoWidget_->resize(videoContainer_->size()); + } + videoWidget_->show(); +} + +void GSTVideoOutput::stop() +{ + emit stopPlayback(); +} + +void GSTVideoOutput::onStopPlayback() +{ + if(activeCallback_ != nullptr) + { + activeCallback_(false); + } + OPENAUTO_LOG(info) << "[GSTVideoOutput] stop."; + gst_element_set_state(vidPipeline_, GST_STATE_PAUSED); + videoWidget_->hide(); +} + +void GSTVideoOutput::resize() +{ + OPENAUTO_LOG(info) << "[GSTVideoOutput] Got resize request to "<< videoContainer_->width() << "x" << videoContainer_->height(); + + if(videoWidget_ != nullptr && videoContainer_ != nullptr) videoWidget_->resize(videoContainer_->size()); +} + +} +} +} +} + +#endif diff --git a/src/autoapp/Service/ServiceFactory.cpp b/src/autoapp/Service/ServiceFactory.cpp index cee69a9..22df94f 100644 --- a/src/autoapp/Service/ServiceFactory.cpp +++ b/src/autoapp/Service/ServiceFactory.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,8 @@ ServiceFactory::ServiceFactory(boost::asio::io_service& ioService, configuration , activeCallback_(activeCallback) #ifdef USE_OMX , omxVideoOutput_(std::make_shared(configuration_, this->QRectToDestRect(screenGeometry_), activeCallback_)) +#elif defined USE_GST + , gstVideoOutput_((QGst::init(nullptr, nullptr), std::make_shared(configuration_, activeArea_, activeCallback_))) #else , qtVideoOutput_(nullptr) #endif @@ -88,6 +91,8 @@ IService::Pointer ServiceFactory::createVideoService(aasdk::messenger::IMessenge { #ifdef USE_OMX auto videoOutput(omxVideoOutput_); +#elif defined USE_GST + auto videoOutput(gstVideoOutput_); #else qtVideoOutput_ = new projection::QtVideoOutput(configuration_, activeArea_); if (activeCallback_ != nullptr) { @@ -188,6 +193,8 @@ void ServiceFactory::resize() if (inputDevice_ != nullptr) inputDevice_->setTouchscreenGeometry(screenGeometry_); #ifdef USE_OMX if (omxVideoOutput_ != nullptr) omxVideoOutput_->setDestRect(this->QRectToDestRect(screenGeometry_)); +#elif defined USE_GST + if (gstVideoOutput_ != nullptr) gstVideoOutput_->resize(); #else if (qtVideoOutput_ != nullptr) qtVideoOutput_->resize(); #endif From c806b15b6155bfb765a0ff620089a1a6927fd920 Mon Sep 17 00:00:00 2001 From: Robert Stanley Judka Date: Mon, 22 Jun 2020 15:59:33 -0500 Subject: [PATCH 6/7] add interface to send keyevents (#5) * explicitly send keyevent to input device; style cleanup * more style updates * more style conformity --- CMakeLists.txt | 13 ++-- .../autoapp/Projection/GSTVideoOutput.hpp | 15 ++-- .../autoapp/Service/SensorService.hpp | 2 +- .../autoapp/Service/ServiceFactory.hpp | 6 +- src/autoapp/Projection/GSTVideoOutput.cpp | 69 ++++++++++--------- src/autoapp/Projection/OMXVideoOutput.cpp | 2 +- src/autoapp/Projection/QtVideoOutput.cpp | 7 +- src/autoapp/Service/ServiceFactory.cpp | 49 ++++++++++--- 8 files changed, 102 insertions(+), 61 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 28b4376..843a2c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,7 @@ find_package(Protobuf REQUIRED) find_package(OpenSSL REQUIRED) find_package(rtaudio REQUIRED) find_package(GObject) + if(WIN32) set(WINSOCK2_LIBRARIES "ws2_32") endif(WIN32) @@ -49,10 +50,11 @@ endif(RPI_BUILD AND NOT GST_BUILD) if(GST_BUILD) find_package(Qt5GStreamer) find_package(PkgConfig REQUIRED) - pkg_check_modules(GST REQUIRED gstreamer-1.0>=1.4 - gstreamer-sdp-1.0>=1.4 - gstreamer-video-1.0>=1.4 - gstreamer-app-1.0>=1.4) + pkg_check_modules(GST REQUIRED + gstreamer-1.0>=1.4 + gstreamer-sdp-1.0>=1.4 + gstreamer-video-1.0>=1.4 + gstreamer-app-1.0>=1.4) add_definitions(-DUSE_GST) if(RPI_BUILD) add_definitions(-DRPI) @@ -61,7 +63,7 @@ if(GST_BUILD) message("Raspberry Pi 4 Found") add_definitions(-DPI4) endif(RPI_REVISION MATCHES "a03111" OR RPI_REVISION MATCHES "b03111" OR RPI_REVISION MATCHES "a03111") - endif(RPI_BUILD) + endif(RPI_BUILD) endif(GST_BUILD) include_directories(${CMAKE_CURRENT_BINARY_DIR} @@ -96,6 +98,7 @@ file(GLOB_RECURSE autoapp_lib_source_files ${autoapp_sources_directory}/App.cpp file(GLOB_RECURSE autoapp_lib_inlcude_files ${autoapp_include_directory}/App.hpp ${autoapp_include_directory}/Configuration/*.hpp ${autoapp_include_directory}/Projection/*.hpp ${autoapp_include_directory}/Service/*.hpp) add_library(auto SHARED ${autoapp_lib_source_files} ${autoapp_lib_inlcude_files}) message(STATUS "${GST_LIBRARIES}") + target_link_libraries(autoapp ${GST_LIBRARIES} ${Boost_LIBRARIES} diff --git a/include/f1x/openauto/autoapp/Projection/GSTVideoOutput.hpp b/include/f1x/openauto/autoapp/Projection/GSTVideoOutput.hpp index 33bb2f8..8be352c 100644 --- a/include/f1x/openauto/autoapp/Projection/GSTVideoOutput.hpp +++ b/include/f1x/openauto/autoapp/Projection/GSTVideoOutput.hpp @@ -15,14 +15,16 @@ * You should have received a copy of the GNU General Public License * along with openauto. If not, see . */ -#ifdef USE_GST +#ifdef USE_GST #pragma once + #include #include #include #include #include +#include #include #include #include @@ -65,20 +67,23 @@ public: void write(uint64_t timestamp, const aasdk::common::DataConstBuffer& buffer) override; void stop() override; void resize(); + signals: void startPlayback(); void stopPlayback(); + protected slots: void onStartPlayback(); void onStopPlayback(); + private: - static GstPadProbeReturn convert_probe(GstPad* pad, GstPadProbeInfo* info, void* user_data); - static gboolean bus_callback(GstBus* bus, GstMessage* message, gpointer* ptr); + static GstPadProbeReturn convertProbe(GstPad* pad, GstPadProbeInfo* info, void*); + static gboolean busCallback(GstBus*, GstMessage* message, gpointer*); QGst::ElementPtr videoSink_; QQuickWidget* videoWidget_; - GstElement* vidPipeline_ = nullptr; - GstAppSrc* vidSrc_ = nullptr; + GstElement* vidPipeline_; + GstAppSrc* vidSrc_; QWidget* videoContainer_; QGst::Quick::VideoSurface* surface_; std::function activeCallback_; diff --git a/include/f1x/openauto/autoapp/Service/SensorService.hpp b/include/f1x/openauto/autoapp/Service/SensorService.hpp index 8006065..8601693 100644 --- a/include/f1x/openauto/autoapp/Service/SensorService.hpp +++ b/include/f1x/openauto/autoapp/Service/SensorService.hpp @@ -33,7 +33,7 @@ namespace service class SensorService: public aasdk::channel::sensor::ISensorServiceChannelEventHandler, public IService, public std::enable_shared_from_this { public: - SensorService(boost::asio::io_service& ioService, aasdk::messenger::IMessenger::Pointer messenger, bool nightMode = false); + SensorService(boost::asio::io_service& ioService, aasdk::messenger::IMessenger::Pointer messenger, bool nightMode=false); void start() override; void stop() override; diff --git a/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp b/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp index 8a1d02e..eb364d0 100644 --- a/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp +++ b/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -39,11 +38,12 @@ namespace service class ServiceFactory: public IServiceFactory { public: - ServiceFactory(boost::asio::io_service& ioService, configuration::IConfiguration::Pointer configuration, QWidget* activeArea=nullptr, std::function activeCallback=nullptr, bool nightMode = false); + ServiceFactory(boost::asio::io_service& ioService, configuration::IConfiguration::Pointer configuration, QWidget* activeArea=nullptr, std::function activeCallback=nullptr, bool nightMode=false); ServiceList create(aasdk::messenger::IMessenger::Pointer messenger) override; void setOpacity(unsigned int alpha); void resize(); void setNightMode(bool nightMode); + void sendKeyEvent(QKeyEvent* event); static QRect mapActiveAreaToGlobal(QWidget* activeArea); #ifdef USE_OMX static projection::DestRect QRectToDestRect(QRect rect); @@ -61,7 +61,7 @@ private: QRect screenGeometry_; std::function activeCallback_; std::shared_ptr inputDevice_; -#ifdef USE_OMX +#if defined USE_OMX std::shared_ptr omxVideoOutput_; #elif defined USE_GST std::shared_ptr gstVideoOutput_; diff --git a/src/autoapp/Projection/GSTVideoOutput.cpp b/src/autoapp/Projection/GSTVideoOutput.cpp index b29d260..d1df573 100644 --- a/src/autoapp/Projection/GSTVideoOutput.cpp +++ b/src/autoapp/Projection/GSTVideoOutput.cpp @@ -45,42 +45,38 @@ GSTVideoOutput::GSTVideoOutput(configuration::IConfiguration::Pointer configurat videoWidget_->setResizeMode(QQuickWidget::SizeRootObjectToView); videoSink_ = surface_->videoSink(); - GstBus* bus; - GError* error = NULL; - const char* vidLaunchStr = "appsrc name=mysrc is-live=true block=false max-latency=100 do-timestamp=true stream-type=stream ! " - "queue ! " - - "h264parse ! " + GError* error = nullptr; + const char* vidLaunchStr = "appsrc name=mysrc is-live=true block=false max-latency=100 do-timestamp=true stream-type=stream ! queue ! h264parse ! " #ifdef RPI #ifdef PI4 - " v4l2h264dec !" + "v4l2h264dec ! " #else - " omxh264dec ! " + "omxh264dec ! " #endif #else - "avdec_h264 ! " + "avdec_h264 ! " #endif - "capsfilter caps=video/x-raw name=mycapsfilter"; + "capsfilter caps=video/x-raw name=mycapsfilter"; #ifdef RPI OPENAUTO_LOG(info) << "[GSTVideoOutput] RPI Build, running with " << #ifdef PI4 - "v4l2h264dec"; + "v4l2h264dec"; #else - "omxh264dec"; + "omxh264dec"; #endif #endif vidPipeline_ = gst_parse_launch(vidLaunchStr, &error); - bus = gst_pipeline_get_bus(GST_PIPELINE(vidPipeline_)); - gst_bus_add_watch(bus, (GstBusFunc)GSTVideoOutput::bus_callback, this); + GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(vidPipeline_)); + gst_bus_add_watch(bus, (GstBusFunc)&GSTVideoOutput::busCallback, this); gst_object_unref(bus); GstElement* sink = QGlib::RefPointer(videoSink_); - g_object_set (sink, "force-aspect-ratio", false, nullptr); + g_object_set(sink, "force-aspect-ratio", false, nullptr); + g_object_set(sink, "sync", false, nullptr); + g_object_set(sink, "async", false, nullptr); - g_object_set (sink, "sync", false, nullptr); - g_object_set (sink, "async", false, nullptr); GstElement* capsFilter = gst_bin_get_by_name(GST_BIN(vidPipeline_), "mycapsfilter"); gst_bin_add(GST_BIN(vidPipeline_), GST_ELEMENT(sink)); gst_element_link(capsFilter, GST_ELEMENT(sink)); @@ -92,14 +88,13 @@ GSTVideoOutput::GSTVideoOutput(configuration::IConfiguration::Pointer configurat connect(this, &GSTVideoOutput::stopPlayback, this, &GSTVideoOutput::onStopPlayback, Qt::QueuedConnection); } - GSTVideoOutput::~GSTVideoOutput() { gst_object_unref(vidPipeline_); gst_object_unref(vidSrc_); } -gboolean GSTVideoOutput::bus_callback(GstBus* /* unused*/, GstMessage* message, gpointer* ptr) +gboolean GSTVideoOutput::busCallback(GstBus*, GstMessage* message, gpointer*) { gchar* debug; GError* err; @@ -115,9 +110,9 @@ gboolean GSTVideoOutput::bus_callback(GstBus* /* unused*/, GstMessage* message, break; case GST_MESSAGE_WARNING: gst_message_parse_warning(message, &err, &debug); - OPENAUTO_LOG(info) << "[GSTVideoOutput] Warning " << err->message<<" | Debug " << debug; + OPENAUTO_LOG(info) << "[GSTVideoOutput] Warning " << err->message << " | Debug " << debug; name = (gchar*)GST_MESSAGE_SRC_NAME(message); - OPENAUTO_LOG(info) << "[GSTVideoOutput] Name of src " << name ? name : "nil"; + OPENAUTO_LOG(info) << "[GSTVideoOutput] Name of src " << (name ? name : "nil"); g_error_free(err); g_free(debug); break; @@ -125,7 +120,6 @@ gboolean GSTVideoOutput::bus_callback(GstBus* /* unused*/, GstMessage* message, OPENAUTO_LOG(info) << "[GSTVideoOutput] End of stream"; break; case GST_MESSAGE_STATE_CHANGED: - break; default: break; } @@ -135,31 +129,34 @@ gboolean GSTVideoOutput::bus_callback(GstBus* /* unused*/, GstMessage* message, bool GSTVideoOutput::open() { - GstElement* capsFilter = gst_bin_get_by_name(GST_BIN(vidPipeline_), "mycapsfilter"); + GstElement* capsFilter = gst_bin_get_by_name(GST_BIN(vidPipeline_), "mycapsfilter"); GstPad* convertPad = gst_element_get_static_pad(capsFilter, "sink"); - gst_pad_add_probe (convertPad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, convert_probe, this, NULL); + gst_pad_add_probe(convertPad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, &GSTVideoOutput::convertProbe, this, nullptr); gst_element_set_state(vidPipeline_, GST_STATE_PLAYING); + return true; } -GstPadProbeReturn GSTVideoOutput::convert_probe(GstPad* pad, GstPadProbeInfo* info, void* user_data) +GstPadProbeReturn GSTVideoOutput::convertProbe(GstPad* pad, GstPadProbeInfo* info, void*) { GstEvent* event = GST_PAD_PROBE_INFO_EVENT(info); - if(GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) { - if(GST_EVENT_TYPE(event) == GST_EVENT_SEGMENT) { + if(GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) + { + if(GST_EVENT_TYPE(event) == GST_EVENT_SEGMENT) + { GstCaps* caps = gst_pad_get_current_caps(pad); - if(caps != NULL) + if(caps != nullptr) { GstVideoInfo* vinfo = gst_video_info_new(); gst_video_info_from_caps(vinfo, caps); - OPENAUTO_LOG(info) << "[GSTVideoOutput] Video Width: "<< vinfo->width; - OPENAUTO_LOG(info) << "[GSTVideoOutput] Video Height: "<< vinfo->height; - - + OPENAUTO_LOG(info) << "[GSTVideoOutput] Video Width: " << vinfo->width; + OPENAUTO_LOG(info) << "[GSTVideoOutput] Video Height: " << vinfo->height; } + return GST_PAD_PROBE_REMOVE; } } + return GST_PAD_PROBE_OK; } @@ -167,6 +164,7 @@ bool GSTVideoOutput::init() { OPENAUTO_LOG(info) << "[GSTVideoOutput] init"; emit startPlayback(); + return true; } @@ -187,6 +185,7 @@ void GSTVideoOutput::onStartPlayback() { activeCallback_(true); } + if(videoContainer_ == nullptr) { OPENAUTO_LOG(info) << "[GSTVideoOutput] No video container, setting projection fullscreen"; @@ -213,6 +212,7 @@ void GSTVideoOutput::onStopPlayback() { activeCallback_(false); } + OPENAUTO_LOG(info) << "[GSTVideoOutput] stop."; gst_element_set_state(vidPipeline_, GST_STATE_PAUSED); videoWidget_->hide(); @@ -222,7 +222,10 @@ void GSTVideoOutput::resize() { OPENAUTO_LOG(info) << "[GSTVideoOutput] Got resize request to "<< videoContainer_->width() << "x" << videoContainer_->height(); - if(videoWidget_ != nullptr && videoContainer_ != nullptr) videoWidget_->resize(videoContainer_->size()); + if(videoWidget_ != nullptr && videoContainer_ != nullptr) + { + videoWidget_->resize(videoContainer_->size()); + } } } diff --git a/src/autoapp/Projection/OMXVideoOutput.cpp b/src/autoapp/Projection/OMXVideoOutput.cpp index cd700fe..9bc9f49 100644 --- a/src/autoapp/Projection/OMXVideoOutput.cpp +++ b/src/autoapp/Projection/OMXVideoOutput.cpp @@ -144,7 +144,7 @@ bool OMXVideoOutput::setupDisplayRegion() displayRegion.noaspect = OMX_TRUE; displayRegion.set = static_cast(OMX_DISPLAY_SET_FULLSCREEN | OMX_DISPLAY_SET_NOASPECT | OMX_DISPLAY_SET_LAYER); - if (destRect_.fullscreen == OMX_FALSE) + if(displayRegion.fullscreen == OMX_FALSE) { displayRegion.alpha = alpha_; displayRegion.dest_rect.x_offset = destRect_.xOffset; diff --git a/src/autoapp/Projection/QtVideoOutput.cpp b/src/autoapp/Projection/QtVideoOutput.cpp index 68ceddf..22d61fa 100644 --- a/src/autoapp/Projection/QtVideoOutput.cpp +++ b/src/autoapp/Projection/QtVideoOutput.cpp @@ -71,12 +71,15 @@ void QtVideoOutput::write(uint64_t, const aasdk::common::DataConstBuffer& buffer void QtVideoOutput::resize() { - if (videoWidget_ != nullptr && videoContainer_ != nullptr) videoWidget_->resize(videoContainer_->size()); + if(videoWidget_ != nullptr && videoContainer_ != nullptr) + { + videoWidget_->resize(videoContainer_->size()); + } } void QtVideoOutput::onStartPlayback() { - if (videoContainer_ == nullptr) + if(videoContainer_ == nullptr) { videoWidget_->setAspectRatioMode(Qt::IgnoreAspectRatio); videoWidget_->setFocus(); diff --git a/src/autoapp/Service/ServiceFactory.cpp b/src/autoapp/Service/ServiceFactory.cpp index 22df94f..d6bd867 100644 --- a/src/autoapp/Service/ServiceFactory.cpp +++ b/src/autoapp/Service/ServiceFactory.cpp @@ -56,7 +56,7 @@ ServiceFactory::ServiceFactory(boost::asio::io_service& ioService, configuration , activeArea_(activeArea) , screenGeometry_(this->mapActiveAreaToGlobal(activeArea_)) , activeCallback_(activeCallback) -#ifdef USE_OMX +#if defined USE_OMX , omxVideoOutput_(std::make_shared(configuration_, this->QRectToDestRect(screenGeometry_), activeCallback_)) #elif defined USE_GST , gstVideoOutput_((QGst::init(nullptr, nullptr), std::make_shared(configuration_, activeArea_, activeCallback_))) @@ -89,13 +89,14 @@ ServiceList ServiceFactory::create(aasdk::messenger::IMessenger::Pointer messeng IService::Pointer ServiceFactory::createVideoService(aasdk::messenger::IMessenger::Pointer messenger) { -#ifdef USE_OMX +#if defined USE_OMX auto videoOutput(omxVideoOutput_); #elif defined USE_GST auto videoOutput(gstVideoOutput_); #else qtVideoOutput_ = new projection::QtVideoOutput(configuration_, activeArea_); - if (activeCallback_ != nullptr) { + if(activeCallback_ != nullptr) + { QObject::connect(qtVideoOutput_, &projection::QtVideoOutput::startPlayback, [callback = activeCallback_]() { callback(true); }); QObject::connect(qtVideoOutput_, &projection::QtVideoOutput::stopPlayback, [this]() { activeCallback_(false); @@ -183,32 +184,58 @@ void ServiceFactory::createAudioServices(ServiceList& serviceList, aasdk::messen void ServiceFactory::setOpacity(unsigned int alpha) { #ifdef USE_OMX - if (omxVideoOutput_ != nullptr) omxVideoOutput_->setOpacity(alpha); + if(omxVideoOutput_ != nullptr) + { + omxVideoOutput_->setOpacity(alpha); + } #endif } void ServiceFactory::resize() { screenGeometry_ = this->mapActiveAreaToGlobal(activeArea_); - if (inputDevice_ != nullptr) inputDevice_->setTouchscreenGeometry(screenGeometry_); -#ifdef USE_OMX - if (omxVideoOutput_ != nullptr) omxVideoOutput_->setDestRect(this->QRectToDestRect(screenGeometry_)); + if(inputDevice_ != nullptr) + { + inputDevice_->setTouchscreenGeometry(screenGeometry_); + } +#if defined USE_OMX + if(omxVideoOutput_ != nullptr) + { + omxVideoOutput_->setDestRect(this->QRectToDestRect(screenGeometry_)); + } #elif defined USE_GST - if (gstVideoOutput_ != nullptr) gstVideoOutput_->resize(); + if(gstVideoOutput_ != nullptr) + { + gstVideoOutput_->resize(); + } #else - if (qtVideoOutput_ != nullptr) qtVideoOutput_->resize(); + if(qtVideoOutput_ != nullptr) + { + qtVideoOutput_->resize(); + } #endif } void ServiceFactory::setNightMode(bool nightMode) { nightMode_ = nightMode; - if (std::shared_ptr sensorService = sensorService_.lock()) sensorService->setNightMode(nightMode_); + if(std::shared_ptr sensorService = sensorService_.lock()) + { + sensorService->setNightMode(nightMode_); + } +} + +void ServiceFactory::sendKeyEvent(QKeyEvent* event) +{ + if(inputDevice_ != nullptr) + { + inputDevice_->eventFilter(activeArea_, event); + } } QRect ServiceFactory::mapActiveAreaToGlobal(QWidget* activeArea) { - if (activeArea == nullptr) + if(activeArea == nullptr) { QScreen* screen = QGuiApplication::primaryScreen(); return screen == nullptr ? QRect(0, 0, 1, 1) : screen->geometry(); From 8bbef14efa4a30578654cfb4116f5a70b80c1d8f Mon Sep 17 00:00:00 2001 From: "Jason C. Wenger" Date: Sat, 4 Jul 2020 10:34:31 -0500 Subject: [PATCH 7/7] Partially revert "Add OMX as a module" This reverts commit 16cec35bdde00615bdaec602b1b24646d067acbc. --- CMakeLists.txt | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 91f98fd..f30daea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,12 +46,19 @@ find_package(OpenSSL REQUIRED) find_package(rtaudio REQUIRED) find_package(aasdk REQUIRED) find_package(ZLIB REQUIRED) -find_package(libomx) if(WIN32) set(WINSOCK2_LIBRARIES "ws2_32") endif(WIN32) +if(RPI_BUILD) + add_definitions(-DUSE_OMX -DOMX_SKIP64BIT) + set(BCM_HOST_LIBRARIES "/opt/vc/lib/libbcm_host.so") + set(BCM_HOST_INCLUDE_DIRS "/opt/vc/include") + set(ILCLIENT_INCLUDE_DIRS "/opt/vc/src/hello_pi/libs/ilclient") + set(ILCLIENT_LIBRARIES "/opt/vc/src/hello_pi/libs/ilclient/libilclient.a;/opt/vc/lib/libvcos.so;/opt/vc/lib/libvcilcs.a;/opt/vc/lib/libvchiq_arm.so") +endif(RPI_BUILD) + include_directories(${CMAKE_CURRENT_BINARY_DIR} ${Qt5Multimedia_INCLUDE_DIRS} ${Qt5MultimediaWidgets_INCLUDE_DIRS} @@ -61,6 +68,8 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR} ${PROTOBUF_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${RTAUDIO_INCLUDE_DIRS} + ${BCM_HOST_INCLUDE_DIRS} + ${ILCLIENT_INCLUDE_DIRS} ${include_directory}) link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) @@ -80,14 +89,12 @@ target_link_libraries(autoapp aasdk libusb ${Qt5Bluetooth_LIBRARIES} ${PROTOBUF_LIBRARIES} ${ZLIB_LIBRARIES} + ${BCM_HOST_LIBRARIES} + ${ILCLIENT_LIBRARIES} ${WINSOCK2_LIBRARIES} ${RTAUDIO_LIBRARIES} ) -if(libomx_FOUND) - target_link_libraries(autoapp omx) -endif() - set(btservice_sources_directory ${sources_directory}/btservice) set(btservice_include_directory ${include_directory}/f1x/openauto/btservice) file(GLOB_RECURSE btservice_source_files ${btservice_sources_directory}/*.cpp ${btservice_include_directory}/*.hpp ${common_include_directory}/*.hpp)