java 如何使用 JMF 捕获视频,但不安装 JMF

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4046621/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 04:32:27  来源:igfitidea点击:

How to capture video using JMF, but without installing JMF

javadistributionjmfjava-native-library

提问by user489041

A videoconferencing project I was working on used JMF to capture video and audio, and transmit it to another endpoint. An issue was that my team didn't want the user of the product to have to install JMF.

我正在处理的一个视频会议项目使用 JMF 捕获视频和音频,并将其传输到另一个端点。一个问题是我的团队不希望产品的用户必须安装 JMF。

I thought it might be worthwhile to share our solution to this problem. It works. It works well. My question to you is: does anyone have a better way to do it?

我认为分享我们对这个问题的解决方案可能是值得的。有用。它运作良好。我要问你的问题是:有没有人有更好的方法来做到这一点?

Environment: Windows, XP and above

环境:Windows、XP及以上

  1. Download JMF for Windows
  2. Install it on your machine

  3. Locate the following dlls in the system32 folder after jmf installs:

    jmacm.dll
    jmam.dll
    jmcvid.dll
    jmdaud.dll
    jmdaudc.dll
    jmddraw.dll
    jmfjawt.dll
    jmg723.dll
    jmgdi.dll
    jmgsm.dll
    jmh261.dll
    jmh263enc.dll
    jmjpeg.dll
    jmmci.dll
    jmmpa.dll
    jmmpegv.dll
    jmutil.dll
    jmvcm.dll
    jmvfw.dll
    jmvh263.dll
    jsound.dll

  4. Copy the dlls into a temporary folder

  5. Locate the jmf.propertiesfile (Do a search on your computer for it)
  6. Download the JMF source code
    In the source code, find the following files:
  1. 下载适用于 Windows 的 JMF
  2. 将其安装在您的机器上

  3. dlljmf安装后在system32文件夹中找到以下s:

    jmacm.dll
    jmam.dll
    jmcvid.dll
    jmdaud.dll
    jmdaudc.dll
    jmddraw.dll
    jmfjawt.dll
    jmg723.dll
    jmgdi.dll
    jmgsm.dll
    jmh261.dll
    jmh263enc.dll
    jmjpeg.dll
    jmmci.dll
    jmmpa.dll
    jmmpegv.dll
    jmutil。 dll
    jmvcm.dll
    jmvfw.dll
    jmvh263.dll
    jsound.dll

  4. dlls复制到一个临时文件夹中

  5. 找到jmf.properties文件(在您的计算机上搜索它)
  6. 下载 JMF 源代码
    在源代码中,找到以下文件:

JMFinit.java
JMRPropertiesGen.java
Registry.java
RegistryGen.java

JMFinit.java
JMRPropertiesGen.java
Registry.java
RegistryGen.java

  1. Create a package; I'll call it JMFNoInstall
  2. Add the files listed in step 6
  3. Add a class called Main to this package as such:
  1. 创建一个包;我会叫它JMFNoInstall
  2. 添加步骤 6 中列出的文件
  3. 将一个名为 Main 的类添加到此包中,如下所示:

 

 

package JMFNoInstall;
// add your imports and whatnot here
public class Main()
{
    public Main()
    {
        JMFinit.main(null);
        JMFPropertiesGen.main(null);
        Registry.main(null);
        RegistryGen.main(new String[] {
            new File(".").getAbsolutePath(),
            "registrylib"
        });
    }
}

The jmf.propertiesfile needs to go in the same folder as the class that has your mainmethod or the same folder as the JAR archive that contains the mainmethod.
The dlls need to go into the win32folder. You can have your program check to see if they are in the win32folder. If they are not, you can have it copy them over from some location. The jmf.propertiesfile gets updated whenever the the Mainclass listed above runs. You only need to run this once, the first time the program is ever run, or if the user would like to add new capture devices. Lastly, just make sure the jmf.jarfile and jmfcom.jarthat comes along with the Windows JMF download is included in the classpath. You're good to go at this point. All the functionality of JMF without actually having to install it.

jmf.properties文件需要与包含您的main方法的类位于同一文件夹中,或者与包含该main方法的 JAR 存档位于同一文件夹中。
dll国家需要进入该win32文件夹。您可以让您的程序检查它们是否在win32文件夹中。如果不是,您可以让它从某个位置复制它们。jmf.properties每当Main上面列出的类运行时,该文件就会更新。您只需要运行一次,第一次运行程序时,或者如果用户想要添加新的捕获设备。最后,只需确保jmf.jar文件和jmfcom.jar随 Windows JMF 下载一起提供的文件包含在类路径中。你现在可以走了。无需实际安装即可使用 JMF 的所有功能。

There really isn't a lot of work involved with this, and you can incorporate it into your custom installer quite easily.

这真的没有太多工作要做,您可以很容易地将它合并到您的自定义安装程序中。

Has anyone found a better way to do this though? There are a few pitfalls of doing it this way.

有没有人找到更好的方法来做到这一点?这样做有一些陷阱。

EDIT: I thought it might be worthwhile to share some of the code that I created. Of course youll need to modify it to handle what you. It prob wont compile, but the stuff that is missing should be easy enough to recreate. But thought it might be a good starting point to help people. The detectCaptureDevices function is probably what will help most people. Ill update this class as I go.

编辑:我认为分享我创建的一些代码可能是值得的。当然你需要修改它来处理你的事情。它可能无法编译,但缺少的东西应该很容易重新创建。但认为这可能是帮助人们的一个很好的起点。detectCaptureDevices 函数可能对大多数人有帮助。我会在我去的时候更新这个类。


import GUI.Window;
import GlobalUtilities.OS;
import GlobalUtilities.ProgressBar;
import GlobalUtilities.FileUtilities;
import java.io.File;
import java.util.ArrayList;
import java.util.Vector;
import javax.swing.text.Utilities;


/**
 * This class providex easy access to the most needed info about JMF. You can test
 * a JMF install (Windows only currently) and also get info about the captrue
 * devices hooked up to JMF.
 * @author dvargo
 */
public class JMFRunner
{
    /**
     * Show the status of operations
     */
    final ProgressBar theBar = new ProgressBar();
    /**
     * Location where the dll's JMF relies on need to be placed
     */
    final String windowsDllFolder = "C:\WINDOWS\system32\";

    final String linuxDllFolder = "/usr/lib/";

    /**
     * Dll's that JMF uses
     */
    final String[] windowsDllList = new String[]{
        "jmacm.dll",
        "jmam.dll",
        "jmcvid.dll",
        "jmdaud.dll",
        "jmdaudc.dll",
        "jmddraw.dll",
        "jmfjawt.dll",
        "jmg723.dll",
        "jmgdi.dll",
        "jmgsm.dll",
        "jmh261.dll",
        "jmh263enc.dll",
        "jmjpeg.dll",
        "jmmci.dll",
        "jmmpa.dll",
        "jmmpegv.dll",
        "jmutil.dll",
        "jmvcm.dll",
        "jmvfw.dll",
        "jmvh263.dll",
        "jsound.dll"};

    String[] linuxDllList = new String[]{
        "libjmcvid.so",
        "libjmdaud.so",
        "libjmfjawt.so",
        "libjmg723.so",
        "libjmgsm.so",
        "libjmh261.so",
        "libjmh263enc.so",
        "libjmjpeg.so",
        "libjmmpa.so",
        "libjmmpegv.so",
        "libjmmpx.so",
        "libjmutil.so",
        "libjmv4l.so",
        "libjmxlib.so"
    };

    String [] dlls= null;
    String dir = null;

    /**
     * List of the video capture devices found by JMF
     */
    Vector videoDevices = null;
    /**
     * List of the audio capture devices found by JMF
     */
    Vector audioDevices = null;

    public JMFRunner()
    {
        if(OS.isWindows())
        {
            dlls = windowsDllList;
            dir = windowsDllFolder;
        }
        else if(OS.isLinux())
        {
            dlls = linuxDllList;
            dir = linuxDllFolder;
        }
        else
        {
            Window.getLogger().severe("Operating system does not support JMF");
        }

    }

    /**
     * Adds new capture devices
     */
    public void detectCaptureDecives()
    {


        Thread theTread = new Thread(theBar);
        theTread.start();
        theBar.repaint();

        JMFInit.main(new String[] {""});
        JMFPropertiesGen.main(new String[] {""});
        Registry.main(new String[] {""});
        RegistryGen.main(new String[] {"-d",
            new File(".").getAbsolutePath(),
            "registrylib"
        });

        theBar.setMessage("");
        theBar.stop();
    }

    /**
     * Verifies that all the dll's that JMF needs are in their correct spot
     * @return True if all dlls are in their correct spot, false otherwise
     */
    public boolean detectDlls()
    {
        boolean retVal = true;
        String currFile;
        for(String currDll : dlls)
        {
            currFile = dir + currDll;
            if(! new File(currFile).exists())
            {
                Window.getLogger().severe("Can not find dll " + currFile + " for JMF");
                retVal = false;
            }
        }
        return retVal;
    }

    //Doesnt work quite yet
    public boolean installLibraryFiles()
    {
        boolean retVal = true;
        String currFile;
        for(String currDll : dlls)
        {
            currFile = dir + currDll;
            File newDll = new File(currFile);
            //see if this dll is already there
            if(!newDll.exists())
            {
                //its not there so lets copy it
                try
                {
                    FileUtilities.copy(newDll,FileUtilities.getResourceFile("/JMFManager/Resources/"+currDll,currDll));
                }
                catch(Exception e)
                {
                    retVal =  false;
                }
            }
        }
        return retVal;
    }

    /**
     * Returns the location of the jmf.properties file that STix is using
     * @return THe locaiton of the JMF properties
     */
    public String getJMFPropertiesFileLocation()
    {
        return Registry.getJMFPropertiesFileLocation();
    }

    /**
     * Returns a list of the audio devices found by JMF
     * @return Returns an Arraylist containing info about the audio capture devices
     */
    public ArrayList getAudioDevices()
    {
        DeviceFinder df = new DeviceFinder();
        audioDevices = df.getSoundCaptureDevices();
        return new ArrayList(audioDevices);
    }

    /**
     * Returns a list of the video decives deteced by JMF
     * @return returns an arraylist with info of the video capture devices
     */
    public ArrayList getVideoDevices()
    {
        DeviceFinder df = new DeviceFinder();
        videoDevices = df.getVideoCaptureDevices();
        return new ArrayList(videoDevices);
    }


    public static void main(String [] args)
    {
        JMFRunner x = new JMFRunner();
        //x.detectCaptureDecives();
        x.installLibraryFiles();
        System.out.println(x.detectDlls());
        System.out.println(x.getJMFPropertiesFileLocation());
        System.out.println(x.getAudioDevices());
        System.out.println(x.getVideoDevices());
    }
}

DeviceFinder.java

设备查找器


import java.util.Vector;
import javax.media.*;
import javax.media.format.*;

/**
 * this class gets information about capture devices (mics and cameras)
 */
public class DeviceFinder {

    Vector videoDevices = new Vector();
    Vector audioDevices = new Vector();

   /**
   * Constructor
   * Creates a new DeviceFinder
   */
   public DeviceFinder()
   {
      /*retrieve ALL video and audio devices*/
      videoDevices = CaptureDeviceManager.getDeviceList(new VideoFormat(null));
      audioDevices = CaptureDeviceManager.getDeviceList(new AudioFormat(null));
   }

   /**
   * purpose:  Get information on all Video capture devices on the system
   * @return java.util.Vector 
a vector of attributes */ public Vector getVideoCaptureDevices() { return videoDevices; } /** * purpose: Get information on all audio capture devices on the system * @return java.util.Vector
a vector of attributes */ public Vector getSoundCaptureDevices() { return audioDevices; } /** * retrieve the first video capture device */ public CaptureDeviceInfo getPrimaryVideoCaptureDevice() { return (CaptureDeviceInfo)videoDevices.get(0); } /*retrieve the first audio capture device*/ public CaptureDeviceInfo getPrimaryAudioCaptureDevice() { return (CaptureDeviceInfo)audioDevices.get(0); } /** * get the first video device name * @return String
the name of the video device */ public String getVideoCaptureDeviceName() { return ((CaptureDeviceInfo)videoDevices.get(0)).getName(); } /** * get the first audio device name * @return String
the name of the audio device */ public String getAudioCaptureDeviceName() { return ((CaptureDeviceInfo)audioDevices.get(0)).getName(); } /** * get the first video device media locator * @return MediaLocator */ public MediaLocator getVideoMediaLocator() { return ((CaptureDeviceInfo)videoDevices.get(0)).getLocator(); } /** * get the first audio device media locator * @return MediaLocator */ public MediaLocator getAudioMediaLocator() { return ((CaptureDeviceInfo)audioDevices.get(0)).getLocator(); } /** * get the video device media locator at index idx * @param idx index of the media locator (0 is the first/default, * as ordered by *
the JMFRegistry) * @return MediaLocator */ public MediaLocator getVideoMediaLocator(int idx) { if(idx >= videoDevices.size()) { return null; } return ((CaptureDeviceInfo)videoDevices.get(idx)).getLocator(); } /** * get the audio device media locator at index idx * @param idx index of the audio device (as ordered by the JMFRegistry) * @return MediaLocator */ public MediaLocator getAudioMediaLocator(int idx) { return ((CaptureDeviceInfo)audioDevices.get(idx)).getLocator(); } /** * * @param args */ public static void main(String[] args) { DeviceFinder df = new DeviceFinder(); //DEBUG: System.out.println(df.getVideoMediaLocator()); System.out.println(df.getAudioMediaLocator()); } }

回答by Berin Loritsch

I don't think there is a better way. Unless the DLLs are explicitly loaded by path name, you would just need to make sure they are in the system path, so if they lived right next to the JVM executables it should also work. Windows does implicitly include the directory the program was started from in the system path, so that is another potential location.

我不认为有更好的方法。除非 DLL 是通过路径名显式加载的,否则您只需要确保它们在系统路径中,因此如果它们位于 JVM 可执行文件旁边,它也应该可以工作。Windows 确实在系统路径中隐式包含了程序启动的目录,因此这是另一个潜在的位置。

Installers are a double edged sword, they make it easy to add new functionality and remove it later, but they also make it harder to deploy solutions that use the product.

安装程序是一把双刃剑,它们使添加新功能和稍后删除它变得容易,但它们也使部署使用该产品的解决方案变得更加困难。

One of the nice things about Java in general is that you don't have to install it for it to work. Essentially, once you perform the install of the JRE on one system, you can bundle it up and use it on another system as a zip file. Java doesn't need to explicitly register the DLLs because it loads them dynamically as needed.

一般来说,Java 的优点之一是您不必安装它就可以工作。本质上,一旦您在一个系统上安装了 JRE,您就可以将它捆绑起来并作为 zip 文件在另一个系统上使用。Java 不需要显式注册 DLL,因为它会根据需要动态加载它们。