Dana
2025-12-01 dd7c75d0d989835c1437e0cfa071408a23d993cd
1.usb添加水印
1 文件已重命名
4个文件已修改
3个文件已添加
589 ■■■■■ 已修改文件
usbcameralib/CMakeLists.txt 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
usbcameralib/build.gradle 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
usbcameralib/src/main/cpp/ImageProc.c 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
usbcameralib/src/main/cpp/apptimer.cpp 262 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
usbcameralib/src/main/cpp/apptimer.h 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
usbcameralib/src/main/cpp/charencode.cpp 204 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
usbcameralib/src/main/cpp/watermark.cpp 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
usbcameralib/src/main/cpp/watermark.h 8 ●●●●● 补丁 | 查看 | 原始文档 | 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