From a59e8567335116695a0e42e5c49af5800c4becff Mon Sep 17 00:00:00 2001 From: UMU618 Date: Tue, 9 Mar 2021 16:03:55 +0800 Subject: [PATCH] * improve, relate to #13 --- src/cge/cge/engine.cpp | 21 +++++++++++++++++++++ src/cge/cge/engine.h | 5 +++++ src/cge/cge/video_encoder.cpp | 30 +++++++++++++++++++++++------- src/cge/cge/ws_server.cpp | 28 ++++++++++++++-------------- src/cge/cge/ws_server.h | 6 +++++- src/cgh/captureyuv/captureyuv.cpp | 3 ++- src/cgh/captureyuv/hook_d3d9.cpp | 2 ++ src/deps/include/regame/protocol.h | 10 +++++++++- 8 files changed, 81 insertions(+), 24 deletions(-) diff --git a/src/cge/cge/engine.cpp b/src/cge/cge/engine.cpp index f37781e..c20644a 100644 --- a/src/cge/cge/engine.cpp +++ b/src/cge/cge/engine.cpp @@ -161,3 +161,24 @@ void Engine::SetPresentFlag(bool donot_present) { ResetEvent(donot_present_event_); } } + +void Engine::NotifyRestartAudioEncoder() noexcept {} + +void Engine::NotifyRestartVideoEncoder() noexcept { + if (ws_server_) { + std::string buffer; + buffer.resize(sizeof(regame::NetPacketHeader)); + auto header = reinterpret_cast(buffer.data()); + header->version = regame::kNetPacketCurrentVersion; + header->type = regame::NetPacketType::ResetVideo; + header->size = 0; + ws_server_->Send(std::move(buffer)); + } + + net::dispatch(ioc_, boost::bind(&Engine::RestartVideoEncoder, this)); +} + +void Engine::RestartVideoEncoder() noexcept { + video_encoder_.Stop(); + video_encoder_.Run(); +} \ No newline at end of file diff --git a/src/cge/cge/engine.h b/src/cge/cge/engine.h index 9e7362f..ba58ad0 100644 --- a/src/cge/cge/engine.h +++ b/src/cge/cge/engine.h @@ -60,6 +60,9 @@ class Engine { return video_encoder_.GetCodecID(); } + void NotifyRestartAudioEncoder() noexcept; + void NotifyRestartVideoEncoder() noexcept; + private: Engine() = default; @@ -67,6 +70,8 @@ class Engine { void Loop() noexcept; + void RestartVideoEncoder() noexcept; + private: bool running_ = false; diff --git a/src/cge/cge/video_encoder.cpp b/src/cge/cge/video_encoder.cpp index 8ad694f..ecd478d 100644 --- a/src/cge/cge/video_encoder.cpp +++ b/src/cge/cge/video_encoder.cpp @@ -66,7 +66,7 @@ bool VideoEncoder::Init(uint64_t bitrate, sizeof(SharedVideoFrameInfo), kSharedVideoFrameInfoFileMappingName.data(), nullptr, g_app.SA()); if (FAILED(hr)) { - std::cerr << "MapSharedMem() failed with 0x" << std::hex << hr << '\n'; + std::cerr << "MapSharedMem(info) failed with 0x" << std::hex << hr << '\n'; return false; } @@ -88,7 +88,14 @@ void VideoEncoder::Stop() { } int VideoEncoder::EncodingThread() { - BOOST_SCOPE_EXIT_ALL(&) { Free(false); }; + bool restart = false; + BOOST_SCOPE_EXIT_ALL(&) { + if (restart) { + Engine::GetInstance().NotifyRestartVideoEncoder(); + } else { + Free(false); + } + }; const char* format_name = nullptr; if (AV_CODEC_ID_H264 == GetCodecID()) { @@ -119,7 +126,9 @@ int VideoEncoder::EncodingThread() { return error_code; } - saved_frame_info_ = *static_cast(shared_frame_info_); + auto shared_frame_info = + static_cast(shared_frame_info_); + saved_frame_info_ = *shared_frame_info; std::cout << "Video timestamp: " << saved_frame_info_.timestamp << ", type: " << static_cast(saved_frame_info_.type) << ", dimension: " << saved_frame_info_.width << " * " @@ -132,11 +141,10 @@ int VideoEncoder::EncodingThread() { sizeof(PackedVideoYuvFrame) * kNumberOfSharedFrames + yuv_size * kNumberOfSharedFrames; - HRESULT hr = shared_frames_.MapSharedMem( - frames_size, kSharedVideoYuvFramesFileMappingName.data(), nullptr, - g_app.SA()); + HRESULT hr = shared_frames_.OpenMapping( + kSharedVideoYuvFramesFileMappingName.data(), frames_size); if (FAILED(hr)) { - std::cerr << "MapSharedMem() failed with 0x" << std::hex << hr << '\n'; + std::cerr << "OpenMapping() failed with 0x" << std::hex << hr << '\n'; return hr; } @@ -185,6 +193,14 @@ int VideoEncoder::EncodingThread() { << ".\n"; return -1; } + + if (shared_frame_info->width != saved_frame_info_.width || + shared_frame_info->height != saved_frame_info_.height) { + std::cout << "Video dimension changed to " << shared_frame_info->width + << " * " << shared_frame_info->height << ".\n"; + restart = true; + return 0; + } } return 0; diff --git a/src/cge/cge/ws_server.cpp b/src/cge/cge/ws_server.cpp index 7f26606..e191fc2 100644 --- a/src/cge/cge/ws_server.cpp +++ b/src/cge/cge/ws_server.cpp @@ -157,6 +157,12 @@ void WsServer::Stop(bool restart) { (*sessions_.begin())->Stop(restart); } } + +void WsServer::CloseAllClients() { + while (!sessions_.empty()) { + (*sessions_.begin())->Stop(true); + } +} #pragma endregion #pragma region "WsSession" @@ -175,9 +181,7 @@ void WsSession::OnRun() { void WsSession::Stop(bool restart) { if (ws_.is_open()) { - std::cout << "Closing " << ws_.next_layer().socket().remote_endpoint() - << '\n'; - + std::cout << "Closing " << remote_endpoint_ << '\n'; if (restart) { ws_.async_close( websocket::close_reason(websocket::close_code::try_again_later), @@ -225,13 +229,11 @@ void WsSession::Write(std::string buffer) { void WsSession::OnAccept(beast::error_code ec) { if (ec == websocket::error::closed) { - std::cout << "Close " << ws_.next_layer().socket().remote_endpoint() - << '\n'; + std::cout << "Close " << remote_endpoint_ << '\n'; return; } if (ec) { - return SessionFail(ec, ws_.next_layer().socket().remote_endpoint(), - "accept"); + return SessionFail(ec, remote_endpoint_, "accept"); } if (!server_->Join(shared_from_this())) { @@ -258,7 +260,7 @@ void WsSession::OnRead(beast::error_code ec, std::size_t bytes_transferred) { if (ec == websocket::error::closed) { return; } - return SessionFail(ec, ws_.next_layer().socket().remote_endpoint(), "read"); + return SessionFail(ec, remote_endpoint_, "read"); } #if _DEBUG std::cout << __func__ << ": " << bytes_transferred << '\n'; @@ -275,8 +277,7 @@ void WsSession::OnRead(beast::error_code ec, std::size_t bytes_transferred) { void WsSession::OnWrite(beast::error_code ec, std::size_t bytes_transferred) { if (ec) { Stop(true); - return SessionFail(ec, ws_.next_layer().socket().remote_endpoint(), - "write"); + return SessionFail(ec, remote_endpoint_, "write"); } #if _DEBUG if (bytes_transferred != write_queue_.front().size()) { @@ -354,8 +355,8 @@ bool WsSession::ServeClient() { } if (!authorized_) { - std::cout << username_ << " login failed from " - << ws_.next_layer().socket().remote_endpoint() << '\n'; + std::cout << username_ << " login failed from " << remote_endpoint_ + << '\n'; return false; } @@ -377,8 +378,7 @@ bool WsSession::ServeClient() { htonl(Engine::GetInstance().GetVideoCodecID()); Write(std::move(buffer)); - std::cout << "Authorized " - << ws_.next_layer().socket().remote_endpoint() << '\n'; + std::cout << "Authorized " << remote_endpoint_ << '\n'; } read_buffer_.consume(packet_size); diff --git a/src/cge/cge/ws_server.h b/src/cge/cge/ws_server.h index ad44a92..176e4df 100644 --- a/src/cge/cge/ws_server.h +++ b/src/cge/cge/ws_server.h @@ -28,7 +28,9 @@ class WsSession : public std::enable_shared_from_this { public: explicit WsSession(tcp::socket&& socket, std::shared_ptr&& server) noexcept - : ws_(std::move(socket)), server_(std::move(server)) {} + : ws_(std::move(socket)), + server_(std::move(server)), + remote_endpoint_(ws_.next_layer().socket().remote_endpoint()) {} ~WsSession() = default; @@ -59,6 +61,7 @@ class WsSession : public std::enable_shared_from_this { std::shared_ptr server_; bool authorized_ = false; websocket::stream ws_; + net::ip::tcp::endpoint remote_endpoint_; beast::flat_buffer read_buffer_; std::mutex queue_mutex_; @@ -76,6 +79,7 @@ class WsServer : public std::enable_shared_from_this { void Run() { Accept(); } void Stop(bool restart); size_t Send(std::string buffer); + void CloseAllClients(); private: void Accept() { diff --git a/src/cgh/captureyuv/captureyuv.cpp b/src/cgh/captureyuv/captureyuv.cpp index d8745aa..79097ec 100644 --- a/src/cgh/captureyuv/captureyuv.cpp +++ b/src/cgh/captureyuv/captureyuv.cpp @@ -257,7 +257,8 @@ bool CaptureYuv::CreateSharedVideoYuvFrames(size_t data_size) noexcept { HRESULT hr = shared_frames_.MapSharedMem( new_size, kSharedVideoYuvFramesFileMappingName.data(), nullptr, SA()); if (FAILED(hr)) { - ATLTRACE2(atlTraceException, 0, "MapSharedMem() failed.\n"); + ATLTRACE2(atlTraceException, 0, "MapSharedMem() failed with 0x%08x.\n", + hr); return false; } diff --git a/src/cgh/captureyuv/hook_d3d9.cpp b/src/cgh/captureyuv/hook_d3d9.cpp index bbd82cd..6547cfa 100644 --- a/src/cgh/captureyuv/hook_d3d9.cpp +++ b/src/cgh/captureyuv/hook_d3d9.cpp @@ -120,6 +120,8 @@ class CaptureD3d9 { size_t frame_size = mapped_rect.Pitch * desc.Height; size_t data_size = sizeof(PackedVideoYuvFrame) + frame_size; if (!CaptureYuv::GetInstance().CreateSharedVideoYuvFrames(data_size)) { + // unchanged but notify + CaptureYuv::GetInstance().SetSharedFrameReadyEvent(); return; } diff --git a/src/deps/include/regame/protocol.h b/src/deps/include/regame/protocol.h index 0703e51..c95727a 100644 --- a/src/deps/include/regame/protocol.h +++ b/src/deps/include/regame/protocol.h @@ -17,7 +17,15 @@ #pragma once namespace regame { -enum class NetPacketType : uint8_t { Login = 0, Audio, Video, Ping, Pong }; +enum class NetPacketType : uint8_t { + Login = 0, + Audio, + Video, + Ping, + Pong, + ResetAudio, + ResetVideo +}; enum class VerificationType : uint8_t { Code = 0, SM3 }; constexpr uint8_t kNetPacketCurrentVersion = 0; constexpr uint8_t kMaxUsernameSize = 32;