Skip to content

Commit

Permalink
[subtitles] Align to screen image based subtitles with cropped source
Browse files Browse the repository at this point in the history
  • Loading branch information
CastagnaIT committed Mar 23, 2022
1 parent fca7647 commit 28d4b35
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 28 deletions.
30 changes: 25 additions & 5 deletions xbmc/cores/VideoPlayer/VideoRenderers/OverlayRenderer.cpp
Expand Up @@ -34,6 +34,8 @@
#include "OverlayRendererDX.h"
#endif

#include <algorithm>

using namespace OVERLAY;

COverlay::COverlay()
Expand Down Expand Up @@ -172,29 +174,47 @@ void CRenderer::Render(COverlay* o)
{
float scale_x = 1.0;
float scale_y = 1.0;
float scale_w = 1.0;
float scale_h = 1.0;

if (align == COverlay::ALIGN_SCREEN || align == COverlay::ALIGN_SUBTITLE)
{
scale_x = m_rv.Width();
scale_y = m_rv.Height();
scale_w = scale_x;
scale_h = scale_y;
}
else if (align == COverlay::ALIGN_SCREEN_AR)
{
// Align to screen by keeping aspect ratio to fit into the screen area
float source_width = o->m_source_width > 0 ? o->m_source_width : m_rs.Width();
float source_height = o->m_source_height > 0 ? o->m_source_height : m_rs.Height();
float ratio = std::min<float>(m_rv.Width() / source_width, m_rv.Height() / source_height);
scale_x = m_rv.Width();
scale_y = m_rv.Height();
scale_w = ratio;
scale_h = ratio;
}
else if (align == COverlay::ALIGN_VIDEO)
{
scale_x = m_rs.Width();
scale_y = m_rs.Height();
scale_w = scale_x;
scale_h = scale_y;
}

state.x *= scale_x;
state.y *= scale_y;
state.width *= scale_x;
state.height *= scale_y;
state.width *= scale_w;
state.height *= scale_h;

pos = COverlay::POSITION_ABSOLUTE;
}

if (pos == COverlay::POSITION_ABSOLUTE)
{
if (align == COverlay::ALIGN_SCREEN || align == COverlay::ALIGN_SUBTITLE)
if (align == COverlay::ALIGN_SCREEN || align == COverlay::ALIGN_SCREEN_AR ||
align == COverlay::ALIGN_SUBTITLE)
{
if (align == COverlay::ALIGN_SUBTITLE)
{
Expand Down Expand Up @@ -483,12 +503,12 @@ COverlay* CRenderer::Convert(CDVDOverlay* o, double pts)

#if defined(HAS_GL) || defined(HAS_GLES)
if (o->IsOverlayType(DVDOVERLAY_TYPE_IMAGE))
r = new COverlayTextureGL(static_cast<CDVDOverlayImage*>(o));
r = new COverlayTextureGL(static_cast<CDVDOverlayImage*>(o), m_rs);
else if (o->IsOverlayType(DVDOVERLAY_TYPE_SPU))
r = new COverlayTextureGL(static_cast<CDVDOverlaySpu*>(o));
#elif defined(HAS_DX)
if (o->IsOverlayType(DVDOVERLAY_TYPE_IMAGE))
r = new COverlayImageDX(static_cast<CDVDOverlayImage*>(o));
r = new COverlayImageDX(static_cast<CDVDOverlayImage*>(o), m_rs);
else if (o->IsOverlayType(DVDOVERLAY_TYPE_SPU))
r = new COverlayImageDX(static_cast<CDVDOverlaySpu*>(o));
#endif
Expand Down
3 changes: 3 additions & 0 deletions xbmc/cores/VideoPlayer/VideoRenderers/OverlayRenderer.h
Expand Up @@ -76,6 +76,7 @@ namespace OVERLAY {
enum EAlign
{
ALIGN_SCREEN,
ALIGN_SCREEN_AR,
ALIGN_VIDEO,
ALIGN_SUBTITLE
} m_align;
Expand All @@ -91,6 +92,8 @@ namespace OVERLAY {
float m_y;
float m_width;
float m_height;
float m_source_width{0}; // Video source width resolution used to calculate aspect ratio
float m_source_height{0}; // Video source height resolution used to calculate aspect ratio
};

class CRenderer : public Observer
Expand Down
38 changes: 28 additions & 10 deletions xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererDX.cpp
Expand Up @@ -197,7 +197,7 @@ COverlayImageDX::~COverlayImageDX()
{
}

COverlayImageDX::COverlayImageDX(CDVDOverlayImage* o)
COverlayImageDX::COverlayImageDX(CDVDOverlayImage* o, CRect& rSource)
{
if (o->palette.empty())
{
Expand All @@ -213,17 +213,35 @@ COverlayImageDX::COverlayImageDX(CDVDOverlayImage* o)
Load(rgba.data(), o->width, o->height, o->width * 4);
}

if (o->source_width && o->source_height)
if (o->source_width > 0 && o->source_height > 0)
{
float center_x = (0.5f * o->width + o->x) / o->source_width;
float center_y = (0.5f * o->height + o->y) / o->source_height;

m_align = ALIGN_VIDEO;
m_pos = POSITION_RELATIVE;
m_x = center_x;
m_y = center_y;
m_width = static_cast<float>(o->width) / o->source_width;
m_height = static_cast<float>(o->height) / o->source_height;

m_x = (0.5f * o->width + o->x) / o->source_width;
m_y = (0.5f * o->height + o->y) / o->source_height;

if (o->source_height == static_cast<int>(rSource.Height()) ||
(static_cast<int>(rSource.Height()) % o->source_height == 0))
{
// We check also for multiple of source_height because for
// example 1080P subtitles can be used on 4K videos
m_align = ALIGN_VIDEO;
m_width = static_cast<float>(o->width) / o->source_width;
m_height = static_cast<float>(o->height) / o->source_height;
}
else
{
// If the source_height is higher than the video source height (rSource)
// means that the video has been re-encoded/cropped (removed black bars).
// May happens that the value instead is lower with 4k videos.
// Then we cannot align to video otherwise the subtitles will be deformed
// better align to screen by keeping the aspect-ratio.
m_align = ALIGN_SCREEN_AR;
m_width = static_cast<float>(o->width);
m_height = static_cast<float>(o->height);
m_source_width = static_cast<float>(o->source_width);
m_source_height = static_cast<float>(o->source_height);
}
}
else
{
Expand Down
6 changes: 5 additions & 1 deletion xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererDX.h
Expand Up @@ -37,7 +37,11 @@ namespace OVERLAY {
: public COverlay
{
public:
explicit COverlayImageDX(CDVDOverlayImage* o);
/*! \brief Create the overlay for rendering
* \param o The overlay image
* \param rSource The video source rect size
*/
explicit COverlayImageDX(CDVDOverlayImage* o, CRect& rSource);
explicit COverlayImageDX(CDVDOverlaySpu* o);
virtual ~COverlayImageDX();

Expand Down
38 changes: 28 additions & 10 deletions xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererGL.cpp
Expand Up @@ -157,7 +157,7 @@ static void LoadTexture(GLenum target
*v = (GLfloat)height / height2;
}

COverlayTextureGL::COverlayTextureGL(CDVDOverlayImage* o)
COverlayTextureGL::COverlayTextureGL(CDVDOverlayImage* o, CRect& rSource)
{
m_texture = 0;

Expand Down Expand Up @@ -185,17 +185,35 @@ COverlayTextureGL::COverlayTextureGL(CDVDOverlayImage* o)

glBindTexture(GL_TEXTURE_2D, 0);

if (o->source_width && o->source_height)
if (o->source_width > 0 && o->source_height > 0)
{
float center_x = (0.5f * o->width + o->x) / o->source_width;
float center_y = (0.5f * o->height + o->y) / o->source_height;

m_align = ALIGN_VIDEO;
m_pos = POSITION_RELATIVE;
m_x = center_x;
m_y = center_y;
m_width = static_cast<float>(o->width) / o->source_width;
m_height = static_cast<float>(o->height) / o->source_height;

m_x = (0.5f * o->width + o->x) / o->source_width;
m_y = (0.5f * o->height + o->y) / o->source_height;

if (o->source_height == static_cast<int>(rSource.Height()) ||
(static_cast<int>(rSource.Height()) % o->source_height == 0))
{
// We check also for multiple of source_height because for
// example 1080P subtitles can be used on 4K videos
m_align = ALIGN_VIDEO;
m_width = static_cast<float>(o->width) / o->source_width;
m_height = static_cast<float>(o->height) / o->source_height;
}
else
{
// If the source_height is higher than the video source height (rSource)
// means that the video has been re-encoded/cropped (removed black bars).
// May happens that the value instead is lower with 4k videos.
// Then we cannot align to video otherwise the subtitles will be deformed
// better align to screen by keeping the aspect-ratio.
m_align = ALIGN_SCREEN_AR;
m_width = static_cast<float>(o->width);
m_height = static_cast<float>(o->height);
m_source_width = static_cast<float>(o->source_width);
m_source_height = static_cast<float>(o->source_height);
}
}
else
{
Expand Down
8 changes: 6 additions & 2 deletions xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererGL.h
Expand Up @@ -24,8 +24,12 @@ namespace OVERLAY {
class COverlayTextureGL : public COverlay
{
public:
explicit COverlayTextureGL(CDVDOverlayImage* o);
explicit COverlayTextureGL(CDVDOverlaySpu* o);
/*! \brief Create the overlay for rendering
* \param o The overlay image
* \param rSource The video source rect size
*/
explicit COverlayTextureGL(CDVDOverlayImage* o, CRect& rSource);
explicit COverlayTextureGL(CDVDOverlaySpu* o);
~COverlayTextureGL() override;

void Render(SRenderState& state) override;
Expand Down

0 comments on commit 28d4b35

Please sign in to comment.