Pregunta

I am currently trying to add a ISampleGrabber filter to my program. Currently the program captures and displays a preview to my windows form however when i try to add my own ISampleGrabber filter using others examples the webcam section of the program stops working completely.

    IVideoWindow videoWindow = null;
    IMediaControl mediaControl = null;
    IMediaEventEx mediaEventEx = null;
    IGraphBuilder graphBuilder = null;
    ICaptureGraphBuilder2 captureGraphBuilder = null;
    IBaseFilter baseFilterForSampleGrabber;
    ISampleGrabber sampleGrabber;
    AMMediaType mediaType;
    VideoInfoHeader videoInfoHeader;

public void capturePreview()
{        
    int hr = 0;
    IBaseFilter baseFilter = null;
    try
    {

            interfaces();

            hr = this.captureGraphBuilder.SetFiltergraph(this.graphBuilder);
            DsError.ThrowExceptionForHR(hr);

            baseFilter = getListOfDevices();

            hr = this.graphBuilder.AddFilter(baseFilter, "Webcam");
            DsError.ThrowExceptionForHR(hr);



            sampleGrabber = new SampleGrabber() as ISampleGrabber;
            baseFilterForSampleGrabber = (IBaseFilter)new SampleGrabber();

            if (baseFilterForSampleGrabber == null)
            {
                Marshal.ReleaseComObject(sampleGrabber);
                sampleGrabber = null;
            }                

            mediaType = new AMMediaType();
            mediaType.majorType = MediaType.Video;
            mediaType.subType = MediaSubType.RGB24;  
            mediaType.formatType = FormatType.VideoInfo;
            //int width = videoInfoHeader.BmiHeader.Width;
            //int height = videoInfoHeader.BmiHeader.Height;
            //int size = videoInfoHeader.BmiHeader.ImageSize;
            //mediaType.formatPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(videoInfoHeader));
            //Marshal.StructureToPtr(videoInfoHeader, mediaType.formatPtr, false);
            hr = sampleGrabber.SetMediaType(mediaType);
            DsUtils.FreeAMMediaType(mediaType);





            hr = graphBuilder.AddFilter(baseFilterForSampleGrabber, "ISampleGrabber Filter");
            DsError.ThrowExceptionForHR(hr);  

            hr = this.captureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, baseFilter, baseFilterForSampleGrabber, null);
            DsError.ThrowExceptionForHR(hr);                

            Marshal.ReleaseComObject(baseFilter);

            videoWindowSetup();

            hr = sampleGrabber.SetBufferSamples(true);
            DsError.ThrowExceptionForHR(hr);

            hr = this.mediaControl.Run();
            DsError.ThrowExceptionForHR(hr);







    }
    catch
    {
        MessageBox.Show("Error...Try restart");
    }



}

The above code contains my current graph along with the starting ISampleGrabber code I see repeated in every example, however when I add the commented code this is when the program stops. I do not know where the issue is and presume I should at least get the basics sorted before continuing adding on the graph.

If I resolve this problem any further help on what else I require to complete this graph would be very helpful, I aim to convert the frames captured into bitmaps so I can immediately edit them, such as add a crosshair, and show them in the windows form once edited straight away.

Any help is appreciated :)

¿Fue útil?

Solución

Commented code does not initialize videoInfoHeader correctly. You need to initialize all members there (well, some might be left with zeros, but you have to add values for mandatory ones). biCompression, biBitCount to say the least. Also your code does not even initialize those members and vice versa reads uninitialized values back.

This is however a wrong way already. Most samples suggest that you don't intialize format and formatPtr for a reason. With major type and subtype, Sample Grabber would "hint" intelligent connect what format you want data in (24-bit RGB here and typically). Yes this is what you can do and this works out well. However there is no flexibility to specify resolution there, or frame rate, not even every pixel format works out. That is, whatever you are trying to do here is likely to be incorrect. You are supposed to be happy with partial media type (major type and subtype only).

DxScan from DirectShow.NET Samples adds the Sample Grabber and shows how to do it and how to set it up:

    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.RGB24;
        media.formatType = FormatType.VideoInfo;
        hr = sampGrabber.SetMediaType( media );
        DsError.ThrowExceptionForHR( hr );

        DsUtils.FreeAMMediaType(media);
        media = null;

        // Choose to call BufferCB instead of SampleCB
        hr = sampGrabber.SetCallback( this, 1 );
        DsError.ThrowExceptionForHR( hr );
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top