DirectShowLib-2005 easycap USB 2.0接口与索尼手持相机图像捕获问题

本文关键字:相机 图像 问题 索尼 USB easycap 接口 DirectShowLib-2005 | 更新日期: 2023-09-27 18:09:38

我有索尼便携式相机连接到Easycap USB 2.0,我使用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

由于这个图像捕获不工作。有人能帮我修复这个错误吗?

DirectShowLib-2005 easycap USB 2.0接口与索尼手持相机图像捕获问题

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