Reputation: 540
I have a program which currently displays a preview of a usb webcam and then displays a frame within a picturebox when a button is pressed. This is done by using the directshow DxSnap sample thus using the ISampleGrabberCB interface.
Would it be possible for each frame to be scanned automatically without the use of a button?
I tried to do this with a timer however the result ended with bad image quality from both preview and the captured image.
Would this be achieved by using the IsampleGrabberCB.BufferCB function?
The way I am currently getting frames using is a button consists of:
int ISampleGrabberCB.BufferCB(double sampleTime, IntPtr buffer, int bufferLength)
{
Debug.Assert(bufferLength == Math.Abs(pitch) * videoHeight, "Wrong Buffer Length");
if (gotFrame)
{
gotFrame = false;
Debug.Assert(imageBuffer != IntPtr.Zero, "Remove Buffer");
CopyMemory(imageBuffer, buffer, bufferLength);
pictureReady.Set();
}
return 0;
}
public void getFrameFromWebcam()
{
if (iPtr != IntPtr.Zero)
{
Marshal.FreeCoTaskMem(iPtr);
iPtr = IntPtr.Zero;
}
//Get Image
iPtr = sampleGrabberCallBack.getFrame();
Bitmap bitmapOfFrame = new Bitmap(sampleGrabberCallBack.width, sampleGrabberCallBack.height, sampleGrabberCallBack.capturePitch, PixelFormat.Format32bppRgb, iPtr);
bitmapOfFrame.RotateFlip(RotateFlipType.RotateNoneFlipY);
pictureBox3.Image = bitmapOfFrame;
barcodeReader(bitmapOfFrame);
}
public IntPtr getFrame()
{
int hr;
pictureReady.Reset();
imageBuffer = Marshal.AllocCoTaskMem(Math.Abs(pitch) * videoHeight);
try
{
gotFrame = true;
if (videoControl != null)
{
hr = videoControl.SetMode(stillPin, VideoControlFlags.Trigger);
DsError.ThrowExceptionForHR(hr);
}
if (!pictureReady.WaitOne(9000, false))
{
throw new Exception("Timeout waiting to get picture");
}
}
catch
{
Marshal.FreeCoTaskMem(imageBuffer);
imageBuffer = IntPtr.Zero;
}
return imageBuffer;
}
Upvotes: 0
Views: 1594
Reputation: 69687
DirectShow sets you up video streaming, hence you have a stream of frames, not individual images such as obtained when pressing a button (in fact, response to button is untypical for DirectShow and is likely to require some camera-specific integration). ISampleGrabberCB::SampleCB
is thus getting you every captured video frame sequentially. You don't poll it with timer, instead you have a callback called for every frame.
Since it sounds like you are not getting this, I suppose you are missing one of the two things, or both:
Also note that some consumer grade cameras have higher resolution for snapshots and lower resolution for video streaming, so when it comes to video processing you are unable to reach highest declared resolution on the camera specification.
Upvotes: 2