aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCrystalPT <CrystalPT@svn>2010-10-13 00:35:05 +0000
committerCrystalPT <CrystalPT@svn>2010-10-13 00:35:05 +0000
commit11220871d167e3455216a63fd6127c983ccca4dc (patch)
tree2146cd1525f285990d34467e3e2411054509708e
parent9bf60cda1f8f2db5cb8a12bbb190b1a08fb423c8 (diff)
[WIN32] fixed: unreleased DXVA surfaces leak memory and prevent device reset
(cherry picked from commit 93df0052fd3098df074b6a5c4e926656d65894f7) git-svn-id: https://xbmc.svn.sourceforge.net/svnroot/xbmc/branches/Dharma@34725 568bbfeb-2a22-0410-94d2-cc84cf5bfa90
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.cpp22
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.h4
2 files changed, 20 insertions, 6 deletions
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.cpp
index d7c67e9211..7e2d63cb78 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.cpp
@@ -39,8 +39,8 @@
#define ALLOW_ADDING_SURFACES 0
using namespace DXVA;
-using namespace boost;
using namespace AUTOPTR;
+using namespace std;
typedef HRESULT (__stdcall *DXVA2CreateVideoServicePtr)(IDirect3DDevice9* pDD, REFIID riid, void** ppService);
static DXVA2CreateVideoServicePtr g_DXVA2CreateVideoService;
@@ -482,6 +482,12 @@ bool CDecoder::Open(AVCodecContext *avctx, enum PixelFormat fmt)
if(!OpenDecoder())
return false;
+ // The front buffer seems to be the only one required and it seems to always be m_buffer[0] on ATI and nVidia
+ // but how reliable is that information?
+ // Not adding refs causes a crash at the end of playback because the surfaces are released with the decoder, despite the >0 D3D ref count.
+ for(unsigned i = 0; i < m_buffer_count; i++)
+ m_processor->HoldSurface(m_buffer[i].surface);
+
avctx->get_buffer = GetBufferS;
avctx->release_buffer = RelBufferS;
avctx->hwaccel_context = m_context;
@@ -673,10 +679,6 @@ bool CDecoder::OpenDecoder()
, m_context->surface_count
, &m_decoder))
- // CreateVideoDecoder will not addref the surfaces, but will release them when released
- for(unsigned i = 0; i < m_buffer_count; i++)
- m_buffer[i].surface->AddRef();
-
m_context->decoder = m_decoder;
return true;
@@ -799,9 +801,10 @@ void CProcessor::Close()
for(unsigned i = 0; i < m_sample.size(); i++)
SAFE_RELEASE(m_sample[i].SrcSurface);
m_sample.clear();
+ for (vector<IDirect3DSurface9*>::iterator it = m_heldsurfaces.begin(); it != m_heldsurfaces.end(); it++)
+ SAFE_RELEASE(*it);
}
-
bool CProcessor::Open(const DXVA2_VideoDesc& dsc)
{
if(!LoadDXVA())
@@ -860,9 +863,16 @@ bool CProcessor::Open(const DXVA2_VideoDesc& dsc)
CHECK(m_service->GetProcAmpRange(m_device, &m_desc, output, DXVA2_ProcAmp_Saturation, &m_saturation));
m_time = 0;
+
return true;
}
+void CProcessor::HoldSurface(IDirect3DSurface9* surface)
+{
+ surface->AddRef();
+ m_heldsurfaces.push_back(surface);
+}
+
REFERENCE_TIME CProcessor::Add(IDirect3DSurface9* source)
{
CSingleLock lock(m_section);
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.h
index 5015bf85fa..00ab72414e 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.h
@@ -26,6 +26,8 @@
#include "Event.h"
#include <dxva2api.h>
#include <deque>
+#include <vector>
+
namespace DXVA {
class CProcessor;
@@ -104,6 +106,7 @@ public:
bool Open(const DXVA2_VideoDesc& dsc);
void Close();
+ void HoldSurface(IDirect3DSurface9* surface);
REFERENCE_TIME Add (IDirect3DSurface9* source);
bool Render(const RECT& dst, IDirect3DSurface9* target, const REFERENCE_TIME time);
int Size() { return m_size; }
@@ -137,6 +140,7 @@ public:
long m_references;
protected:
+ std::vector<IDirect3DSurface9*> m_heldsurfaces;
};
};