Permalink
Browse files

added: intial dxva2 decoder support for vc1/h264

Decoder is not enabled by default as it still has issues.

Working:
VC1 has worked for all samples i've tried (not that many)
x264 encoded h264 all seem to work fine

Known issues:
Apple encoded h264 => green screen or corrupt green screen
Raw blueray h264 => weird corruption of bottom half of video

git-svn-id: https://xbmc.svn.sourceforge.net/svnroot/xbmc/trunk@27376 568bbfeb-2a22-0410-94d2-cc84cf5bfa90
  • Loading branch information...
elupus
elupus committed Feb 2, 2010
1 parent 3805a54 commit a829e510f0df637679ce6bc42a698c90c93e2869
@@ -2186,4 +2186,7 @@
<string id="34000">Lame</string>
<string id="34001">Vorbis</string>
<string id="34002">Wav</string>
<string id="34003">DXVA</string>
</strings>
@@ -1051,6 +1051,14 @@
>
</File>
</Filter>
<File
RelativePath="..\..\xbmc\cores\dvdplayer\DVDCodecs\Video\DXVA.cpp"
>
</File>
<File
RelativePath="..\..\xbmc\cores\dvdplayer\DVDCodecs\Video\DXVA.h"
>
</File>
</Filter>
<Filter
Name="Overlay"
@@ -545,6 +545,10 @@ void CGUISettings::Initialize()
if (CCrystalHD::GetInstance()->DevicePresent())
renderers.insert(make_pair(13425, RENDER_METHOD_CRYSTALHD));
#endif
#ifdef HAS_DX
renderers.insert(make_pair(34003, RENDER_METHOD_DXVA));
#endif
AddInt(3, "videoplayer.rendermethod", 13415, RENDER_METHOD_AUTO, renderers, SPIN_CONTROL_TEXT);
#ifdef HAS_GL
@@ -35,6 +35,7 @@ class TiXmlElement;
#define RENDER_METHOD_SOFTWARE 3
#define RENDER_METHOD_VDPAU 4
#define RENDER_METHOD_CRYSTALHD 5
#define RENDER_METHOD_DXVA 6
#define RENDER_OVERLAYS 99 // to retain compatibility
// Scaling options.
@@ -50,5 +50,5 @@
#define CONF_FLAGS_FORMAT_NV12 0x02000
#define CONF_FLAGS_FORMAT_UYVY 0x04000 /* place holder for future expansion */
#define CONF_FLAGS_FORMAT_YUY2 0x08000 /* place holder for future expansion */
#define CONF_FLAGS_FORMAT_DXVA 0x10000
#endif
@@ -82,6 +82,15 @@ class CXBMCRenderManager
unsigned int PreInit();
void UnInit();
#ifdef HAS_DX
void AddProcessor(DXVA::CProcessor* processor, int64_t id)
{
CSharedLock lock(m_sharedSection);
if (m_pRenderer)
m_pRenderer->AddProcessor(processor, id);
}
#endif
void AddOverlay(CDVDOverlay* o, double pts)
{
CSharedLock lock(m_sharedSection);
@@ -33,6 +33,7 @@
#include "FileSystem/File.h"
#include "MathUtils.h"
#include "VideoShaders/ConvolutionKernels.h"
#include "cores/dvdplayer/DVDCodecs/Video/DXVA.h"
// http://www.martinreddy.net/gfx/faqs/colorconv.faq
@@ -143,6 +144,17 @@ int CWinRenderer::NextYV12Texture()
return -1;
}
void CWinRenderer::AddProcessor(DXVA::CProcessor* processor, int64_t id)
{
int source = NextYV12Texture();
if(source < 0)
return;
m_Processor[source].Clear();
m_Processor[source].proc = processor->Acquire();
m_Processor[source].id = id;
}
int CWinRenderer::GetImage(YV12Image *image, int source, bool readonly)
{
/* take next available buffer */
@@ -218,6 +230,8 @@ void CWinRenderer::FlipPage(int source)
if(source == AUTOSOURCE)
source = NextYV12Texture();
m_Processor[m_iYV12RenderBuffer].Clear();
if( source >= 0 && source < m_NumYV12Buffers )
m_iYV12RenderBuffer = source;
else
@@ -329,7 +343,10 @@ void CWinRenderer::UnInit()
m_bFilterInitialized = false;
for(int i = 0; i < NUM_BUFFERS; i++)
{
DeleteYV12Texture(i);
m_Processor[i].Clear();
}
m_NumYV12Buffers = 0;
}
@@ -455,6 +472,12 @@ void CWinRenderer::UpdateVideoFilter()
void CWinRenderer::Render(DWORD flags)
{
if(CONF_FLAGS_FORMAT_MASK(m_flags) == CONF_FLAGS_FORMAT_DXVA)
{
CWinRenderer::RenderProcessor(flags);
return;
}
UpdateVideoFilter();
//If the GUI is active or we don't need scaling use the bilinear filter.
@@ -642,6 +665,31 @@ void CWinRenderer::RenderLowMem(CD3DEffect &effect, DWORD flags)
pD3DDevice->SetPixelShader( NULL );
}
void CWinRenderer::RenderProcessor(DWORD flags)
{
CSingleLock lock(g_graphicsContext);
RECT rect;
rect.top = m_destRect.y1;
rect.bottom = m_destRect.y2;
rect.left = m_destRect.x1;
rect.right = m_destRect.x2;
SProcessImage& image = m_Processor[m_iYV12RenderBuffer];
if(image.proc == NULL)
return;
IDirect3DSurface9* target;
if(FAILED(g_Windowing.Get3DDevice()->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &target)))
{
CLog::Log(LOGERROR, "CWinRenderer::RenderSurface - failed to get back buffer");
return;
}
image.proc->Render(rect, target, image.id);
target->Release();
}
void CWinRenderer::CreateThumbnail(CBaseTexture *texture, unsigned int width, unsigned int height)
{
CSingleLock lock(g_graphicsContext);
@@ -768,6 +816,13 @@ bool CWinRenderer::Supports(ESCALINGMETHOD method)
return false;
}
void CWinRenderer::SProcessImage::Clear()
{
SAFE_RELEASE(proc);
id = 0;
}
CPixelShaderRenderer::CPixelShaderRenderer()
: CWinRenderer()
{
@@ -788,4 +843,6 @@ void CPixelShaderRenderer::Render(DWORD flags)
CWinRenderer::Render(flags);
}
#endif
@@ -73,6 +73,8 @@
class CBaseTexture;
namespace DXVA { class CProcessor; }
struct DRAWRECT
{
float left;
@@ -115,6 +117,7 @@ class CWinRenderer : public CBaseRenderer
virtual int GetImage(YV12Image *image, int source = AUTOSOURCE, bool readonly = false);
virtual void ReleaseImage(int source, bool preserve = false);
virtual unsigned int DrawSlice(unsigned char *src[], int stride[], int w, int h, int x, int y);
virtual void AddProcessor(DXVA::CProcessor* processor, int64_t id);
virtual void FlipPage(int source);
virtual unsigned int PreInit();
virtual void UnInit();
@@ -146,6 +149,7 @@ class CWinRenderer : public CBaseRenderer
// low memory renderer (default PixelShaderRenderer)
void RenderLowMem(CD3DEffect &effect, DWORD flags);
void RenderProcessor(DWORD flags);
int m_iYV12RenderBuffer;
int m_NumYV12Buffers;
@@ -171,6 +175,24 @@ class CWinRenderer : public CBaseRenderer
YUVVIDEOBUFFERS m_YUVVideoTexture;
YUVMEMORYBUFFERS m_YUVMemoryTexture;
struct SProcessImage
{
SProcessImage()
{
proc = NULL;
id = 0;
}
~SProcessImage()
{
Clear();
}
void Clear();
DXVA::CProcessor* proc;
int64_t id;
} m_Processor[NUM_BUFFERS];
CD3DTexture m_HQKernelTexture;
CD3DEffect m_YUV2RGBEffect;
CD3DEffect m_YUV2RGBHQScalerEffect;
@@ -32,13 +32,24 @@
#define FRAME_TYPE_B 3
#define FRAME_TYPE_D 4
namespace DXVA { class CProcessor; }
// should be entirely filled by all codecs
struct DVDVideoPicture
{
double pts; // timestamp in seconds, used in the CDVDPlayer class to keep track of pts
BYTE* data[4]; // [4] = alpha channel, currently not used
int iLineSize[4]; // [4] = alpha channel, currently not used
union
{
struct {
BYTE* data[4]; // [4] = alpha channel, currently not used
int iLineSize[4]; // [4] = alpha channel, currently not used
};
struct {
DXVA::CProcessor* proc;
int64_t proc_id;
};
};
unsigned int iFlags;
@@ -59,7 +70,8 @@ struct DVDVideoPicture
FMT_VDPAU,
FMT_NV12,
FMT_UYVY, // place holder for future expansion
FMT_YUY2 //place holder for future expansion
FMT_YUY2, //place holder for future expansion
FMT_DXVA,
} format;
};
@@ -48,6 +48,9 @@
#ifdef HAVE_LIBVDPAU
#include "VDPAU.h"
#endif
#ifdef HAS_DX
#include "DXVA.h"
#endif
enum PixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx
, const PixelFormat * fmt )
@@ -79,6 +82,20 @@ enum PixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx
}
return *cur;
}
#endif
#ifdef HAS_DX
if(DXVA::CDecoder::Supports(*cur)
&& method == RENDER_METHOD_DXVA)
{
DXVA::CDecoder* dec = new DXVA::CDecoder();
if(dec->Open(avctx, *cur))
{
ctx->SetHardware(dec);
return *cur;
}
else
delete dec;
}
#endif
cur++;
}
Oops, something went wrong.

0 comments on commit a829e51

Please sign in to comment.