diff --git a/CMakeLists.txt b/CMakeLists.txt index d56c205..5a6f0b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,10 +53,7 @@ endif() include(cmake/FetchTesseract.cmake) target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE Tesseract) -target_sources(${CMAKE_PROJECT_NAME} PRIVATE src/plugin-main.c - src/obs-utils.cpp - src/tesseract-ocr-utils.cpp - src/ocr-filter.cpp - ) +target_sources(${CMAKE_PROJECT_NAME} PRIVATE src/plugin-main.c src/obs-utils.cpp src/tesseract-ocr-utils.cpp + src/ocr-filter.cpp) set_target_properties_plugin(${CMAKE_PROJECT_NAME} PROPERTIES OUTPUT_NAME ${_name}) diff --git a/cmake/FetchOpenCV.cmake b/cmake/FetchOpenCV.cmake index 2e05690..7aaf42a 100644 --- a/cmake/FetchOpenCV.cmake +++ b/cmake/FetchOpenCV.cmake @@ -13,7 +13,8 @@ if(CUSTOM_OPENCV_URL STREQUAL "") else() message(STATUS "Using custom OpenCV: ${CUSTOM_OPENCV_URL}") if(CUSTOM_OPENCV_HASH STREQUAL "") - message(FATAL_ERROR "CUSTOM_OPENCV_HASH not found. Both of CUSTOM_OPENCV_URL and CUSTOM_OPENCV_HASH must be present!") + message( + FATAL_ERROR "CUSTOM_OPENCV_HASH not found. Both of CUSTOM_OPENCV_URL and CUSTOM_OPENCV_HASH must be present!") else() set(USE_PREDEFINED_OPENCV OFF) endif() @@ -74,8 +75,7 @@ if(MSVC) ${opencv_SOURCE_DIR}/x64/vc17/staticlib/zlib.lib) target_include_directories(OpenCV SYSTEM INTERFACE ${opencv_SOURCE_DIR}/include) else() - target_link_libraries( - OpenCV INTERFACE ${opencv_SOURCE_DIR}/lib/libopencv_imgproc.a - ${opencv_SOURCE_DIR}/lib/libopencv_core.a) + target_link_libraries(OpenCV INTERFACE ${opencv_SOURCE_DIR}/lib/libopencv_imgproc.a + ${opencv_SOURCE_DIR}/lib/libopencv_core.a) target_include_directories(OpenCV SYSTEM INTERFACE ${opencv_SOURCE_DIR}/include/opencv4) endif() diff --git a/cmake/FetchTesseract.cmake b/cmake/FetchTesseract.cmake index be64ba2..b8d7975 100644 --- a/cmake/FetchTesseract.cmake +++ b/cmake/FetchTesseract.cmake @@ -13,7 +13,9 @@ if(CUSTOM_TESSERACT_URL STREQUAL "") else() message(STATUS "Using custom Tesseract: ${CUSTOM_TESSERACT_URL}") if(CUSTOM_TESSERACT_HASH STREQUAL "") - message(FATAL_ERROR "CUSTOM_TESSERACT_HASH not found. Both of CUSTOM_TESSERACT_URL and CUSTOM_TESSERACT_HASH must be present!") + message( + FATAL_ERROR + "CUSTOM_TESSERACT_HASH not found. Both of CUSTOM_TESSERACT_URL and CUSTOM_TESSERACT_HASH must be present!") else() set(USE_PREDEFINED_TESSERACT OFF) endif() @@ -67,14 +69,15 @@ FetchContent_MakeAvailable(tesseract) add_library(Tesseract INTERFACE) if(MSVC) - target_link_libraries( - Tesseract - INTERFACE ${tesseract_SOURCE_DIR}/x64/vc17/staticlib/tesseract.lib) + target_link_libraries(Tesseract INTERFACE ${tesseract_SOURCE_DIR}/lib/tesseract53.lib + ${tesseract_SOURCE_DIR}/lib/leptonica-1.84.1.lib) + target_include_directories(Tesseract SYSTEM INTERFACE ${tesseract_SOURCE_DIR}/include) +elseif(APPLE) + target_link_libraries(Tesseract INTERFACE ${tesseract_SOURCE_DIR}/lib/libtesseract.a + ${tesseract_SOURCE_DIR}/lib/libleptonica.a) target_include_directories(Tesseract SYSTEM INTERFACE ${tesseract_SOURCE_DIR}/include) else() - target_link_libraries( - Tesseract INTERFACE ${tesseract_SOURCE_DIR}/lib/libtesseract.a - ${tesseract_SOURCE_DIR}/lib/libleptonica.a - ) + target_link_libraries(Tesseract INTERFACE ${tesseract_SOURCE_DIR}/lib/libtesseract.a + ${tesseract_SOURCE_DIR}/lib/lib/libleptonica.a) target_include_directories(Tesseract SYSTEM INTERFACE ${tesseract_SOURCE_DIR}/include) endif() diff --git a/src/filter-data.h b/src/filter-data.h index f17a322..7c2b8c3 100644 --- a/src/filter-data.h +++ b/src/filter-data.h @@ -36,15 +36,7 @@ struct filter_data { char *output_source_name = nullptr; std::mutex *output_source_mutex = nullptr; -#if _WIN32 - const wchar_t *modelFilepath = nullptr; - const wchar_t *tesseractTraineddataFilepath = nullptr; - const wchar_t *vocabularyFilepath = nullptr; -#else - const char *modelFilepath = nullptr; - const char *tesseractTraineddataFilepath = nullptr; - const char *vocabularyFilepath = nullptr; -#endif + char *tesseractTraineddataFilepath = nullptr; }; #endif /* FILTERDATA_H */ diff --git a/src/obs-utils.cpp b/src/obs-utils.cpp index 5a3d11e..f9b99a1 100644 --- a/src/obs-utils.cpp +++ b/src/obs-utils.cpp @@ -98,11 +98,13 @@ void acquire_weak_output_source_ref(struct filter_data *usd) usd->output_source = obs_source_get_weak_source(source); obs_source_release(source); if (!usd->output_source) { - obs_log(LOG_ERROR, "failed to get weak source for text source %s", + obs_log(LOG_ERROR, + "failed to get weak source for text source %s", usd->output_source_name); } } else { - obs_log(LOG_ERROR, "text source '%s' not found", usd->output_source_name); + obs_log(LOG_ERROR, "text source '%s' not found", + usd->output_source_name); } } @@ -153,16 +155,19 @@ bool add_sources_to_list(void *list_property, obs_source_t *source) return true; } -void update_text_source_on_settings(struct filter_data *usd, obs_data_t *settings) +void update_text_source_on_settings(struct filter_data *usd, + obs_data_t *settings) { // update the text source - const char *new_text_source_name = obs_data_get_string(settings, "text_sources"); + const char *new_text_source_name = + obs_data_get_string(settings, "text_sources"); obs_weak_source_t *old_weak_text_source = NULL; if (!is_valid_output_source_name(new_text_source_name)) { // new selected text source is not valid, release the old one if (usd->output_source) { - std::lock_guard lock(*usd->output_source_mutex); + std::lock_guard lock( + *usd->output_source_mutex); old_weak_text_source = usd->output_source; usd->output_source = nullptr; } @@ -173,10 +178,12 @@ void update_text_source_on_settings(struct filter_data *usd, obs_data_t *setting } else { // new selected text source is valid, check if it's different from the old one if (usd->output_source_name == nullptr || - strcmp(new_text_source_name, usd->output_source_name) != 0) { + strcmp(new_text_source_name, usd->output_source_name) != + 0) { // new text source is different from the old one, release the old one if (usd->output_source) { - std::lock_guard lock(*usd->output_source_mutex); + std::lock_guard lock( + *usd->output_source_mutex); old_weak_text_source = usd->output_source; usd->output_source = nullptr; } @@ -188,4 +195,3 @@ void update_text_source_on_settings(struct filter_data *usd, obs_data_t *setting obs_weak_source_release(old_weak_text_source); } } - diff --git a/src/obs-utils.h b/src/obs-utils.h index a04924b..1279c8a 100644 --- a/src/obs-utils.h +++ b/src/obs-utils.h @@ -8,8 +8,10 @@ bool getRGBAFromStageSurface(filter_data *tf, uint32_t &width, inline bool is_valid_output_source_name(const char *output_source_name) { - return output_source_name != nullptr && strcmp(output_source_name, "none") != 0 && - strcmp(output_source_name, "(null)") != 0 && strcmp(output_source_name, "") != 0; + return output_source_name != nullptr && + strcmp(output_source_name, "none") != 0 && + strcmp(output_source_name, "(null)") != 0 && + strcmp(output_source_name, "") != 0; } void acquire_weak_output_source_ref(struct filter_data *usd); @@ -18,7 +20,7 @@ void setTextCallback(const std::string &str, struct filter_data *usd); bool add_sources_to_list(void *list_property, obs_source_t *source); -void update_text_source_on_settings(struct filter_data *usd, obs_data_t *settings); - +void update_text_source_on_settings(struct filter_data *usd, + obs_data_t *settings); #endif /* OBS_UTILS_H */ diff --git a/src/ocr-filter.cpp b/src/ocr-filter.cpp index 3c0a8fe..d2ccb34 100644 --- a/src/ocr-filter.cpp +++ b/src/ocr-filter.cpp @@ -1,6 +1,3 @@ -#ifdef _WIN32 -#include -#endif // _WIN32 #include @@ -13,6 +10,8 @@ #include +#include + #include #include "filter-data.h" #include "obs-utils.h" @@ -68,9 +67,9 @@ obs_properties_t *ocr_filter_properties(void *data) "scoreboard"); // Add a property for the output text source - obs_property_t *sources = obs_properties_add_list(props, "text_sources", - "Output text source", OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_STRING); + obs_property_t *sources = obs_properties_add_list( + props, "text_sources", "Output text source", + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); // Add a "none" option obs_property_list_add_string(sources, "No output", "none"); // Add the sources @@ -135,21 +134,14 @@ void *ocr_filter_create(obs_data_t *settings, obs_source_t *source) tf->source = source; tf->texrender = gs_texrender_create(GS_BGRA, GS_ZS_NONE); - tf->output_source_name = bstrdup(obs_data_get_string(settings, "text_sources")); + tf->output_source_name = + bstrdup(obs_data_get_string(settings, "text_sources")); tf->output_source = nullptr; // initialize the mutex tf->output_source_mutex = new std::mutex(); - // get the model file path from the module -#if _WIN32 - tf->modelFilepath = obs_module_file("crnn_cs.onnx"); + // get the models folder path from the module tf->tesseractTraineddataFilepath = obs_module_file("tessdata"); - tf->vocabularyFilepath = obs_module_file("alphabet_36.txt"); -#else - tf->modelFilepath = obs_module_file("crnn_cs.onnx"); - tf->tesseractTraineddataFilepath = obs_module_file("tessdata"); - tf->vocabularyFilepath = obs_module_file("alphabet_94.txt"); -#endif tf->tesseract_model = nullptr; @@ -170,6 +162,9 @@ void ocr_filter_destroy(void *data) } obs_leave_graphics(); + if (tf->tesseractTraineddataFilepath != nullptr) { + bfree(tf->tesseractTraineddataFilepath); + } if (tf->tesseract_model != nullptr) { tf->tesseract_model->End(); delete tf->tesseract_model; diff --git a/src/plugin-support.c.in b/src/plugin-support.c.in index 6aef276..98bb4a1 100644 --- a/src/plugin-support.c.in +++ b/src/plugin-support.c.in @@ -18,6 +18,8 @@ with this program. If not, see #include +extern void blogva(int log_level, const char *format, va_list args); + const char *PLUGIN_NAME = "@CMAKE_PROJECT_NAME@"; const char *PLUGIN_VERSION = "@CMAKE_PROJECT_VERSION@"; diff --git a/src/plugin-support.h b/src/plugin-support.h index 2164389..7f88b70 100644 --- a/src/plugin-support.h +++ b/src/plugin-support.h @@ -31,7 +31,6 @@ extern const char *PLUGIN_NAME; extern const char *PLUGIN_VERSION; void obs_log(int log_level, const char *format, ...); -extern void blogva(int log_level, const char *format, va_list args); #ifdef __cplusplus }