Fix bug incorrectly blending cursor image
This commit is contained in:
@@ -122,22 +122,28 @@ void blend_cursor_monochrome(const cursor_t &cursor, img_t &img) {
|
|||||||
int width = cursor.shape_info.Width;
|
int width = cursor.shape_info.Width;
|
||||||
int pitch = cursor.shape_info.Pitch;
|
int pitch = cursor.shape_info.Pitch;
|
||||||
|
|
||||||
// img cursor.y < 0, skip parts of the cursor.img_data
|
// img cursor.{x,y} < 0, skip parts of the cursor.img_data
|
||||||
auto cursor_skip_y = std::min(0, cursor.y);
|
auto cursor_skip_y = -std::min(0, cursor.y);
|
||||||
auto cursor_skip_x = std::min(0, cursor.x);
|
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);
|
|
||||||
|
|
||||||
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
height -= cursor_skip_y;
|
auto img_skip_y = std::max(0, cursor.y);
|
||||||
width -= cursor_skip_x;
|
auto img_skip_x = std::max(0, cursor.x);
|
||||||
|
|
||||||
auto cursor_img_data = cursor.img_data.data() + cursor_skip_y * pitch;
|
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_height = std::min(cursor_height - cursor_truncate_y, std::max(0, img.height - img_skip_y));
|
||||||
int delta_width = std::min(width, std::max(0, img.width - img_skip_x));
|
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 pixels_per_byte = width / pitch;
|
||||||
auto bytes_per_row = delta_width / pixels_per_byte;
|
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 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(int x = 0; x < bytes_per_row; ++x) {
|
||||||
for(auto bit = 0u; bit < 8; ++bit) {
|
for(auto bit = 0u; bit < 8; ++bit) {
|
||||||
if(skip_y > 0) {
|
if(skip_x > 0) {
|
||||||
--skip_y;
|
--skip_x;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -179,26 +185,32 @@ void blend_cursor_color(const cursor_t &cursor, img_t &img) {
|
|||||||
int pitch = cursor.shape_info.Pitch;
|
int pitch = cursor.shape_info.Pitch;
|
||||||
|
|
||||||
// img cursor.y < 0, skip parts of the cursor.img_data
|
// img cursor.y < 0, skip parts of the cursor.img_data
|
||||||
auto cursor_skip_y = std::min(0, cursor.y);
|
auto cursor_skip_y = -std::min(0, cursor.y);
|
||||||
auto cursor_skip_x = std::min(0, cursor.x);
|
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_y = std::max(0, cursor.y);
|
||||||
auto img_skip_x = std::max(0, cursor.x);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
height -= cursor_skip_y;
|
|
||||||
width -= cursor_skip_x;
|
|
||||||
auto cursor_img_data = (int*)&cursor.img_data[cursor_skip_y * pitch];
|
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_height = std::min(cursor_height - cursor_truncate_y, std::max(0, img.height - img_skip_y));
|
||||||
int delta_width = std::min(width, std::max(0, img.width - img_skip_x));
|
int delta_width = std::min(cursor_width - cursor_truncate_x, std::max(0, img.width - img_skip_x));
|
||||||
|
|
||||||
auto img_data = (int*)img.data;
|
auto img_data = (int*)img.data;
|
||||||
|
|
||||||
for(int i = 0; i < delta_height; ++i) {
|
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 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];
|
auto img_pixel_p = &img_data[(i + img_skip_y) * (img.row_pitch / img.pixel_pitch) + img_skip_x];
|
||||||
|
|||||||
+14
-5
@@ -21,6 +21,15 @@ using asio::ip::udp;
|
|||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
|
||||||
namespace stream {
|
namespace stream {
|
||||||
|
|
||||||
|
//FIXME: Quick and dirty workaround for bug in MinGW 9.3 causing a linker error when using std::to_string
|
||||||
|
template<class T>
|
||||||
|
std::string to_string(T && t) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << std::forward<T>(t);
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
constexpr auto RTSP_SETUP_PORT = 48010;
|
constexpr auto RTSP_SETUP_PORT = 48010;
|
||||||
|
|
||||||
void free_msg(PRTSP_MESSAGE msg) {
|
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
|
// I know these string literals will not be modified
|
||||||
option.option = const_cast<char*>("CSeq");
|
option.option = const_cast<char*>("CSeq");
|
||||||
|
|
||||||
auto seqn_str = std::to_string(req->sequenceNumber);
|
auto seqn_str = to_string(req->sequenceNumber);
|
||||||
option.content = const_cast<char*>(seqn_str.c_str());
|
option.content = const_cast<char*>(seqn_str.c_str());
|
||||||
|
|
||||||
respond(server->host(), peer, &option, 200, "OK", req->sequenceNumber, {});
|
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
|
// I know these string literals will not be modified
|
||||||
option.option = const_cast<char*>("CSeq");
|
option.option = const_cast<char*>("CSeq");
|
||||||
|
|
||||||
auto seqn_str = std::to_string(req->sequenceNumber);
|
auto seqn_str = to_string(req->sequenceNumber);
|
||||||
option.content = const_cast<char*>(seqn_str.c_str());
|
option.content = const_cast<char*>(seqn_str.c_str());
|
||||||
|
|
||||||
std::string_view payload;
|
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<char*>("CSeq");
|
seqn.option = const_cast<char*>("CSeq");
|
||||||
|
|
||||||
auto seqn_str = std::to_string(req->sequenceNumber);
|
auto seqn_str = to_string(req->sequenceNumber);
|
||||||
seqn.content = const_cast<char*>(seqn_str.c_str());
|
seqn.content = const_cast<char*>(seqn_str.c_str());
|
||||||
|
|
||||||
std::string_view target { req->message.request.target };
|
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
|
// I know these string literals will not be modified
|
||||||
option.option = const_cast<char*>("CSeq");
|
option.option = const_cast<char*>("CSeq");
|
||||||
|
|
||||||
auto seqn_str = std::to_string(req->sequenceNumber);
|
auto seqn_str = to_string(req->sequenceNumber);
|
||||||
option.content = const_cast<char*>(seqn_str.c_str());
|
option.content = const_cast<char*>(seqn_str.c_str());
|
||||||
|
|
||||||
if(!launch_event.peek()) {
|
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
|
// I know these string literals will not be modified
|
||||||
option.option = const_cast<char*>("CSeq");
|
option.option = const_cast<char*>("CSeq");
|
||||||
|
|
||||||
auto seqn_str = std::to_string(req->sequenceNumber);
|
auto seqn_str = to_string(req->sequenceNumber);
|
||||||
option.content = const_cast<char*>(seqn_str.c_str());
|
option.content = const_cast<char*>(seqn_str.c_str());
|
||||||
|
|
||||||
respond(server->host(), peer, &option, 200, "OK", req->sequenceNumber, {});
|
respond(server->host(), peer, &option, 200, "OK", req->sequenceNumber, {});
|
||||||
|
|||||||
Reference in New Issue
Block a user