webrtc Android jni和c++ 相互调用方法讲解
c++ 调用 java
c++ 调用java方法的写法很繁琐,webrtc中为了避免大量的重复代码,自己实现了一套jni的生成替换方法,从而使得代码看起来更“干净”,但给看代码带来了一些麻烦,记录一下webrtc Android代码的jni调用
sdk中有一个jni目录
我们以一个文件为例 webrtc/sdk/android/src/jni/videoencoderfactorywrapper.cc
可以看到这里面调用了一些jni方法,例如Java_VideoEncoderFactory_createEncode,但我们却无法找到这个的定义
namespace webrtc { namespace jni { std::unique_ptr<VideoEncoder> VideoEncoderFactoryWrapper::CreateVideoEncoder( const SdpVideoFormat& format) { JNIEnv* jni = AttachCurrentThreadIfNeeded(); ScopedJavaLocalRef<jobject> j_codec_info = SdpVideoFormatToVideoCodecInfo(jni, format); ScopedJavaLocalRef<jobject> encoder = Java_VideoEncoderFactory_createEncoder( jni, encoder_factory_, j_codec_info); if (!encoder.obj()) return nullptr; return JavaToNativeVideoEncoder(jni, encoder); } } // namespace jni } // namespace webrtc
我们可以看到webrtc/sdk/android/api/org/webrtc/mozi/VideoEncoderFactory.java,这里面定义了createEncoder方法,但却不是我们直接要的Java_VideoEncoderFactory_createEncode方法
public interface VideoEncoderFactory { /** Creates an encoder for the given video codec. */ @Nullable @CalledByNative VideoEncoder createEncoder(VideoCodecInfo info); /** * Enumerates the list of supported video codecs. This method will only be called once and the * result will be cached. */ @CalledByNative VideoCodecInfo[] getSupportedCodecs(); }
我们在编译的目录里面搜索,看到有一些相关的jni文件
root@eae2b520e6c8:# find -name "VideoEncoderFactory_jni.h" ./releasearm64/gen/sdk/android/generated_video_jni/jni/VideoEncoderFactory_jni.h ./releasearm64/gen/third_party/webrtc/sdk/android/generated_video_jni/jni/VideoEncoderFactory_jni.h ./releasearm/gen/sdk/android/generated_video_jni/jni/VideoEncoderFactory_jni.h ./releasearm/gen/third_party/webrtc/sdk/android/generated_video_jni/jni/VideoEncoderFactory_jni.h
打开看下内容如下,可以看到我们想要的Java_VideoEncoderFactory_createEncode就在这里了
#ifndef org_webrtc_mozi_VideoEncoderFactory_JNI #define org_webrtc_mozi_VideoEncoderFactory_JNI #include <jni.h> #include "../../../../../../../third_party/webrtc/sdk/android/src/jni/jni_generator_helper.h" // Step 1: Forward declarations. JNI_REGISTRATION_EXPORT extern const char kClassPath_org_webrtc_mozi_VideoEncoderFactory[]; const char kClassPath_org_webrtc_mozi_VideoEncoderFactory[] = "org/webrtc/mozi/VideoEncoderFactory"; // Leaking this jclass as we cannot use LazyInstance from some threads. JNI_REGISTRATION_EXPORT std::atomic<jclass> g_org_webrtc_mozi_VideoEncoderFactory_clazz(nullptr); #ifndef org_webrtc_mozi_VideoEncoderFactory_clazz_defined #define org_webrtc_mozi_VideoEncoderFactory_clazz_defined inline jclass org_webrtc_mozi_VideoEncoderFactory_clazz(JNIEnv* env) { return base::android::LazyGetClass(env, kClassPath_org_webrtc_mozi_VideoEncoderFactory, &g_org_webrtc_mozi_VideoEncoderFactory_clazz); } #endif // Step 2: Constants (optional). // Step 3: Method stubs. namespace webrtc { namespace jni { static std::atomic<jmethodID> g_org_webrtc_mozi_VideoEncoderFactory_createEncoder(nullptr); static base::android::ScopedJavaLocalRef<jobject> Java_VideoEncoderFactory_createEncoder(JNIEnv* env, const base::android::JavaRef<jobject>& obj, const base::android::JavaRef<jobject>& info) { CHECK_CLAZZ(env, obj.obj(), org_webrtc_mozi_VideoEncoderFactory_clazz(env), NULL); jmethodID method_id = base::android::MethodID::LazyGet< base::android::MethodID::TYPE_INSTANCE>( env, org_webrtc_mozi_VideoEncoderFactory_clazz(env), "createEncoder", "(Lorg/webrtc/mozi/VideoCodecInfo;)Lorg/webrtc/mozi/VideoEncoder;", &g_org_webrtc_mozi_VideoEncoderFactory_createEncoder); jobject ret = env->CallObjectMethod(obj.obj(), method_id, info.obj()); jni_generator::CheckException(env); return base::android::ScopedJavaLocalRef<jobject>(env, ret); } } // namespace jni } // namespace webrtc #endif // org_webrtc_mozi_VideoEncoderFactory_JNI
总结一下调用链路
c++ ->sdk 里面的jni接口->编译生成的jni方法->Java方法
其中webrtc简化的是c++调用java这里的繁琐写法
Java调用c++
我们可以看到webrtc/sdk/android/src/jni/pc/peerconnectionfactory.h只定义了一个方法,但.cc实现文件里面内容很多,多了很多jni方法的实现,这些方法其实是在这个"sdk/android/generated_peerconnection_jni/jni/PeerConnectionFactory_jni.h"(编译生成)的里面声明的,这些jni方法对应的是PeerConnectionFactory.java里面的native方法
例如我们看到webrtc/sdk/android/src/java/org/webrtc/mozi/NativeCapturerObserver.java的nativeOnFrameCaptured方法,却找不到对应的实现,有两种方法
1. 先去编译后的目录(src/out)中寻找(find -name "NativeCapturerObserver_jni*"),找到对应文件(./releasearm/gen/sdk/android/generated_video_jni/jni/NativeCapturerObserver_jni.h),在文件中找OnFrameCaptured,基本能找到对应的jni方法声明(JNI_NativeCapturerObserver_OnFrameCaptured),然后在源码中就能找到对应的实现函数了
2. 代码有对应关系,直接搜索NativeCapturerObserver.java对应的c++实现文件webrtc/sdk/android/src/jni/nativecapturerobserver.cc(这建立在有对应文件的前提下)
end