我曾经参与的一个视频会议项目使用JMF来捕获视频和音频,并将其传输到另一个端点。问题是,我的团队不希望产品的用户安装JMF。
我认为分享我们解决这个问题的方法可能是值得的。它能正常工作,而且效果很好。我想问一下,有没有更好的方法呢?
环境:Windows XP 及以上版本
- 下载 JMF for Windows
- 在计算机上进行安装
- 在 jmf 安装后,在 system32 文件夹中找到以下
dll
: - 将这些
dll
复制到一个临时文件夹中 - 查找
jmf.properties
文件(在电脑上搜索它) - 下载 JMF 源代码
在源代码中,找到以下文件:
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
JMFinit.java
JMRPropertiesGen.java
Registry.java
RegistryGen.java
- 创建一个包;我称其为
JMFNoInstall
- 添加第 6 步中列出的文件
- 添加名为 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"
});
}
}
jmf.properties
文件需要放在包含main
方法的类所在的文件夹或包含main
方法的JAR归档文件所在的文件夹中。dll
文件需要放在win32
文件夹中。您可以让程序检查这些文件是否位于win32
文件夹中。如果不在,可以将它们从某个位置复制到此处。每次运行上面列出的Main
类时,jmf.properties
文件都会被更新。您只需要在程序第一次运行时运行一次,或者如果用户想要添加新的捕获设备,则需要运行一次。最后,请确保在类路径中包含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;
/**
* 该类提供了对JMF最需要的信息的易于访问。您可以测试JMF安装(目前仅适用于Windows),并获取有关连接到JMF的捕获设备的信息。
*/
public class JMFRunner
{
/**
* 显示操作状态
*/
final ProgressBar theBar = new ProgressBar();
/**
* 存放JMF依赖的dll所需的位置
*/
final String windowsDllFolder = "C:\\WINDOWS\\system32\\";
final String linuxDllFolder = "/usr/lib/";
/**
* JMF使用的dll
*/
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;
/**
* JMF发现的视频捕获设备列表
*/
Vector videoDevices = null;
/**
* 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("操作系统不支持JMF");
}
}
/**
* 添加新的捕获设备
*/
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();
}
/**
* 验证JMF需要的所有dll是否位于其正确位置
* @return 如果所有dll都在正确位置,则为True,否则为False
*/
public boolean detectDlls()
{
boolean retVal = true;
String currFile;
for(String currDll : dlls)
{
currFile = dir + currDll;
if(! new File(currFile).exists())
{
Window.getLogger().severe("找不到JMF所需的dll文件 " + currFile);
retVal = false;
}
}
return retVal;
}
//尚未正常工作
public boolean installLibraryFiles()
{
boolean retVal = true;
String currFile;
for(String currDll : dlls)
{
currFile = dir + currDll;
File newDll = new File(currFile);
//看看这个dll是否已经存在
if(!newDll.exists())
{
//它不存在,让我们将其复制
try
{
FileUtilities.copy(newDll,FileUtilities.getResourceFile("/JMFManager/Resources/"+currDll,currDeviceFinder.java
import java.util.Vector;
import javax.media.*;
import javax.media.format.*;
/**
* 此类获取有关捕获设备(麦克风和摄像头)的信息
*/
public class DeviceFinder {
Vector videoDevices = new Vector();
Vector audioDevices = new Vector();
/**
* 构造函数
* 创建新的 DeviceFinder
*/
public DeviceFinder()
{
/*检索所有视频和音频设备*/
videoDevices = CaptureDeviceManager.getDeviceList(new VideoFormat(null));
audioDevices = CaptureDeviceManager.getDeviceList(new AudioFormat(null));
}
/**
* 作用:获取系统上所有视频捕获设备的信息
* @return java.util.Vector
一个属性向量
*/
public Vector getVideoCaptureDevices()
{
return videoDevices;
}
/**
* 作用:获取系统上所有音频捕获设备的信息
* @return java.util.Vector
一个属性向量
*/
public Vector getSoundCaptureDevices()
{
return audioDevices;
}
/**
* 检索第一台视频捕获设备
*/
public CaptureDeviceInfo getPrimaryVideoCaptureDevice()
{
return (CaptureDeviceInfo)videoDevices.get(0);
}
/*检索第一台音频捕获设备*/
public CaptureDeviceInfo getPrimaryAudioCaptureDevice()
{
return (CaptureDeviceInfo)audioDevices.get(0);
}
/**
* 获取第一个视频设备的名称
* @return String
视频设备的名称
*/
public String getVideoCaptureDeviceName()
{
return ((CaptureDeviceInfo)videoDevices.get(0)).getName();
}
/**
* 获取第一个音频设备的名称
* @return String
音频设备的名称
*/
public String getAudioCaptureDeviceName()
{
return ((CaptureDeviceInfo)audioDevices.get(0)).getName();
}
/**
* 获取第一个视频设备的媒体定位器
* @return MediaLocator
*/
public MediaLocator getVideoMediaLocator()
{
return ((CaptureDeviceInfo)videoDevices.get(0)).getLocator();
}
/**
* 获取第一个音频设备的媒体定位器
* @return MediaLocator
*/
public MediaLocator getAudioMediaLocator()
{
return ((CaptureDeviceInfo)audioDevices.get(0)).getLocator();
}
/**
* 获取索引 idx 的视频设备媒体定位器(0 是第一/默认项,
* 根据 JMFRegistry 排序)
* @param idx 媒体定位器的索引
* @return MediaLocator
*/
public MediaLocator getVideoMediaLocator(int idx)
{
if(idx >= videoDevices.size())
{
return null;
}
return ((CaptureDeviceInfo)videoDevices.get(idx)).getLocator();
}
/**
* 获取索引 idx 的音频设备媒体定位器(根据 JMFRegistry 排序)
* @param idx 音频设备的索引
* @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());
}
}
c:\windows\system32
目录下? - MikeNeresonsystem32
http://pastie.org/1966273 - MikeNereson