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();