Webcam api: maximize capture 720p

I am trying to capture video through an external Logitec C922 camera. Using java, I can make this possible through the api webcam.

<dependency> <groupId>com.github.sarxos</groupId> <artifactId>webcam-capture</artifactId> <version>0.3.10</version> </dependency> <dependency> <groupId>xuggle</groupId> <artifactId>xuggle-xuggler</artifactId> <version>5.4</version> </dependency> 

However, for the life of me, I cannot record at 60FPS. The video accidentally stutters when saving and is not quite smooth.

I can connect to the camera using the following data.

 final List<Webcam> webcams = Webcam.getWebcams(); for (final Webcam cam : webcams) { if (cam.getName().contains("C922")) { System.out.println("### Logitec C922 cam found"); webcam = cam; break; } } 

I set the cam size as follows:

 final Dimension[] nonStandardResolutions = new Dimension[] { WebcamResolution.HD720.getSize(), }; webcam.setCustomViewSizes(nonStandardResolutions); webcam.setViewSize(WebcamResolution.HD720.getSize()); webcam.open(true); 

And then I capture the images:

 while (continueRecording) { // capture the webcam image final BufferedImage webcamImage = ConverterFactory.convertToType(webcam.getImage(), BufferedImage.TYPE_3BYTE_BGR); final Date timeOfCapture = new Date(); // convert the image and store final IConverter converter = ConverterFactory.createConverter(webcamImage, IPixelFormat.Type.YUV420P); final IVideoPicture frame = converter.toPicture(webcamImage, (System.currentTimeMillis() - start) * 1000); frame.setKeyFrame(false); frame.setQuality(0); writer.encodeVideo(0, frame); } 

My writer is defined as follows:

 final Dimension size = WebcamResolution.HD720.getSize(); final IMediaWriter writer = ToolFactory.makeWriter(videoFile.getName()); writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_H264, size.width, size.height); 

I'm honestly not sure what could be the reason for this in my code. Given that I am lowering the resolution, I have no problem. (480p) Could the problem be with the codes that I use?

+4
source share
1 answer

As mentioned in some comments, introducing queues solves the problem. Here is the general logic for performing the necessary steps. Please note, I have set my code to a lower resolution since it allows me to capture 100FPS per second. Adjust as needed.

The class for linking the image / video and the class for editing it:

 public class WebcamRecorder { final Dimension size = WebcamResolution.QVGA.getSize(); final Stopper stopper = new Stopper(); public void startRecording() throws Exception { final Webcam webcam = Webcam.getDefault(); webcam.setViewSize(size); webcam.open(true); final BlockingQueue<CapturedFrame> queue = new LinkedBlockingQueue<CapturedFrame>(); final Thread recordingThread = new Thread(new RecordingThread(queue, webcam, stopper)); final Thread imageProcessingThread = new Thread(new ImageProcessingThread(queue, size)); recordingThread.start(); imageProcessingThread.start(); } public void stopRecording() { stopper.setStop(true); } } 

RecordingThread:

 public void run() { try { System.out.println("## capturing images began"); while (true) { final BufferedImage webcamImage = ConverterFactory.convertToType(webcam.getImage(), BufferedImage.TYPE_3BYTE_BGR); final Date timeOfCapture = new Date(); queue.put(new CapturedFrame(webcamImage, timeOfCapture, false)); if (stopper.isStop()) { System.out.println("### signal to stop capturing images received"); queue.put(new CapturedFrame(null, null, true)); break; } } } catch (InterruptedException e) { System.out.println("### threading issues during recording:: " + e.getMessage()); } finally { System.out.println("## capturing images end"); if (webcam.isOpen()) { webcam.close(); } } } 

ImageProcessingThread:

 public void run() { writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_H264, size.width, size.height); try { int frameIdx = 0; final long start = System.currentTimeMillis(); while (true) { final CapturedFrame capturedFrame = queue.take(); if (capturedFrame.isEnd()) { break; } final BufferedImage webcamImage = capturedFrame.getImage(); size.height); // convert the image and store final IConverter converter = ConverterFactory.createConverter(webcamImage, IPixelFormat.Type.YUV420P); final long end = System.currentTimeMillis(); final IVideoPicture frame = converter.toPicture(webcamImage, (end - start) * 1000); frame.setKeyFrame((frameIdx++ == 0)); frame.setQuality(0); writer.encodeVideo(0, frame); } } catch (final InterruptedException e) { System.out.println("### threading issues during image processing:: " + e.getMessage()); } finally { if (writer != null) { writer.close(); } } 

How it works is pretty simple. The WebcamRecord class instantiates a queue that is used for video capture and image processing. RecordingThread sends the bufferedImages to the queue (in my case, this is a pojo called CapturedFrame (which has a BufferedImage in it)). ImageProcessingThread will listen and retrieve data from the queue. If it does not receive a signal that the recording should end, the cycle is never interrupted.

0
source

Source: https://habr.com/ru/post/1275290/


All Articles