0

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);
}
WatTheCat
  • 3
  • 7
  • It looks like this method is working if I just render video file but with cam capture it's not. Any suggestions? – WatTheCat May 07 '13 at 11:46

1 Answers1

0

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?

Roman R.
  • 68,205
  • 6
  • 94
  • 158
  • Thank you for answer. And yes, I can see preview from camera when I call code above. – WatTheCat May 07 '13 at 12:22
  • One of the quick workarounds you can try is to locate video renderer filter exactly, query its `IBasicVideo` and call GetCurrentImage on it. This filter might also be implementing another GetCurrentImage-enabled interface. It's hard to tell if it does exactly because you don't provide sufficient details. – Roman R. May 07 '13 at 12:25
  • Oh, I can provide any details you need. Actually, this is all code I have (I post it to main message). – WatTheCat May 07 '13 at 12:38