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

VTB on OSX: fix flickering video caused by buffer overwrite #10615

Merged
merged 2 commits into from Oct 4, 2016
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
2 changes: 1 addition & 1 deletion xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.h
Expand Up @@ -90,7 +90,7 @@ class CBaseRenderer
virtual void Flush() {};
virtual void SetBufferSize(int numBuffers) { }
virtual void ReleaseBuffer(int idx) { }
virtual bool NeedBufferForRef(int idx) { return false; }
virtual bool NeedBuffer(int idx) { return false; }
virtual bool IsGuiLayer() { return true; }
// Render info, can be called before configure
virtual CRenderInfo GetRenderInfo() { return CRenderInfo(); }
Expand Down
92 changes: 74 additions & 18 deletions xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVTBGL.cpp
Expand Up @@ -31,22 +31,43 @@
#include <OpenGL/CGLIOSurface.h>
#include "windowing/WindowingFactory.h"

CRendererVTB::CRendererVTB()
struct CVTBData
{
struct __CVBuffer* m_vtbbuf;
GLuint m_fence;
};

CRendererVTB::CRendererVTB()
{
}

CRendererVTB::~CRendererVTB()
{
for (int i = 0; i < NUM_BUFFERS; ++i)
{
DeleteTexture(i);
}
}

CRenderInfo CRendererVTB::GetRenderInfo()
{
CRenderInfo info;
info.formats = m_formats;
info.max_buffer_size = NUM_BUFFERS;
info.optimal_buffer_size = 5;
return info;
}

void CRendererVTB::AddVideoPictureHW(DVDVideoPicture &picture, int index)
{
YUVBUFFER &buf = m_buffers[index];
if (buf.hwDec)
CVBufferRelease((struct __CVBuffer *)buf.hwDec);
buf.hwDec = picture.cvBufferRef;
CVTBData *vtbdata = (CVTBData*)buf.hwDec;
if (vtbdata->m_vtbbuf)
{
CVBufferRelease(vtbdata->m_vtbbuf);
}
vtbdata->m_vtbbuf = picture.cvBufferRef;

// retain another reference, this way VideoPlayer and renderer can issue releases.
CVBufferRetain(picture.cvBufferRef);
}
Expand All @@ -55,20 +76,25 @@ void CRendererVTB::ReleaseBuffer(int idx)
{
YUVBUFFER &buf = m_buffers[idx];
if (buf.hwDec)
CVBufferRelease((struct __CVBuffer *)buf.hwDec);
buf.hwDec = NULL;
}


bool CRendererVTB::Supports(EINTERLACEMETHOD method)
{
return false;
{
CVTBData *vtbdata = (CVTBData*)buf.hwDec;
if (vtbdata->m_vtbbuf)
{
CVBufferRelease(vtbdata->m_vtbbuf);
vtbdata->m_vtbbuf = nullptr;
}

if (vtbdata->m_fence && glIsFenceAPPLE(vtbdata->m_fence))
{
glDeleteFencesAPPLE(1, &vtbdata->m_fence);
vtbdata->m_fence = 0;
}
}
}

bool CRendererVTB::LoadShadersHook()
{
CLog::Log(LOGNOTICE, "GL: Using CVBREF render method");
m_renderMethod = RENDER_CVREF;
m_textureTarget = GL_TEXTURE_RECTANGLE_ARB;
return false;
}
Expand Down Expand Up @@ -110,16 +136,21 @@ bool CRendererVTB::CreateTexture(int index)
planes[2].id = planes[1].id;
glDisable(m_textureTarget);

CVTBData *data = new CVTBData();
data->m_fence = 0;
data->m_vtbbuf = nullptr;
m_buffers[index].hwDec = data;

return true;
}

void CRendererVTB::DeleteTexture(int index)
{
YUVPLANES &planes = m_buffers[index].fields[0];

if (m_buffers[index].hwDec)
CVBufferRelease((struct __CVBuffer *)m_buffers[index].hwDec);
m_buffers[index].hwDec = NULL;
ReleaseBuffer(index);
delete (CVTBData*)m_buffers[index].hwDec;
m_buffers[index].hwDec = nullptr;

if (planes[0].id && glIsTexture(planes[0].id))
{
Expand All @@ -139,8 +170,9 @@ bool CRendererVTB::UploadTexture(int index)
YUVBUFFER &buf = m_buffers[index];
YUVFIELDS &fields = buf.fields;
YUVPLANES &planes = fields[0];
CVTBData *vtbdata = (CVTBData*)m_buffers[index].hwDec;

CVImageBufferRef cvBufferRef = (struct __CVBuffer *)m_buffers[index].hwDec;
CVImageBufferRef cvBufferRef = vtbdata->m_vtbbuf;

glEnable(m_textureTarget);

Expand Down Expand Up @@ -192,8 +224,32 @@ bool CRendererVTB::UploadTexture(int index)

CalculateTextureSourceRects(index, 3);


return true;
}

void CRendererVTB::AfterRenderHook(int idx)
{
CVTBData *vtbdata = (CVTBData*)m_buffers[idx].hwDec;
if (vtbdata->m_fence && glIsFenceAPPLE(vtbdata->m_fence))
{
glDeleteFencesAPPLE(1, &vtbdata->m_fence);
}
glGenFencesAPPLE(1, &vtbdata->m_fence);
glSetFenceAPPLE(vtbdata->m_fence);
}

bool CRendererVTB::NeedBuffer(int idx)
{
CVTBData *vtbdata = (CVTBData*)m_buffers[idx].hwDec;
if (!vtbdata)
return false;

if (vtbdata->m_fence && glIsFenceAPPLE(vtbdata->m_fence))
{
if (glTestFenceAPPLE(vtbdata->m_fence))
return false;
}

return true;
}
#endif
Expand Up @@ -33,19 +33,19 @@ class CRendererVTB : public CLinuxRendererGL
virtual ~CRendererVTB();

// Player functions
virtual void AddVideoPictureHW(DVDVideoPicture &picture, int index);
virtual void ReleaseBuffer(int idx);

// Feature support
virtual bool Supports(EINTERLACEMETHOD method);
virtual void AddVideoPictureHW(DVDVideoPicture &picture, int index) override;
virtual void ReleaseBuffer(int idx) override;
virtual bool NeedBuffer(int idx) override;
virtual CRenderInfo GetRenderInfo() override;

protected:
virtual bool LoadShadersHook();
virtual bool LoadShadersHook() override;
virtual void AfterRenderHook(int idx) override;

// textures
virtual bool UploadTexture(int index);
virtual void DeleteTexture(int index);
virtual bool CreateTexture(int index);
virtual bool UploadTexture(int index) override;
virtual void DeleteTexture(int index) override;
virtual bool CreateTexture(int index) override;
};

#endif
2 changes: 2 additions & 0 deletions xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp
Expand Up @@ -1115,6 +1115,8 @@ void CLinuxRendererGL::Render(DWORD flags, int renderBuffer)
RenderSoftware(renderBuffer, m_currentField);
VerifyGLState();
}

AfterRenderHook(renderBuffer);
}

void CLinuxRendererGL::RenderSinglePass(int index, int field)
Expand Down
2 changes: 1 addition & 1 deletion xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h
Expand Up @@ -87,7 +87,6 @@ enum RenderMethod
RENDER_VDPAU=0x08,
RENDER_POT=0x10,
RENDER_VAAPI=0x20,
RENDER_CVREF = 0x40,
};

enum RenderQuality
Expand Down Expand Up @@ -181,6 +180,7 @@ class CLinuxRendererGL : public CBaseRenderer
// hooks for HwDec Renderered
virtual bool LoadShadersHook() { return false; };
virtual bool RenderHook(int idx) { return false; };
virtual void AfterRenderHook(int idx) {};

struct
{
Expand Down
2 changes: 1 addition & 1 deletion xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp
Expand Up @@ -409,7 +409,7 @@ void CRenderManager::FrameMove()
for (std::deque<int>::iterator it = m_discard.begin(); it != m_discard.end(); )
{
// renderer may want to keep the frame for postprocessing
if (!m_pRenderer->NeedBufferForRef(*it) || !m_bRenderGUI)
if (!m_pRenderer->NeedBuffer(*it) || !m_bRenderGUI)
{
m_pRenderer->ReleaseBuffer(*it);
m_overlays.Release(*it);
Expand Down
2 changes: 1 addition & 1 deletion xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.cpp
Expand Up @@ -1103,7 +1103,7 @@ void CWinRenderer::ReleaseBuffer(int idx)
SAFE_RELEASE(reinterpret_cast<DXVABuffer*>(m_VideoBuffers[idx])->pic);
}

bool CWinRenderer::NeedBufferForRef(int idx)
bool CWinRenderer::NeedBuffer(int idx)
{
// check if processor wants to keep past frames
if (m_renderMethod == RENDER_DXVA && m_processor)
Expand Down
4 changes: 1 addition & 3 deletions xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.h
Expand Up @@ -175,7 +175,7 @@ class CWinRenderer : public CBaseRenderer
virtual void RenderUpdate(bool clear, unsigned int flags = 0, unsigned int alpha = 255);
virtual void SetBufferSize(int numBuffers) { m_neededBuffers = numBuffers; }
virtual void ReleaseBuffer(int idx);
virtual bool NeedBufferForRef(int idx);
virtual bool NeedBuffer(int idx);
virtual bool HandlesRenderFormat(ERenderFormat format) override;

// Feature support
Expand Down Expand Up @@ -240,5 +240,3 @@ class CWinRenderer : public CBaseRenderer
#else
#include "LinuxRenderer.h"
#endif