context: /****************************************************************************
  While the underlying libraries are covered by LGPL, this sample is released 
  as public domain.  It is distributed in the hope that it will be useful, but 
  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  or FITNESS FOR A PARTICULAR PURPOSE.  
  *****************************************************************************/
  
  using System;
  using System.Drawing;
  using System.Drawing.Imaging;
  using System.Collections;
  using System.Runtime.InteropServices;
  using System.Threading;
  using System.Diagnostics;
  using System.Collections.Generic;
  
  using DirectShowLib;
  
  
  namespace WebCamService
  {
      public delegate void CamImage(Image camimage);
  
      /// <summary> Summary description for MainForm. </summary>
      public class Capture : ISampleGrabberCB, IDisposable
      {
          #region Member variables
  
          /// <summary> graph builder interface. </summary>
          private IFilterGraph2 m_FilterGraph = null;
          private IMediaControl m_mediaCtrl = null;
  
          /// <summary> so we can wait for the async job to finish </summary>
          private ManualResetEvent m_PictureReady = null;
  
          /// <summary> Set by async routine when it captures an image </summary>
          private volatile bool m_bGotOne = false;
  
          /// <summary> Indicates the status of the graph </summary>
          private bool m_bRunning = false;
  
          /// <summary> Dimensions of the image, calculated once in constructor. </summary>
          private IntPtr m_handle = IntPtr.Zero;
          private int m_videoWidth;
          private int m_videoHeight;
          private int m_stride;
          public int m_Dropped = 0;
  
          public Image image = null;
          IntPtr ip = IntPtr.Zero;
  
          public event CamImage camimage;
          Thread timer1;
  
          #endregion
  
          #region API
  
          private static class NativeMethods
          {
              [DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory")]
              internal static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);
          }
  
          #endregion
  
          public Capture()
          {
          }
  
          /// <summary> Use capture with selected media caps</summary>
          public Capture(int iDeviceNum, AMMediaType media)
          {
              DsDevice[] capDevices;
  
              // Get the collection of video devices
              capDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
  
              if (iDeviceNum + 1 > capDevices.Length)
              {
                  throw new Exception("No video capture devices found at that index!");
              }
  
              try
              {
                  // Set up the capture graph
                  SetupGraph(capDevices[iDeviceNum], media);
  
                  // tell the callback to ignore new images
                  m_PictureReady = new ManualResetEvent(false);
                  m_bGotOne = true;
                  m_bRunning = false;
  
                  //timer1.Interval = 1000 / 15; // 15 fps
                  //timer1.Tick += new EventHandler(timer1_Tick);
                  //timer1.Start();
  
                  timer1 = new Thread(timer);
                  timer1.IsBackground = true;
                  timer1.Start();
  
              }
              catch
              {
                  Dispose();
                  throw;
              }
          }
  
          void timer()
          {
              DateTime last = DateTime.Now;
  
              while (true)
              {
                  try
                  {
                      System.Threading.Thread.Sleep(1000/25); // 25 fps
  
                      timer1_Tick(this, null);
  
                  }
                  catch (ThreadAbortException)
                  {
                      break;
                  }
                  catch
                  {
  
                  }
              }
          }
  
          /// <summary> release everything. </summary>
          public void Dispose()
          {
              if (timer1 != null)
                  timer1.Abort();
  
              if (camimage != null)
              {
                  camimage(null); // clear last pic
              }
              CloseInterfaces();
              if (m_PictureReady != null)
              {
                  m_PictureReady.Close();
                  m_PictureReady = null;
              }
          }
          // Destructor
          ~Capture()
          {
              Dispose();
          }
  
          public int Width
          {
              get
              {
                  return m_videoWidth;
              }
          }
          public int Height
          {
              get
              {
                  return m_videoHeight;
              }
          }
          public int Stride
          {
              get
              {
                  return m_stride;
              }
          }
          /// <summary> capture the next image </summary>
          public IntPtr GetBitMap()
          {
              if (m_handle == IntPtr.Zero)
                  m_handle = Marshal.AllocCoTaskMem(m_stride * m_videoHeight);
  
              try
              {
                  // get ready to wait for new image
                  m_PictureReady.Reset();
                  m_bGotOne = false;
  
                  // If the graph hasn't been started, start it.
                  Start();
  
                  // Start waiting
                  if ( ! m_PictureReady.WaitOne(5000, false) )
                  {
                      //throw new Exception("Timeout waiting to get picture");
                  }
                  //Pause(); //- we are effectivly pulling at 15 fps, so no need to pause
              }
              catch
              {
                  Marshal.FreeCoTaskMem(m_handle);
                  throw;
              }
  	
              // Got one
              return m_handle;
          }
          // Start the capture graph
          public void Start()
          {
              if (!m_bRunning)
              {
                  int hr = m_mediaCtrl.Run();
                  DsError.ThrowExceptionForHR( hr );
  
                  m_bRunning = true;
              }
          }
          // Pause the capture graph.
          // Running the graph takes up a lot of resources.  Pause it when it
          // isn't needed.
          public void Pause()
          {
              if (m_bRunning)
              {
                  int hr = m_mediaCtrl.Pause();
                  DsError.ThrowExceptionForHR( hr );
  
                  m_bRunning = false;
              }
          }
  
          public static List<string> getDevices()
          {
              List<string> list = new List<string>();
              DsDevice[] capDevices;
  
              // Get the collection of video devices
              capDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
  
              foreach (DsDevice dev in capDevices)
              {
                  list.Add(dev.Name);
              }
  
              return list;
          }
  
          void timer1_Tick(object sender, EventArgs e)
          {
              try
              {
  
gt:                 ip = this.GetBitMap();