利用JNI实现JAVA插件开发

本文主要工作在于利用JNI实现对已经完成的视频镜头提取C++程序的调用。

整个过程如下所示:

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

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

如何利用JNI调用C、C++可以看我另一篇文章:http://blog.csdn.net/ididcan/article/details/6828982

下面贴上程序:

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+"/";		
	}

}


如有疑问请留言

 

你可能感兴趣的:(java,exception,String,jni,Path,library)