sort retrieved capture formats in order of supported, unknown and unsupported pixel formats

This commit is contained in:
Craig Raw 2025-03-20 10:47:07 +02:00
parent 520c5f2cfa
commit 25a3f5539d
2 changed files with 85 additions and 12 deletions

View file

@ -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;
}
}
}

View file

@ -112,7 +112,7 @@ public class WebcamService extends ScheduledService<Image> {
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<Image> {
throw new UnsupportedOperationException("No resolutions supported by camera " + device.getName());
}
Map<WebcamResolution, CaptureFormat> supportedResolutions = device.getFormats().stream()
List<CaptureFormat> 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<WebcamResolution, CaptureFormat> 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<Image> {
}
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<Image> {
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 extends Enum<T>> T getNearestEnum(T target) {
return getNearestEnum(target, target.getDeclaringClass().getEnumConstants());
}