IBasicVideo CetCurrentImage catastrophic failure(D

2019-09-14 17:34发布

问题:

I'm trying to grab image from webcam using DirectShow.NET and IBasicVideo CetCurrentImage. But I only get catastrophic failure on second call GetCurrentImage. What I'm doing particularly:

IBasicVideo bv = (IBasicVideo)graph;
IntPtr bvp = new IntPtr();
int size = 0;
int hr = bv.GetCurrentImage(ref size, IntPtr.Zero);
DsError.ThrowExceptionForHR(hr);
bvp = Marshal.AllocCoTaskMem(size);
hr = bv.GetCurrentImage(ref size, bvp);
DsError.ThrowExceptionForHR(hr);
Bitmap image = new Bitmap(480, 320, 480 * (24 / 8), System.Drawing.Imaging.PixelFormat.Format24bppRgb, bvp);
image.Save(path);

What am I doing wrong?

Prety much all I have:

IGraphBuilder graph = null;
IMediaEventEx eventEx = null;
IMediaControl control = null;
ICaptureGraphBuilder2 capture = null;
IBaseFilter srcFilter = null;
public IVideoWindow videoWindow = null;
IntPtr videoWindowHandle = IntPtr.Zero;

public void GetPreviewFromCam()
{
    graph = (IGraphBuilder)(new FilterGraph());
    capture = (ICaptureGraphBuilder2)(new CaptureGraphBuilder2());
    eventEx = (IMediaEventEx)graph;
    control = (IMediaControl)graph;
    videoWindow = (IVideoWindow)graph;
    videoWindowHandle = hVideoWindow;
    eventEx.SetNotifyWindow(hVideoWindow, WM_GRAPHNOTIFY, IntPtr.Zero);

    int hr;

    // Attach the filter graph to the capture graph
    hr = capture.SetFiltergraph(graph);
    DsError.ThrowExceptionForHR(hr);

    // Find capture device and bind it to srcFilter
    FindCaptureDevice();

    // Add Capture filter to our graph.
    hr = graph.AddFilter(srcFilter, "Video Capture");
    DsError.ThrowExceptionForHR(hr);

    // Render the preview pin on the video capture filter
    // Use this instead of graph->RenderFile
    hr = capture.RenderStream(PinCategory.Preview, MediaType.Video, srcFilter, null, null);
    DsError.ThrowExceptionForHR(hr);

    hr = control.Run();
    DsError.ThrowExceptionForHR(hr);
}

回答1:

IBasicVideo::GetCurrentImage does not have to unconditionally succeed. What it does is forwarding of the call to video renderer in your graph (fails if you don't have one, or you have a weird non-renderer filter which unexpectedly implements the interface), then the renderer would attempt to get you the image. The renderer might fail if it is operating in incompatible mode (windowless video renderers don't have IBasicVideo - might fail here), or the renderer yet did not receive any video frame to have a copy delivered to you, that is the call is premature.

Additionally, there might be a handful of other issues related to obvious bugs - you did not put the graph into active mode, you are under wrong impression about topology you are having, you are using wrong interface, your code has threading issues etc.

With a specter of possibly causes this wide, start with a simple question: at the time of the call, do you have the video frame already presented to you visually?