diff --git a/src/main/java/com/sparrowwallet/sparrow/control/WebcamPixelFormat.java b/src/main/java/com/sparrowwallet/sparrow/control/WebcamPixelFormat.java new file mode 100644 index 00000000..ac14e4a0 --- /dev/null +++ b/src/main/java/com/sparrowwallet/sparrow/control/WebcamPixelFormat.java @@ -0,0 +1,75 @@ +package com.sparrowwallet.sparrow.control; + +import com.sparrowwallet.drongo.OsType; + +public enum WebcamPixelFormat { + PIX_FMT_420V("420v", true), + PIX_FMT_YUVS("yuvs", true), + PIX_FMT_RGB24("RGB3", true), + PIX_FMT_YUYV("YUYV", true), + PIX_FMT_MPJG("MPJG", true), + PIX_FMT_YUY2("YUY2", true), + PIX_FMT_NV12("NV12", false); + + private final String name; + private final boolean supported; + + WebcamPixelFormat(String name, boolean supported) { + this.name = name; + this.supported = supported; + } + + public String getName() { + return name; + } + + public boolean isSupported() { + return supported; + } + + public String toString() { + return name; + } + + public static WebcamPixelFormat fromFourCC(int fourCC) { + String strFourCC = fourCCToString(fourCC); + for(WebcamPixelFormat pixelFormat : WebcamPixelFormat.values()) { + if(pixelFormat.name().equalsIgnoreCase(strFourCC)) { + return pixelFormat; + } + } + + return null; + } + + public static String fourCCToString(int fourCC) { + int fccVal = fourCC; + int tmp = fccVal; + + if(OsType.getCurrent() == OsType.MACOS) { + tmp = ((tmp >> 16) & 0x0000FFFF) | ((tmp << 16) & 0xFFFF0000); + tmp = ((tmp & 0x00FF00FF) << 8) | ((tmp & 0xFF00FF00) >>> 8); + } + + fccVal = tmp; + + StringBuilder v = new StringBuilder(4); + for(int i = 0; i < 4; i++) { + char c = (char) (fccVal & 0xFF); + v.append(c); + fccVal >>>= 8; + } + + return v.toString(); + } + + public static int getPriority(WebcamPixelFormat pixelFormat) { + if(pixelFormat == null) { + return 1; + } else if(pixelFormat.isSupported()) { + return 0; + } else { + return 2; + } + } +} diff --git a/src/main/java/com/sparrowwallet/sparrow/control/WebcamService.java b/src/main/java/com/sparrowwallet/sparrow/control/WebcamService.java index a967e34b..1073bf0a 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/WebcamService.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/WebcamService.java @@ -112,7 +112,7 @@ public class WebcamService extends ScheduledService { throw new UnsupportedOperationException("No cameras available"); } - CaptureDevice selectedDevice = devices.getFirst(); + CaptureDevice selectedDevice = devices.stream().filter(d -> !d.getFormats().isEmpty()).findFirst().orElse(devices.getFirst()); if(device != null) { for(CaptureDevice webcam : devices) { @@ -134,7 +134,14 @@ public class WebcamService extends ScheduledService { throw new UnsupportedOperationException("No resolutions supported by camera " + device.getName()); } - Map supportedResolutions = device.getFormats().stream() + List deviceFormats = new ArrayList<>(device.getFormats()); + deviceFormats.sort((f1, f2) -> { + WebcamPixelFormat pf1 = WebcamPixelFormat.fromFourCC(f1.getFormatInfo().fourcc); + WebcamPixelFormat pf2 = WebcamPixelFormat.fromFourCC(f2.getFormatInfo().fourcc); + return Integer.compare(WebcamPixelFormat.getPriority(pf1), WebcamPixelFormat.getPriority(pf2)); + }); + + Map supportedResolutions = deviceFormats.stream() .filter(f -> WebcamResolution.from(f) != null) .collect(Collectors.toMap(WebcamResolution::from, Function.identity(), (u, v) -> u, TreeMap::new)); resolutions = supportedResolutions.keySet(); @@ -151,7 +158,7 @@ public class WebcamService extends ScheduledService { } if(log.isDebugEnabled()) { - log.debug("Opening capture stream on " + device + " with format " + format.getFormatInfo().width + "x" + format.getFormatInfo().height + " (" + fourCCToString(format.getFormatInfo().fourcc) + ")"); + log.debug("Opening capture stream on " + device + " with format " + format.getFormatInfo().width + "x" + format.getFormatInfo().height + " (" + WebcamPixelFormat.fourCCToString(format.getFormatInfo().fourcc) + ")"); } opening.set(true); @@ -367,15 +374,6 @@ public class WebcamService extends ScheduledService { return closed; } - public static String fourCCToString(int fourCC) { - return new String(new char[] { - (char) (fourCC >> 24 & 0xFF), - (char) ((fourCC >> 16) & 0xFF), - (char) ((fourCC >> 8) & 0xFF), - (char) ((fourCC) & 0xFF) - }); - } - public static > T getNearestEnum(T target) { return getNearestEnum(target, target.getDeclaringClass().getEnumConstants()); }