diff --git a/common/include/dscreen_constants.h b/common/include/dscreen_constants.h index 101c26a197c4f54e0fe8c582b750c9eb692484f5..aff79392cfe2313431a6fec0806e1900ff3b4ecd 100644 --- a/common/include/dscreen_constants.h +++ b/common/include/dscreen_constants.h @@ -63,14 +63,15 @@ enum DataType : uint8_t { }; enum DScreenMsgType : uint32_t { - SETUP_SIGNAL = 0, + START_MIRROR = 0, + START_MIRROR_SUCCESS = 1, + START_MIRROR_FAIL = 2, + STOP_MIRROR = 3, }; enum DScreenEventType : uint32_t { - REMOTE_MSG_RECEIVED = 0, - SENDER_ENGINE_ERROR, - RECEIVER_ENGINE_ERROR, - TRANS_CHANNEL_CLOSED, + ENGINE_ERROR = 0, + TRANS_CHANNEL_CLOSED = 1, }; /* Screen package name */ @@ -205,6 +206,7 @@ constexpr size_t DATA_BUFFER_MAX_SIZE = 10 * 1024 * 1024; constexpr uint8_t TASK_WAIT_SECONDS = 1; constexpr int32_t JPEG_QUALITY = 80; constexpr uint32_t BIT_RATE = 12000000; +constexpr int32_t WAIT_TIMEOUT_MS = 5000; } // namespace DistributedHardware } // namespace OHOS #endif \ No newline at end of file diff --git a/common/include/dscreen_errcode.h b/common/include/dscreen_errcode.h index 2b92e14c0970ccc169300c163e256c81152a3f03..c51528f81923c1862b94bbb11cf893280563ad28 100644 --- a/common/include/dscreen_errcode.h +++ b/common/include/dscreen_errcode.h @@ -122,6 +122,7 @@ enum DScreenErrorCode { ERR_DH_AV_TRANS_STOP_FAILED = -58008, ERR_DH_AV_TRANS_FEED_DATA_FAILED = -58009, ERR_DH_AV_TRANS_SEND_MSG_FAILED = -58010, + ERR_DH_AV_TRANS_SINK_START_FAILED = -58011, }; } // namespace DistributedHardware } // namespace OHOS diff --git a/services/screenservice/sinkservice/screenregionmgr/2.0/src/av_receiver_engine_adapter.cpp b/services/screenservice/sinkservice/screenregionmgr/2.0/src/av_receiver_engine_adapter.cpp index 5f01af009250645fecddfc20bb59e647e3554f9b..ee759a0dcb15d9178d6fe4892f9ae3c33665a413 100644 --- a/services/screenservice/sinkservice/screenregionmgr/2.0/src/av_receiver_engine_adapter.cpp +++ b/services/screenservice/sinkservice/screenregionmgr/2.0/src/av_receiver_engine_adapter.cpp @@ -127,15 +127,22 @@ int32_t AVTransReceiverAdapter::RegisterAdapterCallback(const std::shared_ptrOnEngineEvent(DScreenEventType::TRANS_CHANNEL_CLOSED, event.peerDevId); + break; case EventType::EVENT_ENGINE_ERROR: case EventType::EVENT_REMOTE_ERROR: - if (adapterCallback_ != nullptr) { - adapterCallback_->OnEngineEvent(DScreenEventType::RECEIVER_ENGINE_ERROR, event.content); - } + adapterCallback_->OnEngineEvent(DScreenEventType::ENGINE_ERROR, event.content); break; default: DHLOGE("Invalid event type."); diff --git a/services/screenservice/sinkservice/screenregionmgr/2.0/src/screenregion.cpp b/services/screenservice/sinkservice/screenregionmgr/2.0/src/screenregion.cpp index f5359ea00e26490cdbaedebd60afaf6baa08e950..61b49199d748b0ad7828dfb9a579bf8e25b8c5fe 100644 --- a/services/screenservice/sinkservice/screenregionmgr/2.0/src/screenregion.cpp +++ b/services/screenservice/sinkservice/screenregionmgr/2.0/src/screenregion.cpp @@ -68,20 +68,23 @@ int32_t ScreenRegion::Release() DHLOGI("ScreenRegion not running, no need release"); return DH_SUCCESS; } + ScreenClient::GetInstance().RemoveWindow(windowId_); + if (receiverAdapter_ == nullptr) { DHLOGE("av transport receiver adapter is nullptr."); return ERR_DH_AV_TRANS_NULL_VALUE; } + int32_t ret = receiverAdapter_->Stop(); if (ret != DH_SUCCESS) { DHLOGE("sink trans stop failed."); - return ret; } - ret = ScreenClient::GetInstance().RemoveWindow(windowId_); + + ret = receiverAdapter_->Release(); if (ret != DH_SUCCESS) { - DHLOGE("remove window failed."); - return ret; + DHLOGE("release av receiver adapter failed."); } + isRunning = false; return DH_SUCCESS; } @@ -111,21 +114,17 @@ int32_t ScreenRegion::StartReceiverEngine(const std::string &content) int32_t ScreenRegion::StopReceiverEngine() { DHLOGI("StopReceiverEngine, remoteDevId: %s, screenId: %u", GetAnonyString(remoteDevId_).c_str(), screenId_); + + int32_t ret = ScreenClient::GetInstance().RemoveWindow(windowId_); + if (ret != DH_SUCCESS) { + DHLOGE("remove window failed."); + } + if (receiverAdapter_ == nullptr) { DHLOGE("av transport receiver adapter is null."); return ERR_DH_AV_TRANS_NULL_VALUE; } - int32_t ret = receiverAdapter_->Stop(); - if (ret != DH_SUCCESS) { - DHLOGE("stop av receiver adapter failed."); - return ERR_DH_AV_TRANS_STOP_FAILED; - } - ret = receiverAdapter_->Release(); - if (ret != DH_SUCCESS) { - DHLOGE("release av receiver adapter failed."); - return ERR_DH_AV_TRANS_STOP_FAILED; - } - return DH_SUCCESS; + return receiverAdapter_->Stop(); } int32_t ScreenRegion::SetUp(const std::string &content) @@ -139,7 +138,6 @@ int32_t ScreenRegion::SetUp(const std::string &content) return ERR_DH_SCREEN_INPUT_PARAM_INVALID; } screenId_ = contentJson[KEY_SCREEN_ID].get(); - remoteDevId_ = contentJson[KEY_DEV_ID].get(); displayId_ = Rosen::DisplayManager::GetInstance().GetDefaultDisplayId(); videoParam_ = std::make_shared(contentJson[KEY_VIDEO_PARAM].get()); mapRelation_ = std::make_shared(contentJson[KEY_MAPRELATION].get()); @@ -243,19 +241,31 @@ void ScreenRegion::PublishMessage(const DHTopic topic, const uint64_t &screenId, void ScreenRegion::OnEngineEvent(DScreenEventType event, const std::string &content) { - (void)event; (void)content; + if (event == DScreenEventType::ENGINE_ERROR) { + StopReceiverEngine(); + } } void ScreenRegion::OnEngineMessage(const std::shared_ptr &message) { - DHLOGI("OnEngineMessage enter"); if (message == nullptr) { DHLOGE("received engine message is null."); return; } - if (message->type_ == DScreenMsgType::SETUP_SIGNAL) { - StartReceiverEngine(message->content_); + + DHLOGI("On source device engine message received, message type =%d.", message->type_); + if (message->type_ == DScreenMsgType::START_MIRROR) { + int32_t ret = StartReceiverEngine(message->content_); + DScreenMsgType msgType = (ret == DH_SUCCESS) ? DScreenMsgType::START_MIRROR_SUCCESS : + DScreenMsgType::START_MIRROR_FAIL; + + json paramJson; + paramJson[KEY_DEV_ID] = remoteDevId_; + auto avMessage = std::make_shared(msgType, paramJson.dump(), remoteDevId_); + receiverAdapter_->SendMessageToRemote(avMessage); + } else if (message->type_ == DScreenMsgType::STOP_MIRROR) { + StopReceiverEngine(); } } @@ -367,9 +377,6 @@ bool ScreenRegion::CheckContentJson(json &contentJson) if (!IsUInt64(contentJson, KEY_SCREEN_ID)) { return false; } - if (!IsString(contentJson, KEY_DEV_ID)) { - return false; - } return true; } } // namespace V1_0 diff --git a/services/screenservice/sinkservice/screenregionmgr/2.0/src/screenregionmgr.cpp b/services/screenservice/sinkservice/screenregionmgr/2.0/src/screenregionmgr.cpp index 05d755d1010a76105a1457a4e6d7948bb0a2df12..b501f1f38cbaeecd5dedec5b54f8cfa9e895552b 100644 --- a/services/screenservice/sinkservice/screenregionmgr/2.0/src/screenregionmgr.cpp +++ b/services/screenservice/sinkservice/screenregionmgr/2.0/src/screenregionmgr.cpp @@ -105,14 +105,13 @@ int32_t ScreenRegionManager::CreateDScreenRegion(const std::string &peerDevId) int32_t ScreenRegionManager::DestoryDScreenRegion(const std::string &peerDevId) { DHLOGI("DestoryDScreenRegion for peerDevId: %s", GetAnonyString(peerDevId).c_str()); - for (auto iter = screenRegions_.begin(); iter != screenRegions_.end();) { - if ((*iter)->GetRemoteDevId() == peerDevId) { - (*iter)->Release(); - iter = screenRegions_.erase(iter); - } else { - iter++; + std::lock_guard lock(screenRegionsMtx_); + for (const auto ®ion : screenRegions_) { + if (region != nullptr) { + region->Release(); } } + screenRegions_.clear(); return DH_SUCCESS; } diff --git a/services/screenservice/sourceservice/dscreenmgr/2.0/include/dscreen.h b/services/screenservice/sourceservice/dscreenmgr/2.0/include/dscreen.h index 82b9767ff6006759a25c06615532900195e8661b..486c5a919bf2ffdbb8960486f57eb678550ccdbf 100644 --- a/services/screenservice/sourceservice/dscreenmgr/2.0/include/dscreen.h +++ b/services/screenservice/sourceservice/dscreenmgr/2.0/include/dscreen.h @@ -123,6 +123,7 @@ private: void ChooseParameter(std::string &codecType, std::string &pixelFormat); bool CheckJsonData(json &attrJson); void SetState(DScreenState state); + int32_t WaitForSinkStarted(); std::string devId_; std::string dhId_; @@ -141,6 +142,10 @@ private: bool taskThreadRunning_; std::shared_ptr senderAdapter_; OHOS::sptr syncFence_ = SyncFence::INVALID_FENCE; + + std::mutex waitSinkMtx_; + std::condition_variable waitSinkCondVar_; + std::atomic sinkStartSuccess_ {false}; }; } // namespace V2_0 } // namespace DistributedHardware diff --git a/services/screenservice/sourceservice/dscreenmgr/2.0/src/av_sender_engine_adapter.cpp b/services/screenservice/sourceservice/dscreenmgr/2.0/src/av_sender_engine_adapter.cpp index 9464606ae505f6c45e01ee42985ef246a6f4d6eb..57962692fd879f0e4212631fe1058d796af138f0 100644 --- a/services/screenservice/sourceservice/dscreenmgr/2.0/src/av_sender_engine_adapter.cpp +++ b/services/screenservice/sourceservice/dscreenmgr/2.0/src/av_sender_engine_adapter.cpp @@ -21,8 +21,6 @@ namespace OHOS { namespace DistributedHardware { -constexpr int32_t WAIT_TIMEOUT_MS = 5000; - int32_t AVTransSenderAdapter::Initialize(IAVEngineProvider *providerPtr, const std::string &peerDevId) { DHLOGI("Initialize enter"); @@ -54,6 +52,8 @@ int32_t AVTransSenderAdapter::Release() } initialized_ = false; senderEngine_ = nullptr; + chnCreateSuccess_ = false; + transStartSuccess_ = false; return DH_SUCCESS; } @@ -95,6 +95,7 @@ int32_t AVTransSenderAdapter::Stop() return ERR_DH_AV_TRANS_STOP_FAILED; } DHLOGI("Stop Success"); + transStartSuccess_ = false; return DH_SUCCESS; } @@ -242,7 +243,7 @@ int32_t AVTransSenderAdapter::OnSenderEvent(const AVTransEvent& event) case EventType::EVENT_ENGINE_ERROR: case EventType::EVENT_REMOTE_ERROR: if (adapterCallback_ != nullptr) { - adapterCallback_->OnEngineEvent(DScreenEventType::RECEIVER_ENGINE_ERROR, event.content); + adapterCallback_->OnEngineEvent(DScreenEventType::ENGINE_ERROR, event.content); } break; default: diff --git a/services/screenservice/sourceservice/dscreenmgr/2.0/src/dscreen.cpp b/services/screenservice/sourceservice/dscreenmgr/2.0/src/dscreen.cpp index 8097dddcf5addcc4dfeafbd2d1ea1cee7572d385..22a201b2aabfd269219b78ff4f9fb5382d724d9e 100644 --- a/services/screenservice/sourceservice/dscreenmgr/2.0/src/dscreen.cpp +++ b/services/screenservice/sourceservice/dscreenmgr/2.0/src/dscreen.cpp @@ -216,17 +216,14 @@ void DScreen::HandleDisconnect() return; } SetState(DISCONNECTING); - int32_t ret = RemoveSurface(); - if (ret != DH_SUCCESS) { - DHLOGE("remove image surface failed."); - } - ret = StopSenderEngine(); + int32_t ret = StopSenderEngine(); if (ret != DH_SUCCESS) { SetState(CONNECTED); DHLOGE("dScreen Stop failed."); return; } SetState(ENABLED); + RemoveSurface(); ReportScreenMirrorEvent(DSCREEN_PROJECT_END, GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), "dscreen disconnect success"); } @@ -371,6 +368,14 @@ int32_t DScreen::StopSenderEngine() DHLOGE("av transport sender adapter is null."); return ERR_DH_AV_TRANS_NULL_VALUE; } + + json paramJson; + paramJson[KEY_DEV_ID] = devId_; + paramJson[KEY_DH_ID] = dhId_; + + auto avMessage = std::make_shared(DScreenMsgType::STOP_MIRROR, paramJson.dump(), devId_); + senderAdapter_->SendMessageToRemote(avMessage); + int32_t ret = senderAdapter_->Stop(); if (ret != DH_SUCCESS) { DHLOGE("stop av sender adapter failed."); @@ -431,24 +436,45 @@ int32_t DScreen::SetUp() videoParam_->SetVideoHeight(displayRect.height); json paramJson; - paramJson[KEY_DEV_ID] = devId_; paramJson[KEY_DH_ID] = dhId_; paramJson[KEY_SCREEN_ID] = screenId_; paramJson[KEY_VIDEO_PARAM] = *videoParam_; paramJson[KEY_MAPRELATION] = *mapRelation; - auto avMessage = std::make_shared(DScreenMsgType::SETUP_SIGNAL, paramJson.dump(), devId_); + auto avMessage = std::make_shared(DScreenMsgType::START_MIRROR, paramJson.dump(), devId_); int32_t ret = senderAdapter_->SendMessageToRemote(avMessage); if (ret != DH_SUCCESS) { - DHLOGE("set message to remote engine failed."); + DHLOGE("send message to remote engine failed."); + return ret; + } + + ret = WaitForSinkStarted(); + if (ret != DH_SUCCESS) { + DHLOGE("send message to start remote device engine failed."); return ret; } + std::string codecType; std::string pixelFormat; ChooseParameter(codecType, pixelFormat); return senderAdapter_->SetParameter(AVTransTag::ENGINE_READY, OWNER_NAME_D_SCREEN); } +int32_t DScreen::WaitForSinkStarted() +{ + std::unique_lock lock(waitSinkMtx_); + auto status = waitSinkCondVar_.wait_for(lock, std::chrono::milliseconds(WAIT_TIMEOUT_MS)); + if (status == std::cv_status::timeout) { + DHLOGE("wait for sink device engine start timeout"); + return ERR_DH_AV_TRANS_TIMEOUT; + } + if (!sinkStartSuccess_.load()) { + DHLOGE("start sink device engine failed"); + return ERR_DH_AV_TRANS_SINK_START_FAILED; + } + return DH_SUCCESS; +} + int32_t DScreen::NegotiateCodecType(const std::string &rmtDecoderStr) { DHLOGI("Start NegotiateCodecType, remote decoder: %s", rmtDecoderStr.c_str()); @@ -516,6 +542,7 @@ int32_t DScreen::ChooseCodecType(const std::vector &localVideoEnco return DH_SUCCESS; } + void DScreen::TaskThreadLoop() { DHLOGI("DScreen taskThread start. devId: %s, dhId: %s", GetAnonyString(devId_).c_str(), @@ -557,13 +584,26 @@ bool DScreen::CheckJsonData(json &attrJson) void DScreen::OnEngineEvent(DScreenEventType event, const std::string &content) { - (void)event; (void)content; + if (event == DScreenEventType::ENGINE_ERROR) { + StopSenderEngine(); + } else if (event == DScreenEventType::TRANS_CHANNEL_CLOSED) { + HandleDisconnect(); + } } void DScreen::OnEngineMessage(const std::shared_ptr &message) { - (void)message; + if (message == nullptr) { + DHLOGE("received engine message is null."); + return; + } + DHLOGI("On sink device engine message received, message type =%d.", message->type_); + if ((message->type_ == DScreenMsgType::START_MIRROR_SUCCESS) || + (message->type_ == DScreenMsgType::START_MIRROR_FAIL)) { + sinkStartSuccess_ = (message->type_ == DScreenMsgType::START_MIRROR_SUCCESS); + waitSinkCondVar_.notify_one(); + } } std::shared_ptr DScreen::GetVideoParam()