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,即调用成功.

猜你喜欢

转载自blog.csdn.net/qq_30019237/article/details/52267121
今日推荐