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."); } }
/// <summary> buffer callback, COULD BE FROM FOREIGN THREAD. </summary> 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; }
/// <summary> Set the options on the sample grabber </summary> 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)); }
下面是叠加字符的方法 /// <summary> /// buffer callback, COULD BE FROM FOREIGN THREAD. /// </summary> /// <param name="SampleTime">The sample time.</param> /// <param name="pBuffer">The p buffer.</param> /// <param name="BufferLen">The buffer len.</param> /// <returns></returns> 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; }