Video: There was always a black line around one of the 4 edges (top/left/bottom/right) of the window because the final output size wasn't calculated right (unless the aspect ratio was set to stretch)

This commit is contained in:
Filoppi 2023-06-27 12:43:45 +03:00
parent fae3aee9e0
commit cb34d1aafe
1 changed files with 52 additions and 6 deletions

View File

@ -33,6 +33,39 @@ static float AspectToWidescreen(float aspect)
return aspect * ((16.0f / 9.0f) / (4.0f / 3.0f)); return aspect * ((16.0f / 9.0f) / (4.0f / 3.0f));
} }
static std::tuple<int, int> FindClosestIntegerResolution(float width, float height,
float aspect_ratio)
{
// We can't round both the x and y resolution as that might generate an aspect ratio
// further away from the target one, we also can't either ceil or floor both sides,
// so we find the combination or flooring and ceiling that is closest to the target ar.
const int ceiled_width = static_cast<int>(std::ceil(width));
const int ceiled_height = static_cast<int>(std::ceil(height));
const int floored_width = static_cast<int>(std::floor(width));
const int floored_height = static_cast<int>(std::floor(height));
int int_width = floored_width;
int int_height = floored_height;
float min_aspect_ratio_distance = std::numeric_limits<float>::max();
for (const int new_width : std::array<int, 2>{ceiled_width, floored_width})
{
for (const int new_height : std::array<int, 2>{ceiled_height, floored_height})
{
const float new_aspect_ratio = static_cast<float>(new_width) / new_height;
const float aspect_ratio_distance = std::abs((new_aspect_ratio / aspect_ratio) - 1.f);
if (aspect_ratio_distance < min_aspect_ratio_distance)
{
min_aspect_ratio_distance = aspect_ratio_distance;
int_width = new_width;
int_height = new_height;
}
}
}
return std::make_tuple(int_width, int_height);
}
Presenter::Presenter() Presenter::Presenter()
{ {
m_config_changed = m_config_changed =
@ -414,11 +447,12 @@ void Presenter::UpdateDrawRectangle()
// The rendering window size // The rendering window size
const float win_width = static_cast<float>(m_backbuffer_width); const float win_width = static_cast<float>(m_backbuffer_width);
const float win_height = static_cast<float>(m_backbuffer_height); const float win_height = static_cast<float>(m_backbuffer_height);
const float win_aspect_ratio = win_width / win_height;
// FIXME: this breaks at very low widget sizes // FIXME: this breaks at very low widget sizes
// Make ControllerInterface aware of the render window region actually being used // Make ControllerInterface aware of the render window region actually being used
// to adjust mouse cursor inputs. // to adjust mouse cursor inputs.
g_controller_interface.SetAspectRatioAdjustment(draw_aspect_ratio / (win_width / win_height)); g_controller_interface.SetAspectRatioAdjustment(draw_aspect_ratio / win_aspect_ratio);
float draw_width = draw_aspect_ratio; float draw_width = draw_aspect_ratio;
float draw_height = 1; float draw_height = 1;
@ -427,7 +461,7 @@ void Presenter::UpdateDrawRectangle()
auto [crop_width, crop_height] = ApplyStandardAspectCrop(draw_width, draw_height); auto [crop_width, crop_height] = ApplyStandardAspectCrop(draw_width, draw_height);
// scale the picture to fit the rendering window // scale the picture to fit the rendering window
if (win_width / win_height >= crop_width / crop_height) if (win_aspect_ratio >= crop_width / crop_height)
{ {
// the window is flatter than the picture // the window is flatter than the picture
draw_width *= win_height / crop_height; draw_width *= win_height / crop_height;
@ -444,6 +478,9 @@ void Presenter::UpdateDrawRectangle()
crop_width = win_width; crop_width = win_width;
} }
int int_draw_width;
int int_draw_height;
if (g_frame_dumper->IsFrameDumping()) if (g_frame_dumper->IsFrameDumping())
{ {
// ensure divisibility by "VIDEO_ENCODER_LCM" to make it compatible with all the video encoders. // ensure divisibility by "VIDEO_ENCODER_LCM" to make it compatible with all the video encoders.
@ -452,12 +489,21 @@ void Presenter::UpdateDrawRectangle()
std::ceil(draw_width) - static_cast<int>(std::ceil(draw_width)) % VIDEO_ENCODER_LCM; std::ceil(draw_width) - static_cast<int>(std::ceil(draw_width)) % VIDEO_ENCODER_LCM;
draw_height = draw_height =
std::ceil(draw_height) - static_cast<int>(std::ceil(draw_height)) % VIDEO_ENCODER_LCM; std::ceil(draw_height) - static_cast<int>(std::ceil(draw_height)) % VIDEO_ENCODER_LCM;
int_draw_width = static_cast<int>(draw_width);
int_draw_height = static_cast<int>(draw_height);
}
else
{
const auto int_draw_res =
FindClosestIntegerResolution(draw_width, draw_height, win_aspect_ratio);
int_draw_width = std::get<0>(int_draw_res);
int_draw_height = std::get<1>(int_draw_res);
} }
m_target_rectangle.left = static_cast<int>(std::round(win_width / 2.0 - draw_width / 2.0)); m_target_rectangle.left = static_cast<int>(std::round(win_width / 2.0 - int_draw_width / 2.0));
m_target_rectangle.top = static_cast<int>(std::round(win_height / 2.0 - draw_height / 2.0)); m_target_rectangle.top = static_cast<int>(std::round(win_height / 2.0 - int_draw_height / 2.0));
m_target_rectangle.right = m_target_rectangle.left + static_cast<int>(draw_width); m_target_rectangle.right = m_target_rectangle.left + int_draw_width;
m_target_rectangle.bottom = m_target_rectangle.top + static_cast<int>(draw_height); m_target_rectangle.bottom = m_target_rectangle.top + int_draw_height;
} }
std::tuple<float, float> Presenter::ScaleToDisplayAspectRatio(const int width, std::tuple<float, float> Presenter::ScaleToDisplayAspectRatio(const int width,