55import java .io .File ;
66import java .util .ArrayList ;
77import java .util .List ;
8- import java .util .concurrent .CountDownLatch ;
8+ import java .util .concurrent .Exchanger ;
9+ import java .util .concurrent .TimeUnit ;
10+ import java .util .concurrent .TimeoutException ;
911import java .util .concurrent .atomic .AtomicBoolean ;
1012
1113import org .slf4j .Logger ;
1214import org .slf4j .LoggerFactory ;
1315
16+ import com .github .sarxos .webcam .WebcamDevice ;
17+ import com .github .sarxos .webcam .WebcamException ;
18+ import com .github .sarxos .webcam .WebcamResolution ;
19+
1420import au .edu .jcu .v4l4j .CaptureCallback ;
1521import au .edu .jcu .v4l4j .DeviceInfo ;
1622import au .edu .jcu .v4l4j .FrameGrabber ;
2430import au .edu .jcu .v4l4j .exceptions .StateException ;
2531import au .edu .jcu .v4l4j .exceptions .V4L4JException ;
2632
27- import com .github .sarxos .webcam .WebcamDevice ;
28- import com .github .sarxos .webcam .WebcamException ;
29- import com .github .sarxos .webcam .WebcamResolution ;
30-
3133
3234public class V4l4jDevice implements WebcamDevice , CaptureCallback , WebcamDevice .FPSSource {
3335
@@ -66,9 +68,8 @@ public class V4l4jDevice implements WebcamDevice, CaptureCallback, WebcamDevice.
6668
6769 private AtomicBoolean open = new AtomicBoolean (false );
6870 private AtomicBoolean disposed = new AtomicBoolean (false );
69- private CountDownLatch latch = new CountDownLatch (1 );
7071
71- private volatile BufferedImage image = null ;
72+ private final Exchanger < BufferedImage > exchanger = new Exchanger < BufferedImage >() ;
7273 private volatile V4L4JException exception = null ;
7374
7475 /* used to calculate fps */
@@ -286,19 +287,20 @@ public BufferedImage getImage() {
286287 throw new RuntimeException ("Cannot get image from closed device" );
287288 }
288289
289- V4L4JException ex = null ;
290- if (exception != null ) {
290+ V4L4JException ex = this . exception ;
291+ if (ex != null ) {
291292 throw new WebcamException (ex );
292293 }
293294
295+ int timeout = 3 ;
294296 try {
295- latch . await ( );
297+ return exchanger . exchange ( null , timeout , TimeUnit . SECONDS );
296298 } catch (InterruptedException e ) {
297- LOG .trace ("Await has been interrupted" , e );
299+ return null ;
300+ } catch (TimeoutException e ) {
301+ LOG .error ("UNable to get image in {} seconds timeout" );
298302 return null ;
299303 }
300-
301- return image ;
302304 }
303305
304306 @ Override
@@ -365,8 +367,13 @@ public synchronized void close() {
365367 } catch (StateException e ) {
366368 LOG .trace ("State exception on close" , e ); // ignore
367369 } finally {
368- image = null ;
369- latch .countDown ();
370+ try {
371+ exchanger .exchange (null , 1000 , TimeUnit .MILLISECONDS );
372+ } catch (InterruptedException e ) {
373+ LOG .debug ("Exchange interrupted in close" );
374+ } catch (TimeoutException e ) {
375+ LOG .debug ("Exchange timeout in close" );
376+ }
370377 }
371378
372379 grabber = null ;
@@ -403,6 +410,8 @@ public boolean isOpen() {
403410 @ Override
404411 public void nextFrame (VideoFrame frame ) {
405412
413+ LOG .trace ("Next frame {}" , frame );
414+
406415 if (!open .get ()) {
407416 return ;
408417 }
@@ -413,13 +422,11 @@ public void nextFrame(VideoFrame frame) {
413422 }
414423
415424 try {
416- image = frame .getBufferedImage ();
425+ exchanger .exchange (frame .getBufferedImage ());
426+ } catch (InterruptedException e ) {
427+ return ;
417428 } finally {
418- try {
419- frame .recycle ();
420- } finally {
421- latch .countDown ();
422- }
429+ frame .recycle ();
423430 }
424431
425432 t1 = t2 ;
0 commit comments