Came across an old project where I had to solve this need, andthought I’d archive it on here for search engine purposes. This canbe useful for scenarios like corporate training video directories,where you let the trainers upload videos and it automaticallycreates a thumbnail for clients to browse in a webapp, forexample.
The first thing you’ll need is an interop assembly to allow youto use the DirectShow COM objects from within .NET. You couldeither add a COM reference to your project, or better still use thecommand line tlbimp.exe framework utility tocreate the interop – the latter is preferred, as you’ll want astrongly named interop assembly, which you can accomplish byspecifying a keyfile with the tlbimp.exe /keyfile: parameter(specifying a key file that you created with thesn.exe framework utility). Add the newly createdinterop assembly as a reference in your project – barringspecifying parameters otherwise, it’ll be calledInterop.DexterLib.dll, and once referenced willappear in the references as, of course,Interop.DexterLib.
There are a couple of structures that we need to define as we’llneed them to communicate with DirectShow.
public int left;
public int top;
public int right;
public int bottom;
public element_RECT rcSource;
public element_RECT rcTarget;
public UInt32 dwbitrate;
public UInt32 dwbiterrorrate;
The following code presumes that a couple of variables exist(for instance as parameters to a function)
- videoFilename (string) – The string full pathand filename of the source video
- videoOffset (float) – How many seconds fromthe beginning of the video to pull the frame
- bitmapDestination (string) – The full path ofwhere to store the extracted file. The MediaDet object requiresthat the extracted file be stored as a file
In your extraction function, create a MediaDet instance, set the source video file path via theFilename property, and search for a video stream (there can bemultiple streams. We search for a video stream by looking for oneidentified by the GUID 05589f80-c356-11ce-bf01-00aa0055595a). Thefollowing presumes that the unit has a usingInterop.DexterLib; in it.
MediaDet mediaInt = newInterop.DexterLib.MediaDet();
mediaInt.Filename = videoFilename;
_AMMediaType oMediaType = mediaInt.StreamMediaType;
System.Guid videoHeader = new
int streamCount = mediaInt.OutputStreams;
for (int counter=0;counter< mediaInt.streamCount;counter++)
mediaInt.CurrentStream = counter;
oMediaType = mediaInt.StreamMediaType;
if (oMediaType.formattype == videoHeader)
Notice that we’re setting the CurrentStream property on eachiteration, so when a video stream is found, the MediaDet objectwill already have it selected as the active stream.
If we found a video stream in the file, retrieve the propertiesof the video frame so we can grab a full frame, and then direct itto save a frame at the specified time offset to our specifieddestination file.
element_VideoHeaderInfo *header =
Now ensure that the COM object is predictably freednow.
Note that there are pointers (scary!) used above, sothis code needs to be compiled with /unsafe. Don’tworry – It’s safe.
This technique works for pretty much any non-DRMmultimedia file that contains a video stream, for which there is aDirectShow compatible codec installed on the system.
One note about this entry – I would use thePRE element and layout the codebetter, however Radio Userland exhibits a trait thatdrives me nuts with software: It is too clever, ina way that is often very detrimental. From removingattribute formatting, to completely reformatting PRE blocks, toauto-linking links that it shouldn’t link, I seem to spend too muchtime trying to avoid it’s “helpful” logic. This seems to be thecase with too much software out there.
“It appears that you’re writing a letter…”