我正在进行的一个视频 session 项目使用JMF捕获视频和音频,并将其传输到另一个端点。问题是我的团队不希望产品的用户必须安装JMF。
我认为可能值得分享我们对这个问题的解决方案。有用。效果很好。我对您的问题是:有人有更好的方法吗?
环境:Windows,XP及更高版本
dll
: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
dll
复制到一个临时文件夹jmf.properties
文件(在您的计算机上进行搜索)在源代码中,找到以下文件:
JMFinit.java
JMRPropertiesGen.java
Registry.java
RegistryGen.java
JMFNoInstall
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"
});
}
}
jmf.properties
文件需要与具有main
方法的类位于同一文件夹中,或者与包含main
方法的JAR存档位于同一文件夹中。dll
需要进入win32
文件夹。您可以让程序检查它们是否在win32
文件夹中。如果不是,您可以让它从某个位置复制它们。每当上面列出的jmf.properties
类运行时,Main
文件都会更新。您只需要运行一次,第一次运行该程序,或者用户想添加新的捕获设备。最后,只需确保Windows JMF下载随附的jmf.jar
文件和jmfcom.jar
包含在类路径中。此时,您很好。 JMF的所有功能,而无需实际安装。确实没有很多工作要做,您可以很轻松地将其合并到自定义安装程序中。
有人找到了更好的方法吗?这样做有一些陷阱。
编辑:我认为分享一些我创建的代码可能是值得的。当然,您需要对其进行修改以处理您的问题。它可能不会编译,但是缺少的内容应该足够容易地重新创建。但是认为这可能是帮助人们的良好起点。 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()); }}
最佳答案
我认为没有更好的方法。除非这些DLL是通过路径名显式加载的,否则您只需要确保它们在系统路径中即可,因此,如果这些DLL生活在JVM可执行文件的旁边,那么它也应该起作用。 Windows确实在系统路径中隐式包含了程序从其启动的目录,因此这是另一个可能的位置。
安装程序是一把双刃剑,它们使添加新功能和稍后删除它变得容易,但也使部署使用该产品的解决方案变得更加困难。
通常,关于Java的一件好事是,您无需安装它即可正常工作。本质上,一旦在一个系统上执行了JRE的安装,就可以将其 bundle 并以zip文件的形式在另一个系统上使用。 Java不需要显式注册DLL,因为它会根据需要动态加载它们。