mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-28 13:16:41 +00:00
xbmc: XVBA reduce needed memory, in particular during channel switching
This commit is contained in:
parent
78140bd63f
commit
d88228c8e2
@ -0,0 +1,392 @@
|
|||||||
|
From dffb8b123b9c85e0f78c8ad10ea09534edbe6e61 Mon Sep 17 00:00:00 2001
|
||||||
|
From: xbmc <fernetmenta@online.de>
|
||||||
|
Date: Fri, 5 Oct 2012 11:46:26 +0200
|
||||||
|
Subject: [PATCH] xvba: reduce needed memory, in particular during channel
|
||||||
|
switching
|
||||||
|
|
||||||
|
---
|
||||||
|
xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp | 230 ++++++++++---------------
|
||||||
|
xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h | 7 +-
|
||||||
|
2 files changed, 97 insertions(+), 140 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp
|
||||||
|
index 78ad0a6..790b3b4 100644
|
||||||
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp
|
||||||
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp
|
||||||
|
@@ -517,37 +517,7 @@ long CDecoder::Release()
|
||||||
|
{
|
||||||
|
CSingleLock lock(m_decoderSection);
|
||||||
|
CLog::Log(LOGNOTICE,"XVBA::Release pre-cleanup");
|
||||||
|
-
|
||||||
|
- Message *reply;
|
||||||
|
- if (m_xvbaOutput.m_controlPort.SendOutMessageSync(COutputControlProtocol::PRECLEANUP,
|
||||||
|
- &reply,
|
||||||
|
- 2000))
|
||||||
|
- {
|
||||||
|
- bool success = reply->signal == COutputControlProtocol::ACC ? true : false;
|
||||||
|
- reply->Release();
|
||||||
|
- if (!success)
|
||||||
|
- {
|
||||||
|
- CLog::Log(LOGERROR, "XVBA::%s - pre-cleanup returned error", __FUNCTION__);
|
||||||
|
- m_displayState = XVBA_ERROR;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- CLog::Log(LOGERROR, "XVBA::%s - pre-cleanup timed out", __FUNCTION__);
|
||||||
|
- m_displayState = XVBA_ERROR;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- for(unsigned int i = 0; i < m_videoSurfaces.size(); ++i)
|
||||||
|
- {
|
||||||
|
- xvba_render_state *render = m_videoSurfaces[i];
|
||||||
|
- if (render->surface && !(render->state & FF_XVBA_STATE_USED_FOR_RENDER))
|
||||||
|
- {
|
||||||
|
- g_XVBA_vtable.DestroySurface(render->surface);
|
||||||
|
- render->surface = 0;
|
||||||
|
- render->picture_descriptor = 0;
|
||||||
|
- render->iq_matrix = 0;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ DestroySession(true);
|
||||||
|
}
|
||||||
|
IHardwareDecoder::Release();
|
||||||
|
}
|
||||||
|
@@ -726,7 +696,7 @@ bool CDecoder::CreateSession(AVCodecContext* avctx)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
-void CDecoder::DestroySession()
|
||||||
|
+void CDecoder::DestroySession(bool precleanup /*= false*/)
|
||||||
|
{
|
||||||
|
// wait for unfinished decoding jobs
|
||||||
|
XbmcThreads::EndTime timer;
|
||||||
|
@@ -762,7 +732,29 @@ void CDecoder::DestroySession()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- m_xvbaOutput.Dispose();
|
||||||
|
+ if (precleanup)
|
||||||
|
+ {
|
||||||
|
+ Message *reply;
|
||||||
|
+ if (m_xvbaOutput.m_controlPort.SendOutMessageSync(COutputControlProtocol::PRECLEANUP,
|
||||||
|
+ &reply,
|
||||||
|
+ 2000))
|
||||||
|
+ {
|
||||||
|
+ bool success = reply->signal == COutputControlProtocol::ACC ? true : false;
|
||||||
|
+ reply->Release();
|
||||||
|
+ if (!success)
|
||||||
|
+ {
|
||||||
|
+ CLog::Log(LOGERROR, "XVBA::%s - pre-cleanup returned error", __FUNCTION__);
|
||||||
|
+ m_displayState = XVBA_ERROR;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ CLog::Log(LOGERROR, "XVBA::%s - pre-cleanup timed out", __FUNCTION__);
|
||||||
|
+ m_displayState = XVBA_ERROR;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ m_xvbaOutput.Dispose();
|
||||||
|
|
||||||
|
XVBA_Destroy_Decode_Buffers_Input bufInput;
|
||||||
|
bufInput.size = sizeof(bufInput);
|
||||||
|
@@ -804,6 +796,7 @@ void CDecoder::DestroySession()
|
||||||
|
{
|
||||||
|
g_XVBA_vtable.DestroySurface(render->surface);
|
||||||
|
render->surface = 0;
|
||||||
|
+ render->state = 0;
|
||||||
|
render->picture_descriptor = 0;
|
||||||
|
render->iq_matrix = 0;
|
||||||
|
}
|
||||||
|
@@ -1431,14 +1424,6 @@ long CXvbaRenderPicture::Release()
|
||||||
|
return refCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
-void CXvbaRenderPicture::Transfer()
|
||||||
|
-{
|
||||||
|
- CSingleLock lock(*renderPicSection);
|
||||||
|
-
|
||||||
|
- if (valid)
|
||||||
|
- xvbaOutput->TransferSurface(sourceIdx);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
void CXvbaRenderPicture::ReturnUnused()
|
||||||
|
{
|
||||||
|
{ CSingleLock lock(*renderPicSection);
|
||||||
|
@@ -1617,9 +1602,10 @@ void COutput::StateMachine(int signal, Protocol *port, Message *msg)
|
||||||
|
msg->Reply(COutputControlProtocol::ACC);
|
||||||
|
return;
|
||||||
|
case COutputControlProtocol::PRECLEANUP:
|
||||||
|
- m_state = O_TOP_CONFIGURED_WAIT_RES1;
|
||||||
|
+ m_state = O_TOP_UNCONFIGURED;
|
||||||
|
+ m_extTimeout = 10000;
|
||||||
|
Flush();
|
||||||
|
- PreReleaseBufferPool();
|
||||||
|
+ ReleaseBufferPool(true);
|
||||||
|
msg->Reply(COutputControlProtocol::ACC);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
@@ -1885,6 +1871,7 @@ bool COutput::Init()
|
||||||
|
|
||||||
|
m_xvbaError = false;
|
||||||
|
m_processPicture.render = 0;
|
||||||
|
+ m_fence = None;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@@ -1972,32 +1959,6 @@ bool COutput::IsDecodingFinished()
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
-void COutput::TransferSurface(uint32_t source)
|
||||||
|
-{
|
||||||
|
- XvbaBufferPool::GLVideoSurface *glSurface = &m_bufferPool.glSurfaces[source];
|
||||||
|
-
|
||||||
|
- if (glSurface->transferred)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
- glSurface->transferred = true;
|
||||||
|
-
|
||||||
|
- // transfer surface
|
||||||
|
- XVBA_Transfer_Surface_Input transInput;
|
||||||
|
- transInput.size = sizeof(transInput);
|
||||||
|
- transInput.session = m_config.xvbaSession;
|
||||||
|
- transInput.src_surface = glSurface->render->surface;
|
||||||
|
- transInput.target_surface = glSurface->glSurface;
|
||||||
|
- transInput.flag = glSurface->field;
|
||||||
|
- { CSingleLock lock(*(m_config.apiSec));
|
||||||
|
- if (Success != g_XVBA_vtable.TransferSurface(&transInput))
|
||||||
|
- {
|
||||||
|
- CLog::Log(LOGERROR,"(XVBA) failed to transfer surface");
|
||||||
|
- m_xvbaError = true;
|
||||||
|
- return;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
CXvbaRenderPicture* COutput::ProcessPicture()
|
||||||
|
{
|
||||||
|
CXvbaRenderPicture *retPic = 0;
|
||||||
|
@@ -2021,36 +1982,25 @@ CXvbaRenderPicture* COutput::ProcessPicture()
|
||||||
|
int cmd = 0;
|
||||||
|
m_config.stats->GetCmd(cmd);
|
||||||
|
|
||||||
|
-// if (!(cmd & DVP_FLAG_SKIP_PROC))
|
||||||
|
-// {
|
||||||
|
- // transfer surface
|
||||||
|
- XVBA_Transfer_Surface_Input transInput;
|
||||||
|
- transInput.size = sizeof(transInput);
|
||||||
|
- transInput.session = m_config.xvbaSession;
|
||||||
|
- transInput.src_surface = m_processPicture.render->surface;
|
||||||
|
- transInput.target_surface = glSurface->glSurface;
|
||||||
|
- transInput.flag = m_field;
|
||||||
|
- { CSingleLock lock(*(m_config.apiSec));
|
||||||
|
- if (Success != g_XVBA_vtable.TransferSurface(&transInput))
|
||||||
|
- {
|
||||||
|
- CLog::Log(LOGERROR,"(XVBA) failed to transfer surface");
|
||||||
|
- m_xvbaError = true;
|
||||||
|
- return retPic;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+// if (m_fence)
|
||||||
|
+// glDeleteSync(m_fence);
|
||||||
|
+// m_fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
|
|
||||||
|
- // make sure that transfer is completed
|
||||||
|
-// uint64_t maxTimeout = 1000000000LL;
|
||||||
|
-// GLsync ReadyFence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
|
-// glClientWaitSync(ReadyFence, GL_SYNC_FLUSH_COMMANDS_BIT, maxTimeout);
|
||||||
|
-// glDeleteSync(ReadyFence);
|
||||||
|
-// glFinish();GL_SYNC_FLUSH_COMMANDS_BIT
|
||||||
|
-// }
|
||||||
|
-// else
|
||||||
|
-// {
|
||||||
|
-// CLog::Log(LOGDEBUG,"XVBA::ProcessPicture - skipped transfer surface");
|
||||||
|
-// m_processPicture.DVDPic.iFlags |= DVP_FLAG_DROPPED;
|
||||||
|
-// }
|
||||||
|
+ // transfer surface
|
||||||
|
+ XVBA_Transfer_Surface_Input transInput;
|
||||||
|
+ transInput.size = sizeof(transInput);
|
||||||
|
+ transInput.session = m_config.xvbaSession;
|
||||||
|
+ transInput.src_surface = m_processPicture.render->surface;
|
||||||
|
+ transInput.target_surface = glSurface->glSurface;
|
||||||
|
+ transInput.flag = m_field;
|
||||||
|
+ { CSingleLock lock(*(m_config.apiSec));
|
||||||
|
+ if (Success != g_XVBA_vtable.TransferSurface(&transInput))
|
||||||
|
+ {
|
||||||
|
+ CLog::Log(LOGERROR,"(XVBA) failed to transfer surface");
|
||||||
|
+ m_xvbaError = true;
|
||||||
|
+ return retPic;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
// prepare render pic
|
||||||
|
retPic = m_bufferPool.freeRenderPics.front();
|
||||||
|
@@ -2096,36 +2046,34 @@ void COutput::ProcessReturnPicture(CXvbaRenderPicture *pic)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (m_config.useSharedSurfaces)
|
||||||
|
+ xvba_render_state *render = m_bufferPool.glSurfaces[pic->sourceIdx].render;
|
||||||
|
+ if (render)
|
||||||
|
{
|
||||||
|
- xvba_render_state *render = m_bufferPool.glSurfaces[pic->sourceIdx].render;
|
||||||
|
- if (render)
|
||||||
|
+ // check if video surface is referenced by other glSurfaces
|
||||||
|
+ bool referenced(false);
|
||||||
|
+ for (unsigned int i=0; i<m_bufferPool.glSurfaces.size();++i)
|
||||||
|
{
|
||||||
|
- // check if video surface if referenced by other glSurfaces
|
||||||
|
- bool referenced(false);
|
||||||
|
- for (unsigned int i=0; i<m_bufferPool.glSurfaces.size();++i)
|
||||||
|
+ if (i == pic->sourceIdx)
|
||||||
|
+ continue;
|
||||||
|
+ if (m_bufferPool.glSurfaces[i].render == render)
|
||||||
|
{
|
||||||
|
- if (i == pic->sourceIdx)
|
||||||
|
- continue;
|
||||||
|
- if (m_bufferPool.glSurfaces[i].render == render)
|
||||||
|
- {
|
||||||
|
- referenced = true;
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- if (m_processPicture.render == render)
|
||||||
|
referenced = true;
|
||||||
|
-
|
||||||
|
- // release video surface
|
||||||
|
- if (!referenced)
|
||||||
|
- {
|
||||||
|
- CSingleLock lock(*m_config.videoSurfaceSec);
|
||||||
|
- render->state &= ~(FF_XVBA_STATE_USED_FOR_RENDER | FF_XVBA_STATE_DECODED);
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
+ }
|
||||||
|
+ if (m_processPicture.render == render)
|
||||||
|
+ referenced = true;
|
||||||
|
|
||||||
|
- // unreference video surface
|
||||||
|
- m_bufferPool.glSurfaces[pic->sourceIdx].render = 0;
|
||||||
|
+ // release video surface
|
||||||
|
+ if (!referenced)
|
||||||
|
+ {
|
||||||
|
+ CSingleLock lock(*m_config.videoSurfaceSec);
|
||||||
|
+ render->state &= ~(FF_XVBA_STATE_USED_FOR_RENDER | FF_XVBA_STATE_DECODED);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ // unreference video surface
|
||||||
|
+ m_bufferPool.glSurfaces[pic->sourceIdx].render = 0;
|
||||||
|
+
|
||||||
|
m_bufferPool.glSurfaces[pic->sourceIdx].used = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
@@ -2266,32 +2214,42 @@ bool COutput::EnsureBufferPool()
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
-void COutput::ReleaseBufferPool()
|
||||||
|
+void COutput::ReleaseBufferPool(bool precleanup /*= false*/)
|
||||||
|
{
|
||||||
|
+// if (m_fence)
|
||||||
|
+// {
|
||||||
|
+// uint64_t maxTimeout = 1000000000LL;
|
||||||
|
+// glClientWaitSync(m_fence, GL_SYNC_FLUSH_COMMANDS_BIT, maxTimeout);
|
||||||
|
+// glDeleteSync(m_fence);
|
||||||
|
+// m_fence = None;
|
||||||
|
+// }
|
||||||
|
+
|
||||||
|
CSingleLock lock(m_bufferPool.renderPicSec);
|
||||||
|
|
||||||
|
- if (m_config.useSharedSurfaces)
|
||||||
|
+ for (unsigned int i = 0; i < m_bufferPool.glSurfaces.size(); ++i)
|
||||||
|
{
|
||||||
|
- for (unsigned int i = 0; i < m_bufferPool.glSurfaces.size(); ++i)
|
||||||
|
+ if (m_bufferPool.glSurfaces[i].glSurface)
|
||||||
|
{
|
||||||
|
- if (!m_bufferPool.glSurfaces[i].glSurface)
|
||||||
|
- continue;
|
||||||
|
g_XVBA_vtable.DestroySurface(m_bufferPool.glSurfaces[i].glSurface);
|
||||||
|
+ m_bufferPool.glSurfaces[i].glSurface = 0;
|
||||||
|
+ }
|
||||||
|
+ if (m_bufferPool.glSurfaces[i].texture && !precleanup)
|
||||||
|
+ {
|
||||||
|
glDeleteTextures(1, &m_bufferPool.glSurfaces[i].texture);
|
||||||
|
+ m_bufferPool.glSurfaces[i].texture = 0;
|
||||||
|
}
|
||||||
|
- m_bufferPool.glSurfaces.clear();
|
||||||
|
+ m_bufferPool.glSurfaces[i].render = 0;
|
||||||
|
+ m_bufferPool.glSurfaces[i].used = true;
|
||||||
|
}
|
||||||
|
- // invalidate all used render pictures
|
||||||
|
- for (unsigned int i = 0; i < m_bufferPool.usedRenderPics.size(); ++i)
|
||||||
|
+
|
||||||
|
+ if (!precleanup)
|
||||||
|
{
|
||||||
|
- m_bufferPool.usedRenderPics[i]->valid = false;
|
||||||
|
- unsigned int idx = m_bufferPool.usedRenderPics[i]->sourceIdx;
|
||||||
|
- if (m_bufferPool.glSurfaces[idx].render)
|
||||||
|
+ m_bufferPool.glSurfaces.clear();
|
||||||
|
+
|
||||||
|
+ // invalidate all used render pictures
|
||||||
|
+ for (unsigned int i = 0; i < m_bufferPool.usedRenderPics.size(); ++i)
|
||||||
|
{
|
||||||
|
- { CSingleLock lock(*m_config.videoSurfaceSec);
|
||||||
|
- m_bufferPool.glSurfaces[idx].render->state &= ~(FF_XVBA_STATE_USED_FOR_RENDER | FF_XVBA_STATE_DECODED);
|
||||||
|
- m_bufferPool.glSurfaces[idx].render = 0;
|
||||||
|
- }
|
||||||
|
+ m_bufferPool.usedRenderPics[i]->valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h
|
||||||
|
index 24331e9..f38444c 100644
|
||||||
|
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h
|
||||||
|
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h
|
||||||
|
@@ -144,7 +144,6 @@ class CXvbaRenderPicture
|
||||||
|
CDecoder *xvba;
|
||||||
|
CXvbaRenderPicture* Acquire();
|
||||||
|
long Release();
|
||||||
|
- void Transfer();
|
||||||
|
private:
|
||||||
|
void ReturnUnused();
|
||||||
|
int refCount;
|
||||||
|
@@ -226,7 +225,6 @@ class COutput : private CThread
|
||||||
|
virtual ~COutput();
|
||||||
|
void Start();
|
||||||
|
void Dispose();
|
||||||
|
- void TransferSurface(uint32_t source);
|
||||||
|
COutputControlProtocol m_controlPort;
|
||||||
|
COutputDataProtocol m_dataPort;
|
||||||
|
protected:
|
||||||
|
@@ -247,7 +245,7 @@ class COutput : private CThread
|
||||||
|
bool CreateGlxContext();
|
||||||
|
bool DestroyGlxContext();
|
||||||
|
bool EnsureBufferPool();
|
||||||
|
- void ReleaseBufferPool();
|
||||||
|
+ void ReleaseBufferPool(bool precleanup = false);
|
||||||
|
void PreReleaseBufferPool();
|
||||||
|
CEvent m_outMsgEvent;
|
||||||
|
CEvent *m_inMsgEvent;
|
||||||
|
@@ -265,6 +263,7 @@ class COutput : private CThread
|
||||||
|
GLXWindow m_glWindow;
|
||||||
|
Pixmap m_pixmap;
|
||||||
|
GLXPixmap m_glPixmap;
|
||||||
|
+ GLsync m_fence;
|
||||||
|
std::queue<CXvbaDecodedPicture> m_decodedPics;
|
||||||
|
CXvbaDecodedPicture m_processPicture;
|
||||||
|
XVBA_SURFACE_FLAG m_field;
|
||||||
|
@@ -338,7 +337,7 @@ class CDecoder : public CDVDVideoCodecFFmpeg::IHardwareDecoder,
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool CreateSession(AVCodecContext* avctx);
|
||||||
|
- void DestroySession();
|
||||||
|
+ void DestroySession(bool precleanup = false);
|
||||||
|
bool EnsureDataControlBuffers(unsigned int num);
|
||||||
|
void ResetState();
|
||||||
|
void SetError(const char* function, const char* msg, int line);
|
||||||
|
--
|
||||||
|
1.7.10
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user