本文主要工作在于利用JNI实现对已经完成的视频镜头提取C++程序的调用。
整个过程如下所示:
1)将视频特征提取算法建立相应的windows下的Dll和Linux下的So(这个两个文件大家都知是什么了吧)
2)利用jni调用这些dll。但是有一个问题,就是这里的所有库文件需要打到jar包中,因此需要将这些文件先解压到一个临时文件夹中,然后通过Syste.load加载这些库文件。
如何利用JNI调用C、C++可以看我另一篇文章:http://blog.youkuaiyun.com/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+"/";
}
}
如有疑问请留言