1 /*
2  *  Copyright 2017 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "modules/video_coding/codecs/test/android_codec_factory_helper.h"
12 
13 #include <pthread.h>
14 
15 #include <memory>
16 
17 #include "rtc_base/checks.h"
18 #include "rtc_base/ignore_wundef.h"
19 #include "sdk/android/native_api/base/init.h"
20 #include "sdk/android/native_api/codecs/wrapper.h"
21 #include "sdk/android/native_api/jni/class_loader.h"
22 #include "sdk/android/native_api/jni/jvm.h"
23 #include "sdk/android/native_api/jni/scoped_java_ref.h"
24 
25 // Note: this dependency is dangerous since it reaches into Chromium's base.
26 // There's a risk of e.g. macro clashes. This file may only be used in tests.
27 // Since we use Chrome's build system for creating the gtest binary, this should
28 // be fine.
29 RTC_PUSH_IGNORING_WUNDEF()
30 #include "base/android/jni_android.h"
31 RTC_POP_IGNORING_WUNDEF()
32 
33 namespace webrtc {
34 namespace test {
35 
36 namespace {
37 
38 static pthread_once_t g_initialize_once = PTHREAD_ONCE_INIT;
39 
40 // There can only be one JNI_OnLoad in each binary. So since this is a GTEST
41 // C++ runner binary, we want to initialize the same global objects we normally
42 // do if this had been a Java binary.
EnsureInitializedOnce()43 void EnsureInitializedOnce() {
44   RTC_CHECK(::base::android::IsVMInitialized());
45   JNIEnv* env = ::base::android::AttachCurrentThread();
46   JavaVM* jvm = nullptr;
47   RTC_CHECK_EQ(0, env->GetJavaVM(&jvm));
48 
49   InitAndroid(jvm);
50 }
51 
52 }  // namespace
53 
InitializeAndroidObjects()54 void InitializeAndroidObjects() {
55   RTC_CHECK_EQ(0, pthread_once(&g_initialize_once, &EnsureInitializedOnce));
56 }
57 
CreateAndroidEncoderFactory()58 std::unique_ptr<VideoEncoderFactory> CreateAndroidEncoderFactory() {
59   JNIEnv* env = AttachCurrentThreadIfNeeded();
60   ScopedJavaLocalRef<jclass> factory_class =
61       GetClass(env, "org/webrtc/HardwareVideoEncoderFactory");
62   jmethodID factory_constructor = env->GetMethodID(
63       factory_class.obj(), "<init>", "(Lorg/webrtc/EglBase$Context;ZZ)V");
64   ScopedJavaLocalRef<jobject> factory_object(
65       env, env->NewObject(factory_class.obj(), factory_constructor,
66                           nullptr /* shared_context */,
67                           false /* enable_intel_vp8_encoder */,
68                           true /* enable_h264_high_profile */));
69   return JavaToNativeVideoEncoderFactory(env, factory_object.obj());
70 }
71 
CreateAndroidDecoderFactory()72 std::unique_ptr<VideoDecoderFactory> CreateAndroidDecoderFactory() {
73   JNIEnv* env = AttachCurrentThreadIfNeeded();
74   ScopedJavaLocalRef<jclass> factory_class =
75       GetClass(env, "org/webrtc/HardwareVideoDecoderFactory");
76   jmethodID factory_constructor = env->GetMethodID(
77       factory_class.obj(), "<init>", "(Lorg/webrtc/EglBase$Context;)V");
78   ScopedJavaLocalRef<jobject> factory_object(
79       env, env->NewObject(factory_class.obj(), factory_constructor,
80                           nullptr /* shared_context */));
81   return JavaToNativeVideoDecoderFactory(env, factory_object.obj());
82 }
83 
84 }  // namespace test
85 }  // namespace webrtc
86