0

我在带有 Directshow Lib 的 C#.NET4.0 中的 Windows 应用程序中开发,用于使用网络摄像头录制视频。在视频录制期间,我通过在 BufferCB 中抓取框架来放置覆盖文本,并将覆盖位图放在框架上。

这个带有覆盖的应用程序运行良好。但是几天后覆盖文本没有出现,所以我试图找出问题然后我意识到 BufferCB 没有接到电话。SetCallback() 函数返回 0 表示其中没有错误。那么为什么 BufferCB 没有得到调用?

编辑

用于开始录制的按钮单击代码,配置采样器获取视频大小信息等。

private void button1_Click(object sender, EventArgs e)
    {

        jpg.RotateFlip(RotateFlipType.RotateNoneFlipY);
        //jpgdata = jpg.LockBits(new Rectangle(0, 0, jpg.Width, jpg.Height), ImageLockMode.ReadWrite, jpg.PixelFormat);
        AvailableAudioInputDevices = new List<DsDevice>();
        DsDevice[] audioInputDevices = DsDevice.GetDevicesOfCat(FilterCategory.AudioInputDevice);
        AvailableAudioInputDevices.AddRange(audioInputDevices);

        AvailableVideoInputDevices = new List<DsDevice>();
        DsDevice[] videoInputDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
        AvailableVideoInputDevices.AddRange(videoInputDevices);

        Graph = (IFilterGraph2)new FilterGraph();
        captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();

        hr = captureGraph.SetFiltergraph(Graph);
        DsError.ThrowExceptionForHR(hr);

        hr = captureGraph.SetOutputFileName(MediaSubType.Asf, "qwe.wmv", out pMux, out pFilter);
        DsError.ThrowExceptionForHR(hr);

        hr = Graph.AddSourceFilterForMoniker(AvailableAudioInputDevices.First().Mon, null, AvailableAudioInputDevices.First().Name, out capFilter);
        DsError.ThrowExceptionForHR(hr);

        //ConfigProfileFromFile(pMux, "b.prx");

        hr = captureGraph.RenderStream(PinCategory.Capture, MediaType.Audio, capFilter, null, pMux);
        DsError.ThrowExceptionForHR(hr);

        hr = Graph.AddSourceFilterForMoniker(AvailableVideoInputDevices.First().Mon, null, AvailableVideoInputDevices.First().Name, out capFilter);
        DsError.ThrowExceptionForHR(hr);
        #region code for init. preview window and sample grabber
        mediaControl = (IMediaControl)Graph;
        mediaEventEx = (IMediaEventEx)Graph;
        mediaEventEx.SetNotifyWindow(pic.Handle, WM_GRAPHNOTIFY, IntPtr.Zero);
        IBaseFilter vmr9preview = null;
        vmr9preview = (IBaseFilter)new VideoMixingRenderer9();
        hr = Graph.AddFilter(vmr9preview, "VMR9");
        DsError.ThrowExceptionForHR(hr);
        IVMRFilterConfig9 vmr9Config = (IVMRFilterConfig9)vmr9preview;
        vmr9Config.SetRenderingMode(VMR9Mode.Windowless);
        vmr9Config.SetNumberOfStreams(1);
        vmr9Control = (IVMRWindowlessControl9)vmr9preview;
        vmr9Control.SetVideoClippingWindow(pic.Handle);
        vmr9Control.SetAspectRatioMode(VMR9AspectRatioMode.None);
        var srcRect = new DsRect();
        var dstRect = new DsRect(pic.ClientRectangle);
        int arWidth, arHeight;
        vmr9Control.GetNativeVideoSize(out srcRect.right, out srcRect.bottom, out arWidth, out arHeight);
        vmr9Control.SetVideoPosition(srcRect, dstRect);
        sampGrabber = new SampleGrabber() as ISampleGrabber;
        #endregion

        #region code for get video info and config sample grabber
        IPin iPinOutSource = DsFindPin.ByDirection(capFilter, PinDirection.Output, 0);
        // Configure the sample grabber
        IBaseFilter baseGrabFlt = sampGrabber as IBaseFilter;
        ConfigureSampleGrabber(sampGrabber);
        iPinInFilter = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0);
        iPinOutFilter = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0);

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

        hr = Graph.Connect(iPinOutSource, iPinInFilter);
        DsError.ThrowExceptionForHR(hr);

        // Get the default video renderer
        ibfRenderer = (IBaseFilter)new VideoRendererDefault();

        // Add it to the graph
        hr = Graph.AddFilter(ibfRenderer, "Ds.NET VideoRendererDefault");
        DsError.ThrowExceptionForHR(hr);
        iPinInDest = DsFindPin.ByDirection(ibfRenderer, PinDirection.Input, 0);

        // Connect the graph.  Many other filters automatically get added here
        hr = Graph.Connect(iPinOutFilter, iPinInDest);
        DsError.ThrowExceptionForHR(hr);
        SaveSizeInfo(sampGrabber);
        hr = Graph.RemoveFilter(baseGrabFlt);
        DsError.ThrowExceptionForHR(hr);

        hr = Graph.Disconnect(iPinOutSource);
        DsError.ThrowExceptionForHR(hr);

        hr = Graph.RemoveFilter(ibfRenderer);
        DsError.ThrowExceptionForHR(hr);

        hr = Graph.Disconnect(iPinInDest);
        DsError.ThrowExceptionForHR(hr);
        #endregion
        ConfigProfileFromFile(pMux, "b.prx");

        hr = Graph.AddFilter(capFilter, "VMR9");
        DsError.ThrowExceptionForHR(hr);

        hr = Graph.AddFilter(baseGrabFlt, "Ds.NET Grabber");
        DsError.ThrowExceptionForHR(hr);

        hr = captureGraph.RenderStream(PinCategory.Preview, MediaType.Video, capFilter, null, vmr9preview);
        DsError.ThrowExceptionForHR(hr);
        hr = captureGraph.RenderStream(PinCategory.Capture, MediaType.Video, capFilter, null, pMux);
        DsError.ThrowExceptionForHR(hr);


        m_mediaCtrl = Graph as IMediaControl;
        SetupBitmap();
        m_mediaCtrl.Run();
        //timer1.Start();             
    }

Config Sample Grabber 方法

private void ConfigureSampleGrabber(ISampleGrabber sampGrabber)
    {
        int hr;
        AMMediaType media = new AMMediaType();

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

BufferCB 和 SampleCB

 int ISampleGrabberCB.SampleCB(double SampleTime, IMediaSample pSample)
    {
        Marshal.ReleaseComObject(pSample);
        return 0;
    }

    [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
    static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);
    /// <summary> buffer callback, COULD BE FROM FOREIGN THREAD. </summary>
    int ISampleGrabberCB.BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen)
    {    
        CopyMemory(pBuffer, bmpData.Scan0, bmpData.Stride*20);
        return 0;
    }
4

0 回答 0