Video Frame From Playing Video

Oct 6, 2011 at 4:50 AM

How to capture video frame from playing video?

How to save a video frames for bmp format?

Feb 15, 2012 at 2:03 PM
Edited Feb 15, 2012 at 2:10 PM

I know this question is old but figured since I'm having the same problem maybe others are as well and a real discussion can be formed.

What type of player are you using?  I'm using the UriPlayer and have been able to get frames to a bmp file using D3DXSaveSurfaceToFile.  This isn't quite as easy as one would hope as D3DXSaveSufaceToFile is part of the d3dx9 lib and doesn't appear to be compiled into any dll.  So you'll need to grab a copy of the DirectX SDK and build a dll (or wrapper) that gives you access to the method.  I went the dll route:

// Header
#define PINVOKELIB_API __declspec(dllexport)

extern "C"
{
PINVOKELIB_API int D3DX9SaveSurfaceToFile(
        LPCWSTR                   pDestFile,
        D3DXIMAGE_FILEFORMAT      DestFormat,
        LPDIRECT3DSURFACE9        pSrcSurface,
        CONST PALETTEENTRY*       pSrcPalette,
        CONST RECT*               pSrcRect);
}



#include "StdAfx.h"
#include "D3DX9SaveSurfaceToFile.h"

// Source
#pragma comment(lib,"ole32.lib")

PINVOKELIB_API int D3DX9SaveSurfaceToFile(
        LPCWSTR                   pDestFile,
        D3DXIMAGE_FILEFORMAT      DestFormat,
        LPDIRECT3DSURFACE9        pSrcSurface,
        CONST PALETTEENTRY*       pSrcPalette,
        CONST RECT*               pSrcRect)
{
   return D3DXSaveSurfaceToFile(pDestFile, DestFormat, pSrcSurface, pSrcPalette, pSrcRect);
}

then I added (where Direct3D9.dll was my custom dll)

DllImport("Direct3D9.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void D3DX9SaveSurfaceToFile([MarshalAs(UnmanagedType.LPWStr)]String pDestFile, D3DXIMAGE_FILEFORMAT DestFormat,
   IntPtr pSrcSurface, IntPtr pSrcPallette, RECT pSrcRect);

After this you just need to make a call using the following:

string filename = "c:/bitmapSample.bmp";

IntPtr lplpSurface;
int result = GetSurface(IntPtr.Zero, 0, 0, out lplpSurface);

Direct3D.D3DX9SaveSurfaceToFile2(filename, D3DXIMAGE_FILEFORMAT.D3DXIFF_BMP,
               lplpSurface, IntPtr.Zero, null);

// GetSurface adds a reference to lplpSurface, so remove it when done. 
Marshal.Release(lplpSurface);

from somewhere within Vmr9Allocator. While this does the trick the saved bitmap looks bad, at least for me.  That's what I'm working on now. If anyone's had any experience with this I'd appreciate any help they could offer.

Feb 15, 2012 at 3:29 PM

Don't know how I didn't run across this earlier (would have saved me so much time) but this question has already been solved.  Take a look at this discussion post http://wpfmediakit.codeplex.com/discussions/225103 .  SiggiK's response solves this problem very effeciently.