Question

I have a web cam that's capable of running both YUY and MJPG color spaces. This camera default is YUY, what do i need to alter or add in my DirectShow graph to start the camera in MJPG programmatically? My code is very similar to the typical graph setup, resembling the DxSnap example found in the DirectShow.Net sample directory. documentation is scarce regarding this, the only sample i've seen is displaying the capture pin property page and changing it through that UI, however my technique needs to be implemented programmatically. any help, guidance or advice would be greatly appreciated. Thank you

Here is my graph construction:

/// <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);
    }

function for frame callback:

    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;

    }
Was it helpful?

Solution 2

Throughout all this trial and error, my research reaches a conclusion that my efforts were not exactly failed attempts. The Microsoft MJPEG Decompressor is not working above 3MP resolution, i was attempting to run the graph at 5MP. Using a 3rd party MJPEG Compressor that was capable of running 5MP fixed all the issues i was experiencing.

Thank you Roman for your help.

OTHER TIPS

Unless the camera does it in a non-standard way, it should expose IAMStreamConfig interface on its output pin, where you can select format by providing the media type of interest into SetFormat method. Once done, keep building graph and connecting the pin downstream.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top