Skip to content

Commit

Permalink
Merge pull request #10615 from FernetMenta/vtb
Browse files Browse the repository at this point in the history
VTB on OSX: fix flickering video caused by buffer overwrite
  • Loading branch information
FernetMenta committed Oct 4, 2016
2 parents dd13b73 + c9dc2d1 commit df45f18
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 34 deletions.
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


0 comments on commit df45f18

Please sign in to comment.