mercoledì 29 maggio 2013

How TO: C# internal WEB CAM

Ho cercato in lungo e in largo qualcosa di UTILIZZABILE e facilmente documentabile per creare un applicazione C# che sia in grado di utilizzare la WEBcam interna..

Ammetto che non c'e' molto ( c'è tanto ma nulla come lo cercavo io ) se non qualche esempio con Wia, o librerie create da qualcuno di cui non sempre si sa la provenienza.


Questo listato .. frutto di una traduzione da VB.Net, mi ha dato un buon risultato, e ammetto che paga. E' veloce, decisamente snello non semplicissimo da leggere.


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
    {

        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 frmMain()
        {
            WM_GRAPHNOTIFY = D + 1;
            InitializeComponent();
            CaptureVideo(this);
        }



        protected void WndProc(Message m)
        {
            if (m.Msg == WM_GRAPHNOTIFY)
            {
                HandleGraphEvent();
            }

            if (VideoWindow != null)
            {
                VideoWindow.NotifyOwnerMessage(m.HWnd, m.Msg, 
                        (int)m.WParam, 
                        (int)m.LParam);
            }
            else
            {
                base.WndProc(ref m);
            }
        }

        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);            
            }
        }

        private void frmMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            closeinterfaces();
        }


        public void SetupVideoWindow()
        {
            int hr = 0;

            hr = VideoWindow.put_Owner(this.Handle);


            hr = VideoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren);

            ResizeVideoWindow();

            hr = VideoWindow.put_Visible(OABool.True);
        }


        private void frmMain_Resize(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized )
                ChangePreviewState(false);
            
            if (this.WindowState == FormWindowState.Normal )
                ChangePreviewState(true);

            ResizeVideoWindow();
        }

        public void ResizeVideoWindow()
        {
            if (VideoWindow != null) 
            {
                VideoWindow.SetWindowPosition(0, 0, this.Width, this.ClientSize.Height);
            }
        }



        public void GetInterfaces(Form 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 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 CaptureVideo(frmMain 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);

                f.SetupVideoWindow();

                rot = new DsROTEntry(this.GraphBuilder);

                hr = this.MediaControl.Run();

                this.CurrentState = PlayState.Running;

            }
            catch (Exception ex)
            {

            }
        }

        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 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;
            }
        }
    }
}

E questo è l'enumerativo.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CameraCapture.Objects
{
    public enum PlayState
    {
        Stopped,
        Paused,
        Running,
        Init
    }
}





L'unica notazione è l'aggiunta della libreria di DirectShow.


Il resto è solo divertimento .. o sperimentazione:


... E buon prò vi faccia come al solito !!


Nessun commento: