-
Notifications
You must be signed in to change notification settings - Fork 7
Getting Started
When you start this tutorial, it is assumed that you have already completed Installation.
All interaction with the webcam or other video source is done through the VideoDevice
object. To connect to a camera, type
VideoDevice device = new VideoDevice("/dev/video0");
If your device is not at /dev/video0
, replace it with the path to the camera.
From the VideoDevice, you can:
- detect the supported resolutions and framerates with a
DeviceInfo
object - access its controls with a
ControlList
- capture video with a
FrameGrabber
- control whatever tuners the device may have with a
TunerList
After opening a VideoDevice, you must call device.release()
on it, before terminating your program
Now that you have your VideoDevice, it's time to figure out what resolutions are supported, and at what framerates. To do this, you must first get a DeviceInfo
object:
DeviceInfo info = device.getDeviceInfo();
From the DeviceInfo
object, you can get many different attributes about the device, but first, we should to find out what formats are supported by the device:
ImageFormatList formats = info.getFormatList();
A VideoDevice has two types of formats:
- Native formats
- No guarantees as to whether your preferred format is available on any given
VideoDevice
- Faster to read, as no conversion takes place
- Usually
YUYV
orMJPEG
- No guarantees as to whether your preferred format is available on any given
- Converted formats
- These are a bit slower, because conversion has to happen (but not by much)
- Doesn't depend on hardware capabilities (although can be accelerated in some cases)
- More format options
- Including
MJPEG
,RGB
,YUV
,BGR
, andYVU
- Including
To print out all the native formats:
for (ImageFormat format : formats.getNativeFormats()) {
System.out.println("Native format: " + format);
ResolutionInfo resolutions = format.getResolutionInfo();
for (DiscreteResolution resolution : resolutions.getDiscreteResolutions()) {
System.out.println("Resolution available: " + resolution.getWidth() + "x" + resolution.getHeight());
FrameInterval intervals = resolution.getInterval();
for (DiscreteInterval interval : intervals.getDiscreteIntervals()) {
float fps = ((float) interval.getDenom()) / ((float) interval.getNum());
System.out.println("-> " + fps + " FPS");
}
}
}
Because that was a lot, let's go through it:
First, we loop through the available native formats, and print them. Note that these aren't the only formats that you can use (far from it!), but they are the ones that the video device supports without internal conversion.
for (ImageFormat format : formats.getNativeFormats())
System.out.println("Native format: " + format);
Now, we loop through all the available resolutions (for the format), and print them as WIDTHxHEIGHT
.
ResolutionInfo resolutions = format.getResolutionInfo();
for (DiscreteResolution resolution : resolutions.getDiscreteResolutions()) {
System.out.println("Resolution available: " + resolution.getWidth() + "x" + resolution.getHeight());
We end with going through the frame intervals for each resolution. Each discrete interval is represented as a fraction of a second, so an interval for 1 frame per 40ms would be 1/25
. To calculate the FPS, you do the inverse of the interval, so 25/1 = 25 FPS
.
FrameInterval intervals = resolution.getInterval();
for (DiscreteInterval interval : intervals.getDiscreteIntervals()) {
float fps = ((float) interval.getNumerator()) / ((float) interval.getDenominator());
System.out.println("-> " + fps + " FPS");
Because there are many formats available for conversion, looping through all of them might not be ideal in your program. To detect if a format is available, VideoDevice
has a nice method, supportXXXConversion()
. For example:
if (!device.supportJPEGConversion())
throw new Exception("No JPEG conversion available!");
Now that we know what formats, resolutions, and intervals are available, we can start streaming pictures in from the camera. We do that with a FrameGrabber
; to open it, we need at least 4 arguments:
-
width: the width, in pixels to capture frames in. Setting this to
V4L4JConstants.MAX_WIDTH
will request the largest available resolution. - height: The height of the frames captured.
- channel: the input channel, that depends on the hardware: webcams only have one (channel 0), while capture cards might have many. If you don't know what this means, you probably want to set it to 0.
- std: the video standard. Can be one of:
Wrapping it all together, we get:
if (device.supportRGBConversion()) { //or device.support___Conversion()
FrameGrabber grabber;
try {
frameGrabber = device.getRGBFrameGrabber(width, height, channel, std);
//do stuff
} finally {
device.releaseFrameGrabber();
}
}
device.release();
Note: After finishing with the FrameGrabber
, you MUST call releaseFrameGrabber()
, especially before calling release()
on the VideoDevice, or your program will hang.
Now that you have your FrameGrabber, we should tell v4l4j how to capture frames. The main thing that we want to set is the FPS to capture at. Here we're restricted to the FPS ranges that are offered by the device.
Note: The FPS that you pass to your FrameGrabber is more of an upper bound, and YMMV based on USB speed, background processing, etc.
frameGrabber.setFrameInterval(interval.getNumerator(), interval.getDenominator());
[TODO: finish section]
Next: Using frames
After installing, you should be able to use any of the examples provided with V4L4J. To do this, run ant [example name]
. Elevated privileges may be required for some of the examples.
test-fps
- Test the FPS of a video device
test-gui
- Open a window, and display the video stream from a camera
test-server
- Open a HTTP server on port `8080`. You can connect to this in your web browser (Chrome works pretty well), and see the video and control the camera.
test-dual
- Open two windows and show the video streams from two cameras at the same time
test-getsnapshot
- Get snapshots from a camera
deviceinfo
- Display information about a video source