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

 

 
posted @ 2021-11-26 15:03  2BiTT  阅读(1205)  评论(0编辑  收藏  举报