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

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM