MFormats SDK: WPF preview

Preview is handled by the MFPreview object. By using this object we are able to send audio to the sound card of your machine and send video frames to any receiver.


Any object that has a handle can be used as a receiver for MFPreview, e.g., Panel or Button control if you use WinForms for your application. But if you work on application based on WPF, where only the main window has а handle, there is no way to set up MFPreview object for video preview. It is fit only for audio. 


In this case we need a workaround. Because MFormats SDK is frame-based, we are able to use each frame to make our custom video preview for WPF.


For example, we will use the Image control that will receive our frames. Let's name it PreviewImage. This control has a Source property where we are able to place graphic data. So, the main task is to create an object that can be used as a Source for the Image control. We will use a BitmapSource object.


We need to get video data from a MFFrame object (that we receive from our source - MFReader or MFLive objects), create a BitmapSource and set it as a Source for the PreviewImage.


1. Getting data from a source frame:


MFFrame pFrame = null;
m_objMFReader.SourceFrameConvertedGetByTime(ref m_avProps, dblRequest, -1, out pFrame, strParams); // get a frame from a file
MFFrame mFrame;
pFrame.MFClone(out mFrame, eMFrameClone.eMFC_Video, eMFCC.eMFCC_RGB32); // make a local copy of source frame where there is only video data
M_AV_PROPS avProps;
int audioSample;
mFrame.MFAVPropsGet(out avProps, out audioSample); // get media properties of the local frame
int cbSize;
long pbVideo;
mFrame.MFVideoGetBytes(out cbSize, out pbVideo); // get access to frame's data in the memory


2. Creating a new BitmapSource:


BitmapSource source = BitmapSource.Create(avProps.vidProps.nWidth, Math.Abs(avProps.vidProps.nHeight), 96, 96, PixelFormats.Bgr32, null, new IntPtr(pbVideo), cbSize, avProps.vidProps.nRowBytes);


3. Setting the BitmapSource as a Source for our PreviewImage control and releasing frames:


PreviewImage.Source = source;
Marshal.ReleaseComObject(mFrame);
Marshal.ReleaseComObject(pFrame);


This is how to make a video preview in WPF.


As for audio, we would need to use the MFPreview object. Just initialize this object and enable audio for it.


m_objPreview = new MFPreviewClass();
m_objPreview.PreviewEnable("", 1, 0);


Once we get a frame (mFrame from the example above) we just need to put it to the m_objPreview object like this:


m_objPreview.ReceiverFramePut(pFrame, -1, "");


Join audio and video paths to make a complex preview: use the same MFFrame object to get video data, set the Source for the PreviewImage and send this MFFrame to the MFPreview object.