从 YUY 更改为 MJPG 格式



我有一个能够同时运行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;
    }

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

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

谢谢罗曼的帮助。

最新更新