You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
TermApp/app/src/main/cpp/PhoneDevice.cpp

1167 lines
33 KiB
C++

#include "TerminalDevice.h"
1 year ago
#include <AndroidHelper.h>
#include "PhoneDevice.h"
#include <Client/Terminal.h>
#include <Utils.h>
#include <LogThread.h>
#include "ncnn/yolov5ncnn.h"
#include "GPIOControl.h"
2 years ago
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
1 year ago
2 years ago
#include <opencv2/core/types.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <android/log.h>
#include <android/thermal.h>
#include <sys/system_properties.h>
#include <Mat.h>
#include <filesystem>
namespace fs = std::filesystem;
#define CMD_SET_485_EN_STATE 131
#define CMD_SET_CAM_3V3_EN_STATE 132
#define CMD_SET_12V_EN_STATE 133
extern bool GetJniEnv(JavaVM *vm, JNIEnv **env, bool& didAttachThread);
#define WAKELOCK_NAME "NDK_WK_"
2 years ago
// This value is 2 ^ 18 - 1, and is used to clamp the RGB values before their
// ranges
// are normalized to eight bits.
static const int kMaxChannelValue = 262143;
static long getFreeMemoryImpl(const char* const sums[], const size_t sumsLen[], size_t num)
{
int fd = open("/proc/meminfo", O_RDONLY | O_CLOEXEC);
if (fd < 0) {
ALOGW("Unable to open /proc/meminfo");
return -1;
}
char buffer[2048];
const int len = read(fd, buffer, sizeof(buffer)-1);
close(fd);
if (len < 0) {
ALOGW("Unable to read /proc/meminfo");
return -1;
}
buffer[len] = 0;
size_t numFound = 0;
jlong mem = 0;
char* p = buffer;
while (*p && numFound < num) {
int i = 0;
while (sums[i]) {
if (strncmp(p, sums[i], sumsLen[i]) == 0) {
p += sumsLen[i];
while (*p == ' ') p++;
char* num = p;
while (*p >= '0' && *p <= '9') p++;
if (*p != 0) {
*p = 0;
p++;
if (*p == 0) p--;
}
mem += atoll(num) * 1024;
numFound++;
break;
}
i++;
}
p++;
}
return numFound > 0 ? mem : -1;
}
static jlong android_os_Process_getFreeMemory()
{
static const char* const sums[] = { "MemFree:", "Cached:", NULL };
static const size_t sumsLen[] = { strlen("MemFree:"), strlen("Cached:"), 0 };
return getFreeMemoryImpl(sums, sumsLen, 2);
}
static jlong android_os_Process_getTotalMemory()
{
static const char* const sums[] = { "MemTotal:", NULL };
static const size_t sumsLen[] = { strlen("MemTotal:"), 0 };
return getFreeMemoryImpl(sums, sumsLen, 1);
}
2 years ago
static inline uint32_t YUV2RGB(int nY, int nU, int nV) {
nY -= 16;
nU -= 128;
nV -= 128;
if (nY < 0) nY = 0;
// This is the floating point equivalent. We do the conversion in integer
// because some Android devices do not have floating point in hardware.
// nR = (int)(1.164 * nY + 1.596 * nV);
// nG = (int)(1.164 * nY - 0.813 * nV - 0.391 * nU);
// nB = (int)(1.164 * nY + 2.018 * nU);
int nR = (int)(1192 * nY + 1634 * nV);
int nG = (int)(1192 * nY - 833 * nV - 400 * nU);
int nB = (int)(1192 * nY + 2066 * nU);
nR = std::min(kMaxChannelValue, std::max(0, nR));
nG = std::min(kMaxChannelValue, std::max(0, nG));
nB = std::min(kMaxChannelValue, std::max(0, nB));
nR = (nR >> 10) & 0xff;
nG = (nG >> 10) & 0xff;
nB = (nB >> 10) & 0xff;
return 0xff000000 | (nR << 16) | (nG << 8) | nB;
}
CPhoneDevice::CPhoneCamera::CPhoneCamera(CPhoneDevice* dev, int32_t width, int32_t height, const NdkCamera::CAMERA_PARAMS& params) : NdkCamera(width, height, params), m_dev(dev)
{
}
bool CPhoneDevice::CPhoneCamera::on_image(cv::Mat& rgb)
{
if (m_dev != NULL)
{
return m_dev->OnImageReady(rgb);
}
return false;
}
void CPhoneDevice::CPhoneCamera::on_error(const std::string& msg)
{
if (m_dev != NULL)
{
m_dev->onError(msg);
}
}
1 year ago
CPhoneDevice::CPhoneDevice(JavaVM* vm, jobject service, const std::string& appPath, unsigned int netId) : mCameraPowerCount(0), mOtgCount(0)
{
mCamera = NULL;
m_listener = NULL;
m_pRecognizationCfg = NULL;
mHeartbeatStartTime = 0;
mHeartbeatDuration = 0;
m_javaService = NULL;
m_appPath = appPath;
mNetId = netId;
m_sysApiClass = NULL;
m_vm = vm;
JNIEnv* env = NULL;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
}
m_javaService = env->NewGlobalRef(service);
jclass classService = env->GetObjectClass(m_javaService);
mRegisterTimerMid = env->GetMethodID(classService, "registerTimer", "(JIJ)Z");
2 years ago
mRegisterHeartbeatMid = env->GetMethodID(classService, "registerHeartbeatTimer", "(I)V");
mUnregisterTimerMid = env->GetMethodID(classService, "unregisterTimer", "(J)Z");
mUpdateTimeMid = env->GetMethodID(classService, "updateTime", "(J)Z");
mStartRecordingMid = env->GetMethodID(classService, "startRecording", "(IJIIII)V");
mRequestWakelockMid = env->GetMethodID(classService, "requestWakelock", "(Ljava/lang/String;J)V");
mReleaseWakelockMid = env->GetMethodID(classService, "releaseWakelock", "(Ljava/lang/String;)V");
mGetSystemInfoMid = env->GetMethodID(classService, "getSystemInfo", "()Ljava/lang/String;");
mRebootMid = env->GetMethodID(classService, "reboot", "(I)V");
mEnableGpsMid = env->GetMethodID(classService, "enableGps", "(Z)V");
mRequestPositionMid = env->GetMethodID(classService, "requestPosition", "()Z");
env->DeleteLocalRef(classService);
jclass classSysApi = env->FindClass("com/dev/devapi/api/SysApi");
if(classSysApi != NULL)
{
m_sysApiClass = (jclass)env->NewGlobalRef(classSysApi);
mTurnOtgMid = env->GetStaticMethodID(classSysApi, "setOtgState", "(Z)V");
mSetCam3V3EnableMid = env->GetStaticMethodID(classSysApi, "setCam3V3Enable", "(Z)V");
env->DeleteLocalRef(classSysApi);
}
if (didAttachThread)
{
vm->DetachCurrentThread();
}
m_timerUidFeed = time(NULL) * 1000;
m_wakelockIdFeed = (unsigned long)m_timerUidFeed;
}
CPhoneDevice::~CPhoneDevice()
{
JNIEnv* env = NULL;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
}
env->DeleteGlobalRef(m_javaService);
if (m_sysApiClass != NULL)
{
env->DeleteGlobalRef(m_sysApiClass);
}
if (didAttachThread)
{
m_vm->DetachCurrentThread();
}
m_javaService = NULL;
m_sysApiClass = NULL;
if (m_pRecognizationCfg != NULL)
{
ncnn_uninit();
m_pRecognizationCfg = NULL;
}
}
void CPhoneDevice::SetListener(IListener* listener)
{
m_listener = listener;
}
void CPhoneDevice::SetRecognizationCfg(const IDevice::CFG_RECOGNIZATION* pRecognizationCfg)
{
if (m_pRecognizationCfg == NULL && pRecognizationCfg != NULL && (pRecognizationCfg->enabled != 0))
{
// TODO
ncnn_init();
std::string paramFile = m_appPath + (APP_PATH_RECOG_PARAM);
std::string binFile = m_appPath + (APP_PATH_RECOG_BIN);
bool res = YoloV5Ncnn_Init(paramFile, binFile);
if (res)
{
XYLOG(XYLOG_SEVERITY_INFO, "Succeeded to Init NCNN");
}
else
{
XYLOG(XYLOG_SEVERITY_ERROR, "Failed to Init NCNN");
}
}
m_pRecognizationCfg = pRecognizationCfg;
}
bool CPhoneDevice::BindNetwork(int sock)
{
return true;
}
bool CPhoneDevice::UpdateTime(time_t ts)
{
JNIEnv* env = NULL;
jboolean ret = JNI_FALSE;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
}
jlong timeInMillis = ((jlong)ts) * 1000;
ret = env->CallBooleanMethod(m_javaService, mUpdateTimeMid, timeInMillis);
if (didAttachThread)
{
m_vm->DetachCurrentThread();
}
return (ret == JNI_TRUE);
}
bool CPhoneDevice::UpdateSchedules()
{
return true;
}
bool CPhoneDevice::QuerySystemProperties(std::map<std::string, std::string>& properties)
{
2 years ago
char value[PROP_VALUE_MAX] = { 0 };
std::map<std::string, std::string> powerInfo;
for (std::map<std::string, std::string>::iterator it = properties.begin(); it != properties.end(); ++it)
{
if (it->first == PROP_EQUIP_NAME)
{
__system_property_get("ro.product.name", value);
it->second = value;
}
else if (it->first == PROP_MODEL)
{
__system_property_get("ro.product.model", value);
it->second = value;
}
else if (it->first == PROP_BS_MANU)
{
__system_property_get("ro.product.manufacturer", value);
it->second = value;
}
else if (it->first == PROP_VERSION) {
__system_property_get("ro.build.version.release", value);
it->second = value;
}
else if (it->first == PROP_PROD_DATE) {
__system_property_get("ro.build.date.utc", value);
it->second = value;
}
else if (it->first == PROP_SN)
{
__system_property_get("ro.serialno", value);
it->second = value;
}
else if (it->first == PROP_IMEI)
{
__system_property_get("phone.imei", value);
it->second = value;
}
else if (it->first == PROP_OPERATION_TEMP)
{
it->second = QueryCpuTemperature();
}
else if (it->first == PROP_BS_ID)
{
it->second = "SHXY";
}
else if (it->first == PROP_FREE_ROM)
{
fs::space_info si = fs::space("/data");
it->second = std::to_string(si.available);
}
else if (it->first == PROP_TOTAL_ROM)
{
fs::space_info si = fs::space("/data");
it->second = std::to_string(si.capacity);
}
else if (it->first == (PROP_CHARGING_VOLTAGE))
{
double val = GpioControl::getChargingVoltage() / 200.0; // ChargeVol *5/1000
char str[32] = { 0 };
snprintf(str, sizeof(str), "%.1f", val);
it->second = str;
}
else if (it->first == (PROP_CHARGING_CURRENT))
{
it->second = std::to_string(GpioControl::getChargingCurrent());
}
else if (it->first == (PROP_CHARGING_POWER))
{
it->second = std::to_string(GpioControl::getChargingPower());
}
else if (it->first == (PROP_CHARGING_BUS_VOL))
{
it->second = std::to_string(GpioControl::getChargingBusVoltage());
}
else if (it->first == (PROP_BATTERY_VOLTAGE))
{
// double val = GpioControl::getBatteryVoltage() * 3.0 / 1000.0; // // BatVol
double val = GpioControl::getBatteryVoltage() / 1000.0; // // BatVol
char str[32] = { 0 };
snprintf(str, sizeof(str), "%.1f", val);
it->second = str;
}
else if (it->first == (PROP_BATTERY_CURRENT))
{
it->second = std::to_string(GpioControl::getBatteryCurrent());
}
else if (it->first == (PROP_BATTERY_POWER))
{
it->second = std::to_string(GpioControl::getBatteryPower());
}
else if (it->first == (PROP_BATTERY_BUS_VOL))
{
it->second = std::to_string(GpioControl::getBatteryBusVoltage());
}
else if (startsWith(it->first, PROP_JAVA_PREFIX))
{
if (powerInfo.empty())
{
QueryPowerInfo(powerInfo);
}
auto it2 = powerInfo.find(it->first);
if (it2 != powerInfo.cend())
{
it->second = it2->second;
}
}
}
2 years ago
// __system_property_get("ro.telephony.default_network", value);
2 years ago
return true;
}
2 years ago
std::string CPhoneDevice::QueryCpuTemperature()
{
// /sys/devices/virtual/thermal/thermal_zone0/temp
std::vector<unsigned char> data;
if (readFile("/sys/devices/virtual/thermal/thermal_zone0/temp", data) && !data.empty())
{
data.push_back(0);
int temp = atoi((const char*)(&data[0]));
return std::to_string(temp / 1000);
}
2 years ago
return "";
}
void CPhoneDevice::QueryPowerInfo(std::map<std::string, std::string>& powerInfo)
{
JNIEnv* env = NULL;
jboolean ret = JNI_FALSE;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
}
jobject jobj = env->CallObjectMethod(m_javaService, mGetSystemInfoMid);
std::string str = jstring2string(env, (jstring)jobj);
if (didAttachThread)
{
m_vm->DetachCurrentThread();
}
if (!str.empty())
{
std::map<std::string, std::string> queries = parseQuery(str);
powerInfo.swap(queries);
}
}
bool CPhoneDevice::GetNextScheduleItem(uint32_t tsBasedZero, uint32_t scheduleTime, vector<uint32_t>& items)
{
return false;
}
bool CPhoneDevice::Reboot(int resetType)
2 years ago
{
if (resetType == 1)
{
// reboot the device
GpioControl::reboot();
return true;
}
JNIEnv* env = NULL;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
}
env->CallVoidMethod(m_javaService, mRebootMid, resetType);
if (didAttachThread)
{
m_vm->DetachCurrentThread();
}
return true;
}
bool CPhoneDevice::EnableGPS(bool enabled)
{
JNIEnv* env = NULL;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
return false;
}
jboolean jenabled = enabled ? JNI_TRUE : JNI_FALSE;
env->CallVoidMethod(m_javaService, mEnableGpsMid, jenabled);
if (didAttachThread)
{
m_vm->DetachCurrentThread();
}
return true;
}
bool CPhoneDevice::RequestPosition()
{
JNIEnv* env = NULL;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
return false;
}
jboolean ret = env->CallBooleanMethod(m_javaService, mRequestPositionMid);
if (didAttachThread)
{
m_vm->DetachCurrentThread();
}
return (ret == JNI_TRUE);
2 years ago
}
IDevice::timer_uid_t CPhoneDevice::RegisterTimer(unsigned int timerType, unsigned int timeout, unsigned long times/* = 0*/)
{
IDevice::timer_uid_t uid = m_timerUidFeed.fetch_add(1);
ALOGI("NDK RegTimer: uid=%lld Type=%u timeout=%u", uid, timerType, timeout);
JNIEnv* env = NULL;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
return 0;
}
jboolean ret = env->CallBooleanMethod(m_javaService, mRegisterTimerMid, (jlong)uid, (jint)timeout, (jlong)times);
if (didAttachThread)
{
m_vm->DetachCurrentThread();
}
if (ret == JNI_TRUE)
{
unsigned long val = timerType;
mTimers.insert(mTimers.end(), std::pair<IDevice::timer_uid_t, unsigned long>(uid, val));
return uid;
}
return 0;
}
bool CPhoneDevice::UnregisterTimer(IDevice::timer_uid_t uid)
{
jboolean ret = JNI_FALSE;
JNIEnv* env = NULL;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
return false;
}
ret = env->CallBooleanMethod(m_javaService, mUnregisterTimerMid, (jlong)uid);
if (didAttachThread)
{
m_vm->DetachCurrentThread();
}
if (ret == JNI_TRUE)
{
mTimers.erase(uid);
return true;
}
return false;
}
unsigned long CPhoneDevice::RequestWakelock(unsigned long timeout)
{
unsigned long wakelockId = m_wakelockIdFeed.fetch_add(1);
std::string name = WAKELOCK_NAME;
name += to_string(wakelockId);
// ALOGI("RequestWakelock=%lld",wakelockId);
jboolean ret = JNI_FALSE;
JNIEnv* env = NULL;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
return 0;
}
jstring jname = env->NewStringUTF(name.c_str());
jlong jtimeout = (jlong)timeout;
env->CallVoidMethod(m_javaService, mRequestWakelockMid, jname, jtimeout);
// env->ReleaseStringUTFChars(jname, name.c_str());
env->DeleteLocalRef(jname);
if (didAttachThread)
{
m_vm->DetachCurrentThread();
}
return wakelockId;
}
bool CPhoneDevice::ReleaseWakelock(unsigned long wakelock)
{
// ALOGI("ReleaseWakelock=%lld", wakelock);
std::string name = WAKELOCK_NAME;
name += to_string(wakelock);
jboolean ret = JNI_FALSE;
JNIEnv* env = NULL;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
return false;
}
jstring jname = env->NewStringUTF(name.c_str());
env->CallVoidMethod(m_javaService, mReleaseWakelockMid, jname);
env->DeleteLocalRef(jname);
// env->ReleaseStringUTFChars(jname, name.c_str());
if (didAttachThread)
{
m_vm->DetachCurrentThread();
}
return true;
}
bool CPhoneDevice::FireTimer(timer_uid_t uid, unsigned long times)
{
std::map<IDevice::timer_uid_t, unsigned long>::iterator it = mTimers.find(uid);
if (it == mTimers.end())
{
return false;
}
unsigned long timerType = it->second & 0xFFFFFFFF;
unsigned long ntimes = (it->second & 0xFFFFFFFF00000000) >> 32;
ntimes++;
if (timerType != 100)
{
// int aa = 0;
}
it->second = timerType | (ntimes << 32);
if (m_listener == NULL)
{
return false;
}
m_listener->OnTimeout(uid, timerType, ntimes);
return true;
}
IDevice::timer_uid_t CPhoneDevice::RegisterHeartbeat(unsigned int timerType, unsigned int timeout)
{
mHeartbeatStartTime = time(NULL);
mHeartbeatDuration = timeout;
2 years ago
IDevice::timer_uid_t uid = m_timerUidFeed.fetch_add(1);
jboolean ret = JNI_FALSE;
JNIEnv* env = NULL;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
return 0;
}
env->CallVoidMethod(m_javaService, mRegisterHeartbeatMid, (jint)timeout);
if (didAttachThread)
2 years ago
{
m_vm->DetachCurrentThread();
}
return uid;
}
bool CPhoneDevice::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<OSD_INFO>& osds, const std::string& path)
{
if (mCamera != NULL)
{
delete mCamera;
mCamera = NULL;
}
ALOGI("TAKE_PHOTO: CH=%u PR=%u PHOTOID=%u\n", (unsigned int)photoInfo.channel, (unsigned int)photoInfo.preset, photoInfo.photoId);
mPhotoInfo = photoInfo;
mPath = path;
mOsds = osds;
NdkCamera::CAMERA_PARAMS params;
params.hdrMode = mPhotoInfo.hdrMode;
params.nightMode = mPhotoInfo.nightMode;
params.autoFocus = mPhotoInfo.autoFocus;
params.autoExposure = mPhotoInfo.autoExposure;
params.exposureTime = mPhotoInfo.exposureTime;
params.sensibility = mPhotoInfo.sensibility;
params.orientation = mPhotoInfo.orientation;
// GpioControl::EnableGpio(CMD_SET_CAM_3V3_EN_STATE, true);
JNIEnv* env = NULL;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
return false;
}
if (photoInfo.usbCamera)
{
1 year ago
TurnOnOtg(env);
}
1 year ago
TurnOnCameraPower(env);
res = true;
if (mPhotoInfo.mediaType == 0)
{
mCamera = new CPhoneCamera(this, photoInfo.width, photoInfo.height, params);
if (mCamera->open(to_string(mPhotoInfo.cameraId)) == 0)
{
}
else
{
delete mCamera;
mCamera = NULL;
res = false;
}
}
else
{
env->CallVoidMethod(m_javaService, mStartRecordingMid, mPhotoInfo.cameraId, (unsigned long)mPhotoInfo.photoId, mPhotoInfo.duration, mPhotoInfo.width, mPhotoInfo.height, mPhotoInfo.duration);
}
if (didAttachThread)
{
m_vm->DetachCurrentThread();
}
return res;
}
bool CPhoneDevice::CloseCamera()
{
if (mCamera != NULL)
{
auto camera = mCamera;
mCamera = NULL;
camera->close();
delete camera;
}
return true;
}
void CPhoneDevice::CloseCamera2(CPhoneDevice::CPhoneCamera* camera, bool turnOffOtg)
{
// std::this_thread::sleep_for(std::chrono::milliseconds(16));
if (camera != NULL)
{
camera->close();
delete camera;
}
// GpioControl::EnableGpio(CMD_SET_CAM_3V3_EN_STATE, true);
JNIEnv* env = NULL;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
return;
}
1 year ago
if (turnOffOtg)
{
1 year ago
TurnOffOtg(env);
}
1 year ago
TurnOffCameraPower(env);
if (didAttachThread)
{
m_vm->DetachCurrentThread();
}
}
void visualize(const char* filename, const ncnn::Mat& m)
{
cv::Mat a(m.h, m.w, CV_8UC3);
m.to_pixels(a.data, ncnn::Mat::PIXEL_BGR2RGB);
cv::imwrite(filename, a);
}
void DrawOutlineText(cv::Mat& mat, const std::string& str, cv::Point startPoint, double fontScale, cv::Scalar clr1, cv::Scalar clr2, int thickness1, int thickness2)
{
std::vector<std::string> chars;
splitUtf8Str(str, chars);
int lineHeight = 0;
cv::Point pt = startPoint;
cv::Size textSize, textSize2;
int baseline = 0;
cv::Point pt2;
for (std::vector<std::string>::const_iterator it = chars.cbegin(); it != chars.cend(); ++it )
{
if (it->compare("\n") == 0)
{
pt.x = startPoint.x;
pt.y += lineHeight > 0 ? (lineHeight + 2) : 0;
continue;
}
textSize = cv::getTextSize(*it, cv::FONT_HERSHEY_COMPLEX, fontScale, thickness1, &baseline);
textSize2 = cv::getTextSize(*it, cv::FONT_HERSHEY_COMPLEX, fontScale, thickness2, &baseline);
lineHeight = std::max(lineHeight, std::max(textSize.height, textSize2.height));
if (it->compare(" ") != 0)
{
// cv2.putText(image,"text",(180,150),cv2.FONT_HERSHEY_COMPLEX,3,(255,255,255),16,cv2.LINE_AA)
// cv2.putText(image,"text",(180,150),cv2.FONT_HERSHEY_COMPLEX,3,(0,0,0),4,cv2.LINE
// balck
cv::putText(mat, *it, pt, cv::FONT_HERSHEY_COMPLEX, fontScale, clr1, thickness1, cv::LINE_AA);
// white
pt2 = pt;
// pt2.y += 1;
cv::putText(mat, *it, pt2, cv::FONT_HERSHEY_COMPLEX, fontScale, clr2, thickness2, cv::LINE_AA);
}
pt.x += std::max(textSize.width, textSize2.width);
}
}
bool CPhoneDevice::OnImageReady(cv::Mat& mat)
{
if (mCamera == NULL)
{
int aa = 0;
return false;
}
mPhotoInfo.photoTime = time(NULL);
int baseline = 0;
cv::Size textSize, textSize2;
double fontScale = 1; // base 1024
double height = mat.size().height;
double width = mat.size().width;
2 years ago
// double ratio = std::min(height / 1024, width / 1920);
double ratio = std::sqrt((height * width) / (1024.0 * 1920.0));
fontScale = fontScale * ratio;
// cv::Rect rc(0, 0, mat.cols, mat.rows);
// cv::rectangle (mat, rc, cv::Scalar(255, 255, 255), cv::FILLED);
std::vector<IDevice::RECOG_OBJECT> objs;
if ((m_pRecognizationCfg != NULL) && (m_pRecognizationCfg->enabled != 0) && (mPhotoInfo.recognization != 0))
{
// visualize(ncnnPath.c_str(), in);
#ifdef _DEBUG
double startTime = ncnn::get_current_time();
#endif // _DEBUG
bool detected = YoloV5NcnnDetect(mat, true, m_pRecognizationCfg->blobName8, m_pRecognizationCfg->blobName16, m_pRecognizationCfg->blobName32, objs);
#ifdef _DEBUG
double elasped = ncnn::get_current_time() - startTime;
// __android_log_print(ANDROID_LOG_DEBUG, "YoloV5Ncnn", "%.2fms detect", elasped);
#endif // _DEBUG
#ifdef _DEBUG
ALOGI( "NCNN recognization: %.2fms res=%d", elasped, ((detected && !objs.empty()) ? 1 : 0));
#endif
if (detected && !objs.empty())
{
#if 0
static const char* class_names[] = {
"person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light",
"fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow",
"elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee",
"skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard",
"tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
"sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
"potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone",
"microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear",
"hair drier", "toothbrush"
};
#endif
cv::Scalar borderColor(m_pRecognizationCfg->borderColor & 0xFF, (m_pRecognizationCfg->borderColor & 0xFF00) >> 8, (m_pRecognizationCfg->borderColor & 0xFF0000) >> 16);
for (std::vector<IDevice::RECOG_OBJECT>::const_iterator it = objs.cbegin(); it != objs.cend(); ++it)
{
if (it->label >= m_pRecognizationCfg->items.size())
{
continue;
}
const IDevice::CFG_RECOGNIZATION::ITEM& item = m_pRecognizationCfg->items[it->label];
if (item.enabled == 0 || it->prob < item.prob)
{
continue;
}
#ifdef _DEBUG
ALOGD("Label: %d=%s (%f,%f)-(%f,%f)", it->label, item.name.c_str(), it->x, it->y, it->w, it->h);
#endif
cv::Rect rc(it->x, it->y, it->w, it->h);
cv::rectangle(mat, rc, borderColor, m_pRecognizationCfg->thickness);
// putText
}
}
}
int thickness2 = 8 * ratio;
if (thickness2 < 2) thickness2 = 2;
int thickness1 = 1 * ratio;
if (thickness1 < 1) thickness1 = 1;
cv::Scalar scalar1(0, 0, 0); // black
cv::Scalar scalar2(255, 255, 255); // white
#ifdef _DEBUG
1 year ago
cv::Scalar scalar(0, 0, 255); // white
NdkCamera::CAPTURE_RESULT captureResult = mCamera->getCaptureResult();
char str[128] = { 0 };
snprintf(str, sizeof(str), "AE=%u EXPS=%ums ISO=%d AF=%u FD=%.3f HDR=%d", captureResult.autoExposure,
(unsigned int)(captureResult.exposureTime / 1000000),
captureResult.sensitibity,
captureResult.autoFocus,
isnan(captureResult.FocusDistance) ? 0 : captureResult.FocusDistance,
captureResult.hdrMode);
1 year ago
cv::putText(mat, str, cv::Point(0, mat.rows - 20), cv::FONT_HERSHEY_COMPLEX, fontScale, scalar, thickness1, cv::LINE_AA);
#endif
cv::Point pt1, pt2;
for (vector<OSD_INFO>::const_iterator it = mOsds.cbegin(); it != mOsds.cend(); ++it)
{
2 years ago
if (it->text.empty())
{
continue;
}
textSize = cv::getTextSize(it->text, cv::FONT_HERSHEY_TRIPLEX, fontScale, thickness1, &baseline);
textSize2 = cv::getTextSize(it->text, cv::FONT_HERSHEY_TRIPLEX, fontScale, thickness2, &baseline);
if (it->alignment == OSD_ALIGNMENT_TOP_LEFT)
{
pt1.x = it->x * ratio;
pt1.y = it->y * ratio + textSize.height;
}
else if (it->alignment == OSD_ALIGNMENT_TOP_RIGHT)
{
pt1.x = width - textSize.width - it->x * ratio;
pt1.y= it->y * ratio + textSize.height;
}
else if (it->alignment == OSD_ALIGNMENT_BOTTOM_RIGHT)
{
pt1.x = width - textSize.width - it->x * ratio;
pt1.y = height - it->y * ratio;
}
else if (it->alignment == OSD_ALIGNMENT_BOTTOM_LEFT)
{
pt1.x = it->x * ratio;
pt1.y = height - it->y * ratio;
}
2 years ago
cv::Point pt = pt1;
pt.x += textSize.width;
pt.y -= textSize.height;
// cv::rectangle(mat, pt1, pt, scalar2, -1);
pt2 = pt1;
pt2.y += textSize.height;
DrawOutlineText(mat, it->text, pt1, fontScale, scalar1, scalar2, thickness1, thickness2);
}
vector <int> params;
params.push_back(cv::IMWRITE_JPEG_QUALITY);
params.push_back(mPhotoInfo.quality);
bool res = false;
std::string fullPath = mPath + CTerminal::BuildPhotoFileName(mPhotoInfo);
if (!std::filesystem::exists(std::filesystem::path(fullPath)))
{
bool res = cv::imwrite(fullPath.c_str(), mat, params);
if (!res)
{
ALOGE("Failed to write photo: %s", fullPath.c_str());
}
else
{
ALOGI("Succeeded to write photo: %s", fullPath.c_str());
}
TakePhotoCb(res, mPhotoInfo, fullPath, time(NULL), objs);
}
else
{
ALOGI("Photo file exists: %s", mPath.c_str());
}
CPhoneCamera* pCamera = mCamera;
mCamera = NULL;
bool turnOffOtg = (mPhotoInfo.usbCamera != 0);
std::thread closeThread(&CPhoneDevice::CloseCamera2, this, pCamera, turnOffOtg);
closeThread.detach();
return res;
}
bool CPhoneDevice::OnVideoReady(bool result, const char* path, unsigned int photoId)
{
mPhotoInfo.photoTime = time(NULL);
CPhoneCamera* pCamera = NULL;
std::vector<IDevice::RECOG_OBJECT> objs;
std::string fullPath = mPath + CTerminal::BuildPhotoFileName(mPhotoInfo);
if (result)
{
std::rename(path, fullPath.c_str());
}
TakePhotoCb(result, mPhotoInfo, fullPath, time(NULL), objs);
bool turnOffOtg = (mPhotoInfo.usbCamera != 0);
std::thread closeThread(&CPhoneDevice::CloseCamera2, this, pCamera, turnOffOtg);
closeThread.detach();
return result;
}
void CPhoneDevice::onError(const std::string& msg)
{
// XFLOG(XFLOG_SEVERITY_ERROR, "Failed to Take Photo: %s", msg.c_str());
if (mCamera == NULL)
{
int aa = 0;
return;
}
ALOGE("Failed to Take Photo: %s", msg.c_str());
CPhoneCamera* pCamera = mCamera;
mCamera = NULL;
TakePhotoCb(false, mPhotoInfo, mPath, 0);
bool turnOffOtg = (mPhotoInfo.usbCamera != 0);
std::thread closeThread(&CPhoneDevice::CloseCamera2, this, pCamera, turnOffOtg);
closeThread.detach();
}
std::string CPhoneDevice::GetFileName() const
{
return mPath;
}
2 years ago
void CPhoneDevice::UpdatePosition(double lon, double lat, time_t ts)
{
if (m_listener != NULL)
{
return m_listener->OnPositionDataArrived(lon, lat, ts);
}
1 year ago
}
void CPhoneDevice::TurnOnCameraPower(JNIEnv* env)
{
mCameraPowerLocker.lock();
if (mCameraPowerCount == 0)
{
#if 0
1 year ago
if(m_sysApiClass != NULL)
{
#ifdef _DEBUG
XYLOG(XYLOG_SEVERITY_INFO, "Set Cam3V3 Enabled ");
#endif
env->CallStaticVoidMethod(m_sysApiClass, mSetCam3V3EnableMid, JNI_TRUE);
}
#endif
GpioControl::setCam3V3Enable(true);
1 year ago
}
mCameraPowerCount++;
mCameraPowerLocker.unlock();
}
void CPhoneDevice::TurnOffCameraPower(JNIEnv* env)
{
mCameraPowerLocker.lock();
if (mCameraPowerCount > 0)
{
mCameraPowerCount--;
if (mCameraPowerCount == 0)
{
#if 0
1 year ago
if(m_sysApiClass != NULL)
{
#ifdef _DEBUG
XYLOG(XYLOG_SEVERITY_INFO, "Set Cam3V3 Disabled ");
#endif
env->CallStaticVoidMethod(m_sysApiClass, mSetCam3V3EnableMid, JNI_FALSE);
}
#endif // 0
GpioControl::setCam3V3Enable(false);
1 year ago
}
}
mCameraPowerLocker.unlock();
}
void CPhoneDevice::TurnOnOtg(JNIEnv* env)
{
mCameraPowerLocker.lock();
if (mOtgCount == 0)
{
#if 0
1 year ago
if(m_sysApiClass != NULL)
{
#ifdef _DEBUG
XYLOG(XYLOG_SEVERITY_INFO, "Turn On Otg");
#endif
env->CallStaticVoidMethod(m_sysApiClass, mTurnOtgMid, JNI_TRUE);
}
#endif
GpioControl::setOtgState(true);
1 year ago
}
mOtgCount++;
mCameraPowerLocker.unlock();
}
void CPhoneDevice::TurnOffOtg(JNIEnv* env)
{
mCameraPowerLocker.lock();
if (mOtgCount > 0)
{
mOtgCount--;
if (mOtgCount == 0)
{
#if 0
1 year ago
if(m_sysApiClass != NULL)
{
#ifdef _DEBUG
XYLOG(XYLOG_SEVERITY_INFO, "Turn Off Otg");
#endif
env->CallStaticVoidMethod(m_sysApiClass, mTurnOtgMid, JNI_FALSE);
}
#endif
GpioControl::setOtgState(false);
1 year ago
}
}
mCameraPowerLocker.unlock();
}