From 6ec0cae2d0ca341b88b6fbba145068ddaf1d8770 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Wed, 22 Jan 2020 17:40:48 -0800 Subject: [PATCH] Fix row pitch being assumed to be 'width * 4' --- sunshine/platform/common.h | 2 ++ sunshine/platform/linux.cpp | 18 +++++++++++------- sunshine/platform/windows_dxgi.cpp | 7 +++++-- sunshine/video.cpp | 2 +- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/sunshine/platform/common.h b/sunshine/platform/common.h index 5e1fed5a..5334ffb4 100644 --- a/sunshine/platform/common.h +++ b/sunshine/platform/common.h @@ -40,6 +40,8 @@ public: std::uint8_t *data {}; std::int32_t width {}; std::int32_t height {}; + std::int32_t pixel_pitch {}; + std::int32_t row_pitch {}; img_t() = default; img_t(const img_t&) = delete; diff --git a/sunshine/platform/linux.cpp b/sunshine/platform/linux.cpp index acfe68a7..f4cdc52f 100644 --- a/sunshine/platform/linux.cpp +++ b/sunshine/platform/linux.cpp @@ -89,7 +89,7 @@ struct shm_img_t : public img_t { } }; -void blend_cursor(Display *display, std::uint8_t *img_data, int width, int height) { +void blend_cursor(Display *display, img_t &img) { xcursor_t overlay { XFixesGetCursorImage(display) }; if(!overlay) { @@ -103,10 +103,10 @@ void blend_cursor(Display *display, std::uint8_t *img_data, int width, int heigh overlay->x = std::max((short)0, overlay->x); overlay->y = std::max((short)0, overlay->y); - auto pixels = (int*)img_data; + auto pixels = (int*)img.data; - auto screen_height = height; - auto screen_width = width; + auto screen_height = img.height; + auto screen_width = img.width; auto delta_height = std::min(overlay->height, std::max(0, screen_height - overlay->y)); auto delta_width = std::min(overlay->width, std::max(0, screen_width - overlay->x)); @@ -115,7 +115,7 @@ void blend_cursor(Display *display, std::uint8_t *img_data, int width, int heigh auto overlay_begin = &overlay->pixels[y * overlay->width]; auto overlay_end = &overlay->pixels[y * overlay->width + delta_width]; - auto pixels_begin = &pixels[(y + overlay->y) * screen_width + overlay->x]; + auto pixels_begin = &pixels[(y + overlay->y) * (img.row_pitch / img.pixel_pitch) + overlay->x]; std::for_each(overlay_begin, overlay_end, [&](long pixel) { int *pixel_p = (int*)&pixel; @@ -166,10 +166,12 @@ struct x11_attr_t : public display_t { img_out->width = img->width; img_out->height = img->height; img_out->data = (uint8_t*)img->data; + img_out->row_pitch = img->bytes_per_line; + img_out->pixel_pitch = img->bits_per_pixel / 8; img_out->img.reset(img); if(cursor) { - blend_cursor(xdisplay.get(), (std::uint8_t*)img->data, img->width, img->height); + blend_cursor(xdisplay.get(), *img_out_base); } return capture_e::ok; @@ -237,12 +239,14 @@ struct shm_attr_t : public x11_attr_t { img->data = new std::uint8_t[frame_size()]; img->width = display->width_in_pixels; img->height = display->height_in_pixels; + img->pixel_pitch = 4; + img->row_pitch = img->width * img->pixel_pitch; } std::copy_n((std::uint8_t*)data.data, frame_size(), img->data); if(cursor) { - blend_cursor(shm_xdisplay.get(), img->data, img->width, img->height); + blend_cursor(shm_xdisplay.get(), *img); } return capture_e::ok; diff --git a/sunshine/platform/windows_dxgi.cpp b/sunshine/platform/windows_dxgi.cpp index fef95e1e..9cd86e77 100644 --- a/sunshine/platform/windows_dxgi.cpp +++ b/sunshine/platform/windows_dxgi.cpp @@ -144,7 +144,7 @@ void blend_cursor_monochrome(const cursor_t &cursor, img_t &img) { auto and_mask = &cursor_img_data[i * pitch]; auto xor_mask = &cursor_img_data[(i + height) * pitch]; - auto img_pixel_p = &img_data[(i + img_skip_y) * img.width + 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; for(int x = 0; x < bytes_per_row; ++x) { @@ -198,7 +198,7 @@ void blend_cursor_color(const cursor_t &cursor, img_t &img) { auto cursor_begin = &cursor_img_data[i * width + cursor_skip_x]; auto cursor_end = &cursor_begin[delta_width]; - auto img_pixel_p = &img_data[(i + img_skip_y) * img.width + img_skip_x]; + auto img_pixel_p = &img_data[(i + img_skip_y) * (img.row_pitch / img.pixel_pitch) + img_skip_x]; std::for_each(cursor_begin, cursor_end, [&](int cursor_pixel) { auto colors_out = (std::uint8_t*)&cursor_pixel; auto colors_in = (std::uint8_t*)img_pixel_p; @@ -313,6 +313,7 @@ public: img->width = width; img->height = height; + img->row_pitch = current_img.RowPitch; } std::copy_n((std::uint8_t*)current_img.pData, height * current_img.RowPitch, (std::uint8_t*)img->data); @@ -329,6 +330,8 @@ public: img->data = nullptr; img->height = 0; img->width = 0; + img->row_pitch = 0; + img->pixel_pitch = 4; return img; } diff --git a/sunshine/video.cpp b/sunshine/video.cpp index be9652c7..d83b6e6f 100644 --- a/sunshine/video.cpp +++ b/sunshine/video.cpp @@ -46,7 +46,7 @@ void encode(int64_t frame, ctx_t &ctx, sws_t &sws, frame_t &yuv_frame, platf::im av_frame_make_writable(yuv_frame.get()); const int linesizes[2] { - (int)(img.width * sizeof(int)), 0 + img.row_pitch, 0 }; auto data = img.data;