Skip to content

Commit a659148

Browse files
committed
Fix buggy synchronization in V4L4J driver
1 parent d93e386 commit a659148

File tree

1 file changed

+28
-21
lines changed
  • webcam-capture-drivers/driver-v4l4j/src/main/java/com/github/sarxos/webcam/ds/v4l4j

1 file changed

+28
-21
lines changed

webcam-capture-drivers/driver-v4l4j/src/main/java/com/github/sarxos/webcam/ds/v4l4j/V4l4jDevice.java

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,18 @@
55
import java.io.File;
66
import java.util.ArrayList;
77
import 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;
911
import java.util.concurrent.atomic.AtomicBoolean;
1012

1113
import org.slf4j.Logger;
1214
import 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+
1420
import au.edu.jcu.v4l4j.CaptureCallback;
1521
import au.edu.jcu.v4l4j.DeviceInfo;
1622
import au.edu.jcu.v4l4j.FrameGrabber;
@@ -24,10 +30,6 @@
2430
import au.edu.jcu.v4l4j.exceptions.StateException;
2531
import 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

3234
public 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

Comments
 (0)