001 package com.github.sarxos.webcam.ds.buildin;
002
003 import java.util.ArrayList;
004 import java.util.Collections;
005 import java.util.List;
006 import java.util.concurrent.atomic.AtomicReference;
007
008 import org.bridj.Pointer;
009 import org.slf4j.Logger;
010 import org.slf4j.LoggerFactory;
011
012 import com.github.sarxos.webcam.WebcamDevice;
013 import com.github.sarxos.webcam.WebcamDiscoverySupport;
014 import com.github.sarxos.webcam.WebcamDriver;
015 import com.github.sarxos.webcam.WebcamTask;
016 import com.github.sarxos.webcam.ds.buildin.natives.Device;
017 import com.github.sarxos.webcam.ds.buildin.natives.DeviceList;
018 import com.github.sarxos.webcam.ds.buildin.natives.OpenIMAJGrabber;
019
020
021 /**
022 * Default build-in webcam driver based on natives from OpenIMAJ framework. It
023 * can be widely used on various systems - Mac OS, Linux (x86, x64, ARM),
024 * Windows (win32, win64).
025 *
026 * @author Bartosz Firyn (SarXos)
027 */
028 public class WebcamDefaultDriver implements WebcamDriver, WebcamDiscoverySupport {
029
030 static {
031 if (!"true".equals(System.getProperty("webcam.debug"))) {
032 System.setProperty("bridj.quiet", "true");
033 }
034 }
035
036 private static class WebcamNewGrabberTask extends WebcamTask {
037
038 private AtomicReference<OpenIMAJGrabber> grabber = new AtomicReference<OpenIMAJGrabber>();
039
040 public WebcamNewGrabberTask(WebcamDriver driver) {
041 super(driver, null);
042 }
043
044 public OpenIMAJGrabber newGrabber() {
045 try {
046 process();
047 } catch (InterruptedException e) {
048 LOG.error("Processor has been interrupted");
049 return null;
050 }
051 return grabber.get();
052 }
053
054 @Override
055 protected void handle() {
056 grabber.set(new OpenIMAJGrabber());
057 }
058 }
059
060 private static class GetDevicesTask extends WebcamTask {
061
062 private volatile List<WebcamDevice> devices = null;
063 private volatile OpenIMAJGrabber grabber = null;
064
065 public GetDevicesTask(WebcamDriver driver) {
066 super(driver, null);
067 }
068
069 /**
070 * Return camera devices.
071 *
072 * @param grabber the native grabber to use for search
073 * @return Camera devices.
074 */
075 public List<WebcamDevice> getDevices(OpenIMAJGrabber grabber) {
076
077 this.grabber = grabber;
078
079 try {
080 process();
081 } catch (InterruptedException e) {
082 LOG.error("Processor has been interrupted");
083 return Collections.emptyList();
084 }
085
086 return devices;
087 }
088
089 @Override
090 protected void handle() {
091
092 devices = new ArrayList<WebcamDevice>();
093
094 Pointer<DeviceList> pointer = grabber.getVideoDevices();
095 DeviceList list = pointer.get();
096
097 for (Device device : list.asArrayList()) {
098 devices.add(new WebcamDefaultDevice(device));
099 }
100 }
101 }
102
103 /**
104 * Logger.
105 */
106 private static final Logger LOG = LoggerFactory.getLogger(WebcamDefaultDriver.class);
107
108 private static OpenIMAJGrabber grabber = null;
109
110 @Override
111 public List<WebcamDevice> getDevices() {
112
113 LOG.debug("Searching devices");
114
115 if (grabber == null) {
116
117 WebcamNewGrabberTask task = new WebcamNewGrabberTask(this);
118 grabber = task.newGrabber();
119
120 if (grabber == null) {
121 return Collections.emptyList();
122 }
123 }
124
125 List<WebcamDevice> devices = new GetDevicesTask(this).getDevices(grabber);
126
127 if (LOG.isDebugEnabled()) {
128 for (WebcamDevice device : devices) {
129 LOG.debug("Found device {}", device.getName());
130 }
131 }
132
133 return devices;
134 }
135
136 @Override
137 public long getScanInterval() {
138 return 3000;
139 }
140
141 @Override
142 public boolean isScanPossible() {
143 return true;
144 }
145
146 @Override
147 public boolean isThreadSafe() {
148 return false;
149 }
150 }