diff --git a/.gitignore b/.gitignore index 7e47c61..30e72b9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ # Add any directories, files, or patterns you don't want to be tracked by version control +.vscode/ + lib/ bin/ -CMakeLists.txt.user \ No newline at end of file +CMakeLists.txt.user diff --git a/CMakeLists.txt b/CMakeLists.txt index fc87b2e..4016de8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,13 +38,13 @@ if(WIN32) set(WINSOCK2_LIBRARIES "ws2_32") endif(WIN32) -if(RPI3_BUILD) - add_definitions(-DUSE_OMX -DOMX_SKIP64BIT -DRASPBERRYPI3) +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(RPI3_BUILD) +endif(RPI_BUILD) include_directories(${CMAKE_CURRENT_BINARY_DIR} ${Qt5Multimedia_INCLUDE_DIRS} @@ -72,6 +72,10 @@ file(GLOB_RECURSE autoapp_source_files ${autoapp_sources_directory}/*.ui ${autoa 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}) + target_link_libraries(autoapp ${Boost_LIBRARIES} ${Qt5Multimedia_LIBRARIES} diff --git a/include/f1x/openauto/autoapp/Projection/OMXVideoOutput.hpp b/include/f1x/openauto/autoapp/Projection/OMXVideoOutput.hpp index 4c88900..30d0888 100644 --- a/include/f1x/openauto/autoapp/Projection/OMXVideoOutput.hpp +++ b/include/f1x/openauto/autoapp/Projection/OMXVideoOutput.hpp @@ -26,6 +26,7 @@ extern "C" #include #include +#include #include #include #include @@ -39,15 +40,28 @@ namespace autoapp namespace projection { +struct DestRect +{ + DestRect(); + DestRect(OMX_S16 xOffset, OMX_S16 yOffset, OMX_S16 width, OMX_S16 height); + + OMX_BOOL fullscreen; + OMX_S16 xOffset; + OMX_S16 yOffset; + OMX_S16 width; + OMX_S16 height; +}; + class OMXVideoOutput: public VideoOutput { public: - OMXVideoOutput(configuration::IConfiguration::Pointer configuration); + OMXVideoOutput(configuration::IConfiguration::Pointer configuration, DestRect destRect=DestRect(), std::function activeCallback=nullptr); bool open() override; bool init() override; void write(uint64_t timestamp, const aasdk::common::DataConstBuffer& buffer) override; void stop() override; + void setOpacity(OMX_U32 alpha); private: bool createComponents(); @@ -62,6 +76,9 @@ private: ILCLIENT_T* client_; COMPONENT_T* components_[5]; TUNNEL_T tunnels_[4]; + DestRect destRect_; + OMX_U32 alpha_; + std::function activeCallback_; }; } diff --git a/include/f1x/openauto/autoapp/Projection/QtVideoOutput.hpp b/include/f1x/openauto/autoapp/Projection/QtVideoOutput.hpp index 172c3b5..5800351 100644 --- a/include/f1x/openauto/autoapp/Projection/QtVideoOutput.hpp +++ b/include/f1x/openauto/autoapp/Projection/QtVideoOutput.hpp @@ -38,7 +38,7 @@ class QtVideoOutput: public QObject, public VideoOutput, boost::noncopyable Q_OBJECT public: - QtVideoOutput(configuration::IConfiguration::Pointer configuration); + QtVideoOutput(configuration::IConfiguration::Pointer configuration, QWidget* videoContainer=nullptr); bool open() override; bool init() override; void write(uint64_t timestamp, const aasdk::common::DataConstBuffer& buffer) override; @@ -57,6 +57,7 @@ private: SequentialBuffer videoBuffer_; std::unique_ptr videoWidget_; std::unique_ptr mediaPlayer_; + QWidget* videoContainer_; }; } diff --git a/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp b/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp index 2ee9c6b..2c4475c 100644 --- a/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp +++ b/include/f1x/openauto/autoapp/Service/ServiceFactory.hpp @@ -20,6 +20,7 @@ #include #include +#include namespace f1x { @@ -33,8 +34,13 @@ namespace service class ServiceFactory: public IServiceFactory { public: - ServiceFactory(boost::asio::io_service& ioService, configuration::IConfiguration::Pointer configuration); + 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); + static QRect mapActiveAreaToGlobal(QWidget* activeArea); +#ifdef USE_OMX + static projection::DestRect QRectToDestRect(QRect rect); +#endif private: IService::Pointer createVideoService(aasdk::messenger::IMessenger::Pointer messenger); @@ -44,6 +50,12 @@ private: boost::asio::io_service& ioService_; configuration::IConfiguration::Pointer configuration_; + QWidget* activeArea_; + QRect screenGeometry_; + std::function activeCallback_; +#ifdef USE_OMX + std::shared_ptr omxVideoOutput_; +#endif }; } diff --git a/include/f1x/openauto/autoapp/Service/VideoService.hpp b/include/f1x/openauto/autoapp/Service/VideoService.hpp index a7bc52d..0b484bf 100644 --- a/include/f1x/openauto/autoapp/Service/VideoService.hpp +++ b/include/f1x/openauto/autoapp/Service/VideoService.hpp @@ -46,6 +46,7 @@ public: void onChannelOpenRequest(const aasdk::proto::messages::ChannelOpenRequest& request) override; void onAVChannelSetupRequest(const aasdk::proto::messages::AVChannelSetupRequest& request) override; void onAVChannelStartIndication(const aasdk::proto::messages::AVChannelStartIndication& indication) override; + void onAVChannelStopIndication(const aasdk::proto::messages::AVChannelStopIndication& indication) override; void onAVMediaWithTimestampIndication(aasdk::messenger::Timestamp::ValueType timestamp, const aasdk::common::DataConstBuffer& buffer) override; void onAVMediaIndication(const aasdk::common::DataConstBuffer& buffer) override; void onVideoFocusRequest(const aasdk::proto::messages::VideoFocusRequest& request) override; diff --git a/src/autoapp/Projection/OMXVideoOutput.cpp b/src/autoapp/Projection/OMXVideoOutput.cpp index 12f5960..4b4f75a 100644 --- a/src/autoapp/Projection/OMXVideoOutput.cpp +++ b/src/autoapp/Projection/OMXVideoOutput.cpp @@ -36,6 +36,22 @@ namespace autoapp namespace projection { +DestRect::DestRect() + : fullscreen(OMX_TRUE) +{ + +} + +DestRect::DestRect(OMX_S16 _xOffset, OMX_S16 _yOffset, OMX_S16 _width, OMX_S16 _height) + : fullscreen(OMX_FALSE) + , xOffset(_xOffset) + , yOffset(_yOffset) + , width(_width) + , height(_height) +{ + +} + namespace VideoComponent { static constexpr uint32_t DECODER = 0; @@ -44,11 +60,14 @@ namespace VideoComponent static constexpr uint32_t SCHEDULER = 3; } -OMXVideoOutput::OMXVideoOutput(configuration::IConfiguration::Pointer configuration) +OMXVideoOutput::OMXVideoOutput(configuration::IConfiguration::Pointer configuration, DestRect destRect, std::function activeCallback) : VideoOutput(std::move(configuration)) , isActive_(false) , portSettingsChanged_(false) , client_(nullptr) + , destRect_(destRect) + , alpha_(255) + , activeCallback_(activeCallback) { memset(components_, 0, sizeof(components_)); memset(tunnels_, 0, sizeof(tunnels_)); @@ -95,6 +114,10 @@ bool OMXVideoOutput::open() } isActive_ = true; + if(this->activeCallback_ != nullptr) + { + this->activeCallback_(isActive_); + } return true; } @@ -115,10 +138,20 @@ bool OMXVideoOutput::setupDisplayRegion() displayRegion.nVersion.nVersion = OMX_VERSION; displayRegion.nPortIndex = 90; displayRegion.layer = static_cast(configuration_->getOMXLayerIndex()); - displayRegion.fullscreen = OMX_TRUE; + displayRegion.fullscreen = destRect_.fullscreen; 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) + { + displayRegion.alpha = alpha_; + displayRegion.dest_rect.x_offset = destRect_.xOffset; + displayRegion.dest_rect.y_offset = destRect_.yOffset; + displayRegion.dest_rect.width = destRect_.width; + displayRegion.dest_rect.height = destRect_.height; + displayRegion.set = static_cast(displayRegion.set | OMX_DISPLAY_SET_ALPHA | OMX_DISPLAY_SET_DEST_RECT); + } + return OMX_SetConfig(ilclient_get_handle(components_[VideoComponent::RENDERER]), OMX_IndexConfigDisplayRegion, &displayRegion) == OMX_ErrorNone; } @@ -186,6 +219,10 @@ void OMXVideoOutput::stop() if(isActive_) { isActive_ = false; + if(this->activeCallback_ != nullptr) + { + this->activeCallback_(isActive_); + } ilclient_disable_tunnel(&tunnels_[0]); ilclient_disable_tunnel(&tunnels_[1]); @@ -199,6 +236,27 @@ void OMXVideoOutput::stop() ilclient_cleanup_components(components_); OMX_Deinit(); ilclient_destroy(client_); + client_ = nullptr; + + portSettingsChanged_ = false; + } +} + +void OMXVideoOutput::setOpacity(OMX_U32 alpha) +{ + std::lock_guard lock(mutex_); + + 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); + + OMX_SetConfig(ilclient_get_handle(components_[VideoComponent::RENDERER]), OMX_IndexConfigDisplayRegion, &displayRegion) == OMX_ErrorNone; } } diff --git a/src/autoapp/Projection/QtVideoOutput.cpp b/src/autoapp/Projection/QtVideoOutput.cpp index ad4636c..ec7c349 100644 --- a/src/autoapp/Projection/QtVideoOutput.cpp +++ b/src/autoapp/Projection/QtVideoOutput.cpp @@ -29,8 +29,9 @@ namespace autoapp namespace projection { -QtVideoOutput::QtVideoOutput(configuration::IConfiguration::Pointer configuration) +QtVideoOutput::QtVideoOutput(configuration::IConfiguration::Pointer configuration, QWidget* videoContainer) : VideoOutput(std::move(configuration)) + , videoContainer_(videoContainer) { this->moveToThread(QApplication::instance()->thread()); connect(this, &QtVideoOutput::startPlayback, this, &QtVideoOutput::onStartPlayback, Qt::QueuedConnection); @@ -42,7 +43,7 @@ QtVideoOutput::QtVideoOutput(configuration::IConfiguration::Pointer configuratio void QtVideoOutput::createVideoOutput() { OPENAUTO_LOG(debug) << "[QtVideoOutput] create."; - videoWidget_ = std::make_unique(); + videoWidget_ = std::make_unique(videoContainer_); mediaPlayer_ = std::make_unique(nullptr, QMediaPlayer::StreamPlayback); } @@ -70,10 +71,17 @@ void QtVideoOutput::write(uint64_t, const aasdk::common::DataConstBuffer& buffer void QtVideoOutput::onStartPlayback() { - videoWidget_->setAspectRatioMode(Qt::IgnoreAspectRatio); - videoWidget_->setFocus(); - videoWidget_->setWindowFlags(Qt::WindowStaysOnTopHint); - videoWidget_->setFullScreen(true); + if (videoContainer_ == nullptr) + { + videoWidget_->setAspectRatioMode(Qt::IgnoreAspectRatio); + videoWidget_->setFocus(); + videoWidget_->setWindowFlags(Qt::WindowStaysOnTopHint); + videoWidget_->setFullScreen(true); + } + else + { + videoWidget_->resize(videoContainer_->size()); + } videoWidget_->show(); mediaPlayer_->setVideoOutput(videoWidget_.get()); diff --git a/src/autoapp/Service/AndroidAutoEntity.cpp b/src/autoapp/Service/AndroidAutoEntity.cpp index 50aabf8..0e89b57 100644 --- a/src/autoapp/Service/AndroidAutoEntity.cpp +++ b/src/autoapp/Service/AndroidAutoEntity.cpp @@ -272,6 +272,8 @@ void AndroidAutoEntity::sendPing() promise->then([]() {}, std::bind(&AndroidAutoEntity::onChannelError, this->shared_from_this(), std::placeholders::_1)); aasdk::proto::messages::PingRequest request; + auto timestamp = std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()); + request.set_timestamp(timestamp.count()); controlServiceChannel_->sendPingRequest(request, std::move(promise)); } diff --git a/src/autoapp/Service/ServiceFactory.cpp b/src/autoapp/Service/ServiceFactory.cpp index 5f9d60e..ceead5e 100644 --- a/src/autoapp/Service/ServiceFactory.cpp +++ b/src/autoapp/Service/ServiceFactory.cpp @@ -49,9 +49,15 @@ namespace autoapp namespace service { -ServiceFactory::ServiceFactory(boost::asio::io_service& ioService, configuration::IConfiguration::Pointer configuration) +ServiceFactory::ServiceFactory(boost::asio::io_service& ioService, configuration::IConfiguration::Pointer configuration, QWidget *activeArea, std::function activeCallback) : ioService_(ioService) , configuration_(std::move(configuration)) + , activeArea_(activeArea) + , screenGeometry_(this->mapActiveAreaToGlobal(activeArea_)) + , activeCallback_(activeCallback) +#ifdef USE_OMX + , omxVideoOutput_(std::make_shared(configuration_, this->QRectToDestRect(screenGeometry_), activeCallback_)) +#endif { } @@ -74,9 +80,10 @@ ServiceList ServiceFactory::create(aasdk::messenger::IMessenger::Pointer messeng IService::Pointer ServiceFactory::createVideoService(aasdk::messenger::IMessenger::Pointer messenger) { #ifdef USE_OMX - auto videoOutput(std::make_shared(configuration_)); + auto videoOutput(omxVideoOutput_); #else - projection::IVideoOutput::Pointer videoOutput(new projection::QtVideoOutput(configuration_), std::bind(&QObject::deleteLater, std::placeholders::_1)); + auto qtVideoOutput = new projection::QtVideoOutput(configuration_, activeArea_); + projection::IVideoOutput::Pointer videoOutput(qtVideoOutput, std::bind(&QObject::deleteLater, std::placeholders::_1)); #endif return std::make_shared(ioService_, messenger, std::move(videoOutput)); } @@ -120,9 +127,8 @@ IService::Pointer ServiceFactory::createInputService(aasdk::messenger::IMessenge break; } - QScreen* screen = QGuiApplication::primaryScreen(); - QRect screenGeometry = screen == nullptr ? QRect(0, 0, 1, 1) : screen->geometry(); - projection::IInputDevice::Pointer inputDevice(std::make_shared(*QApplication::instance(), configuration_, std::move(screenGeometry), std::move(videoGeometry))); + 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))); return std::make_shared(ioService_, messenger, std::move(inputDevice)); } @@ -154,6 +160,34 @@ void ServiceFactory::createAudioServices(ServiceList& serviceList, aasdk::messen serviceList.emplace_back(std::make_shared(ioService_, messenger, std::move(systemAudioOutput))); } +void ServiceFactory::setOpacity(unsigned int alpha) +{ +#ifdef USE_OMX + omxVideoOutput_->setOpacity(alpha); +#endif +} + +QRect ServiceFactory::mapActiveAreaToGlobal(QWidget* activeArea) +{ + if (activeArea == nullptr) + { + QScreen* screen = QGuiApplication::primaryScreen(); + return screen == nullptr ? QRect(0, 0, 1, 1) : screen->geometry(); + } + + QRect g = activeArea->geometry(); + QPoint p = activeArea->mapToGlobal(g.topLeft()); + + return QRect(p.x(), p.y(), g.width(), g.height()); +} + +#ifdef USE_OMX +projection::DestRect ServiceFactory::QRectToDestRect(QRect rect) +{ + return projection::DestRect(rect.x(), rect.y(), rect.width(), rect.height()); +} +#endif + } } } diff --git a/src/autoapp/Service/VideoService.cpp b/src/autoapp/Service/VideoService.cpp index 1bb0aa1..bd5dc67 100644 --- a/src/autoapp/Service/VideoService.cpp +++ b/src/autoapp/Service/VideoService.cpp @@ -95,6 +95,13 @@ void VideoService::onAVChannelStartIndication(const aasdk::proto::messages::AVCh channel_->receive(this->shared_from_this()); } +void VideoService::onAVChannelStopIndication(const aasdk::proto::messages::AVChannelStopIndication& indication) +{ + OPENAUTO_LOG(info) << "[VideoService] stop indication"; + + channel_->receive(this->shared_from_this()); +} + void VideoService::onAVMediaWithTimestampIndication(aasdk::messenger::Timestamp::ValueType timestamp, const aasdk::common::DataConstBuffer& buffer) { videoOutput_->write(timestamp, buffer);