Java利用JNI调用FFMpeg对h264码流进行解码

前期配置工作:

在Visual Studio端配置FFMpeg

在Visual Studio端配置OpenCV

解码部分主要源代码及说明

解码部分vs工程下载地址


使用JNI调用:

java端:

package com.recon.action;
public class Decode {

 public native String loadfile(String s);
 //传递字符串告知c++工程所要打开的h264文件
 static
 {
//Ffmpeg_Decode为之后c++所生成的动态库
 }
 public static void main(String[] args)
 {
 Decode d=new Decode();
 String input = d.loadfile("C:\\Users\\xxx\\Desktop\\myData.h264"); 
 /*此处为h264文件放置位置 */
 System.out.println(input); //若调用成功则返回字符串
 }
}

打开命令提示符 (Win+R 输入cmd后回车)

  1. 到工程的.java文件的目录下 输入 javac Decode.java 生成Decoe.class文件
  2. 退回工程的src目录 输入javah命令和包名加类文件名字生成.h文件。(在我的工程中生成为com_recon_action_Decode.h文件)

    (例如:输入 javah com.recon.action.Decode) (必须是完整包名且不需要加后缀)

生成的头文件如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_recon_action_Decode */

#ifndef _Included_com_recon_action_Decode
#define _Included_com_recon_action_Decode
#ifdef __cplusplus
extern "C" {
#endif
/* * Class: com_recon_action_Decode * Method: loadfile * Signature: (Ljava/lang/String;)Ljava/lang/String; */
JNIEXPORT jstring JNICALL Java_com_recon_action_Decode_loadfile
 (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

该头文件所用到的jni.h文件在本机电脑所安装的jdk的include目录下即可找到(注意:jni.h文件还需要调用一个jni_md.h文件,该文件在同一include目录下的win32目录内可找到)

在工程中添加完以上三个头文件后,需要在第一个头文件(即使用java生成的那个)中将#include <jni.h>改为#include "jni.h"

C++端:

将刚才在第三个链接中所下载的工程打开.

右键工程属性,将其配置类型从应用程序改为dll动态库文件.

按照第一个链接配置FFMpeg环境,第二个链接配置OpenCV.

配置完成之后,将Ffmpeg_Decode_Main.cpp文件稍作如下改动即可.

#include "Ffmpeg_Decode.h"
#include "com_recon_action_Decode.h"

JNIEXPORT jstring JNICALL Java_com_recon_action_Decode_loadfile(JNIEnv *env, jobject obj, jstring s)
//void main()
{
    const char* stri;
    stri = env->GetStringUTFChars(s,false);

    if(stri == NULL) {
        return NULL;//内存错误已抛出
    }
    int i = 0;
    Ffmpeg_Decorder ffmpegobj;
    ffmpegobj.Ffmpeg_Decorder_Init();//初始化解码器
    File *pf = NULL;
    //fopen_s(&pf, "myData.h264","rb");
    fopen_s(&pf,stri,"rb");

(注释部分为未改动的代码)

(i变量为之后存储图片所要使用到的变量)

在文件末尾添加如下代码返回成功值.

env->ReleaseStringUTFChars(s,stri);
char* tmpstr = "load file succeeded";
jstring rtstr = env->NewStringUTF(tmpstr);
return rtstr;

由于我的工程要求需要将h264码流解码并且将视频按帧存储为图片,于是我在Ffmpeg_Decode.cpp中cvShowImage("解码图像", img);语句之后加入了如下代码:

 char path[] = "F://pictures//";//为图片存储路径
 char *file = ".jpg";//图片存储格式
 char str[256];
 _ltoa(i, str, 10);//整型与字符串转化
 strcat(path, str);
 strcat(path, file);
 cvSaveImage(path, img);//opencv中自带的存储图片函数

(要在头文件的函数声明以及前面的函数调用中添加i变量的声明)

右键项目生成,在工程的Debug目录下可看到所生成的dll文件.将dll文件所在的目录(例如C:\Ffmpeg_Decode\Debug)添加到环境变量Path中(右键我的电脑–>属性–>高级系统设置–>环境变量–>系统变量)

重启eclipse(否则无法识别到路径),运行Decode,即调用成功.

全部评论

相关推荐

2024-12-25 09:09
四川师范大学 运营
想和你交朋友的潜伏者要冲国企:先去沃尔玛亲身感受标准化流程体系,一两年后再跳槽国内任何零售行业,可以有更大选择权吧?
点赞 评论 收藏
分享
hanliu:1. 排版与格式问题字体与对齐问题:标题和内容的字体大小差异不够明显,无法迅速吸引目光。某些文字看起来有些拥挤(比如校园经历中的“班委成员”部分)。2. 内容逻辑性模块顺序问题:实习经历放在较靠后的位置,实际上这部分内容对应聘来说更重要,建议提前突出。细节表述不够突出:比如教育背景部分的专业课程仅仅列出名字,没有说明自己在这些课程中表现如何或者掌握了什么技能,缺乏量化描述。多余内容:例如“班委成员”和“宣传委员”这类校园经历,叙述过于普通,缺乏和岗位相关的实质性贡献。,建议简写。3. 措辞专业性表达不够精准:例如“协助班长与团支书更好地为同学服务”显得较为笼统,没有实际成果的体现。用词重复:如“学习了焊接”“学习了光检”等重复词语较多,缺乏丰富的动词来展示个人能力(如“负责”“优化”“改进”等)。技能展示不足:虽然列出了UG和CAD证书,但没有明确提到这些技能如何在实际工作中发挥作用。4. 技能匹配度技能深度不足:虽然列出了掌握的软件和技术,但没有描述技能水平(如“熟练掌握”“精通”),也没有具体案例支持这些技能。缺乏岗位导向性:比如针对机械设计与制造方向,实习经历提到了“E6尾灯项目”,但没有详细说明自己在其中的技术贡献,可能会显得经验描述泛泛而谈。5. 自我评价问题表达空泛:如“具有良好的沟通协调能力”“责任心强”之类的描述太常见,没有让人眼前一亮的特点。缺乏成果支持:自我评价中的能力没有用具体项目、经历或成就来验证,可信度较弱。 兄弟加油
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务