public void CaptureVideo()
{
int hr = 0;
IBaseFilter sourceFilter = null;
try
{
// Get DirectShow interfaces
GetInterfaces();
// Attach the filter graph to the capture graph
hr = this.captureGraphBuilder.SetFiltergraph(this.graphBuilder);
DsError.ThrowExceptionForHR(hr);
// Use the system device enumerator and class enumerator to find
// a video capture/preview device, such as a desktop USB video camera.
sourceFilter = FindCaptureDevice();
ISampleGrabber sampGrabber = new SampleGrabber() as ISampleGrabber;
hr = sampGrabber.SetOneShot(false);
hr = sampGrabber.SetBufferSamples(true);
DsError.ThrowExceptionForHR(hr);
ConfigureSampleGrabber(sampGrabber);
IBaseFilter baseGrabFlt = sampGrabber as IBaseFilter;
// Add Capture filter to our graph.
hr = this.graphBuilder.AddFilter(sourceFilter, "Video Capture");
DsError.ThrowExceptionForHR(hr);
hr = this.graphBuilder.AddFilter(baseGrabFlt, "SampleGrabber");
DsError.ThrowExceptionForHR(hr);
// Render the preview pin on the video capture filter
// Use this instead of this.graphBuilder.RenderFile
// 在这会返回一个错误,hr的值为262782.不知道如果解决.
hr = this.captureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, sourceFilter, baseGrabFlt, null);
DsError.ThrowExceptionForHR(hr);
// Now that the filter has been added to the graph and we have
// rendered its stream, we can release this reference to the filter.
Marshal.ReleaseComObject(sourceFilter);
// Set video window style and position
SetupVideoWindow();
// Add our graph to the running object table, which will allow
// the GraphEdit application to "spy" on our graph
rot = new DsROTEntry(this.graphBuilder);
// Start previewing video data
hr = this.mediaControl.Run();
DsError.ThrowExceptionForHR(hr);
// Remember current state
this.currentState = PlayState.Running;
}
catch
{
MessageBox.Show("An unrecoverable error has occurred.");
}
}
/// buffer callback, COULD BE FROM FOREIGN THREAD.
int ISampleGrabberCB.BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen)
{
Graphics g;
String s;
float sLeft;
float sTop;
SizeF d;
g = Graphics.FromImage(bitmapOverlay);
g.Clear(System.Drawing.Color.Transparent);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
// Prepare to put the specified string on the image
g.DrawRectangle(System.Drawing.Pens.Blue, 0, 0, this.Width - 1, this.Height - 1);
g.DrawRectangle(System.Drawing.Pens.Blue, 1, 1, this.Width - 3, this.Height - 3);
d = g.MeasureString(m_String, fontOverlay);
sLeft = (this.Width - d.Width) / 2;
sTop = (this.Height - d.Height) / 2;
g.DrawString(m_String, fontOverlay, System.Drawing.Brushes.Red,
sLeft, sTop, System.Drawing.StringFormat.GenericTypographic);
// Add a frame number in the bottom right
s = "Frame " + m_Count.ToString();
d = g.MeasureString(s, transparentFont);
sLeft = (this.Width - d.Width) - 10;
sTop = (this.Height - d.Height) - 10;
g.DrawString(s, transparentFont, transparentBrush, sLeft, sTop,
System.Drawing.StringFormat.GenericTypographic);
g.Dispose();
// need to flip the bitmap so it's the same orientation as the
// video buffer
bitmapOverlay.RotateFlip(RotateFlipType.RotateNoneFlipY);
// create and copy the video's buffer image to a bitmap
Bitmap v;
v = new Bitmap(this.Width , this.Height , m_stride, PixelFormat.Format32bppArgb, pBuffer);
g = Graphics.FromImage(v);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
// draw the overlay bitmap over the video's bitmap
g.DrawImage(bitmapOverlay, 0, 0, bitmapOverlay.Width, bitmapOverlay.Height);
// dispose of the various objects
g.Dispose();
v.Dispose();
// Increment frame number. Done this way, frame are zero indexed.
m_Count++;
return 0;
}
/// Set the options on the sample grabber
private void ConfigureSampleGrabber(ISampleGrabber sampGrabber)
{
AMMediaType media;
int hr;
// Set the media type to Video/RBG24
media = new AMMediaType();
media.majorType = MediaType.Video;
media.subType = MediaSubType.ARGB32;
media.formatType = FormatType.VideoInfo;
hr = sampGrabber.SetMediaType(media);
DsError.ThrowExceptionForHR(hr);
DsUtils.FreeAMMediaType(media);
media = null;
hr = sampGrabber.SetCallback(this, 1);
DsError.ThrowExceptionForHR(hr);
}
void SetupBitmap()
{
int fSize;
// scale the font size in some portion to the video image
fSize = 9 * (this.Width / 64);
bitmapOverlay = new Bitmap(this.Width , this.Height ,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
fontOverlay = new Font("Times New Roman", fSize, System.Drawing.FontStyle.Bold,
System.Drawing.GraphicsUnit.Point);
// scale the font size in some portion to the video image
fSize = 5 * (this.Width / 64);
transparentFont = new Font("Tahoma", fSize, System.Drawing.FontStyle.Bold,
System.Drawing.GraphicsUnit.Point);
transparentBrush = new SolidBrush(Color.FromArgb(96, 0, 0, 255));
}
下面是叠加字符的方法
///
/// buffer callback, COULD BE FROM FOREIGN THREAD.
///
/// The sample time.
/// The p buffer.
/// The buffer len.
///
int ISampleGrabberCB.BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen)
{
// Note that we depend on only being called once per call to Click. Otherwise
// a second call can overwrite the previous image.
Debug.Assert(BufferLen == Math.Abs(stride)*videoHeight, "Incorrect buffer length");
if (imageLogo != null || stringLogo != null)
{
//获取帧图片。
Bitmap frameImage = new Bitmap(videoWidth, videoHeight, stride, PixelFormat.Format24bppRgb, pBuffer);
Graphics g = Graphics.FromImage(frameImage);
g.SmoothingMode = SmoothingMode.AntiAlias;
//帧图片的坐标原点为左下角,GDI+的坐标原点为左上角,需要变换全局坐标系。
System.Drawing.Drawing2D.Matrix matrix = new System.Drawing.Drawing2D.Matrix(1, 0, 0, -1, 0, 0);
g.Transform = matrix;
g.TranslateTransform(0, -videoHeight);
//设置字符所处的位置。
if (imageLogo != null)
{
g.DrawImage(imageLogo, imagePosition.X, imagePosition.Y);
}
if (stringLogo != null)
{
g.DrawImage(stringLogo, stringPosition.X, stringPosition.Y);
}
//释放设备管理器和帧图片的内存。
g.Dispose();
frameImage.Dispose();
}
return 0;
}