From f2863cceb7ce23f0232ee59ff4be8da7534ffed3 Mon Sep 17 00:00:00 2001 From: loki Date: Sat, 5 Jun 2021 12:25:19 +0200 Subject: [PATCH] Properly scale image on VAAPI --- assets/sunshine.conf | 3 +-- sunshine/platform/common.h | 2 +- sunshine/platform/linux/display.cpp | 4 ++-- sunshine/platform/linux/vaapi.cpp | 37 ++++++++++++++++++++--------- sunshine/platform/linux/vaapi.h | 2 +- sunshine/video.cpp | 6 ++--- 6 files changed, 34 insertions(+), 20 deletions(-) diff --git a/assets/sunshine.conf b/assets/sunshine.conf index a7728d0c..7a67c87b 100644 --- a/assets/sunshine.conf +++ b/assets/sunshine.conf @@ -247,5 +247,4 @@ # To set the initial state of flags -0 and -1 to on, set the following flags: # flags = 01 # -# See: sunshine --help for all options under the header: flags -adapter_name = /dev/dri/renderD129 \ No newline at end of file +# See: sunshine --help for all options under the header: flags \ No newline at end of file diff --git a/sunshine/platform/common.h b/sunshine/platform/common.h index 88622674..2f131a3b 100644 --- a/sunshine/platform/common.h +++ b/sunshine/platform/common.h @@ -192,7 +192,7 @@ public: virtual int dummy_img(img_t *img) = 0; - virtual std::shared_ptr make_hwdevice(int width, int height, pix_fmt_e pix_fmt) { + virtual std::shared_ptr make_hwdevice(pix_fmt_e pix_fmt) { return std::make_shared(); } diff --git a/sunshine/platform/linux/display.cpp b/sunshine/platform/linux/display.cpp index 1bad274c..a6f3df9c 100644 --- a/sunshine/platform/linux/display.cpp +++ b/sunshine/platform/linux/display.cpp @@ -243,9 +243,9 @@ struct x11_attr_t : public display_t { return std::make_shared(); } - std::shared_ptr make_hwdevice(int width, int height, pix_fmt_e pix_fmt) override { + std::shared_ptr make_hwdevice(pix_fmt_e pix_fmt) override { if(mem_type == mem_type_e::vaapi) { - return egl::make_hwdevice(); + return egl::make_hwdevice(width, height); } return std::make_shared(); diff --git a/sunshine/platform/linux/vaapi.cpp b/sunshine/platform/linux/vaapi.cpp index 273e64a6..21c14c75 100644 --- a/sunshine/platform/linux/vaapi.cpp +++ b/sunshine/platform/linux/vaapi.cpp @@ -494,7 +494,7 @@ public: color_matrix.update(members, sizeof(members) / sizeof(decltype(members[0]))); } - int init(const char *render_device) { + int init(int in_width, int in_height, const char *render_device) { file.el = open(render_device, O_RDWR); if(file.el < 0) { @@ -661,6 +661,9 @@ public: tex_in = gl::tex_t::make(1); + this->in_width = in_width; + this->in_height = in_height; + data = (void *)vaapi_make_hwdevice_ctx; gl_drain_errors; return 0; @@ -671,7 +674,7 @@ public: gl::ctx.ActiveTexture(GL_TEXTURE0); gl::ctx.BindTexture(GL_TEXTURE_2D, tex); - gl::ctx.TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, out_width, out_height, GL_BGRA, GL_UNSIGNED_BYTE, img.data); + gl::ctx.TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, in_width, in_height, GL_BGRA, GL_UNSIGNED_BYTE, img.data); GLenum attachments[] { GL_COLOR_ATTACHMENT0, @@ -693,7 +696,7 @@ public: gl::ctx.UseProgram(program[x].handle()); program[x].bind(color_matrix); - gl::ctx.Viewport(0, 0, out_width / (x + 1), out_height / (x + 1)); + gl::ctx.Viewport(offsetX / (x + 1), offsetY / (x + 1), out_width / (x + 1), out_height / (x + 1)); gl::ctx.DrawArrays(GL_TRIANGLES, 0, 3); } @@ -718,15 +721,25 @@ public: nv12 = std::move(*nv12_opt); - out_width = frame->width; - out_height = frame->height; + // // Ensure aspect ratio is maintained + auto scalar = std::fminf(frame->width / (float)in_width, frame->height / (float)in_height); + auto out_width_f = in_width * scalar; + auto out_height_f = in_height * scalar; + + // result is always positive + auto offsetX_f = (frame->width - out_width_f) / 2; + auto offsetY_f = (frame->height - out_height_f) / 2; + + out_width = out_width_f; + out_height = out_height_f; + + offsetX = offsetX_f; + offsetY = offsetY_f; auto tex = tex_in[0]; - // gl::ctx.ActiveTexture(GL_TEXTURE0); gl::ctx.BindTexture(GL_TEXTURE_2D, tex); - // gl::ctx.TexImage2D(GL_TEXTURE_2D, 0, 4, out_width, out_height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (void *)dummy_img.begin()); - gl::ctx.TexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, out_width, out_height); + gl::ctx.TexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, in_width, in_height); auto loc_width_i = gl::ctx.GetUniformLocation(program[1].handle(), "width_i"); if(loc_width_i < 0) { @@ -748,7 +761,9 @@ public: } } - std::uint32_t out_width, out_height; + int in_width, in_height; + int out_width, out_height; + int offsetX, offsetY; va::display_t::pointer va_display; @@ -831,11 +846,11 @@ int vaapi_make_hwdevice_ctx(platf::hwdevice_t *base, AVBufferRef **hw_device_buf return 0; } -std::shared_ptr make_hwdevice() { +std::shared_ptr make_hwdevice(int width, int height) { auto egl = std::make_shared(); auto render_device = config::video.adapter_name.empty() ? "/dev/dri/renderD128" : config::video.adapter_name.c_str(); - if(egl->init(render_device)) { + if(egl->init(width, height, render_device)) { return nullptr; } diff --git a/sunshine/platform/linux/vaapi.h b/sunshine/platform/linux/vaapi.h index 2621e056..10b1b3f1 100644 --- a/sunshine/platform/linux/vaapi.h +++ b/sunshine/platform/linux/vaapi.h @@ -3,6 +3,6 @@ #include "sunshine/platform/common.h" namespace platf::egl { -std::shared_ptr make_hwdevice(); +std::shared_ptr make_hwdevice(int width, int height); } // namespace platf::egl #endif \ No newline at end of file diff --git a/sunshine/video.cpp b/sunshine/video.cpp index e9d793ec..46572ed4 100644 --- a/sunshine/video.cpp +++ b/sunshine/video.cpp @@ -982,7 +982,7 @@ std::optional make_synced_session(platf::display_t *disp, const encode_session.delay = std::chrono::nanoseconds { 1s } / ctx.config.framerate; auto pix_fmt = ctx.config.dynamicRange == 0 ? map_pix_fmt(encoder.static_pix_fmt) : map_pix_fmt(encoder.dynamic_pix_fmt); - auto hwdevice = disp->make_hwdevice(ctx.config.width, ctx.config.height, pix_fmt); + auto hwdevice = disp->make_hwdevice(pix_fmt); if(!hwdevice) { return std::nullopt; } @@ -1223,7 +1223,7 @@ void capture_async( } auto pix_fmt = config.dynamicRange == 0 ? platf::pix_fmt_e::yuv420p : platf::pix_fmt_e::yuv420p10; - auto hwdevice = display->make_hwdevice(config.width, config.height, pix_fmt); + auto hwdevice = display->make_hwdevice(pix_fmt); if(!hwdevice) { return; } @@ -1278,7 +1278,7 @@ bool validate_config(std::shared_ptr &disp, const encoder_t &e } auto pix_fmt = config.dynamicRange == 0 ? map_pix_fmt(encoder.static_pix_fmt) : map_pix_fmt(encoder.dynamic_pix_fmt); - auto hwdevice = disp->make_hwdevice(config.width, config.height, pix_fmt); + auto hwdevice = disp->make_hwdevice(pix_fmt); if(!hwdevice) { return false; }