Added a new cropSize property to the video element.

This commit is contained in:
Leon Styhre 2023-03-01 20:55:22 +01:00
parent b9a2a146b7
commit 95ef3b0555
5 changed files with 64 additions and 6 deletions

View file

@ -317,6 +317,7 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>>
{"video", {"video",
{{"pos", NORMALIZED_PAIR}, {{"pos", NORMALIZED_PAIR},
{"size", NORMALIZED_PAIR}, {"size", NORMALIZED_PAIR},
{"cropSize", NORMALIZED_PAIR},
{"maxSize", NORMALIZED_PAIR}, {"maxSize", NORMALIZED_PAIR},
{"origin", NORMALIZED_PAIR}, {"origin", NORMALIZED_PAIR},
{"path", PATH}, {"path", PATH},

View file

@ -28,6 +28,8 @@ 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}
, mTopLeftCrop {0.0f, 0.0f}
, mBottomRightCrop {1.0f, 1.0f}
, mPillarboxThreshold {0.85f, 0.90f} , mPillarboxThreshold {0.85f, 0.90f}
, mStartTime {0} , mStartTime {0}
, mIsPlaying {false} , mIsPlaying {false}
@ -36,6 +38,7 @@ VideoComponent::VideoComponent()
, mMediaViewerMode {false} , mMediaViewerMode {false}
, mScreensaverMode {false} , mScreensaverMode {false}
, mTargetIsMax {false} , mTargetIsMax {false}
, mTargetIsCrop {false}
, mPlayAudio {true} , mPlayAudio {true}
, mDrawPillarboxes {true} , mDrawPillarboxes {true}
, mRenderScanlines {false} , mRenderScanlines {false}
@ -154,6 +157,13 @@ void VideoComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
setMaxSize(videoMaxSize * scale); setMaxSize(videoMaxSize * scale);
mVideoAreaSize = videoMaxSize * scale; mVideoAreaSize = videoMaxSize * scale;
} }
else if (elem->has("cropSize")) {
glm::vec2 videoCropSize {elem->get<glm::vec2>("cropSize")};
videoCropSize.x = glm::clamp(videoCropSize.x, 0.01f, 2.0f);
videoCropSize.y = glm::clamp(videoCropSize.y, 0.01f, 2.0f);
setCroppedSize(videoCropSize * scale);
mVideoAreaSize = videoCropSize * scale;
}
} }
if (properties & ThemeFlags::POSITION) { if (properties & ThemeFlags::POSITION) {
@ -302,8 +312,17 @@ void VideoComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
mPillarboxThreshold.y = glm::clamp(pillarboxThreshold.y, 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"); if (elem->has("cropSize") && elem->get<bool>("scanlines")) {
LOG(LogWarning) << "VideoComponent: Invalid theme configuration, property "
"\"cropSize\" for element \""
<< element.substr(6)
<< "\" can't be combined with the \"scanlines\" property";
}
else {
mRenderScanlines = elem->get<bool>("scanlines");
}
}
if (elem->has("scrollFadeIn") && elem->get<bool>("scrollFadeIn")) if (elem->has("scrollFadeIn") && elem->get<bool>("scrollFadeIn"))
mComponentThemeFlags |= ComponentThemeFlags::SCROLL_FADE_IN; mComponentThemeFlags |= ComponentThemeFlags::SCROLL_FADE_IN;

View file

@ -83,6 +83,8 @@ public:
// Never breaks the aspect ratio. setMaxSize() and setResize() are mutually exclusive. // Never breaks the aspect ratio. setMaxSize() and setResize() are mutually exclusive.
virtual void setMaxSize(float width, float height) = 0; virtual void setMaxSize(float width, float height) = 0;
void setMaxSize(const glm::vec2& size) { setMaxSize(size.x, size.y); } void setMaxSize(const glm::vec2& size) { setMaxSize(size.x, size.y); }
// Resize and crop the video so it fills the entire area.
virtual void setCroppedSize(const glm::vec2& size) = 0;
// Basic video controls. // Basic video controls.
void startVideoPlayer(); void startVideoPlayer();
@ -109,6 +111,8 @@ protected:
glm::vec2 mTargetSize; glm::vec2 mTargetSize;
glm::vec2 mVideoAreaPos; glm::vec2 mVideoAreaPos;
glm::vec2 mVideoAreaSize; glm::vec2 mVideoAreaSize;
glm::vec2 mTopLeftCrop;
glm::vec2 mBottomRightCrop;
glm::vec2 mPillarboxThreshold; glm::vec2 mPillarboxThreshold;
std::shared_ptr<TextureResource> mTexture; std::shared_ptr<TextureResource> mTexture;
std::string mStaticImagePath; std::string mStaticImagePath;
@ -126,6 +130,7 @@ protected:
bool mMediaViewerMode; bool mMediaViewerMode;
bool mScreensaverMode; bool mScreensaverMode;
bool mTargetIsMax; bool mTargetIsMax;
bool mTargetIsCrop;
bool mPlayAudio; bool mPlayAudio;
bool mDrawPillarboxes; bool mDrawPillarboxes;
bool mRenderScanlines; bool mRenderScanlines;

View file

@ -66,6 +66,7 @@ void VideoFFmpegComponent::setResize(const float width, const float height)
// This resize function is used when stretching videos to full screen in the video screensaver. // This resize function is used when stretching videos to full screen in the video screensaver.
mTargetSize = glm::vec2 {width, height}; mTargetSize = glm::vec2 {width, height};
mTargetIsMax = false; mTargetIsMax = false;
mTargetIsCrop = false;
mStaticImage.setResize(mTargetSize); mStaticImage.setResize(mTargetSize);
resize(); resize();
} }
@ -76,10 +77,20 @@ void VideoFFmpegComponent::setMaxSize(float width, float height)
// and the gamelist videos. // and the gamelist videos.
mTargetSize = glm::vec2 {width, height}; mTargetSize = glm::vec2 {width, height};
mTargetIsMax = true; mTargetIsMax = true;
mTargetIsCrop = false;
mStaticImage.setMaxSize(width, height); mStaticImage.setMaxSize(width, height);
resize(); resize();
} }
void VideoFFmpegComponent::setCroppedSize(const glm::vec2& size)
{
mTargetSize = size;
mTargetIsMax = false;
mTargetIsCrop = true;
mStaticImage.setCroppedSize(size);
resize();
}
void VideoFFmpegComponent::resize() void VideoFFmpegComponent::resize()
{ {
if (!mTexture) if (!mTexture)
@ -106,6 +117,25 @@ void VideoFFmpegComponent::resize()
mSize.x = (mSize.y / textureSize.y) * textureSize.x; mSize.x = (mSize.y / textureSize.y) * textureSize.x;
} }
else if (mTargetIsCrop) {
// Size texture to allow for cropped video to fill the entire area.
const float cropFactor {
std::max(mTargetSize.x / textureSize.x, mTargetSize.y / textureSize.y)};
mSize = textureSize * cropFactor;
if (std::round(mSize.y) > std::round(mTargetSize.y)) {
const float cropSize {1.0f - (mTargetSize.y / mSize.y)};
mTopLeftCrop.y = cropSize / 2.0f;
mBottomRightCrop.y = 1.0f - (cropSize / 2.0f);
mSize.y = mSize.y - (mSize.y * cropSize);
}
else {
const float cropSize {1.0f - (mTargetSize.x / mSize.x)};
mTopLeftCrop.x = cropSize / 2.0f;
mBottomRightCrop.x = 1.0f - (cropSize / 2.0f);
mSize.x = mSize.x - (mSize.x * cropSize);
}
}
else { else {
// If both components are set, we just stretch. // If both components are set, we just stretch.
// If no components are set, we don't resize at all. // If no components are set, we don't resize at all.
@ -159,10 +189,10 @@ void VideoFFmpegComponent::render(const glm::mat4& parentTrans)
return; return;
// clang-format off // clang-format off
vertices[0] = {{0.0f + mRectangleOffset.x, 0.0f + mRectangleOffset.y }, {0.0f, 0.0f}, 0xFFFFFFFF}; vertices[0] = {{0.0f + mRectangleOffset.x, 0.0f + mRectangleOffset.y }, {mTopLeftCrop.x, 1.0f - mBottomRightCrop.y}, 0xFFFFFFFF};
vertices[1] = {{0.0f + mRectangleOffset.x, mSize.y + mRectangleOffset.y }, {0.0f, 1.0f}, 0xFFFFFFFF}; vertices[1] = {{0.0f + mRectangleOffset.x, mSize.y + mRectangleOffset.y }, {mTopLeftCrop.x, 1.0f - mTopLeftCrop.y }, 0xFFFFFFFF};
vertices[2] = {{mSize.x + mRectangleOffset.x, 0.0f + + mRectangleOffset.y }, {1.0f, 0.0f}, 0xFFFFFFFF}; vertices[2] = {{mSize.x + mRectangleOffset.x, 0.0f + + mRectangleOffset.y }, {mBottomRightCrop.x * 1.0f, 1.0f - mBottomRightCrop.y}, 0xFFFFFFFF};
vertices[3] = {{mSize.x + mRectangleOffset.x, mSize.y + + mRectangleOffset.y}, {1.0f, 1.0f}, 0xFFFFFFFF}; vertices[3] = {{mSize.x + mRectangleOffset.x, mSize.y + + mRectangleOffset.y}, {mBottomRightCrop.x * 1.0f, 1.0f - mTopLeftCrop.y }, 0xFFFFFFFF};
// clang-format on // clang-format on
vertices[0].color = mColorShift; vertices[0].color = mColorShift;

View file

@ -46,6 +46,9 @@ public:
// This can be set before or after a video is loaded. // This can be set before or after a video is loaded.
// Never breaks the aspect ratio. setMaxSize() and setResize() are mutually exclusive. // Never breaks the aspect ratio. setMaxSize() and setResize() are mutually exclusive.
void setMaxSize(float width, float height) override; void setMaxSize(float width, float height) override;
// Resize and crop the video so it fills the entire area.
void setCroppedSize(const glm::vec2& size) override;
// Basic video controls. // Basic video controls.
void stopVideoPlayer(bool muteAudio = true) override; void stopVideoPlayer(bool muteAudio = true) override;
void pauseVideoPlayer() override; void pauseVideoPlayer() override;