JNI call and callback in Android

This is a cpp file which I used to jni call and callback in one of my project. I post it here so that i do not have to re r&d. It uses android 4.0.3 source to compile.

 

#include "JNIMain.h"
#include "GlobalResource.h"
#include "Recorder.h"

JavaVM *javaVM;
jobject recorderJava;
Recorder recorder;
jmethodID audioCallBackID;
jmethodID videoCallBackID;
extern sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, struct JNICameraContext** context);

extern "C" {

Recorder* recorder;
jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved)
{
	GlobalResource* gr = GlobalResource::getInstance();
	javaVM = jvm;
	return JNI_VERSION_1_6;
}

jint Java_stopNativeRecording(JNIEnv *env, jobject obj)
{
	if(recorder!=0)
	{
		LOGD("stopping native recorder");
		recorder->stop();
		if(recorderJava!=0)
			env->DeleteGlobalRef(recorderJava);

	}
	else
	{
		LOGD("recording was not started");
	}

	return 0;
}

jint Java_startNativeRecording(JNIEnv *env, jobject obj, jobject jCamera, jobject jSurface)
{
	LOGD("starting native recorder");
	GlobalResource* gr = GlobalResource::getInstance();
	recorderJava = env->NewGlobalRef(obj);


	jclass cls = env->GetObjectClass(obj);
	audioCallBackID = env->GetMethodID(cls,"onAudioData", "([B)V");
	videoCallBackID = env->GetMethodID(cls,"onVideoData", "([B)V");




	sp<Camera> cmr=get_native_camera(env,jCamera, NULL);	
    jclass surfaceClass = env->FindClass("android/view/Surface");
    jfieldID surfaceField = env->GetFieldID(surfaceClass, "mNativeSurface", "I");
    Surface* const  p = (Surface*)(env->GetIntField(jSurface, surfaceField));
	sp<Surface> surface=sp<Surface>(p);

	recorder = new Recorder();
	recorder->start(cmr,surface);

	return 0;
}

jobject Java_getCodecInfo(JNIEnv *env, jobject obj, jobject jCamera, jobject jSurface)
{
	LOGD("starting native recorder");
	GlobalResource* gr = GlobalResource::getInstance();
	recorderJava = env->NewGlobalRef(obj);


	jclass cls = env->GetObjectClass(obj);
	audioCallBackID = env->GetMethodID(cls,"onAudioData", "([B)V");
	videoCallBackID = env->GetMethodID(cls,"onVideoData", "([B)V");




	sp<Camera> cmr=get_native_camera(env,jCamera, NULL);	
    jclass surfaceClass = env->FindClass("android/view/Surface");
    jfieldID surfaceField = env->GetFieldID(surfaceClass, "mNativeSurface", "I");
    Surface* const  p = (Surface*)(env->GetIntField(jSurface, surfaceField));
	sp<Surface> surface=sp<Surface>(p);

	recorder = new Recorder();
	recorder->storeCodecInfo(cmr,surface);



/*******************************************returning**************************************/
	jclass CodecInfoClass = env->FindClass("CodecInfo");
	jmethodID constructor = env->GetMethodID(CodecInfoClass, "<init>", "()V"); // no parameters  
	jobject codecInfo = env->NewObject(CodecInfoClass, constructor); 

	

	//get field ids
	LOGD("here");
	jfieldID spsFieldID = env->GetFieldID(CodecInfoClass, "VIDEO_SPS", "[B");
	jfieldID ppsFieldID = env->GetFieldID(CodecInfoClass, "VIDEO_PPS", "[B");
	jfieldID audioProfileFieldID = env->GetFieldID(CodecInfoClass, "AUDIO_PROFILE", "I");
	jfieldID audioSamplingRateFieldID = env->GetFieldID(CodecInfoClass, "AUDIO_ACTUAL_SAMPLING_RATE", "I");
	jfieldID audioChannelID = env->GetFieldID(CodecInfoClass, "AUDIO_CHANNEL", "I");
	LOGD("here");



	//sps
	
	android::List<AVCParamSet>::iterator itS = gr->mSeqParamSets.begin();

	if(itS != gr->mSeqParamSets.end())
	{
		int seqParamSetLength = itS->mLength;
		jbyteArray vsps = env->NewByteArray(seqParamSetLength);;
		env->SetByteArrayRegion(vsps, 0, seqParamSetLength, (jbyte*)itS->mData); 
		env->SetObjectField (codecInfo, spsFieldID, vsps);
	}
	LOGD("sps done");
	//pps
	android::List<AVCParamSet>::iterator itP = gr->mPicParamSets.begin();

	if(itP != gr->mPicParamSets.end())
	{
		int picParamSetLength = itP->mLength;
		jbyteArray vpps = env->NewByteArray(picParamSetLength);
		env->SetByteArrayRegion(vpps, 0, picParamSetLength, (jbyte*)itP->mData); 
		env->SetObjectField (codecInfo, ppsFieldID, vpps);
	}

	LOGD("pps done");
	//audioProfile
	env->SetIntField(codecInfo, audioProfileFieldID, gr->mProfile);
	//audioSamplingRate
	env->SetIntField(codecInfo, audioSamplingRateFieldID, gr->mActualSampleingRate);
	//audioChannel
	env->SetIntField(codecInfo, audioChannelID, gr->mChannel);

	
	return codecInfo;
}





jint Java_cameraPreviewTest(JNIEnv *env, 
	jobject obj, jobject jSurface)
{

	
	return 0;
}

} //extern c

// these functions are  called from c++
JNIEnv* attachCurrentThreadtoJVM()
{
 	JavaVM *jvm = javaVM;
    JNIEnv *env=NULL;
	jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
	jvm->AttachCurrentThread(&env, NULL);
	return env;
}

void detachCurrentThreadtoJVM()
{
	JavaVM *jvm = javaVM;
	jvm->DetachCurrentThread();
}


void sendDataToJava(JNIEnv* env,Packet* pk, MEDIATYPE dataType)
{
	jbyteArray jbArray = env->NewByteArray(pk->length);
	env->SetByteArrayRegion(jbArray, 0, pk->length, (jbyte*)pk->data);
	if(dataType == AUDIO)
		env->CallVoidMethod(recorderJava, audioCallBackID, jbArray);
	else
		env->CallVoidMethod(recorderJava, videoCallBackID, jbArray);

	delete pk->data;
	delete pk;
	env->DeleteLocalRef(jbArray);
}
Advertisements
JNI call and callback in Android

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s