Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VideoPlayer: fix video rotation #14298

Merged
merged 2 commits into from Aug 15, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
154 changes: 40 additions & 114 deletions xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.cpp
Expand Up @@ -25,16 +25,7 @@

CBaseRenderer::CBaseRenderer()
{
m_sourceFrameRatio = 1.0f;
m_sourceWidth = 720;
m_sourceHeight = 480;
m_fps = 0.0f;
m_renderOrientation = 0;
m_oldRenderOrientation = 0;
m_oldDestRect.SetRect(0.0f, 0.0f, 0.0f, 0.0f);
m_iFlags = 0;

for(int i=0; i < 4; i++)
for (int i=0; i < 4; i++)
{
m_rotatedDestCoords[i].x = 0;
m_rotatedDestCoords[i].y = 0;
Expand Down Expand Up @@ -66,106 +57,22 @@ inline void CBaseRenderer::ReorderDrawPoints()
{m_destRect.x2, m_destRect.y1},
{m_destRect.x2, m_destRect.y2},
{m_destRect.x1, m_destRect.y2}};
bool changeAspect = false;
int pointOffset = 0;

switch (m_renderOrientation)
{
case 90:
pointOffset = 1;
changeAspect = true;
break;
case 180:
pointOffset = 2;
break;
case 270:
pointOffset = 3;
changeAspect = true;
break;
}
int pointOffset = m_renderOrientation / 90;

// if renderer doesn't support rotation
// treat orientation as 0 degree so that
// ffmpeg might handle it.
if (!Supports(RENDERFEATURE_ROTATION))
{
pointOffset = 0;
changeAspect = false;
}


float diffX = 0.0f;
float diffY = 0.0f;
float centerX = 0.0f;
float centerY = 0.0f;

if (changeAspect)// we are either rotating by 90 or 270 degrees which inverts aspect ratio
{
float newWidth = m_destRect.Height(); // new width is old height
float newHeight = m_destRect.Width(); // new height is old width
float diffWidth = newWidth - m_destRect.Width(); // difference between old and new width
float diffHeight = newHeight - m_destRect.Height(); // difference between old and new height

// if the new width is bigger then the old or
// the new height is bigger then the old - we need to scale down
if (diffWidth > 0.0f || diffHeight > 0.0f)
{
float aspectRatio = GetAspectRatio();
// scale to fit screen width because
// the difference in width is bigger then the
// difference in height
if (diffWidth > diffHeight)
{
newWidth = m_destRect.Width(); // clamp to the width of the old dest rect
newHeight *= aspectRatio;
}
else // scale to fit screen height
{
newHeight = m_destRect.Height(); // clamp to the height of the old dest rect
newWidth /= aspectRatio;
}
}

// calculate the center point of the view
centerX = m_viewRect.x1 + m_viewRect.Width() / 2.0f;
centerY = m_viewRect.y1 + m_viewRect.Height() / 2.0f;

// calculate the number of pixels we need to go in each
// x direction from the center point
diffX = newWidth / 2;
// calculate the number of pixels we need to go in each
// y direction from the center point
diffY = newHeight / 2;

}

for (int destIdx=0, srcIdx=pointOffset; destIdx < 4; destIdx++)
{
m_rotatedDestCoords[destIdx].x = origMat[srcIdx][0];
m_rotatedDestCoords[destIdx].y = origMat[srcIdx][1];

if (changeAspect)
{
switch (srcIdx)
{
case 0:// top left
m_rotatedDestCoords[destIdx].x = centerX - diffX;
m_rotatedDestCoords[destIdx].y = centerY - diffY;
break;
case 1:// top right
m_rotatedDestCoords[destIdx].x = centerX + diffX;
m_rotatedDestCoords[destIdx].y = centerY - diffY;
break;
case 2:// bottom right
m_rotatedDestCoords[destIdx].x = centerX + diffX;
m_rotatedDestCoords[destIdx].y = centerY + diffY;
break;
case 3:// bottom left
m_rotatedDestCoords[destIdx].x = centerX - diffX;
m_rotatedDestCoords[destIdx].y = centerY + diffY;
break;
}
}
srcIdx++;
srcIdx = srcIdx % 4;
}
Expand Down Expand Up @@ -199,7 +106,7 @@ void CBaseRenderer::CalcNormalRenderRect(float offsetX, float offsetY, float wid
float inputFrameRatio, float zoomAmount, float verticalShift)
{
// if view window is empty, set empty destination
if(height == 0 || width == 0)
if (height == 0 || width == 0)
{
m_destRect.SetRect(0.0f, 0.0f, 0.0f, 0.0f);
return;
Expand All @@ -214,20 +121,43 @@ void CBaseRenderer::CalcNormalRenderRect(float offsetX, float offsetY, float wid

// allow a certain error to maximize size of render area
float fCorrection = width / height / outputFrameRatio - 1.0f;
float fAllowed = CServiceBroker::GetSettings().GetInt(CSettings::SETTING_VIDEOPLAYER_ERRORINASPECT) * 0.01f;
if(fCorrection > fAllowed) fCorrection = fAllowed;
if(fCorrection < - fAllowed) fCorrection = - fAllowed;
float fAllowed = CServiceBroker::GetSettings().GetInt(CSettings::SETTING_VIDEOPLAYER_ERRORINASPECT) * 0.01f;
if (fCorrection > fAllowed)
fCorrection = fAllowed;
if (fCorrection < -fAllowed)
fCorrection = - fAllowed;

outputFrameRatio *= 1.0f + fCorrection;

// maximize the movie width
float newWidth = width;
float newHeight = newWidth / outputFrameRatio;
bool isRotated = false;
if (m_renderOrientation == 90 ||
m_renderOrientation == 270)
isRotated = true;

if (newHeight > height)
float newWidth;
float newHeight;

if (!isRotated)
{
newHeight = height;
newWidth = newHeight * outputFrameRatio;
// maximize the movie width
newWidth = width;
newHeight = newWidth / outputFrameRatio;
if (newHeight > height)
{
newHeight = height;
newWidth = newHeight * outputFrameRatio;
}
}
else
{
// maximize the movie hight
newHeight = std::min(width, height);
newWidth = newHeight / outputFrameRatio;
if (newWidth > width)
{
newWidth = std::min(width, height);
newHeight = newWidth * outputFrameRatio;
}
}

// Scale the movie up by set zoom amount
Expand Down Expand Up @@ -279,14 +209,7 @@ void CBaseRenderer::CalcNormalRenderRect(float offsetX, float offsetY, float wid
}
}

if (m_oldDestRect != m_destRect || m_oldRenderOrientation != m_renderOrientation)
{
// adapt the drawing rect points if we have to rotate
// and either destrect or orientation changed
ReorderDrawPoints();
m_oldDestRect = m_destRect;
m_oldRenderOrientation = m_renderOrientation;
}
ReorderDrawPoints();
}

//***************************************************************************************
Expand Down Expand Up @@ -394,7 +317,10 @@ void CBaseRenderer::ManageRenderArea()
break;
}

CalcNormalRenderRect(m_viewRect.x1, m_viewRect.y1, m_viewRect.Width(), m_viewRect.Height(), GetAspectRatio() * CDisplaySettings::GetInstance().GetPixelRatio(), CDisplaySettings::GetInstance().GetZoomAmount(), CDisplaySettings::GetInstance().GetVerticalShift());
CalcNormalRenderRect(m_viewRect.x1, m_viewRect.y1, m_viewRect.Width(), m_viewRect.Height(),
GetAspectRatio() * CDisplaySettings::GetInstance().GetPixelRatio(),
CDisplaySettings::GetInstance().GetZoomAmount(),
CDisplaySettings::GetInstance().GetVerticalShift());
}

EShaderFormat CBaseRenderer::GetShaderFormat()
Expand Down
20 changes: 10 additions & 10 deletions xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.h
Expand Up @@ -94,33 +94,33 @@ class CBaseRenderer
float inputFrameRatio, float zoomAmount, float verticalShift);
void CalculateFrameAspectRatio(unsigned int desired_width, unsigned int desired_height);
virtual void ManageRenderArea();
virtual void ReorderDrawPoints();//might be overwritten (by egl e.x.)
virtual void ReorderDrawPoints();
virtual EShaderFormat GetShaderFormat();
void MarkDirty();

//@todo drop those
void saveRotatedCoords();//saves the current state of m_rotatedDestCoords
void syncDestRectToRotatedPoints();//sync any changes of m_destRect to m_rotatedDestCoords
void restoreRotatedCoords();//restore the current state of m_rotatedDestCoords from saveRotatedCoords
void MarkDirty();

unsigned int m_sourceWidth;
unsigned int m_sourceHeight;
float m_sourceFrameRatio;
float m_fps;
unsigned int m_sourceWidth = 720;
unsigned int m_sourceHeight = 480;
float m_sourceFrameRatio = 1.0f;
float m_fps = 0.0f;

unsigned int m_renderOrientation; // orientation of the video in degrees counter clockwise
unsigned int m_oldRenderOrientation; // orientation of the previous frame
unsigned int m_renderOrientation = 0; // orientation of the video in degrees counter clockwise
// for drawing the texture with glVertex4f (holds all 4 corner points of the destination rect
// with correct orientation based on m_renderOrientation
// 0 - top left, 1 - top right, 2 - bottom right, 3 - bottom left
CPoint m_rotatedDestCoords[4];
CPoint m_savedRotatedDestCoords[4];//saved points from saveRotatedCoords call

CRect m_destRect;
CRect m_oldDestRect; // destrect of the previous frame
CRect m_sourceRect;
CRect m_viewRect;

// rendering flags
unsigned m_iFlags;
unsigned m_iFlags = 0;
AVPixelFormat m_format = AV_PIX_FMT_NONE;

CVideoSettings m_videoSettings;
Expand Down
42 changes: 21 additions & 21 deletions xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp
Expand Up @@ -557,7 +557,7 @@ void CLinuxRendererGL::DrawBlackBars()
glUniform4f(uniCol, m_clearColour / 255.0f, m_clearColour / 255.0f, m_clearColour / 255.0f, 1.0f);

//top quad
if (m_rotatedDestCoords[0].y > 0.0)
if (m_destRect.y1 > 0.0)
{
GLubyte quad = count;
vertices[quad].x = 0.0;
Expand All @@ -567,25 +567,25 @@ void CLinuxRendererGL::DrawBlackBars()
vertices[quad+1].y = 0;
vertices[quad+1].z = 0;
vertices[quad+2].x = m_viewRect.Width();
vertices[quad+2].y = m_rotatedDestCoords[0].y;
vertices[quad+2].y = m_destRect.y1;
vertices[quad+2].z = 0;
vertices[quad+3] = vertices[quad+2];
vertices[quad+4].x = 0;
vertices[quad+4].y = m_rotatedDestCoords[0].y;
vertices[quad+4].y = m_destRect.y1;
vertices[quad+4].z = 0;
vertices[quad+5] = vertices[quad];
count += 6;
}

// bottom quad
if (m_rotatedDestCoords[2].y < m_viewRect.Height())
if (m_destRect.y2 < m_viewRect.Height())
{
GLubyte quad = count;
vertices[quad].x = 0.0;
vertices[quad].y = m_rotatedDestCoords[2].y;
vertices[quad].y = m_destRect.y2;
vertices[quad].z = 0;
vertices[quad+1].x = m_viewRect.Width();
vertices[quad+1].y = m_rotatedDestCoords[2].y;
vertices[quad+1].y = m_destRect.y2;
vertices[quad+1].z = 0;
vertices[quad+2].x = m_viewRect.Width();
vertices[quad+2].y = m_viewRect.Height();
Expand All @@ -599,42 +599,42 @@ void CLinuxRendererGL::DrawBlackBars()
}

// left quad
if (m_rotatedDestCoords[0].x > 0.0)
if (m_destRect.x1 > 0.0)
{
GLubyte quad = count;
vertices[quad].x = 0.0;
vertices[quad].y = m_rotatedDestCoords[0].y;
vertices[quad].y = m_destRect.y1;
vertices[quad].z = 0;
vertices[quad+1].x = m_rotatedDestCoords[0].x;
vertices[quad+1].y = m_rotatedDestCoords[0].y;
vertices[quad+1].x = m_destRect.x1;
vertices[quad+1].y = m_destRect.y1;
vertices[quad+1].z = 0;
vertices[quad+2].x = m_rotatedDestCoords[3].x;
vertices[quad+2].y = m_rotatedDestCoords[3].y;
vertices[quad+2].x = m_destRect.x1;
vertices[quad+2].y = m_destRect.y2;
vertices[quad+2].z = 0;
vertices[quad+3] = vertices[quad+2];
vertices[quad+4].x = 0;
vertices[quad+4].y = m_rotatedDestCoords[3].y;
vertices[quad+4].y = m_destRect.y2;
vertices[quad+4].z = 0;
vertices[quad+5] = vertices[quad];
count += 6;
}

//right quad
if (m_rotatedDestCoords[2].x < m_viewRect.Width())
// right quad
if (m_destRect.x2 < m_viewRect.Width())
{
GLubyte quad = count;
vertices[quad].x = m_rotatedDestCoords[1].x;
vertices[quad].y = m_rotatedDestCoords[1].y;
vertices[quad].x = m_destRect.x2;
vertices[quad].y = m_destRect.y1;
vertices[quad].z = 0;
vertices[quad+1].x = m_viewRect.Width();
vertices[quad+1].y = m_rotatedDestCoords[1].y;
vertices[quad+1].y = m_destRect.y1;
vertices[quad+1].z = 0;
vertices[quad+2].x = m_viewRect.Width();
vertices[quad+2].y = m_rotatedDestCoords[2].y;
vertices[quad+2].y = m_destRect.y2;
vertices[quad+2].z = 0;
vertices[quad+3] = vertices[quad+2];
vertices[quad+4].x = m_rotatedDestCoords[1].x;
vertices[quad+4].y = m_rotatedDestCoords[2].y;
vertices[quad+4].x = m_destRect.x2;
vertices[quad+4].y = m_destRect.y2;
vertices[quad+4].z = 0;
vertices[quad+5] = vertices[quad];
count += 6;
Expand Down