Skip to content

Commit

Permalink
dxva: fix and rework video surface handling
Browse files Browse the repository at this point in the history
  • Loading branch information
FernetMenta committed Sep 19, 2014
1 parent 99fde6c commit 4f49d56
Show file tree
Hide file tree
Showing 8 changed files with 269 additions and 194 deletions.
79 changes: 34 additions & 45 deletions xbmc/cores/VideoRenderers/DXVA.cpp
Expand Up @@ -151,7 +151,6 @@ CProcessor::CProcessor()
m_time = 0;
g_Windowing.Register(this);

m_surfaces = NULL;
m_context = NULL;
m_index = 0;
m_progressive = true;
Expand All @@ -174,21 +173,13 @@ void CProcessor::Close()
{
CSingleLock lock(m_section);
SAFE_RELEASE(m_process);
for(unsigned i = 0; i < m_sample.size(); i++)
for(unsigned i = 0; i < m_samples.size(); i++)
{
SAFE_RELEASE(m_sample[i].context);
SAFE_RELEASE(m_sample[i].sample.SrcSurface);
SAFE_RELEASE(m_samples[i].renderPic);
}
m_sample.clear();
m_samples.clear();

SAFE_RELEASE(m_context);
if (m_surfaces)
{
for (unsigned i = 0; i < m_size; i++)
SAFE_RELEASE(m_surfaces[i]);
free(m_surfaces);
m_surfaces = NULL;
}
}

bool CProcessor::UpdateSize(const DXVA2_VideoDesc& dsc)
Expand Down Expand Up @@ -499,17 +490,23 @@ bool CProcessor::OpenProcessor()
bool CProcessor::CreateSurfaces()
{
LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
m_surfaces = (LPDIRECT3DSURFACE9*)calloc(m_size, sizeof(LPDIRECT3DSURFACE9));
LPDIRECT3DSURFACE9 surfaces[32];
for (unsigned idx = 0; idx < m_size; idx++)
{
CHECK(pD3DDevice->CreateOffscreenPlainSurface(
(m_desc.SampleWidth + 15) & ~15,
(m_desc.SampleHeight + 15) & ~15,
m_desc.Format,
D3DPOOL_DEFAULT,
&m_surfaces[idx],
NULL));
(m_desc.SampleWidth + 15) & ~15,
(m_desc.SampleHeight + 15) & ~15,
m_desc.Format,
D3DPOOL_DEFAULT,
&surfaces[idx],
NULL));
}

m_context = new CSurfaceContext();
for (int i = 0; i < m_size; i++)
{
m_context->AddSurface(surfaces[i]);
}

return true;
}
Expand All @@ -519,7 +516,6 @@ REFERENCE_TIME CProcessor::Add(DVDVideoPicture* picture)
CSingleLock lock(m_section);

IDirect3DSurface9* surface = NULL;
CSurfaceContext* context = NULL;

if (picture->iFlags & DVP_FLAG_DROPPED)
return 0;
Expand All @@ -528,18 +524,15 @@ REFERENCE_TIME CProcessor::Add(DVDVideoPicture* picture)
{
case RENDER_FMT_DXVA:
{
surface = (IDirect3DSurface9*)picture->data[3];
context = picture->context;
surface = picture->dxva->surface;
break;
}

case RENDER_FMT_YUV420P:
{
surface = m_surfaces[m_index];
surface = m_context->GetAtIndex(m_index);
m_index = (m_index + 1) % m_size;

context = m_context;

D3DLOCKED_RECT rectangle;
if (FAILED(surface->LockRect(&rectangle, NULL, 0)))
return 0;
Expand Down Expand Up @@ -585,18 +578,18 @@ REFERENCE_TIME CProcessor::Add(DVDVideoPicture* picture)
}
}

if (!surface || !context)
if (!surface)
return 0;

m_time += 2;

surface->AddRef();
context->Acquire();

SVideoSample vs = {};
vs.sample.Start = m_time;
vs.sample.End = 0;
vs.sample.SampleFormat = m_desc.SampleFormat;
vs.renderPic = NULL;
if (picture->format == RENDER_FMT_DXVA)
vs.renderPic = picture->dxva->Acquire();

if (picture->iFlags & DVP_FLAG_INTERLACED)
{
Expand All @@ -615,17 +608,14 @@ REFERENCE_TIME CProcessor::Add(DVDVideoPicture* picture)
vs.sample.SrcSurface = surface;


vs.context = context;

if(!m_sample.empty())
m_sample.back().sample.End = vs.sample.Start;
if(!m_samples.empty())
m_samples.back().sample.End = vs.sample.Start;

m_sample.push_back(vs);
if (m_sample.size() > m_size)
m_samples.push_back(vs);
if (m_samples.size() > m_size)
{
SAFE_RELEASE(m_sample.front().context);
SAFE_RELEASE(m_sample.front().sample.SrcSurface);
m_sample.pop_front();
SAFE_RELEASE(m_samples.front().renderPic);
m_samples.pop_front();
}

return m_time;
Expand Down Expand Up @@ -671,20 +661,19 @@ bool CProcessor::Render(CRect src, CRect dst, IDirect3DSurface9* target, REFEREN
REFERENCE_TIME MinTime = time - m_max_back_refs*2;
REFERENCE_TIME MaxTime = time + m_max_fwd_refs*2;

SSamples::iterator it = m_sample.begin();
while (it != m_sample.end())
std::deque<SVideoSample>::iterator it = m_samples.begin();
while (it != m_samples.end())
{
if (it->sample.Start < MinTime)
{
SAFE_RELEASE(it->context);
SAFE_RELEASE(it->sample.SrcSurface);
it = m_sample.erase(it);
SAFE_RELEASE(it->renderPic);
it = m_samples.erase(it);
}
else
++it;
}

if(m_sample.empty())
if(m_samples.empty())
return false;

// MinTime and MaxTime are now the first and last samples to feed the processor.
Expand All @@ -711,7 +700,7 @@ bool CProcessor::Render(CRect src, CRect dst, IDirect3DSurface9* target, REFEREN
for (int i = 0; i < count; i++)
samp[i].SampleFormat.SampleFormat = DXVA2_SampleUnknown;

for(it = m_sample.begin(); it != m_sample.end() && valid < count; ++it)
for(it = m_samples.begin(); it != m_samples.end() && valid < count; ++it)
{
if (it->sample.Start >= MinTime && it->sample.Start <= MaxTime)
{
Expand Down
6 changes: 2 additions & 4 deletions xbmc/cores/VideoRenderers/DXVA.h
Expand Up @@ -84,13 +84,11 @@ class CProcessor
struct SVideoSample
{
DXVA2_VideoSample sample;
CSurfaceContext* context;
CRenderPicture* renderPic;
};
typedef std::deque<SVideoSample> SSamples;
SSamples m_sample;
std::deque<SVideoSample> m_samples;

CCriticalSection m_section;
LPDIRECT3DSURFACE9* m_surfaces;
CSurfaceContext* m_context;
bool m_quirk_nodeintprocforprog;
static CCriticalSection m_dlSection;
Expand Down
60 changes: 24 additions & 36 deletions xbmc/cores/VideoRenderers/DXVAHD.cpp
Expand Up @@ -88,7 +88,6 @@ CProcessorHD::CProcessorHD()
m_frame = 0;
g_Windowing.Register(this);

m_surfaces = NULL;
m_context = NULL;
}

Expand All @@ -112,21 +111,11 @@ void CProcessorHD::Close()

for(unsigned i = 0; i < m_frames.size(); i++)
{
SAFE_RELEASE(m_frames[i].context);
SAFE_RELEASE(m_frames[i].pSurface);
SAFE_RELEASE(m_frames[i].pRenderPic);
}
m_frames.clear();

SAFE_RELEASE(m_context);
if (m_surfaces)
{
for (unsigned i = 0; i < m_size; i++)
{
SAFE_RELEASE(m_surfaces[i]);
}
free(m_surfaces);
m_surfaces = NULL;
}
}

bool CProcessorHD::UpdateSize(const DXVA2_VideoDesc& dsc)
Expand Down Expand Up @@ -330,17 +319,23 @@ bool CProcessorHD::OpenProcessor()
bool CProcessorHD::CreateSurfaces()
{
LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
m_surfaces = (LPDIRECT3DSURFACE9*)calloc(m_size, sizeof(LPDIRECT3DSURFACE9));
LPDIRECT3DSURFACE9 surfaces[32];
for (unsigned idx = 0; idx < m_size; idx++)
{
CHECK(pD3DDevice->CreateOffscreenPlainSurface(
(m_width + 15) & ~15,
(m_height + 15) & ~15,
m_format,
m_VPDevCaps.InputPool,
&m_surfaces[idx],
NULL));
(m_width + 15) & ~15,
(m_height + 15) & ~15,
m_format,
m_VPDevCaps.InputPool,
&surfaces[idx],
NULL));
}

m_context = new CSurfaceContext();
for (int i = 0; i < m_size; i++)
{
m_context->AddSurface(surfaces[i]);
}

return true;
}
Expand All @@ -350,7 +345,6 @@ REFERENCE_TIME CProcessorHD::Add(DVDVideoPicture* picture)
CSingleLock lock(m_section);

IDirect3DSurface9* surface = NULL;
CSurfaceContext* context = NULL;

if (picture->iFlags & DVP_FLAG_DROPPED)
{
Expand All @@ -361,23 +355,20 @@ REFERENCE_TIME CProcessorHD::Add(DVDVideoPicture* picture)
{
case RENDER_FMT_DXVA:
{
surface = (IDirect3DSurface9*)picture->data[3];
context = picture->context;
surface = picture->dxva->surface;
break;
}

case RENDER_FMT_YUV420P:
{
if (!m_surfaces)
if (!m_context)
{
CLog::Log(LOGWARNING, __FUNCTION__" - not initialized.");
return 0;
}

surface = m_surfaces[m_index];
surface = m_context->GetAtIndex(m_index);
m_index = (m_index + 1) % m_size;

context = m_context;

D3DLOCKED_RECT rectangle;
if (FAILED(surface->LockRect(&rectangle, NULL, 0)))
Expand Down Expand Up @@ -430,19 +421,18 @@ REFERENCE_TIME CProcessorHD::Add(DVDVideoPicture* picture)
}
}

if (!surface || !context)
if (!surface)
{
return 0;
}
m_frame += 2;

surface->AddRef();
context->Acquire();

SFrame frame = {};
frame.index = m_frame;
frame.pSurface = surface;
frame.context = context;
frame.pSurface = surface;
frame.pRenderPic = NULL;
if (picture->format == RENDER_FMT_DXVA)
frame.pRenderPic = picture->dxva->Acquire();
frame.format = DXVAHD_FRAME_FORMAT_PROGRESSIVE;

if (picture->iFlags & DVP_FLAG_INTERLACED)
Expand All @@ -456,8 +446,7 @@ REFERENCE_TIME CProcessorHD::Add(DVDVideoPicture* picture)

if (m_frames.size() > m_size)
{
SAFE_RELEASE(m_frames.front().context);
SAFE_RELEASE(m_frames.front().pSurface);
SAFE_RELEASE(m_frames.front().pRenderPic);

m_frames.pop_front();
}
Expand Down Expand Up @@ -526,8 +515,7 @@ bool CProcessorHD::Render(CRect src, CRect dst, IDirect3DSurface9* target, REFER
{
if (it->index < minFrame)
{
SAFE_RELEASE(it->context);
SAFE_RELEASE(it->pSurface);
SAFE_RELEASE(it->pRenderPic);
it = m_frames.erase(it);
}
else
Expand Down
2 changes: 1 addition & 1 deletion xbmc/cores/VideoRenderers/DXVAHD.h
Expand Up @@ -97,7 +97,7 @@ class CProcessorHD
struct SFrame
{
IDirect3DSurface9* pSurface;
CSurfaceContext* context;
CRenderPicture* pRenderPic;
unsigned int index;
unsigned format;
};
Expand Down
4 changes: 2 additions & 2 deletions xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
Expand Up @@ -47,7 +47,7 @@ struct DVDCodecAvailableType
#define FRAME_TYPE_B 3
#define FRAME_TYPE_D 4

namespace DXVA { class CSurfaceContext; }
namespace DXVA { class CRenderPicture; }
namespace VAAPI { class CVaapiRenderPicture; }
namespace VDPAU { class CVdpauRenderPicture; }
class COpenMax;
Expand All @@ -72,7 +72,7 @@ struct DVDVideoPicture
int iLineSize[4]; // [4] = alpha channel, currently not used
};
struct {
DXVA::CSurfaceContext* context;
DXVA::CRenderPicture* dxva;
};
struct {
VDPAU::CVdpauRenderPicture* vdpau;
Expand Down
Expand Up @@ -101,6 +101,7 @@ enum PixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx
#ifdef HAS_DX
if(DXVA::CDecoder::Supports(*cur) && CSettings::Get().GetBool("videoplayer.usedxva2"))
{
CLog::Log(LOGNOTICE, "CDVDVideoCodecFFmpeg::GetFormat - Creating DXVA(%ix%i)", avctx->width, avctx->height);
DXVA::CDecoder* dec = new DXVA::CDecoder();
if(dec->Open(avctx, *cur, ctx->m_uSurfacesCount))
{
Expand Down

0 comments on commit 4f49d56

Please sign in to comment.