Skip to content

Commit

Permalink
Fix sundry display issues when using fullscreen and/or resolution
Browse files Browse the repository at this point in the history
switching

- update VideoOutWindow to only process changes when a parameter has
actually changed. This avoids unnecessary signals to the video classes
and attempts to stop spamming the logs with updates.
- focus on the window size in VideoOutWindow as we are always bound by
the window size - not the display size - and other areas of the code
need to ensure the window is resized and VideoOutWindow updated as
necessary
- 'display visible rect' is not pertinent to OpenGLVideo - the window
rect is king for the OpenGL view port (we previously used display
visible rect as a bad proxy as it was never updated).
- reimplement WindowResized in VideoOutputOpenGL to ensure we pick up
window resizing events.
- sundry removal of unused methods/members
- NB there are still various issues. OSD font sizing when the window has
been resized is erratic for some reason (both when switching to
fullscreen and using display resolution switching). When using display
resolution switching, switching to the guide grid etc is not working
quite right and needs more work.
  • Loading branch information
mark-kendall committed Oct 18, 2019
1 parent 40c450f commit dee4508
Show file tree
Hide file tree
Showing 12 changed files with 231 additions and 191 deletions.
3 changes: 1 addition & 2 deletions mythtv/libs/libmythtv/mythplayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,7 @@ void MythPlayer::WindowResized(const QSize &new_size)
{
if (videoOutput)
videoOutput->WindowResized(new_size);
ReinitOSD();
}

void MythPlayer::EnableTeletext(int page)
Expand Down Expand Up @@ -2581,10 +2582,8 @@ void MythPlayer::VideoStart(void)

osdLock.lock();
osd = new OSD(this, m_tv, videoOutput->GetOSDPainter());

videoOutput->GetOSDBounds(total, visible, aspect, scaling, 1.0F);
osd->Init(visible, aspect);
videoOutput->InitOSD(osd);
osd->EnableSubtitles(kDisplayNone);

#ifdef USING_MHEG
Expand Down
6 changes: 1 addition & 5 deletions mythtv/libs/libmythtv/openglvideo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ OpenGLVideo::OpenGLVideo(MythRenderOpenGL *Render, VideoColourSpace *ColourSpace
m_videoDispDim(VideoDispDim),
m_videoDim(VideoDim),
m_masterViewportSize(DisplayVisibleRect.size()),
m_displayVisibleRect(DisplayVisibleRect),
m_displayVideoRect(DisplayVideoRect),
m_videoRect(VideoRect),
m_deinterlacer(MythDeintType::DEINT_NONE),
Expand Down Expand Up @@ -778,10 +777,7 @@ void OpenGLVideo::PrepareFrame(VideoFrame *Frame, bool TopFieldFirst, FrameScanT

// bind default framebuffer
m_render->BindFramebuffer(nullptr);
if (m_viewportControl)
m_render->SetViewPort(QRect(QPoint(), m_displayVisibleRect.size()));
else
m_render->SetViewPort(QRect(QPoint(), m_masterViewportSize));
m_render->SetViewPort(QRect(QPoint(), m_masterViewportSize));

// PiP border
if (DrawBorder)
Expand Down
3 changes: 1 addition & 2 deletions mythtv/libs/libmythtv/openglvideo.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ class OpenGLVideo : public QObject
MythRenderOpenGL *m_render;
QSize m_videoDispDim; ///< Useful video frame size e.g. 1920x1080
QSize m_videoDim; ///< Total video frame size e.g. 1920x1088
QSize m_masterViewportSize; ///< Current viewport into which OpenGL is rendered
QRect m_displayVisibleRect; ///< Total useful, visible rectangle
QSize m_masterViewportSize; ///< Current viewport into which OpenGL is rendered, usually the window size
QRect m_displayVideoRect; ///< Sub-rect of display_visible_rect for video
QRect m_videoRect; ///< Sub-rect of video_disp_dim to display (after zoom adjustments etc)
MythDeintType m_deinterlacer;
Expand Down
1 change: 0 additions & 1 deletion mythtv/libs/libmythtv/videoout_d3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ class VideoOutputD3D : public VideoOutput
MythCodecID av_codec_id,
bool &aspect_only,
MythMultiLocker *Locks) override; // VideoOutput
void MoveResizeWindow(QRect new_rect) override {;} // VideoOutput
void UpdatePauseFrame(int64_t &disp_timecode) override; // VideoOutput
void EmbedInWidget(const QRect &rect) override; // VideoOutput
void StopEmbedding(void) override; // VideoOutput
Expand Down
1 change: 0 additions & 1 deletion mythtv/libs/libmythtv/videoout_null.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ class VideoOutputNull : public VideoOutput
FrameScanType scan) override; // VideoOutput
static QStringList GetAllowedRenderers(MythCodecID myth_codec_id,
const QSize &video_dim);
void MoveResizeWindow(QRect ) override {;} // VideoOutput
bool SetupVisualisation(AudioPlayer *, MythRender *,
const QString &) override // VideoOutput
{ return false; }
Expand Down
50 changes: 26 additions & 24 deletions mythtv/libs/libmythtv/videoout_opengl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ VideoOutputOpenGL::VideoOutputOpenGL(const QString &Profile)
// Connect VideoOutWindow to OpenGLVideo
QObject::connect(&m_window, &VideoOutWindow::VideoSizeChanged, m_openGLVideo, &OpenGLVideo::SetVideoDimensions);
QObject::connect(&m_window, &VideoOutWindow::VideoRectsChanged, m_openGLVideo, &OpenGLVideo::SetVideoRects);
QObject::connect(&m_window, &VideoOutWindow::VisibleRectChanged, m_openGLVideo, &OpenGLVideo::SetViewportRect);
QObject::connect(&m_window, &VideoOutWindow::WindowRectChanged, m_openGLVideo, &OpenGLVideo::SetViewportRect);
}

VideoOutputOpenGL::~VideoOutputOpenGL()
Expand Down Expand Up @@ -226,7 +226,7 @@ bool VideoOutputOpenGL::Init(const QSize &VideoDim, const QSize &VideoDispDim, f

// Setup display
QSize size = m_window.GetVideoDim();
InitDisplayMeasurements(size.width(), size.height(), false);
InitDisplayMeasurements(size.width(), size.height());

// Create buffers
if (!CreateBuffers(CodecId, m_window.GetVideoDim()))
Expand All @@ -237,7 +237,6 @@ bool VideoOutputOpenGL::Init(const QSize &VideoDim, const QSize &VideoDispDim, f
if (m_videoCodecID == kCodec_NONE)
{
m_render->SetViewPort(QRect(QPoint(), dvr.size()));
MoveResize();
return true;
}

Expand All @@ -251,8 +250,6 @@ bool VideoOutputOpenGL::Init(const QSize &VideoDim, const QSize &VideoDispDim, f
if (m_openGLVideo->IsValid())
m_openGLVideo->ResetFrameFormat();

// Finalise output
MoveResize();
return true;
}

Expand Down Expand Up @@ -408,6 +405,22 @@ void VideoOutputOpenGL::ProcessFrame(VideoFrame *Frame, OSD */*osd*/,
StopEmbedding();
}

// Note - we don't call the default VideoOutput::InputChanged method as
// the OpenGL implementation is asynchronous.
// So we need to update the video display profile here. It is a little
// circular as we need to set the video dimensions first which are then
// reset in Init.
// All told needs a cleanup - not least because the use of codecName appears
// to be inconsistent.
m_window.InputChanged(m_newVideoDim, m_newVideoDispDim, m_newAspect);
AVCodecID avCodecId = myth2av_codecid(m_newCodecId);
AVCodec *codec = avcodec_find_decoder(avCodecId);
QString codecName;
if (codec)
codecName = codec->name;
if (m_dbDisplayProfile)
m_dbDisplayProfile->SetInput(m_window.GetVideoDispDim(), 0 , codecName);

bool ok = Init(m_newVideoDim, m_newVideoDispDim, m_newAspect,
0, m_window.GetDisplayVisibleRect(), m_newCodecId);
m_newCodecId = kCodec_NONE;
Expand Down Expand Up @@ -515,7 +528,7 @@ void VideoOutputOpenGL::PrepareFrame(VideoFrame *Frame, FrameScanType Scan, OSD
else if (m_window.IsEmbedding())
{
// use MythRenderOpenGL rendering as it will clear to the appropriate 'black level'
m_render->ClearRect(nullptr, m_window.GetDisplayVisibleRect(), gray);
m_render->ClearRect(nullptr, m_window.GetWindowRect(), gray);
}
else
{
Expand Down Expand Up @@ -714,6 +727,13 @@ VideoFrameType* VideoOutputOpenGL::DirectRenderFormats(void)
return m_isGLES2 ? &opengles2formats[0] : &openglformats[0];
}

void VideoOutputOpenGL::WindowResized(const QSize &Size)
{
m_window.SetWindowSize(Size);
QSize size = m_window.GetVideoDim();
InitDisplayMeasurements(size.width(), size.height());
}

void VideoOutputOpenGL::Show(FrameScanType /*scan*/)
{
if (m_render && !IsErrored())
Expand Down Expand Up @@ -874,24 +894,6 @@ void VideoOutputOpenGL::RemovePIP(MythPlayer *PiPPlayer)
}
}

void VideoOutputOpenGL::MoveResizeWindow(QRect NewRect)
{
if (m_render)
m_render->MoveResizeWindow(NewRect);
}

void VideoOutputOpenGL::EmbedInWidget(const QRect &Rect)
{
VideoOutput::EmbedInWidget(Rect);
MoveResize();
}

void VideoOutputOpenGL::StopEmbedding(void)
{
VideoOutput::StopEmbedding();
MoveResize();
}

QStringList VideoOutputOpenGL::GetVisualiserList(void)
{
if (m_render)
Expand Down
4 changes: 1 addition & 3 deletions mythtv/libs/libmythtv/videoout_opengl.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,7 @@ class VideoOutputOpenGL : public VideoOutput
MythMultiLocker* Locks, int ReferenceFrames) override;
void UpdatePauseFrame(int64_t &DisplayTimecode) override;
void InitPictureAttributes(void) override;
void EmbedInWidget(const QRect &Rect) override;
void StopEmbedding(void) override;
void ShowPIP(VideoFrame *Frame, MythPlayer *PiPPlayer, PIPLocation Location) override;
void MoveResizeWindow(QRect NewRect) override;
void RemovePIP(MythPlayer *PiPPlayer) override;
bool IsPIPSupported(void) const override { return true; }
MythPainter *GetOSDPainter(void) override;
Expand All @@ -46,6 +43,7 @@ class VideoOutputOpenGL : public VideoOutput
void DoneDisplayingFrame(VideoFrame *Frame) override;
void DiscardFrames(bool KeyFrame, bool Flushed) override;
VideoFrameType* DirectRenderFormats(void) override;
void WindowResized(const QSize &Size) override;

protected:
void DestroyBuffers(void);
Expand Down
76 changes: 23 additions & 53 deletions mythtv/libs/libmythtv/videooutbase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -973,9 +973,10 @@ void VideoOutput::ResizeForVideo(int Width, int Height)
{
// Switching to custom display resolution succeeded
// Make a note of the new size
m_window.SetDisplayDim(QSize(m_displayRes->GetPhysicalWidth(),
m_displayRes->GetPhysicalHeight()));
m_window.SetDisplayAspect(static_cast<float>(m_displayRes->GetAspectRatio()));
m_window.SetDisplayProperties(QSize(m_displayRes->GetPhysicalWidth(),
m_displayRes->GetPhysicalHeight()),
static_cast<float>(m_displayRes->GetAspectRatio()));
m_window.SetWindowSize(QSize(m_displayRes->GetWidth(), m_displayRes->GetHeight()));

bool fullscreen = !m_window.UsingGuiSize();

Expand All @@ -990,12 +991,9 @@ void VideoOutput::ResizeForVideo(int Width, int Height)
if (fullscreen)
{
QSize sz(m_displayRes->GetWidth(), m_displayRes->GetHeight());
const QRect display_visible_rect =
QRect(GetMythMainWindow()->geometry().topLeft(), sz);
m_window.SetDisplayVisibleRect(display_visible_rect);
MoveResize();
// Resize X window to fill new resolution
MoveResizeWindow(display_visible_rect);
QRect display_visible_rect = QRect(GetMythMainWindow()->geometry().topLeft(), sz);
if (HasMythMainWindow())
GetMythMainWindow()->MoveResize(display_visible_rect);
}
}
}
Expand All @@ -1004,53 +1002,31 @@ void VideoOutput::ResizeForVideo(int Width, int Height)
* \brief Init display measurements based on database settings and
* actual screen parameters.
*/
void VideoOutput::InitDisplayMeasurements(int Width, int Height, bool Resize)
void VideoOutput::InitDisplayMeasurements(int Width, int Height)
{
DisplayInfo disp = MythDisplay::GetDisplayInfo();
QString source = "Actual";

// The very first Resize needs to be the maximum possible
// desired res, because X will mask off anything outside
// the initial dimensions
QSize sz1 = disp.m_res;
QSize sz2 = m_window.GetScreenGeometry().size();
QSize max_size = sz1.expandedTo(sz2);

if (m_window.UsingGuiSize())
max_size = GetMythMainWindow()->geometry().size();

if (m_displayRes)
{
max_size.setWidth(m_displayRes->GetMaxWidth());
max_size.setHeight(m_displayRes->GetMaxHeight());
}

if (Resize)
{
MoveResizeWindow(QRect(GetMythMainWindow()->geometry().x(),
GetMythMainWindow()->geometry().y(),
max_size.width(), max_size.height()));
}

// get the physical dimensions (in mm) of the display. If using
// DisplayRes, this will be overridden when we call ResizeForVideo
if (m_dbDisplayDimensionsMM.isEmpty())
{
m_window.SetDisplayDim(disp.m_size);
}
float disp_aspect = m_window.GetDisplayAspect();
QSize disp_dim = m_dbDisplayDimensionsMM;
if (disp_dim.isEmpty())
disp_dim = disp.m_size;
else
{
m_window.SetDisplayDim(m_dbDisplayDimensionsMM);
source = "Database";
}
m_window.SetDisplayProperties(disp_dim, disp_aspect);

// Set the display mode if required
if (m_displayRes)
{
ResizeForVideo(Width, Height);
disp = MythDisplay::GetDisplayInfo();
}

// Determine window and screen dimensions in pixels
QSize screen_size = disp.m_res;
QSize window_size = m_window.GetDisplayVisibleRect().size();
QSize window_size = m_window.GetWindowRect().size();

if (screen_size.isEmpty())
screen_size = window_size.isEmpty() ? QSize(1920, 1080): window_size;
Expand All @@ -1065,8 +1041,8 @@ void VideoOutput::InitDisplayMeasurements(int Width, int Height, bool Resize)
.arg(window_size.width()).arg(window_size.height()));

// Check the display dimensions
QSize disp_dim = m_window.GetDisplayDim();
float disp_aspect;
disp_aspect = m_window.GetDisplayAspect();
disp_dim = m_window.GetDisplayDim();

// If we are using Xinerama the display dimensions cannot be trusted.
// We need to use the Xinerama monitor aspect ratio from the DB to set
Expand All @@ -1086,8 +1062,8 @@ void VideoOutput::InitDisplayMeasurements(int Width, int Height, bool Resize)
if (disp_dim.isEmpty())
{
source = "Guessed!";
LOG(VB_GENERAL, LOG_WARNING, LOC + "Physical size of display unknown."
"\n\t\t\tAssuming 17\" monitor with square pixels.");
LOG(VB_GENERAL, LOG_WARNING, LOC +
"Physical size of display unknown. Assuming 17\" monitor with square pixels.");
disp_dim = QSize(static_cast<int>(lroundf(300 * pixel_aspect)), 300);
}

Expand All @@ -1108,18 +1084,12 @@ void VideoOutput::InitDisplayMeasurements(int Width, int Height, bool Resize)
(disp_dim.height() * window_size.height()) /
screen_size.height());
disp_aspect = static_cast<float>(disp_dim.width()) / disp_dim.height();
m_window.SetDisplayDim(disp_dim);
m_window.SetDisplayAspect(disp_aspect);

// If we are using XRandR, use the aspect ratio from it
if (m_displayRes)
m_window.SetDisplayAspect(static_cast<float>(m_displayRes->GetAspectRatio()));
disp_aspect = static_cast<float>(m_displayRes->GetAspectRatio());

LOG(VB_PLAYBACK, LOG_INFO, LOC +
QString("Estimated window dimensions: %1x%2 mm Aspect: %3")
.arg(m_window.GetDisplayDim().width())
.arg(m_window.GetDisplayDim().height())
.arg(static_cast<double>(m_window.GetDisplayAspect())));
m_window.SetDisplayProperties(disp_dim, disp_aspect);
}

///\note Probably no longer required
Expand Down
4 changes: 1 addition & 3 deletions mythtv/libs/libmythtv/videooutbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ class VideoOutput
virtual bool Init(const QSize &VideoDim, const QSize &VideoDispDim,
float VideoAspect, WId WinID,
const QRect &WindowRect, MythCodecID CodecID);
virtual void InitOSD(OSD *) { }
virtual void SetVideoFrameRate(float);
virtual void SetDeinterlacing(bool Enable, bool DoubleRate);
virtual void ProcessFrame(VideoFrame *Frame, OSD *Osd, const PIPMap &PipPlayers,
Expand Down Expand Up @@ -153,8 +152,7 @@ class VideoOutput

protected:
virtual void MoveResize(void);
virtual void MoveResizeWindow(QRect NewRect) = 0;
void InitDisplayMeasurements(int Width, int Height, bool Resize);
void InitDisplayMeasurements(int Width, int Height);
virtual void ShowPIPs(VideoFrame *Frame, const PIPMap &PiPPlayers);
virtual void ShowPIP(VideoFrame*, MythPlayer*, PIPLocation) { }

Expand Down
13 changes: 13 additions & 0 deletions mythtv/libs/libmythtv/videoouttypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,19 @@ inline QString toString(FrameScanType scan, bool brief = false)
return ret;
}

inline QString toString(PIPState State)
{
switch (State)
{
case kPIPOff: return QString("Pip Off");
case kPIPonTV: return QString("Pip on TV");
case kPIPStandAlone: return QString("Pip Standalone");
case kPBPLeft: return QString("PBP Left");
case kPBPRight: return QString("PBP Right");
}
return QString("Unknown");
}

inline QString toString(PIPLocation location)
{
QString ret;
Expand Down
Loading

0 comments on commit dee4508

Please sign in to comment.