diff --git a/CMakeLists.txt b/CMakeLists.txt index 24d3e19d..0809c04d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,14 +92,18 @@ ENDIF(WIN32) set(QT_HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include/Qt) FILE(GLOB QT_HEADER_FILES "${QT_HEADER_DIR}/*.h") -############## PROCESS SUB-DIRECTORIES ############## +############## PROCESS src/ DIRECTORIES ############## add_subdirectory(src) -add_subdirectory(tests) ################### DOCUMENTATION ################### # Find Doxygen (used for documentation) include(cmake/Modules/UseDoxygen.cmake) +# Doxygen was found +if (TARGET doc) + message(STATUS "Doxygen found, documentation target enabled") + message("\nTo compile documentation in doc/html, run: 'make doc'") + # Install docs, if the user builds them with `make doc` install(CODE "MESSAGE(\"Checking for documentation files to install...\")") install(CODE "MESSAGE(\"(Compile with 'make doc' command, requires Doxygen)\")") @@ -108,3 +112,8 @@ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/html/ DESTINATION ${CMAKE_INSTALL_DOCDIR}/API MESSAGE_NEVER # Don't spew about file copies OPTIONAL ) # No error if the docs aren't found +endif() + +############# PROCESS tests/ DIRECTORY ############## +add_subdirectory(tests) + diff --git a/cmake/Modules/FindPythonLibs.cmake b/cmake/Modules/FindPythonLibs.cmake deleted file mode 100644 index e2ca1c79..00000000 --- a/cmake/Modules/FindPythonLibs.cmake +++ /dev/null @@ -1,294 +0,0 @@ -#.rst: -# FindPythonLibs -# -------------- -# -# Find python libraries -# -# This module finds if Python is installed and determines where the -# include files and libraries are. It also determines what the name of -# the library is. This code sets the following variables: -# -# :: -# -# PYTHONLIBS_FOUND - have the Python libs been found -# PYTHON_LIBRARIES - path to the python library -# PYTHON_INCLUDE_PATH - path to where Python.h is found (deprecated) -# PYTHON_INCLUDE_DIRS - path to where Python.h is found -# PYTHON_DEBUG_LIBRARIES - path to the debug library (deprecated) -# PYTHONLIBS_VERSION_STRING - version of the Python libs found (since CMake 2.8.8) -# -# -# -# The Python_ADDITIONAL_VERSIONS variable can be used to specify a list -# of version numbers that should be taken into account when searching -# for Python. You need to set this variable before calling -# find_package(PythonLibs). -# -# If you'd like to specify the installation of Python to use, you should -# modify the following cache variables: -# -# :: -# -# PYTHON_LIBRARY - path to the python library -# PYTHON_INCLUDE_DIR - path to where Python.h is found -# -# If also calling find_package(PythonInterp), call find_package(PythonInterp) -# first to get the currently active Python version by default with a consistent -# version of PYTHON_LIBRARIES. - -#============================================================================= -# Copyright 2001-2009 Kitware, Inc. -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= -# (To distribute this file outside of CMake, substitute the full -# License text for the above reference.) - -include(CMakeFindFrameworks) -# Search for the python framework on Apple. -CMAKE_FIND_FRAMEWORKS(Python) - -set(_PYTHON1_VERSIONS 1.6 1.5) -set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0) -set(_PYTHON3_VERSIONS 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) - -if(PythonLibs_FIND_VERSION) - if(PythonLibs_FIND_VERSION_COUNT GREATER 1) - set(_PYTHON_FIND_MAJ_MIN "${PythonLibs_FIND_VERSION_MAJOR}.${PythonLibs_FIND_VERSION_MINOR}") - unset(_PYTHON_FIND_OTHER_VERSIONS) - if(PythonLibs_FIND_VERSION_EXACT) - if(_PYTHON_FIND_MAJ_MIN STREQUAL PythonLibs_FIND_VERSION) - set(_PYTHON_FIND_OTHER_VERSIONS "${PythonLibs_FIND_VERSION}") - else() - set(_PYTHON_FIND_OTHER_VERSIONS "${PythonLibs_FIND_VERSION}" "${_PYTHON_FIND_MAJ_MIN}") - endif() - else() - foreach(_PYTHON_V ${_PYTHON${PythonLibs_FIND_VERSION_MAJOR}_VERSIONS}) - if(NOT _PYTHON_V VERSION_LESS _PYTHON_FIND_MAJ_MIN) - list(APPEND _PYTHON_FIND_OTHER_VERSIONS ${_PYTHON_V}) - endif() - endforeach() - endif() - unset(_PYTHON_FIND_MAJ_MIN) - else() - set(_PYTHON_FIND_OTHER_VERSIONS ${_PYTHON${PythonLibs_FIND_VERSION_MAJOR}_VERSIONS}) - endif() -else() - set(_PYTHON_FIND_OTHER_VERSIONS ${_PYTHON3_VERSIONS} ${_PYTHON2_VERSIONS} ${_PYTHON1_VERSIONS}) -endif() - -# Set up the versions we know about, in the order we will search. Always add -# the user supplied additional versions to the front. -# If FindPythonInterp has already found the major and minor version, -# insert that version between the user supplied versions and the stock -# version list. -set(_Python_VERSIONS ${Python_ADDITIONAL_VERSIONS}) -if(DEFINED PYTHON_VERSION_MAJOR AND DEFINED PYTHON_VERSION_MINOR) - list(APPEND _Python_VERSIONS ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}) -endif() -list(APPEND _Python_VERSIONS ${_PYTHON_FIND_OTHER_VERSIONS}) - -unset(_PYTHON_FIND_OTHER_VERSIONS) -unset(_PYTHON1_VERSIONS) -unset(_PYTHON2_VERSIONS) -unset(_PYTHON3_VERSIONS) - -foreach(_CURRENT_VERSION ${_Python_VERSIONS}) - string(REPLACE "." "" _CURRENT_VERSION_NO_DOTS ${_CURRENT_VERSION}) - if(WIN32) - find_library(PYTHON_DEBUG_LIBRARY - NAMES python${_CURRENT_VERSION_NO_DOTS}_d python - PATHS - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs/Debug - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs/Debug - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs - ) - endif() - - find_library(PYTHON_LIBRARY - NAMES - python${_CURRENT_VERSION_NO_DOTS} - python${_CURRENT_VERSION}mu - python${_CURRENT_VERSION}m - python${_CURRENT_VERSION}u - python${_CURRENT_VERSION} - PATHS - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs - # Avoid finding the .dll in the PATH. We want the .lib. - NO_SYSTEM_ENVIRONMENT_PATH - ) - # Look for the static library in the Python config directory - find_library(PYTHON_LIBRARY - NAMES python${_CURRENT_VERSION_NO_DOTS} python${_CURRENT_VERSION} - # Avoid finding the .dll in the PATH. We want the .lib. - NO_SYSTEM_ENVIRONMENT_PATH - # This is where the static library is usually located - PATH_SUFFIXES python${_CURRENT_VERSION}/config - ) - - # For backward compatibility, honour value of PYTHON_INCLUDE_PATH, if - # PYTHON_INCLUDE_DIR is not set. - if(DEFINED PYTHON_INCLUDE_PATH AND NOT DEFINED PYTHON_INCLUDE_DIR) - set(PYTHON_INCLUDE_DIR "${PYTHON_INCLUDE_PATH}" CACHE PATH - "Path to where Python.h is found" FORCE) - endif() - - set(PYTHON_FRAMEWORK_INCLUDES) - if(Python_FRAMEWORKS AND NOT PYTHON_INCLUDE_DIR) - foreach(dir ${Python_FRAMEWORKS}) - set(PYTHON_FRAMEWORK_INCLUDES ${PYTHON_FRAMEWORK_INCLUDES} - ${dir}/Versions/${_CURRENT_VERSION}/include/python${_CURRENT_VERSION}) - endforeach() - endif() - - find_path(PYTHON_INCLUDE_DIR - NAMES Python.h - PATHS - ${PYTHON_FRAMEWORK_INCLUDES} - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/include - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/include - PATH_SUFFIXES - python${_CURRENT_VERSION}mu - python${_CURRENT_VERSION}m - python${_CURRENT_VERSION}u - python${_CURRENT_VERSION} - ) - - # For backward compatibility, set PYTHON_INCLUDE_PATH. - set(PYTHON_INCLUDE_PATH "${PYTHON_INCLUDE_DIR}") - - if(PYTHON_INCLUDE_DIR AND EXISTS "${PYTHON_INCLUDE_DIR}/patchlevel.h") - file(STRINGS "${PYTHON_INCLUDE_DIR}/patchlevel.h" python_version_str - REGEX "^#define[ \t]+PY_VERSION[ \t]+\"[^\"]+\"") - string(REGEX REPLACE "^#define[ \t]+PY_VERSION[ \t]+\"([^\"]+)\".*" "\\1" - PYTHONLIBS_VERSION_STRING "${python_version_str}") - unset(python_version_str) - endif() - - if(PYTHON_LIBRARY AND PYTHON_INCLUDE_DIR) - break() - endif() -endforeach() - -mark_as_advanced( - PYTHON_DEBUG_LIBRARY - PYTHON_LIBRARY - PYTHON_INCLUDE_DIR -) - -# We use PYTHON_INCLUDE_DIR, PYTHON_LIBRARY and PYTHON_DEBUG_LIBRARY for the -# cache entries because they are meant to specify the location of a single -# library. We now set the variables listed by the documentation for this -# module. -set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}") -set(PYTHON_DEBUG_LIBRARIES "${PYTHON_DEBUG_LIBRARY}") - -# These variables have been historically named in this module different from -# what SELECT_LIBRARY_CONFIGURATIONS() expects. -set(PYTHON_LIBRARY_DEBUG "${PYTHON_DEBUG_LIBRARY}") -set(PYTHON_LIBRARY_RELEASE "${PYTHON_LIBRARY}") -include(SelectLibraryConfigurations) -SELECT_LIBRARY_CONFIGURATIONS(PYTHON) -# SELECT_LIBRARY_CONFIGURATIONS() sets ${PREFIX}_FOUND if it has a library. -# Unset this, this prefix doesn't match the module prefix, they are different -# for historical reasons. -unset(PYTHON_FOUND) - -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(PythonLibs - REQUIRED_VARS PYTHON_LIBRARIES PYTHON_INCLUDE_DIRS - VERSION_VAR PYTHONLIBS_VERSION_STRING) - -# PYTHON_ADD_MODULE( src1 src2 ... srcN) is used to build modules for python. -# PYTHON_WRITE_MODULES_HEADER() writes a header file you can include -# in your sources to initialize the static python modules -function(PYTHON_ADD_MODULE _NAME ) - get_property(_TARGET_SUPPORTS_SHARED_LIBS - GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS) - option(PYTHON_ENABLE_MODULE_${_NAME} "Add module ${_NAME}" TRUE) - option(PYTHON_MODULE_${_NAME}_BUILD_SHARED - "Add module ${_NAME} shared" ${_TARGET_SUPPORTS_SHARED_LIBS}) - - # Mark these options as advanced - mark_as_advanced(PYTHON_ENABLE_MODULE_${_NAME} - PYTHON_MODULE_${_NAME}_BUILD_SHARED) - - if(PYTHON_ENABLE_MODULE_${_NAME}) - if(PYTHON_MODULE_${_NAME}_BUILD_SHARED) - set(PY_MODULE_TYPE MODULE) - else() - set(PY_MODULE_TYPE STATIC) - set_property(GLOBAL APPEND PROPERTY PY_STATIC_MODULES_LIST ${_NAME}) - endif() - - set_property(GLOBAL APPEND PROPERTY PY_MODULES_LIST ${_NAME}) - add_library(${_NAME} ${PY_MODULE_TYPE} ${ARGN}) -# target_link_libraries(${_NAME} ${PYTHON_LIBRARIES}) - - if(PYTHON_MODULE_${_NAME}_BUILD_SHARED) - set_target_properties(${_NAME} PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}") - if(WIN32 AND NOT CYGWIN) - set_target_properties(${_NAME} PROPERTIES SUFFIX ".pyd") - endif() - endif() - - endif() -endfunction() - -function(PYTHON_WRITE_MODULES_HEADER _filename) - - get_property(PY_STATIC_MODULES_LIST GLOBAL PROPERTY PY_STATIC_MODULES_LIST) - - get_filename_component(_name "${_filename}" NAME) - string(REPLACE "." "_" _name "${_name}") - string(TOUPPER ${_name} _nameUpper) - set(_filename ${CMAKE_CURRENT_BINARY_DIR}/${_filename}) - - set(_filenameTmp "${_filename}.in") - file(WRITE ${_filenameTmp} "/*Created by cmake, do not edit, changes will be lost*/\n") - file(APPEND ${_filenameTmp} -"#ifndef ${_nameUpper} -#define ${_nameUpper} - -#include - -#ifdef __cplusplus -extern \"C\" { -#endif /* __cplusplus */ - -") - - foreach(_currentModule ${PY_STATIC_MODULES_LIST}) - file(APPEND ${_filenameTmp} "extern void init${PYTHON_MODULE_PREFIX}${_currentModule}(void);\n\n") - endforeach() - - file(APPEND ${_filenameTmp} -"#ifdef __cplusplus -} -#endif /* __cplusplus */ - -") - - - foreach(_currentModule ${PY_STATIC_MODULES_LIST}) - file(APPEND ${_filenameTmp} "int ${_name}_${_currentModule}(void) \n{\n static char name[]=\"${PYTHON_MODULE_PREFIX}${_currentModule}\"; return PyImport_AppendInittab(name, init${PYTHON_MODULE_PREFIX}${_currentModule});\n}\n\n") - endforeach() - - file(APPEND ${_filenameTmp} "void ${_name}_LoadAllPythonModules(void)\n{\n") - foreach(_currentModule ${PY_STATIC_MODULES_LIST}) - file(APPEND ${_filenameTmp} " ${_name}_${_currentModule}();\n") - endforeach() - file(APPEND ${_filenameTmp} "}\n\n") - file(APPEND ${_filenameTmp} "#ifndef EXCLUDE_LOAD_ALL_FUNCTION\nvoid CMakeLoadAllPythonModules(void)\n{\n ${_name}_LoadAllPythonModules();\n}\n#endif\n\n#endif\n") - -# with configure_file() cmake complains that you may not use a file created using file(WRITE) as input file for configure_file() - execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_filenameTmp}" "${_filename}" OUTPUT_QUIET ERROR_QUIET) - -endfunction() diff --git a/include/Exceptions.h b/include/Exceptions.h index c5228f13..28942050 100644 --- a/include/Exceptions.h +++ b/include/Exceptions.h @@ -61,6 +61,14 @@ namespace openshot { int64_t frame_number; int64_t chunk_number; int64_t chunk_frame; + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param frame_number The frame number being processed + * @param chunk_number The chunk requested + * @param chunk_frame The chunk frame + */ ChunkNotFound(std::string message, int64_t frame_number, int64_t chunk_number, int64_t chunk_frame) : BaseException(message), frame_number(frame_number), chunk_number(chunk_number), chunk_frame(chunk_frame) { } virtual ~ChunkNotFound() noexcept {} @@ -71,6 +79,11 @@ namespace openshot { class DecklinkError : public BaseException { public: + /** + * @brief Constructor + * + * @param message A message to accompany the exception + */ DecklinkError(std::string message) : BaseException(message) { } virtual ~DecklinkError() noexcept {} @@ -81,6 +94,12 @@ namespace openshot { { public: int64_t frame_number; + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param frame_number The frame number being processed + */ ErrorDecodingAudio(std::string message, int64_t frame_number) : BaseException(message), frame_number(frame_number) { } virtual ~ErrorDecodingAudio() noexcept {} @@ -91,6 +110,12 @@ namespace openshot { { public: int64_t frame_number; + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param frame_number The frame number being processed + */ ErrorEncodingAudio(std::string message, int64_t frame_number) : BaseException(message), frame_number(frame_number) { } virtual ~ErrorEncodingAudio() noexcept {} @@ -101,6 +126,12 @@ namespace openshot { { public: int64_t frame_number; + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param frame_number The frame number being processed + */ ErrorEncodingVideo(std::string message, int64_t frame_number) : BaseException(message), frame_number(frame_number) { } virtual ~ErrorEncodingVideo() noexcept {} @@ -111,7 +142,13 @@ namespace openshot { { public: std::string file_path; - InvalidChannels(std::string message, std::string file_path) + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param file_path (optional) The input file being processed + */ + InvalidChannels(std::string message, std::string file_path="") : BaseException(message), file_path(file_path) { } virtual ~InvalidChannels() noexcept {} }; @@ -121,7 +158,13 @@ namespace openshot { { public: std::string file_path; - InvalidCodec(std::string message, std::string file_path) + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param file_path (optional) The input file being processed + */ + InvalidCodec(std::string message, std::string file_path="") : BaseException(message), file_path(file_path) { } virtual ~InvalidCodec() noexcept {} }; @@ -131,6 +174,12 @@ namespace openshot { { public: std::string file_path; + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param file_path The input file being processed + */ InvalidFile(std::string message, std::string file_path) : BaseException(message), file_path(file_path) { } virtual ~InvalidFile() noexcept {} @@ -141,7 +190,13 @@ namespace openshot { { public: std::string file_path; - InvalidFormat(std::string message, std::string file_path) + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param file_path (optional) The input file being processed + */ + InvalidFormat(std::string message, std::string file_path="") : BaseException(message), file_path(file_path) { } virtual ~InvalidFormat() noexcept {} }; @@ -151,7 +206,13 @@ namespace openshot { { public: std::string file_path; - InvalidJSON(std::string message, std::string file_path) + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param file_path (optional) The input file being processed + */ + InvalidJSON(std::string message, std::string file_path="") : BaseException(message), file_path(file_path) { } virtual ~InvalidJSON() noexcept {} }; @@ -161,7 +222,13 @@ namespace openshot { { public: std::string file_path; - InvalidOptions(std::string message, std::string file_path) + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param file_path (optional) The input file being processed + */ + InvalidOptions(std::string message, std::string file_path="") : BaseException(message), file_path(file_path) { } virtual ~InvalidOptions() noexcept {} }; @@ -171,7 +238,13 @@ namespace openshot { { public: std::string file_path; - InvalidSampleRate(std::string message, std::string file_path) + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param file_path (optional) The input file being processed + */ + InvalidSampleRate(std::string message, std::string file_path="") : BaseException(message), file_path(file_path) { } virtual ~InvalidSampleRate() noexcept {} }; @@ -181,6 +254,12 @@ namespace openshot { { public: std::string json; + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param json The json data being processed + */ InvalidJSONKey(std::string message, std::string json) : BaseException(message), json(json) { } virtual ~InvalidJSONKey() noexcept {} @@ -191,7 +270,13 @@ namespace openshot { { public: std::string file_path; - NoStreamsFound(std::string message, std::string file_path) + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param file_path (optional) The input file being processed + */ + NoStreamsFound(std::string message, std::string file_path="") : BaseException(message), file_path(file_path) { } virtual ~NoStreamsFound() noexcept {} }; @@ -202,6 +287,13 @@ namespace openshot { public: int64_t FrameRequested; int64_t MaxFrames; + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param frame_requested The out-of-bounds frame number requested + * @param max_frames The maximum available frame number + */ OutOfBoundsFrame(std::string message, int64_t frame_requested, int64_t max_frames) : BaseException(message), FrameRequested(frame_requested), MaxFrames(max_frames) { } virtual ~OutOfBoundsFrame() noexcept {} @@ -213,6 +305,13 @@ namespace openshot { public: int PointRequested; int MaxPoints; + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param point_requested The out-of-bounds point requested + * @param max_points The maximum available point value + */ OutOfBoundsPoint(std::string message, int point_requested, int max_points) : BaseException(message), PointRequested(point_requested), MaxPoints(max_points) { } virtual ~OutOfBoundsPoint() noexcept {} @@ -223,7 +322,13 @@ namespace openshot { { public: std::string file_path; - OutOfMemory(std::string message, std::string file_path) + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param file_path (optional) The input file being processed + */ + OutOfMemory(std::string message, std::string file_path="") : BaseException(message), file_path(file_path) { } virtual ~OutOfMemory() noexcept {} }; @@ -233,7 +338,13 @@ namespace openshot { { public: std::string file_path; - ReaderClosed(std::string message, std::string file_path) + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param file_path (optional) The input file being processed + */ + ReaderClosed(std::string message, std::string file_path="") : BaseException(message), file_path(file_path) { } virtual ~ReaderClosed() noexcept {} }; @@ -243,7 +354,13 @@ namespace openshot { { public: std::string file_path; - ResampleError(std::string message, std::string file_path) + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param file_path (optional) The input file being processed + */ + ResampleError(std::string message, std::string file_path="") : BaseException(message), file_path(file_path) { } virtual ~ResampleError() noexcept {} }; @@ -253,7 +370,13 @@ namespace openshot { { public: std::string file_path; - TooManySeeks(std::string message, std::string file_path) + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param file_path (optional) The input file being processed + */ + TooManySeeks(std::string message, std::string file_path="") : BaseException(message), file_path(file_path) { } virtual ~TooManySeeks() noexcept {} }; @@ -263,7 +386,13 @@ namespace openshot { { public: std::string file_path; - WriterClosed(std::string message, std::string file_path) + /** + * @brief Constructor + * + * @param message A message to accompany the exception + * @param file_path (optional) The output file being written + */ + WriterClosed(std::string message, std::string file_path="") : BaseException(message), file_path(file_path) { } virtual ~WriterClosed() noexcept {} }; diff --git a/include/OpenShotVersion.h.in b/include/OpenShotVersion.h.in index 89f4ed52..e15662b2 100644 --- a/include/OpenShotVersion.h.in +++ b/include/OpenShotVersion.h.in @@ -43,36 +43,28 @@ #define OPENSHOT_VERSION_SO @PROJECT_SO_VERSION@ /// Shared object version number. This increments any time the API and ABI changes (so old apps will no longer link) #include -using namespace std; namespace openshot { /// This struct holds version number information. Use the GetVersion() method to access the current version of libopenshot. struct OpenShotVersion { - int major; /// Major version number - int minor; /// Minor version number - int build; /// Build number - int so; /// Shared Object Number (incremented when API or ABI changes) + static const int Major = OPENSHOT_VERSION_MAJOR; /// Major version number + static const int Minor = OPENSHOT_VERSION_MINOR; /// Minor version number + static const int Build = OPENSHOT_VERSION_BUILD; /// Build number + static const int So = OPENSHOT_VERSION_SO; /// Shared Object Number (incremented when API or ABI changes) /// Get a string version of the version (i.e. "Major.Minor.Build") - string ToString() { - stringstream version_string; - version_string << major << "." << minor << "." << build; + inline static const std::string ToString() { + std::stringstream version_string; + version_string << Major << "." << Minor << "." << Build; return version_string.str(); } }; + static const openshot::OpenShotVersion Version; + /// Get the current version number of libopenshot (major, minor, and build number) - static OpenShotVersion GetVersion() { - OpenShotVersion version; - - // Set version info - version.major = OPENSHOT_VERSION_MAJOR; - version.minor = OPENSHOT_VERSION_MINOR; - version.build = OPENSHOT_VERSION_BUILD; - version.so = OPENSHOT_VERSION_SO; - - return version; - } + openshot::OpenShotVersion GetVersion(); } -#endif + +#endif // OPENSHOT_VERSION_H \ No newline at end of file diff --git a/include/QtImageReader.h b/include/QtImageReader.h index 814e3cb3..02f00347 100644 --- a/include/QtImageReader.h +++ b/include/QtImageReader.h @@ -67,7 +67,7 @@ namespace openshot class QtImageReader : public ReaderBase { private: - string path; + QString path; std::shared_ptr image; ///> Original image (full quality) std::shared_ptr cached_image; ///> Scaled for performance bool is_open; ///> Is Reader opened diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5e6c631b..9122f9bf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,8 +6,8 @@ # # Copyright (c) 2008-2019 OpenShot Studios, LLC # . This file is part of -# OpenShot Library (libopenshot), an open-source project dedicated to -# delivering high quality video editing and animation solutions to the +# OpenShot Library (libopenshot), an open-source project dedicated to +# delivering high quality video editing and animation solutions to the # world. For more information visit . # # OpenShot Library (libopenshot) is free software: you can redistribute it @@ -128,7 +128,7 @@ IF (ENABLE_BLACKMAGIC) FIND_PACKAGE(BlackMagic) IF (BLACKMAGIC_FOUND) - # Include headers (needed for compile) + # Include Blackmagic headers (needed for compile) include_directories(${BLACKMAGIC_INCLUDE_DIR}) # define a global var (used in the C++) @@ -138,20 +138,19 @@ IF (ENABLE_BLACKMAGIC) ENDIF (BLACKMAGIC_FOUND) ENDIF (ENABLE_BLACKMAGIC) -################### OPENMP ##################### -# Check for OpenMP (used for multi-core processing) -FIND_PACKAGE(OpenMP) - -if (OPENMP_FOUND) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS} ") -endif(OPENMP_FOUND) - ################### ZEROMQ ##################### # Find ZeroMQ library (used for socket communication & logging) -FIND_PACKAGE(ZMQ REQUIRED) + +# Some platforms package the header-only cppzmq C++ bindings separately, +# others (Ubuntu) bundle them in with libzmq itself +find_package(cppzmq QUIET) +find_package(ZMQ REQUIRED) # Include ZeroMQ headers (needed for compile) include_directories(${ZMQ_INCLUDE_DIRS}) +if (cppzmq_FOUND) + include_directories(${cppzmq_INCLUDE_DIRS}) +endif() ################### RESVG ##################### # Find resvg library (used for rendering svg files) @@ -216,6 +215,7 @@ SET ( OPENSHOT_SOURCE_FILES Frame.cpp FrameMapper.cpp KeyFrame.cpp + OpenShotVersion.cpp ZmqLogger.cpp PlayerBase.cpp Point.cpp @@ -273,6 +273,7 @@ set_target_properties(openshot INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib" ) + ################### FFMPEG ##################### # Find FFmpeg libraries (used for video encoding / decoding) FIND_PACKAGE(FFmpeg REQUIRED COMPONENTS avcodec avdevice avformat avutil swscale) @@ -283,6 +284,25 @@ foreach(ff_comp avcodec avdevice avformat avfilter avutil postproc swscale swres endif() endforeach() +################### OPENMP ##################### +# Check for OpenMP (used for multi-core processing) + +# OpenMP is required by FFmpegReader/Writer +find_package(OpenMP REQUIRED) + +if(NOT TARGET OpenMP::OpenMP_CXX) + # Older CMake versions (< 3.9) don't create find targets. + add_library(OpenMP_TARGET INTERFACE) + add_library(OpenMP::OpenMP_CXX ALIAS OpenMP_TARGET) + target_compile_options(OpenMP_TARGET INTERFACE ${OpenMP_CXX_FLAGS}) + find_package(Threads REQUIRED) + target_link_libraries(OpenMP_TARGET INTERFACE Threads::Threads) + target_link_libraries(OpenMP_TARGET INTERFACE ${OpenMP_CXX_FLAGS}) +endif() + +target_link_libraries(openshot PUBLIC OpenMP::OpenMP_CXX) + + ############### LINK LIBRARY ################# SET ( REQUIRED_LIBRARIES ${LIBOPENSHOT_AUDIO_LIBRARIES} @@ -296,9 +316,6 @@ IF (RESVG_FOUND) list(APPEND REQUIRED_LIBRARIES ${RESVG_LIBRARIES}) ENDIF(RESVG_FOUND) -IF (OPENMP_FOUND) - list(APPEND REQUIRED_LIBRARIES ${OpenMP_CXX_FLAGS}) -ENDIF (OPENMP_FOUND) IF (ImageMagick_FOUND) list(APPEND REQUIRED_LIBRARIES ${ImageMagick_LIBRARIES}) @@ -316,11 +333,21 @@ ENDIF(WIN32) # Link all referenced libraries target_link_libraries(openshot PUBLIC ${REQUIRED_LIBRARIES}) +# Pick up parameters from OpenMP target and propagate +target_link_libraries(openshot PUBLIC OpenMP::OpenMP_CXX) ############### CLI EXECUTABLE ################ # Create test executable add_executable(openshot-example examples/Example.cpp) +# Define path to test input files +SET(TEST_MEDIA_PATH "${PROJECT_SOURCE_DIR}/src/examples/") +IF (WIN32) + STRING(REPLACE "/" "\\\\" TEST_MEDIA_PATH TEST_MEDIA_PATH) +ENDIF(WIN32) +target_compile_definitions(openshot-example PRIVATE + -DTEST_MEDIA_PATH="${TEST_MEDIA_PATH}" ) + # Link test executable to the new library target_link_libraries(openshot-example openshot) diff --git a/src/CacheDisk.cpp b/src/CacheDisk.cpp index b1b1876b..9b345478 100644 --- a/src/CacheDisk.cpp +++ b/src/CacheDisk.cpp @@ -519,7 +519,7 @@ void CacheDisk::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -529,7 +529,7 @@ void CacheDisk::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/CacheMemory.cpp b/src/CacheMemory.cpp index 7bd480e4..4ffed949 100644 --- a/src/CacheMemory.cpp +++ b/src/CacheMemory.cpp @@ -372,7 +372,7 @@ void CacheMemory::SetJson(string value) { delete reader; if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -382,7 +382,7 @@ void CacheMemory::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/ChunkReader.cpp b/src/ChunkReader.cpp index 0836f09f..e1fadc21 100644 --- a/src/ChunkReader.cpp +++ b/src/ChunkReader.cpp @@ -292,7 +292,7 @@ void ChunkReader::SetJson(string value) { delete reader; if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -302,7 +302,7 @@ void ChunkReader::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/Clip.cpp b/src/Clip.cpp index 3bf6030d..7e82ff01 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -235,7 +235,7 @@ ReaderBase* Clip::Reader() return reader; else // Throw error if reader not initialized - throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method.", ""); + throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method."); } // Open the internal reader @@ -252,7 +252,7 @@ void Clip::Open() } else // Throw error if reader not initialized - throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method.", ""); + throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method."); } // Close the internal reader @@ -266,7 +266,7 @@ void Clip::Close() } else // Throw error if reader not initialized - throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method.", ""); + throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method."); } // Get end position of clip (trim end of video), which can be affected by the time curve. @@ -282,7 +282,7 @@ float Clip::End() fps = reader->info.fps.ToFloat(); else // Throw error if reader not initialized - throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method.", ""); + throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method."); return float(time.GetLength()) / fps; } @@ -350,7 +350,7 @@ std::shared_ptr Clip::GetFrame(int64_t requested_frame) } else // Throw error if reader not initialized - throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method.", ""); + throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method."); } // Get file extension @@ -394,7 +394,7 @@ void Clip::get_time_mapped_frame(std::shared_ptr frame, int64_t frame_num // Check for valid reader if (!reader) // Throw error if reader not initialized - throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method.", ""); + throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method."); // Check for a valid time map curve if (time.Values.size() > 1) @@ -812,7 +812,7 @@ void Clip::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -822,7 +822,7 @@ void Clip::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/Color.cpp b/src/Color.cpp index b219e695..1c314aa9 100644 --- a/src/Color.cpp +++ b/src/Color.cpp @@ -120,7 +120,7 @@ void Color::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -130,7 +130,7 @@ void Color::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/Coordinate.cpp b/src/Coordinate.cpp index 739d693f..eaa65dea 100644 --- a/src/Coordinate.cpp +++ b/src/Coordinate.cpp @@ -83,7 +83,7 @@ void Coordinate::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -93,7 +93,7 @@ void Coordinate::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/DecklinkReader.cpp b/src/DecklinkReader.cpp index 3af5e3fc..4ce30149 100644 --- a/src/DecklinkReader.cpp +++ b/src/DecklinkReader.cpp @@ -278,7 +278,7 @@ void DecklinkReader::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -288,7 +288,7 @@ void DecklinkReader::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/DecklinkWriter.cpp b/src/DecklinkWriter.cpp index 7dcede04..4ebbd1f0 100644 --- a/src/DecklinkWriter.cpp +++ b/src/DecklinkWriter.cpp @@ -234,7 +234,7 @@ void DecklinkWriter::WriteFrame(std::shared_ptr frame) { // Check for open reader (or throw exception) if (!is_open) - throw WriterClosed("The DecklinkWriter is closed. Call Open() before calling this method.", ""); + throw WriterClosed("The DecklinkWriter is closed. Call Open() before calling this method."); delegate->WriteFrame(frame); } diff --git a/src/DummyReader.cpp b/src/DummyReader.cpp index 346430dc..bdfb7cb5 100644 --- a/src/DummyReader.cpp +++ b/src/DummyReader.cpp @@ -156,7 +156,7 @@ void DummyReader::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -166,7 +166,7 @@ void DummyReader::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/EffectBase.cpp b/src/EffectBase.cpp index 30909420..77bfec9b 100644 --- a/src/EffectBase.cpp +++ b/src/EffectBase.cpp @@ -112,7 +112,7 @@ void EffectBase::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -122,7 +122,7 @@ void EffectBase::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index 6e8553f1..d017df19 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -309,7 +309,7 @@ void FFmpegReader::Open() { char *adapter_ptr = NULL; int adapter_num; adapter_num = openshot::Settings::Instance()->HW_DE_DEVICE_SET; - fprintf(stderr, "\n\nDecodiing Device Nr: %d\n", adapter_num); + fprintf(stderr, "Hardware decoding device number: %d\n", adapter_num); // Set hardware pix format (callback) pCodecCtx->get_format = get_hw_dec_format; @@ -729,6 +729,33 @@ void FFmpegReader::UpdateVideoInfo() { info.display_ratio.num = size.num; info.display_ratio.den = size.den; + // Get scan type and order from codec context/params + if (!check_interlace) { + check_interlace = true; + AVFieldOrder field_order = AV_GET_CODEC_ATTRIBUTES(pStream, pCodecCtx)->field_order; + switch(field_order) { + case AV_FIELD_PROGRESSIVE: + info.interlaced_frame = false; + break; + case AV_FIELD_TT: + case AV_FIELD_TB: + info.interlaced_frame = true; + info.top_field_first = true; + break; + case AV_FIELD_BT: + case AV_FIELD_BB: + info.interlaced_frame = true; + info.top_field_first = false; + break; + case AV_FIELD_UNKNOWN: + // Check again later? + check_interlace = false; + break; + } + // check_interlace will prevent these checks being repeated, + // unless it was cleared because we got an AV_FIELD_UNKNOWN response. + } + // Set the video timebase info.video_timebase.num = pStream->time_base.num; info.video_timebase.den = pStream->time_base.den; @@ -1078,14 +1105,14 @@ bool FFmpegReader::GetAVFrame() { ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::GetAVFrame (Packet not sent)"); } else { - AVFrame *next_frame2; - if (hw_de_on && hw_de_supported) { - next_frame2 = AV_ALLOCATE_FRAME(); - } - else - { - next_frame2 = next_frame; - } + AVFrame *next_frame2; + if (hw_de_on && hw_de_supported) { + next_frame2 = AV_ALLOCATE_FRAME(); + } + else + { + next_frame2 = next_frame; + } pFrame = AV_ALLOCATE_FRAME(); while (ret >= 0) { ret = avcodec_receive_frame(pCodecCtx, next_frame2); @@ -1119,11 +1146,6 @@ bool FFmpegReader::GetAVFrame() { av_image_alloc(pFrame->data, pFrame->linesize, info.width, info.height, (AVPixelFormat)(pStream->codecpar->format), 1); av_image_copy(pFrame->data, pFrame->linesize, (const uint8_t**)next_frame->data, next_frame->linesize, (AVPixelFormat)(pStream->codecpar->format), info.width, info.height); - if (!check_interlace) { - check_interlace = true; - info.interlaced_frame = next_frame->interlaced_frame; - info.top_field_first = next_frame->top_field_first; - } } } if (hw_de_on && hw_de_supported) { @@ -1143,13 +1165,6 @@ bool FFmpegReader::GetAVFrame() { avpicture_alloc((AVPicture *) pFrame, pCodecCtx->pix_fmt, info.width, info.height); av_picture_copy((AVPicture *) pFrame, (AVPicture *) next_frame, pCodecCtx->pix_fmt, info.width, info.height); - - // Detect interlaced frame (only once) - if (!check_interlace) { - check_interlace = true; - info.interlaced_frame = next_frame->interlaced_frame; - info.top_field_first = next_frame->top_field_first; - } } #endif } @@ -2049,18 +2064,11 @@ bool FFmpegReader::CheckMissingFrame(int64_t requested_frame) { // Lock const GenericScopedLock lock(processingCriticalSection); - // Init # of times this frame has been checked so far - int checked_count = 0; - // Increment check count for this frame (or init to 1) - if (checked_frames.count(requested_frame) == 0) - checked_frames[requested_frame] = 1; - else - checked_frames[requested_frame]++; - checked_count = checked_frames[requested_frame]; + ++checked_frames[requested_frame]; // Debug output - ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::CheckMissingFrame", "requested_frame", requested_frame, "has_missing_frames", has_missing_frames, "missing_video_frames.size()", missing_video_frames.size(), "checked_count", checked_count); + ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::CheckMissingFrame", "requested_frame", requested_frame, "has_missing_frames", has_missing_frames, "missing_video_frames.size()", missing_video_frames.size(), "checked_count", checked_frames[requested_frame]); // Missing frames (sometimes frame #'s are skipped due to invalid or missing timestamps) map::iterator itr; @@ -2073,7 +2081,7 @@ bool FFmpegReader::CheckMissingFrame(int64_t requested_frame) { // If MP3 with single video frame, handle this special case by copying the previously // decoded image to the new frame. Otherwise, it will spend a huge amount of // CPU time looking for missing images for all the audio-only frames. - if (checked_count > 8 && !missing_video_frames.count(requested_frame) && + if (checked_frames[requested_frame] > 8 && !missing_video_frames.count(requested_frame) && !processing_audio_frames.count(requested_frame) && processed_audio_frames.count(requested_frame) && last_frame && last_video_frame->has_image_data && aCodecId == AV_CODEC_ID_MP3 && (vCodecId == AV_CODEC_ID_MJPEGB || vCodecId == AV_CODEC_ID_MJPEG)) { missing_video_frames.insert(pair(requested_frame, last_video_frame->number)); @@ -2087,10 +2095,7 @@ bool FFmpegReader::CheckMissingFrame(int64_t requested_frame) { int64_t missing_source_frame = missing_video_frames.find(requested_frame)->second; // Increment missing source frame check count (or init to 1) - if (checked_frames.count(missing_source_frame) == 0) - checked_frames[missing_source_frame] = 1; - else - checked_frames[missing_source_frame]++; + ++checked_frames[missing_source_frame]; // Get the previous frame of this missing frame (if it's available in missing cache) std::shared_ptr parent_frame = missing_frames.GetFrame(missing_source_frame); @@ -2452,7 +2457,7 @@ void FFmpegReader::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { // Set all values that match @@ -2460,7 +2465,7 @@ void FFmpegReader::SetJson(string value) { } catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 94d03e76..f85e09ad 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -172,7 +172,7 @@ void FFmpegWriter::SetVideoOptions(bool has_video, string codec, Fraction fps, i AVCodec *new_codec; // Check if the codec selected is a hardware accelerated codec #if IS_FFMPEG_3_2 - #if defined(__linux__) + #if defined(__linux__) if ( (strcmp(codec.c_str(),"h264_vaapi") == 0)) { new_codec = avcodec_find_encoder_by_name(codec.c_str()); hw_en_on = 1; @@ -194,7 +194,7 @@ void FFmpegWriter::SetVideoOptions(bool has_video, string codec, Fraction fps, i hw_en_supported = 0; } } -#elif defined(_WIN32) + #elif defined(_WIN32) if ( (strcmp(codec.c_str(),"h264_dxva2") == 0)) { new_codec = avcodec_find_encoder_by_name(codec.c_str()); hw_en_on = 1; @@ -216,7 +216,7 @@ void FFmpegWriter::SetVideoOptions(bool has_video, string codec, Fraction fps, i hw_en_supported = 0; } } -#elif defined(__APPLE__) + #elif defined(__APPLE__) if ( (strcmp(codec.c_str(),"h264_videotoolbox") == 0)) { new_codec = avcodec_find_encoder_by_name(codec.c_str()); hw_en_on = 1; @@ -229,9 +229,9 @@ void FFmpegWriter::SetVideoOptions(bool has_video, string codec, Fraction fps, i hw_en_on = 0; hw_en_supported = 0; } -#else // is FFmpeg 3 but not linux + #else // is FFmpeg 3 but not linux new_codec = avcodec_find_encoder_by_name(codec.c_str()); -#endif //__linux__ + #endif //__linux__ #else // not ffmpeg 3 new_codec = avcodec_find_encoder_by_name(codec.c_str()); #endif //IS_FFMPEG_3_2 diff --git a/src/FrameMapper.cpp b/src/FrameMapper.cpp index ff7cf1ce..40d1899e 100644 --- a/src/FrameMapper.cpp +++ b/src/FrameMapper.cpp @@ -75,7 +75,7 @@ ReaderBase* FrameMapper::Reader() return reader; else // Throw error if reader not initialized - throw ReaderClosed("No Reader has been initialized for FrameMapper. Call Reader(*reader) before calling this method.", ""); + throw ReaderClosed("No Reader has been initialized for FrameMapper. Call Reader(*reader) before calling this method."); } void FrameMapper::AddField(int64_t frame) @@ -707,7 +707,7 @@ void FrameMapper::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -717,7 +717,7 @@ void FrameMapper::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/ImageReader.cpp b/src/ImageReader.cpp index a0b7e8f3..b719ee3d 100644 --- a/src/ImageReader.cpp +++ b/src/ImageReader.cpp @@ -169,7 +169,7 @@ void ImageReader::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -179,7 +179,7 @@ void ImageReader::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/KeyFrame.cpp b/src/KeyFrame.cpp index 94618135..37e005d9 100644 --- a/src/KeyFrame.cpp +++ b/src/KeyFrame.cpp @@ -379,7 +379,7 @@ void Keyframe::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -389,7 +389,7 @@ void Keyframe::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/OpenShotVersion.cpp b/src/OpenShotVersion.cpp new file mode 100644 index 00000000..1bc73c3a --- /dev/null +++ b/src/OpenShotVersion.cpp @@ -0,0 +1,38 @@ +/** + * @file + * @brief Source file for GetVersion function + * @author Jonathan Thomas + * @author FeRD (Frank Dana) + * + * @ref License + */ + +/* LICENSE + * + * Copyright (c) 2008-2019 OpenShot Studios, LLC + * . This file is part of + * OpenShot Library (libopenshot), an open-source project dedicated to + * delivering high quality video editing and animation solutions to the + * world. For more information visit . + * + * OpenShot Library (libopenshot) is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * OpenShot Library (libopenshot) is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OpenShot Library. If not, see . + */ + +#include "OpenShotVersion.h" + +namespace openshot { + OpenShotVersion GetVersion() { + return openshot::Version; + } +} \ No newline at end of file diff --git a/src/Point.cpp b/src/Point.cpp index fd23da55..72eedebc 100644 --- a/src/Point.cpp +++ b/src/Point.cpp @@ -146,7 +146,7 @@ void Point::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -156,7 +156,7 @@ void Point::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/Profiles.cpp b/src/Profiles.cpp index e57f7aa3..752bdb1e 100644 --- a/src/Profiles.cpp +++ b/src/Profiles.cpp @@ -177,7 +177,7 @@ void Profile::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -187,7 +187,7 @@ void Profile::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/Qt/VideoCacheThread.cpp b/src/Qt/VideoCacheThread.cpp index fbe784f7..46b6f030 100644 --- a/src/Qt/VideoCacheThread.cpp +++ b/src/Qt/VideoCacheThread.cpp @@ -93,7 +93,7 @@ namespace openshot try { if (reader) { - ZmqLogger::Instance()->AppendDebugMethod("VideoCacheThread::run (cache frame)", "position", position, "current_display_frame", current_display_frame, "max_frames", max_frames, "needed_frames", (position - current_display_frame), "", -1, "", -1); + ZmqLogger::Instance()->AppendDebugMethod("VideoCacheThread::run (cache frame)", "position", position, "current_display_frame", current_display_frame, "max_frames", max_frames, "needed_frames", (position - current_display_frame)); // Force the frame to be generated reader->GetFrame(position); diff --git a/src/Qt/VideoPlaybackThread.cpp b/src/Qt/VideoPlaybackThread.cpp index 730a1d37..f1cff756 100644 --- a/src/Qt/VideoPlaybackThread.cpp +++ b/src/Qt/VideoPlaybackThread.cpp @@ -64,7 +64,7 @@ namespace openshot if (need_render && frame) { // Debug - ZmqLogger::Instance()->AppendDebugMethod("VideoPlaybackThread::run (before render)", "frame->number", frame->number, "need_render", need_render, "", -1, "", -1, "", -1, "", -1); + ZmqLogger::Instance()->AppendDebugMethod("VideoPlaybackThread::run (before render)", "frame->number", frame->number, "need_render", need_render); // Render the frame to the screen renderer->paint(frame); diff --git a/src/QtImageReader.cpp b/src/QtImageReader.cpp index 9107e51f..97a0b24f 100644 --- a/src/QtImageReader.cpp +++ b/src/QtImageReader.cpp @@ -44,14 +44,14 @@ using namespace openshot; -QtImageReader::QtImageReader(string path) : path(path), is_open(false) +QtImageReader::QtImageReader(string path) : path{QString::fromStdString(path)}, is_open(false) { // Open and Close the reader, to populate its attributes (such as height, width, etc...) Open(); Close(); } -QtImageReader::QtImageReader(string path, bool inspect_reader) : path(path), is_open(false) +QtImageReader::QtImageReader(string path, bool inspect_reader) : path{QString::fromStdString(path)}, is_open(false) { // Open and Close the reader, to populate its attributes (such as height, width, etc...) if (inspect_reader) { @@ -77,12 +77,12 @@ void QtImageReader::Open() // If defined and found in CMake, utilize the libresvg for parsing // SVG files and rasterizing them to QImages. // Only use resvg for files ending in '.svg' or '.svgz' - if (path.find(".svg") != std::string::npos || path.find(".svgz") != std::string::npos) { + if (path.toLower().endsWith(".svg") || path.toLower().endsWith(".svgz")) { - ResvgRenderer renderer(QString::fromStdString(path)); + ResvgRenderer renderer(path); if (!renderer.isValid()) { // Attempt to open file (old method using Qt5 limited SVG parsing) - success = image->load(QString::fromStdString(path)); + success = image->load(path); if (success) { image = std::shared_ptr(new QImage(image->convertToFormat(QImage::Format_RGBA8888))); } @@ -98,20 +98,20 @@ void QtImageReader::Open() } else { // Attempt to open file (old method) - success = image->load(QString::fromStdString(path)); + success = image->load(path); if (success) image = std::shared_ptr(new QImage(image->convertToFormat(QImage::Format_RGBA8888))); } #else // Attempt to open file using Qt's build in image processing capabilities - success = image->load(QString::fromStdString(path)); + success = image->load(path); if (success) image = std::shared_ptr(new QImage(image->convertToFormat(QImage::Format_RGBA8888))); #endif if (!success) // raise exception - throw InvalidFile("File could not be opened.", path); + throw InvalidFile("File could not be opened.", path.toStdString()); // Update image properties info.has_audio = false; @@ -171,7 +171,7 @@ std::shared_ptr QtImageReader::GetFrame(int64_t requested_frame) { // Check for open reader (or throw exception) if (!is_open) - throw ReaderClosed("The Image is closed. Call Open() before calling this method.", path); + throw ReaderClosed("The Image is closed. Call Open() before calling this method.", path.toStdString()); // Create a scoped lock, allowing only a single thread to run the following code at one time const GenericScopedLock lock(getFrameCriticalSection); @@ -228,8 +228,8 @@ std::shared_ptr QtImageReader::GetFrame(int64_t requested_frame) // If defined and found in CMake, utilize the libresvg for parsing // SVG files and rasterizing them to QImages. // Only use resvg for files ending in '.svg' or '.svgz' - if (path.find(".svg") != std::string::npos || path.find(".svgz") != std::string::npos) { - ResvgRenderer renderer(QString::fromStdString(path)); + if (path.toLower().endsWith(".svg") || path.toLower().endsWith(".svgz")) { + ResvgRenderer renderer(path); if (renderer.isValid()) { // Scale SVG size to keep aspect ratio, and fill the max_size as best as possible QSize svg_size(renderer.defaultSize().width(), renderer.defaultSize().height()); @@ -289,7 +289,7 @@ Json::Value QtImageReader::JsonValue() { // Create root json object Json::Value root = ReaderBase::JsonValue(); // get parent properties root["type"] = "QtImageReader"; - root["path"] = path; + root["path"] = path.toStdString(); // return JsonValue return root; @@ -310,7 +310,7 @@ void QtImageReader::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -320,7 +320,7 @@ void QtImageReader::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } @@ -332,7 +332,7 @@ void QtImageReader::SetJsonValue(Json::Value root) { // Set data from Json (if key is found) if (!root["path"].isNull()) - path = root["path"].asString(); + path = QString::fromStdString(root["path"].asString()); // Re-Open path, and re-init everything (if needed) if (is_open) diff --git a/src/TextReader.cpp b/src/TextReader.cpp index 27f503e1..e92ec285 100644 --- a/src/TextReader.cpp +++ b/src/TextReader.cpp @@ -230,7 +230,7 @@ void TextReader::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -240,7 +240,7 @@ void TextReader::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 296e7a93..b8dabf68 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -746,7 +746,7 @@ std::shared_ptr Timeline::GetFrame(int64_t requested_frame) // Check for open reader (or throw exception) if (!is_open) - throw ReaderClosed("The Timeline is closed. Call Open() before calling this method.", ""); + throw ReaderClosed("The Timeline is closed. Call Open() before calling this method."); // Check cache again (due to locking) #pragma omp critical (T_GetFrame) @@ -1040,7 +1040,7 @@ void Timeline::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -1050,7 +1050,7 @@ void Timeline::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } @@ -1139,7 +1139,7 @@ void Timeline::ApplyJsonDiff(string value) { if (!success || !root.isArray()) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid).", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)."); try { @@ -1167,7 +1167,7 @@ void Timeline::ApplyJsonDiff(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/WriterBase.cpp b/src/WriterBase.cpp index f677215a..3344c55a 100644 --- a/src/WriterBase.cpp +++ b/src/WriterBase.cpp @@ -209,7 +209,7 @@ void WriterBase::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -219,7 +219,7 @@ void WriterBase::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/bindings/python/CMakeLists.txt b/src/bindings/python/CMakeLists.txt index 90053270..bc07571f 100644 --- a/src/bindings/python/CMakeLists.txt +++ b/src/bindings/python/CMakeLists.txt @@ -48,7 +48,6 @@ if (PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND) ### Enable C++ support in SWIG set_property(SOURCE openshot.i PROPERTY CPLUSPLUS ON) set_property(SOURCE openshot.i PROPERTY SWIG_MODULE_NAME openshot) - SET(CMAKE_SWIG_FLAGS "") ### Suppress a ton of warnings in the generated SWIG C++ code set(SWIG_CXX_FLAGS "-Wno-unused-variable -Wno-unused-function -Wno-deprecated-copy -Wno-class-memaccess -Wno-cast-function-type \ diff --git a/src/bindings/python/openshot.i b/src/bindings/python/openshot.i index 732a1313..a19919c1 100644 --- a/src/bindings/python/openshot.i +++ b/src/bindings/python/openshot.i @@ -123,6 +123,13 @@ } } +%extend openshot::OpenShotVersion { + // Give the struct a string representation + const std::string __str__() { + return std::string(OPENSHOT_VERSION_FULL); + } +} + %include "OpenShotVersion.h" %include "../../../include/ReaderBase.h" %include "../../../include/WriterBase.h" diff --git a/src/bindings/ruby/CMakeLists.txt b/src/bindings/ruby/CMakeLists.txt index 5208abc1..0a9fe6de 100644 --- a/src/bindings/ruby/CMakeLists.txt +++ b/src/bindings/ruby/CMakeLists.txt @@ -50,7 +50,6 @@ IF (RUBY_FOUND) set_property(SOURCE openshot.i PROPERTY CPLUSPLUS ON) set_property(SOURCE openshot.i PROPERTY SWIG_MODULE_NAME openshot) - SET(CMAKE_SWIG_FLAGS "") ### Suppress a ton of warnings in the generated SWIG C++ code set(SWIG_CXX_FLAGS "-Wno-unused-variable -Wno-unused-function -Wno-deprecated-copy -Wno-class-memaccess -Wno-cast-function-type \ -Wno-unused-parameter -Wno-catch-value -Wno-sign-compare -Wno-ignored-qualifiers") diff --git a/src/effects/Bars.cpp b/src/effects/Bars.cpp index 6d731d9c..9748db99 100644 --- a/src/effects/Bars.cpp +++ b/src/effects/Bars.cpp @@ -151,7 +151,7 @@ void Bars::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -161,7 +161,7 @@ void Bars::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/effects/Blur.cpp b/src/effects/Blur.cpp index 7946e249..d4f7c19d 100644 --- a/src/effects/Blur.cpp +++ b/src/effects/Blur.cpp @@ -288,7 +288,7 @@ void Blur::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -298,7 +298,7 @@ void Blur::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/effects/Brightness.cpp b/src/effects/Brightness.cpp index 3a1a4bdb..4ffd69f3 100644 --- a/src/effects/Brightness.cpp +++ b/src/effects/Brightness.cpp @@ -142,7 +142,7 @@ void Brightness::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -152,7 +152,7 @@ void Brightness::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/effects/ChromaKey.cpp b/src/effects/ChromaKey.cpp index 2e2dc511..9c7124e6 100644 --- a/src/effects/ChromaKey.cpp +++ b/src/effects/ChromaKey.cpp @@ -135,7 +135,7 @@ void ChromaKey::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -145,7 +145,7 @@ void ChromaKey::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/effects/ColorShift.cpp b/src/effects/ColorShift.cpp index 10f22217..c16f0aa6 100644 --- a/src/effects/ColorShift.cpp +++ b/src/effects/ColorShift.cpp @@ -234,7 +234,7 @@ void ColorShift::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -244,7 +244,7 @@ void ColorShift::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/effects/Crop.cpp b/src/effects/Crop.cpp index 7ff6ec0b..3e9a2fa3 100644 --- a/src/effects/Crop.cpp +++ b/src/effects/Crop.cpp @@ -150,7 +150,7 @@ void Crop::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -160,7 +160,7 @@ void Crop::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/effects/Deinterlace.cpp b/src/effects/Deinterlace.cpp index 65f00ff6..8bcd1a8e 100644 --- a/src/effects/Deinterlace.cpp +++ b/src/effects/Deinterlace.cpp @@ -129,7 +129,7 @@ void Deinterlace::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -139,7 +139,7 @@ void Deinterlace::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/effects/Hue.cpp b/src/effects/Hue.cpp index fd33272d..eefaf4d9 100644 --- a/src/effects/Hue.cpp +++ b/src/effects/Hue.cpp @@ -136,7 +136,7 @@ void Hue::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -146,7 +146,7 @@ void Hue::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/effects/Mask.cpp b/src/effects/Mask.cpp index 9f19475d..c2f49545 100644 --- a/src/effects/Mask.cpp +++ b/src/effects/Mask.cpp @@ -189,7 +189,7 @@ void Mask::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -199,7 +199,7 @@ void Mask::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/effects/Negate.cpp b/src/effects/Negate.cpp index 938030bc..94022aee 100644 --- a/src/effects/Negate.cpp +++ b/src/effects/Negate.cpp @@ -90,7 +90,7 @@ void Negate::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -100,7 +100,7 @@ void Negate::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/effects/Pixelate.cpp b/src/effects/Pixelate.cpp index d7c3fa12..ab211535 100644 --- a/src/effects/Pixelate.cpp +++ b/src/effects/Pixelate.cpp @@ -147,7 +147,7 @@ void Pixelate::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -157,7 +157,7 @@ void Pixelate::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/effects/Saturation.cpp b/src/effects/Saturation.cpp index 98818127..6e7b758b 100644 --- a/src/effects/Saturation.cpp +++ b/src/effects/Saturation.cpp @@ -147,7 +147,7 @@ void Saturation::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -157,7 +157,7 @@ void Saturation::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/effects/Shift.cpp b/src/effects/Shift.cpp index c22844e7..b4ab11b8 100644 --- a/src/effects/Shift.cpp +++ b/src/effects/Shift.cpp @@ -167,7 +167,7 @@ void Shift::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -177,7 +177,7 @@ void Shift::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/effects/Wave.cpp b/src/effects/Wave.cpp index 6e3bd48a..fa8ba6a7 100644 --- a/src/effects/Wave.cpp +++ b/src/effects/Wave.cpp @@ -150,7 +150,7 @@ void Wave::SetJson(string value) { if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -160,7 +160,7 @@ void Wave::SetJson(string value) { catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } diff --git a/src/examples/Example.cpp b/src/examples/Example.cpp index eec8d00e..9e5ee369 100644 --- a/src/examples/Example.cpp +++ b/src/examples/Example.cpp @@ -39,16 +39,19 @@ using namespace openshot; int main(int argc, char* argv[]) { - Settings *s = Settings::Instance(); - s->HARDWARE_DECODER = 2; // 1 VA-API, 2 NVDEC - s->HW_DE_DEVICE_SET = 0; + Settings *s = Settings::Instance(); + s->HARDWARE_DECODER = 2; // 1 VA-API, 2 NVDEC, 6 VDPAU + s->HW_DE_DEVICE_SET = 0; - FFmpegReader r9("/home/jonathan/Videos/sintel_trailer-720p.mp4"); + std::string input_filepath = TEST_MEDIA_PATH; + input_filepath += "sintel_trailer-720p.mp4"; + + FFmpegReader r9(input_filepath); r9.Open(); r9.DisplayInfo(); /* WRITER ---------------- */ - FFmpegWriter w9("/home/jonathan/metadata.mp4"); + FFmpegWriter w9("metadata.mp4"); // Set options w9.SetAudioOptions(true, "libmp3lame", r9.info.sample_rate, r9.info.channels, r9.info.channel_layout, 128000); @@ -80,7 +83,7 @@ int main(int argc, char* argv[]) { // Close timeline r9.Close(); - cout << "Completed successfully!" << endl; + cout << "Completed successfully!" << endl; return 0; -} \ No newline at end of file +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3c0cba7e..f4b244c2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -113,20 +113,20 @@ IF (ENABLE_BLACKMAGIC) ENDIF (BLACKMAGIC_FOUND) ENDIF (ENABLE_BLACKMAGIC) -################### OPENMP ##################### -# Check for OpenMP (used for multi-core processing) -FIND_PACKAGE(OpenMP) - -if (OPENMP_FOUND) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS} ") -endif(OPENMP_FOUND) ################### ZEROMQ ##################### # Find ZeroMQ library (used for socket communication & logging) + +# Some platforms package the header-only cppzmq C++ bindings separately, +# others (Ubuntu) bundle them in with libzmq itself +find_package(cppzmq QUIET) FIND_PACKAGE(ZMQ REQUIRED) # Include ZeroMQ headers (needed for compile) include_directories(${ZMQ_INCLUDE_DIRS}) +if (cppzmq_FOUND) + include_directories(${cppzmq_INCLUDE_DIRS}) +endif() ################### RESVG ##################### # Find resvg library (used for rendering svg files) @@ -148,7 +148,7 @@ endif(USE_SYSTEM_JSONCPP) IF (NOT DISABLE_TESTS) ############### SET TEST SOURCE FILES ################# - SET ( OPENSHOT_TEST_FILES tests.cpp + SET ( OPENSHOT_TEST_FILES Cache_Tests.cpp Clip_Tests.cpp Color_Tests.cpp @@ -166,6 +166,7 @@ IF (NOT DISABLE_TESTS) ################ TESTER EXECUTABLE ################# # Create unit test executable (openshot-test) + message (STATUS "Tests enabled, test executable will be built as tests/openshot-test") add_executable(openshot-test tests.cpp ${OPENSHOT_TEST_FILES} ) @@ -173,7 +174,24 @@ IF (NOT DISABLE_TESTS) # Link libraries to the new executable target_link_libraries(openshot-test openshot ${UNITTEST++_LIBRARY}) - #################### MAKE TEST ###################### + ##### RUNNING TESTS (make os_test / make test) ##### # Hook up the 'make os_test' target to the 'openshot-test' executable ADD_CUSTOM_TARGET(os_test COMMAND openshot-test) -ENDIF (NOT DISABLE_TESTS) + list(APPEND OS_TEST_CMDS "'make os_test'") + + # Also hook up 'make test', if possible + # This requires CMake 3.11+, where the CMP0037 policy + # configured to 'NEW' mode will not reserve target names + # unless the corresponding feature is actually used + if (POLICY CMP0037) + cmake_policy(SET CMP0037 NEW) + endif() + if (CMAKE_VERSION VERSION_GREATER 3.11) + message(STATUS "Cmake 3.11+ detected, enabling 'test' target") + add_custom_target(test COMMAND openshot-test) + list(APPEND OS_TEST_CMDS " or " "'make test'") + endif() + + string(CONCAT t ${OS_TEST_CMDS}) + message("\nTo run unit tests, use: ${t}") +endif() diff --git a/tests/Clip_Tests.cpp b/tests/Clip_Tests.cpp index 1b7475f4..5789780b 100644 --- a/tests/Clip_Tests.cpp +++ b/tests/Clip_Tests.cpp @@ -120,7 +120,7 @@ TEST(Clip_Properties) if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -132,7 +132,7 @@ TEST(Clip_Properties) catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } @@ -145,7 +145,7 @@ TEST(Clip_Properties) properties.c_str() + properties.size(), &root, &errors ); if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -157,7 +157,7 @@ TEST(Clip_Properties) catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } @@ -170,7 +170,7 @@ TEST(Clip_Properties) properties.c_str() + properties.size(), &root, &errors ); if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -181,7 +181,7 @@ TEST(Clip_Properties) catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } @@ -194,7 +194,7 @@ TEST(Clip_Properties) properties.c_str() + properties.size(), &root, &errors ); if (!success) // Raise exception - throw InvalidJSON("JSON could not be parsed (or is invalid)", ""); + throw InvalidJSON("JSON could not be parsed (or is invalid)"); try { @@ -206,7 +206,7 @@ TEST(Clip_Properties) catch (const std::exception& e) { // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", ""); + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } diff --git a/tests/FFmpegReader_Tests.cpp b/tests/FFmpegReader_Tests.cpp index 68aba4bb..4b808d83 100644 --- a/tests/FFmpegReader_Tests.cpp +++ b/tests/FFmpegReader_Tests.cpp @@ -97,10 +97,10 @@ TEST(FFmpegReader_Check_Video_File) int pixel_index = 112 * 4; // pixel 112 (4 bytes per pixel) // Check image properties on scanline 10, pixel 112 - CHECK_EQUAL(21, (int)pixels[pixel_index]); - CHECK_EQUAL(191, (int)pixels[pixel_index + 1]); - CHECK_EQUAL(0, (int)pixels[pixel_index + 2]); - CHECK_EQUAL(255, (int)pixels[pixel_index + 3]); + CHECK_CLOSE(21, (int)pixels[pixel_index], 5); + CHECK_CLOSE(191, (int)pixels[pixel_index + 1], 5); + CHECK_CLOSE(0, (int)pixels[pixel_index + 2], 5); + CHECK_CLOSE(255, (int)pixels[pixel_index + 3], 5); // Check pixel function CHECK_EQUAL(true, f->CheckPixel(10, 112, 21, 191, 0, 255, 5)); @@ -114,10 +114,10 @@ TEST(FFmpegReader_Check_Video_File) pixel_index = 112 * 4; // pixel 112 (4 bytes per pixel) // Check image properties on scanline 10, pixel 112 - CHECK_EQUAL(0, (int)pixels[pixel_index]); - CHECK_EQUAL(96, (int)pixels[pixel_index + 1]); - CHECK_EQUAL(188, (int)pixels[pixel_index + 2]); - CHECK_EQUAL(255, (int)pixels[pixel_index + 3]); + CHECK_CLOSE(0, (int)pixels[pixel_index], 5); + CHECK_CLOSE(96, (int)pixels[pixel_index + 1], 5); + CHECK_CLOSE(188, (int)pixels[pixel_index + 2], 5); + CHECK_CLOSE(255, (int)pixels[pixel_index + 3], 5); // Check pixel function CHECK_EQUAL(true, f->CheckPixel(10, 112, 0, 96, 188, 255, 5)); diff --git a/tests/FFmpegWriter_Tests.cpp b/tests/FFmpegWriter_Tests.cpp index 8cb10e15..1cab8043 100644 --- a/tests/FFmpegWriter_Tests.cpp +++ b/tests/FFmpegWriter_Tests.cpp @@ -75,8 +75,8 @@ TEST(FFmpegWriter_Test_Webm) int pixel_index = 112 * 4; // pixel 112 (4 bytes per pixel) // Check image properties on scanline 10, pixel 112 - CHECK_EQUAL(23, (int)pixels[pixel_index]); - CHECK_EQUAL(23, (int)pixels[pixel_index + 1]); - CHECK_EQUAL(23, (int)pixels[pixel_index + 2]); - CHECK_EQUAL(255, (int)pixels[pixel_index + 3]); + CHECK_CLOSE(23, (int)pixels[pixel_index], 5); + CHECK_CLOSE(23, (int)pixels[pixel_index + 1], 5); + CHECK_CLOSE(23, (int)pixels[pixel_index + 2], 5); + CHECK_CLOSE(255, (int)pixels[pixel_index + 3], 5); } diff --git a/tests/ImageWriter_Tests.cpp b/tests/ImageWriter_Tests.cpp index 4236b462..49202e96 100644 --- a/tests/ImageWriter_Tests.cpp +++ b/tests/ImageWriter_Tests.cpp @@ -75,9 +75,9 @@ TEST(ImageWriter_Test_Gif) int pixel_index = 230 * 4; // pixel 230 (4 bytes per pixel) // Check image properties - CHECK_EQUAL(20, (int)pixels[pixel_index]); - CHECK_EQUAL(18, (int)pixels[pixel_index + 1]); - CHECK_EQUAL(11, (int)pixels[pixel_index + 2]); - CHECK_EQUAL(255, (int)pixels[pixel_index + 3]); + CHECK_CLOSE(20, (int)pixels[pixel_index], 5); + CHECK_CLOSE(18, (int)pixels[pixel_index + 1], 5); + CHECK_CLOSE(11, (int)pixels[pixel_index + 2], 5); + CHECK_CLOSE(255, (int)pixels[pixel_index + 3], 5); } #endif diff --git a/tests/Timeline_Tests.cpp b/tests/Timeline_Tests.cpp index 0bb42b89..77a3bcbc 100644 --- a/tests/Timeline_Tests.cpp +++ b/tests/Timeline_Tests.cpp @@ -121,64 +121,64 @@ TEST(Timeline_Check_Two_Track_Video) int pixel_index = 230 * 4; // pixel 230 (4 bytes per pixel) // Check image properties - CHECK_EQUAL(21, (int)f->GetPixels(pixel_row)[pixel_index]); - CHECK_EQUAL(191, (int)f->GetPixels(pixel_row)[pixel_index + 1]); - CHECK_EQUAL(0, (int)f->GetPixels(pixel_row)[pixel_index + 2]); - CHECK_EQUAL(255, (int)f->GetPixels(pixel_row)[pixel_index + 3]); + CHECK_CLOSE(21, (int)f->GetPixels(pixel_row)[pixel_index], 5); + CHECK_CLOSE(191, (int)f->GetPixels(pixel_row)[pixel_index + 1], 5); + CHECK_CLOSE(0, (int)f->GetPixels(pixel_row)[pixel_index + 2], 5); + CHECK_CLOSE(255, (int)f->GetPixels(pixel_row)[pixel_index + 3], 5); // Get frame f = t.GetFrame(2); // Check image properties - CHECK_EQUAL(176, (int)f->GetPixels(pixel_row)[pixel_index]); - CHECK_EQUAL(0, (int)f->GetPixels(pixel_row)[pixel_index + 1]); - CHECK_EQUAL(186, (int)f->GetPixels(pixel_row)[pixel_index + 2]); - CHECK_EQUAL(255, (int)f->GetPixels(pixel_row)[pixel_index + 3]); + CHECK_CLOSE(176, (int)f->GetPixels(pixel_row)[pixel_index], 5); + CHECK_CLOSE(0, (int)f->GetPixels(pixel_row)[pixel_index + 1], 5); + CHECK_CLOSE(186, (int)f->GetPixels(pixel_row)[pixel_index + 2], 5); + CHECK_CLOSE(255, (int)f->GetPixels(pixel_row)[pixel_index + 3], 5); // Get frame f = t.GetFrame(3); // Check image properties - CHECK_EQUAL(23, (int)f->GetPixels(pixel_row)[pixel_index]); - CHECK_EQUAL(190, (int)f->GetPixels(pixel_row)[pixel_index + 1]); - CHECK_EQUAL(0, (int)f->GetPixels(pixel_row)[pixel_index + 2]); - CHECK_EQUAL(255, (int)f->GetPixels(pixel_row)[pixel_index + 3]); + CHECK_CLOSE(23, (int)f->GetPixels(pixel_row)[pixel_index], 5); + CHECK_CLOSE(190, (int)f->GetPixels(pixel_row)[pixel_index + 1], 5); + CHECK_CLOSE(0, (int)f->GetPixels(pixel_row)[pixel_index + 2], 5); + CHECK_CLOSE(255, (int)f->GetPixels(pixel_row)[pixel_index + 3], 5); // Get frame f = t.GetFrame(24); // Check image properties - CHECK_EQUAL(186, (int)f->GetPixels(pixel_row)[pixel_index]); - CHECK_EQUAL(106, (int)f->GetPixels(pixel_row)[pixel_index + 1]); - CHECK_EQUAL(0, (int)f->GetPixels(pixel_row)[pixel_index + 2]); - CHECK_EQUAL(255, (int)f->GetPixels(pixel_row)[pixel_index + 3]); + CHECK_CLOSE(186, (int)f->GetPixels(pixel_row)[pixel_index], 5); + CHECK_CLOSE(106, (int)f->GetPixels(pixel_row)[pixel_index + 1], 5); + CHECK_CLOSE(0, (int)f->GetPixels(pixel_row)[pixel_index + 2], 5); + CHECK_CLOSE(255, (int)f->GetPixels(pixel_row)[pixel_index + 3], 5); // Get frame f = t.GetFrame(5); // Check image properties - CHECK_EQUAL(23, (int)f->GetPixels(pixel_row)[pixel_index]); - CHECK_EQUAL(190, (int)f->GetPixels(pixel_row)[pixel_index + 1]); - CHECK_EQUAL(0, (int)f->GetPixels(pixel_row)[pixel_index + 2]); - CHECK_EQUAL(255, (int)f->GetPixels(pixel_row)[pixel_index + 3]); + CHECK_CLOSE(23, (int)f->GetPixels(pixel_row)[pixel_index], 5); + CHECK_CLOSE(190, (int)f->GetPixels(pixel_row)[pixel_index + 1], 5); + CHECK_CLOSE(0, (int)f->GetPixels(pixel_row)[pixel_index + 2], 5); + CHECK_CLOSE(255, (int)f->GetPixels(pixel_row)[pixel_index + 3], 5); // Get frame f = t.GetFrame(25); // Check image properties - CHECK_EQUAL(0, (int)f->GetPixels(pixel_row)[pixel_index]); - CHECK_EQUAL(94, (int)f->GetPixels(pixel_row)[pixel_index + 1]); - CHECK_EQUAL(186, (int)f->GetPixels(pixel_row)[pixel_index + 2]); - CHECK_EQUAL(255, (int)f->GetPixels(pixel_row)[pixel_index + 3]); + CHECK_CLOSE(0, (int)f->GetPixels(pixel_row)[pixel_index], 5); + CHECK_CLOSE(94, (int)f->GetPixels(pixel_row)[pixel_index + 1], 5); + CHECK_CLOSE(186, (int)f->GetPixels(pixel_row)[pixel_index + 2], 5); + CHECK_CLOSE(255, (int)f->GetPixels(pixel_row)[pixel_index + 3], 5); // Get frame f = t.GetFrame(4); // Check image properties - CHECK_EQUAL(176, (int)f->GetPixels(pixel_row)[pixel_index]); - CHECK_EQUAL(0, (int)f->GetPixels(pixel_row)[pixel_index + 1]); - CHECK_EQUAL(186, (int)f->GetPixels(pixel_row)[pixel_index + 2]); - CHECK_EQUAL(255, (int)f->GetPixels(pixel_row)[pixel_index + 3]); + CHECK_CLOSE(176, (int)f->GetPixels(pixel_row)[pixel_index], 5); + CHECK_CLOSE(0, (int)f->GetPixels(pixel_row)[pixel_index + 1], 5); + CHECK_CLOSE(186, (int)f->GetPixels(pixel_row)[pixel_index + 2], 5); + CHECK_CLOSE(255, (int)f->GetPixels(pixel_row)[pixel_index + 3], 5); // Close reader t.Close();