public int InitializeDevice(IntPtr dwUserID, ref VMR9AllocationInfo lpAllocInfo, ref int lpNumBuffers) { int hr = 0; Debug.WriteLine(string.Format("{0}x{1} : {2} / {3} / 0x{4:x}", lpAllocInfo.dwWidth, lpAllocInfo.dwHeight, FourCCToStr(lpAllocInfo.Format), lpAllocInfo.Pool, lpAllocInfo.dwFlags)); // if format is YUV ? (note : 0x30303030 = " ") if (lpAllocInfo.Format > 0x30303030) { // Check if the hardware support format conversion from this YUV format to the RGB desktop format if (!D3D.CheckDeviceFormatConversion(creationParameters.AdapterOrdinal, creationParameters.DeviceType, (Format)lpAllocInfo.Format, adapterInfo.CurrentDisplayMode.Format)) { // If not, refuse this format! // The VMR9 will propose other formats supported by the downstream filter output pin. return(D3DERR_INVALIDCALL); } } try { IntPtr unmanagedDevice = device.ComPointer; IntPtr hMonitor = D3D.GetAdapterMonitor(adapterInfo.Adapter); // Give our Direct3D device to the VMR9 filter hr = vmrSurfaceAllocatorNotify.SetD3DDevice(unmanagedDevice, hMonitor); DsError.ThrowExceptionForHR(hr); videoSize = new Size(lpAllocInfo.dwWidth, lpAllocInfo.dwHeight); int width = 1; int height = 1; // If hardware require textures to power of two sized if ((device.Capabilities.TextureCaps & TextureCaps.Pow2) == TextureCaps.Pow2) { // Compute the ideal size while (width < lpAllocInfo.dwWidth) { width = width << 1; } while (height < lpAllocInfo.dwHeight) { height = height << 1; } // notify this change to the VMR9 filter lpAllocInfo.dwWidth = width; lpAllocInfo.dwHeight = height; } textureSize = new Size(lpAllocInfo.dwWidth, lpAllocInfo.dwHeight); // Just in case DeleteSurfaces(); // if format is YUV ? if (lpAllocInfo.Format > 0x30303030) { // An offscreen surface must be created lpAllocInfo.dwFlags |= VMR9SurfaceAllocationFlags.OffscreenSurface; // Create it videoSurface = Surface.CreateOffscreenPlain(device, lpAllocInfo.dwWidth, lpAllocInfo.dwHeight, (Format)lpAllocInfo.Format, (Pool)lpAllocInfo.Pool); // And get it unmanaged pointer unmanagedSurface = videoSurface.ComPointer; // Then create a private texture for the client application privateTexture = new Texture( device, lpAllocInfo.dwWidth, lpAllocInfo.dwHeight, 1, Usage.RenderTarget, adapterInfo.CurrentDisplayMode.Format, Pool.Default ); // Get the MipMap surface 0 for the copy (see PresentImage) privateSurface = privateTexture.GetSurfaceLevel(0); // This code path need a surface copy needCopy = true; } else { // in RGB pixel format lpAllocInfo.dwFlags |= VMR9SurfaceAllocationFlags.TextureSurface; // Simply create a texture privateTexture = new Texture( device, lpAllocInfo.dwWidth, lpAllocInfo.dwHeight, 1, Usage.RenderTarget, adapterInfo.CurrentDisplayMode.Format, Pool.Default ); // And get the MipMap surface 0 for the VMR9 filter privateSurface = privateTexture.GetSurfaceLevel(0); unmanagedSurface = privateSurface.ComPointer; // This code path don't need a surface copy. // The client appllication use the same texture the VMR9 filter use. needCopy = false; } // This allocator only support 1 buffer. // Notify the VMR9 filter lpNumBuffers = 1; } catch (SlimDXException e) { // A Direct3D error can occure : Notify it to the VMR9 filter return(e.ResultCode.Code); } catch { // Or else, notify a more general error return(E_FAIL); } // This allocation is a success return(0); }