From 1f1bffe70d677278520655877b089fe20772636b Mon Sep 17 00:00:00 2001 From: codeanticode Date: Thu, 6 Oct 2011 04:53:36 +0000 Subject: [PATCH] Better device selection in Capture --- .../video/src/processing/video/Capture.java | 226 ++++++++---------- .../video/src/processing/video/Movie.java | 18 +- .../video/src/processing/video/Video.java | 5 + 3 files changed, 117 insertions(+), 132 deletions(-) diff --git a/java/libraries/video/src/processing/video/Capture.java b/java/libraries/video/src/processing/video/Capture.java index 169702e98..0ed0a9af0 100644 --- a/java/libraries/video/src/processing/video/Capture.java +++ b/java/libraries/video/src/processing/video/Capture.java @@ -50,6 +50,42 @@ import org.gstreamer.interfaces.Property; * @usage application */ public class Capture extends PImage implements PConstants { + public static String capturePlugin; + public static String devicePropertyName; + public static String indexPropertyName; + // Default gstreamer capture plugin for each platform, and property names. + static { + if (PApplet.platform == MACOSX) { + if (Video.bitsJVM == 32) { + capturePlugin = "osxvideosrc"; + // osxvideosrc has "device-name" and "device" properties, which both take a string + // value. The first should be the human-readable name of the video device (i.e.: + // "Display iSight") but it appears as only readable. The second can be written with + // the sequence grabber input device in format "sgname:input#", for example: + // "USB Video Class Video:0" + devicePropertyName = "device"; + // osxvideosrc doesn't have an index property. + indexPropertyName = ""; + } else if (Video.bitsJVM == 64) { + capturePlugin = "qtkitvideosrc"; + // qtkitvideosrc doesn't have a property to set the device name + devicePropertyName = ""; + indexPropertyName = "device-index"; + } + } else if (PApplet.platform == WINDOWS) { + capturePlugin = "ksvideosrc"; + devicePropertyName = "device-name"; + indexPropertyName = "device-index"; + } else if (PApplet.platform == LINUX) { + capturePlugin = "v4l2src"; + // The "device" property in v4l2src expects the device location (/dev/video0, etc). + // v4l2src has "device-name", which requires the human-readable name, but how to obtain + // in linux?. + devicePropertyName = "device"; + indexPropertyName = "device-fd"; + } else {} + } + protected String source; protected boolean capturing = false; @@ -93,8 +129,8 @@ public class Capture extends PImage implements PConstants { */ public Capture(PApplet parent, int requestWidth, int requestHeight) { super(requestWidth, requestHeight, RGB); - initPlatform(parent, requestWidth, requestHeight, new String[] {}, new int[] {}, - new String[] {}, new String[] {}, ""); + initGStreamer(parent, requestWidth, requestHeight, capturePlugin, new String[] {}, new int[] {}, + new String[] {}, new String[] {}, ""); } /** @@ -105,8 +141,8 @@ public class Capture extends PImage implements PConstants { */ public Capture(PApplet parent, int requestWidth, int requestHeight, int frameRate) { super(requestWidth, requestHeight, RGB); - initPlatform(parent, requestWidth, requestHeight, new String[] {}, new int[] {}, - new String[] {}, new String[] {}, frameRate + "/1"); + initGStreamer(parent, requestWidth, requestHeight, capturePlugin, new String[] {}, new int[] {}, + new String[] {}, new String[] {}, frameRate + "/1"); } /** @@ -118,73 +154,34 @@ public class Capture extends PImage implements PConstants { */ public Capture(PApplet parent, int requestWidth, int requestHeight, String cameraName) { super(requestWidth, requestHeight, RGB); - initPlatform(parent, requestWidth, requestHeight, new String[] {}, new int[] {}, - new String[] { devicePropertyName() }, new String[] { cameraName }, ""); + if (devicePropertyName.equals("")) { + // For plugins without device name property, the name is casted as an index + initGStreamer(parent, requestWidth, requestHeight, capturePlugin, + new String[] { indexPropertyName }, new int[] { PApplet.parseInt(cameraName) }, + new String[] { }, new String[] { }, ""); + } else { + initGStreamer(parent, requestWidth, requestHeight, capturePlugin, new String[] {}, new int[] {}, + new String[] { devicePropertyName }, new String[] { cameraName }, ""); + } } /** *

Advanced

* This constructor allows to specify the camera name and the desired framerate. */ - public Capture(PApplet parent, int requestWidth, int requestHeight, int frameRate, - String cameraName) { + public Capture(PApplet parent, int requestWidth, int requestHeight, String cameraName, int frameRate) { super(requestWidth, requestHeight, RGB); - initPlatform(parent, requestWidth, requestHeight, new String[] {}, new int[] {}, - new String[] { devicePropertyName() }, new String[] { cameraName }, - frameRate + "/1"); + if (devicePropertyName.equals("")) { + // For plugins without device name property, the name is casted as an index + initGStreamer(parent, requestWidth, requestHeight, capturePlugin, + new String[] { indexPropertyName }, new int[] { PApplet.parseInt(cameraName) }, + new String[] { }, new String[] { }, frameRate + "/1"); + } else { + initGStreamer(parent, requestWidth, requestHeight, capturePlugin, new String[] {}, new int[] {}, + new String[] { devicePropertyName }, new String[] { cameraName }, frameRate + "/1"); + } } - /** - *

Advanced

- * This constructor lets to indicate which source element to use (i.e.: v4l2src, - * osxvideosrc, dshowvideosrc, ksvideosrc, etc). - * - * @nowebref - * @param sourceName ??? - */ - public Capture(PApplet parent, int requestWidth, int requestHeight, int frameRate, - String sourceName, String cameraName) { - super(requestWidth, requestHeight, RGB); - initGStreamer(parent, requestWidth, requestHeight, sourceName, new String[] {}, new int[] {}, - new String[] { devicePropertyName() }, new String[] { cameraName }, - frameRate + "/1"); - } - - /** - *

Advanced

- * This constructor accepts an arbitrary list of string properties for the source element. - * The camera name could be one of these properties. The framerate must be specified - * as a fraction string: 30/1, 15/2, etc. - * - * @nowebref - * @param strPropNames ??? - * @param strPropValues ??? - */ - public Capture(PApplet parent, int requestWidth, int requestHeight, String frameRate, - String sourceName, String[] strPropNames, String[] strPropValues) { - super(requestWidth, requestHeight, RGB); - initGStreamer(parent, requestWidth, requestHeight, sourceName, new String[] {}, new int[] {}, - strPropNames, strPropValues, frameRate); - } - - /** - *

Advanced

- * This constructor accepts an arbitrary list of string properties for the source element, - * as well as a list of integer properties. This could be useful if a camera cannot by - * specified by name but by index. Framerate must be a fraction string: 30/1, 15/2, etc. - * - * @nowebref - * @param intPropNames ??? - * @param intPropValues ??? - */ - public Capture(PApplet parent, int requestWidth, int requestHeight, String frameRate, - String sourceName, String[] strPropNames, String[] strPropValues, - String[] intPropNames, int[] intPropValues) { - super(requestWidth, requestHeight, RGB); - initGStreamer(parent, requestWidth, requestHeight, sourceName, intPropNames, intPropValues, - strPropNames, strPropValues, frameRate); - } - /** * Releases the gstreamer resources associated to this capture object. * It shouldn't be used after this. @@ -229,6 +226,17 @@ public class Capture extends PImage implements PConstants { delete(); } + /** + * Finalizer of the class. + */ + protected void finalize() throws Throwable { + try { + delete(); + } finally { + super.finalize(); + } + } + /** * Prints all the gstreamer elements currently used in the * current pipeline instance. @@ -350,6 +358,10 @@ public class Capture extends PImage implements PConstants { * @usage web_application */ public void stop() { + if (!pipelineReady) { + initPipeline(); + } + capturing = false; gpipeline.stop(); } @@ -458,15 +470,7 @@ public class Capture extends PImage implements PConstants { * @usage web_application */ static public String[] list() { - if (PApplet.platform == LINUX) { - return list("v4l2src"); - } else if (PApplet.platform == WINDOWS) { - return list("dshowvideosrc"); - } else if (PApplet.platform == MACOSX) { - return list("osxvideosrc"); - } else { - return null; - } + return list(capturePlugin); } /** @@ -477,7 +481,7 @@ public class Capture extends PImage implements PConstants { * @param sourceName String */ static public String[] list(String sourceName) { - return list(sourceName, devicePropertyName()); + return list(sourceName, devicePropertyName); } static protected String[] list(String sourceName, String propertyName) { @@ -560,29 +564,6 @@ public class Capture extends PImage implements PConstants { public String getSource() { return source; } - - // Tries to guess the best correct source elements for each platform. - protected void initPlatform(PApplet parent, int requestWidth, int requestHeight, - String[] intPropNames, int[] intPropValues, - String[] strPropNames, String[] strPropValues, - String frameRate) { - if (PApplet.platform == LINUX) { - initGStreamer(parent, requestWidth, requestHeight, "v4l2src", intPropNames, intPropValues, - strPropNames, strPropValues, frameRate); - } else if (PApplet.platform == WINDOWS) { - //initGStreamer(parent, requestWidth, requestHeight, "ksvideosrc", intPropNames, - // intPropValues, strPropNames, strPropValues, frameRate); - initGStreamer(parent, requestWidth, requestHeight, "dshowvideosrc", intPropNames, - intPropValues, strPropNames, strPropValues, frameRate); - //init(requestWidth, requestHeight, "dshowvideosrc", intPropNames, - // intPropValues, strPropNames, strPropValues, frameRate, addDecoder, null, ""); - } else if (PApplet.platform == MACOSX) { - initGStreamer(parent, requestWidth, requestHeight, "osxvideosrc", intPropNames, - intPropValues, strPropNames, strPropValues, frameRate); - } else { - parent.die("Error: unrecognized platform.", null); - } - } // The main initialization here. protected void initGStreamer(PApplet parent, int requestWidth, int requestHeight, String sourceName, @@ -817,23 +798,32 @@ public class Capture extends PImage implements PConstants { } } } else { - boolean sigleFrac = false; + boolean singleFrac = false; try { Fraction fr = str.getFraction("framerate"); addFps(fr); - sigleFrac = true; + singleFrac = true; } catch (Exception e) { } - if (!sigleFrac) { - ValueList flist = str.getValueList("framerate"); - // All the framerates are put together, but this is not - // entirely accurate since there might be some of them' - // that work only for certain resolutions. - for (int k = 0; k < flist.getSize(); k++) { - Fraction fr = flist.getFraction(k); - addFps(fr); + if (!singleFrac) { + ValueList flist = null; + + try { + flist = str.getValueList("framerate"); + } catch (Exception e) { } + + if (flist != null) { + // All the framerates are put together, but this is not + // entirely accurate since there might be some of them' + // that work only for certain resolutions. + for (int k = 0; k < flist.getSize(); k++) { + Fraction fr = flist.getFraction(k); + addFps(fr); + } + } + } } } @@ -861,32 +851,6 @@ public class Capture extends PImage implements PConstants { } } - static protected String devicePropertyName() { - // TODO: Check the property names - if (PApplet.platform == LINUX) { - return "device"; // Is this correct? - } else if (PApplet.platform == WINDOWS) { - return "device-name"; - } else if (PApplet.platform == MACOSX) { - return "device-name"; - } else { - return ""; - } - } - - static protected String indexPropertyName() { - // TODO: Check the property names - if (PApplet.platform == LINUX) { - return "device-index"; // Is this correct? Probably not. - } else if (PApplet.platform == WINDOWS) { - return "device-index"; - } else if (PApplet.platform == MACOSX) { - return "device"; - } else { - return ""; - } - } - public synchronized void disposeBuffer(Object buf) { ((Buffer)buf).dispose(); } diff --git a/java/libraries/video/src/processing/video/Movie.java b/java/libraries/video/src/processing/video/Movie.java index 04300aefd..c1e978bdd 100644 --- a/java/libraries/video/src/processing/video/Movie.java +++ b/java/libraries/video/src/processing/video/Movie.java @@ -134,6 +134,17 @@ public class Movie extends PImage implements PConstants { delete(); } + /** + * Finalizer of the class. + */ + protected void finalize() throws Throwable { + try { + delete(); + } finally { + super.finalize(); + } + } + /** * Prints all the gstreamer elements currently used in the * current player instance. @@ -374,6 +385,10 @@ public class Movie extends PImage implements PConstants { public void jump(float where) { if (seeking) return; + if (!sinkReady) { + initSink(); + } + boolean res; long pos = Video.secToNanoLong(where); @@ -384,7 +399,8 @@ public class Movie extends PImage implements PConstants { System.err.println("Seek operation failed."); } - // Will wait until any async state change (seek) has completed + // getState() will wait until any async state change + // (like seek in this case) has completed seeking = true; gplayer.getState(); seeking = false; diff --git a/java/libraries/video/src/processing/video/Video.java b/java/libraries/video/src/processing/video/Video.java index 322f7d157..f9c65f6cf 100644 --- a/java/libraries/video/src/processing/video/Video.java +++ b/java/libraries/video/src/processing/video/Video.java @@ -62,6 +62,11 @@ public class Video implements PConstants { } else {} } + protected static int bitsJVM; + static { + bitsJVM = PApplet.parseInt(System.getProperty("sun.arch.data.model")); + } + // Default location of the local install of gstreamer. Suggested by Charles Bourasseau. // When it is left as empty string, GSVideo will attempt to use the path from GSLibraryPath.get(), // otherwise it will use it as the path to the folder where the libgstreamer.dylib and other