mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-06-14 12:05:58 +08:00
封装MediaPlayer JNI接口
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
#include "test_server.cpp"
|
||||
|
||||
#define JNI_API(retType,funName,...) extern "C" JNIEXPORT retType Java_com_zlmediakit_jni_ZLMediaKit_##funName(JNIEnv* env, jclass cls,##__VA_ARGS__)
|
||||
#define MediaPlayerCallBackSign "com/zlmediakit/jni/ZLMediaKit$MediaPlayerCallBack"
|
||||
#define MediaFrameSign "com/zlmediakit/jni/ZLMediaKit$MediaFrame"
|
||||
|
||||
|
||||
string stringFromJstring(JNIEnv *env,jstring jstr){
|
||||
@@ -60,11 +62,69 @@ jbyteArray jbyteArrayFromString(JNIEnv* env, const char* pat,int len = 0){
|
||||
return jarray;
|
||||
}
|
||||
|
||||
jobject makeJavaFrame(JNIEnv* env,const Frame::Ptr &frame){
|
||||
static jclass jclass_obj = (jclass)env->NewGlobalRef(env->FindClass(MediaFrameSign));
|
||||
static jmethodID jmethodID_init = env->GetMethodID(jclass_obj, "<init>", "()V");
|
||||
static jfieldID jfieldID_dts = env->GetFieldID(jclass_obj,"dts","I");
|
||||
static jfieldID jfieldID_pts = env->GetFieldID(jclass_obj,"pts","I");
|
||||
static jfieldID jfieldID_prefixSize = env->GetFieldID(jclass_obj,"prefixSize","I");
|
||||
static jfieldID jfieldID_keyFrame = env->GetFieldID(jclass_obj,"keyFrame","Z");
|
||||
static jfieldID jfieldID_data = env->GetFieldID(jclass_obj,"data","[B");
|
||||
static jfieldID jfieldID_trackType = env->GetFieldID(jclass_obj,"trackType","I");
|
||||
static jfieldID jfieldID_codecId = env->GetFieldID(jclass_obj,"codecId","I");
|
||||
|
||||
if(!frame){
|
||||
return nullptr;
|
||||
}
|
||||
jobject ret = env->NewObject(jclass_obj, jmethodID_init);
|
||||
env->SetIntField(ret,jfieldID_dts,frame->dts());
|
||||
env->SetIntField(ret,jfieldID_pts,frame->pts());
|
||||
env->SetIntField(ret,jfieldID_prefixSize,frame->prefixSize());
|
||||
env->SetBooleanField(ret,jfieldID_keyFrame,frame->keyFrame());
|
||||
env->SetObjectField(ret,jfieldID_data,jbyteArrayFromString(env,frame->data(),frame->size()));
|
||||
env->SetIntField(ret,jfieldID_trackType,frame->getTrackType());
|
||||
env->SetIntField(ret,jfieldID_codecId,frame->getCodecId());
|
||||
return ret;
|
||||
}
|
||||
|
||||
static JavaVM *s_jvm = nullptr;
|
||||
|
||||
template <typename FUN>
|
||||
void doInJavaThread(FUN &&fun){
|
||||
JNIEnv *env;
|
||||
int status = s_jvm->GetEnv((void **) &env, JNI_VERSION_1_6);
|
||||
if (status != JNI_OK) {
|
||||
if (s_jvm->AttachCurrentThread(&env, NULL) != JNI_OK) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
fun(env);
|
||||
if (status != JNI_OK) {
|
||||
//Detach线程
|
||||
s_jvm->DetachCurrentThread();
|
||||
}
|
||||
}
|
||||
|
||||
#define emitEvent(delegate,method,argFmt,...) \
|
||||
{ \
|
||||
doInJavaThread([&](JNIEnv* env) { \
|
||||
static jclass cls = env->GetObjectClass(delegate); \
|
||||
static jmethodID jmid = env->GetMethodID(cls, method, argFmt); \
|
||||
jobject localRef = env->NewLocalRef(delegate); \
|
||||
if(localRef){ \
|
||||
env->CallVoidMethod(localRef, jmid, ##__VA_ARGS__); \
|
||||
}else{ \
|
||||
WarnL << "弱引用已经释放:" << method << " " << argFmt; \
|
||||
}\
|
||||
}); \
|
||||
}
|
||||
|
||||
/*
|
||||
* 加载动态库
|
||||
*/
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
//设置日志
|
||||
s_jvm = vm;
|
||||
Logger::Instance().add(std::make_shared<ConsoleChannel>());
|
||||
Logger::Instance().setWriter(std::make_shared<AsyncLogWriter>());
|
||||
InfoL;
|
||||
@@ -100,3 +160,57 @@ JNI_API(jboolean,startDemo,jstring path_to_jni_file){
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
JNI_API(jlong,createMediaPlayer,jstring url,jobject callback){
|
||||
static auto loadFrameClass = makeJavaFrame(env,nullptr);
|
||||
MediaPlayer::Ptr *ret = new MediaPlayer::Ptr(new MediaPlayer());
|
||||
MediaPlayer::Ptr &player = *ret;
|
||||
|
||||
weak_ptr<MediaPlayer> weakPlayer = player;
|
||||
jobject globalWeakRef = env->NewWeakGlobalRef(callback);
|
||||
player->setOnPlayResult([weakPlayer,globalWeakRef](const SockException &ex) {
|
||||
auto strongPlayer = weakPlayer.lock();
|
||||
if (!strongPlayer) {
|
||||
return;
|
||||
}
|
||||
emitEvent((jobject)globalWeakRef,"onPlayResult","(ILjava/lang/String;)V",(jint)ex.getErrCode(),env->NewStringUTF(ex.what()));
|
||||
|
||||
if(ex){
|
||||
return;
|
||||
}
|
||||
|
||||
auto viedoTrack = strongPlayer->getTrack(TrackVideo);
|
||||
if (viedoTrack) {
|
||||
viedoTrack->addDelegate(std::make_shared<FrameWriterInterfaceHelper>([globalWeakRef](const Frame::Ptr &frame) {
|
||||
emitEvent((jobject)globalWeakRef,"onData","(L" MediaFrameSign ";)V",makeJavaFrame(env,frame));
|
||||
}));
|
||||
}
|
||||
|
||||
auto audioTrack = strongPlayer->getTrack(TrackAudio);
|
||||
if (audioTrack) {
|
||||
audioTrack->addDelegate(std::make_shared<FrameWriterInterfaceHelper>([globalWeakRef](const Frame::Ptr &frame) {
|
||||
emitEvent((jobject)globalWeakRef,"onData","(L" MediaFrameSign ";)V",makeJavaFrame(env,frame));
|
||||
}));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
player->setOnShutdown([globalWeakRef,weakPlayer](const SockException &ex) {
|
||||
auto strongPlayer = weakPlayer.lock();
|
||||
if (!strongPlayer) {
|
||||
return;
|
||||
}
|
||||
emitEvent((jobject)globalWeakRef,"onShutdown","(ILjava/lang/String;)V",(jint)ex.getErrCode(),env->NewStringUTF(ex.what()));
|
||||
});
|
||||
|
||||
player->play(stringFromJstring(env,url));
|
||||
|
||||
return (jlong)(ret);
|
||||
}
|
||||
|
||||
|
||||
|
||||
JNI_API(void,releaseMediaPlayer,jlong ptr){
|
||||
MediaPlayer::Ptr *player = (MediaPlayer::Ptr *)ptr;
|
||||
delete player;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user