package com.github.sarxos.webcam.ds.ffmpegcli; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.github.sarxos.webcam.WebcamDevice; import com.github.sarxos.webcam.WebcamDiscoverySupport; import com.github.sarxos.webcam.WebcamDriver; import com.github.sarxos.webcam.ds.ffmpegcli.impl.VideoDeviceFilenameFilter; public class FFmpegCliDriver implements WebcamDriver, WebcamDiscoverySupport { private static final Logger LOG = LoggerFactory.getLogger(FFmpegCliDriver.class); private static final VideoDeviceFilenameFilter VFFILTER = new VideoDeviceFilenameFilter(); private static final Runtime RT = Runtime.getRuntime(); private static final String MARKER = "mjpeg"; private static final String STARTER = "[video4linux"; @Override public List<WebcamDevice> getDevices() { File[] vfiles = VFFILTER.getVideoFiles(); List<WebcamDevice> devices = new ArrayList<WebcamDevice>(); OutputStream os = null; InputStream is1 = null; InputStream is2 = null; Process process = null; String line = null; BufferedReader br1 = null; BufferedReader br2 = null; for (File vfile : vfiles) { String[] cmd = new String[] { "ffmpeg", "-f", "video4linux2", "-list_formats", "all", "-i", vfile.getAbsolutePath() }; if (LOG.isDebugEnabled()) { StringBuilder sb = new StringBuilder(); for (String c : cmd) { sb.append(c).append(' '); } LOG.debug("Executing command: {}", sb.toString()); } try { process = RT.exec(cmd); } catch (IOException e) { throw new RuntimeException(e); } os = process.getOutputStream(); is1 = process.getInputStream(); is2 = process.getErrorStream(); try { os.close(); } catch (IOException e) { throw new RuntimeException(e); } br1 = new BufferedReader(new InputStreamReader(is1)); br2 = new BufferedReader(new InputStreamReader(is2)); boolean read = false; try { while ((line = br2.readLine()) != null) { if (line.startsWith(STARTER) && line.indexOf(MARKER) != -1) { LOG.debug("Command stderr line: {}", line); devices.add(new FFmpegCliDevice(vfile, line)); read = true; break; } } if (!read) { while ((line = br1.readLine()) != null) { if (line.startsWith(STARTER) && line.indexOf(MARKER) != -1) { LOG.debug("Command stdout line: {}", line); devices.add(new FFmpegCliDevice(vfile, line)); break; } } } } catch (IOException e) { throw new RuntimeException(e); } finally { try { is1.close(); is2.close(); } catch (IOException e) { throw new RuntimeException(e); } } } return devices; } @Override public boolean isThreadSafe() { return false; } @Override public long getScanInterval() { return 3000; } @Override public boolean isScanPossible() { return true; } @Override public String toString() { return getClass().getSimpleName(); } }