Custom DXVA Renderer
-
sabato 3 settembre 2011 22:20
Hi All!
I am implementing custom Renderer with DXVA support. I did not find helpfull documentation on that and need help of Experts!
I used CBaseVideoRenderer as a base class.
Renderer: CBaseVideoRenderer
IAMFilterMiscFlags
IPersistThis is what input pin exposes:
IMFGetService >> MR_VIDEO_ACCELERATION_SERVICE >> IDirect3DDeviceManager9 created and exposed
IDirectXVideoMemoryConfiguration
IMFVideoDisplayControl
IEVRVideoStreamControl
IPinConnection << this helps to fallback to software mode in case of NV12 onlyIf I use NV12 format than renderer connects successfully but after running graph DXVA falls back to software decoding.
According to MSDN YV12 is in DXVA2 mode only. So if I use YV12 in CheckMediaType() then Renderer doesn't connect to MS DTV-DVD Video Decoder and returns 0x80040217. If I replace custom renderer with EVR - everithing is OK. What can be wrong?
I'm using h264 video file.
Here is a stack trace. YV12 type has been choosen. At this point I can find 0x8004022A (VFW_E_TYPE_NOT_ACCEPTED) error code. It returns with error code after call to CVIDEOfilter::ConfigureDXVA2Accelerator() which returns 0x1 (I suppose TRUE or S_FALSE).
> msmpeg2vdec.dll!CVIDEOfilter::CompleteConnect() + 0x1019 bytes
msmpeg2vdec.dll!CDSopin::CompleteConnect() + 0x1f8 bytes
msmpeg2vdec.dll!CBasePin::AttemptConnection() + 0x62 bytes
msmpeg2vdec.dll!CBasePin::TryMediaTypes() + 0x68 bytes
msmpeg2vdec.dll!CBasePin::AgreeMediaType() + 0x73 bytes
msmpeg2vdec.dll!CBasePin::Connect() + 0x64 bytes
quartz.dll!CFilterGraph::ConnectDirectInternal() + 0x83 bytes
quartz.dll!CFilterGraph::ConnectRecursively() + 0x2c bytes
quartz.dll!CFilterGraph::ConnectInternal() + 0xde bytes
quartz.dll!CFilterGraph::Connect() + 0x17 bytes
----------------------------------------------------------------------------------------
This is a stack stack trace when using NV12 format. DXVA2 changes to software decoding. Why?
> quartz.dll!DoReconnect() + 0x5e bytes
quartz.dll!CGraphConfig::Reconnect() + 0x136 bytes
msmpeg2vdec.dll!CVIDEOfilter::PerformReconnect() + 0x461 bytes
msmpeg2vdec.dll!CVIDEOfilter::ChangeDXVA2Software() + 0xd2 bytes
msmpeg2vdec.dll!CH264DecoderDXVA::ChangeDXVA2Software() + 0x39 bytes
msmpeg2vdec.dll!g_callbackChangeDXVA2Software() + 0x1a bytes
msmpeg2vdec.dll!_H264DecodeGetOutputInfo@12() + 0x9c bytes
msmpeg2vdec.dll!5c56449d()
Additionally I tried ffdshow DXVA video decoder and it seems it works fine with my Renderer.
I can post source code if needed...Thanks in advance!
- Modificato Evgeniy86 sabato 3 settembre 2011 23:13
- Modificato Evgeniy86 domenica 4 settembre 2011 07:29
- Modificato Evgeniy86 domenica 4 settembre 2011 07:29
- Modificato Evgeniy86 domenica 4 settembre 2011 07:30
- Modificato Evgeniy86 domenica 4 settembre 2011 07:31
- Modificato Evgeniy86 domenica 4 settembre 2011 23:10
- Modificato Evgeniy86 domenica 4 settembre 2011 23:11
Tutte le risposte
-
martedì 13 settembre 2011 08:17Any ideas???
Jhony -
giovedì 15 settembre 2011 08:40
Anyone? I need to know why msmpeg2vdec.dll!g_callbackChangeDXVA2Software() is called? What the reason? Why MS DTV-DVD Video Decoder falls back to software decoding?
Jhony -
sabato 17 settembre 2011 00:14
I've done this successfully in C# before and it works fine for msmpeg2vdec DXVA2, NV12 media type from the decoder.. my only thought is maybe your Direct3DDeviceManager9 hasn't been initialized before connect or NV12 MediaType is slightly off.Here's what I'm doing, excuse the C# (this is probably useless but maybe it'll spark an idea);#region IDirectXVideoMemoryConfiguration Members public HRESULT GetAvailableSurfaceTypeByIndex(int dwTypeIndex, out DXVA2_SurfaceType pdwType) { pdwType = DXVA2_SurfaceType.DXVA2_SurfaceType_DecoderRenderTarget; return dwTypeIndex == 0 ? HRESULT.S_OK : HRESULT.MF_E_NO_MORE_TYPES; } public HRESULT SetSurfaceType(DXVA2_SurfaceType dwType) { return HRESULT.S_OK; } #endregion<br/><br/>#region IMFGetService Members public HRESULT GetService(Guid guidService, Guid riid, out IntPtr ppvObject) { ppvObject = IntPtr.Zero; if (guidService == MFHelper.MR_VIDEO_ACCELERATION_SERVICE && Feed.Demux.DeviceManager != null) { _IsDxva2Decoding = true; if (riid == IID_IDirectXVideoMemoryConfiguration) { ppvObject = Marshal.GetComInterfaceForObject(this, typeof(IDirectXVideoMemoryConfiguration)); Marshal.AddRef(ppvObject); return HRESULT.S_OK; } else if (riid == IID_IDirect3DDeviceManager9) { Marshal.QueryInterface(Feed.Demux.DeviceManager.PtrIUnknown, ref riid, out ppvObject); Marshal.AddRef(ppvObject); return HRESULT.S_OK; } else { Debug.Assert(false, "Super freaky MR_VIDEO_ACCELERATION_SERVICE riid " + riid); } } return HRESULT.MF_E_UNSUPPORTED_SERVICE; } #endregion
and here's the d3d setup (again, please excuse the odd-ball managed classes, it was an XNA type of affair):class Demux { ...<br/> public Demux(GraphicsDevice device) { Device = new Direct3DDevice9(device.GetPtr()); uint token; IntPtr p; Debug.Assert(MFHelper.DXVA2CreateDirect3DDeviceManager9(out token, out p) == HRESULT.S_OK, "DXVA2CreateDirect3DDeviceManager9 failed"); DeviceManager = new Direct3DDeviceManager9(p); DeviceManager.ResetToken = token; Debug.Assert(DeviceManager.ResetDevice(device.GetPtr(), DeviceManager.ResetToken) == HRESULT.S_OK, "ResetDevice failed"); } <br/>... }
.. you're probably already doing all that. Another thing is I take the MediaType directly from the ms dtv video decoder output (QueryMediaTypes and scan for it's copy of NV12) maybe there's a sneaky field value (sampleSize/fixedSampleSizes for instance) that it's not expecting. I'm also doing decoderOutputPin.Connect(.., nv12type) directly.
That's about all I can think of, probably useless. Pretty maddening these types of issues. Hope you manage to nail it anyway -- good luck. -
martedì 20 settembre 2011 16:06Thanks Sichbo, I will try the thing with media types!
Jhony -
lunedì 13 febbraio 2012 11:28Hi Evgeniy86. Please could you send me an example of DXVA renderer? Or could you send me a link where is any tutorial of DXVA renderer? Thank you very much.
talbot
-
domenica 4 marzo 2012 19:43
Talbot,
if you need DXVA to capture RAW frames I suggest you to get acquainted with Media Foundation and MFSourceReader object. It simplifies all the stuff a lot. This is a kind of samples grabber.
BTW, nVidia and AMD APUs are able to handle fast copy from video memory to system memory (only in case of HW decode). Intel's quick sync technology available on i3/i5/i7 CPUs need use of SSE4 instructions to perform fast copy. Take a look at http://software.intel.com/en-us/articles/copying-accelerated-video-decode-frame-buffers/
Jhony

