Xuggle 和 java 库路径

发布于 2024-12-14 15:30:35 字数 6455 浏览 4 评论 0原文

我正在用 Java 编写一个截屏应用程序。 我决定使用 Xuggle 来完成此操作,并按照 xuggle wiki 上的安装说明进行操作。

我使用 %XUGGLE_HOME%\bin 和 %XUGGLE_HOME%\lib 设置 PATH 环境。一切看起来都还好。 我将此应用程序制作为 RCP 插件。我在“RCP-mail”模板上尝试过,该插件正在工作并且视频已正确生成。

但是当我决定在“真正的”应用程序上使用它时,插件崩溃并显示一条奇怪的错误消息:

开始捕获

2011-11-10 08:08:45,438 [Thread-5] 警告 com.xuggle.ferry.JNILibraryLoader - 失败:库加载:xuggle-xuggler;版本:3:绝对路径:C:\Program Files (x86)\Xuggle\bin\libxuggle-xuggler-3.dll;错误:java.lang.UnsatisfiedLinkError:C:\Program Files (x86)\Xuggle\bin\libxuggle-xuggler-3.dll:找不到依赖库

2011-11-10 08:08:45,447 [Thread-5] 警告 com.xuggle.ferry.JNILibraryLoader - 失败:库加载:xuggle-xuggler;版本:3:绝对路径:C:\Program Files (x86)\Xuggle\bin\libxuggle-xuggler-3.dll;错误:java.lang.UnsatisfiedLinkError:C:\Program Files (x86)\Xuggle\bin\libxuggle-xuggler-3.dll:找不到依赖库

2011-11-10 08:08:45,453 [Thread-5] 错误 com.xuggle.ferry.JNILibraryLoader - 无法加载库:xuggle-xuggler;版本:3;访问 http://www.xuggle.com/xuggler/faq/ 查找常见解决方案对于这个问题

很奇怪,因为 java.library.path 定义良好:

logger.info(System.getProperty("java.library.path"));

返回

Nov 10, 2011 8:08:45 AM com.gvs.tools.ui.record.video.handler.RecordHandler startRecording
INFO: C:\Program Files (x86)\Java\jre6\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:/Program Files (x86)/Java/jre6/bin/client;C:/Program Files (x86)/Java/jre6/bin;C:/Program Files (x86)/Java/jre6/lib/i386;C:\Program Files (x86)\Xuggle\bin;C:\Program Files (x86)\Xuggle\lib;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\JProbe 8.3\bin;C:\Program Files\TortoiseSVN\bin;D:\Work\Paul\eclipse;;.

我缺少什么来使插件与此应用程序一起工作? 此问题是否是由于应用程序使用其他本机库(例如 3D-dll)所致?

以下是用于制作截屏视频的代码:

RecordHandler.java:
    private void startRecording() {

    Logger logger = Logger.getLogger(RecordHandler.class.getName());
    logger.info(System.getProperty("java.library.path"));

    // Initialize framesQueue
    framesQueue =  new LinkedBlockingQueue<BufferedImage>();
    // Initialize the capture thread
    captureThread =  new ScreenCapturer();
    captureThread.setCaptureFramesQueue(framesQueue);
    
    // Initialize the recorder
    encoderThread = new FrameEncoder("test.mp4");
    encoderThread.setCapturedFramesQueue(framesQueue);      
    
    // Start capture
    captureThread.start();
    // wait for the Queue to be feed before encoding
    try {
        Thread.sleep(1000L);
    } catch (InterruptedException e) {
    }
    encoderThread.start();
}

ScreenCapturer.java:

    @Override
public void run() {
    // Retrieve the application main window's shell
    Display.getDefault().asyncExec(new Runnable() {
        
        @Override
        public void run() {
            appShell = Display.getCurrent().getActiveShell();
        }
    });
    
    isRunning = true;
    System.out.println("Starting Capture");
    for (numberOfFramesTaken = 0; isRunning && numberOfFramesTaken <= IVideoEncoderConfiguration.MAXIMUM_NUMBER_OF_FRAMES; numberOfFramesTaken++) {
        try {
            takeScreenShot();
            Thread.sleep(IVideoEncoderConfiguration.CAPTURE_TIME_INTERVAL_MILLIS);
        } catch (InterruptedException e) {
        }
    }
    System.out.println("Capture has ended");
    System.out.println("Number of frames taken: "
            + numberOfFramesTaken);
}

/**
 * Take a screen capture and store it in the capturedFramesQueue
 */
private void takeScreenShot() {
    Display.getDefault().asyncExec(new Runnable() {
        @Override
        public void run() {
            if (appShell != null) {
                Rectangle bounds = appShell.getBounds();
                java.awt.Rectangle awtBounds =  new java.awt.Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
                final BufferedImage screenCapture =  robot.createScreenCapture(awtBounds);
                try {
                    capturedFramesQueue.put(screenCapture);
                } catch (InterruptedException e) {
                }
            }
        }
    });
}

FrameEncoder.java:

public void run() {
    isRunning = true;
    String outFile = outputdirectoryPath + outputFileName;
    // First, let's make a IMediaWriter to write the file.
    final IMediaWriter writer = ToolFactory.makeWriter(outFile);
    // Retrieve the first frame to guess video dimensions
    BufferedImage firstFrame = null;
    try {
        firstFrame = capturedFramesQueue.take();
    } catch (InterruptedException e) {
    }
    if (firstFrame == null) {
        return;
    }
    // We tell it we're going to add one video stream, with id 0,
    // at position 0, and that it will have a fixed frame rate of
    // FRAME_RATE.
    writer.addVideoStream(0, 0,
            IVideoEncoderConfiguration.FRAME_RATE,
            firstFrame.getWidth(), firstFrame.getHeight());
    
    long startTime = System.nanoTime();
    for (numberOfFramesRecorded = 0; isRunning
            && numberOfFramesRecorded <= IVideoEncoderConfiguration.MAXIMUM_NUMBER_OF_FRAMES; numberOfFramesRecorded++) {
        // Retrieve the captured frame
        try {
            final BufferedImage currentFrame = convertToType(capturedFramesQueue.take(), BufferedImage.TYPE_3BYTE_BGR);
            // encode the next frame
            writer.encodeVideo(0, currentFrame, System.nanoTime() - startTime,
                    TimeUnit.NANOSECONDS);
            // sleep, time depending of FRAME_RATE
            Thread.sleep(IVideoEncoderConfiguration.CAPTURE_TIME_INTERVAL_MILLIS);
        } catch (InterruptedException e) {
        }
    }
    // Get the remaining frame on the queue
    Collection<BufferedImage> frames = new LinkedList<BufferedImage>();
    capturedFramesQueue.drainTo(frames, IVideoEncoderConfiguration.MAXIMUM_NUMBER_OF_FRAMES - numberOfFramesRecorded);
    for (BufferedImage frame : frames) {
        BufferedImage currentFrame = convertToType(frame, BufferedImage.TYPE_3BYTE_BGR);
        writer.encodeVideo(0, currentFrame, System.nanoTime() - startTime,
                TimeUnit.NANOSECONDS);
    }
    // close the MediaWriter, write the trailer if needed
    writer.close();
}

I'm writing a screencast application in Java.
I decided to use Xuggle to do it and I followed up the installation instructions on the xuggle wiki.

I set up the PATH environment with %XUGGLE_HOME%\bin and %XUGGLE_HOME%\lib. Everything seems OK.
I made this application as a RCP plugin. I tried it on the "RCP-mail" template and the plugin is working and the video is generated correctly.

But when I decided to use it on a "real" application, the plug-in crashed with a strange error message:

Starting Capture

2011-11-10 08:08:45,438 [Thread-5] WARN com.xuggle.ferry.JNILibraryLoader - Failure: library load of library: xuggle-xuggler; version: 3: absolute path: C:\Program Files (x86)\Xuggle\bin\libxuggle-xuggler-3.dll; error: java.lang.UnsatisfiedLinkError: C:\Program Files (x86)\Xuggle\bin\libxuggle-xuggler-3.dll: Can't find dependent libraries

2011-11-10 08:08:45,447 [Thread-5] WARN com.xuggle.ferry.JNILibraryLoader - Failure: library load of library: xuggle-xuggler; version: 3: absolute path: C:\Program Files (x86)\Xuggle\bin\libxuggle-xuggler-3.dll; error: java.lang.UnsatisfiedLinkError: C:\Program Files (x86)\Xuggle\bin\libxuggle-xuggler-3.dll: Can't find dependent libraries

2011-11-10 08:08:45,453 [Thread-5] ERROR com.xuggle.ferry.JNILibraryLoader - Could not load library: xuggle-xuggler; version: 3; Visit http://www.xuggle.com/xuggler/faq/ to find common solutions to this problem

But this strange because the java.library.path is well defined:

logger.info(System.getProperty("java.library.path"));

returns

Nov 10, 2011 8:08:45 AM com.gvs.tools.ui.record.video.handler.RecordHandler startRecording
INFO: C:\Program Files (x86)\Java\jre6\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:/Program Files (x86)/Java/jre6/bin/client;C:/Program Files (x86)/Java/jre6/bin;C:/Program Files (x86)/Java/jre6/lib/i386;C:\Program Files (x86)\Xuggle\bin;C:\Program Files (x86)\Xuggle\lib;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\JProbe 8.3\bin;C:\Program Files\TortoiseSVN\bin;D:\Work\Paul\eclipse;;.

What I'm missing to make the plug-in work with this application?
Is this issue due to the fact that the application uses other native libraries such as 3D-dll?

Here is the code used to make the screencast video:

RecordHandler.java:
    private void startRecording() {

    Logger logger = Logger.getLogger(RecordHandler.class.getName());
    logger.info(System.getProperty("java.library.path"));

    // Initialize framesQueue
    framesQueue =  new LinkedBlockingQueue<BufferedImage>();
    // Initialize the capture thread
    captureThread =  new ScreenCapturer();
    captureThread.setCaptureFramesQueue(framesQueue);
    
    // Initialize the recorder
    encoderThread = new FrameEncoder("test.mp4");
    encoderThread.setCapturedFramesQueue(framesQueue);      
    
    // Start capture
    captureThread.start();
    // wait for the Queue to be feed before encoding
    try {
        Thread.sleep(1000L);
    } catch (InterruptedException e) {
    }
    encoderThread.start();
}

ScreenCapturer.java:

    @Override
public void run() {
    // Retrieve the application main window's shell
    Display.getDefault().asyncExec(new Runnable() {
        
        @Override
        public void run() {
            appShell = Display.getCurrent().getActiveShell();
        }
    });
    
    isRunning = true;
    System.out.println("Starting Capture");
    for (numberOfFramesTaken = 0; isRunning && numberOfFramesTaken <= IVideoEncoderConfiguration.MAXIMUM_NUMBER_OF_FRAMES; numberOfFramesTaken++) {
        try {
            takeScreenShot();
            Thread.sleep(IVideoEncoderConfiguration.CAPTURE_TIME_INTERVAL_MILLIS);
        } catch (InterruptedException e) {
        }
    }
    System.out.println("Capture has ended");
    System.out.println("Number of frames taken: "
            + numberOfFramesTaken);
}

/**
 * Take a screen capture and store it in the capturedFramesQueue
 */
private void takeScreenShot() {
    Display.getDefault().asyncExec(new Runnable() {
        @Override
        public void run() {
            if (appShell != null) {
                Rectangle bounds = appShell.getBounds();
                java.awt.Rectangle awtBounds =  new java.awt.Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
                final BufferedImage screenCapture =  robot.createScreenCapture(awtBounds);
                try {
                    capturedFramesQueue.put(screenCapture);
                } catch (InterruptedException e) {
                }
            }
        }
    });
}

FrameEncoder.java:

public void run() {
    isRunning = true;
    String outFile = outputdirectoryPath + outputFileName;
    // First, let's make a IMediaWriter to write the file.
    final IMediaWriter writer = ToolFactory.makeWriter(outFile);
    // Retrieve the first frame to guess video dimensions
    BufferedImage firstFrame = null;
    try {
        firstFrame = capturedFramesQueue.take();
    } catch (InterruptedException e) {
    }
    if (firstFrame == null) {
        return;
    }
    // We tell it we're going to add one video stream, with id 0,
    // at position 0, and that it will have a fixed frame rate of
    // FRAME_RATE.
    writer.addVideoStream(0, 0,
            IVideoEncoderConfiguration.FRAME_RATE,
            firstFrame.getWidth(), firstFrame.getHeight());
    
    long startTime = System.nanoTime();
    for (numberOfFramesRecorded = 0; isRunning
            && numberOfFramesRecorded <= IVideoEncoderConfiguration.MAXIMUM_NUMBER_OF_FRAMES; numberOfFramesRecorded++) {
        // Retrieve the captured frame
        try {
            final BufferedImage currentFrame = convertToType(capturedFramesQueue.take(), BufferedImage.TYPE_3BYTE_BGR);
            // encode the next frame
            writer.encodeVideo(0, currentFrame, System.nanoTime() - startTime,
                    TimeUnit.NANOSECONDS);
            // sleep, time depending of FRAME_RATE
            Thread.sleep(IVideoEncoderConfiguration.CAPTURE_TIME_INTERVAL_MILLIS);
        } catch (InterruptedException e) {
        }
    }
    // Get the remaining frame on the queue
    Collection<BufferedImage> frames = new LinkedList<BufferedImage>();
    capturedFramesQueue.drainTo(frames, IVideoEncoderConfiguration.MAXIMUM_NUMBER_OF_FRAMES - numberOfFramesRecorded);
    for (BufferedImage frame : frames) {
        BufferedImage currentFrame = convertToType(frame, BufferedImage.TYPE_3BYTE_BGR);
        writer.encodeVideo(0, currentFrame, System.nanoTime() - startTime,
                TimeUnit.NANOSECONDS);
    }
    // close the MediaWriter, write the trailer if needed
    writer.close();
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

云淡风轻 2024-12-21 15:30:35

我知道有点晚了,但问题是 Xuggler 要求所有 DLL 都位于操作系统加载路径环境中,而不仅仅是 java.library.path

这意味着使用 Xuggler 安装的所有 DLL(例如,libavcodec .dll)需要位于启动 Java 的进程的 %PATH% 环境变量中。

It's a little late I know, but the problem is that Xuggler requires ALL THE DLLs to be in the operating system load-path environment, not just the java.library.path

That means that all DLLs that install with Xuggle (for example, libavcodec.dll) need to be in the %PATH% environment variable of the process that launched Java.

旧人九事 2024-12-21 15:30:35

原因可能是依赖项 jar 不可用或版本冲突。

在类路径中添加以下 jar 对我来说效果很好:

xuggle-xuggler-5.4.jar
slf4j-api-1.6.4.jar
logback-core-1.0.0.jar
logback-classic-1.0.0.jar

Cause Could be un-availability of dependency jars or version conflicts.

Adding the following jars in the class path worked fine for me:

xuggle-xuggler-5.4.jar
slf4j-api-1.6.4.jar
logback-core-1.0.0.jar
logback-classic-1.0.0.jar

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文