//------------------------------------------------------------------- // TransformImage_RGB32 // // RGB-32 to RGB-32 // // Note: This function is needed to copy the image from system // memory to the Direct3D surface. //------------------------------------------------------------------- private static void TransformImage_RGB32(IntPtr pDest, int lDestStride, IntPtr pSrc, int lSrcStride, int dwWidthInPixels, int dwHeightInPixels) { MFExtern.MFCopyImage(pDest, lDestStride, pSrc, lSrcStride, dwWidthInPixels * 4, dwHeightInPixels); }
//------------------------------------------------------------------- // DrawFrame // // Draw the video frame. //------------------------------------------------------------------- public int DrawFrame(IMFMediaBuffer pCaptureDeviceBuffer, bool snap, string snapFormat = null) { if (m_convertFn == null) { return(MFError.MF_E_INVALIDREQUEST); } var hr = S_Ok; Result res; Surface pSurf; if (pDevice == null || pSwapChain == null) { return(S_Ok); } var r = new Rectangle(0, 0, width, height); // Helper object to lock the video buffer. using (var xbuffer = new VideoBufferLock(pCaptureDeviceBuffer)) { IntPtr pbScanline0; int lStride; try { hr = TestCooperativeLevel(); if (Failed(hr)) { throw new InvalidOperationException(); } // Lock the video buffer. This method returns a pointer to the first scan // line in the image, and the stride in bytes. hr = xbuffer.LockBuffer(lDefaultStride, height, out pbScanline0, out lStride); if (Failed(hr)) { throw new InvalidOperationException(); } } catch (InvalidOperationException) { return(hr); } // Get the swap-chain surface. pSurf = pSwapChain.GetBackBuffer(0); // Lock the swap-chain surface and get Graphic stream object. try { DataRectangle dr; if (offScreenSurface == null) { dr = pSurf.LockRectangle(LockFlags.NoSystemLock); // Convert the frame. This also copies it to the Direct3D surface. m_convertFn(dr.Data.DataPointer, dr.Pitch, pbScanline0, lStride, width, height); } else { var off = offScreenSurface.LockRectangle(LockFlags.NoSystemLock); MFExtern.MFCopyImage(off.Data.DataPointer, off.Pitch, pbScanline0, lStride, width * offScreenCoeffN / offScreenCoeffD, height); offScreenSurface.UnlockRectangle(); pDevice.StretchRectangle(offScreenSurface, pSurf, TextureFilter.Linear); dr = pSurf.LockRectangle(LockFlags.NoSystemLock); } if (snap) { ImageHelper.SnapShot(dr.Data.DataPointer, dr.Pitch, width, height, snapFormat); } } finally { res = pSurf.UnlockRectangle(); MFError.ThrowExceptionForHR(res.Code); } } // Color fill the back buffer. var pBB = pDevice.GetBackBuffer(0, 0); pDevice.ColorFill(pBB, DefaultBackColor); // Blit the frame. res = pDevice.StretchRectangle(pSurf, r, pBB, rcDest, TextureFilter.Linear); hr = res.Code; if (res.IsSuccess) { // Present the frame. res = pDevice.Present(); hr = res.Code; } SafeRelease(pBB); SafeRelease(pSurf); return(hr); }