| usbcameralib/CMakeLists.txt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| usbcameralib/build.gradle | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| usbcameralib/src/main/cpp/ImageProc.c | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| usbcameralib/src/main/cpp/apptimer.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| usbcameralib/src/main/cpp/apptimer.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| usbcameralib/src/main/cpp/charencode.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| usbcameralib/src/main/cpp/watermark.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| usbcameralib/src/main/cpp/watermark.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
usbcameralib/CMakeLists.txt
@@ -17,10 +17,11 @@ # Provides a relative path to your source file(s). src/main/cpp/libyuv.c src/main/cpp/apptimer.cpp src/main/cpp/charencode.cpp src/main/cpp/watermark.cpp src/main/cpp/ImageProc.c src/main/cpp/charencode.c src/main/cpp/jpeg.c src/main/cpp/watermark.c src/main/cpp/SonixCamera/ROMData.c src/main/cpp/SonixCamera/SFData.c src/main/cpp/SonixCamera/SonixCamera.c @@ -62,7 +63,9 @@ jpeg turbojpeg ${log-lib} ${g-lib}) ${g-lib} c++_shared ) #target_link_libraries( # Specifies the target library. # usbcamera-lib usbcameralib/build.gradle
@@ -14,7 +14,7 @@ externalNativeBuild { cmake { arguments "-DANDROID_ARM_NEON=TRUE" arguments "-DANDROID_ARM_NEON=TRUE","-DANDROID_STL=c++_shared" cppFlags "" } } @@ -43,6 +43,7 @@ pickFirst 'lib/armeabi-v7a/libturbojpeg.so' pickFirst 'lib/arm64-v8a/libjpeg.so' pickFirst 'lib/arm64-v8a/libturbojpeg.so' pickFirst 'lib/*/libc++_shared.so' } usbcameralib/src/main/cpp/ImageProc.c
@@ -1107,6 +1107,11 @@ (*env)->ReleaseStringUTFChars(env, name, except_camera_name); } if (ret == SUCCESS_LOCAL) { InitWatermark("/system/ms_unicode_24.bin", IMG_WIDTH, IMG_HEIGHT); wm_enable = true; } return ret; } @@ -1122,6 +1127,9 @@ pthread_mutex_lock(&mutex); cam_inited = false; wm_enable = false; UninitWatermark(); LOGI("stopcapturing"); stopcapturing(); usbcameralib/src/main/cpp/apptimer.cpp
New file @@ -0,0 +1,262 @@ // // Created by YY on 2021/3/16. // #include "apptimer.h" //#include "../jni_log.h" #include <cstdint> #include <functional> #include <chrono> #include <mutex> #include <condition_variable> #include <list> #include <thread> #include <map> #include <string> #include <sstream> #include <iomanip> #define DEBUG(fmt, args...) //LOGD("<apptimer> <%s>: " fmt, __func__, ##args) std::mutex mtx; std::map<void(*)(apptimer_var_t), CTimer *> TimerList; static void RemoveTimerList(const CTimer *p); CTimer::CTimer() { flag = 0; var.var_ptr = nullptr; var.var1 = var.var2 = var.var_length = 0; pthread = nullptr; } CTimer::~CTimer() { if (pthread != nullptr) { delete pthread; } if (var.var_ptr != nullptr) { delete var.var_ptr; } } bool CTimer::_updateStatus(CTimer *timer) { if (timer->flag == 0) { return false; } else { return true; //cancel } } void CTimer::_do_task_func(uint32_t msec, CTimer *timer, std::function<void(apptimer_var_t)> callback) { std::unique_lock<std::mutex> lk(timer->cv_mtx); auto now = std::chrono::steady_clock::now(); if (timer->cv.wait_until(lk, now + std::chrono::milliseconds(msec), std::bind(_updateStatus, timer)) == false) { RemoveTimerList(timer); // 从列表中删除索引 if (timer->flag == 0) { callback(timer->var); } } else { // LOGD("Cancel %d", static_cast<int>(timer->flag)); RemoveTimerList(timer); } //delete timer; lk.unlock(); // std::thread(clear, timer).detach(); delete timer; } void CTimer::copy(int value1, int value2, const void *data, int length) { this->var.var1 = value1; this->var.var2 = value2; this->var.var_length = length; if (length > 0 && data != nullptr) { this->var.var_ptr = new uint8_t[length]; memcpy(this->var.var_ptr, data, length); } else { this->var.var_ptr = nullptr; } } void CTimer::clear(CTimer *timer) { if (timer != nullptr) { delete timer; } } bool CTimer::start(uint32_t msec, std::function<void(apptimer_var_t)> callback) { if (pthread == nullptr) { try { pthread = new std::thread(_do_task_func, msec, this, callback); pthread->detach(); } catch (std::exception &ex) { DEBUG("%s", ex.what()); return false; } // this->callbackThread = std::thread(_do_task_func, msec, this, callback); // this->callbackThread.detach(); } return true; } void CTimer::stop() { std::unique_lock<std::mutex> lk(this->cv_mtx); this->flag = 1; this->cv.notify_one(); } void AppTimer_init(void) { TimerList.clear(); } void AppTimer_add(void(*cb)(apptimer_var_t), uint32_t msec) { CTimer *cTimer = new CTimer(); cTimer->copy(0, 0, nullptr, 0); std::lock_guard<std::mutex> lock(mtx); TimerList.insert(std::pair<void (*)(apptimer_var_t), CTimer *>(cb, cTimer)); if (cTimer->start(msec, cb) == false) { auto it = TimerList.find(cb); if (it != TimerList.end()) { CTimer *ptr = it->second; TimerList.erase(it); } delete cTimer; } } void AppTimer_add(void(*cb)(apptimer_var_t), uint32_t msec, int value1, int value2) { CTimer *cTimer = new CTimer(); cTimer->copy(value1, value2, nullptr, 0); std::lock_guard<std::mutex> lock(mtx); TimerList.insert(std::pair<void (*)(apptimer_var_t), CTimer *>(cb, cTimer)); if (cTimer->start(msec, cb) == false) { auto it = TimerList.find(cb); if (it != TimerList.end()) { CTimer *ptr = it->second; TimerList.erase(it); } delete cTimer; } } void AppTimer_add(void(*cb)(apptimer_var_t), uint32_t msec, void *data, int lenght) { CTimer *cTimer = new CTimer(); cTimer->copy(0, 0, data, lenght); std::lock_guard<std::mutex> lock(mtx); TimerList.insert(std::pair<void (*)(apptimer_var_t), CTimer *>(cb, cTimer)); if (cTimer->start(msec, cb) == false) { auto it = TimerList.find(cb); if (it != TimerList.end()) { CTimer *ptr = it->second; TimerList.erase(it); } delete cTimer; } } void AppTimer_delete(void(*cb)(apptimer_var_t)) { std::lock_guard<std::mutex> lock(mtx); auto it = TimerList.find(cb); if (it != TimerList.end()) { CTimer *ptr = it->second; TimerList.erase(it); ptr->stop(); } } static void RemoveTimerList(const CTimer *p) { std::lock_guard<std::mutex> lock(mtx); for (auto it = TimerList.begin(); it != TimerList.end(); ++it) { CTimer *ptr = it->second; if (ptr == p) { TimerList.erase(it); break; } } } uint32_t AppTimer_GetTickCount(void) { std::chrono::milliseconds as = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()); return as.count(); } uint64_t AppTimer_GetGmtTickCount(void) { std::chrono::milliseconds as = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()); return as.count(); } std::string FormatTime(const char *fmt) { auto now = std::chrono::system_clock::now(); auto timet = std::chrono::system_clock::to_time_t(now); auto localTime = *std::localtime(&timet); std::stringstream ss; std::string str; ss << std::put_time(&localTime, "%Y-%m-%d %H:%M:%S"); str = ss.str(); return str; } std::time_t MktimeString(const char *str, const char *fmt) { struct std::tm dt; std::istringstream ss(str); ss >> std::get_time(&dt, fmt); std::stringstream out; out << std::put_time(&dt, "%Y-%m-%d %H:%M:%S"); // DEBUG("%s, %ld", out.str().c_str(), std::mktime(&dt)); time_t utc = std::mktime(&dt); return utc; } time_t TimeStamp(int year, int mon, int day, int hour, int min, int sec) { // YYHHDDhhmmss(GMT+8) struct tm test_tm; struct timeval tv; struct timezone tz; gettimeofday(&tv,&tz); memset(&test_tm, 0, sizeof(test_tm)); test_tm.tm_year = year - 1900; test_tm.tm_mon = mon - 1; test_tm.tm_mday = day; test_tm.tm_hour = hour; test_tm.tm_min = min; test_tm.tm_sec = sec; return mktime(&test_tm) - tz.tz_minuteswest*60; } usbcameralib/src/main/cpp/apptimer.h
New file @@ -0,0 +1,69 @@ // // Created by YY on 2021/3/16. // #ifndef NDKADV_APPTIMER_H #define NDKADV_APPTIMER_H #include <cstdint> #include <functional> #include <thread> #include <chrono> #include <atomic> #include <mutex> #include <condition_variable> #include <string> #include <ctime> #define D_SEC(n) ((n)*1000UL) #define D_MIN(n) ((n)*1000UL*60UL) #define D_HOUR(n) ((n)*1000UL*60UL*60UL) typedef struct { int var1; int var2; void * var_ptr; int var_length; } apptimer_var_t; class CTimer { public: CTimer(); virtual ~CTimer(); static bool _updateStatus(CTimer *timer); static void _do_task_func(uint32_t msec, CTimer *timer, std::function<void(apptimer_var_t)> callback); bool start(uint32_t msec, std::function<void(apptimer_var_t)> callback); void stop(); void copy(int value1, int value2, const void *data, int length); static void clear(CTimer *timer); private: std::mutex cv_mtx; std::condition_variable cv; // std::thread callbackThread; std::thread *pthread; apptimer_var_t var; public: std::atomic_int flag; }; void AppTimer_init(void); void AppTimer_add(void(*cb)(apptimer_var_t), uint32_t msec); void AppTimer_add(void(*cb)(apptimer_var_t), uint32_t msec, int value1, int value2); void AppTimer_add(void(*cb)(apptimer_var_t), uint32_t msec, void *data, int lenght); void AppTimer_delete(void (*cb) (apptimer_var_t)); uint32_t AppTimer_GetTickCount(void); uint64_t AppTimer_GetGmtTickCount(void); std::string FormatTime(const char *fmt = "%Y-%m-%d %H:%M:%S"); std::time_t MktimeString(const char *str, const char *fmt); time_t TimeStamp(int year, int mon, int day, int hour, int min, int sec); #endif //NDKADV_APPTIMER_H usbcameralib/src/main/cpp/charencode.cpp
New file @@ -0,0 +1,204 @@ // // Created by YY on 2021/10/22. // #include <stdlib.h> #include "charencode.h" /***************************************************************************** * 将一个字符的Unicode(UCS-2和UCS-4)编码转换成UTF-8编码. * * 参数: * unic 字符的Unicode编码值 * pOutput 指向输出的用于存储UTF8编码值的缓冲区的指针 * outsize pOutput缓冲的大小 * * 返回值: * 返回转换后的字符的UTF8编码所占的字节数, 如果出错则返回 0 . * * 注意: * 1. UTF8没有字节序问题, 但是Unicode有字节序要求; * 字节序分为大端(Big Endian)和小端(Little Endian)两种; * 在Intel处理器中采用小端法表示, 在此采用小端法表示. (低地址存低位) * 2. 请保证 pOutput 缓冲区有最少有 6 字节的空间大小! ****************************************************************************/ int enc_unicode_to_utf8_one(unsigned long unic, unsigned char *pOutput, int outSize) { if (pOutput == NULL || outSize < 6) return 0; if (unic <= 0x0000007F) { // * U-00000000 - U-0000007F: 0xxxxxxx *pOutput = (unic & 0x7F); return 1; } else if (unic >= 0x00000080 && unic <= 0x000007FF) { // * U-00000080 - U-000007FF: 110xxxxx 10xxxxxx *(pOutput + 1) = (unic & 0x3F) | 0x80; *pOutput = ((unic >> 6) & 0x1F) | 0xC0; return 2; } else if (unic >= 0x00000800 && unic <= 0x0000FFFF) { // * U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx *(pOutput + 2) = (unic & 0x3F) | 0x80; *(pOutput + 1) = ((unic >> 6) & 0x3F) | 0x80; *pOutput = ((unic >> 12) & 0x0F) | 0xE0; return 3; } else if (unic >= 0x00010000 && unic <= 0x001FFFFF) { // * U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx *(pOutput + 3) = (unic & 0x3F) | 0x80; *(pOutput + 2) = ((unic >> 6) & 0x3F) | 0x80; *(pOutput + 1) = ((unic >> 12) & 0x3F) | 0x80; *pOutput = ((unic >> 18) & 0x07) | 0xF0; return 4; } else if (unic >= 0x00200000 && unic <= 0x03FFFFFF) { // * U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx *(pOutput + 4) = (unic & 0x3F) | 0x80; *(pOutput + 3) = ((unic >> 6) & 0x3F) | 0x80; *(pOutput + 2) = ((unic >> 12) & 0x3F) | 0x80; *(pOutput + 1) = ((unic >> 18) & 0x3F) | 0x80; *pOutput = ((unic >> 24) & 0x03) | 0xF8; return 5; } else if (unic >= 0x04000000 && unic <= 0x7FFFFFFF) { // * U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx *(pOutput + 5) = (unic & 0x3F) | 0x80; *(pOutput + 4) = ((unic >> 6) & 0x3F) | 0x80; *(pOutput + 3) = ((unic >> 12) & 0x3F) | 0x80; *(pOutput + 2) = ((unic >> 18) & 0x3F) | 0x80; *(pOutput + 1) = ((unic >> 24) & 0x3F) | 0x80; *pOutput = ((unic >> 30) & 0x01) | 0xFC; return 6; } return 0; } /***************************************************************************** * 将一个字符的UTF8编码转换成Unicode(UCS-2和UCS-4)编码. * * 参数: * pInput 指向输入缓冲区, 以UTF-8编码 * Unic 指向输出缓冲区, 其保存的数据即是Unicode编码值, * 类型为unsigned long . * * 返回值: * 成功则返回该字符的UTF8编码所占用的字节数; 失败则返回0. * * 注意: * 1. UTF8没有字节序问题, 但是Unicode有字节序要求; * 字节序分为大端(Big Endian)和小端(Little Endian)两种; * 在Intel处理器中采用小端法表示, 在此采用小端法表示. (低地址存低位) ****************************************************************************/ int enc_utf8_to_unicode_one(const unsigned char* pInput, unsigned long *Unic) { if (pInput == NULL || Unic == NULL) return 0; // b1 表示UTF-8编码的pInput中的高字节, b2 表示次高字节, ... char b1, b2, b3, b4, b5, b6; *Unic = 0x0; // 把 *Unic 初始化为全零 int utfbytes = enc_get_utf8_size(*pInput); unsigned char *pOutput = (unsigned char *)Unic; switch (utfbytes) { case 0: *pOutput = *pInput; utfbytes += 1; break; case 2: b1 = *pInput; b2 = *(pInput + 1); if ((b2 & 0xE0) != 0x80) return 0; *pOutput = (b1 << 6) + (b2 & 0x3F); *(pOutput + 1) = (b1 >> 2) & 0x07; break; case 3: b1 = *pInput; b2 = *(pInput + 1); b3 = *(pInput + 2); if (((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80)) return 0; *pOutput = (b2 << 6) + (b3 & 0x3F); *(pOutput + 1) = (b1 << 4) + ((b2 >> 2) & 0x0F); break; case 4: b1 = *pInput; b2 = *(pInput + 1); b3 = *(pInput + 2); b4 = *(pInput + 3); if (((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80) || ((b4 & 0xC0) != 0x80)) return 0; *pOutput = (b3 << 6) + (b4 & 0x3F); *(pOutput + 1) = (b2 << 4) + ((b3 >> 2) & 0x0F); *(pOutput + 2) = ((b1 << 2) & 0x1C) + ((b2 >> 4) & 0x03); break; case 5: b1 = *pInput; b2 = *(pInput + 1); b3 = *(pInput + 2); b4 = *(pInput + 3); b5 = *(pInput + 4); if (((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80) || ((b4 & 0xC0) != 0x80) || ((b5 & 0xC0) != 0x80)) return 0; *pOutput = (b4 << 6) + (b5 & 0x3F); *(pOutput + 1) = (b3 << 4) + ((b4 >> 2) & 0x0F); *(pOutput + 2) = (b2 << 2) + ((b3 >> 4) & 0x03); *(pOutput + 3) = (b1 << 6); break; case 6: b1 = *pInput; b2 = *(pInput + 1); b3 = *(pInput + 2); b4 = *(pInput + 3); b5 = *(pInput + 4); b6 = *(pInput + 5); if (((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80) || ((b4 & 0xC0) != 0x80) || ((b5 & 0xC0) != 0x80) || ((b6 & 0xC0) != 0x80)) return 0; *pOutput = (b5 << 6) + (b6 & 0x3F); *(pOutput + 1) = (b5 << 4) + ((b6 >> 2) & 0x0F); *(pOutput + 2) = (b3 << 2) + ((b4 >> 4) & 0x03); *(pOutput + 3) = ((b1 << 6) & 0x40) + (b2 & 0x3F); break; default: return 0; break; } return utfbytes; } int enc_get_utf8_size(const unsigned char pInput) { unsigned char c = pInput; // 0xxxxxxx 返回0 // 10xxxxxx 不存在 // 110xxxxx 返回2 // 1110xxxx 返回3 // 11110xxx 返回4 // 111110xx 返回5 // 1111110x 返回6 if(c< 0x80) return 0; if(c>=0x80 && c<0xC0) return -1; if(c>=0xC0 && c<0xE0) return 2; if(c>=0xE0 && c<0xF0) return 3; if(c>=0xF0 && c<0xF8) return 4; if(c>=0xF8 && c<0xFC) return 5; if(c>=0xFC) return 6; } usbcameralib/src/main/cpp/watermark.cpp
File was renamed from usbcameralib/src/main/cpp/watermark.c @@ -12,6 +12,7 @@ #include "watermark.h" #include "charencode.h" #include "ImageProc.h" #include "apptimer.h" //static pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; typedef enum { @@ -33,6 +34,22 @@ static int pic_width = 0, pic_height = 0; static color_t wm_color; static void PrintTime(apptimer_var_t val) { text_t text; text.x = 10; text.y = 10; memset(text.text, 0, sizeof (text.text)); strcpy(text.text, FormatTime().c_str()); PrepareWatermark(RED, 24, 2, 1, &text); AppTimer_add(PrintTime, D_SEC(1)); } void InitWatermark(const char *font, int width, int height) { LOGI("InitWatermark"); @@ -48,6 +65,8 @@ pic_width = width; pic_height = height; AppTimer_add(PrintTime, D_SEC(1)); } void UninitWatermark(void) @@ -58,6 +77,7 @@ wm = NULL; } wm_num = 0; AppTimer_delete(PrintTime); } void PrepareWatermark(int color, int font_size, int multiple, int num, const text_t *texts) @@ -75,7 +95,7 @@ const int bytes_per_line = font_size / 8; wm_num = 0; wm_color = color; wm_color = static_cast<color_t>(color); //FILE *fp = fopen("/storage/self/primary/ms_unicode.bin", "rb"); //FILE *fp = fopen("/system/ms_unicode.bin", "rb"); @@ -86,14 +106,14 @@ uint8_t zm[64*64/8]; // 最大 for (int m = 0; m < num; ++m) { char *str = texts[m].text; const char *str = texts[m].text; int screen_x = texts[m].x; int screen_y = texts[m].y; offset = 0; while (str != NULL && offset < strlen(str)) { int skip = enc_utf8_to_unicode_one(str + offset, &unicode); int skip = enc_utf8_to_unicode_one(reinterpret_cast<const unsigned char *>(str + offset), &unicode); int next_x = 0; if (skip == 0) { usbcameralib/src/main/cpp/watermark.h
@@ -5,6 +5,10 @@ #ifndef FLOATWINDOWVEDIO_WATERMARK_H #define FLOATWINDOWVEDIO_WATERMARK_H #ifdef __cplusplus extern "C" { #endif typedef struct { int x; int y; @@ -19,4 +23,8 @@ void AddWatermark(uint8_t *mem); #ifdef __cplusplus } #endif #endif //FLOATWINDOWVEDIO_WATERMARK_H