using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; namespace CameraCapture.Objects { public class HandledObject { public int width; public int height; public Size clientSize; public IntPtr handle; } }
Questo primo oggetto mi serve come tramite per la gestiione dell'Handle... quasi mi sembra di tornare ai fasti delle API a 32bit.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace CameraCapture.Objects { public enum PlayState { Stopped, Paused, Running, Init } }
Questo è rimasto invariato.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using DirectShowLib; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; namespace CameraCapture.Objects { public class DirectShowWrapper { public int D = Convert.ToInt32("0X8000", 16); public int WM_GRAPHNOTIFY = 0; public IVideoWindow VideoWindow = null; public IMediaControl MediaControl = null; public IMediaEventEx MediaEventEx = null; public IGraphBuilder GraphBuilder = null; public ICaptureGraphBuilder2 CaptureGraphBuilder = null; public DsROTEntry rot = null; private PlayState CurrentState = PlayState.Stopped; public DirectShowWrapper() { WM_GRAPHNOTIFY = D + 1; } public void GetInterfaces(HandledObject f) { int hr = 0; this.GraphBuilder = (IGraphBuilder)(new FilterGraph()); this.CaptureGraphBuilder = (ICaptureGraphBuilder2)(new CaptureGraphBuilder2()); this.MediaControl = (IMediaControl)(this.GraphBuilder); this.VideoWindow = (IVideoWindow)(this.GraphBuilder); this.MediaEventEx = (IMediaEventEx)(this.GraphBuilder); hr = this.MediaEventEx.SetNotifyWindow(f.handle, WM_GRAPHNOTIFY, IntPtr.Zero); } public void CaptureVideo(HandledObject f) { int hr = 0; IBaseFilter sourceFilter = null; try { GetInterfaces(f); hr = this.CaptureGraphBuilder.SetFiltergraph(this.GraphBuilder); sourceFilter = FindCaptureDevice(); hr = this.GraphBuilder.AddFilter(sourceFilter, "Video Capture"); hr = this.CaptureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, sourceFilter, null, null); Marshal.ReleaseComObject(sourceFilter); SetupVideoWindow(f); rot = new DsROTEntry(this.GraphBuilder); hr = this.MediaControl.Run(); this.CurrentState = PlayState.Running; } catch (Exception ex) { } } public void SetupVideoWindow(HandledObject f) { int hr = 0; hr = VideoWindow.put_Owner(f.handle); hr = VideoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren); ResizeVideoWindow(f); hr = VideoWindow.put_Visible(OABool.True); } public void closeinterfaces() { if (this.MediaControl != null) { this.MediaControl.StopWhenReady(); } this.CurrentState = PlayState.Stopped; if (this.MediaEventEx != null) { this.MediaEventEx.SetNotifyWindow(IntPtr.Zero, WM_GRAPHNOTIFY, IntPtr.Zero); } if (this.VideoWindow != null) { this.VideoWindow.put_Visible(OABool.False); this.VideoWindow.put_Owner(IntPtr.Zero); } if (rot != null) { rot.Dispose(); rot = null; } Marshal.ReleaseComObject(this.MediaControl); Marshal.ReleaseComObject(this.MediaEventEx); Marshal.ReleaseComObject(this.VideoWindow); Marshal.ReleaseComObject(this.GraphBuilder); Marshal.ReleaseComObject(this.CaptureGraphBuilder); this.MediaControl = null; this.MediaEventEx = null; this.VideoWindow = null; this.CaptureGraphBuilder = null; this.GraphBuilder = null; } public void HandleGraphEvent() { int hr = 0; EventCode evCode; int evParam1; int evParam2; if (MediaEventEx == null) { return; } while (MediaEventEx.GetEvent(out evCode, out evParam1, out evParam2, 0) == 0) { hr = MediaEventEx.FreeEventParams(evCode, evParam1, evParam2); } } public IBaseFilter FindCaptureDevice() { int hr = 0; IEnumMoniker IclassEnum; System.Runtime.InteropServices.UCOMIEnumMoniker classEnum; IMoniker[] moniker = new IMoniker[1]; Object source = null; ICreateDevEnum devEnum = (ICreateDevEnum)(new CreateDevEnum()); hr = devEnum.CreateClassEnumerator(FilterCategory.VideoInputDevice, out classEnum, 0); IclassEnum = (IEnumMoniker)(classEnum); Marshal.ReleaseComObject(devEnum); if (classEnum == null) { throw new ApplicationException("No device video on board."); } if (IclassEnum.Next(moniker.Length, moniker, IntPtr.Zero) == 0) { Guid iid = typeof(IBaseFilter).GUID; moniker[0].BindToObject(null, null, iid, out source); } else { throw new ApplicationException("Unable to access video capture device!"); } Marshal.ReleaseComObject(moniker[0]); Marshal.ReleaseComObject(classEnum); return (IBaseFilter)(source); } public void ChangePreviewState(bool showVideo) { int hr = 0; if (this.MediaControl == null) { return; } if (showVideo == true) { if (this.CurrentState != PlayState.Running) { hr = this.MediaControl.Run(); this.CurrentState = PlayState.Running; } } else { hr = this.MediaControl.StopWhenReady(); this.CurrentState = PlayState.Stopped; } } public void ResizeVideoWindow(HandledObject ho) { if (VideoWindow != null) { VideoWindow.SetWindowPosition(0, 0, ho.width, ho.clientSize.Height); } } } }
Questo è l'oggetto che sostituisce e wrappa tutte le attività lasciando libero e snello il form.
Il motivo è semplice, in questo modo posso aggiungere una picturebox o qualsiasi altro oggetto per cui sussistano dimensioni e handle, mapparlo nell'oggetto di scambio, e gestire così la camera.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using DirectShowLib; using System.Windows.Forms; using CameraCapture.Objects; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; namespace CameraCapture { public partial class frmMain : Form { DirectShowWrapper dsw = new DirectShowWrapper(); HandledObject ho = new HandledObject(); public frmMain() { InitializeComponent(); ho.height = this.Height; ho.width = this.Width; ho.handle = this.Handle; ho.clientSize = this.ClientSize; dsw.CaptureVideo(ho); } protected void WndProc(Message m) { if (m.Msg == dsw.WM_GRAPHNOTIFY) { dsw.HandleGraphEvent(); } if (dsw.VideoWindow != null) { dsw.VideoWindow.NotifyOwnerMessage( m.HWnd, m.Msg, (int)m.WParam, (int)m.LParam); } else { base.WndProc(ref m); } } private void frmMain_Resize(object sender, EventArgs e) { if (this.WindowState == FormWindowState.Minimized) dsw.ChangePreviewState(false); if (this.WindowState == FormWindowState.Normal) dsw.ChangePreviewState(true); ho.height = this.Height; ho.width = this.Width; ho.handle = this.Handle; ho.clientSize = this.ClientSize; dsw.ResizeVideoWindow(ho); } public void frmMain_FormClosed(object sender, FormClosedEventArgs e) { dsw.closeinterfaces(); } } }
Orbene questo è quanto rimane del form ...ora la situazione è sicuramente molto più gestibile e pulita.
Nessun commento:
Posta un commento