使用ISampleGrabberCB :: SampleCB

时间:2013-10-31 01:25:42

标签: c# bitmap directshow directshow.net

您好我正在尝试使用ISampleGrabberCB::SampleCB在我的表单中显示图像之前从实时预览中获取图像。

我希望能够将每个新帧转换为要处理的位图(例如扫描+添加水印类型图像)。

目前我正尝试以下列方式进行此操作:

int ISampleGrabberCB.SampleCB(double SampleTime, IMediaSample sample)
    {
        int hr;
        IntPtr buffer;
        AMMediaType mediaType;
        VideoInfoHeader videoInfo;
        int frameWidth;
        int frameHeight;
        int stride;
        int bufferLength;


        hr = sample.GetPointer(out buffer);
        DsError.ThrowExceptionForHR(hr);

        hr = sample.GetMediaType(out mediaType);
        DsError.ThrowExceptionForHR(hr);

        bufferLength = sample.GetSize();

        try
        {
            videoInfo = new VideoInfoHeader();
            Marshal.PtrToStructure(mediaType.formatPtr, videoInfo);

            frameWidth = videoInfo.BmiHeader.Width;
            frameHeight = videoInfo.BmiHeader.Height;
            stride = frameWidth * (videoInfo.BmiHeader.BitCount / 8);

            CopyMemory(imageBuffer, buffer, bufferLength);                

            Bitmap bitmapOfFrame = new Bitmap(frameWidth, frameHeight, stride, PixelFormat.Format24bppRgb, buffer);
            bitmapOfFrame.Save("C:\\Users\\...\\...\\...\\....jpg");


        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }

        return 0;
    }

理论上,这应该得到媒体类型,然后用于获取图像的宽度,高度和步幅,然后用于创建位图。然后从IMediaSample的指针获取缓冲区。

然而,这似乎不起作用(我假设这是因为位图永远不会保存)。那么我如何将每个新帧转换为位图呢?

设置引脚的附加功能:

public void setupGraphForSampleGrabber(DsDevice webcamDevice, Control displayBox)
    {
        int hr;
        ISampleGrabber sampleGrabber = null;
        IPin capturePin = null;
        IPin samplePin = null;
        IPin renderPin = null;
        IBaseFilter captureFilter;
        filtergraph = new FilterGraph() as IFilterGraph2;

        try
        {


            //Add the webcam
            hr = filtergraph.AddSourceFilterForMoniker(webcamDevice.Mon, null, webcamDevice.Name, out captureFilter);
            DsError.ThrowExceptionForHR(hr);

            //Get the still pin
            stillPin = DsFindPin.ByCategory(captureFilter, PinCategory.Still, 0);

            if (stillPin == null)
            {
                stillPin = DsFindPin.ByCategory(captureFilter, PinCategory.Preview, 0);
            }

            if (stillPin == null)
            {
                IPin outputPin = null;
                IPin inputPin = null;

                //As there is still no still pin set this to null
                videoControl = null;

                // Add a splitter
                IBaseFilter smartTee = (IBaseFilter)new SmartTee();

                try
                {
                    hr = filtergraph.AddFilter(smartTee, "SmartTee");
                    DsError.ThrowExceptionForHR(hr);

                    //Obtain the capture pin from the webcam and the input pin from the spliter and assign them to the outputPin and inputPin respectivly
                    outputPin = DsFindPin.ByCategory(captureFilter, PinCategory.Capture, 0);
                    inputPin = DsFindPin.ByDirection(smartTee, PinDirection.Input, 0);

                    //Then connect both of them to the graph
                    hr = filtergraph.Connect(outputPin, inputPin);
                    DsError.ThrowExceptionForHR(hr);

                    //Set the capture and still pins so we can use them with the rest of the program
                    stillPin = DsFindPin.ByName(smartTee, "Preview");
                    capturePin = DsFindPin.ByName(smartTee, "Capture");

                    setParameters(outputPin);

                }
                    //Release all the com objects to avoid problems as the program is to be used for extended periods

                finally
                {
                    if (outputPin != null)
                    {
                        Marshal.ReleaseComObject(outputPin);
                    }
                    if (outputPin != inputPin)
                    {
                        Marshal.ReleaseComObject(inputPin);
                    }
                    if (outputPin != smartTee)
                    {
                        Marshal.ReleaseComObject(smartTee);
                    }
                }
            }
            else
            {
                videoControl = captureFilter as IAMVideoControl;
                capturePin = DsFindPin.ByCategory(captureFilter, PinCategory.Capture, 0);
                setParameters(stillPin);
            }

            //Get interface
            sampleGrabber = new SampleGrabber() as ISampleGrabber;

            //Configure the samplegrabber
            IBaseFilter baseFilter = sampleGrabber as IBaseFilter;
            configureSampleGrabber(sampleGrabber);
            samplePin = DsFindPin.ByDirection(baseFilter, PinDirection.Input, 0);

            //Video Renderer
            IBaseFilter render = new VideoRendererDefault() as IBaseFilter;
            hr = filtergraph.AddFilter(render, "Renderer");
            DsError.ThrowExceptionForHR(hr);

            renderPin = DsFindPin.ByDirection(render, PinDirection.Input, 0);

            //Add samplegrabber to graph
            hr = filtergraph.AddFilter(baseFilter, "SampleGrabber");
            DsError.ThrowExceptionForHR(hr);

            if (videoControl == null)
            {
                //Connect still pin to samplegrabber
                hr = filtergraph.Connect(stillPin, samplePin);
                DsError.ThrowExceptionForHR(hr);

                //Connect capture pin to render
                hr = filtergraph.Connect(capturePin, renderPin);
                DsError.ThrowExceptionForHR(hr);
            }
            else
            {
                //Connect capture pin to render
                hr = filtergraph.Connect(capturePin, renderPin);
                DsError.ThrowExceptionForHR(hr);

                //Connect still pin to samplegrabber
                hr = filtergraph.Connect(stillPin, samplePin);
                DsError.ThrowExceptionForHR(hr);
            }

            //Get video properties
            saveVideoInfo(sampleGrabber);
            ConfigureVideoLocation(displayBox);

            //Run Graph
            IMediaControl mediaControl = filtergraph as IMediaControl;
            hr = mediaControl.Run();
            DsError.ThrowExceptionForHR(hr);


        }
        finally
        {
            if (sampleGrabber != null)
            {
                Marshal.ReleaseComObject(sampleGrabber);
                sampleGrabber = null;
            }
            if (capturePin != null)
            {
                Marshal.ReleaseComObject(capturePin);
                capturePin = null;
            }
            if (renderPin != null)
            {
                Marshal.ReleaseComObject(renderPin);
                renderPin = null;
            }
            if (samplePin != null)
            {
                Marshal.ReleaseComObject(samplePin);
                samplePin = null;
            }
        }
    }

此外,我像这样配置我的samplegrabber:

    public void configureSampleGrabber(ISampleGrabber sampleGrabber)
    {
        int hr;
        AMMediaType mediaType = new AMMediaType();

        //Set the values for media type and format
        mediaType.majorType = MediaType.Video;
        mediaType.subType = MediaSubType.RGB24;
        mediaType.formatType = FormatType.VideoInfo;
        hr = sampleGrabber.SetMediaType(mediaType);
        DsError.ThrowExceptionForHR(hr);

        DsUtils.FreeAMMediaType(mediaType);
        mediaType = null;

        //Configure
        hr = sampleGrabber.SetCallback(this, 0);
        DsError.ThrowExceptionForHR(hr);

    }

2 个答案:

答案 0 :(得分:1)

Sample Grabber不会为每个抓取的样本提供正确的MediaType,因此请不要在此处从样本中请求它。而是获取抓取器的输入引脚或相机的输出引脚,并调用IPin.ConnectionMediaType()以了解此流的正确媒体类型。

答案 1 :(得分:1)

我认为您的图表设置不正确,样本永远不会通过样本采集器。乍一看,我认为样本采集器从未被渲染过。将样本采集器输出引脚连接到空渲染器,事情应该可行。