DirectShowLib-2005 easycap USB 2.0与sony handycam图像捕获问题接口

时间:2013-04-17 05:11:27

标签: c# video directshow video-capture directshow.net

我有一个附加到Easycap USB 2.0的sony handycam,我正在使用DirectShowLib-2005进行图像捕获。 Capture类的源代码如下:

    public Capture(int iDeviceNum, int iWidth, int iHeight, short iBPP, Control hControl)
    {
        Pic_Control = hControl;

        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], iWidth, iHeight, iBPP, hControl);

            // tell the callback to ignore new images
            m_PictureReady = new ManualResetEvent(false);
        }
        catch
        {
            Dispose();
            throw;
        }
    }


    private void SetupGraph(DsDevice dev, int iWidth, int iHeight, short iBPP, Control hControl)
    {
        int hr;

        ISampleGrabber sampGrabber = null;
        IBaseFilter capFilter = null;
        IPin pCaptureOut = null;
        IPin pSampleIn = null;
        IPin pRenderIn = null;

        // Get the graphbuilder object
        m_FilterGraph = new FilterGraph() as IFilterGraph2;

        try
        {

            m_rot = new DsROTEntry(m_FilterGraph);

            // add the video input device
            hr = m_FilterGraph.AddSourceFilterForMoniker(dev.Mon, null, dev.Name, out capFilter);
            DsError.ThrowExceptionForHR( hr );

            // Find the still pin
            m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Still, 0);

            // Didn't find one.  Is there a preview pin?
            if (m_pinStill == null)
            {
                m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Preview, 0);
            }

            // Still haven't found one.  Need to put a splitter in so we have
            // one stream to capture the bitmap from, and one to display.  Ok, we
            // don't *have* to do it that way, but we are going to anyway.
            if (m_pinStill == null)
            {
                IPin pRaw = null;
                IPin pSmart = null;

                // There is no still pin
                m_VidControl = null;

                // Add a splitter
                IBaseFilter iSmartTee = (IBaseFilter)new SmartTee();

                try
                {
                    hr = m_FilterGraph.AddFilter(iSmartTee, "SmartTee");
                    DsError.ThrowExceptionForHR( hr );

                    // Find the find the capture pin from the video device and the
                    // input pin for the splitter, and connnect them
                    pRaw = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0);
                    pSmart = DsFindPin.ByDirection(iSmartTee, PinDirection.Input, 0);

                    hr = m_FilterGraph.Connect(pRaw, pSmart);
                    DsError.ThrowExceptionForHR( hr );

                    // Now set the capture and still pins (from the splitter)
                    m_pinStill = DsFindPin.ByName(iSmartTee, "Preview");
                    pCaptureOut = DsFindPin.ByName(iSmartTee, "Capture");

                    // If any of the default config items are set, perform the config
                    // on the actual video device (rather than the splitter)
                    if (iHeight + iWidth + iBPP > 0)
                    {
                        SetConfigParms(pRaw, iWidth, iHeight, iBPP);
                    }
                }
                finally
                {
                    if (pRaw != null)
                    {
                        Marshal.ReleaseComObject(pRaw);
                    }
                    if (pRaw != pSmart)
                    {
                        Marshal.ReleaseComObject(pSmart);
                    }
                    if (pRaw != iSmartTee)
                    {
                        Marshal.ReleaseComObject(iSmartTee);
                    }
                }
            }
            else
            {
                // Get a control pointer (used in Click())
                m_VidControl = capFilter as IAMVideoControl;

                pCaptureOut = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0);

                // If any of the default config items are set
                if (iHeight + iWidth + iBPP > 0)
                {
                    SetConfigParms(m_pinStill, iWidth, iHeight, iBPP);
                }
            }

            // Get the SampleGrabber interface
            sampGrabber = new SampleGrabber() as ISampleGrabber;

            // Configure the sample grabber
            IBaseFilter baseGrabFlt = sampGrabber as IBaseFilter;
            ConfigureSampleGrabber(sampGrabber);
            pSampleIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0);

            // Get the default video renderer
            IBaseFilter pRenderer = new VideoRendererDefault() as IBaseFilter;
            hr = m_FilterGraph.AddFilter(pRenderer, "Renderer");
            DsError.ThrowExceptionForHR( hr );

            pRenderIn = DsFindPin.ByDirection(pRenderer, PinDirection.Input, 0);

            // Add the sample grabber to the graph
            hr = m_FilterGraph.AddFilter( baseGrabFlt, "Ds.NET Grabber" );
            DsError.ThrowExceptionForHR( hr );

            if (m_VidControl == null)
            {
                // Connect the Still pin to the sample grabber
                hr = m_FilterGraph.Connect(m_pinStill, pSampleIn);
                DsError.ThrowExceptionForHR( hr );

                // Connect the capture pin to the renderer
                hr = m_FilterGraph.Connect(pCaptureOut, pRenderIn);
                DsError.ThrowExceptionForHR( hr );
            }
            else
            {
                // Connect the capture pin to the renderer
                hr = m_FilterGraph.Connect(pCaptureOut, pRenderIn);
                DsError.ThrowExceptionForHR( hr );

                // Connect the Still pin to the sample grabber
                hr = m_FilterGraph.Connect(m_pinStill, pSampleIn);
                DsError.ThrowExceptionForHR( hr );
            }

            // Learn the video properties
            SaveSizeInfo(sampGrabber);
            ConfigVideoWindow(hControl);

            // Start the graph
            IMediaControl mediaCtrl = m_FilterGraph as IMediaControl;
            hr = mediaCtrl.Run();
            DsError.ThrowExceptionForHR( hr );
        }
        finally
        {
            if (sampGrabber != null)
            {
                Marshal.ReleaseComObject(sampGrabber);
                sampGrabber = null;
            }
            if (pCaptureOut != null)
            {
                Marshal.ReleaseComObject(pCaptureOut);
                pCaptureOut = null;
            }
            if (pRenderIn != null)
            {
                Marshal.ReleaseComObject(pRenderIn);
                pRenderIn = null;
            }
            if (pSampleIn != null)
            {
                Marshal.ReleaseComObject(pSampleIn);
                pSampleIn = null;
            }
        }
    }

    private void SaveSizeInfo(ISampleGrabber sampGrabber)
    {
        int hr;

        // Get the media type from the SampleGrabber
        AMMediaType media = new AMMediaType();

        hr = sampGrabber.GetConnectedMediaType( media );
        DsError.ThrowExceptionForHR( hr );

        if( (media.formatType != FormatType.VideoInfo) || (media.formatPtr == IntPtr.Zero) )
        {
            throw new NotSupportedException( "Unknown Grabber Media Format" );
        }

        // Grab the size info
        VideoInfoHeader videoInfoHeader = (VideoInfoHeader) Marshal.PtrToStructure( media.formatPtr, typeof(VideoInfoHeader) );
        m_videoWidth = videoInfoHeader.BmiHeader.Width;
        m_videoHeight = videoInfoHeader.BmiHeader.Height;
        m_stride = m_videoWidth * (videoInfoHeader.BmiHeader.BitCount / 8);

        DsUtils.FreeAMMediaType(media);
        media = null;
    }


    private void ConfigVideoWindow(Control hControl)
    {
        int hr;

        IVideoWindow ivw = m_FilterGraph as IVideoWindow;

        // Set the parent
        hr = ivw.put_Owner(hControl.Handle);
        DsError.ThrowExceptionForHR( hr );

        // Turn off captions, etc
        hr = ivw.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren | WindowStyle.ClipSiblings);
        DsError.ThrowExceptionForHR( hr );

        // Yes, make it visible
        hr = ivw.put_Visible( OABool.True );
        DsError.ThrowExceptionForHR( hr );

        // Move to upper left corner
        Rectangle rc = hControl.ClientRectangle;
        hr = ivw.SetWindowPosition( 0, 0, rc.Right, rc.Bottom );
        DsError.ThrowExceptionForHR( hr );
    }

    private void ConfigureSampleGrabber(ISampleGrabber sampGrabber)
    {
        int hr;
        AMMediaType media = new AMMediaType();

        // Set the media type to Video/RBG24
        media.majorType = MediaType.Video;
        media.subType = MediaSubType.RGB24;
        media.formatType = FormatType.VideoInfo;
        hr = sampGrabber.SetMediaType( media );
        DsError.ThrowExceptionForHR( hr );

        DsUtils.FreeAMMediaType(media);
        media = null;

        // Configure the samplegrabber
        hr = sampGrabber.SetCallback( this, 1 );
        DsError.ThrowExceptionForHR( hr );
    }


    private void SetConfigParms(IPin pStill, int iWidth, int iHeight, short iBPP)
    {
        int hr;
        AMMediaType media;
        VideoInfoHeader v;

        IAMStreamConfig videoStreamConfig = pStill as IAMStreamConfig;

        // Get the existing format block
        hr = videoStreamConfig.GetFormat(out media);
        DsError.ThrowExceptionForHR(hr);

        try
        {
            // copy out the videoinfoheader
            v = new VideoInfoHeader();
            Marshal.PtrToStructure( media.formatPtr, v );

            // if overriding the width, set the width
            if (iWidth > 0)
            {
                v.BmiHeader.Width = iWidth;
            }

            // if overriding the Height, set the Height
            if (iHeight > 0)
            {
                v.BmiHeader.Height = iHeight;
            }

            // if overriding the bits per pixel
            if (iBPP > 0)
            {
                v.BmiHeader.BitCount = iBPP;
            }

            // Copy the media structure back
            Marshal.StructureToPtr( v, media.formatPtr, false );

            // Set the new format
            hr = videoStreamConfig.SetFormat( media );
            DsError.ThrowExceptionForHR( hr );
        }
        finally
        {
            DsUtils.FreeAMMediaType(media);
            media = null;
        }
    }

代码在行中抛出异常: hr = mediaCtrl.Run();

返回的hr值是-2147023729

因为此图像捕获不起作用。有人可以帮我解决这个错误吗?

1 个答案:

答案 0 :(得分:0)

代码为0x8007048F ERROR_DEVICE_NOT_CONNECTED "The device is not connected."。如果/何时未连接设备,则不会进行捕获,不是吗?该错误很可能是从其中一个过滤器转发的,尤其是。捕获过滤器,因此您的故障排除应从检查捕获过滤器图形的拓扑开始。