1. 程式人生 > >Java利用JNI呼叫FFMpeg對h264碼流進行解碼

Java利用JNI呼叫FFMpeg對h264碼流進行解碼

前期配置工作:

使用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,即呼叫成功.