|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionThis class contains methods to use the IMediaDet interface that can be found in Microsoft DirectShow. The Media Detector object, among other things, can be used to extract still pictures from several file formats including *.avi, *.wmv and some *.mpeg files. This class exposes the Using the CodeJust add a reference to JockerSoft.Media.dll in your project (or include the source code). Remember also to distribute Interop.DexterLib.dll. try
{
this.pictureBox1.Image = FrameGrabber.GetFrameFromVideo(strVideoFile, 0.2d);
}
catch (InvalidVideoFileException ex)
{
MessageBox.Show(ex.Message, "Extraction failed");
}
catch (StackOverflowException)
{
MessageBox.Show("The target image size is too big", "Extraction failed");
}
or try
{
FrameGrabber.SaveFrameFromVideo(strVideoFile, 0.2d, strBitmapFile);
}
catch (InvalidVideoFileException ex)
{
MessageBox.Show(ex.Message, "Extraction failed");
}
Here, we used the simplest of the three overloads of Points of InterestThe To extract images, there are two methods: extract them in memory (using GetBitmapBits - here
public static void SaveFrameFromVideo(string videoFile,
double percentagePosition, string outputBitmapFile,
out double streamLength, Size target)
{
if (percentagePosition > 1 || percentagePosition < 0)
throw new ArgumentOutOfRangeException("percentagePosition",
percentagePosition, "Valid range is 0.0 .. 1.0");
try
{
MediaDetClass mediaDet;
_AMMediaType mediaType;
if (openVideoStream(videoFile, out mediaDet, out mediaType))
{
streamLength = mediaDet.StreamLength;
//calculates the REAL target size of our frame
if (target == Size.Empty)
target = getVideoSize(mediaType);
else
target = scaleToFit(target, getVideoSize(mediaType));
mediaDet.WriteBitmapBits(streamLength * percentagePosition,
target.Width, target.Height, outputBitmapFile);
return;
}
}
catch (COMException ex)
{
throw new InvalidVideoFileException(getErrorMsg((uint)ex.ErrorCode), ex);
}
throw new InvalidVideoFileException("No video stream was found");
}
You'll notice that two private static bool openVideoStream(string videoFile,
out MediaDetClass mediaDetClass, out _AMMediaType aMMediaType)
{
MediaDetClass mediaDet = new MediaDetClass();
//loads file
mediaDet.Filename = videoFile;
//gets # of streams
int streamsNumber = mediaDet.OutputStreams;
//finds a video stream and grabs a frame
for (int i = 0; i < streamsNumber; i++)
{
mediaDet.CurrentStream = i;
_AMMediaType mediaType = mediaDet.StreamMediaType;
if (mediaType.majortype == JockerSoft.Media.MayorTypes.MEDIATYPE_Video)
{
mediaDetClass = mediaDet;
aMMediaType = mediaType;
return true;
}
}
mediaDetClass = null;
aMMediaType = new _AMMediaType();
return false;
}
(where private static Size getVideoSize(_AMMediaType mediaType)
{
WinStructs.VIDEOINFOHEADER videoInfo =
(WinStructs.VIDEOINFOHEADER)Marshal.PtrToStructure(mediaType.pbFormat,
typeof(WinStructs.VIDEOINFOHEADER));
return new Size(videoInfo.bmiHeader.biWidth, videoInfo.bmiHeader.biHeight);
}
Using The first part is identical to Once we have the size of the buffer, we allocate memory on the heap to receive the image (in the first version of this code, memory was allocated on the stack which is fine if the target image is small sized, but if it is big we may get a nice After this, we call public static Bitmap GetFrameFromVideo(string videoFile,
double percentagePosition, out double streamLength, Size target)
{
if (percentagePosition > 1 || percentagePosition < 0)
throw new ArgumentOutOfRangeException("percentagePosition",
percentagePosition, "Valid range is 0.0 .. 1.0");
try
{
MediaDetClass mediaDet;
_AMMediaType mediaType;
if (openVideoStream(videoFile, out mediaDet, out mediaType))
{
streamLength = mediaDet.StreamLength;
//calculates the REAL target size of our frame
if (target == Size.Empty)
target = getVideoSize(mediaType);
else
target = scaleToFit(target, getVideoSize(mediaType));
unsafe
{
Size s= GetVideoSize(videoFile);
//equal to sizeof(CommonClasses.BITMAPINFOHEADER);
int bmpinfoheaderSize = 40;
//get size for buffer
int bufferSize = (((s.Width * s.Height) * 24) / 8 ) + bmpinfoheaderSize;
//equal to mediaDet.GetBitmapBits
// (0d, ref bufferSize, ref *buffer, target.Width, target.Height);
//allocates enough memory to store the frame
IntPtr frameBuffer =
System.Runtime.InteropServices.Marshal.AllocHGlobal(bufferSize);
byte* frameBuffer2 = (byte*)frameBuffer.ToPointer();
//gets bitmap, save in frameBuffer2
mediaDet.GetBitmapBits(streamLength * percentagePosition,
ref bufferSize, ref *frameBuffer2, target.Width, target.Height);
//now in buffer2 we have a BITMAPINFOHEADER structure
//followed by the DIB bits
Bitmap bmp = new Bitmap(target.Width, target.Height, target.Width * 3,
System.Drawing.Imaging.PixelFormat.Format24bppRgb,
new IntPtr(frameBuffer2 + bmpinfoheaderSize));
bmp.RotateFlip(RotateFlipType.Rotate180FlipX);
System.Runtime.InteropServices.Marshal.FreeHGlobal(frameBuffer);
return bmp;
}
}
}
catch (COMException ex)
{
throw new InvalidVideoFileException(getErrorMsg((uint)ex.ErrorCode), ex);
}
throw new InvalidVideoFileException("No video stream was found");
}
Known Limitations
History
|
||||||||||||||||||||||