Added a pillarboxThreshold property to control these values for the video element.

This commit is contained in:
Leon Styhre 2022-10-16 16:40:52 +02:00
parent 0f327582c1
commit 45fa3d2c37
4 changed files with 25 additions and 8 deletions

View file

@ -123,6 +123,7 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>>
{"audio", BOOLEAN}, {"audio", BOOLEAN},
{"interpolation", STRING}, {"interpolation", STRING},
{"pillarboxes", BOOLEAN}, {"pillarboxes", BOOLEAN},
{"pillarboxThreshold", NORMALIZED_PAIR},
{"scanlines", BOOLEAN}, {"scanlines", BOOLEAN},
{"delay", FLOAT}, {"delay", FLOAT},
{"fadeInTime", FLOAT}, {"fadeInTime", FLOAT},

View file

@ -25,6 +25,7 @@ VideoComponent::VideoComponent()
, mTargetSize {0.0f, 0.0f} , mTargetSize {0.0f, 0.0f}
, mVideoAreaPos {0.0f, 0.0f} , mVideoAreaPos {0.0f, 0.0f}
, mVideoAreaSize {0.0f, 0.0f} , mVideoAreaSize {0.0f, 0.0f}
, mPillarboxThreshold {0.85f, 0.90f}
, mStartTime {0} , mStartTime {0}
, mIsPlaying {false} , mIsPlaying {false}
, mIsActuallyPlaying {false} , mIsActuallyPlaying {false}
@ -256,6 +257,12 @@ void VideoComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
if (elem->has("pillarboxes")) if (elem->has("pillarboxes"))
mDrawPillarboxes = elem->get<bool>("pillarboxes"); mDrawPillarboxes = elem->get<bool>("pillarboxes");
if (elem->has("pillarboxThreshold")) {
const glm::vec2 pillarboxThreshold {elem->get<glm::vec2>("pillarboxThreshold")};
mPillarboxThreshold.x = glm::clamp(pillarboxThreshold.x, 0.2f, 1.0f);
mPillarboxThreshold.y = glm::clamp(pillarboxThreshold.y, 0.2f, 1.0f);
}
if (elem->has("scanlines")) if (elem->has("scanlines"))
mRenderScanlines = elem->get<bool>("scanlines"); mRenderScanlines = elem->get<bool>("scanlines");

View file

@ -110,6 +110,7 @@ protected:
glm::vec2 mTargetSize; glm::vec2 mTargetSize;
glm::vec2 mVideoAreaPos; glm::vec2 mVideoAreaPos;
glm::vec2 mVideoAreaSize; glm::vec2 mVideoAreaSize;
glm::vec2 mPillarboxThreshold;
std::shared_ptr<TextureResource> mTexture; std::shared_ptr<TextureResource> mTexture;
std::string mStaticImagePath; std::string mStaticImagePath;
std::string mDefaultImagePath; std::string mDefaultImagePath;

View file

@ -103,7 +103,6 @@ void VideoFFmpegComponent::resize()
mSize.y *= resizeScale.y; mSize.y *= resizeScale.y;
} }
mSize.y = std::round(mSize.y);
mSize.x = (mSize.y / textureSize.y) * textureSize.x; mSize.x = (mSize.y / textureSize.y) * textureSize.x;
} }
else { else {
@ -113,11 +112,11 @@ void VideoFFmpegComponent::resize()
// If only one component is set, we resize in a way that maintains aspect ratio. // If only one component is set, we resize in a way that maintains aspect ratio.
if (!mTargetSize.x && mTargetSize.y) { if (!mTargetSize.x && mTargetSize.y) {
mSize.y = std::round(mTargetSize.y); mSize.y = mTargetSize.y;
mSize.x = (mSize.y / textureSize.y) * textureSize.x; mSize.x = (mSize.y / textureSize.y) * textureSize.x;
} }
else if (mTargetSize.x && !mTargetSize.y) { else if (mTargetSize.x && !mTargetSize.y) {
mSize.y = std::round((mTargetSize.x / textureSize.x) * textureSize.y); mSize.y = (mTargetSize.x / textureSize.x) * textureSize.y;
mSize.x = (mSize.y / textureSize.y) * textureSize.x; mSize.x = (mSize.y / textureSize.y) * textureSize.x;
} }
} }
@ -933,6 +932,11 @@ void VideoFFmpegComponent::calculateBlackRectangle()
// otherwise it will exactly match the video size. The reason to add a black rectangle // otherwise it will exactly match the video size. The reason to add a black rectangle
// behind videos in this second instance is that the scanline rendering will make the // behind videos in this second instance is that the scanline rendering will make the
// video partially transparent so this may avoid some unforseen issues with some themes. // video partially transparent so this may avoid some unforseen issues with some themes.
// In general, adding very narrow pillarboxes or letterboxes doesn't look good, so by
// default this is not done unless the size of the video vs the overall video area is
// above the threshold defined by mPillarboxThreshold. By default this is set to 0.85
// for the X axis and 0.90 for the Y axis, but this is theme-controllable via the
// pillarboxThreshold property.
if (mVideoAreaPos != glm::vec2 {0.0f, 0.0f} && mVideoAreaSize != glm::vec2 {0.0f, 0.0f}) { if (mVideoAreaPos != glm::vec2 {0.0f, 0.0f} && mVideoAreaSize != glm::vec2 {0.0f, 0.0f}) {
mVideoRectangleCoords.clear(); mVideoRectangleCoords.clear();
mRectangleOffset = {0.0f, 0.0f}; mRectangleOffset = {0.0f, 0.0f};
@ -949,20 +953,24 @@ void VideoFFmpegComponent::calculateBlackRectangle()
// and then scaled, there could be rounding errors that make the video height // and then scaled, there could be rounding errors that make the video height
// slightly higher than allowed. It's only a single pixel or a few pixels, but // slightly higher than allowed. It's only a single pixel or a few pixels, but
// it's still visible for some videos. // it's still visible for some videos.
if (mSize.y < mVideoAreaSize.y && mSize.y / mVideoAreaSize.y < 0.90f) if (mSize.y < mVideoAreaSize.y &&
mSize.y / mVideoAreaSize.y < mPillarboxThreshold.y)
rectHeight = mVideoAreaSize.y; rectHeight = mVideoAreaSize.y;
else else
rectHeight = mSize.y; rectHeight = mSize.y;
// Don't add a black border that is too narrow, that's what the 0.85 constant if (mSize.x < mVideoAreaSize.x &&
// takes care of. mSize.x / mVideoAreaSize.x < mPillarboxThreshold.x)
if (mSize.x < mVideoAreaSize.x && mSize.x / mVideoAreaSize.x < 0.85f)
rectWidth = mVideoAreaSize.x; rectWidth = mVideoAreaSize.x;
else else
rectWidth = mSize.x; rectWidth = mSize.x;
} }
// Video is in portrait orientation (or completely square). // Video is in portrait orientation (or completely square).
else { else {
if (mSize.x <= mVideoAreaSize.x &&
mSize.x / mVideoAreaSize.x < mPillarboxThreshold.x)
rectWidth = mVideoAreaSize.x; rectWidth = mVideoAreaSize.x;
else
rectWidth = mSize.x;
rectHeight = mSize.y; rectHeight = mSize.y;
} }
// If an origin value other than 0.5 is used, then create an offset for centering // If an origin value other than 0.5 is used, then create an offset for centering