Beispiel #1
0
    /// <summary>
    /// 工作线程
    /// </summary>
    private void WorkerThread()
    {
      VideoSourceFinishedReasonType reasonToStop = VideoSourceFinishedReasonType.StoppedByUser;

      // grabber
      Grabber grabber = new Grabber(this);

      // objects
      object graphObject = null;
      object grabberObject = null;

      // interfaces
      IGraphBuilder graph = null;
      IBaseFilter sourceBase = null;
      IBaseFilter grabberBase = null;
      ISampleGrabber sampleGrabber = null;
      IMediaControl mediaControl = null;
      IMediaEventEx mediaEvent = null;

      try
      {
        // get type for filter graph
        Type type = Type.GetTypeFromCLSID(Clsid.FilterGraph);
        if (type == null)
          throw new VideoSourceException("Failed creating filter graph");

        // create filter graph
        graphObject = Activator.CreateInstance(type);
        graph = (IGraphBuilder)graphObject;

        // create source device's object
        graph.AddSourceFilter(Source, "source", out sourceBase);
        if (sourceBase == null)
          throw new VideoSourceException("Failed creating source filter");

        // get type for sample grabber
        type = Type.GetTypeFromCLSID(Clsid.SampleGrabber);
        if (type == null)
          throw new VideoSourceException("Failed creating sample grabber");

        // create sample grabber
        grabberObject = Activator.CreateInstance(type);
        sampleGrabber = (ISampleGrabber)grabberObject;
        grabberBase = (IBaseFilter)grabberObject;

        // add grabber filters to graph
        graph.AddFilter(grabberBase, "grabber");

        // set media type
        AMMediaType mediaType = new AMMediaType();
        mediaType.MajorType = MediaType.Video;
        mediaType.SubType = MediaSubType.RGB24;
        sampleGrabber.SetMediaType(mediaType);

        // connect pins
        int pinToTry = 0;

        IPin inPin = PinHelper.GetInPin(grabberBase, 0);
        IPin outPin = null;

        // find output pin acceptable by sample grabber
        while (true)
        {
          outPin = PinHelper.GetOutPin(sourceBase, pinToTry);

          if (outPin == null)
          {
            Marshal.ReleaseComObject(inPin);
            throw new VideoSourceException("Cannot find acceptable output video pin in the given source");
          }

          if (graph.Connect(outPin, inPin) < 0)
          {
            Marshal.ReleaseComObject(outPin);
            outPin = null;
            pinToTry++;
          }
          else
          {
            break;
          }
        }

        Marshal.ReleaseComObject(outPin);
        Marshal.ReleaseComObject(inPin);

        // get media type
        if (sampleGrabber.GetConnectedMediaType(mediaType) == 0)
        {
          VideoInfoHeader vih = (VideoInfoHeader)Marshal.PtrToStructure(mediaType.FormatPtr, typeof(VideoInfoHeader));

          grabber.Width = vih.BmiHeader.Width;
          grabber.Height = vih.BmiHeader.Height;
          mediaType.Dispose();
        }

        // let's do rendering, if we don't need to prevent freezing
        if (!PreventFreezing)
        {
          // render pin
          graph.Render(PinHelper.GetOutPin(grabberBase, 0));

          // configure video window
          IVideoWindow window = (IVideoWindow)graphObject;
          window.put_AutoShow(false);
          window = null;
        }

        // configure sample grabber
        sampleGrabber.SetBufferSamples(false);
        sampleGrabber.SetOneShot(false);
        sampleGrabber.SetCallback(grabber, 1);

        // disable clock, if someone requested it
        if (!ReferenceClockEnabled)
        {
          IMediaFilter mediaFilter = (IMediaFilter)graphObject;
          mediaFilter.SetSyncSource(null);
        }

        // get media control
        mediaControl = (IMediaControl)graphObject;

        // get media events' interface
        mediaEvent = (IMediaEventEx)graphObject;
        IntPtr p1, p2;
        DsEvCode code;

        // run
        mediaControl.Run();

        while (!stopEvent.WaitOne(0, false))
        {
          Thread.Sleep(100);

          if (mediaEvent != null)
          {
            if (mediaEvent.GetEvent(out code, out p1, out p2, 0) >= 0)
            {
              mediaEvent.FreeEventParams(code, p1, p2);

              if (code == DsEvCode.Complete)
              {
                reasonToStop = VideoSourceFinishedReasonType.EndOfStreamReached;
                break;
              }
            }
          }
        }

        // stop
        mediaControl.Stop();
      }
      catch (Exception ex)
      {
        // provide information to clients
        if (VideoSourceException != null)
        {
          VideoSourceException(this, new VideoSourceExceptionEventArgs(ex.Message));
        }
      }
      finally
      {
        // release all objects
        graph = null;
        grabberBase = null;
        sampleGrabber = null;
        mediaControl = null;
        mediaEvent = null;

        if (graphObject != null)
        {
          Marshal.ReleaseComObject(graphObject);
          graphObject = null;
        }
        if (sourceBase != null)
        {
          Marshal.ReleaseComObject(sourceBase);
          sourceBase = null;
        }
        if (grabberObject != null)
        {
          Marshal.ReleaseComObject(grabberObject);
          grabberObject = null;
        }
      }

      if (VideoSourceFinished != null)
      {
        VideoSourceFinished(this, new VideoSourceFinishedEventArgs(reasonToStop));
      }
    }
    private void WorkerThread(bool runGraph)
    {
      VideoSourceFinishedReasonType reasonToStop = VideoSourceFinishedReasonType.StoppedByUser;
      bool isSapshotSupported = false;

      // grabber
      Grabber videoGrabber = new Grabber(this, false);
      Grabber snapshotGrabber = new Grabber(this, true);

      // objects
      object captureGraphObject = null;
      object graphObject = null;
      object videoGrabberObject = null;
      object snapshotGrabberObject = null;

      // interfaces
      ICaptureGraphBuilder2 captureGraph = null;
      IFilterGraph2 graph = null;
      IBaseFilter sourceBase = null;
      IBaseFilter videoGrabberBase = null;
      IBaseFilter snapshotGrabberBase = null;
      ISampleGrabber videoSampleGrabber = null;
      ISampleGrabber snapshotSampleGrabber = null;
      IMediaControl mediaControl = null;
      IAMVideoControl videoControl = null;
      IMediaEventEx mediaEvent = null;
      IPin pinStillImage = null;

      try
      {
        // get type of capture graph builder
        Type type = Type.GetTypeFromCLSID(Clsid.CaptureGraphBuilder2);
        if (type == null)
          throw new ApplicationException("Failed creating capture graph builder");

        // create capture graph builder
        captureGraphObject = Activator.CreateInstance(type);
        captureGraph = (ICaptureGraphBuilder2)captureGraphObject;

        // get type of filter graph
        type = Type.GetTypeFromCLSID(Clsid.FilterGraph);
        if (type == null)
          throw new ApplicationException("Failed creating filter graph");

        // create filter graph
        graphObject = Activator.CreateInstance(type);
        graph = (IFilterGraph2)graphObject;

        // set filter graph to the capture graph builder
        captureGraph.SetFiltergraph((IGraphBuilder)graph);

        // create source device's object
        sourceObject = FilterInfo.CreateFilter(deviceMoniker);
        if (sourceObject == null)
          throw new ApplicationException("Failed creating device object for moniker");

        // get base filter interface of source device
        sourceBase = (IBaseFilter)sourceObject;

        // get video control interface of the device
        try
        {
          videoControl = (IAMVideoControl)sourceObject;
        }
        catch
        {
          // some camera drivers may not support IAMVideoControl interface
        }

        // get type of sample grabber
        type = Type.GetTypeFromCLSID(Clsid.SampleGrabber);
        if (type == null)
          throw new ApplicationException("Failed creating sample grabber");

        // create sample grabber used for video capture
        videoGrabberObject = Activator.CreateInstance(type);
        videoSampleGrabber = (ISampleGrabber)videoGrabberObject;
        videoGrabberBase = (IBaseFilter)videoGrabberObject;
        // create sample grabber used for snapshot capture
        snapshotGrabberObject = Activator.CreateInstance(type);
        snapshotSampleGrabber = (ISampleGrabber)snapshotGrabberObject;
        snapshotGrabberBase = (IBaseFilter)snapshotGrabberObject;

        // add source and grabber filters to graph
        graph.AddFilter(sourceBase, "source");
        graph.AddFilter(videoGrabberBase, "grabber_video");
        graph.AddFilter(snapshotGrabberBase, "grabber_snapshot");

        // set media type
        AMMediaType mediaType = new AMMediaType();
        mediaType.MajorType = MediaType.Video;
        mediaType.SubType = MediaSubType.RGB24;

        videoSampleGrabber.SetMediaType(mediaType);
        snapshotSampleGrabber.SetMediaType(mediaType);

        if (videoControl != null)
        {
          // find Still Image output pin of the vedio device
          captureGraph.FindPin(sourceObject, PinDirection.Output,
              PinCategory.StillImage, MediaType.Video, false, 0, out pinStillImage);
          // check if it support trigger mode
          if (pinStillImage != null)
          {
            VideoControlFlags caps;
            videoControl.GetCaps(pinStillImage, out caps);
            isSapshotSupported = ((caps & VideoControlFlags.ExternalTriggerEnable) != 0);
          }
        }

        // configure video sample grabber
        videoSampleGrabber.SetBufferSamples(false);
        videoSampleGrabber.SetOneShot(false);
        videoSampleGrabber.SetCallback(videoGrabber, 1);

        // configure snapshot sample grabber
        snapshotSampleGrabber.SetBufferSamples(true);
        snapshotSampleGrabber.SetOneShot(false);
        snapshotSampleGrabber.SetCallback(snapshotGrabber, 1);

        // configure pins
        GetPinCapabilitiesAndConfigureSizeAndRate(captureGraph, sourceBase,
            PinCategory.Capture, desiredFrameSize, desiredFrameRate, ref videoCapabilities);
        if (isSapshotSupported)
        {
          GetPinCapabilitiesAndConfigureSizeAndRate(captureGraph, sourceBase,
              PinCategory.StillImage, desiredSnapshotSize, 0, ref snapshotCapabilities);
        }
        else
        {
          snapshotCapabilities = new VideoCapabilities[0];
        }

        if (runGraph)
        {
          // render capture pin
          captureGraph.RenderStream(PinCategory.Capture, MediaType.Video, sourceBase, null, videoGrabberBase);

          if (videoSampleGrabber.GetConnectedMediaType(mediaType) == 0)
          {
            VideoInfoHeader vih = (VideoInfoHeader)Marshal.PtrToStructure(mediaType.FormatPtr, typeof(VideoInfoHeader));

            videoGrabber.Width = vih.BmiHeader.Width;
            videoGrabber.Height = vih.BmiHeader.Height;

            mediaType.Dispose();
          }

          if ((isSapshotSupported) && (provideSnapshots))
          {
            // render snapshot pin
            captureGraph.RenderStream(PinCategory.StillImage, MediaType.Video, sourceBase, null, snapshotGrabberBase);

            if (snapshotSampleGrabber.GetConnectedMediaType(mediaType) == 0)
            {
              VideoInfoHeader vih = (VideoInfoHeader)Marshal.PtrToStructure(mediaType.FormatPtr, typeof(VideoInfoHeader));

              snapshotGrabber.Width = vih.BmiHeader.Width;
              snapshotGrabber.Height = vih.BmiHeader.Height;

              mediaType.Dispose();
            }
          }

          // get media control
          mediaControl = (IMediaControl)graphObject;

          // get media events' interface
          mediaEvent = (IMediaEventEx)graphObject;
          IntPtr p1, p2;
          DsEvCode code;

          // run
          mediaControl.Run();

          if ((isSapshotSupported) && (provideSnapshots))
          {
            startTime = DateTime.Now;
            videoControl.SetMode(pinStillImage, VideoControlFlags.ExternalTriggerEnable);
          }

          while (!stopEvent.WaitOne(0, false))
          {
            Thread.Sleep(100);

            if (mediaEvent != null)
            {
              if (mediaEvent.GetEvent(out code, out p1, out p2, 0) >= 0)
              {
                mediaEvent.FreeEventParams(code, p1, p2);

                if (code == DsEvCode.DeviceLost)
                {
                  reasonToStop = VideoSourceFinishedReasonType.DeviceLost;
                  break;
                }
              }
            }

            if (needToSimulateTrigger)
            {
              needToSimulateTrigger = false;

              if ((isSapshotSupported) && (provideSnapshots))
              {
                videoControl.SetMode(pinStillImage, VideoControlFlags.Trigger);
              }
            }

            if (needToDisplayPropertyPage)
            {
              needToDisplayPropertyPage = false;

              try
              {
                // retrieve ISpecifyPropertyPages interface of the device
                ISpecifyPropertyPages pPropPages = (ISpecifyPropertyPages)sourceObject;

                // get property pages from the property bag
                CAUUID caGUID;
                pPropPages.GetPages(out caGUID);

                // get filter info
                FilterInfo filterInfo = new FilterInfo(deviceMoniker);

                // create and display the OlePropertyFrame
                Win32.OleCreatePropertyFrame(parentWindowForPropertyPage, 0, 0, filterInfo.Name, 1, ref sourceObject, caGUID.cElems, caGUID.pElems, 0, 0, IntPtr.Zero);

                // release COM objects
                Marshal.FreeCoTaskMem(caGUID.pElems);
              }
              catch
              {
              }
            }
          }
          mediaControl.Stop();
        }
      }
      catch (Exception exception)
      {
        // provide information to clients
        if (VideoSourceException != null)
        {
          VideoSourceException(this, new VideoSourceExceptionEventArgs(exception.Message));
        }
      }
      finally
      {
        // release all objects
        captureGraph = null;
        graph = null;
        sourceBase = null;
        mediaControl = null;
        videoControl = null;
        mediaEvent = null;
        pinStillImage = null;

        videoGrabberBase = null;
        snapshotGrabberBase = null;
        videoSampleGrabber = null;
        snapshotSampleGrabber = null;

        if (graphObject != null)
        {
          Marshal.ReleaseComObject(graphObject);
          graphObject = null;
        }
        if (sourceObject != null)
        {
          Marshal.ReleaseComObject(sourceObject);
          sourceObject = null;
        }
        if (videoGrabberObject != null)
        {
          Marshal.ReleaseComObject(videoGrabberObject);
          videoGrabberObject = null;
        }
        if (snapshotGrabberObject != null)
        {
          Marshal.ReleaseComObject(snapshotGrabberObject);
          snapshotGrabberObject = null;
        }
        if (captureGraphObject != null)
        {
          Marshal.ReleaseComObject(captureGraphObject);
          captureGraphObject = null;
        }
      }

      if (VideoSourceFinished != null)
      {
        VideoSourceFinished(this, new VideoSourceFinishedEventArgs(reasonToStop));
      }
    }