sarxos / webcam-capture

The goal of this project is to allow integrated or USB-connected webcams to be accessed directly from Java. Using provided libraries users are able to read camera images and detect motion. Main project consist of several sub projects - the root one, which contains required classes, build-in webcam driver compatible with Windows, Linux and Mac OS, which can stream images as fast as your camera can serve them (up to 50 FPS). Main project can be used standalone, but user is able to replace build-in driver with different one - such as OpenIMAJ, GStreamer, V4L4j, JMF, LTI-CIVIL, FMJ, etc.
http://webcam-capture.sarxos.pl
MIT License
2.28k stars 1.11k forks source link

macOS Catalina Issue #723

Open burniejm opened 5 years ago

burniejm commented 5 years ago

My javaFX app uses this library to capture video from a webcam on windows and mac. It has worked great on both platforms up until now. I am testing on macOS Catalina beta2 and now getWebCams() is returning nothing. My discoveryListener is not firing either. I have enabled debug logging as described in the wiki and I don't see any errors. I am using the default driver. Any idea what could be going on??

erdemy commented 5 years ago

Hi @burniejm seems there is a change in security permissions in macOS Cataline as: https://developer.apple.com/videos/play/wwdc2019/701/
 I am also looking for a solution.

erdemy commented 5 years ago

@sarxos any suggestions for that issue?

burniejm commented 5 years ago

I am actually only using webcam-capture to enumerate cameras and populate a dropdown of cameras. I am then using openCV to grab frames from the selected device index (gathered from webcam-capture). Even hardcoding the device index didn't work until I updated to the newest javaCV (1.5). My project already uses ffmpeg for various video tasks, so I implemented the ffmpeg driver for webcam-capture and used the "list-devices" command to populate my dropdown. Hope this helps.

erdemy commented 5 years ago

hi @burniejm may I ask how you are able to run ffmpeg driver on macOS? it expects to have /dev/videoX (X is a . number) device on computer.

burniejm commented 5 years ago

hi @burniejm may I ask how you are able to run ffmpeg driver on macOS? it expects to have /dev/videoX (X is a . number) device on computer.

Since I don't actually use the webcam library to capture all I really need is the index of the video devices and the name. I do rely on this library to scan for hardware changes (usb camera add/remove) using the WebcamDiscoveryListener functionality. Here is my pared down getUnixDevices method:

private List<WebcamDevice> getUnixDevices() {
        List<WebcamDevice> devices = new ArrayList<WebcamDevice>();

        String[] command = {
                getCommand(),
                "-f",
                "avfoundation",
                "-list_devices",
                "true",
                "-hide_banner",
                "-i",
                "\"\""
        };

        ProcessBuilder processBuilder = new ProcessBuilder(command);
        processBuilder.redirectErrorStream(true);

        try {
            Process process = processBuilder.start();

            InputStream inputStream = process.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

            String videoSeperator = "video devices";
            String audioSeperator = "audio devices";
            String captureScreenDevice = "capture screen";
            String line;

            while ((line = bufferedReader.readLine()) != null) {

                if(line.toLowerCase().contains(videoSeperator)) {
                    continue;
                }

                if(line.toLowerCase().contains(captureScreenDevice)) {
                    break;
                }

                if(line.toLowerCase().contains(audioSeperator)) {
                    break;
                }

                String[] lineArray = line.split("] ");
                FFmpegCliDevice device = new FFmpegCliDevice(lineArray[2]);
                devices.add(device);
            }

            try {
                process.waitFor();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } catch (IOException ex) {
            ex.printStackTrace();

        }

        return devices;
    }

I added an FFMpegCliDevice constructor that just takes a name as well.

erdemy commented 5 years ago

Hi @burniejm thanks for the sharing, definitely only solution we have now to get the camera list and names on Catalina. regards

ademzumbul commented 5 years ago

I am trying to run it on macos catalina beta, I have 2 questions:

1-) It cannot find dependency in pom.xml for webcam-capture-driver-ffmpeg-cli

`

com.github.sarxos
<artifactId>webcam-capture-driver-ffmpeg-cli</artifactId>
<version>0.3.12</version>

`

2-) I have tried other drivers listed on the page but, It could not detect any camera with other drivers? How you have resolved it?

burniejm commented 5 years ago

@ademzumbul I just manually added the driver files to my project as I couldn't get it to work using gradle.

paipeng commented 5 years ago

Hello,

I am using OpenIMAJGrabber on MAC for handling camera device. Now after update MAC OSX to 10.15, i can't get listed devices (empty).

Can anyone share any information about how to work OpenIMAJGrabber on MAC 10.15?

Regards,

Pai

dahveed123 commented 5 years ago

https://github.com/openimaj/openimaj/issues/170

Here is the issue for the default driver used by this library.

kkieffer commented 4 years ago

I'm having the same issue on Catalina. Looks like work was started on a fix for openimaj/openimaj#170 but no activity since Oct 2019.

kkieffer commented 4 years ago

The author of openimaj has just pushed an update 1.3.10 that fixes the Catalina issue. @sarxos could you incorporate this update?

kkieffer commented 4 years ago

I have PR (https://github.com/sarxos/webcam-capture/pull/765) that may address this issue.

sarxos commented 4 years ago

Hi @kkieffer Can you please take a look at the comment in your PR?

sarxos commented 4 years ago

Hi guys,

This should already be fixed by commit https://github.com/sarxos/webcam-capture/commit/ae28f268f081f2a1b13f06578a0f4fddb6ffc568 from @kkieffer. Can you please verify this issue with latest JAR, that is 0.3.13-SNAPSHOT, which is available here:

https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=com.github.sarxos&a=webcam-capture&v=0.3.13-SNAPSHOT

jingmingcn commented 4 years ago

@sarxos

I got the following error message on my macOS Catalina 10.15.4.

14:19:13.532 [main] DEBUG com.github.sarxos.webcam.Webcam - Setting new capture driver OpenImajDriver
Exception in thread "main" com.github.sarxos.webcam.WebcamException: java.util.concurrent.ExecutionException: com.github.sarxos.webcam.WebcamException: Cannot execute task
    at com.github.sarxos.webcam.WebcamDiscoveryService.getWebcams(WebcamDiscoveryService.java:124)
    at com.github.sarxos.webcam.Webcam.getWebcams(Webcam.java:893)
    at com.github.sarxos.webcam.Webcam.getDefault(Webcam.java:956)
    at com.github.sarxos.webcam.Webcam.getDefault(Webcam.java:933)
    at com.github.sarxos.webcam.Webcam.getDefault(Webcam.java:911)
    at gist.WebcamPanelExample.main(WebcamPanelExample.java:18)
Caused by: java.util.concurrent.ExecutionException: com.github.sarxos.webcam.WebcamException: Cannot execute task
    at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
    at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
    at com.github.sarxos.webcam.WebcamDiscoveryService.getWebcams(WebcamDiscoveryService.java:116)
    ... 5 more
Caused by: com.github.sarxos.webcam.WebcamException: Cannot execute task
    at com.github.sarxos.webcam.WebcamProcessor$AtomicProcessor.process(WebcamProcessor.java:72)
    at com.github.sarxos.webcam.WebcamProcessor.process(WebcamProcessor.java:140)
    at com.github.sarxos.webcam.WebcamTask.process(WebcamTask.java:46)
    at com.github.sarxos.webcam.ds.openimaj.OpenImajDriver$GetDevicesTask.getDevices(OpenImajDriver.java:47)
    at com.github.sarxos.webcam.ds.openimaj.OpenImajDriver.getDevices(OpenImajDriver.java:67)
    at com.github.sarxos.webcam.WebcamDiscoveryService$WebcamsDiscovery.call(WebcamDiscoveryService.java:36)
    at com.github.sarxos.webcam.WebcamDiscoveryService$WebcamsDiscovery.call(WebcamDiscoveryService.java:26)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:830)
Caused by: java.lang.UnsatisfiedLinkError: 'org.bridj.Pointer org.openimaj.video.capture.OpenIMAJGrabber.getVideoDevices()'
    at org.openimaj.video.capture.OpenIMAJGrabber.getVideoDevices(Native Method)
    at org.openimaj.video.capture.VideoCapture.getVideoDevices(VideoCapture.java:221)
    at com.github.sarxos.webcam.ds.openimaj.OpenImajDriver$GetDevicesTask.handle(OpenImajDriver.java:58)
    at com.github.sarxos.webcam.WebcamProcessor$AtomicProcessor.run(WebcamProcessor.java:81)
    ... 3 more

Process finished with exit code 1

Here is the source code which can be used to reproduce the case.

import javax.swing.JFrame;

import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamPanel;
import com.github.sarxos.webcam.WebcamResolution;
import com.github.sarxos.webcam.ds.openimaj.OpenImajDriver;

public class WebcamPanelExample {

    static {
       Webcam.setDriver(new OpenImajDriver());
    }

    public static void main(String[] args) throws InterruptedException {
        Webcam webcam = Webcam.getDefault();
        webcam.setViewSize(WebcamResolution.VGA.getSize());

        WebcamPanel panel = new WebcamPanel(webcam);
        panel.setFPSDisplayed(true);
        panel.setDisplayDebugInfo(true);
        panel.setImageSizeDisplayed(true);
        panel.setMirrored(true);

        JFrame window = new JFrame("Test webcam panel");
        window.add(panel);
        window.setResizable(true);
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.pack();
        window.setVisible(true);
    }
}

Here is the project depenencies in maven approach, and I also tried the Grade way, still NOT work:

<dependency>
    <groupId>com.github.sarxos</groupId>
    <artifactId>webcam-capture</artifactId>
    <version>0.3.13-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>com.github.sarxos</groupId>
    <artifactId>webcam-capture-driver-openimaj</artifactId>
    <version>0.3.13-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>org.openimaj</groupId>
    <artifactId>core-video-capture</artifactId>
    <version>1.4-SNAPSHOT</version>
</dependency>

IMO. I think this error is caused by the openIMAJ 3rd library, because I got the same error message

Caused by: java.lang.UnsatisfiedLinkError: 'org.bridj.Pointer org.openimaj.video.capture.OpenIMAJGrabber.getVideoDevices()'

when I test the code which only depended on the openIMAJ library without import the webcam-capture package.

So, in your opinion, is there any solution to this problem. Or this is caused by the macOS Catalina 10.15.4, which is just released a few days ago.

kkieffer commented 4 years ago

@jingmingcn try commenting out this line:

Webcam.setDriver(new OpenImajDriver());

The fix from my PR addressed the built in default driver (which is openImaj) in webcam capture. I neglected to remember that you can also load the external OpenImaj driver (separate source).

@sarxos can you also patch the driver-openimaj under webcam-capture-drivers?

jingmingcn commented 4 years ago

@kkieffer I got the same error message after removing the driver setting command line.

An update about this issue is the case works very well on my macOS Mojave 10.14.6. So I think this issue is caused by the lastest macOS Catalina 10.15.4, which requires more security permission.

I hope the information above will help you to figure out the problem and find a solution. Thanks for your great work.

kkieffer commented 4 years ago

Can you open your Console.app in /Applications/Utilities and see if anything is logged when you run?

Although I can now see which webcam devices are available, there's a problem when trying to open the camera. In console I see this:

Prompting policy for hardened runtime; service: kTCCServiceCamera requires entitlement com.apple.security.device.camera but it is missing for REQ:{ID: net.java.openjdk.cmd, PID[1631], auid: 501, euid: 501, binary path: '/Library/Frameworks/Java/jdk-14.jdk/Contents/Home/bin/java'}

jingmingcn commented 4 years ago

@kkieffer I got the following message bundling to the process syspolicyd from the console app on the macOS Catalina 10.15.4.

assessment denied for libOpenIMAJGrabber.dylib
com.apple.message.domain: com.apple.security.assessment.outcome2
com.apple.message.signature2: bundle:UNBUNDLED
com.apple.message.signature3: libOpenIMAJGrabber.dylib
com.apple.message.signature5: UNKNOWN
com.apple.message.signature4: 1
com.apple.message.signature: denied:no usable signature
SenderMachUUID: 821D8C33-5B0B-317C-B2CB-29137C319A18

I am not sure whether the updates above would help or not. I am kind of lacking the system driver's developing experience.

kkieffer commented 4 years ago

Ok - I have a solution, although it's not going to be pretty. But it does work. First, the process "java" does not have an entitlement to use the camera. The only way around this as far as I can figure is to re-sign the java executable. So for this you're going to need a Apple Developer certificate.

  1. Find the java binary in your sdk. Mine is located at: /Library/Java/JavaVirtualMachines/current/Contents/Home/bin>

  2. Create a file called entitlements.plist in the bin directory. It's the same as the existing java entitlements but I added the camera entitlement at the end.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>com.apple.security.cs.allow-jit</key>
    <true/>
    <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
    <true/>
    <key>com.apple.security.cs.disable-library-validation</key>
    <true/>
    <key>com.apple.security.cs.allow-dyld-environment-variables</key>
    <true/>
    <key>com.apple.security.cs.debugger</key>
    <true/>
    <key>com.apple.security.device.camera</key>
    <true/>
</dict>
</plist>
  1. Codesign the java binary. Force will re-sign over the existing signature. Note this assumes you have a 3rd party developer certificate in your keychain: codesign -s "3rd" --force --options runtime --entitlements entitlements.plist java

  2. Find the Info.plist file located two directories up and copy it into the bin directory: cp ../../Info.plist .

  3. Edit this file and add this key:

    <key>NSCameraUsageDescription</key>
    <string>Arggh Catalina and Java!</string>

Now, assuming you run your test code with this java binary, it should work. You will get a prompt asking for permission to use the camera.

Unfortunately, you're not going to be able to redistribute your jar to anyone with Catalina since they won't have the re-signed java binary.

The solution will be to package into a .app with the correct entitlements. However the JDK14 jpackage tool is broken at the moment and I'm waiting on this fix:

https://bugs.openjdk.java.net/browse/JDK-8237490

jingmingcn commented 4 years ago

@kkieffer Thanks for your solution which I believe will work. But in my own case, the java command is located in the system level folder named /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands, which protected by the macOS SIP. For now, I have two options, one is turning off the SIP which is too risky for my macOS Catalina 10.15.4 laptop carrying important work in progress; another one would be installing a duplicate Java or JDK application to do the compiling work. I will give you the update once I finish the test case.

Thanks for your great idea which really blows my mind.

jingmingcn commented 4 years ago

@kkieffer Here is the update about the solution you provided in the last thread been applied on the macOS Catalina 10.15.4.

First, I have to correct one mistake in the previous thread I posted, which said about the java command in the folder /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands. It turns out that the java located in that folder is not a real java function file, but a java verifying function file. After I unzip a JDK version 14 distribution into the folder /Library/Java/JavaVirtualMachines, the java -version command running in the terminal (or the iTerm2) can detect the last JDK version I just installed.

The conclusion is I have failed to make the solution you have given works on my case. By codesign the java file with the entitlement file and vi the Info.list with the insertion of the camera access declaration, the same error message still comes all the time.

12:28:49.212 [main] INFO  com.github.sarxos.webcam.Webcam - WebcamDefaultDriver capture driver will be used
12:28:49.221 [webcam-discovery-service] DEBUG c.g.s.w.d.b.WebcamDefaultDriver - Searching devices
Exception in thread "main" com.github.sarxos.webcam.WebcamException: java.util.concurrent.ExecutionException: com.github.sarxos.webcam.WebcamException: Cannot execute task
    at com.github.sarxos.webcam.WebcamDiscoveryService.getWebcams(WebcamDiscoveryService.java:124)
    at com.github.sarxos.webcam.Webcam.getWebcams(Webcam.java:893)
    at com.github.sarxos.webcam.Webcam.getDefault(Webcam.java:956)
    at com.github.sarxos.webcam.Webcam.getDefault(Webcam.java:933)
    at com.github.sarxos.webcam.Webcam.getDefault(Webcam.java:911)
    at gist.WebcamPanelExample.main(WebcamPanelExample.java:18)
Caused by: java.util.concurrent.ExecutionException: com.github.sarxos.webcam.WebcamException: Cannot execute task
    at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
    at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
    at com.github.sarxos.webcam.WebcamDiscoveryService.getWebcams(WebcamDiscoveryService.java:116)
    ... 5 more
Caused by: com.github.sarxos.webcam.WebcamException: Cannot execute task
    at com.github.sarxos.webcam.WebcamProcessor$AtomicProcessor.process(WebcamProcessor.java:72)
    at com.github.sarxos.webcam.WebcamProcessor.process(WebcamProcessor.java:140)
    at com.github.sarxos.webcam.WebcamTask.process(WebcamTask.java:46)
    at com.github.sarxos.webcam.ds.buildin.WebcamDefaultDriver$GetDevicesTask.getDevices(WebcamDefaultDriver.java:79)
    at com.github.sarxos.webcam.ds.buildin.WebcamDefaultDriver.getDevices(WebcamDefaultDriver.java:124)
    at com.github.sarxos.webcam.WebcamDiscoveryService$WebcamsDiscovery.call(WebcamDiscoveryService.java:36)
    at com.github.sarxos.webcam.WebcamDiscoveryService$WebcamsDiscovery.call(WebcamDiscoveryService.java:26)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: java.lang.UnsatisfiedLinkError: 'org.bridj.Pointer com.github.sarxos.webcam.ds.buildin.natives.OpenIMAJGrabber.getVideoDevices()'
    at com.github.sarxos.webcam.ds.buildin.natives.OpenIMAJGrabber.getVideoDevices(Native Method)
    at com.github.sarxos.webcam.ds.buildin.WebcamDefaultDriver$GetDevicesTask.handle(WebcamDefaultDriver.java:93)
    at com.github.sarxos.webcam.WebcamProcessor$AtomicProcessor.run(WebcamProcessor.java:81)
    ... 3 more

Process finished with exit code 1
assessment denied for libOpenIMAJGrabber.dylib
com.apple.message.domain: com.apple.security.assessment.outcome2
com.apple.message.signature2: bundle:UNBUNDLED
com.apple.message.signature3: libOpenIMAJGrabber.dylib
com.apple.message.signature5: UNKNOWN
com.apple.message.signature4: 1
com.apple.message.signature: denied:no usable signature
SenderMachUUID: 821D8C33-5B0B-317C-B2CB-29137C319A18

Thanks for your help anyway. Maybe the cause of the problem is due to my individual special case on macOS Catalina 10.15.4. I think I should switch to the macOS Mojave laptop to continue the work until the fix released in the future. So may God bless the programmers working on the openIMAJ project.

Here are some supplementary notes. When doing the codesign step, I used the identity belongs to my personal developer account, which is free and not officially confirmed by the Apple Developer Center. I think this may be the reason why I failed to apply the solution.

jingmingcn commented 4 years ago

@kkieffer Here is the update.

I found a solution to solve this issue, which is by explicitly declaring an environment variable name DYLD_LIBRARY_PATH to a folder contains the libOpenIMAJGrabber.dylib file.

Sorry for wasting your valuable time on a stupid question I have posted.

sarxos commented 4 years ago

Hi @jingmingcn, @kkieffer,

I believe this is not a stupid question at all. It's a real issue. Adding libOpenIMAJGrabber.dylib to DYLD_LIBRARY_PATH environment variable is only a workaround. Ideally I would like this dylib to be loaded automatically the same way as it's done for dll on Windows and so on Linux.

I'm not really familiar with the MacOS permissions, especially on the newer systems, and with current COVID-19 situation, have no access to Mac machine where I can test. If you have any ideas on how we can permanently fix this issue I'm willing to work this out somehow. Can building and signing it properly help in this case?

kkieffer commented 4 years ago

Ah, it turns out I had a copy of libOpenIMAJGrabber.dylib in my /usr/local/lib directory, which is why it worked for me. Removing this, I see:

Exception in thread "main" java.lang.UnsatisfiedLinkError: 'org.bridj.Pointer org.openimaj.video.capture.OpenIMAJGrabber.getVideoDevices()

I'm not familiar with bridj so I'll have to dig into it again. Perhaps @jonhare could comment.

sarxos commented 4 years ago

@kkieffer

I have two suspicions:

Option 1, a wrong BridJ version. Now when I look at the POM there is BridJ 0.7.0 used in Webcam Capture API and 0.7-20140918-2 in OpenIMAJ. To verify this case you can download version 0.7-20140918-2 from OpenIMAJ Maven repo:

http://maven.ecs.soton.ac.uk/content/groups/maven.openimaj.org/com/nativelibs4java/bridj/0.7-20140918-2/bridj-0.7-20140918-2.jar

Replace original BridJ with the one you downloaded and redo the test. If it fails, move to option 2.

Option 2, and I only guess, may be caused by the denied assessment mentioned in https://github.com/sarxos/webcam-capture/issues/723#issuecomment-606679227. If this is the case then maybe having your version of signed dylib would be a better option. At least this is something we could test against to verify if this is the root cause.

kkieffer commented 4 years ago

Option 1 - That works! However I had to manually do this, trying to change it in the pom file, I get this error:

The POM for com.nativelibs4java:bridj:jar:0.7-20140918-2 is missing, no dependency information available. Failed to execute goal on project webcam-capture: Could not resolve dependencies for project com.github.sarxos:webcam-capture:bundle:0.3.13-SNAPSHOT: Failure to find com.nativelibs4java:bridj:jar:0.7-20140918-2 in https://repo.maven.apache.org/maven2

I guess the folks from bridj need put release their next version.

jonhare commented 4 years ago

@kkieffer @sarxos I remember now - there was a problem with dyncall in the bridj 0.7 (and 0.7-20140918) builds that meant that it wouldn't pick up libraries loaded from unusual locations (bridj stores the libs in the jar, and then unpacks them and links them dynamically) when using Catalina. This was in addition to the deprecated video capture apis that I had to rewrite the code for. My modified bridj is in the openimaj maven repo (just add maven.openimaj.org as an additional repo in your pom file and it should work): http://maven.ecs.soton.ac.uk/content/groups/maven.openimaj.org/com/nativelibs4java/bridj/0.7-20140918-2/ All it does is update the dyncall version (from last October).

I suspect that going forwards we are going to hit problems with the dylibs not being signed though that will need addressing. I can probably sign the libOpenIMAJGrabber.dylib and the bridj dylibs, but I'm not sure if that will be enough (the java executable would need signing and also need entitlements to load dylibs from arbitrary places; I'm guessing the bridj dylibs need similar entitlements and the OpenIMAJ one needs the camera entitlement). I literally know nothing about any of this though!!

kkieffer commented 4 years ago

@jonhare can you submit your fix to bridj to their mainline?

I have not had a problem using unsigned openimaj library at this point but I'm actually surprised that it works without signing. In addition to signing the dylibs must be notarized for Catalina.

I don't think the dylibs need any entitlements. That's for the binary (java) to supply.

kkieffer commented 4 years ago

Oh, the reason it works without signing the dylib is the java binary has the entitlement

<key>com.apple.security.cs.disable-library-validation</key>

which allows unsigned libraries to be executed.

jonhare commented 4 years ago

@kkieffer not sure if @ochafik is still actively maintaining bridj these days... Olivier - ping me if you're able to do a new release and we can figure out what I changed.

The fact that library verification is disabled certainly makes things a lot easier for us for now! How does that interact with other entitlements though - does it allow the library to do absolutely anything (like open the camera, albeit with asking permission the first time around)?

kkieffer commented 4 years ago

You still need a camera entitlement for the main exe - and the changes you made in the dylib prompt the user for permission to use the camera. I had to modify the java binary entitlement to include camera, as well as Info.plist with a reason why java should be able to use the camera. See:

https://github.com/sarxos/webcam-capture/issues/723#issuecomment-606714970

jonhare commented 4 years ago

@kkieffer sorry, I'm asking lots of questions: can a library have an entitlement? I'd have assumed in our case the idea thing would be for the java executable to be allowed to load libraries (but not do anything else) & each library to have entitlements for anything specific they wanted to do (like access the camera)?

kkieffer commented 4 years ago

Good question - I could try signing the dylib with the entitlement. But I think the Info.plist would still be needed on whatever is calling into the library.

kkieffer commented 4 years ago

No good - it appears the entitlement is tied to the launched binary, not the library. I get this:

image
kkieffer commented 4 years ago

@sarxos Would like to put this thread to conclusion. With your latest snapshot jar and substituting in the bridj library version 0.7-20140918-2 from @jonhare I was able to build my java application into an .app, sign it, and distribute it to Catalina machines. Running the app on Catalina, it prompts to use the camera correctly and if the user accepts, I get streaming video just fine.

I would say the problem is resolved but to tidy up, could you add the new bridj library as a dependency and release a new version to maven?

If if @ochafik is not actively maintaining bridj then perhaps either use the artifact from openimaj or one of us could fork bridj and release a new artifact to maven central.

craigraw commented 4 years ago

@jonhare is the source that created bridj-0.7-20140918-2.jar available somewhere? Unsure whether it is at https://github.com/jonhare/nativelibs4java

I ask because there is another issue when using modules in Java 9+ discussed in #586 which requires a one line fix. I've created a jar which copies the .class files with this fix into bridj-0.7-20140918-2.jar and it's working on Catalina with Java modules, but obviously not ideal.

ekamikke commented 4 years ago

@jonhare I would also be curious where I could find the sources for the bridj-0.7-20140918-2 build.

jonhare commented 4 years ago

@ekamikke @craigraw sorry - I missed this the first time around. I believe (but I'm not 100% sure) that it is based off https://github.com/jonhare/nativelibs4java (which added armhf and armel support), but with a new dyncall dylib (straight build of the dyncall 1.0 source) just for OSX. As it was a quick fix, I just patched the bridj-0.7-20140918 jar with the updated library.

For a quick fix, I could patch the bridj-0.7-20140918-2 jar with the change required for java 9 if someone tells me what needs changing?

Going forwards we should perhaps try to work together to sort this mess out... Probably starting with @ochafik's latest sources, merging in the changes from my branch for arm support (which really need testing on a modern arm platform, not one from 2014!) and fixing the Java 9 issue.

craigraw commented 4 years ago

Hi @jonhare - no problems and thanks for the original fix! It's been working well. Would love to have the security of having access to the source though.

Re the Java 9 change, as I recall it's just a one line addition in Platform.java - see the last diff at this link: https://github.com/nativelibs4java/BridJ/compare/master...ConsensusJ:consensusj-master#

It effectively just removes the leading / from the path allowing the classloader to find the resource in Java 9 and up.

ekamikke commented 4 years ago

@jonhare I do agree with @craigraw that having the sources for builds would obviously be preferable. However this at least gives all the info on how to rebuild it if needed. Thanks a lot for the quick response!

I am using the 0.7-20140918-2 build as such in OpenJdk 11. No issues found when running org.openimaj:core-video-capture:1.3.10 on it on OSX Catalina or Windows 10.

jonhare commented 4 years ago

Totally agreed we need to have actual source. Looking more closely I'm pretty much satisfied that the original 0.7-20140918 version corresponds with the HEAD of the master branch of https://github.com/jonhare/nativelibs4java (not least because the dates tie up exactly!)

I'll add the Java 9 fix & back-port the dyncall fix into my fork of the code and then make a new release. We we can think about whether we need any of the other changes that @ochafik made after the 18th Sept 2014...

jonhare commented 4 years ago

@ekamikke @craigraw are you willing to do some testing? http://maven.openimaj.org/com/nativelibs4java/bridj/0.7-20140918-3/ has jars with a fix for java 9 and also the dyncall fix on OSX. My java 9 fix for modules is slightly different to the one-liner because I wasn't convinced that it wouldn't break older Java versions or non-module based projects in Java 9+. Source code for the build is here: https://github.com/jonhare/nativelibs4java/tree/0.7-20140918-3

craigraw commented 4 years ago

Thanks @jonhare! It's working here on

This is on a Java 9 modules project.

Hopefully @ochafik can make this an official release.

ekamikke commented 4 years ago

This is awesome @jonhare. Verified it works on OSX Catalina and Windows 10 on Corretto JDK 11. Thanks a whole bunch!

I forked your repo because we prefer to not depend on custom builds from unofficial repositories directly. With the changes you made I am able to compile and package the BridJ project, but only if I ignore tests. Did all tests pass for you?

jonhare commented 4 years ago

@ekamikke re tests - yes tests were fine for me (Catalina 10.15.4, JDK 1.8.0_121). I had to update the STLTest and JAWTTest to the versions in the official HEAD version in one of the commits I made though...

Venorcis commented 4 years ago

Using webcam-capture 0.3.13-SNAPSHOT with bridj 0.7-20140918-3 (from maven.openimaj.org) makes everything work on Mac again for me.

frankfliu commented 3 years ago

I got a JVM crash with webcam-capture 0.3.13-SNAPSHOT and bridj 0.7-20140918-3.

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00000001032dbaa0, pid=65460, tid=0x000000000000a703
#
# JRE version: Java(TM) SE Runtime Environment (8.0_231-b11) (build 1.8.0_231-b11)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.231-b11 mixed mode bsd-amd64 compressed oops)
# Problematic frame:
# V  [libjvm.dylib+0xdbaa0]  acl_CopyRight+0x29
#

Sometime I got another error:

[main] INFO com.github.sarxos.webcam.Webcam - WebcamDefaultDriver capture driver will be used
[atomic-processor-1] INFO com.github.sarxos.webcam.ds.cgt.WebcamOpenTask - Opening webcam FaceTime HD Camera (Built-in) 0x8020000005ac8514
[atomic-processor-1] INFO com.github.sarxos.webcam.ds.cgt.WebcamCloseTask - Closing FaceTime HD Camera (Built-in) 0x8020000005ac8514
[atomic-processor-1] INFO com.github.sarxos.webcam.ds.cgt.WebcamOpenTask - Opening webcam FaceTime HD Camera (Built-in) 0x8020000005ac8514
[frames-refresher-[0x8020000005ac8514]] ERROR com.github.sarxos.webcam.ds.buildin.WebcamDefaultDevice - Timeout when requesting image!
ripcurlx commented 3 years ago

@sarxos Do you have any plans to wrap this into an official release?