0

我有一个能够同时运行 YUY 和 MJPG 颜色空间的网络摄像头。此相机默认为 YUY,我需要在 DirectShow 图形中更改或添加什么才能以编程方式在 MJPG 中启动相机?我的代码与典型的图形设置非常相似,类似于 DirectShow.Net 示例目录中的 DxSnap 示例。关于这一点的文档很少,我见过的唯一示例是显示捕获引脚属性页面并通过该 UI 更改它,但是我的技术需要以编程方式实现。任何帮助、指导或建议将不胜感激。谢谢

这是我的图形构造:

/// <summary> build the capture graph for grabber. </summary>
    private void SetupGraph(DsDevice dev, int iFrameRate, int iWidth, int iHeight)
    {
        int hr;

        ISampleGrabber sampGrabber = null;

        ICaptureGraphBuilder2 capGraph = null;

        // Get the graphbuilder object
        m_graphBuilder = (IFilterGraph2)new FilterGraph();
        m_mediaCtrl = m_graphBuilder as IMediaControl;
        try
        {
            // Get the ICaptureGraphBuilder2
            capGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();

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

            // Start building the graph
            hr = capGraph.SetFiltergraph(m_graphBuilder);
            DsError.ThrowExceptionForHR(hr);

            // Add the video device
            hr = m_graphBuilder.AddSourceFilterForMoniker(dev.Mon, null, "Video input", out capFilter);
            DsError.ThrowExceptionForHR(hr);

            IBaseFilter baseGrabFlt = (IBaseFilter)sampGrabber;
            ConfigureSampleGrabber(sampGrabber);

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

            // Get list of video compressors on the system
            DsDevice[] videoCompressors = DsDevice.GetDevicesOfCat(FilterCategory.VideoCompressorCategory);

            IBaseFilter videoCompressorFilter = null;
            string videoCompressor = "MJPEG Compressor";
            foreach (DsDevice compressor in videoCompressors)
            {
                if (compressor.Name == videoCompressor)
                {
                    object obj = null;
                    Guid bfGuid = typeof(IBaseFilter).GUID;
                    compressor.Mon.BindToObject(null, null, ref bfGuid, out obj);
                    videoCompressorFilter = obj as IBaseFilter;
                    break; // Found the compressor - stop looking for it
                }

            }

            if (videoCompressorFilter != null)
            {
                hr = m_graphBuilder.AddFilter(videoCompressorFilter, videoCompressor);
                DsError.ThrowExceptionForHR(hr);
            }


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


            hr = capGraph.RenderStream(PinCategory.Capture, MediaType.Video, capFilter, null, baseGrabFlt);
            DsError.ThrowExceptionForHR(hr);

            SaveSizeInfo(sampGrabber);

        }
        finally
        {

            if (sampGrabber != null)
            {
                Marshal.ReleaseComObject(sampGrabber);
                sampGrabber = null;
            }
            if (capGraph != null)
            {
                Marshal.ReleaseComObject(capGraph);
                capGraph = 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 ISampleGrabber 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 ConfigureSampleGrabber(ISampleGrabber sampGrabber)
    {
        AMMediaType media;
        int hr;

        // Set the media type to Video/RBG24
        media = new AMMediaType();
        media.majorType = MediaType.Video;
        media.subType = MediaSubType.MJPG;
        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);
    }

帧回调函数:

    void OnFrameDone()
    {
        try
        {
            int w = Width;
            int h = Height;
            if (((w < 32) || (h < 32)))
            {                   
                return;
            }

            int stride = w * 3;

            lock (this)
            {
                GCHandle handle = GCHandle.Alloc(savedArray, GCHandleType.Pinned);
                int scan0 = (int)handle.AddrOfPinnedObject();
                scan0 += (h - 1) * stride;
                Bitmap b = new Bitmap(w, h, -stride, PixelFormat.Format24bppRgb, (IntPtr)scan0);


                //switch (FrameDirection)
                //{
                //    case VideoDir.Portrait:
                //        b.RotateFlip(RotateFlipType.Rotate90FlipNone);
                //        break;

                //    case VideoDir.Landscape:
                //        b.RotateFlip(RotateFlipType.Rotate180FlipNone);
                //        b.RotateFlip(RotateFlipType.Rotate180FlipNone);
                //        break;

                //}

                if(FrameCaptureComplete != null)
                    FrameCaptureComplete(b);

                handle.Free();
            }

        }
        catch (Exception ex)
        {
            string error = ex.Message;
        }


        return;

    }
4

2 回答 2

1

除非相机以非标准方式执行此操作,否则它应该IAMStreamConfig在其输出引脚上公开接口,您可以通过在 SetFormat 方法中提供感兴趣的媒体类型来选择格式。完成后,继续构建图表并将引脚连接到下游。

于 2012-09-29T20:04:36.390 回答
1

在所有这些反复试验中,我的研究得出的结论是,我的努力并非完全失败的尝试。Microsoft MJPEG Decompressor 无法在 3MP 以上的分辨率下工作,我试图以 5MP 运行图表。使用能够运行 5MP 的第 3 方 MJPEG 压缩器解决了我遇到的所有问题。

谢谢罗曼的帮助。

于 2012-10-03T13:33:44.247 回答