您的位置:首页 > 编程语言 > Java开发

利用JNI实现JAVA插件开发

2011-09-29 09:56 363 查看
本文主要工作在于利用JNI实现对已经完成的视频镜头提取C++程序的调用。

整个过程如下所示:

1)将视频特征提取算法建立相应的windows下的Dll和Linux下的So(这个两个文件大家都知是什么了吧)

2)利用jni调用这些dll。但是有一个问题,就是这里的所有库文件需要打到jar包中,因此需要将这些文件先解压到一个临时文件夹中,然后通过Syste.load加载这些库文件。

如何利用JNI调用C、C++可以看我另一篇文章:/article/9282691.html

下面贴上程序:

VideoUtil.java

package udms.video;

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

public class VideoUtil {
public static String path = "";
static {
try{
// copy the so file to native temp dir
String path = LoadVideoLib.loadLib();

// according to different operating system to load the library
String systemType=System.getProperty("os.name");

systemType = systemType.toLowerCase();
if(systemType.contains("win")){
// windows dynamic link library. (dll)
System.load(path+"cv210.dll");
System.load(path+"cxcore210.dll");
System.load(path+"cxts210.dll");
System.load(path+"highgui210.dll");
System.load(path+"VideoUtily.dll");
}
else{
// linux share object. (so)
System.load(path+"libavutil.so.51");
System.load(path+"libswscale.so.2");
System.load(path+"libavcodec.so.53");
System.load(path+"libavformat.so.53");
System.load(path+"libtiff.so");
System.load(path+"libcxcore.so.2.1");
System.load(path+"libcv.so.2.1");
System.load(path+"libml.so.2.1");
System.load(path+"libhighgui.so.2.1");
System.load(path+"libcvaux.so.2.1");
System.load(path+"libcxts.so.2.1");
System.load(path+"libVideoUtily.so");
}

}catch(UnsatisfiedLinkError e){
System.err.println("Cannot load VideoUtil.so\n"+e.toString());
}
}

/**
* extract the abstract frame from the video return the frame director path
* @param fileName
* @param abFrameNum
* @param timeDisFlag
* @return
*/
private native static String getAbstractFrameFromVideo(String fileName,int abFrameNum,int timeDisFlag);

/**
* extract the abstract frame from the video
* @param videoPath the video file path
* @param abFrameNum the number of abstract frame
* @param timeDisFlag time flag
* @return
*/
public static List<String> extractAbstractFrameFromVideo(String videoPath,int abFrameNum,int timeDisFlag)
{
List<String> reFiles=new ArrayList<String>(abFrameNum+1);

String allPaths=getAbstractFrameFromVideo(videoPath,abFrameNum,timeDisFlag);

StringTokenizer toker=new StringTokenizer(allPaths,"|");

while(toker.hasMoreTokens()){
reFiles.add(toker.nextToken());
}

return reFiles;
}

}


LoadVideoLib.java 该类主要是从jar包中将那些库文件解压到本地临时目录中来。有以下几点要注意

就是我在jar包中的库文件夹下放置了info文件,该文件中包含了该目录下的文件名。那么解压的时候先读取该info利用这些文件名,然后把所有该文件夹下的库文件都解压出来。这是一种折中的方式,应该有更好的方式,直接可以读取jar文件夹下的文件名列表。

另,生成info文件的代码也放到这里,可以直接调用。

package udms.video;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class LoadVideoLib {

/**
* write the file name list of the directory to an info file.
* @param path directory path
*/
public static void readFileList(String path){
try{
BufferedWriter bw = new BufferedWriter(new FileWriter(new File(path+"/info")));
File dir = new File(path);
if(dir.isDirectory()){
String[] list = dir.list();
for(int i= 0 ;i < list.length; i++)
bw.append(list[i]+"\r\n");
}
bw.close();
}catch(Exception e){
e.printStackTrace();
}
}

/**
* read the info from jar file. the info contain the file name of dll or so according to the os system.
* @param infoPath info path in the jar
* @return the file name list of dll or so.
*/
public static List<String> readInfo(String infoPath){
List<String> list = new ArrayList<String>();
// get the info input stream
InputStream in = LoadVideoLib.class.getResourceAsStream(infoPath);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String str = null;
try{
// read the list of library file name from info
while((str = br.readLine())!=null)
list.add(str);
br.close();
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(br!=null)
br.close();
}catch(Exception e){
e.printStackTrace();
}
}
return list;
}

/**
* load the relate library according to the os system.
* @return the directory path of library.
*/
public static String loadLib(){
// get the os system name
String systemType=System.getProperty("os.name");
systemType = systemType.toLowerCase();
// here only support windows and linux
if(systemType.contains("win"))
systemType="win";
else
systemType="linux";
// judge the bit of os system.
String bit = System.getProperty("os.arch");
String osType = "";
// here only support X86 and X64
if(bit.contains("64"))
osType = systemType+"64";
else
osType = systemType+"32";

// read the lib name list from info
List<String> list = readInfo(osType+"/info");

// the director path which contains the library.
String jarLibDir = osType+"/";

// get directory path which store the extracted library store in the jar file
String nativeLibDir = System.getProperty("java.io.tmpdir")+"/"+osType;

// extract the library file to the native library directory
InputStream in=null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
for(String libName : list){
// create a native directory to store the library
File libDir = new File(nativeLibDir);
if(!libDir.exists())
libDir.mkdir();

// create the extracted library file
File extractedLibFile=new File(nativeLibDir+"/"+libName);
if(!extractedLibFile.exists()){
try{
in=LoadVideoLib.class.getResourceAsStream(jarLibDir+libName);
bis = new BufferedInputStream(in);
bos = new BufferedOutputStream(new FileOutputStream(extractedLibFile));
byte[] data = new byte[bis.available()];
bis.read(data);
bos.write(data);
bis.close();
bos.close();
}catch(IOException ioe){
ioe.printStackTrace();
}finally{
try{
if(bis!=null)
bis.close();
if(bos!=null)
bos.close();
}catch(Exception e){
e.printStackTrace();
}

}
}
}
// return the directory path which contains the library.
return nativeLibDir+"/";
}

}


如有疑问请留言
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: