Add support for custom device events and implement for CaptureManagerSDK driver

This commit is contained in:
Eduardo Ramos Ibáñez 2023-09-24 11:27:20 +02:00
parent d417760b30
commit 395d76a752
6 changed files with 78 additions and 3 deletions

View File

@ -3,7 +3,7 @@
<groupId>io.github.eduramiba</groupId>
<artifactId>webcam-capture-driver-native</artifactId>
<version>1.0.0</version>
<version>1.0.1</version>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>

View File

@ -2,5 +2,5 @@ package com.github.eduramiba.webcamcapture.drivers;
import com.github.sarxos.webcam.WebcamDevice;
public interface WebcamDeviceExtended extends WebcamDevice, WebcamDevice.FPSSource, WebcamDevice.BufferAccess, WebcamDeviceWithId, WebcamDeviceWithBufferOperations {
public interface WebcamDeviceExtended extends WebcamDevice, WebcamDevice.FPSSource, WebcamDevice.BufferAccess, WebcamDeviceWithId, WebcamDeviceWithBufferOperations, WebcamDeviceWithCustomEvents {
}

View File

@ -0,0 +1,14 @@
package com.github.eduramiba.webcamcapture.drivers;
import com.github.sarxos.webcam.WebcamDevice;
public interface WebcamDeviceWithCustomEvents extends WebcamDevice {
interface Listener {
void customEventReceived(String type, Object event);
}
void addCustomEventsListener(Listener listener);
boolean removeCustomEventsListener(Listener listener);
}

View File

@ -296,4 +296,15 @@ public class AVFVideoDevice implements WebcamDeviceExtended {
final Raster raster = Raster.createRaster(sampleModel, dataBuffer, null);
bufferedImage.setData(raster);
}
@Override
public void addCustomEventsListener(Listener listener) {
// NOOP. To be improved with custom events from AVFoundation
}
@Override
public boolean removeCustomEventsListener(Listener listener) {
// NOOP
return true;
}
}

View File

@ -12,6 +12,8 @@ import java.awt.image.*;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import javafx.scene.image.PixelFormat;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
@ -40,6 +42,8 @@ public class CaptureManagerFrameGrabberSession {
private int bufferSizeBytes = -1;
private long lastFrameTimestamp = -1;
private Consumer<String> customEventListener = (eventType) -> {};
public boolean init(
final CaptureManagerSource source,
final CaptureManagerStreamDescriptor stream,
@ -190,7 +194,11 @@ public class CaptureManagerFrameGrabberSession {
session.addUpdateStateListener(new IUpdateStateListener() {
@Override
public void invoke(int aCallEventCode, int aSessionDescriptor) {
LOG.info("invoke with (aCallEventCode, aSessionDescriptor) = ({}, {})", aCallEventCode, aSessionDescriptor);
final String eventType = eventCodeToEventName(aCallEventCode);
LOG.info("IUpdateStateListener invoked with (eventType, aSessionDescriptor) = ({}, {})", eventType, aSessionDescriptor);
customEventListener.accept("CaptureManagerSDK::" + eventType);
}
});
@ -199,6 +207,23 @@ public class CaptureManagerFrameGrabberSession {
return true;
}
private String eventCodeToEventName(int code) {
switch(code) {
case 1: return "Error";
case 2: return "Status_Error";
case 3: return "Execution_Error";
case 4: return "ItIsReadyToStart";
case 5: return "ItIsStarted";
case 6: return "ItIsPaused";
case 7: return "ItIsStopped";
case 8: return "ItIsEnded";
case 9: return "ItIsClosed";
case 10: return "VideoCaptureDeviceRemoved";
case 11: return "SnapTrigger";
default: return "UnknownEvent(" + code + ")";
}
}
private SinkValuePart findSinkValuePart(final CaptureManagerSinkFactory sinkFactory, final String name) {
return sinkFactory.getValueParts().stream()
.filter(s -> name == null || s.getValue().equalsIgnoreCase(name))
@ -321,6 +346,10 @@ public class CaptureManagerFrameGrabberSession {
copyBuffer(target, directBuffer);
}
public void setCustomEventListener(final Consumer<String> customEventListener) {
this.customEventListener = customEventListener != null ? customEventListener : (eventType -> {});
}
private static int copyBuffer(ByteBuffer dest, ByteBuffer src) {
final int nTransfer = Math.min(dest.remaining(), src.remaining());
if (nTransfer > 0) {

View File

@ -1,6 +1,7 @@
package com.github.eduramiba.webcamcapture.drivers.capturemanager;
import com.github.eduramiba.webcamcapture.drivers.WebcamDeviceExtended;
import com.github.eduramiba.webcamcapture.drivers.WebcamDeviceWithCustomEvents;
import com.github.eduramiba.webcamcapture.drivers.capturemanager.model.CaptureManagerMediaType;
import com.github.eduramiba.webcamcapture.drivers.capturemanager.model.CaptureManagerSource;
import com.github.eduramiba.webcamcapture.drivers.capturemanager.model.CaptureManagerStreamDescriptor;
@ -26,6 +27,8 @@ public class CaptureManagerVideoDevice implements WebcamDeviceExtended {
private final Dimension[] resolutions;
private Dimension resolution;
private final LinkedHashSet<WebcamDeviceWithCustomEvents.Listener> listeners = new LinkedHashSet<>();
private CaptureManagerFrameGrabberSession session = null;
public CaptureManagerVideoDevice(CaptureManagerSource source, List<CaptureManagerSinkFactory> sinksFactories) {
@ -103,6 +106,8 @@ public class CaptureManagerVideoDevice implements WebcamDeviceExtended {
session = new CaptureManagerFrameGrabberSession();
session.setCustomEventListener(this::customEventReceived);
final Pair<CaptureManagerStreamDescriptor, CaptureManagerMediaType> best = findBestMediaTypeInStreams(
source.getStreamDescriptors(),
resolution
@ -281,4 +286,20 @@ public class CaptureManagerVideoDevice implements WebcamDeviceExtended {
return session.toBufferedImage(byteBuffer);
}
@Override
public void addCustomEventsListener(Listener listener) {
listeners.add(listener);
}
@Override
public boolean removeCustomEventsListener(Listener listener) {
return listeners.remove(listener);
}
public void customEventReceived(String eventType) {
for (Listener l: listeners) {
l.customEventReceived(eventType, eventType);
}
}
}