diff --git a/sunshine/platform/windows_dxgi.cpp b/sunshine/platform/windows_dxgi.cpp index c5f6539d..07ab44fe 100644 --- a/sunshine/platform/windows_dxgi.cpp +++ b/sunshine/platform/windows_dxgi.cpp @@ -122,22 +122,28 @@ void blend_cursor_monochrome(const cursor_t &cursor, img_t &img) { int width = cursor.shape_info.Width; int pitch = cursor.shape_info.Pitch; - // img cursor.y < 0, skip parts of the cursor.img_data - auto cursor_skip_y = std::min(0, cursor.y); - auto cursor_skip_x = std::min(0, cursor.x); - auto img_skip_y = std::max(0, cursor.y); - auto img_skip_x = std::max(0, cursor.x); + // img cursor.{x,y} < 0, skip parts of the cursor.img_data + auto cursor_skip_y = -std::min(0, cursor.y); + auto cursor_skip_x = -std::min(0, cursor.x); - if(cursor_skip_y > height || cursor_skip_x > width) { + // img cursor.{x,y} > img.{x,y}, truncate parts of the cursor.img_data + auto cursor_truncate_y = std::max(0, cursor.y - img.height); + auto cursor_truncate_x = std::max(0, cursor.x - img.width); + + auto cursor_width = width - cursor_skip_x - cursor_truncate_x; + auto cursor_height = height - cursor_skip_y - cursor_truncate_y; + + if(cursor_height > height || cursor_width > width) { return; } - height -= cursor_skip_y; - width -= cursor_skip_x; + auto img_skip_y = std::max(0, cursor.y); + auto img_skip_x = std::max(0, cursor.x); + auto cursor_img_data = cursor.img_data.data() + cursor_skip_y * pitch; - int delta_height = std::min(height, std::max(0, img.height - img_skip_y)); - int delta_width = std::min(width, std::max(0, img.width - img_skip_x)); + int delta_height = std::min(cursor_height - cursor_truncate_y, std::max(0, img.height - img_skip_y)); + int delta_width = std::min(cursor_width - cursor_truncate_x, std::max(0, img.width - img_skip_x)); auto pixels_per_byte = width / pitch; auto bytes_per_row = delta_width / pixels_per_byte; @@ -149,11 +155,11 @@ void blend_cursor_monochrome(const cursor_t &cursor, img_t &img) { auto img_pixel_p = &img_data[(i + img_skip_y) * (img.row_pitch / img.pixel_pitch) + img_skip_x]; - auto skip_y = cursor_skip_y; + auto skip_x = cursor_skip_x; for(int x = 0; x < bytes_per_row; ++x) { for(auto bit = 0u; bit < 8; ++bit) { - if(skip_y > 0) { - --skip_y; + if(skip_x > 0) { + --skip_x; continue; } @@ -179,26 +185,32 @@ void blend_cursor_color(const cursor_t &cursor, img_t &img) { int pitch = cursor.shape_info.Pitch; // img cursor.y < 0, skip parts of the cursor.img_data - auto cursor_skip_y = std::min(0, cursor.y); - auto cursor_skip_x = std::min(0, cursor.x); + auto cursor_skip_y = -std::min(0, cursor.y); + auto cursor_skip_x = -std::min(0, cursor.x); + + // img cursor.{x,y} > img.{x,y}, truncate parts of the cursor.img_data + auto cursor_truncate_y = std::max(0, cursor.y - img.height); + auto cursor_truncate_x = std::max(0, cursor.x - img.width); + auto img_skip_y = std::max(0, cursor.y); auto img_skip_x = std::max(0, cursor.x); - if(cursor_skip_y > height || cursor_skip_x > width) { + auto cursor_width = width - cursor_skip_x - cursor_truncate_x; + auto cursor_height = height - cursor_skip_y - cursor_truncate_y; + + if(cursor_height > height || cursor_width > width) { return; } - height -= cursor_skip_y; - width -= cursor_skip_x; auto cursor_img_data = (int*)&cursor.img_data[cursor_skip_y * pitch]; - int delta_height = std::min(height, std::max(0, img.height - img_skip_y)); - int delta_width = std::min(width, std::max(0, img.width - img_skip_x)); + int delta_height = std::min(cursor_height - cursor_truncate_y, std::max(0, img.height - img_skip_y)); + int delta_width = std::min(cursor_width - cursor_truncate_x, std::max(0, img.width - img_skip_x)); auto img_data = (int*)img.data; for(int i = 0; i < delta_height; ++i) { - auto cursor_begin = &cursor_img_data[i * width + cursor_skip_x]; + auto cursor_begin = &cursor_img_data[i * cursor.shape_info.Width + cursor_skip_x]; auto cursor_end = &cursor_begin[delta_width]; auto img_pixel_p = &img_data[(i + img_skip_y) * (img.row_pitch / img.pixel_pitch) + img_skip_x]; diff --git a/sunshine/rtsp.cpp b/sunshine/rtsp.cpp index b98a5432..d16aef73 100644 --- a/sunshine/rtsp.cpp +++ b/sunshine/rtsp.cpp @@ -21,6 +21,15 @@ using asio::ip::udp; using namespace std::literals; namespace stream { + +//FIXME: Quick and dirty workaround for bug in MinGW 9.3 causing a linker error when using std::to_string +template +std::string to_string(T && t) { + std::stringstream ss; + ss << std::forward(t); + return ss.str(); +} + constexpr auto RTSP_SETUP_PORT = 48010; void free_msg(PRTSP_MESSAGE msg) { @@ -222,7 +231,7 @@ void cmd_option(rtsp_server_t *server, net::peer_t peer, msg_t&& req) { // I know these string literals will not be modified option.option = const_cast("CSeq"); - auto seqn_str = std::to_string(req->sequenceNumber); + auto seqn_str = to_string(req->sequenceNumber); option.content = const_cast(seqn_str.c_str()); respond(server->host(), peer, &option, 200, "OK", req->sequenceNumber, {}); @@ -234,7 +243,7 @@ void cmd_describe(rtsp_server_t *server, net::peer_t peer, msg_t&& req) { // I know these string literals will not be modified option.option = const_cast("CSeq"); - auto seqn_str = std::to_string(req->sequenceNumber); + auto seqn_str = to_string(req->sequenceNumber); option.content = const_cast(seqn_str.c_str()); std::string_view payload; @@ -256,7 +265,7 @@ void cmd_setup(rtsp_server_t *server, net::peer_t peer, msg_t &&req) { seqn.option = const_cast("CSeq"); - auto seqn_str = std::to_string(req->sequenceNumber); + auto seqn_str = to_string(req->sequenceNumber); seqn.content = const_cast(seqn_str.c_str()); std::string_view target { req->message.request.target }; @@ -285,7 +294,7 @@ void cmd_announce(rtsp_server_t *server, net::peer_t peer, msg_t &&req) { // I know these string literals will not be modified option.option = const_cast("CSeq"); - auto seqn_str = std::to_string(req->sequenceNumber); + auto seqn_str = to_string(req->sequenceNumber); option.content = const_cast(seqn_str.c_str()); if(!launch_event.peek()) { @@ -394,7 +403,7 @@ void cmd_play(rtsp_server_t *server, net::peer_t peer, msg_t &&req) { // I know these string literals will not be modified option.option = const_cast("CSeq"); - auto seqn_str = std::to_string(req->sequenceNumber); + auto seqn_str = to_string(req->sequenceNumber); option.content = const_cast(seqn_str.c_str()); respond(server->host(), peer, &option, 200, "OK", req->sequenceNumber, {}); @@ -464,4 +473,4 @@ void print_msg(PRTSP_MESSAGE msg) { BOOST_LOG(debug) << "---Begin MessageBuffer---"sv << std::endl << messageBuffer << std::endl << "---End MessageBuffer---"sv << std::endl; } -} \ No newline at end of file +}