本篇文章的前一篇是采用FFmpeg解帧,并保持到JPG格式文件,其中使用了main函数对视频进行了解帧,本篇将针对Java如何调用来实现解帧并输出到文件。
一、使用VS2010将其改为Dll输出时,需要改变以下项目属性设置:
1、常规设置
2、库目录设置
3、预编译头设置
4、预处理设置
_INTEL WIN32 _DEBUG _CONSOLE _Windows _CRT_SECURE_NO_DEPRECATE
二、基于上篇文章代码我们添加如下函数声明以及实现
_declspec(dllexport) int findFKeyFrame(char *videoFilePath, char *frameFile); int findFKeyFrame(char *videoFilePath, char *frameFile) { AVFormatContext *pFormatCtx = NULL; int i,videoStream; AVCodecContext *pCodecCtx; AVCodec *pCodec; AVFrame *pFrame; AVFrame *pFrameRGB; int numBytes; uint8_t *buffer; AVPacket packet; int frameFinished; struct SwsContext *img_convert_ctx = NULL; av_register_all(); // 检查参数以及视频能否解码 if(avformat_open_input(&pFormatCtx, videoFilePath, NULL, NULL)!=0) { printf("can not open"); return -1; } if(avformat_find_stream_info(pFormatCtx, NULL) < 0) { printf("can not find"); return -1; } av_dump_format(pFormatCtx, -1, videoFilePath, 0); videoStream = -1; for (i=0;i<pFormatCtx->nb_streams;i++) { if( pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoStream = i; break; } } if ( videoStream == -1 ) { printf("not find videoStream"); return -1; } pCodecCtx = pFormatCtx->streams[videoStream]->codec; pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if ( pCodec == NULL ) { return -1; } if( avcodec_open2(pCodecCtx, pCodec, NULL) < 0 ) { return -1; } pFrame = av_frame_alloc(); if( pFrame == NULL ) { return -1; } pFrameRGB = av_frame_alloc(); if( pFrameRGB == NULL ) { return -1; } // 根据视频宽高设置帧大小 numBytes = avpicture_get_size(PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height); buffer = av_malloc(numBytes); avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height); img_convert_ctx = sws_getCachedContext(img_convert_ctx, pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL); i = 0; while( av_read_frame(pFormatCtx, &packet) >= 0 ) { if( packet.stream_index == videoStream ) { avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet); if ( frameFinished && pFrame->key_frame) { if (!img_convert_ctx ) { fprintf(stderr, "Cannot initialize sws conversion context\n"); exit(1); } sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize); if(i++<1) { saveFrameJpg(pFrameRGB->data[0],frameFile, i, pCodecCtx->width, pCodecCtx->height); } } } if(i > 5) { break; } } av_free_packet(&packet); av_free(buffer); av_free(pFrame); av_free(pFrameRGB); avcodec_close(pCodecCtx); avformat_close_input(&pFormatCtx); return 1; }
编译项目,生成DLL,并拷贝其到Java调用类目录下。
三、编写Java代码调用DLL
Java调用dll,肯定会用到JNI,但是此处使用比较常用地JNA框架来调用。JNA相关链接
可从test包可以查看怎么使用指针类Pointer等等
JNA代码实现如下:
package com.xiva.test.pic; import java.io.UnsupportedEncodingException; import com.sun.jna.Library; import com.sun.jna.Memory; import com.sun.jna.Native; import com.sun.jna.NativeLong; import com.sun.jna.Pointer; /** * * <调用DLL读取视频的第一关键帧,并以JPG格式输出到文件> * @author xiva * @version [1.0, 2014-5-15] * @see [相关类/方法] * @since [产品、模块版本] */ public class ReadVideoKeyFrame { public interface VideoDecoder extends Library { /** * 当前路径是在项目下,而不是bin输出目录下。 */ VideoDecoder INSTANCE = (VideoDecoder) Native.loadLibrary("VideoDecoder", VideoDecoder.class); public NativeLong findFKeyFrame(Pointer videoFilePath, Pointer frameFile); } public static void main(String[] args) throws UnsupportedEncodingException { final String ENCODING = "utf8"; String fileName = "E:\\frame01.jpg"; String path = "E:\\zookeeper.avi"; Pointer videoFilePath = new Memory(path.getBytes(ENCODING).length+1); Pointer frameFile = new Memory(fileName.getBytes(ENCODING).length+1); videoFilePath.setString(0, path); frameFile.setString(0, fileName); NativeLong ret = VideoDecoder.INSTANCE.findFKeyFrame(videoFilePath, frameFile); System.out.println(ret); } }
运行程序,可以看到解帧成功。
同样此处还是未解决如何集成其他地解码器,毕竟ffmpeg地解码能力有限;需要后续再次扩展。
相关推荐
JAVA使用JNative包调用DLL文件
JAVA调用DLL JAVA调用DLLJAVA调用DLLJAVA调用DLLJAVA调用DLLJAVA调用DLL
亲测可用,java 成功调用dll函数。包含调用回调函数,springboot版本。最近由于公司业务需要,要调用dll文件,用JNA调用。
Java调用动态链接库 Java 调用 DLL 源码
java调用c++ dll代码
1、Labview生成Dll文件 2、Java通过Jnative第三方Jar包调用Labview生成的DLL文件 3、Java在Windows系统调用Labview生成的Dll的说明 有JNative的使用说明 直接下载,根据使用说明可以直接使用。
Java调用dll示例,Java命名方法,C++实现生成DLL供JAVA调用
这是java采用jni技术调用dll(动态链接库的一个demo),不需要任何改动,自己可以用,很适合初学者
java调用ocx控件,jacob,jar和dll文件
Java通过JNI调用DLL动态库,亲测试编写
java 通过 jawin 调用dll范例小程序
一个用于在java中调用dll动态代码库的开源组件,JNative-1.3.2
就是SAP 的ABAP语言调用 DLL文件中的函数实现一些功能, 例如可以用DLL文件连接外部数据库读取数据. 我在网上找了好久,都没有一个完整的答案, 也没有一个完整的实例, 根据网上的各种说法, 我整合到一起, 终于成功, ...
是Java 调用DLL动态库框架,功能强大,告别往日的JNI,只需定义接口,就可以方便调用DLL库,为开发人员省了不少事。
java调用本地dll的几种方法性能对比测试。 JNA消耗的总时间(ms):5406 bridj消耗的总时间(ms):984 JNI消耗的总时间(ms):47 包含c++源码和java源码,部署和使用方法。在win7和winxp下测试用过。 部分源码是...
java调用dll接口,备份供大家察看,谢谢大家共享。
java调用vc的dll,java调用vc的dll,java调用vc的dll,java调用vc的dll
大华视频文件分割下载,根据大华提供的win64的dll文件,通过java代码对C代码进行调用,获取大华录像设备中保存的视频
该资源包含C#开发DLL源码,Java调用DLL源码,测试已通过