aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuriy Romanenko <yromanen@gmail.com>2011-02-24 12:03:53 +0200
committerJoakim Plate <elupus@xbmc.org>2011-02-26 18:51:07 +0100
commit76b51cce5dd64d6f33348cd36eddce95d571f783 (patch)
tree0ba1ee232f82ad0fff17c07425f34df95d20e063
parenta39d9d82275348e039d2befce3120f16cf27b761 (diff)
linux: VAAPI fix from bug #10928 http://trac.xbmc.org/ticket/10928
Signed-off-by: Joakim Plate <elupus@xbmc.org>
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp20
1 files changed, 14 insertions, 6 deletions
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp
index 0aac8fe53f..b03ea5c651 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp
@@ -149,10 +149,10 @@ int CDecoder::GetBuffer(AVCodecContext *avctx, AVFrame *pic)
{
VASurfaceID surface = GetSurfaceID(pic);
CSurface* wrapper = NULL;
+ std::list<CSurfacePtr>::iterator it = m_surfaces_free.begin();
if(surface)
{
/* reget call */
- std::list<CSurfacePtr>::iterator it = m_surfaces_free.begin();
for(; it != m_surfaces_free.end(); it++)
{
if((*it)->m_id == surface)
@@ -171,20 +171,28 @@ int CDecoder::GetBuffer(AVCodecContext *avctx, AVFrame *pic)
}
else
{
- if(m_surfaces_free.empty())
+ // To avoid stutter, we scan the free surface pool (provided by decoder) for surfaces
+ // that are 100% not in use by renderer. The pointers to these surfaces have a use_count of 1.
+ for (; it != m_surfaces_free.end() && it->use_count() > 1; it++) {}
+
+ // If we have zero free surface from decoder OR all free surfaces are in use by renderer, we allocate a new surface
+ if (it == m_surfaces_free.end())
{
+ if (!m_surfaces_free.empty()) CLog::Log(LOGERROR, "VAAPI - renderer still using all freed up surfaces by decoder");
CLog::Log(LOGERROR, "VAAPI - unable to find free surface, trying to allocate a new one");
if(!EnsureSurfaces(avctx, m_surfaces_count+1) || m_surfaces_free.empty())
{
CLog::Log(LOGERROR, "VAAPI - unable to find free surface");
return -1;
}
+ // Set itarator position to the newly allocated surface (end-1)
+ it = m_surfaces_free.end(); it--;
}
/* getbuffer call */
- wrapper = m_surfaces_free.front().get();
+ wrapper = it->get();
surface = wrapper->m_id;
- m_surfaces_used.push_back(m_surfaces_free.front());
- m_surfaces_free.pop_front();
+ m_surfaces_used.push_back(*it);
+ m_surfaces_free.erase(it);
}
pic->type = FF_BUFFER_TYPE_USER;
@@ -349,7 +357,7 @@ bool CDecoder::EnsureContext(AVCodecContext *avctx)
else
m_refs = 2;
}
- return EnsureSurfaces(avctx, m_refs + 1 + 1);
+ return EnsureSurfaces(avctx, m_refs + 3);
}
bool CDecoder::EnsureSurfaces(AVCodecContext *avctx, unsigned n_surfaces_count)