151 lines
5.8 KiB
C++
151 lines
5.8 KiB
C++
/*
|
|
* Copyright (C) 2023 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#define LOG_TAG "DeviceAsWebcamNative"
|
|
|
|
#include <DeviceAsWebcamServiceManager.h>
|
|
#include <log/log.h>
|
|
#include <nativehelper/JNIHelp.h>
|
|
|
|
#include "DeviceAsWebcamNative.h"
|
|
|
|
/**
|
|
* Called by the JVM when JNI is loaded. This does not imply that the service is actually running,
|
|
* only that the jni library is loaded.
|
|
*/
|
|
jint JNI_OnLoad(JavaVM* jvm, void*) {
|
|
using namespace android::webcam;
|
|
JNIEnv* e = NULL;
|
|
if (jvm->GetEnv((void**)&e, JNI_VERSION_1_6)) {
|
|
return JNI_ERR;
|
|
}
|
|
if (DeviceAsWebcamNative::registerJNIMethods(e, jvm)) {
|
|
return JNI_ERR;
|
|
}
|
|
return JNI_VERSION_1_6;
|
|
}
|
|
|
|
namespace android {
|
|
namespace webcam {
|
|
|
|
// These will be initialized by registerJNIMethods
|
|
JavaMethods DeviceAsWebcamNative::kJavaMethods = {};
|
|
JavaVM* DeviceAsWebcamNative::kJVM = nullptr;
|
|
|
|
static inline jclass FindClassOrDie(JNIEnv* env, const char* class_name) {
|
|
jclass clazz = env->FindClass(class_name);
|
|
LOG_ALWAYS_FATAL_IF(clazz == nullptr, "Unable to find class %s", class_name);
|
|
return clazz;
|
|
}
|
|
|
|
static inline jmethodID GetMethodIdOrDie(JNIEnv* env, jclass clazz, const char* method_name,
|
|
const char* method_signature) {
|
|
jmethodID res = env->GetMethodID(clazz, method_name, method_signature);
|
|
LOG_ALWAYS_FATAL_IF(res == nullptr, "Unable to find method %s with signature %s", method_name,
|
|
method_signature);
|
|
return res;
|
|
}
|
|
|
|
const JNINativeMethod DeviceAsWebcamNative::sMethods[] = {
|
|
{"setupServicesAndStartListeningNative", "()I",
|
|
(void*)com_android_DeviceAsWebcam_setupServicesAndStartListening},
|
|
{"nativeOnDestroy", "()V", (void*)com_android_DeviceAsWebcam_onDestroy},
|
|
{"shouldStartServiceNative", "()Z", (void*)com_android_DeviceAsWebcam_shouldStartService},
|
|
{"nativeEncodeImage", "(Landroid/hardware/HardwareBuffer;J)I",
|
|
(void*)com_android_DeviceAsWebcam_encodeImage},
|
|
};
|
|
|
|
int DeviceAsWebcamNative::registerJNIMethods(JNIEnv* e, JavaVM* jvm) {
|
|
char clsName[] = "com/android/DeviceAsWebcam/DeviceAsWebcamFgService";
|
|
int ret = jniRegisterNativeMethods(e, clsName, sMethods, NELEM(sMethods));
|
|
if (ret) {
|
|
return JNI_ERR;
|
|
}
|
|
|
|
jclass clazz = FindClassOrDie(e, clsName);
|
|
kJavaMethods.setStreamConfig = GetMethodIdOrDie(e, clazz, "setStreamConfig", "(ZIII)V");
|
|
kJavaMethods.startStreaming = GetMethodIdOrDie(e, clazz, "startStreaming", "()V");
|
|
kJavaMethods.stopStreaming = GetMethodIdOrDie(e, clazz, "stopStreaming", "()V");
|
|
kJavaMethods.stopService = GetMethodIdOrDie(e, clazz, "stopService", "()V");
|
|
kJavaMethods.returnImage = GetMethodIdOrDie(e, clazz, "returnImage", "(J)V");
|
|
|
|
kJVM = jvm;
|
|
return 0;
|
|
}
|
|
|
|
jint DeviceAsWebcamNative::com_android_DeviceAsWebcam_encodeImage(JNIEnv* env, jobject,
|
|
jobject hardwareBuffer,
|
|
jlong timestamp) {
|
|
return DeviceAsWebcamServiceManager::kInstance->encodeImage(env, hardwareBuffer, timestamp);
|
|
}
|
|
|
|
jint DeviceAsWebcamNative::com_android_DeviceAsWebcam_setupServicesAndStartListening(JNIEnv* env,
|
|
jobject thiz) {
|
|
return DeviceAsWebcamServiceManager::kInstance->setupServicesAndStartListening(env, thiz);
|
|
}
|
|
|
|
jboolean DeviceAsWebcamNative::com_android_DeviceAsWebcam_shouldStartService(JNIEnv*, jclass) {
|
|
return DeviceAsWebcamServiceManager::kInstance->shouldStartService();
|
|
}
|
|
|
|
void DeviceAsWebcamNative::com_android_DeviceAsWebcam_onDestroy(JNIEnv*, jobject) {
|
|
DeviceAsWebcamServiceManager::kInstance->onDestroy();
|
|
}
|
|
|
|
void DeviceAsWebcamNative::setStreamConfig(jobject thiz, bool mjpeg, uint32_t width,
|
|
uint32_t height, uint32_t fps) {
|
|
JNIEnv* env = getJNIEnvOrAbort();
|
|
jboolean jMjpeg = mjpeg ? JNI_TRUE : JNI_FALSE;
|
|
jint jWidth = static_cast<jint>(width);
|
|
jint jHeight = static_cast<jint>(height);
|
|
jint jFps = static_cast<jint>(fps);
|
|
env->CallVoidMethod(thiz, kJavaMethods.setStreamConfig, jMjpeg, jWidth, jHeight, jFps);
|
|
}
|
|
|
|
void DeviceAsWebcamNative::startStreaming(jobject thiz) {
|
|
JNIEnv* env = getJNIEnvOrAbort();
|
|
env->CallVoidMethod(thiz, kJavaMethods.startStreaming);
|
|
}
|
|
void DeviceAsWebcamNative::stopStreaming(jobject thiz) {
|
|
JNIEnv* env = getJNIEnvOrAbort();
|
|
env->CallVoidMethod(thiz, kJavaMethods.stopStreaming);
|
|
}
|
|
|
|
void DeviceAsWebcamNative::returnImage(jobject thiz, long timestamp) {
|
|
JNIEnv* env = getJNIEnvOrAbort();
|
|
jlong jTimestamp = static_cast<jlong>(timestamp);
|
|
env->CallVoidMethod(thiz, kJavaMethods.returnImage, jTimestamp);
|
|
}
|
|
|
|
void DeviceAsWebcamNative::stopService(jobject thiz) {
|
|
JNIEnv* env = getJNIEnvOrAbort();
|
|
env->CallVoidMethod(thiz, kJavaMethods.stopService);
|
|
}
|
|
|
|
JNIEnv* DeviceAsWebcamNative::getJNIEnvOrAbort() {
|
|
JNIEnv* env = nullptr;
|
|
kJVM->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
|
|
if (env == nullptr) {
|
|
ALOGE("%s: Called from a thread not bound to the JVM", __FUNCTION__);
|
|
// Call abort() to force creation of a tombstone for easier debugging.
|
|
abort(); // :(
|
|
}
|
|
return env;
|
|
}
|
|
|
|
} // namespace webcam
|
|
} // namespace android
|