From ba4fc5cecf01d3891c2ab1db5fca9229962adf98 Mon Sep 17 00:00:00 2001 From: Daniel Jour Date: Tue, 19 Nov 2019 11:27:17 +0100 Subject: [PATCH 01/45] Enable coverage reporting for openshot-test Uses CodeCoverage.cmake from [1] to build libopenshot with gcov support. Option ENABLE_COVERAGE enables this and sets a target test_coverage which builds and runs openshot-tests and collects coverage information into a html report [1]: https://github.com/bilke/cmake-modules/blob/master/CodeCoverage.cmake --- CMakeLists.txt | 9 + cmake/Modules/CodeCoverage.cmake | 307 +++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 8 + 3 files changed, 324 insertions(+) create mode 100644 cmake/Modules/CodeCoverage.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index acbb3195c..bfaf3af8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,6 +85,15 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_BINARY_DIR}/include) +############## Code Coverage ######################### +option(ENABLE_COVERAGE "Enable coverage reporting." OFF) + +if (ENABLE_COVERAGE) + include(CodeCoverage) + APPEND_COVERAGE_COMPILER_FLAGS() +endif() + + ############## PROCESS src/ DIRECTORIES ############## add_subdirectory(src) diff --git a/cmake/Modules/CodeCoverage.cmake b/cmake/Modules/CodeCoverage.cmake new file mode 100644 index 000000000..f3a8afe7b --- /dev/null +++ b/cmake/Modules/CodeCoverage.cmake @@ -0,0 +1,307 @@ +# Copyright (c) 2012 - 2017, Lars Bilke +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# CHANGES: +# +# 2012-01-31, Lars Bilke +# - Enable Code Coverage +# +# 2013-09-17, Joakim Söderberg +# - Added support for Clang. +# - Some additional usage instructions. +# +# 2016-02-03, Lars Bilke +# - Refactored functions to use named parameters +# +# 2017-06-02, Lars Bilke +# - Merged with modified version from github.com/ufz/ogs +# +# +# USAGE: +# +# 1. Copy this file into your cmake modules path. +# +# 2. Add the following line to your CMakeLists.txt: +# include(CodeCoverage) +# +# 3. Append necessary compiler flags: +# APPEND_COVERAGE_COMPILER_FLAGS() +# +# 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og +# +# 4. If you need to exclude additional directories from the report, specify them +# using the COVERAGE_LCOV_EXCLUDES variable before calling SETUP_TARGET_FOR_COVERAGE_LCOV. +# Example: +# set(COVERAGE_LCOV_EXCLUDES 'dir1/*' 'dir2/*') +# +# 5. Use the functions described below to create a custom make target which +# runs your test executable and produces a code coverage report. +# +# 6. Build a Debug build: +# cmake -DCMAKE_BUILD_TYPE=Debug .. +# make +# make my_coverage_target +# + +include(CMakeParseArguments) + +# Check prereqs +find_program( GCOV_PATH gcov ) +find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl) +find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat ) +find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test) +find_package(Python COMPONENTS Interpreter) + +if(NOT GCOV_PATH) + message(FATAL_ERROR "gcov not found! Aborting...") +endif() # NOT GCOV_PATH + +if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") + if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3) + message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...") + endif() +elseif(NOT CMAKE_COMPILER_IS_GNUCXX) + message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...") +endif() + +set(COVERAGE_COMPILER_FLAGS "-g --coverage -fprofile-arcs -ftest-coverage" + CACHE INTERNAL "") + +set(CMAKE_CXX_FLAGS_COVERAGE + ${COVERAGE_COMPILER_FLAGS} + CACHE STRING "Flags used by the C++ compiler during coverage builds." + FORCE ) +set(CMAKE_C_FLAGS_COVERAGE + ${COVERAGE_COMPILER_FLAGS} + CACHE STRING "Flags used by the C compiler during coverage builds." + FORCE ) +set(CMAKE_EXE_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used for linking binaries during coverage builds." + FORCE ) +set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used by the shared libraries linker during coverage builds." + FORCE ) +mark_as_advanced( + CMAKE_CXX_FLAGS_COVERAGE + CMAKE_C_FLAGS_COVERAGE + CMAKE_EXE_LINKER_FLAGS_COVERAGE + CMAKE_SHARED_LINKER_FLAGS_COVERAGE ) + +if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") + message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading") +endif() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug" + +if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + link_libraries(gcov) +else() + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") +endif() + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# SETUP_TARGET_FOR_COVERAGE_LCOV( +# NAME testrunner_coverage # New target name +# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES testrunner # Dependencies to build first +# ) +function(SETUP_TARGET_FOR_COVERAGE_LCOV) + + set(options NONE) + set(oneValueArgs NAME) + set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT LCOV_PATH) + message(FATAL_ERROR "lcov not found! Aborting...") + endif() # NOT LCOV_PATH + + if(NOT GENHTML_PATH) + message(FATAL_ERROR "genhtml not found! Aborting...") + endif() # NOT GENHTML_PATH + + # Setup target + add_custom_target(${Coverage_NAME} + + # Cleanup lcov + COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -directory . --zerocounters + # Create baseline to make sure untouched files show up in the report + COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -c -i -d . -o ${Coverage_NAME}.base + + # Run tests + COMMAND ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} + + # Capturing lcov counters and generating report + COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . --capture --output-file ${Coverage_NAME}.info + # add baseline counters + COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base -a ${Coverage_NAME}.info --output-file ${Coverage_NAME}.total + COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove ${Coverage_NAME}.total ${COVERAGE_LCOV_EXCLUDES} --output-file ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned + COMMAND ${GENHTML_PATH} ${Coverage_GENHTML_ARGS} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned + COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.base ${Coverage_NAME}.total ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned + + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." + ) + + # Show where to find the lcov info report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info." + ) + + # Show info where to find the report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." + ) + +endfunction() # SETUP_TARGET_FOR_COVERAGE_LCOV + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# SETUP_TARGET_FOR_COVERAGE_GCOVR_XML( +# NAME ctest_coverage # New target name +# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES executable_target # Dependencies to build first +# ) +function(SETUP_TARGET_FOR_COVERAGE_GCOVR_XML) + + set(options NONE) + set(oneValueArgs NAME) + set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT Python_FOUND) + message(FATAL_ERROR "python not found! Aborting...") + endif() + + if(NOT GCOVR_PATH) + message(FATAL_ERROR "gcovr not found! Aborting...") + endif() # NOT GCOVR_PATH + + # Combine excludes to several -e arguments + set(GCOVR_EXCLUDES "") + foreach(EXCLUDE ${COVERAGE_GCOVR_EXCLUDES}) + string(REPLACE "*" "\\*" EXCLUDE_REPLACED ${EXCLUDE}) + list(APPEND GCOVR_EXCLUDES "-e") + list(APPEND GCOVR_EXCLUDES "${EXCLUDE_REPLACED}") + endforeach() + + add_custom_target(${Coverage_NAME} + # Run tests + ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} + + # Running gcovr + COMMAND ${GCOVR_PATH} --xml + -r ${PROJECT_SOURCE_DIR} ${GCOVR_EXCLUDES} + --object-directory=${PROJECT_BINARY_DIR} + -o ${Coverage_NAME}.xml + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + COMMENT "Running gcovr to produce Cobertura code coverage report." + ) + + # Show info where to find the report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml." + ) + +endfunction() # SETUP_TARGET_FOR_COVERAGE_GCOVR_XML + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML( +# NAME ctest_coverage # New target name +# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES executable_target # Dependencies to build first +# ) +function(SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML) + + set(options NONE) + set(oneValueArgs NAME) + set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT Python_FOUND) + message(FATAL_ERROR "python not found! Aborting...") + endif() + + if(NOT GCOVR_PATH) + message(FATAL_ERROR "gcovr not found! Aborting...") + endif() # NOT GCOVR_PATH + + # Combine excludes to several -e arguments + set(GCOVR_EXCLUDES "") + foreach(EXCLUDE ${COVERAGE_GCOVR_EXCLUDES}) + string(REPLACE "*" "\\*" EXCLUDE_REPLACED ${EXCLUDE}) + list(APPEND GCOVR_EXCLUDES "-e") + list(APPEND GCOVR_EXCLUDES "${EXCLUDE_REPLACED}") + endforeach() + + add_custom_target(${Coverage_NAME} + # Run tests + ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} + + # Create folder + COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/${Coverage_NAME} + + # Running gcovr + COMMAND ${Python_EXECUTABLE} ${GCOVR_PATH} --html --html-details + -r ${PROJECT_SOURCE_DIR} ${GCOVR_EXCLUDES} + --object-directory=${PROJECT_BINARY_DIR} + -o ${Coverage_NAME}/index.html + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + COMMENT "Running gcovr to produce HTML code coverage report." + ) + + # Show info where to find the report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." + ) + +endfunction() # SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML + +function(APPEND_COVERAGE_COMPILER_FLAGS) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) + message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}") +endfunction() # APPEND_COVERAGE_COMPILER_FLAGS diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a104d766a..855694a74 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -151,3 +151,11 @@ endif() string(CONCAT t ${OS_TEST_CMDS}) message("\nTo run unit tests, use: ${t}") + +if (ENABLE_COVERAGE) + setup_target_for_coverage_lcov( + NAME test_coverage + EXECUTABLE openshot-test + DEPENDENCIES openshot-test) +endif() + From 7b7f2cc574e238aef779da548c1ccbb870d1e85b Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 7 Dec 2019 13:01:55 -0500 Subject: [PATCH 02/45] Move feature summary to root CMakeLists --- CMakeLists.txt | 15 +++++++++++++++ src/CMakeLists.txt | 12 ------------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5cfb678c9..574ff8bbc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,6 +66,15 @@ Generating build files for OpenShot with CMake ${CMAKE_VERSION} # in order to properly configure CMAKE_INSTALL_LIBDIR path include(GNUInstallDirs) +# Collect and display summary of options/dependencies +include(FeatureSummary) + +################ OPTIONS ################## +# Optional build settings for libopenshot +option(USE_SYSTEM_JSONCPP "Use system installed JsonCpp, if found" ON) +option(DISABLE_BUNDLED_JSONCPP "Don't fall back to bundled JsonCpp" OFF) +option(ENABLE_IWYU "Enable 'Include What You Use' scanner (CMake 3.3+)" OFF) + ########## Configure Version.h header ############## configure_file(include/OpenShotVersion.h.in include/OpenShotVersion.h @ONLY) # We'll want that installed later @@ -111,3 +120,9 @@ endif() if(NOT DISABLE_TESTS) add_subdirectory(tests) endif() + +########### PRINT FEATURE SUMMARY ############## +feature_summary(WHAT ALL + INCLUDE_QUIET_PACKAGES + FATAL_ON_MISSING_REQUIRED_PACKAGES + DESCRIPTION "Displaying feature summary\n\nBuild configuration:") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fd61ef509..b684aaec6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,12 +27,6 @@ # Collect and display summary of options/dependencies include(FeatureSummary) -################ OPTIONS ################## -# Optional build settings for libopenshot -option(USE_SYSTEM_JSONCPP "Use system installed JsonCpp, if found" ON) -option(DISABLE_BUNDLED_JSONCPP "Don't fall back to bundled JsonCpp" OFF) -option(ENABLE_IWYU "Enable 'Include What You Use' scanner (CMake 3.3+)" OFF) - # Automatically process Qt classes with meta-object compiler set(CMAKE_AUTOMOC True) @@ -426,12 +420,6 @@ ENDIF (BLACKMAGIC_FOUND) ############### INCLUDE SWIG BINDINGS ################ add_subdirectory(bindings) -########### PRINT FEATURE SUMMARY ############## -feature_summary(WHAT ALL - INCLUDE_QUIET_PACKAGES - FATAL_ON_MISSING_REQUIRED_PACKAGES - DESCRIPTION "Displaying feature summary\n\nBuild configuration:") - ############### INSTALL HEADERS & LIBRARY ################ set(LIB_INSTALL_DIR lib${LIB_SUFFIX}) # determine correct lib folder From b4682ac3d76c85a1f0c2cc6dcba12664d210524d Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 7 Dec 2019 13:40:43 -0500 Subject: [PATCH 03/45] Move coverage to root CMakeLists, add more tooling --- CMakeLists.txt | 22 ++++++++++++++++++++-- tests/CMakeLists.txt | 8 -------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 413da3212..af2010df4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,7 +73,9 @@ include(FeatureSummary) # Optional build settings for libopenshot option(USE_SYSTEM_JSONCPP "Use system installed JsonCpp, if found" ON) option(DISABLE_BUNDLED_JSONCPP "Don't fall back to bundled JsonCpp" OFF) +option(DISABLE_TESTS "Don't build unit tests" OFF) option(ENABLE_IWYU "Enable 'Include What You Use' scanner (CMake 3.3+)" OFF) +option(ENABLE_COVERAGE "Enable coverage reporting" OFF) ########## Configure Version.h header ############## configure_file(include/OpenShotVersion.h.in include/OpenShotVersion.h @ONLY) @@ -95,13 +97,20 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR}/include) ############## Code Coverage ######################### -option(ENABLE_COVERAGE "Enable coverage reporting." OFF) +if (DISABLE_TESTS AND ENABLE_COVERAGE) + message(WARNING "ENABLE_COVERAGE requires tests, overriding DISABLE_TESTS") + set(DISABLE_TESTS OFF CACHE BOOL "Don't build unit tests" FORCE) +endif() if (ENABLE_COVERAGE) + if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Debug") + message(STATUS "Coverage enabled, setting build type to Debug") + endif() include(CodeCoverage) APPEND_COVERAGE_COMPILER_FLAGS() endif() - +add_feature_info("Coverage" ENABLE_COVERAGE "analyze test coverage and generate report") ############## PROCESS src/ DIRECTORIES ############## add_subdirectory(src) @@ -130,6 +139,15 @@ if(NOT DISABLE_TESTS) add_subdirectory(tests) endif() +############## COVERAGE REPORTING ################# +if (ENABLE_COVERAGE) + setup_target_for_coverage_lcov( + NAME coverage + EXECUTABLE openshot-test + DEPENDENCIES openshot-test) + message("Generate coverage report with 'make coverage'") +endif() + ########### PRINT FEATURE SUMMARY ############## feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 855694a74..a104d766a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -151,11 +151,3 @@ endif() string(CONCAT t ${OS_TEST_CMDS}) message("\nTo run unit tests, use: ${t}") - -if (ENABLE_COVERAGE) - setup_target_for_coverage_lcov( - NAME test_coverage - EXECUTABLE openshot-test - DEPENDENCIES openshot-test) -endif() - From 70bf3df41d3291e6a56afae8311e8c6a18a96378 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 7 Dec 2019 13:45:28 -0500 Subject: [PATCH 04/45] CodeCoverage.cmake: Add demangling, cleanup --- cmake/Modules/CodeCoverage.cmake | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/cmake/Modules/CodeCoverage.cmake b/cmake/Modules/CodeCoverage.cmake index f3a8afe7b..ff043ee08 100644 --- a/cmake/Modules/CodeCoverage.cmake +++ b/cmake/Modules/CodeCoverage.cmake @@ -75,7 +75,8 @@ find_program( GCOV_PATH gcov ) find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl) find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat ) find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test) -find_package(Python COMPONENTS Interpreter) +find_package( Python COMPONENTS Interpreter ) +find_program( CPPFILT_PATH NAMES c++filt ) if(NOT GCOV_PATH) message(FATAL_ERROR "gcov not found! Aborting...") @@ -149,6 +150,9 @@ function(SETUP_TARGET_FOR_COVERAGE_LCOV) message(FATAL_ERROR "genhtml not found! Aborting...") endif() # NOT GENHTML_PATH + # Conditional arguments + set(GENHTML_ARGS $<$:"--demangle-cpp">) + # Setup target add_custom_target(${Coverage_NAME} @@ -165,8 +169,12 @@ function(SETUP_TARGET_FOR_COVERAGE_LCOV) # add baseline counters COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base -a ${Coverage_NAME}.info --output-file ${Coverage_NAME}.total COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove ${Coverage_NAME}.total ${COVERAGE_LCOV_EXCLUDES} --output-file ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned - COMMAND ${GENHTML_PATH} ${Coverage_GENHTML_ARGS} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned + + # Generate HTML output + COMMAND ${GENHTML_PATH} ${GENHTML_ARGS} ${Coverage_GENHTML_ARGS} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned + COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.base ${Coverage_NAME}.total ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned + BYPRODUCTS ${Coverage_NAME}.info WORKING_DIRECTORY ${PROJECT_BINARY_DIR} DEPENDS ${Coverage_DEPENDENCIES} @@ -185,6 +193,11 @@ function(SETUP_TARGET_FOR_COVERAGE_LCOV) COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." ) + # Clean up output on 'make clean' + set_property(DIRECTORY APPEND PROPERTY + ADDITIONAL_MAKE_CLEAN_FILES + ${Coverage_NAME}) + endfunction() # SETUP_TARGET_FOR_COVERAGE_LCOV # Defines a target for running and collection code coverage information @@ -240,6 +253,11 @@ function(SETUP_TARGET_FOR_COVERAGE_GCOVR_XML) COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml." ) + # Clean up output on 'make clean' + set_property(DIRECTORY APPEND PROPERTY + ADDITIONAL_MAKE_CLEAN_FILES + ${Coverage_NAME}) + endfunction() # SETUP_TARGET_FOR_COVERAGE_GCOVR_XML # Defines a target for running and collection code coverage information @@ -283,7 +301,7 @@ function(SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML) COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/${Coverage_NAME} # Running gcovr - COMMAND ${Python_EXECUTABLE} ${GCOVR_PATH} --html --html-details + COMMAND ${GCOVR_PATH} --html --html-details -r ${PROJECT_SOURCE_DIR} ${GCOVR_EXCLUDES} --object-directory=${PROJECT_BINARY_DIR} -o ${Coverage_NAME}/index.html @@ -298,6 +316,11 @@ function(SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML) COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." ) + # Clean up output on 'make clean' + set_property(DIRECTORY APPEND PROPERTY + ADDITIONAL_MAKE_CLEAN_FILES + ${Coverage_NAME}) + endfunction() # SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML function(APPEND_COVERAGE_COMPILER_FLAGS) From ab3aef4564a761b766826a174a17b3d25675abf6 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 7 Dec 2019 14:31:15 -0500 Subject: [PATCH 05/45] Set lcov base directory to PROJECT_SOURCE_DIR --- cmake/Modules/CodeCoverage.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/Modules/CodeCoverage.cmake b/cmake/Modules/CodeCoverage.cmake index ff043ee08..11c410ac9 100644 --- a/cmake/Modules/CodeCoverage.cmake +++ b/cmake/Modules/CodeCoverage.cmake @@ -157,15 +157,15 @@ function(SETUP_TARGET_FOR_COVERAGE_LCOV) add_custom_target(${Coverage_NAME} # Cleanup lcov - COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -directory . --zerocounters + COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -directory . -b ${PROJECT_SOURCE_DIR} --zerocounters # Create baseline to make sure untouched files show up in the report - COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -c -i -d . -o ${Coverage_NAME}.base + COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -c -i -d . -b ${PROJECT_SOURCE_DIR} -o ${Coverage_NAME}.base # Run tests COMMAND ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} # Capturing lcov counters and generating report - COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . --capture --output-file ${Coverage_NAME}.info + COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . -b ${PROJECT_SOURCE_DIR} --capture --output-file ${Coverage_NAME}.info # add baseline counters COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base -a ${Coverage_NAME}.info --output-file ${Coverage_NAME}.total COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove ${Coverage_NAME}.total ${COVERAGE_LCOV_EXCLUDES} --output-file ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned From a2513823d571d4f40c6c37abdf40eb0b12f21d7d Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 7 Dec 2019 17:05:01 -0500 Subject: [PATCH 06/45] Remove Python detection from CodeCoverage --- cmake/Modules/CodeCoverage.cmake | 9 --------- 1 file changed, 9 deletions(-) diff --git a/cmake/Modules/CodeCoverage.cmake b/cmake/Modules/CodeCoverage.cmake index 11c410ac9..8555ed01a 100644 --- a/cmake/Modules/CodeCoverage.cmake +++ b/cmake/Modules/CodeCoverage.cmake @@ -75,7 +75,6 @@ find_program( GCOV_PATH gcov ) find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl) find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat ) find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test) -find_package( Python COMPONENTS Interpreter ) find_program( CPPFILT_PATH NAMES c++filt ) if(NOT GCOV_PATH) @@ -217,10 +216,6 @@ function(SETUP_TARGET_FOR_COVERAGE_GCOVR_XML) set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - if(NOT Python_FOUND) - message(FATAL_ERROR "python not found! Aborting...") - endif() - if(NOT GCOVR_PATH) message(FATAL_ERROR "gcovr not found! Aborting...") endif() # NOT GCOVR_PATH @@ -277,10 +272,6 @@ function(SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML) set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - if(NOT Python_FOUND) - message(FATAL_ERROR "python not found! Aborting...") - endif() - if(NOT GCOVR_PATH) message(FATAL_ERROR "gcovr not found! Aborting...") endif() # NOT GCOVR_PATH From 0710ecc1683c4826dc3038f05c795c4e9900d3f8 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Tue, 10 Dec 2019 15:31:45 -0500 Subject: [PATCH 07/45] Fix demangling Generator expressions don't work in set(), or in the COMMAND arg to add_custom_target(). --- cmake/Modules/CodeCoverage.cmake | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmake/Modules/CodeCoverage.cmake b/cmake/Modules/CodeCoverage.cmake index 8555ed01a..f497700ba 100644 --- a/cmake/Modules/CodeCoverage.cmake +++ b/cmake/Modules/CodeCoverage.cmake @@ -150,7 +150,9 @@ function(SETUP_TARGET_FOR_COVERAGE_LCOV) endif() # NOT GENHTML_PATH # Conditional arguments - set(GENHTML_ARGS $<$:"--demangle-cpp">) + if(CPPFILT_PATH) + set(GENHTML_EXTRA_ARGS "--demangle-cpp") + endif() # Setup target add_custom_target(${Coverage_NAME} @@ -170,7 +172,7 @@ function(SETUP_TARGET_FOR_COVERAGE_LCOV) COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove ${Coverage_NAME}.total ${COVERAGE_LCOV_EXCLUDES} --output-file ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned # Generate HTML output - COMMAND ${GENHTML_PATH} ${GENHTML_ARGS} ${Coverage_GENHTML_ARGS} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned + COMMAND ${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.base ${Coverage_NAME}.total ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned BYPRODUCTS ${Coverage_NAME}.info From a697bda9c5e56732cb33ee06f0d8440dd658ebc8 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 14 Dec 2019 20:20:55 -0500 Subject: [PATCH 08/45] Use full paths in COVERAGE_LCOV_EXCLUDES examples --- cmake/Modules/CodeCoverage.cmake | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmake/Modules/CodeCoverage.cmake b/cmake/Modules/CodeCoverage.cmake index f497700ba..155235cd3 100644 --- a/cmake/Modules/CodeCoverage.cmake +++ b/cmake/Modules/CodeCoverage.cmake @@ -55,9 +55,10 @@ # 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og # # 4. If you need to exclude additional directories from the report, specify them -# using the COVERAGE_LCOV_EXCLUDES variable before calling SETUP_TARGET_FOR_COVERAGE_LCOV. +# using full paths in the COVERAGE_LCOV_EXCLUDES variable before calling +# setup_target_for_coverage_lcov(). # Example: -# set(COVERAGE_LCOV_EXCLUDES 'dir1/*' 'dir2/*') +# set(COVERAGE_LCOV_EXCLUDES '${PROJECT_SOURCE_DIR}/dir1/*' '/path/to/my/dir2/*') # # 5. Use the functions described below to create a custom make target which # runs your test executable and produces a code coverage report. From 66febac6b1a68569705dfb9e77f5327dac2b783c Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 14 Dec 2019 20:21:50 -0500 Subject: [PATCH 09/45] Lowercase function names, add change comment --- cmake/Modules/CodeCoverage.cmake | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/cmake/Modules/CodeCoverage.cmake b/cmake/Modules/CodeCoverage.cmake index 155235cd3..4cf9c26be 100644 --- a/cmake/Modules/CodeCoverage.cmake +++ b/cmake/Modules/CodeCoverage.cmake @@ -42,6 +42,13 @@ # - Merged with modified version from github.com/ufz/ogs # # +# 2019-12-10, FeRD (Frank Dana) +# - Set PROJECT_SOURCE_DIR as lcov basedir with -b argument +# - Add automatic --demangle-cpp if 'c++filt' is available +# - Remove Python detection, since version mismatches will break gcovr +# - Remove output dir, .info file on 'make clean' +# - Minor cleanup (lowercase function names, update excludes example...) +# # USAGE: # # 1. Copy this file into your cmake modules path. @@ -50,7 +57,7 @@ # include(CodeCoverage) # # 3. Append necessary compiler flags: -# APPEND_COVERAGE_COMPILER_FLAGS() +# append_coverage_compiler_flags() # # 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og # @@ -130,12 +137,12 @@ endif() # NOTE! The executable should always have a ZERO as exit code otherwise # the coverage generation will not complete. # -# SETUP_TARGET_FOR_COVERAGE_LCOV( +# setup_target_for_coverage_lcov( # NAME testrunner_coverage # New target name # EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR # DEPENDENCIES testrunner # Dependencies to build first # ) -function(SETUP_TARGET_FOR_COVERAGE_LCOV) +function(setup_target_for_coverage_lcov) set(options NONE) set(oneValueArgs NAME) @@ -200,19 +207,19 @@ function(SETUP_TARGET_FOR_COVERAGE_LCOV) ADDITIONAL_MAKE_CLEAN_FILES ${Coverage_NAME}) -endfunction() # SETUP_TARGET_FOR_COVERAGE_LCOV +endfunction() # setup_target_for_coverage_lcov # Defines a target for running and collection code coverage information # Builds dependencies, runs the given executable and outputs reports. # NOTE! The executable should always have a ZERO as exit code otherwise # the coverage generation will not complete. # -# SETUP_TARGET_FOR_COVERAGE_GCOVR_XML( +# setup_target_for_coverage_gcovr_xml( # NAME ctest_coverage # New target name # EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR # DEPENDENCIES executable_target # Dependencies to build first # ) -function(SETUP_TARGET_FOR_COVERAGE_GCOVR_XML) +function(setup_target_for_coverage_gcovr_xml) set(options NONE) set(oneValueArgs NAME) @@ -256,19 +263,19 @@ function(SETUP_TARGET_FOR_COVERAGE_GCOVR_XML) ADDITIONAL_MAKE_CLEAN_FILES ${Coverage_NAME}) -endfunction() # SETUP_TARGET_FOR_COVERAGE_GCOVR_XML +endfunction() # setup_target_for_coverage_gcovr_xml # Defines a target for running and collection code coverage information # Builds dependencies, runs the given executable and outputs reports. # NOTE! The executable should always have a ZERO as exit code otherwise # the coverage generation will not complete. # -# SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML( +# setup_target_for_coverage_gcovr_html( # NAME ctest_coverage # New target name # EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR # DEPENDENCIES executable_target # Dependencies to build first # ) -function(SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML) +function(setup_target_for_coverage_gcovr_html) set(options NONE) set(oneValueArgs NAME) @@ -315,10 +322,10 @@ function(SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML) ADDITIONAL_MAKE_CLEAN_FILES ${Coverage_NAME}) -endfunction() # SETUP_TARGET_FOR_COVERAGE_GCOVR_HTML +endfunction() # setup_target_for_coverage_gcovr_html -function(APPEND_COVERAGE_COMPILER_FLAGS) +function(append_coverage_compiler_flags) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}") -endfunction() # APPEND_COVERAGE_COMPILER_FLAGS +endfunction() # append_coverage_compiler_flags From 14dc2b38e270b16b1cbb5e4ef9c47b1261a3cf0e Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 14 Dec 2019 20:23:19 -0500 Subject: [PATCH 10/45] CodeCoverage: Import upstream changes --- cmake/Modules/CodeCoverage.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/Modules/CodeCoverage.cmake b/cmake/Modules/CodeCoverage.cmake index 4cf9c26be..6363ef96a 100644 --- a/cmake/Modules/CodeCoverage.cmake +++ b/cmake/Modules/CodeCoverage.cmake @@ -41,6 +41,8 @@ # 2017-06-02, Lars Bilke # - Merged with modified version from github.com/ufz/ogs # +# 2019-05-06, Anatolii Kurotych +# - Remove unnecessary --coverage flag # # 2019-12-10, FeRD (Frank Dana) # - Set PROJECT_SOURCE_DIR as lcov basedir with -b argument @@ -97,7 +99,7 @@ elseif(NOT CMAKE_COMPILER_IS_GNUCXX) message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...") endif() -set(COVERAGE_COMPILER_FLAGS "-g --coverage -fprofile-arcs -ftest-coverage" +set(COVERAGE_COMPILER_FLAGS "-g -fprofile-arcs -ftest-coverage" CACHE INTERNAL "") set(CMAKE_CXX_FLAGS_COVERAGE @@ -128,8 +130,6 @@ endif() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug" if(CMAKE_C_COMPILER_ID STREQUAL "GNU") link_libraries(gcov) -else() - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") endif() # Defines a target for running and collection code coverage information From 1df984070596e32869c19cf974d775fdc7f2498f Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sun, 15 Dec 2019 01:12:07 -0500 Subject: [PATCH 11/45] Import CodeCoverage changes --- cmake/Modules/CodeCoverage.cmake | 148 ++++++++++++++++++++++++------- 1 file changed, 118 insertions(+), 30 deletions(-) diff --git a/cmake/Modules/CodeCoverage.cmake b/cmake/Modules/CodeCoverage.cmake index 6363ef96a..0353948a1 100644 --- a/cmake/Modules/CodeCoverage.cmake +++ b/cmake/Modules/CodeCoverage.cmake @@ -44,12 +44,17 @@ # 2019-05-06, Anatolii Kurotych # - Remove unnecessary --coverage flag # -# 2019-12-10, FeRD (Frank Dana) -# - Set PROJECT_SOURCE_DIR as lcov basedir with -b argument -# - Add automatic --demangle-cpp if 'c++filt' is available +# 2019-12-13, FeRD (Frank Dana) +# - Deprecate COVERAGE_LCOVR_EXCLUDES and COVERAGE_GCOVR_EXCLUDES lists in favor +# of tool-agnostic COVERAGE_EXCLUDES variable, or EXCLUDE setup arguments. +# - CMake 3.4+: All excludes can be specified relative to BASE_DIRECTORY +# - All setup functions: accept BASE_DIRECTORY, EXCLUDE list +# - Set lcov basedir with -b argument +# - Add automatic --demangle-cpp in lcovr, if 'c++filt' is available (can be +# overridden with NO_DEMANGLE option in setup_target_for_coverage_lcovr().) +# - Delete output dir, .info file on 'make clean' # - Remove Python detection, since version mismatches will break gcovr -# - Remove output dir, .info file on 'make clean' -# - Minor cleanup (lowercase function names, update excludes example...) +# - Minor cleanup (lowercase function names, update examples...) # # USAGE: # @@ -64,10 +69,28 @@ # 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og # # 4. If you need to exclude additional directories from the report, specify them -# using full paths in the COVERAGE_LCOV_EXCLUDES variable before calling -# setup_target_for_coverage_lcov(). +# using full paths in the COVERAGE_EXCLUDES variable before calling +# setup_target_for_coverage_*(). # Example: -# set(COVERAGE_LCOV_EXCLUDES '${PROJECT_SOURCE_DIR}/dir1/*' '/path/to/my/dir2/*') +# set(COVERAGE_EXCLUDES +# '${PROJECT_SOURCE_DIR}/src/dir1/*' +# '/path/to/my/src/dir2/*') +# Or, use the EXCLUDE argument to setup_target_for_coverage_*(). +# Example: +# setup_target_for_coverage_lcov( +# NAME coverage +# EXECUTABLE testrunner +# EXCLUDE "${PROJECT_SOURCE_DIR}/src/dir1/*" "/path/to/my/src/dir2/*") +# +# 4.a NOTE: With CMake 3.4+, COVERAGE_EXCLUDES or EXCLUDE can also be set +# relative to the BASE_DIRECTORY (default: PROJECT_SOURCE_DIR) +# Example: +# set(COVERAGE_EXCLUDES "dir1/*") +# setup_target_for_coverage_gcovr_html( +# NAME coverage +# EXECUTABLE testrunner +# BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src" +# EXCLUDE "dir2/*") # # 5. Use the functions described below to create a custom make target which # runs your test executable and produces a code coverage report. @@ -141,12 +164,18 @@ endif() # NAME testrunner_coverage # New target name # EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR # DEPENDENCIES testrunner # Dependencies to build first +# BASE_DIRECTORY "../" # Base directory for report +# # (defaults to PROJECT_SOURCE_DIR) +# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative +# # to BASE_DIRECTORY, with CMake 3.4+) +# NO_DEMANGLE # Don't demangle C++ symbols +# # even if c++filt is found # ) function(setup_target_for_coverage_lcov) - set(options NONE) - set(oneValueArgs NAME) - set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS) + set(options NO_DEMANGLE) + set(oneValueArgs BASE_DIRECTORY NAME) + set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS) cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if(NOT LCOV_PATH) @@ -157,8 +186,25 @@ function(setup_target_for_coverage_lcov) message(FATAL_ERROR "genhtml not found! Aborting...") endif() # NOT GENHTML_PATH + # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR + if(${Coverage_BASE_DIRECTORY}) + get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE) + else() + set(BASEDIR ${PROJECT_SOURCE_DIR}) + endif() + + # Collect excludes (CMake 3.4+: Also compute absolute paths) + set(LCOV_EXCLUDES "") + foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_LCOV_EXCLUDES}) + if(CMAKE_VERSION VERSION_GREATER 3.4) + get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR}) + endif() + list(APPEND LCOV_EXCLUDES "${EXCLUDE}") + endforeach() + list(REMOVE_DUPLICATES LCOV_EXCLUDES) + # Conditional arguments - if(CPPFILT_PATH) + if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE}) set(GENHTML_EXTRA_ARGS "--demangle-cpp") endif() @@ -166,18 +212,18 @@ function(setup_target_for_coverage_lcov) add_custom_target(${Coverage_NAME} # Cleanup lcov - COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -directory . -b ${PROJECT_SOURCE_DIR} --zerocounters + COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -directory . -b ${BASEDIR} --zerocounters # Create baseline to make sure untouched files show up in the report - COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -c -i -d . -b ${PROJECT_SOURCE_DIR} -o ${Coverage_NAME}.base + COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -c -i -d . -b ${BASEDIR} -o ${Coverage_NAME}.base # Run tests COMMAND ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} # Capturing lcov counters and generating report - COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . -b ${PROJECT_SOURCE_DIR} --capture --output-file ${Coverage_NAME}.info + COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . -b ${BASEDIR} --capture --output-file ${Coverage_NAME}.info # add baseline counters COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base -a ${Coverage_NAME}.info --output-file ${Coverage_NAME}.total - COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove ${Coverage_NAME}.total ${COVERAGE_LCOV_EXCLUDES} --output-file ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned + COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove ${Coverage_NAME}.total ${LCOV_EXCLUDES} --output-file ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned # Generate HTML output COMMAND ${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned @@ -218,24 +264,45 @@ endfunction() # setup_target_for_coverage_lcov # NAME ctest_coverage # New target name # EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR # DEPENDENCIES executable_target # Dependencies to build first +# BASE_DIRECTORY "../" # Base directory for report +# # (defaults to PROJECT_SOURCE_DIR) +# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative +# # to BASE_DIRECTORY, with CMake 3.4+) # ) function(setup_target_for_coverage_gcovr_xml) set(options NONE) - set(oneValueArgs NAME) - set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) + set(oneValueArgs BASE_DIRECTORY NAME) + set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if(NOT GCOVR_PATH) message(FATAL_ERROR "gcovr not found! Aborting...") endif() # NOT GCOVR_PATH - # Combine excludes to several -e arguments + # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR + if(${Coverage_BASE_DIRECTORY}) + get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE) + else() + set(BASEDIR ${PROJECT_SOURCE_DIR}) + endif() + + # Collect excludes (CMake 3.4+: Also compute absolute paths) set(GCOVR_EXCLUDES "") - foreach(EXCLUDE ${COVERAGE_GCOVR_EXCLUDES}) + foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES}) + if(CMAKE_VERSION VERSION_GREATER 3.4) + get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR}) + endif() + list(APPEND GCOVR_EXCLUDES "${EXCLUDE}") + endforeach() + list(REMOVE_DUPLICATES GCOVR_EXCLUDES) + + # Combine excludes to several -e arguments + set(GCOVR_EXCLUDE_ARGS "") + foreach(EXCLUDE ${GCOVR_EXCLUDES}) string(REPLACE "*" "\\*" EXCLUDE_REPLACED ${EXCLUDE}) - list(APPEND GCOVR_EXCLUDES "-e") - list(APPEND GCOVR_EXCLUDES "${EXCLUDE_REPLACED}") + list(APPEND GCOVR_EXCLUDE_ARGS "-e") + list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE_REPLACED}") endforeach() add_custom_target(${Coverage_NAME} @@ -244,7 +311,7 @@ function(setup_target_for_coverage_gcovr_xml) # Running gcovr COMMAND ${GCOVR_PATH} --xml - -r ${PROJECT_SOURCE_DIR} ${GCOVR_EXCLUDES} + -r ${BASEDIR} ${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR} -o ${Coverage_NAME}.xml WORKING_DIRECTORY ${PROJECT_BINARY_DIR} @@ -274,24 +341,45 @@ endfunction() # setup_target_for_coverage_gcovr_xml # NAME ctest_coverage # New target name # EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR # DEPENDENCIES executable_target # Dependencies to build first +# BASE_DIRECTORY "../" # Base directory for report +# # (defaults to PROJECT_SOURCE_DIR) +# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative +# # to BASE_DIRECTORY, with CMake 3.4+) # ) function(setup_target_for_coverage_gcovr_html) set(options NONE) - set(oneValueArgs NAME) - set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) + set(oneValueArgs BASE_DIRECTORY NAME) + set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if(NOT GCOVR_PATH) message(FATAL_ERROR "gcovr not found! Aborting...") endif() # NOT GCOVR_PATH - # Combine excludes to several -e arguments + # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR + if(${Coverage_BASE_DIRECTORY}) + get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE) + else() + set(BASEDIR ${PROJECT_SOURCE_DIR}) + endif() + + # Collect excludes (CMake 3.4+: Also compute absolute paths) set(GCOVR_EXCLUDES "") - foreach(EXCLUDE ${COVERAGE_GCOVR_EXCLUDES}) + foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES}) + if(CMAKE_VERSION VERSION_GREATER 3.4) + get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR}) + endif() + list(APPEND GCOVR_EXCLUDES "${EXCLUDE}") + endforeach() + list(REMOVE_DUPLICATES GCOVR_EXCLUDES) + + # Combine excludes to several -e arguments + set(GCOVR_EXCLUDE_ARGS "") + foreach(EXCLUDE ${GCOVR_EXCLUDES}) string(REPLACE "*" "\\*" EXCLUDE_REPLACED ${EXCLUDE}) - list(APPEND GCOVR_EXCLUDES "-e") - list(APPEND GCOVR_EXCLUDES "${EXCLUDE_REPLACED}") + list(APPEND GCOVR_EXCLUDE_ARGS "-e") + list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE_REPLACED}") endforeach() add_custom_target(${Coverage_NAME} @@ -303,7 +391,7 @@ function(setup_target_for_coverage_gcovr_html) # Running gcovr COMMAND ${GCOVR_PATH} --html --html-details - -r ${PROJECT_SOURCE_DIR} ${GCOVR_EXCLUDES} + -r ${BASEDIR} ${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR} -o ${Coverage_NAME}/index.html WORKING_DIRECTORY ${PROJECT_BINARY_DIR} From bd4d2bfdc4b9b33340e24b5c007c0067343ed83f Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sun, 15 Dec 2019 07:14:01 -0500 Subject: [PATCH 12/45] Cover all values in switch(enum_type) --- src/FFmpegReader.cpp | 11 +++++--- src/FFmpegWriter.cpp | 4 +++ src/Timeline.cpp | 66 +++++++++++++++++++++++++------------------- 3 files changed, 49 insertions(+), 32 deletions(-) diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index e8ac4af91..2bd5c53f6 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -191,10 +191,10 @@ static enum AVPixelFormat get_hw_dec_format(AVCodecContext *ctx, const enum AVPi #if defined(__APPLE__) // Apple pix formats case AV_PIX_FMT_VIDEOTOOLBOX: - hw_de_av_pix_fmt_global = AV_PIX_FMT_VIDEOTOOLBOX; - hw_de_av_device_type_global = AV_HWDEVICE_TYPE_VIDEOTOOLBOX; - return *p; - break; + hw_de_av_pix_fmt_global = AV_PIX_FMT_VIDEOTOOLBOX; + hw_de_av_device_type_global = AV_HWDEVICE_TYPE_VIDEOTOOLBOX; + return *p; + break; #endif // Cross-platform pix formats case AV_PIX_FMT_CUDA: @@ -207,6 +207,9 @@ static enum AVPixelFormat get_hw_dec_format(AVCodecContext *ctx, const enum AVPi hw_de_av_device_type_global = AV_HWDEVICE_TYPE_QSV; return *p; break; + default: + // This is only here to silence unused-enum warnings + break; } } ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::get_hw_dec_format (Unable to decode this file using hardware decode)"); diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 645c0cca4..47652854d 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -1563,6 +1563,10 @@ void FFmpegWriter::write_audio_packets(bool is_final) { output_sample_fmt = AV_SAMPLE_FMT_U8; break; } + default: { + // This is only here to silence unused-enum warnings + break; + } } // Update total samples & input frame size (due to bigger or smaller data types) diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 86ef2911f..2decf26c6 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -466,34 +466,37 @@ void Timeline::add_layer(std::shared_ptr new_frame, Clip* source_clip, in float crop_h = source_clip->crop_height.GetValue(clip_frame_number); switch(source_clip->crop_gravity) { - case (GRAVITY_TOP): - crop_x += 0.5; - break; - case (GRAVITY_TOP_RIGHT): - crop_x += 1.0; - break; - case (GRAVITY_LEFT): - crop_y += 0.5; - break; - case (GRAVITY_CENTER): - crop_x += 0.5; - crop_y += 0.5; - break; - case (GRAVITY_RIGHT): - crop_x += 1.0; - crop_y += 0.5; - break; - case (GRAVITY_BOTTOM_LEFT): - crop_y += 1.0; - break; - case (GRAVITY_BOTTOM): - crop_x += 0.5; - crop_y += 1.0; - break; - case (GRAVITY_BOTTOM_RIGHT): - crop_x += 1.0; - crop_y += 1.0; - break; + case (GRAVITY_TOP_LEFT): + // This is only here to prevent unused-enum warnings + break; + case (GRAVITY_TOP): + crop_x += 0.5; + break; + case (GRAVITY_TOP_RIGHT): + crop_x += 1.0; + break; + case (GRAVITY_LEFT): + crop_y += 0.5; + break; + case (GRAVITY_CENTER): + crop_x += 0.5; + crop_y += 0.5; + break; + case (GRAVITY_RIGHT): + crop_x += 1.0; + crop_y += 0.5; + break; + case (GRAVITY_BOTTOM_LEFT): + crop_y += 1.0; + break; + case (GRAVITY_BOTTOM): + crop_x += 0.5; + crop_y += 1.0; + break; + case (GRAVITY_BOTTOM_RIGHT): + crop_x += 1.0; + crop_y += 1.0; + break; } @@ -509,6 +512,9 @@ void Timeline::add_layer(std::shared_ptr new_frame, Clip* source_clip, in switch (source_clip->gravity) { + case (GRAVITY_TOP_LEFT): + // This is only here to prevent unused-enum warnings + break; case (GRAVITY_TOP): x = (Settings::Instance()->MAX_WIDTH - scaled_source_width) / 2.0; // center break; @@ -611,6 +617,10 @@ void Timeline::add_layer(std::shared_ptr new_frame, Clip* source_clip, in std::stringstream frame_number_str; switch (source_clip->display) { + case (FRAME_DISPLAY_NONE): + // This is only here to prevent unused-enum warnings + break; + case (FRAME_DISPLAY_CLIP): frame_number_str << clip_frame_number; break; From e502f97d8aff6eda7ae6c4d5438c4d854afb0674 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sun, 15 Dec 2019 14:22:59 -0500 Subject: [PATCH 13/45] Don't compare differently-signed types --- src/Clip.cpp | 2 +- src/FFmpegWriter.cpp | 4 ++-- src/FrameMapper.cpp | 4 ++-- src/KeyFrame.cpp | 16 ++++++++-------- src/Timeline.cpp | 16 ++++++++-------- src/effects/Wave.cpp | 2 +- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/Clip.cpp b/src/Clip.cpp index 45afd2aa5..985df0158 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -905,7 +905,7 @@ void Clip::SetJsonValue(Json::Value root) { effects.clear(); // loop through effects - for (int x = 0; x < root["effects"].size(); x++) { + for (Json::Value::ArrayIndex x = 0; x < root["effects"].size(); x++) { // Get each effect Json::Value existing_effect = root["effects"][x]; diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 645c0cca4..4a7a0acb4 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -615,7 +615,7 @@ void FFmpegWriter::WriteFrame(std::shared_ptr frame) { ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::WriteFrame", "frame->number", frame->number, "spooled_video_frames.size()", spooled_video_frames.size(), "spooled_audio_frames.size()", spooled_audio_frames.size(), "cache_size", cache_size, "is_writing", is_writing); // Write the frames once it reaches the correct cache size - if (spooled_video_frames.size() == cache_size || spooled_audio_frames.size() == cache_size) { + if ((int)spooled_video_frames.size() == cache_size || (int)spooled_audio_frames.size() == cache_size) { // Is writer currently writing? if (!is_writing) // Write frames to video file @@ -1083,7 +1083,7 @@ AVStream *FFmpegWriter::add_audio_stream() { // Set a valid number of channels (or throw error) - int channel_layout = info.channel_layout; + const uint64_t channel_layout = info.channel_layout; if (codec->channel_layouts) { int i; for (i = 0; codec->channel_layouts[i] != 0; i++) diff --git a/src/FrameMapper.cpp b/src/FrameMapper.cpp index fe12a780b..6ace84002 100644 --- a/src/FrameMapper.cpp +++ b/src/FrameMapper.cpp @@ -235,7 +235,7 @@ void FrameMapper::Init() int64_t start_samples_frame = 1; int start_samples_position = 0; - for (int64_t field = 1; field <= fields.size(); field++) + for (std::vector::size_type field = 1; field <= fields.size(); field++) { // Get the current field Field f = fields[field - 1]; @@ -337,7 +337,7 @@ MappedFrame FrameMapper::GetMappedFrame(int64_t TargetFrameNumber) // frame too small, return error throw OutOfBoundsFrame("An invalid frame was requested.", TargetFrameNumber, frames.size()); - else if (TargetFrameNumber > frames.size()) + else if (TargetFrameNumber > (int64_t)frames.size()) // frame too large, set to end frame TargetFrameNumber = frames.size(); diff --git a/src/KeyFrame.cpp b/src/KeyFrame.cpp index d16348a2e..e58c5e8f7 100644 --- a/src/KeyFrame.cpp +++ b/src/KeyFrame.cpp @@ -169,7 +169,7 @@ void Keyframe::AddPoint(double x, double y, InterpolationType interpolate) // Get the index of a point by matching a coordinate int64_t Keyframe::FindIndex(Point p) const { // loop through points, and find a matching coordinate - for (int64_t x = 0; x < Points.size(); x++) { + for (std::vector::size_type x = 0; x < Points.size(); x++) { // Get each point Point existing_point = Points[x]; @@ -333,7 +333,7 @@ Json::Value Keyframe::JsonValue() const { root["Points"] = Json::Value(Json::arrayValue); // loop through points, and find a matching coordinate - for (int x = 0; x < Points.size(); x++) { + for (std::vector::size_type x = 0; x < Points.size(); x++) { // Get each point Point existing_point = Points[x]; root["Points"].append(existing_point.JsonValue()); @@ -509,7 +509,7 @@ double Keyframe::GetDelta(int64_t index) const { // Get a point at a specific index Point const & Keyframe::GetPoint(int64_t index) const { // Is index a valid point? - if (index >= 0 && index < Points.size()) + if (index >= 0 && index < (int64_t)Points.size()) return Points[index]; else // Invalid index @@ -532,7 +532,7 @@ int64_t Keyframe::GetCount() const { // Remove a point by matching a coordinate void Keyframe::RemovePoint(Point p) { // loop through points, and find a matching coordinate - for (int64_t x = 0; x < Points.size(); x++) { + for (std::vector::size_type x = 0; x < Points.size(); x++) { // Get each point Point existing_point = Points[x]; @@ -551,7 +551,7 @@ void Keyframe::RemovePoint(Point p) { // Remove a point by index void Keyframe::RemovePoint(int64_t index) { // Is index a valid point? - if (index >= 0 && index < Points.size()) + if (index >= 0 && index < (int64_t)Points.size()) { // Remove a specific point by index Points.erase(Points.begin() + index); @@ -581,7 +581,7 @@ void Keyframe::PrintValues() const { cout << fixed << setprecision(4); cout << "Frame Number (X)\tValue (Y)\tIs Increasing\tRepeat Numerator\tRepeat Denominator\tDelta (Y Difference)\n"; - for (uint64_t i = 1; i < GetLength(); ++i) { + for (int64_t i = 1; i < GetLength(); ++i) { cout << i << "\t" << GetValue(i) << "\t" << IsIncreasing(i) << "\t" ; cout << GetRepeatFraction(i).num << "\t" << GetRepeatFraction(i).den << "\t" << GetDelta(i) << "\n"; } @@ -597,7 +597,7 @@ void Keyframe::ScalePoints(double scale) // TODO: What if scale < 0? // Loop through each point (skipping the 1st point) - for (int64_t point_index = 1; point_index < Points.size(); point_index++) { + for (std::vector::size_type point_index = 1; point_index < Points.size(); point_index++) { // Scale X value Points[point_index].co.X = round(Points[point_index].co.X * scale); } @@ -605,7 +605,7 @@ void Keyframe::ScalePoints(double scale) // Flip all the points in this openshot::Keyframe (useful for reversing an effect or transition, etc...) void Keyframe::FlipPoints() { - for (int64_t point_index = 0, reverse_index = Points.size() - 1; point_index < reverse_index; point_index++, reverse_index--) { + for (std::vector::size_type point_index = 0, reverse_index = Points.size() - 1; point_index < reverse_index; point_index++, reverse_index--) { // Flip the points using std::swap; swap(Points[point_index].co.Y, Points[reverse_index].co.Y); diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 86ef2911f..63e1c1216 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -780,7 +780,7 @@ std::shared_ptr Timeline::GetFrame(int64_t requested_frame) for (int64_t frame_number = requested_frame; frame_number < requested_frame + minimum_frames; frame_number++) { // Loop through clips - for (int clip_index = 0; clip_index < nearby_clips.size(); clip_index++) + for (std::vector::size_type clip_index = 0; clip_index < nearby_clips.size(); clip_index++) { // Get clip object from the iterator Clip *clip = nearby_clips[clip_index]; @@ -832,7 +832,7 @@ std::shared_ptr Timeline::GetFrame(int64_t requested_frame) ZmqLogger::Instance()->AppendDebugMethod("Timeline::GetFrame (Loop through clips)", "frame_number", frame_number, "clips.size()", clips.size(), "nearby_clips.size()", nearby_clips.size()); // Find Clips near this time - for (int clip_index = 0; clip_index < nearby_clips.size(); clip_index++) + for (std::vector::size_type clip_index = 0; clip_index < nearby_clips.size(); clip_index++) { // Get clip object from the iterator Clip *clip = nearby_clips[clip_index]; @@ -850,7 +850,7 @@ std::shared_ptr Timeline::GetFrame(int64_t requested_frame) // Determine if clip is "top" clip on this layer (only happens when multiple clips are overlapping) bool is_top_clip = true; float max_volume = 0.0; - for (int top_clip_index = 0; top_clip_index < nearby_clips.size(); top_clip_index++) + for (std::vector::size_type top_clip_index = 0; top_clip_index < nearby_clips.size(); top_clip_index++) { Clip *nearby_clip = nearby_clips[top_clip_index]; long nearby_clip_start_position = round(nearby_clip->Position() * info.fps.ToDouble()) + 1; @@ -1069,7 +1069,7 @@ void Timeline::SetJsonValue(Json::Value root) { clips.clear(); // loop through clips - for (int x = 0; x < root["clips"].size(); x++) { + for (Json::Value::ArrayIndex x = 0; x < root["clips"].size(); x++) { // Get each clip Json::Value existing_clip = root["clips"][x]; @@ -1089,7 +1089,7 @@ void Timeline::SetJsonValue(Json::Value root) { effects.clear(); // loop through effects - for (int x = 0; x < root["effects"].size(); x++) { + for (Json::Value::ArrayIndex x = 0; x < root["effects"].size(); x++) { // Get each effect Json::Value existing_effect = root["effects"][x]; @@ -1144,7 +1144,7 @@ void Timeline::ApplyJsonDiff(std::string value) { try { // Process the JSON change array, loop through each item - for (int x = 0; x < root.size(); x++) { + for (Json::Value::ArrayIndex x = 0; x < root.size(); x++) { // Get each change Json::Value change = root[x]; std::string root_key = change["key"][(uint)0].asString(); @@ -1180,7 +1180,7 @@ void Timeline::apply_json_to_clips(Json::Value change) { Clip *existing_clip = NULL; // Find id of clip (if any) - for (int x = 0; x < change["key"].size(); x++) { + for (Json::Value::ArrayIndex x = 0; x < change["key"].size(); x++) { // Get each change Json::Value key_part = change["key"][x]; @@ -1308,7 +1308,7 @@ void Timeline::apply_json_to_effects(Json::Value change) { EffectBase *existing_effect = NULL; // Find id of an effect (if any) - for (int x = 0; x < change["key"].size(); x++) { + for (Json::Value::ArrayIndex x = 0; x < change["key"].size(); x++) { // Get each change Json::Value key_part = change["key"][x]; diff --git a/src/effects/Wave.cpp b/src/effects/Wave.cpp index 2139e4ac8..3b1cfb210 100644 --- a/src/effects/Wave.cpp +++ b/src/effects/Wave.cpp @@ -95,7 +95,7 @@ std::shared_ptr Wave::GetFrame(std::shared_ptr frame, int64_t fram float waveformVal = sin((Y * wavelength_value) + (time * speed_y_value)); // Waveform algorithm on y-axis float waveVal = (waveformVal + shift_x_value) * noiseAmp; // Shifts pixels on the x-axis - int source_X = round(pixel + waveVal) * 4; + long unsigned int source_X = round(pixel + waveVal) * 4; if (source_X < 0) source_X = 0; if (source_X > frame_image->width() * frame_image->height() * 4 * sizeof(char)) From 4806f2ff7566bb243f7c4e897a3b7781340fcda2 Mon Sep 17 00:00:00 2001 From: Chris Kirmse Date: Wed, 18 Dec 2019 18:27:04 -0800 Subject: [PATCH 14/45] fix incorrect buffer size being passed to avcodec_fill_audio_frame - most of the time the fixed number being sent in was large enough, but not always - also added logging if avcodec_fill_audio_frame fails --- src/FFmpegWriter.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 645c0cca4..f5c85467f 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -1482,7 +1482,8 @@ void FFmpegWriter::write_audio_packets(bool is_final) { ChannelLayout channel_layout_in_frame = LAYOUT_MONO; // default channel layout // Create a new array (to hold all S16 audio samples, for the current queued frames - int16_t *all_queued_samples = (int16_t *) av_malloc((sizeof(int16_t) * (queued_audio_frames.size() * AVCODEC_MAX_AUDIO_FRAME_SIZE))); + unsigned int all_queued_samples_size = sizeof(int16_t) * (queued_audio_frames.size() * AVCODEC_MAX_AUDIO_FRAME_SIZE); + int16_t *all_queued_samples = (int16_t *) av_malloc(all_queued_samples_size); int16_t *all_resampled_samples = NULL; int16_t *final_samples_planar = NULL; int16_t *final_samples = NULL; @@ -1542,8 +1543,10 @@ void FFmpegWriter::write_audio_packets(bool is_final) { audio_frame->nb_samples = total_frame_samples / channels_in_frame; // Fill input frame with sample data - avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) all_queued_samples, - audio_encoder_buffer_size, 0); + int error_code = avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) all_queued_samples, all_queued_samples_size, 0); + if (error_code < 0) { + ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets ERROR [" + (std::string) av_err2str(error_code) + "]", "error_code", error_code); + } // Do not convert audio to planar format (yet). We need to keep everything interleaved at this point. switch (audio_codec->sample_fmt) { From fd78be6b9592890fa264c92bce47d066d915ca38 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Wed, 18 Dec 2019 23:55:16 -0500 Subject: [PATCH 15/45] Remove JUCE defines A few headers contained #defines that were intended to work around issues with the JUCE library headers, but those things are best handled in other ways. --- include/AudioBufferSource.h | 8 -------- include/AudioReaderSource.h | 8 -------- include/AudioResampler.h | 10 ---------- include/Clip.h | 5 ----- include/ClipBase.h | 5 ----- include/Frame.h | 9 --------- 6 files changed, 45 deletions(-) diff --git a/include/AudioBufferSource.h b/include/AudioBufferSource.h index 42e55c943..3a17feb3c 100644 --- a/include/AudioBufferSource.h +++ b/include/AudioBufferSource.h @@ -31,14 +31,6 @@ #ifndef OPENSHOT_AUDIOBUFFERSOURCE_H #define OPENSHOT_AUDIOBUFFERSOURCE_H -/// Do not include the juce unittest headers, because it collides with unittest++ -#define __JUCE_UNITTEST_JUCEHEADER__ - -#ifndef _NDEBUG - /// Define NO debug for JUCE on mac os - #define _NDEBUG -#endif - #include #include "JuceHeader.h" diff --git a/include/AudioReaderSource.h b/include/AudioReaderSource.h index 33030adf1..c4e2d2480 100644 --- a/include/AudioReaderSource.h +++ b/include/AudioReaderSource.h @@ -31,14 +31,6 @@ #ifndef OPENSHOT_AUDIOREADERSOURCE_H #define OPENSHOT_AUDIOREADERSOURCE_H -/// Do not include the juce unittest headers, because it collides with unittest++ -#define __JUCE_UNITTEST_JUCEHEADER__ - -#ifndef _NDEBUG - /// Define NO debug for JUCE on mac os - #define _NDEBUG -#endif - #include #include "ReaderBase.h" #include "JuceHeader.h" diff --git a/include/AudioResampler.h b/include/AudioResampler.h index 96615cb3f..d88eb7cbe 100644 --- a/include/AudioResampler.h +++ b/include/AudioResampler.h @@ -31,16 +31,6 @@ #ifndef OPENSHOT_RESAMPLER_H #define OPENSHOT_RESAMPLER_H -/// Do not include the juce unittest headers, because it collides with unittest++ -#ifndef __JUCE_UNITTEST_JUCEHEADER__ - #define __JUCE_UNITTEST_JUCEHEADER__ -#endif - -#ifndef _NDEBUG - // Define NO debug for JUCE on mac os - #define _NDEBUG -#endif - #include "AudioBufferSource.h" #include "Exceptions.h" #include "JuceHeader.h" diff --git a/include/Clip.h b/include/Clip.h index 4fdccea98..6fa02c9a1 100644 --- a/include/Clip.h +++ b/include/Clip.h @@ -31,11 +31,6 @@ #ifndef OPENSHOT_CLIP_H #define OPENSHOT_CLIP_H -/// Do not include the juce unittest headers, because it collides with unittest++ -#ifndef __JUCE_UNITTEST_JUCEHEADER__ - #define __JUCE_UNITTEST_JUCEHEADER__ -#endif - #include #include #include diff --git a/include/ClipBase.h b/include/ClipBase.h index 2890f5d8f..cf0d11fab 100644 --- a/include/ClipBase.h +++ b/include/ClipBase.h @@ -31,11 +31,6 @@ #ifndef OPENSHOT_CLIPBASE_H #define OPENSHOT_CLIPBASE_H -/// Do not include the juce unittest headers, because it collides with unittest++ -#ifndef __JUCE_UNITTEST_JUCEHEADER__ - #define __JUCE_UNITTEST_JUCEHEADER__ -#endif - #include #include #include "Exceptions.h" diff --git a/include/Frame.h b/include/Frame.h index b9b989a50..f4ff54d44 100644 --- a/include/Frame.h +++ b/include/Frame.h @@ -31,15 +31,6 @@ #ifndef OPENSHOT_FRAME_H #define OPENSHOT_FRAME_H -/// Do not include the juce unittest headers, because it collides with unittest++ -#ifndef __JUCE_UNITTEST_JUCEHEADER__ - #define __JUCE_UNITTEST_JUCEHEADER__ -#endif -#ifndef _NDEBUG - // Define NO debug for JUCE on mac os - #define _NDEBUG -#endif - #include #include #include From 07b6e2c403c49a72d4aada03cc013ec539e7bb9a Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Thu, 19 Dec 2019 07:57:26 -0500 Subject: [PATCH 16/45] ColorShift effect: Correct class_name --- src/effects/ColorShift.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/effects/ColorShift.cpp b/src/effects/ColorShift.cpp index ea8ae136e..4fc9c941c 100644 --- a/src/effects/ColorShift.cpp +++ b/src/effects/ColorShift.cpp @@ -53,7 +53,7 @@ void ColorShift::init_effect_details() InitEffectInfo(); /// Set the effect info - info.class_name = "Color Shift"; + info.class_name = "ColorShift"; info.name = "Color Shift"; info.description = "Shift the colors of an image up, down, left, and right (with infinite wrapping)."; info.has_audio = false; From c11b4ac26693412cc6079f5c7aede3b404db003d Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Thu, 19 Dec 2019 07:59:30 -0500 Subject: [PATCH 17/45] EffectBase: Remove unused short_name --- include/EffectBase.h | 1 - src/EffectBase.cpp | 2 -- 2 files changed, 3 deletions(-) diff --git a/include/EffectBase.h b/include/EffectBase.h index 29e98b589..f462526db 100644 --- a/include/EffectBase.h +++ b/include/EffectBase.h @@ -50,7 +50,6 @@ namespace openshot struct EffectInfoStruct { std::string class_name; ///< The class name of the effect - std::string short_name; ///< A short name of the effect, commonly used for icon names, etc... std::string name; ///< The name of the effect std::string description; ///< The description of this effect and what it does bool has_video; ///< Determines if this effect manipulates the image of a frame diff --git a/src/EffectBase.cpp b/src/EffectBase.cpp index 30e837652..e4a9e0ab2 100644 --- a/src/EffectBase.cpp +++ b/src/EffectBase.cpp @@ -87,7 +87,6 @@ Json::Value EffectBase::JsonValue() { Json::Value root = ClipBase::JsonValue(); // get parent properties root["name"] = info.name; root["class_name"] = info.class_name; - root["short_name"] = info.short_name; root["description"] = info.description; root["has_video"] = info.has_video; root["has_audio"] = info.has_audio; @@ -144,7 +143,6 @@ Json::Value EffectBase::JsonInfo() { Json::Value root; root["name"] = info.name; root["class_name"] = info.class_name; - root["short_name"] = info.short_name; root["description"] = info.description; root["has_video"] = info.has_video; root["has_audio"] = info.has_audio; From d5f94dd72d3d55b8fb98e3acbee7f9024e470faa Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sun, 22 Dec 2019 14:24:03 -0500 Subject: [PATCH 18/45] Run LCOV with --no-external --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index af2010df4..31b0de2cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,6 +143,7 @@ endif() if (ENABLE_COVERAGE) setup_target_for_coverage_lcov( NAME coverage + LCOV_ARGS "--no-external" EXECUTABLE openshot-test DEPENDENCIES openshot-test) message("Generate coverage report with 'make coverage'") From d0e5d061f0457f24e8798b8ed735fc1fb6697f12 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Thu, 19 Dec 2019 22:09:12 -0500 Subject: [PATCH 19/45] CodeCoverage: import upstream PR changes --- cmake/Modules/CodeCoverage.cmake | 41 ++++++++++++++------------------ 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/cmake/Modules/CodeCoverage.cmake b/cmake/Modules/CodeCoverage.cmake index 0353948a1..786a06b4a 100644 --- a/cmake/Modules/CodeCoverage.cmake +++ b/cmake/Modules/CodeCoverage.cmake @@ -56,6 +56,9 @@ # - Remove Python detection, since version mismatches will break gcovr # - Minor cleanup (lowercase function names, update examples...) # +# 2019-12-19, FeRD (Frank Dana) +# - Rename Lcov outputs, make filtered file canonical, fix cleanup for targets +# # USAGE: # # 1. Copy this file into your cmake modules path. @@ -81,7 +84,7 @@ # NAME coverage # EXECUTABLE testrunner # EXCLUDE "${PROJECT_SOURCE_DIR}/src/dir1/*" "/path/to/my/src/dir2/*") -# +# # 4.a NOTE: With CMake 3.4+, COVERAGE_EXCLUDES or EXCLUDE can also be set # relative to the BASE_DIRECTORY (default: PROJECT_SOURCE_DIR) # Example: @@ -220,16 +223,22 @@ function(setup_target_for_coverage_lcov) COMMAND ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS} # Capturing lcov counters and generating report - COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . -b ${BASEDIR} --capture --output-file ${Coverage_NAME}.info + COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . -b ${BASEDIR} --capture --output-file ${Coverage_NAME}.capture # add baseline counters - COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base -a ${Coverage_NAME}.info --output-file ${Coverage_NAME}.total - COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove ${Coverage_NAME}.total ${LCOV_EXCLUDES} --output-file ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned + COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base -a ${Coverage_NAME}.capture --output-file ${Coverage_NAME}.total + # filter collected data to final coverage report + COMMAND ${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove ${Coverage_NAME}.total ${LCOV_EXCLUDES} --output-file ${Coverage_NAME}.info # Generate HTML output - COMMAND ${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned + COMMAND ${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS} -o ${Coverage_NAME} ${Coverage_NAME}.info - COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.base ${Coverage_NAME}.total ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned - BYPRODUCTS ${Coverage_NAME}.info + # Set output files as GENERATED (will be removed on 'make clean') + BYPRODUCTS + ${Coverage_NAME}.base + ${Coverage_NAME}.capture + ${Coverage_NAME}.total + ${Coverage_NAME}.info + ${Coverage_NAME} # report directory WORKING_DIRECTORY ${PROJECT_BINARY_DIR} DEPENDS ${Coverage_DEPENDENCIES} @@ -248,11 +257,6 @@ function(setup_target_for_coverage_lcov) COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." ) - # Clean up output on 'make clean' - set_property(DIRECTORY APPEND PROPERTY - ADDITIONAL_MAKE_CLEAN_FILES - ${Coverage_NAME}) - endfunction() # setup_target_for_coverage_lcov # Defines a target for running and collection code coverage information @@ -314,6 +318,7 @@ function(setup_target_for_coverage_gcovr_xml) -r ${BASEDIR} ${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR} -o ${Coverage_NAME}.xml + BYPRODUCTS ${Coverage_NAME}.xml WORKING_DIRECTORY ${PROJECT_BINARY_DIR} DEPENDS ${Coverage_DEPENDENCIES} COMMENT "Running gcovr to produce Cobertura code coverage report." @@ -324,12 +329,6 @@ function(setup_target_for_coverage_gcovr_xml) COMMAND ; COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml." ) - - # Clean up output on 'make clean' - set_property(DIRECTORY APPEND PROPERTY - ADDITIONAL_MAKE_CLEAN_FILES - ${Coverage_NAME}) - endfunction() # setup_target_for_coverage_gcovr_xml # Defines a target for running and collection code coverage information @@ -394,6 +393,7 @@ function(setup_target_for_coverage_gcovr_html) -r ${BASEDIR} ${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR} -o ${Coverage_NAME}/index.html + BYPRODUCTS ${PROJECT_BINARY_DIR}/${Coverage_NAME} # report directory WORKING_DIRECTORY ${PROJECT_BINARY_DIR} DEPENDS ${Coverage_DEPENDENCIES} COMMENT "Running gcovr to produce HTML code coverage report." @@ -405,11 +405,6 @@ function(setup_target_for_coverage_gcovr_html) COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." ) - # Clean up output on 'make clean' - set_property(DIRECTORY APPEND PROPERTY - ADDITIONAL_MAKE_CLEAN_FILES - ${Coverage_NAME}) - endfunction() # setup_target_for_coverage_gcovr_html function(append_coverage_compiler_flags) From 31a0565d264d69d2ad71b7b32682178d400701c1 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Fri, 27 Dec 2019 10:51:02 -0500 Subject: [PATCH 20/45] Frame: DeepCopy has_audio_data correctly --- src/Frame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Frame.cpp b/src/Frame.cpp index 40183422c..358c310a3 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -109,7 +109,7 @@ void Frame::DeepCopy(const Frame& other) width = other.width; height = other.height; channel_layout = other.channel_layout; - has_audio_data = other.has_image_data; + has_audio_data = other.has_audio_data; has_image_data = other.has_image_data; sample_rate = other.sample_rate; pixel_ratio = Fraction(other.pixel_ratio.num, other.pixel_ratio.den); From d60678af0dd633f01a1214ed57bc765a993db6c9 Mon Sep 17 00:00:00 2001 From: Chris Kirmse Date: Fri, 27 Dec 2019 09:54:57 -0800 Subject: [PATCH 21/45] correctly calculate remaining_frame_samples - sometimes the output from the SWR_CONVERT is not the exact amount we asked for - without this fix, the old code would sometimes read past the end of a buffer - valgrind complained about the old code - read https://stackoverflow.com/questions/39587839/libswresample-swr-convert-not-producing-enough-samples --- src/FFmpegWriter.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 645c0cca4..81b8232ec 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -1417,7 +1417,7 @@ void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) { // unless "qp" was set for CQP, switch to VBR RC mode av_opt_set(video_codec->priv_data, "rc_mode", "VBR", 0); - // In the current state (ffmpeg-4.2-4 libva-mesa-driver-19.1.5-1) to use VBR, + // In the current state (ffmpeg-4.2-4 libva-mesa-driver-19.1.5-1) to use VBR, // one has to specify both bit_rate and maxrate, otherwise a small low quality file is generated on Intel iGPU). video_codec->rc_max_rate = video_codec->bit_rate; } @@ -1569,9 +1569,6 @@ void FFmpegWriter::write_audio_packets(bool is_final) { total_frame_samples *= (float(info.sample_rate) / sample_rate_in_frame); // adjust for different byte sizes total_frame_samples *= (float(info.channels) / channels_in_frame); // adjust for different # of channels - // Set remaining samples - remaining_frame_samples = total_frame_samples; - // Create output frame (and allocate arrays) AVFrame *audio_converted = AV_ALLOCATE_FRAME(); AV_RESET_FRAME(audio_converted); @@ -1604,6 +1601,9 @@ void FFmpegWriter::write_audio_packets(bool is_final) { audio_frame->linesize[0], // input plane size, in bytes (0 if unknown) audio_frame->nb_samples); // number of input samples to convert + // Set remaining samples + remaining_frame_samples = nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16); + // Create a new array (to hold all resampled S16 audio samples) all_resampled_samples = (int16_t *) av_malloc( sizeof(int16_t) * nb_samples * info.channels * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16))); From dc217a9bdfade96d24e398cf6b833e65d1d500c0 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 28 Dec 2019 09:48:25 -0500 Subject: [PATCH 22/45] tests: Cast container.size() to int for comparison --- tests/Cache_Tests.cpp | 20 ++++++++++---------- tests/Clip_Tests.cpp | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/Cache_Tests.cpp b/tests/Cache_Tests.cpp index ea5b45ce4..ddf698f54 100644 --- a/tests/Cache_Tests.cpp +++ b/tests/Cache_Tests.cpp @@ -395,31 +395,31 @@ TEST(CacheDisk_JSON) // Add some frames (out of order) std::shared_ptr f3(new Frame(3, 1280, 720, "Blue", 500, 2)); c.Add(f3); - CHECK_EQUAL(1, c.JsonValue()["ranges"].size()); + CHECK_EQUAL(1, (int)c.JsonValue()["ranges"].size()); CHECK_EQUAL("1", c.JsonValue()["version"].asString()); // Add some frames (out of order) std::shared_ptr f1(new Frame(1, 1280, 720, "Blue", 500, 2)); c.Add(f1); - CHECK_EQUAL(2, c.JsonValue()["ranges"].size()); + CHECK_EQUAL(2, (int)c.JsonValue()["ranges"].size()); CHECK_EQUAL("2", c.JsonValue()["version"].asString()); // Add some frames (out of order) std::shared_ptr f2(new Frame(2, 1280, 720, "Blue", 500, 2)); c.Add(f2); - CHECK_EQUAL(1, c.JsonValue()["ranges"].size()); + CHECK_EQUAL(1, (int)c.JsonValue()["ranges"].size()); CHECK_EQUAL("3", c.JsonValue()["version"].asString()); // Add some frames (out of order) std::shared_ptr f5(new Frame(5, 1280, 720, "Blue", 500, 2)); c.Add(f5); - CHECK_EQUAL(2, c.JsonValue()["ranges"].size()); + CHECK_EQUAL(2, (int)c.JsonValue()["ranges"].size()); CHECK_EQUAL("4", c.JsonValue()["version"].asString()); // Add some frames (out of order) std::shared_ptr f4(new Frame(4, 1280, 720, "Blue", 500, 2)); c.Add(f4); - CHECK_EQUAL(1, c.JsonValue()["ranges"].size()); + CHECK_EQUAL(1, (int)c.JsonValue()["ranges"].size()); CHECK_EQUAL("5", c.JsonValue()["version"].asString()); // Delete cache directory @@ -435,31 +435,31 @@ TEST(CacheMemory_JSON) // Add some frames (out of order) std::shared_ptr f3(new Frame(3, 1280, 720, "Blue", 500, 2)); c.Add(f3); - CHECK_EQUAL(1, c.JsonValue()["ranges"].size()); + CHECK_EQUAL(1, (int)c.JsonValue()["ranges"].size()); CHECK_EQUAL("1", c.JsonValue()["version"].asString()); // Add some frames (out of order) std::shared_ptr f1(new Frame(1, 1280, 720, "Blue", 500, 2)); c.Add(f1); - CHECK_EQUAL(2, c.JsonValue()["ranges"].size()); + CHECK_EQUAL(2, (int)c.JsonValue()["ranges"].size()); CHECK_EQUAL("2", c.JsonValue()["version"].asString()); // Add some frames (out of order) std::shared_ptr f2(new Frame(2, 1280, 720, "Blue", 500, 2)); c.Add(f2); - CHECK_EQUAL(1, c.JsonValue()["ranges"].size()); + CHECK_EQUAL(1, (int)c.JsonValue()["ranges"].size()); CHECK_EQUAL("3", c.JsonValue()["version"].asString()); // Add some frames (out of order) std::shared_ptr f5(new Frame(5, 1280, 720, "Blue", 500, 2)); c.Add(f5); - CHECK_EQUAL(2, c.JsonValue()["ranges"].size()); + CHECK_EQUAL(2, (int)c.JsonValue()["ranges"].size()); CHECK_EQUAL("4", c.JsonValue()["version"].asString()); // Add some frames (out of order) std::shared_ptr f4(new Frame(4, 1280, 720, "Blue", 500, 2)); c.Add(f4); - CHECK_EQUAL(1, c.JsonValue()["ranges"].size()); + CHECK_EQUAL(1, (int)c.JsonValue()["ranges"].size()); CHECK_EQUAL("5", c.JsonValue()["version"].asString()); } diff --git a/tests/Clip_Tests.cpp b/tests/Clip_Tests.cpp index 711fef03c..c66cc9a48 100644 --- a/tests/Clip_Tests.cpp +++ b/tests/Clip_Tests.cpp @@ -241,7 +241,7 @@ TEST(Clip_Effects) CHECK_EQUAL(255, (int)pixels[pixel_index + 3]); // Check the # of Effects - CHECK_EQUAL(1, c10.Effects().size()); + CHECK_EQUAL(1, (int)c10.Effects().size()); // Add a 2nd negate effect @@ -262,5 +262,5 @@ TEST(Clip_Effects) CHECK_EQUAL(255, (int)pixels[pixel_index + 3]); // Check the # of Effects - CHECK_EQUAL(2, c10.Effects().size()); + CHECK_EQUAL(2, (int)c10.Effects().size()); } From e49f62247e9528415f6c253c0cb7029eb10a7ccf Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Fri, 27 Dec 2019 01:01:48 -0500 Subject: [PATCH 23/45] Use C++11 range-based for loops where we can --- src/AudioBufferSource.cpp | 2 +- src/AudioReaderSource.cpp | 2 +- src/CacheBase.cpp | 4 +- src/CacheDisk.cpp | 10 ++-- src/CacheMemory.cpp | 4 +- src/Clip.cpp | 16 ++---- src/Frame.cpp | 8 +-- src/KeyFrame.cpp | 9 +--- src/ReaderBase.cpp | 10 ++-- src/Timeline.cpp | 111 +++++++++++--------------------------- 10 files changed, 53 insertions(+), 123 deletions(-) diff --git a/src/AudioBufferSource.cpp b/src/AudioBufferSource.cpp index 46b04916e..2f3d14ca3 100644 --- a/src/AudioBufferSource.cpp +++ b/src/AudioBufferSource.cpp @@ -43,7 +43,7 @@ AudioBufferSource::~AudioBufferSource() { // forget the AudioSampleBuffer. It still exists; we just don't know about it. buffer = NULL; -}; +} // Get the next block of audio samples void AudioBufferSource::getNextAudioBlock (const juce::AudioSourceChannelInfo& info) diff --git a/src/AudioReaderSource.cpp b/src/AudioReaderSource.cpp index 41c0b3f6b..c96d0bcc3 100644 --- a/src/AudioReaderSource.cpp +++ b/src/AudioReaderSource.cpp @@ -51,7 +51,7 @@ AudioReaderSource::~AudioReaderSource() // Clear and delete the buffer delete buffer; buffer = NULL; -}; +} // Get more samples from the reader void AudioReaderSource::GetMoreSamplesFromReader() diff --git a/src/CacheBase.cpp b/src/CacheBase.cpp index 8a7d541ae..4599d5ca5 100644 --- a/src/CacheBase.cpp +++ b/src/CacheBase.cpp @@ -37,13 +37,13 @@ using namespace openshot; CacheBase::CacheBase() : max_bytes(0) { // Init the critical section cacheCriticalSection = new CriticalSection(); -}; +} // Constructor that sets the max frames to cache CacheBase::CacheBase(int64_t max_bytes) : max_bytes(max_bytes) { // Init the critical section cacheCriticalSection = new CriticalSection(); -}; +} // Set maximum bytes to a different amount based on a ReaderInfo struct void CacheBase::SetMaxBytesFromInfo(int64_t number_of_frames, int width, int height, int sample_rate, int channels) diff --git a/src/CacheDisk.cpp b/src/CacheDisk.cpp index 5dc677e56..3f8bf37ed 100644 --- a/src/CacheDisk.cpp +++ b/src/CacheDisk.cpp @@ -47,7 +47,7 @@ CacheDisk::CacheDisk(std::string cache_path, std::string format, float quality, // Init path directory InitPath(cache_path); -}; +} // Constructor that sets the max bytes to cache CacheDisk::CacheDisk(std::string cache_path, std::string format, float quality, float scale, int64_t max_bytes) : CacheBase(max_bytes) { @@ -62,7 +62,7 @@ CacheDisk::CacheDisk(std::string cache_path, std::string format, float quality, // Init path directory InitPath(cache_path); -}; +} // Initialize cache directory void CacheDisk::InitPath(std::string cache_path) { @@ -103,13 +103,11 @@ void CacheDisk::CalculateRanges() { // Increment range version range_version++; - std::vector::iterator itr_ordered; int64_t starting_frame = *ordered_frame_numbers.begin(); - int64_t ending_frame = *ordered_frame_numbers.begin(); + int64_t ending_frame = starting_frame; // Loop through all known frames (in sequential order) - for (itr_ordered = ordered_frame_numbers.begin(); itr_ordered != ordered_frame_numbers.end(); ++itr_ordered) { - int64_t frame_number = *itr_ordered; + for (const auto frame_number : ordered_frame_numbers) { if (frame_number - ending_frame > 1) { // End of range detected Json::Value range; diff --git a/src/CacheMemory.cpp b/src/CacheMemory.cpp index ff8963fdc..0b2d9ab8a 100644 --- a/src/CacheMemory.cpp +++ b/src/CacheMemory.cpp @@ -39,7 +39,7 @@ CacheMemory::CacheMemory() : CacheBase(0) { cache_type = "CacheMemory"; range_version = 0; needs_range_processing = false; -}; +} // Constructor that sets the max bytes to cache CacheMemory::CacheMemory(int64_t max_bytes) : CacheBase(max_bytes) { @@ -47,7 +47,7 @@ CacheMemory::CacheMemory(int64_t max_bytes) : CacheBase(max_bytes) { cache_type = "CacheMemory"; range_version = 0; needs_range_processing = false; -}; +} // Default destructor CacheMemory::~CacheMemory() diff --git a/src/Clip.cpp b/src/Clip.cpp index 985df0158..ef6b98525 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -782,11 +782,8 @@ Json::Value Clip::JsonValue() { root["effects"] = Json::Value(Json::arrayValue); // loop through effects - std::list::iterator effect_itr; - for (effect_itr=effects.begin(); effect_itr != effects.end(); ++effect_itr) + for (auto existing_effect : effects) { - // Get clip object from the iterator - EffectBase *existing_effect = (*effect_itr); root["effects"].append(existing_effect->JsonValue()); } @@ -905,10 +902,7 @@ void Clip::SetJsonValue(Json::Value root) { effects.clear(); // loop through effects - for (Json::Value::ArrayIndex x = 0; x < root["effects"].size(); x++) { - // Get each effect - Json::Value existing_effect = root["effects"][x]; - + for (const auto existing_effect : root["effects"]) { // Create Effect EffectBase *e = NULL; @@ -1025,12 +1019,8 @@ void Clip::RemoveEffect(EffectBase* effect) std::shared_ptr Clip::apply_effects(std::shared_ptr frame) { // Find Effects at this position and layer - std::list::iterator effect_itr; - for (effect_itr=effects.begin(); effect_itr != effects.end(); ++effect_itr) + for (auto effect : effects) { - // Get clip object from the iterator - EffectBase *effect = (*effect_itr); - // Apply the effect to this frame frame = effect->GetFrame(frame, frame->number); diff --git a/src/Frame.cpp b/src/Frame.cpp index 40183422c..f01f0c4fb 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -43,7 +43,7 @@ Frame::Frame() : number(1), pixel_ratio(1,1), channels(2), width(1), height(1), // initialize the audio samples to zero (silence) audio->clear(); -}; +} // Constructor - image only (48kHz audio silence) Frame::Frame(int64_t number, int width, int height, std::string color) @@ -56,7 +56,7 @@ Frame::Frame(int64_t number, int width, int height, std::string color) // initialize the audio samples to zero (silence) audio->clear(); -}; +} // Constructor - audio only (300x200 blank image) Frame::Frame(int64_t number, int samples, int channels) : @@ -69,7 +69,7 @@ Frame::Frame(int64_t number, int samples, int channels) : // initialize the audio samples to zero (silence) audio->clear(); -}; +} // Constructor - image & audio Frame::Frame(int64_t number, int width, int height, std::string color, int samples, int channels) @@ -82,7 +82,7 @@ Frame::Frame(int64_t number, int width, int height, std::string color, int sampl // initialize the audio samples to zero (silence) audio->clear(); -}; +} // Copy constructor diff --git a/src/KeyFrame.cpp b/src/KeyFrame.cpp index e58c5e8f7..c54bc7d44 100644 --- a/src/KeyFrame.cpp +++ b/src/KeyFrame.cpp @@ -333,9 +333,7 @@ Json::Value Keyframe::JsonValue() const { root["Points"] = Json::Value(Json::arrayValue); // loop through points, and find a matching coordinate - for (std::vector::size_type x = 0; x < Points.size(); x++) { - // Get each point - Point existing_point = Points[x]; + for (auto existing_point : Points) { root["Points"].append(existing_point.JsonValue()); } @@ -379,10 +377,7 @@ void Keyframe::SetJsonValue(Json::Value root) { if (!root["Points"].isNull()) // loop through points - for (int64_t x = 0; x < root["Points"].size(); x++) { - // Get each point - Json::Value existing_point = root["Points"][(Json::UInt) x]; - + for (const auto existing_point : root["Points"]) { // Create Point Point p; diff --git a/src/ReaderBase.cpp b/src/ReaderBase.cpp index ccd271f48..f4c377c5e 100644 --- a/src/ReaderBase.cpp +++ b/src/ReaderBase.cpp @@ -108,9 +108,8 @@ void ReaderBase::DisplayInfo() { std::cout << "----------------------------" << std::endl; // Iterate through metadata - std::map::iterator it; - for (it = info.metadata.begin(); it != info.metadata.end(); it++) - std::cout << "--> " << it->first << ": " << it->second << std::endl; + for (auto it : info.metadata) + std::cout << "--> " << it.first << ": " << it.second << std::endl; } // Generate Json::JsonValue for this object @@ -160,9 +159,8 @@ Json::Value ReaderBase::JsonValue() { // Append metadata map root["metadata"] = Json::Value(Json::objectValue); - std::map::iterator it; - for (it = info.metadata.begin(); it != info.metadata.end(); it++) - root["metadata"][it->first] = it->second; + for (auto it : info.metadata) + root["metadata"][it.first] = it.second; // return JsonValue return root; diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 63e1c1216..305af06e4 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -79,15 +79,16 @@ Timeline::~Timeline() { Close(); // Free all allocated frame mappers - std::set::iterator frame_mapper_itr; - for (frame_mapper_itr = allocated_frame_mappers.begin(); frame_mapper_itr != allocated_frame_mappers.end(); ++frame_mapper_itr) { - // Get frame mapper object from the iterator - FrameMapper *frame_mapper = (*frame_mapper_itr); - frame_mapper->Reader(NULL); - frame_mapper->Close(); - delete frame_mapper; + std::set::iterator it; + for (it = allocated_frame_mappers.begin(); it != allocated_frame_mappers.end(); ) { + // Dereference and clean up FrameMapper object + FrameMapper *mapper = (*it); + mapper->Reader(NULL); + mapper->Close(); + delete mapper; + // Remove reference and proceed to next element + it = allocated_frame_mappers.erase(it); } - allocated_frame_mappers.clear(); // Destroy previous cache (if managed by timeline) if (managed_cache && final_cache) { @@ -169,12 +170,8 @@ void Timeline::ApplyMapperToClips() ClearAllCache(); // Loop through all clips - std::list::iterator clip_itr; - for (clip_itr=clips.begin(); clip_itr != clips.end(); ++clip_itr) + for (auto clip : clips) { - // Get clip object from the iterator - Clip *clip = (*clip_itr); - // Apply framemapper (or update existing framemapper) apply_mapper_to_clip(clip); } @@ -197,12 +194,8 @@ std::shared_ptr Timeline::apply_effects(std::shared_ptr frame, int ZmqLogger::Instance()->AppendDebugMethod("Timeline::apply_effects", "frame->number", frame->number, "timeline_frame_number", timeline_frame_number, "layer", layer); // Find Effects at this position and layer - std::list::iterator effect_itr; - for (effect_itr=effects.begin(); effect_itr != effects.end(); ++effect_itr) + for (auto effect : effects) { - // Get effect object from the iterator - EffectBase *effect = (*effect_itr); - // Does clip intersect the current requested time long effect_start_position = round(effect->Position() * info.fps.ToDouble()) + 1; long effect_end_position = round((effect->Position() + (effect->Duration())) * info.fps.ToDouble()) + 1; @@ -692,12 +685,8 @@ void Timeline::Close() ZmqLogger::Instance()->AppendDebugMethod("Timeline::Close"); // Close all open clips - std::list::iterator clip_itr; - for (clip_itr=clips.begin(); clip_itr != clips.end(); ++clip_itr) + for (auto clip : clips) { - // Get clip object from the iterator - Clip *clip = (*clip_itr); - // Open or Close this clip, based on if it's intersecting or not update_open_clips(clip, false); } @@ -780,10 +769,8 @@ std::shared_ptr Timeline::GetFrame(int64_t requested_frame) for (int64_t frame_number = requested_frame; frame_number < requested_frame + minimum_frames; frame_number++) { // Loop through clips - for (std::vector::size_type clip_index = 0; clip_index < nearby_clips.size(); clip_index++) + for (auto clip : nearby_clips) { - // Get clip object from the iterator - Clip *clip = nearby_clips[clip_index]; long clip_start_position = round(clip->Position() * info.fps.ToDouble()) + 1; long clip_end_position = round((clip->Position() + clip->Duration()) * info.fps.ToDouble()) + 1; @@ -832,10 +819,8 @@ std::shared_ptr Timeline::GetFrame(int64_t requested_frame) ZmqLogger::Instance()->AppendDebugMethod("Timeline::GetFrame (Loop through clips)", "frame_number", frame_number, "clips.size()", clips.size(), "nearby_clips.size()", nearby_clips.size()); // Find Clips near this time - for (std::vector::size_type clip_index = 0; clip_index < nearby_clips.size(); clip_index++) + for (auto clip : nearby_clips) { - // Get clip object from the iterator - Clip *clip = nearby_clips[clip_index]; long clip_start_position = round(clip->Position() * info.fps.ToDouble()) + 1; long clip_end_position = round((clip->Position() + clip->Duration()) * info.fps.ToDouble()) + 1; @@ -850,9 +835,8 @@ std::shared_ptr Timeline::GetFrame(int64_t requested_frame) // Determine if clip is "top" clip on this layer (only happens when multiple clips are overlapping) bool is_top_clip = true; float max_volume = 0.0; - for (std::vector::size_type top_clip_index = 0; top_clip_index < nearby_clips.size(); top_clip_index++) + for (auto nearby_clip : nearby_clips) { - Clip *nearby_clip = nearby_clips[top_clip_index]; long nearby_clip_start_position = round(nearby_clip->Position() * info.fps.ToDouble()) + 1; long nearby_clip_end_position = round((nearby_clip->Position() + nearby_clip->Duration()) * info.fps.ToDouble()) + 1; long nearby_clip_start_frame = (nearby_clip->Start() * info.fps.ToDouble()) + 1; @@ -927,12 +911,8 @@ std::vector Timeline::find_intersecting_clips(int64_t requested_frame, in sort_clips(); // Find Clips at this time - std::list::iterator clip_itr; - for (clip_itr=clips.begin(); clip_itr != clips.end(); ++clip_itr) + for (auto clip : clips) { - // Get clip object from the iterator - Clip *clip = (*clip_itr); - // Does clip intersect the current requested time long clip_start_position = round(clip->Position() * info.fps.ToDouble()) + 1; long clip_end_position = round((clip->Position() + clip->Duration()) * info.fps.ToDouble()) + 1; @@ -998,11 +978,8 @@ Json::Value Timeline::JsonValue() { root["clips"] = Json::Value(Json::arrayValue); // Find Clips at this time - std::list::iterator clip_itr; - for (clip_itr=clips.begin(); clip_itr != clips.end(); ++clip_itr) + for (auto existing_clip : clips) { - // Get clip object from the iterator - Clip *existing_clip = (*clip_itr); root["clips"].append(existing_clip->JsonValue()); } @@ -1010,11 +987,8 @@ Json::Value Timeline::JsonValue() { root["effects"] = Json::Value(Json::arrayValue); // loop through effects - std::list::iterator effect_itr; - for (effect_itr=effects.begin(); effect_itr != effects.end(); ++effect_itr) + for (auto existing_effect: effects) { - // Get clip object from the iterator - EffectBase *existing_effect = (*effect_itr); root["effects"].append(existing_effect->JsonValue()); } @@ -1069,10 +1043,7 @@ void Timeline::SetJsonValue(Json::Value root) { clips.clear(); // loop through clips - for (Json::Value::ArrayIndex x = 0; x < root["clips"].size(); x++) { - // Get each clip - Json::Value existing_clip = root["clips"][x]; - + for (const Json::Value existing_clip : root["clips"]) { // Create Clip Clip *c = new Clip(); @@ -1089,10 +1060,7 @@ void Timeline::SetJsonValue(Json::Value root) { effects.clear(); // loop through effects - for (Json::Value::ArrayIndex x = 0; x < root["effects"].size(); x++) { - // Get each effect - Json::Value existing_effect = root["effects"][x]; - + for (const Json::Value existing_effect :root["effects"]) { // Create Effect EffectBase *e = NULL; @@ -1144,17 +1112,15 @@ void Timeline::ApplyJsonDiff(std::string value) { try { // Process the JSON change array, loop through each item - for (Json::Value::ArrayIndex x = 0; x < root.size(); x++) { - // Get each change - Json::Value change = root[x]; - std::string root_key = change["key"][(uint)0].asString(); + for (const Json::Value change : root) { + std::string change_key = change["key"][(uint)0].asString(); // Process each type of change - if (root_key == "clips") + if (change_key == "clips") // Apply to CLIPS apply_json_to_clips(change); - else if (root_key == "effects") + else if (change_key == "effects") // Apply to EFFECTS apply_json_to_effects(change); @@ -1180,10 +1146,8 @@ void Timeline::apply_json_to_clips(Json::Value change) { Clip *existing_clip = NULL; // Find id of clip (if any) - for (Json::Value::ArrayIndex x = 0; x < change["key"].size(); x++) { + for (auto key_part : change["key"]) { // Get each change - Json::Value key_part = change["key"][x]; - if (key_part.isObject()) { // Check for id if (!key_part["id"].isNull()) { @@ -1191,11 +1155,8 @@ void Timeline::apply_json_to_clips(Json::Value change) { clip_id = key_part["id"].asString(); // Find matching clip in timeline (if any) - std::list::iterator clip_itr; - for (clip_itr=clips.begin(); clip_itr != clips.end(); ++clip_itr) + for (auto c : clips) { - // Get clip object from the iterator - Clip *c = (*clip_itr); if (c->Id() == clip_id) { existing_clip = c; break; // clip found, exit loop @@ -1222,11 +1183,8 @@ void Timeline::apply_json_to_clips(Json::Value change) { // Find matching effect in timeline (if any) std::list effect_list = existing_clip->Effects(); - std::list::iterator effect_itr; - for (effect_itr=effect_list.begin(); effect_itr != effect_list.end(); ++effect_itr) + for (auto e : effect_list) { - // Get effect object from the iterator - EffectBase *e = (*effect_itr); if (e->Id() == effect_id) { // Apply the change to the effect directly apply_json_to_effects(change, e); @@ -1308,9 +1266,7 @@ void Timeline::apply_json_to_effects(Json::Value change) { EffectBase *existing_effect = NULL; // Find id of an effect (if any) - for (Json::Value::ArrayIndex x = 0; x < change["key"].size(); x++) { - // Get each change - Json::Value key_part = change["key"][x]; + for (auto key_part : change["key"]) { if (key_part.isObject()) { // Check for id @@ -1320,11 +1276,8 @@ void Timeline::apply_json_to_effects(Json::Value change) { std::string effect_id = key_part["id"].asString(); // Find matching effect in timeline (if any) - std::list::iterator effect_itr; - for (effect_itr=effects.begin(); effect_itr != effects.end(); ++effect_itr) + for (auto e : effects) { - // Get effect object from the iterator - EffectBase *e = (*effect_itr); if (e->Id() == effect_id) { existing_effect = e; break; // effect found, exit loop @@ -1533,12 +1486,8 @@ void Timeline::ClearAllCache() { final_cache->Clear(); // Loop through all clips - std::list::iterator clip_itr; - for (clip_itr=clips.begin(); clip_itr != clips.end(); ++clip_itr) + for (auto clip : clips) { - // Get clip object from the iterator - Clip *clip = (*clip_itr); - // Clear cache on clip clip->Reader()->GetCache()->Clear(); From b1aff667e5ce15784cacebec2c33594a95c4c98c Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 28 Dec 2019 12:27:58 -0500 Subject: [PATCH 24/45] tests: Start Frame_Tests.cpp --- tests/CMakeLists.txt | 1 + tests/Frame_Tests.cpp | 150 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 tests/Frame_Tests.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a104d766a..12f84bb6c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -115,6 +115,7 @@ SET ( OPENSHOT_TEST_FILES FFmpegReader_Tests.cpp FFmpegWriter_Tests.cpp Fraction_Tests.cpp + Frame_Tests.cpp FrameMapper_Tests.cpp KeyFrame_Tests.cpp Point_Tests.cpp diff --git a/tests/Frame_Tests.cpp b/tests/Frame_Tests.cpp new file mode 100644 index 000000000..76e4ba57b --- /dev/null +++ b/tests/Frame_Tests.cpp @@ -0,0 +1,150 @@ +/** + * @file + * @brief Unit tests for openshot::Frame + * @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 "UnitTest++.h" +// Prevent name clashes with juce::UnitTest +#define DONT_SET_USING_JUCE_NAMESPACE 1 +#include "../include/OpenShot.h" + +#include + +using namespace openshot; + +SUITE(Frame_Tests) +{ + +TEST(Default_Constructor) +{ + // Create a "blank" default Frame + std::shared_ptr f1(new Frame()); + + REQUIRE CHECK(f1 != nullptr); // Test aborts here if we didn't get a Frame + + // Check basic default parameters + CHECK_EQUAL(1, f1->GetHeight()); + CHECK_EQUAL(1, f1->GetWidth()); + CHECK_EQUAL(44100, f1->SampleRate()); + CHECK_EQUAL(2, f1->GetAudioChannelsCount()); + + // Should be false until we load or create contents + CHECK_EQUAL(false, f1->has_image_data); + CHECK_EQUAL(false, f1->has_audio_data); + + // Calling GetImage() paints a blank frame, by default + std::shared_ptr i1 = f1->GetImage(); + + REQUIRE CHECK(i1 != nullptr); + + CHECK_EQUAL(true,f1->has_image_data); + CHECK_EQUAL(false,f1->has_audio_data); +} + + +TEST(Data_Access) +{ + // Create a video clip + std::stringstream path; + path << TEST_MEDIA_PATH << "sintel_trailer-720p.mp4"; + Clip c1(path.str()); + c1.Open(); + + // Get first frame + std::shared_ptr f1 = c1.GetFrame(1); + + REQUIRE CHECK(f1 != nullptr); + + CHECK_EQUAL(1, f1->number); + CHECK_EQUAL(1280, f1->GetWidth()); + CHECK_EQUAL(720, f1->GetHeight()); +} + + +TEST(AddImage_QImage) +{ + // Create a "blank" default Frame + std::shared_ptr f1(new Frame()); + + // Load an image + std::stringstream path; + path << TEST_MEDIA_PATH << "front.png"; + std::shared_ptr i1(new QImage(QString::fromStdString(path.str()))) ; + + REQUIRE CHECK(f1 != nullptr); // Test aborts here if we didn't get a Frame + REQUIRE CHECK_EQUAL(false, i1->isNull()); + + f1->AddImage(i1); + + // Check loaded image parameters + CHECK_EQUAL(i1->height(), f1->GetHeight()); + CHECK_EQUAL(i1->width(), f1->GetWidth()); + CHECK_EQUAL(true, f1->has_image_data); +} + + +TEST(Copy_Constructor) +{ + // Create a dummy Frame + openshot::Frame f1(1, 800, 600, "#000000"); + + // Load an image + std::stringstream path; + path << TEST_MEDIA_PATH << "front.png"; + std::shared_ptr i1( new QImage(QString::fromStdString(path.str())) ); + + REQUIRE CHECK_EQUAL(false, i1->isNull()); + + // Add image to f1, then copy f1 to f2 + f1.AddImage(i1); + + Frame f2 = f1; + + CHECK_EQUAL(f1.GetHeight(), f2.GetHeight()); + CHECK_EQUAL(f1.GetWidth(), f2.GetWidth()); + + CHECK_EQUAL(f1.has_image_data, f2.has_image_data); + CHECK_EQUAL(f1.has_audio_data, f2.has_audio_data); + + Fraction par1 = f1.GetPixelRatio(); + Fraction par2 = f2.GetPixelRatio(); + + CHECK_EQUAL(par1.num, par2.num); + CHECK_EQUAL(par1.den, par2.den); + + + CHECK_EQUAL(f1.SampleRate(), f2.SampleRate()); + CHECK_EQUAL(f1.GetAudioChannelsCount(), f2.GetAudioChannelsCount()); + CHECK_EQUAL(f1.ChannelsLayout(), f2.ChannelsLayout()); + + CHECK_EQUAL(f1.GetBytes(), f2.GetBytes()); + CHECK_EQUAL(f1.GetAudioSamplesCount(), f2.GetAudioSamplesCount()); +} + +} // SUITE(Frame_Tests) From f8d715ce7658d2ea2b2888907e828d9524d55f8f Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 28 Dec 2019 15:50:37 -0500 Subject: [PATCH 25/45] tests: Don't use REQUIRE in unit tests It's not supported in the older UnitTest++ version still in use on Ubuntu Xenial. --- tests/Frame_Tests.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Frame_Tests.cpp b/tests/Frame_Tests.cpp index 76e4ba57b..a92906a3d 100644 --- a/tests/Frame_Tests.cpp +++ b/tests/Frame_Tests.cpp @@ -46,7 +46,7 @@ TEST(Default_Constructor) // Create a "blank" default Frame std::shared_ptr f1(new Frame()); - REQUIRE CHECK(f1 != nullptr); // Test aborts here if we didn't get a Frame + CHECK(f1 != nullptr); // Test aborts here if we didn't get a Frame // Check basic default parameters CHECK_EQUAL(1, f1->GetHeight()); @@ -61,7 +61,7 @@ TEST(Default_Constructor) // Calling GetImage() paints a blank frame, by default std::shared_ptr i1 = f1->GetImage(); - REQUIRE CHECK(i1 != nullptr); + CHECK(i1 != nullptr); CHECK_EQUAL(true,f1->has_image_data); CHECK_EQUAL(false,f1->has_audio_data); @@ -79,7 +79,7 @@ TEST(Data_Access) // Get first frame std::shared_ptr f1 = c1.GetFrame(1); - REQUIRE CHECK(f1 != nullptr); + CHECK(f1 != nullptr); CHECK_EQUAL(1, f1->number); CHECK_EQUAL(1280, f1->GetWidth()); @@ -97,8 +97,8 @@ TEST(AddImage_QImage) path << TEST_MEDIA_PATH << "front.png"; std::shared_ptr i1(new QImage(QString::fromStdString(path.str()))) ; - REQUIRE CHECK(f1 != nullptr); // Test aborts here if we didn't get a Frame - REQUIRE CHECK_EQUAL(false, i1->isNull()); + CHECK(f1 != nullptr); // Test aborts here if we didn't get a Frame + CHECK_EQUAL(false, i1->isNull()); f1->AddImage(i1); @@ -119,7 +119,7 @@ TEST(Copy_Constructor) path << TEST_MEDIA_PATH << "front.png"; std::shared_ptr i1( new QImage(QString::fromStdString(path.str())) ); - REQUIRE CHECK_EQUAL(false, i1->isNull()); + CHECK_EQUAL(false, i1->isNull()); // Add image to f1, then copy f1 to f2 f1.AddImage(i1); From ea3bb103ac274727a55462227c153d78b1d1d0a9 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Mon, 30 Dec 2019 06:21:16 -0500 Subject: [PATCH 26/45] Travis: Add coverage build, un-failjail FFmpeg4 --- .travis.yml | 48 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4375b3f2e..b4cd9024d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,13 +33,12 @@ addons: matrix: - # The FFmpeg4 PPA is currently down as a protest - allow_failures: - - env: BUILD_VERSION=ffmpeg4 - include: - name: "FFmpeg 2 GCC (Ubuntu 16.04 Xenial)" - env: BUILD_VERSION=ffmpeg2 + env: + - BUILD_VERSION=ffmpeg2 + - CMAKE_EXTRA_ARGS="" + - MAKE_TARGET="os_test" os: linux dist: xenial addons: @@ -51,7 +50,10 @@ matrix: - *ff_common - name: "FFmpeg 3 GCC (Ubuntu 18.04 Bionic)" - env: BUILD_VERSION=ffmpeg3 + env: + - BUILD_VERSION=ffmpeg3 + - CMAKE_EXTRA_ARGS="" + - MAKE_TARGET="test" os: linux dist: bionic addons: @@ -64,7 +66,10 @@ matrix: - qt5-default - name: "FFmpeg 4 GCC (Ubuntu 18.04 Bionic)" - env: BUILD_VERSION=ffmpeg4 + env: + - BUILD_VERSION=ffmpeg4 + - CMAKE_EXTRA_ARGS="" + - MAKE_TARGET="test" os: linux dist: bionic addons: @@ -87,7 +92,10 @@ matrix: - libswresample3 - name: "FFmpeg 3 Clang (Ubuntu 18.04 Bionic)" - env: BUILD_VERSION=ffmpeg3 + env: + - BUILD_VERSION=clang_ffmpeg3 + - CMAKE_EXTRA_ARGS="" + - MAKE_TARGET="test" os: linux dist: bionic compiler: clang @@ -101,9 +109,29 @@ matrix: - qt5-default - libomp-dev + + - name: "Coverage (Ubuntu 18.04 Bionic)" + env: + - BUILD_VERSION=coverage + - CMAKE_EXTRA_ARGS="-DENABLE_COVERAGE=1" + - MAKE_TARGET="coverage" + os: linux + dist: bionic + addons: + apt: + sources: + - sourceline: 'ppa:openshot.developers/libopenshot-daily' + - sourceline: 'ppa:beineri/opt-qt-5.12.3-bionic' + packages: + - *ff_common + - qt5-default + - libomp-dev + - lcov + - binutils-common # For c++filt + script: - mkdir -p build; cd build; - - cmake -DCMAKE_BUILD_TYPE:STRING="Debug" ../ + - cmake -DCMAKE_BUILD_TYPE:STRING="Debug" ${CMAKE_EXTRA_ARGS} ../ - make VERBOSE=1 - - make os_test + - make ${MAKE_TARGET} - make install DESTDIR="$BUILD_VERSION" From 5d5b4071c619c809cdfd35fdb02ee6d2b11fbc15 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Mon, 30 Dec 2019 12:46:54 -0500 Subject: [PATCH 27/45] Travis: Upload coverage report to Codacy --- .travis.yml | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index b4cd9024d..4635f86c3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,8 @@ addons: - qtmultimedia5-dev - doxygen - graphviz + - curl + - jq packages: &ff_common # Common set of FFmpeg packages - *p_common - libfdk-aac-dev @@ -38,7 +40,7 @@ matrix: env: - BUILD_VERSION=ffmpeg2 - CMAKE_EXTRA_ARGS="" - - MAKE_TARGET="os_test" + - TEST_TARGET="os_test" os: linux dist: xenial addons: @@ -53,7 +55,7 @@ matrix: env: - BUILD_VERSION=ffmpeg3 - CMAKE_EXTRA_ARGS="" - - MAKE_TARGET="test" + - TEST_TARGET=test os: linux dist: bionic addons: @@ -69,7 +71,7 @@ matrix: env: - BUILD_VERSION=ffmpeg4 - CMAKE_EXTRA_ARGS="" - - MAKE_TARGET="test" + - TEST_TARGET=test os: linux dist: bionic addons: @@ -95,7 +97,7 @@ matrix: env: - BUILD_VERSION=clang_ffmpeg3 - CMAKE_EXTRA_ARGS="" - - MAKE_TARGET="test" + - TEST_TARGET=test os: linux dist: bionic compiler: clang @@ -112,9 +114,9 @@ matrix: - name: "Coverage (Ubuntu 18.04 Bionic)" env: - - BUILD_VERSION=coverage + - BUILD_VERSION=coverage_ffmpeg3 - CMAKE_EXTRA_ARGS="-DENABLE_COVERAGE=1" - - MAKE_TARGET="coverage" + - TEST_TARGET=coverage os: linux dist: bionic addons: @@ -125,13 +127,20 @@ matrix: packages: - *ff_common - qt5-default - - libomp-dev - lcov - binutils-common # For c++filt +before_script: + - CODACY_VERSION="$(curl -Ls https://api.bintray.com/packages/codacy/Binaries/codacy-coverage-reporter/versions/_latest | jq -r .name)" + - if [ "x${TEST_TARGET}" = "xcoverage" ]; then curl -Ls -o codacy-coverage-reporter "https://dl.bintray.com/codacy/Binaries/${CODACY_VERSION}/codacy-coverage-reporter-linux"; chmod +x codacy-coverage-reporter; fi + script: - mkdir -p build; cd build; - cmake -DCMAKE_BUILD_TYPE:STRING="Debug" ${CMAKE_EXTRA_ARGS} ../ - make VERBOSE=1 - - make ${MAKE_TARGET} + - make ${TEST_TARGET} - make install DESTDIR="$BUILD_VERSION" + - cd .. + +after_success: + - if [ "x${TEST_TARGET}" = "xcoverage" ]; then ./codacy-coverage-reporter report -l CPP -r build/coverage.info; fi From 2f037add7d77d53408d5be5dff915034dc07d17e Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Thu, 2 Jan 2020 16:04:54 -0600 Subject: [PATCH 28/45] Revert "Remove JUCE defines" --- include/AudioBufferSource.h | 8 ++++++++ include/AudioReaderSource.h | 8 ++++++++ include/AudioResampler.h | 10 ++++++++++ include/Clip.h | 5 +++++ include/ClipBase.h | 5 +++++ include/Frame.h | 9 +++++++++ 6 files changed, 45 insertions(+) diff --git a/include/AudioBufferSource.h b/include/AudioBufferSource.h index 3a17feb3c..42e55c943 100644 --- a/include/AudioBufferSource.h +++ b/include/AudioBufferSource.h @@ -31,6 +31,14 @@ #ifndef OPENSHOT_AUDIOBUFFERSOURCE_H #define OPENSHOT_AUDIOBUFFERSOURCE_H +/// Do not include the juce unittest headers, because it collides with unittest++ +#define __JUCE_UNITTEST_JUCEHEADER__ + +#ifndef _NDEBUG + /// Define NO debug for JUCE on mac os + #define _NDEBUG +#endif + #include #include "JuceHeader.h" diff --git a/include/AudioReaderSource.h b/include/AudioReaderSource.h index c4e2d2480..33030adf1 100644 --- a/include/AudioReaderSource.h +++ b/include/AudioReaderSource.h @@ -31,6 +31,14 @@ #ifndef OPENSHOT_AUDIOREADERSOURCE_H #define OPENSHOT_AUDIOREADERSOURCE_H +/// Do not include the juce unittest headers, because it collides with unittest++ +#define __JUCE_UNITTEST_JUCEHEADER__ + +#ifndef _NDEBUG + /// Define NO debug for JUCE on mac os + #define _NDEBUG +#endif + #include #include "ReaderBase.h" #include "JuceHeader.h" diff --git a/include/AudioResampler.h b/include/AudioResampler.h index d88eb7cbe..96615cb3f 100644 --- a/include/AudioResampler.h +++ b/include/AudioResampler.h @@ -31,6 +31,16 @@ #ifndef OPENSHOT_RESAMPLER_H #define OPENSHOT_RESAMPLER_H +/// Do not include the juce unittest headers, because it collides with unittest++ +#ifndef __JUCE_UNITTEST_JUCEHEADER__ + #define __JUCE_UNITTEST_JUCEHEADER__ +#endif + +#ifndef _NDEBUG + // Define NO debug for JUCE on mac os + #define _NDEBUG +#endif + #include "AudioBufferSource.h" #include "Exceptions.h" #include "JuceHeader.h" diff --git a/include/Clip.h b/include/Clip.h index 6fa02c9a1..4fdccea98 100644 --- a/include/Clip.h +++ b/include/Clip.h @@ -31,6 +31,11 @@ #ifndef OPENSHOT_CLIP_H #define OPENSHOT_CLIP_H +/// Do not include the juce unittest headers, because it collides with unittest++ +#ifndef __JUCE_UNITTEST_JUCEHEADER__ + #define __JUCE_UNITTEST_JUCEHEADER__ +#endif + #include #include #include diff --git a/include/ClipBase.h b/include/ClipBase.h index cf0d11fab..2890f5d8f 100644 --- a/include/ClipBase.h +++ b/include/ClipBase.h @@ -31,6 +31,11 @@ #ifndef OPENSHOT_CLIPBASE_H #define OPENSHOT_CLIPBASE_H +/// Do not include the juce unittest headers, because it collides with unittest++ +#ifndef __JUCE_UNITTEST_JUCEHEADER__ + #define __JUCE_UNITTEST_JUCEHEADER__ +#endif + #include #include #include "Exceptions.h" diff --git a/include/Frame.h b/include/Frame.h index f4ff54d44..b9b989a50 100644 --- a/include/Frame.h +++ b/include/Frame.h @@ -31,6 +31,15 @@ #ifndef OPENSHOT_FRAME_H #define OPENSHOT_FRAME_H +/// Do not include the juce unittest headers, because it collides with unittest++ +#ifndef __JUCE_UNITTEST_JUCEHEADER__ + #define __JUCE_UNITTEST_JUCEHEADER__ +#endif +#ifndef _NDEBUG + // Define NO debug for JUCE on mac os + #define _NDEBUG +#endif + #include #include #include From 2a0d10be3b01ef6842e7aba467d9951d07199623 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Thu, 2 Jan 2020 16:29:49 -0600 Subject: [PATCH 29/45] Adding back in changes from https://github.com/OpenShot/libopenshot/pull/392 --- .gitlab-ci.yml | 2 +- include/AudioBufferSource.h | 8 -------- include/AudioReaderSource.h | 8 -------- include/AudioResampler.h | 10 ---------- include/Clip.h | 5 ----- include/ClipBase.h | 5 ----- include/Frame.h | 9 --------- 7 files changed, 1 insertion(+), 46 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 612f234cf..624950781 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -46,7 +46,7 @@ mac-builder: - export LIBOPENSHOT_AUDIO_DIR=$CI_PROJECT_DIR/build/install-x64 - mkdir -p build; cd build; - mkdir -p install-x64/python; - - cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -D"CMAKE_INSTALL_PREFIX:PATH=$CI_PROJECT_DIR/build/install-x64" -DCMAKE_CXX_COMPILER=/usr/local/opt/gcc48/bin/g++-4.8 -DCMAKE_C_COMPILER=/usr/local/opt/gcc48/bin/gcc-4.8 -DCMAKE_PREFIX_PATH=/usr/local/qt5/5.5/clang_64 -DPYTHON_INCLUDE_DIR=/Library/Frameworks/Python.framework/Versions/3.6/include/python3.6m -DPYTHON_LIBRARY=/Library/Frameworks/Python.framework/Versions/3.6/lib/libpython3.6.dylib -DPython_FRAMEWORKS=/Library/Frameworks/Python.framework/ -D"CMAKE_BUILD_TYPE:STRING=Debug" -D"CMAKE_OSX_SYSROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk" -D"CMAKE_OSX_DEPLOYMENT_TARGET=10.9" -D"CMAKE_INSTALL_RPATH_USE_LINK_PATH=1" -D"ENABLE_RUBY=0" ../ + - cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -D"CMAKE_INSTALL_PREFIX:PATH=$CI_PROJECT_DIR/build/install-x64" -DCMAKE_CXX_COMPILER=/usr/local/opt/gcc48/bin/g++-4.8 -DCMAKE_C_COMPILER=/usr/local/opt/gcc48/bin/gcc-4.8 -DCMAKE_PREFIX_PATH=/usr/local/qt5/5.5/clang_64 -DPYTHON_INCLUDE_DIR=/Library/Frameworks/Python.framework/Versions/3.6/include/python3.6m -DPYTHON_LIBRARY=/Library/Frameworks/Python.framework/Versions/3.6/lib/libpython3.6.dylib -DPython_FRAMEWORKS=/Library/Frameworks/Python.framework/ -D"CMAKE_BUILD_TYPE:STRING=Release" -D"CMAKE_OSX_SYSROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk" -D"CMAKE_OSX_DEPLOYMENT_TARGET=10.9" -D"CMAKE_INSTALL_RPATH_USE_LINK_PATH=1" -D"ENABLE_RUBY=0" ../ - make - make install - mv install-x64/lib/python3.6/site-packages/*openshot* install-x64/python diff --git a/include/AudioBufferSource.h b/include/AudioBufferSource.h index 42e55c943..3a17feb3c 100644 --- a/include/AudioBufferSource.h +++ b/include/AudioBufferSource.h @@ -31,14 +31,6 @@ #ifndef OPENSHOT_AUDIOBUFFERSOURCE_H #define OPENSHOT_AUDIOBUFFERSOURCE_H -/// Do not include the juce unittest headers, because it collides with unittest++ -#define __JUCE_UNITTEST_JUCEHEADER__ - -#ifndef _NDEBUG - /// Define NO debug for JUCE on mac os - #define _NDEBUG -#endif - #include #include "JuceHeader.h" diff --git a/include/AudioReaderSource.h b/include/AudioReaderSource.h index 33030adf1..c4e2d2480 100644 --- a/include/AudioReaderSource.h +++ b/include/AudioReaderSource.h @@ -31,14 +31,6 @@ #ifndef OPENSHOT_AUDIOREADERSOURCE_H #define OPENSHOT_AUDIOREADERSOURCE_H -/// Do not include the juce unittest headers, because it collides with unittest++ -#define __JUCE_UNITTEST_JUCEHEADER__ - -#ifndef _NDEBUG - /// Define NO debug for JUCE on mac os - #define _NDEBUG -#endif - #include #include "ReaderBase.h" #include "JuceHeader.h" diff --git a/include/AudioResampler.h b/include/AudioResampler.h index 96615cb3f..d88eb7cbe 100644 --- a/include/AudioResampler.h +++ b/include/AudioResampler.h @@ -31,16 +31,6 @@ #ifndef OPENSHOT_RESAMPLER_H #define OPENSHOT_RESAMPLER_H -/// Do not include the juce unittest headers, because it collides with unittest++ -#ifndef __JUCE_UNITTEST_JUCEHEADER__ - #define __JUCE_UNITTEST_JUCEHEADER__ -#endif - -#ifndef _NDEBUG - // Define NO debug for JUCE on mac os - #define _NDEBUG -#endif - #include "AudioBufferSource.h" #include "Exceptions.h" #include "JuceHeader.h" diff --git a/include/Clip.h b/include/Clip.h index 4fdccea98..6fa02c9a1 100644 --- a/include/Clip.h +++ b/include/Clip.h @@ -31,11 +31,6 @@ #ifndef OPENSHOT_CLIP_H #define OPENSHOT_CLIP_H -/// Do not include the juce unittest headers, because it collides with unittest++ -#ifndef __JUCE_UNITTEST_JUCEHEADER__ - #define __JUCE_UNITTEST_JUCEHEADER__ -#endif - #include #include #include diff --git a/include/ClipBase.h b/include/ClipBase.h index 2890f5d8f..cf0d11fab 100644 --- a/include/ClipBase.h +++ b/include/ClipBase.h @@ -31,11 +31,6 @@ #ifndef OPENSHOT_CLIPBASE_H #define OPENSHOT_CLIPBASE_H -/// Do not include the juce unittest headers, because it collides with unittest++ -#ifndef __JUCE_UNITTEST_JUCEHEADER__ - #define __JUCE_UNITTEST_JUCEHEADER__ -#endif - #include #include #include "Exceptions.h" diff --git a/include/Frame.h b/include/Frame.h index b9b989a50..f4ff54d44 100644 --- a/include/Frame.h +++ b/include/Frame.h @@ -31,15 +31,6 @@ #ifndef OPENSHOT_FRAME_H #define OPENSHOT_FRAME_H -/// Do not include the juce unittest headers, because it collides with unittest++ -#ifndef __JUCE_UNITTEST_JUCEHEADER__ - #define __JUCE_UNITTEST_JUCEHEADER__ -#endif -#ifndef _NDEBUG - // Define NO debug for JUCE on mac os - #define _NDEBUG -#endif - #include #include #include From 0bec048acc9e8b0966867c1f9c592c3ac5589499 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Thu, 2 Jan 2020 17:15:49 -0600 Subject: [PATCH 30/45] Copy max_audio_samples with Frame DeepCopy --- src/Frame.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Frame.cpp b/src/Frame.cpp index f01f0c4fb..b3e3126f3 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -114,6 +114,7 @@ void Frame::DeepCopy(const Frame& other) sample_rate = other.sample_rate; pixel_ratio = Fraction(other.pixel_ratio.num, other.pixel_ratio.den); color = other.color; + max_audio_sample = other.max_audio_sample; if (other.image) image = std::shared_ptr(new QImage(*(other.image))); From 1cefa65794b92b2a0d82e4396a25f66a40a4ace1 Mon Sep 17 00:00:00 2001 From: SuslikV Date: Fri, 27 Dec 2019 15:47:28 +0200 Subject: [PATCH 31/45] Skip painter transform by using shortcut Fixes issue for clip being rendered as black rectangle even if the has_video at the frame is set to zero. Co-authored-by: Frank Dana --- src/Timeline.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 86ef2911f..60e6ac81e 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -379,8 +379,9 @@ void Timeline::add_layer(std::shared_ptr new_frame, Clip* source_clip, in } - // Skip out if only an audio frame - if (!source_clip->Waveform() && !source_clip->Reader()->info.has_video) + // Skip out if video was disabled or only an audio frame (no visualisation in use) + if (source_clip->has_video.GetInt(clip_frame_number) == 0 || + (!source_clip->Waveform() && !source_clip->Reader()->info.has_video)) // Skip the rest of the image processing for performance reasons return; From ffa5aab17a29e305329a74e4c304f7cb438d27c5 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Tue, 7 Jan 2020 17:06:22 -0500 Subject: [PATCH 32/45] Bump version for development --- CMakeLists.txt | 4 ++-- src/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 31b0de2cc..cce01d357 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,8 +40,8 @@ For more information, please visit . set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules") ################ PROJECT VERSION #################### -set(PROJECT_VERSION_FULL "0.2.3-dev1") -set(PROJECT_SO_VERSION 17) +set(PROJECT_VERSION_FULL "0.2.4-dev1") +set(PROJECT_SO_VERSION 18) # Remove the dash and anything following, to get the #.#.# version for project() STRING(REGEX REPLACE "\-.*$" "" VERSION_NUM "${PROJECT_VERSION_FULL}") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b684aaec6..41c425c2a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -79,7 +79,7 @@ ENDIF (ImageMagick_FOUND) ################# LIBOPENSHOT-AUDIO ################### # Find JUCE-based openshot Audio libraries -FIND_PACKAGE(OpenShotAudio 0.1.8 REQUIRED) +FIND_PACKAGE(OpenShotAudio 0.1.9 REQUIRED) # Include Juce headers (needed for compile) include_directories(${LIBOPENSHOT_AUDIO_INCLUDE_DIRS}) From a95772079038202e97f5719f6f3d2070a19fb852 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Wed, 8 Jan 2020 16:40:52 -0500 Subject: [PATCH 33/45] FindRESVG: Modernize with targets --- cmake/Modules/FindRESVG.cmake | 135 +++++++++++++++++++++++++++------- src/CMakeLists.txt | 39 +++++----- tests/CMakeLists.txt | 12 +-- 3 files changed, 129 insertions(+), 57 deletions(-) diff --git a/cmake/Modules/FindRESVG.cmake b/cmake/Modules/FindRESVG.cmake index b03a0667e..1d5d1c10f 100644 --- a/cmake/Modules/FindRESVG.cmake +++ b/cmake/Modules/FindRESVG.cmake @@ -1,28 +1,107 @@ -# - Try to find RESVG -# Once done this will define -# RESVG_FOUND - System has RESVG -# RESVG_INCLUDE_DIRS - The RESVG include directories -# RESVG_LIBRARIES - The libraries needed to use RESVG -find_path ( RESVG_INCLUDE_DIR ResvgQt.h - PATHS ${RESVGDIR}/include/resvg - $ENV{RESVGDIR}/include/resvg - $ENV{RESVGDIR}/include - /usr/include/resvg - /usr/include - /usr/local/include/resvg - /usr/local/include ) - -find_library ( RESVG_LIBRARY NAMES resvg - PATHS /usr/lib - /usr/local/lib - $ENV{RESVGDIR} - $ENV{RESVGDIR}/lib ) - -set ( RESVG_LIBRARIES ${RESVG_LIBRARY} ) -set ( RESVG_INCLUDE_DIRS ${RESVG_INCLUDE_DIR} ) - -include ( FindPackageHandleStandardArgs ) -# handle the QUIETLY and REQUIRED arguments and set RESVG_FOUND to TRUE -# if all listed variables are TRUE -find_package_handle_standard_args ( RESVG "Could NOT find RESVG, using Qt SVG parsing instead" RESVG_LIBRARY RESVG_INCLUDE_DIR ) -mark_as_advanced( RESVG_LIBRARY RESVG_INCLUDE_DIR ) +# vim: ts=2 sw=2 +#[=======================================================================[.rst: +FindRESVG +--------- +Try to find the shared-library build of resvg, the Rust SVG library + +IMPORTED targets +^^^^^^^^^^^^^^^^ + +This module defines :prop_tgt:`IMPORTED` target ``RESVG::resvg`` when +the library and headers are found. + +Result Variables +^^^^^^^^^^^^^^^^ + +This module defines the following variables: + +:: + + RESVG_FOUND - Library and header files found + RESVG_INCLUDE_DIRS - Include directory path + RESVG_LIBRARIES - Link path to the library + RESVG_DEFINITIONS - Compiler switches (currently unused) + +Backwards compatibility +^^^^^^^^^^^^^^^^^^^^^^^ + +For compatibility with previous versions of this module, uppercase names +for FFmpeg and for all components are also recognized, and all-uppercase +versions of the cache variables are also created. + +Control variables +^^^^^^^^^^^^^^^^^ + +The following variables can be used to provide path hints to the module: + +RESVGDIR - Set in the calling CMakeLists.txt or on the command line +ENV{RESVGDIR} - An environment variable in the cmake process context + +Copyright (c) 2020, FeRD (Frank Dana) +#]=======================================================================] +include(FindPackageHandleStandardArgs) + +# CMake 3.4+ only: Convert relative paths to absolute +if(CMAKE_VERSION VERSION_GREATER 3.4) + get_filename_component(RESVGDIR ${RESVGDIR} ABSOLUTE + BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}) +endif() + +find_path(RESVG_INCLUDE_DIRS + ResvgQt.h + PATHS + ${RESVGDIR} + ${RESVGDIR}/include + $ENV{RESVGDIR} + $ENV{RESVGDIR}/include + /usr/include + /usr/local/include + PATH_SUFFIXES + resvg + capi/include + resvg/capi/include +) + +find_library(RESVG_LIBRARIES + NAMES resvg + PATHS + ${RESVGDIR} + ${RESVGDIR}/lib + $ENV{RESVGDIR} + $ENV{RESVGDIR}/lib + /usr/lib + /usr/local/lib + PATH_SUFFIXES + resvg + target/release + resvg/target/release +) + +if (RESVG_INCLUDE_DIRS AND RESVG_LIBRARIES) + set(RESVG_FOUND TRUE) +endif() +set(RESVG_LIBRARIES ${RESVG_LIBRARIES} CACHE STRING "The Resvg library link path") +set(RESVG_INCLUDE_DIRS ${RESVG_INCLUDE_DIRS} CACHE STRING "The Resvg include directories") +set(RESVG_DEFINITIONS "" CACHE STRING "The Resvg CFLAGS") + +mark_as_advanced(RESVG_LIBRARIES RESVG_INCLUDE_DIRS RESVG_DEFINITIONS) + +# Give a nice error message if some of the required vars are missing. +find_package_handle_standard_args(RESVG + "Could NOT find RESVG, using Qt SVG parsing instead" + RESVG_LIBRARIES RESVG_INCLUDE_DIRS ) + +# Export target +if(RESVG_FOUND AND NOT TARGET RESVG::resvg) + message(STATUS "Creating IMPORTED target RESVG::resvg") + add_library(RESVG::resvg UNKNOWN IMPORTED) + + set_target_properties(RESVG::resvg PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${RESVG_INCLUDE_DIRS}") + + set_property(TARGET RESVG::resvg APPEND PROPERTY + INTERFACE_COMPILE_DEFINITIONS "${RESVG_DEFINITIONS}") + + set_property(TARGET RESVG::resvg APPEND PROPERTY + IMPORTED_LOCATION "${RESVG_LIBRARIES}") +endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 41c425c2a..fb62de0a2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -100,20 +100,6 @@ IF (ENABLE_BLACKMAGIC) ENDIF (BLACKMAGIC_FOUND) ENDIF (ENABLE_BLACKMAGIC) - -################### RESVG ##################### -# Find resvg library (used for rendering svg files) -FIND_PACKAGE(RESVG) - -# Include resvg headers (optional SVG library) -if (RESVG_FOUND) - include_directories(${RESVG_INCLUDE_DIRS}) - - # define a global var (used in the C++) - add_definitions( -DUSE_RESVG=1 ) - SET(CMAKE_SWIG_FLAGS "-DUSE_RESVG=1") -endif(RESVG_FOUND) - ############### PROFILING ################# #set(PROFILER "/usr/lib/libprofiler.so.0.3.2") #set(PROFILER "/usr/lib/libtcmalloc.so.4") @@ -357,6 +343,27 @@ if (TARGET cppzmq) target_link_libraries(openshot PUBLIC cppzmq) endif() +################### RESVG ##################### +# Migrate some legacy variable names +if(DEFINED RESVGDIR AND NOT DEFINED RESVG_ROOT) + set(RESVG_ROOT ${RESVGDIR}) +endif() +if(DEFINED ENV{RESVGDIR} AND NOT DEFINED RESVG_ROOT) + set(RESVG_ROOT $ENV{RESVGDIR}) +endif() + +# Find resvg library (used for rendering svg files) +FIND_PACKAGE(RESVG) + +# Include resvg headers (optional SVG library) +if (TARGET RESVG::resvg) + #include_directories(${RESVG_INCLUDE_DIRS}) + target_link_libraries(openshot PUBLIC RESVG::resvg) + + # define a global var (used in the C++) + add_definitions( -DUSE_RESVG=1 ) + set(CMAKE_SWIG_FLAGS "-DUSE_RESVG=1") +endif() ############### LINK LIBRARY ################# # Link remaining dependency libraries @@ -368,10 +375,6 @@ if(ImageMagick_FOUND) target_link_libraries(openshot PUBLIC ${ImageMagick_LIBRARIES}) endif() -if(RESVG_FOUND) - target_link_libraries(openshot PUBLIC ${RESVG_LIBRARIES}) -endif() - if(BLACKMAGIC_FOUND) target_link_libraries(openshot PUBLIC ${BLACKMAGIC_LIBRARY_DIR}) endif() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 12f84bb6c..4b2284f63 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -76,7 +76,7 @@ ENDIF (ImageMagick_FOUND) ################# LIBOPENSHOT-AUDIO ################### # Find JUCE-based openshot Audio libraries -FIND_PACKAGE(OpenShotAudio 0.1.8 REQUIRED) +FIND_PACKAGE(OpenShotAudio 0.1.9 REQUIRED) # Include Juce headers (needed for compile) include_directories(${LIBOPENSHOT_AUDIO_INCLUDE_DIRS}) @@ -94,16 +94,6 @@ IF (ENABLE_BLACKMAGIC) ENDIF (ENABLE_BLACKMAGIC) -################### RESVG ##################### -# Find resvg library (used for rendering svg files) -FIND_PACKAGE(RESVG) - -# Include resvg headers (optional SVG library) -if (RESVG_FOUND) - include_directories(${RESVG_INCLUDE_DIRS}) -endif(RESVG_FOUND) - - ############### SET TEST SOURCE FILES ################# SET ( OPENSHOT_TEST_FILES Cache_Tests.cpp From 6aa799cb518f57339f52fdef8f39d74f88e062b1 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Wed, 8 Jan 2020 16:40:52 -0500 Subject: [PATCH 34/45] FindRESVG: Modernize with targets --- cmake/Modules/FindRESVG.cmake | 135 +++++++++++++++++++++++++++------- src/CMakeLists.txt | 39 +++++----- tests/CMakeLists.txt | 12 +-- 3 files changed, 129 insertions(+), 57 deletions(-) diff --git a/cmake/Modules/FindRESVG.cmake b/cmake/Modules/FindRESVG.cmake index b03a0667e..d9942730c 100644 --- a/cmake/Modules/FindRESVG.cmake +++ b/cmake/Modules/FindRESVG.cmake @@ -1,28 +1,107 @@ -# - Try to find RESVG -# Once done this will define -# RESVG_FOUND - System has RESVG -# RESVG_INCLUDE_DIRS - The RESVG include directories -# RESVG_LIBRARIES - The libraries needed to use RESVG -find_path ( RESVG_INCLUDE_DIR ResvgQt.h - PATHS ${RESVGDIR}/include/resvg - $ENV{RESVGDIR}/include/resvg - $ENV{RESVGDIR}/include - /usr/include/resvg - /usr/include - /usr/local/include/resvg - /usr/local/include ) - -find_library ( RESVG_LIBRARY NAMES resvg - PATHS /usr/lib - /usr/local/lib - $ENV{RESVGDIR} - $ENV{RESVGDIR}/lib ) - -set ( RESVG_LIBRARIES ${RESVG_LIBRARY} ) -set ( RESVG_INCLUDE_DIRS ${RESVG_INCLUDE_DIR} ) - -include ( FindPackageHandleStandardArgs ) -# handle the QUIETLY and REQUIRED arguments and set RESVG_FOUND to TRUE -# if all listed variables are TRUE -find_package_handle_standard_args ( RESVG "Could NOT find RESVG, using Qt SVG parsing instead" RESVG_LIBRARY RESVG_INCLUDE_DIR ) -mark_as_advanced( RESVG_LIBRARY RESVG_INCLUDE_DIR ) +# vim: ts=2 sw=2 +#[=======================================================================[.rst: +FindRESVG +--------- +Try to find the shared-library build of resvg, the Rust SVG library + +IMPORTED targets +^^^^^^^^^^^^^^^^ + +This module defines :prop_tgt:`IMPORTED` target ``RESVG::resvg`` when +the library and headers are found. + +Result Variables +^^^^^^^^^^^^^^^^ + +This module defines the following variables: + +:: + + RESVG_FOUND - Library and header files found + RESVG_INCLUDE_DIRS - Include directory path + RESVG_LIBRARIES - Link path to the library + RESVG_DEFINITIONS - Compiler switches (currently unused) + +Backwards compatibility +^^^^^^^^^^^^^^^^^^^^^^^ + +For compatibility with previous versions of this module, uppercase names +for FFmpeg and for all components are also recognized, and all-uppercase +versions of the cache variables are also created. + +Control variables +^^^^^^^^^^^^^^^^^ + +The following variables can be used to provide path hints to the module: + +RESVGDIR - Set in the calling CMakeLists.txt or on the command line +ENV{RESVGDIR} - An environment variable in the cmake process context + +Copyright (c) 2020, FeRD (Frank Dana) +#]=======================================================================] +include(FindPackageHandleStandardArgs) + +# CMake 3.4+ only: Convert relative paths to absolute +if(DEFINED RESVGDIR AND CMAKE_VERSION VERSION_GREATER 3.4) + get_filename_component(RESVGDIR "${RESVGDIR}" ABSOLUTE + BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}) +endif() + +find_path(RESVG_INCLUDE_DIRS + ResvgQt.h + PATHS + ${RESVGDIR} + ${RESVGDIR}/include + $ENV{RESVGDIR} + $ENV{RESVGDIR}/include + /usr/include + /usr/local/include + PATH_SUFFIXES + resvg + capi/include + resvg/capi/include +) + +find_library(RESVG_LIBRARIES + NAMES resvg + PATHS + ${RESVGDIR} + ${RESVGDIR}/lib + $ENV{RESVGDIR} + $ENV{RESVGDIR}/lib + /usr/lib + /usr/local/lib + PATH_SUFFIXES + resvg + target/release + resvg/target/release +) + +if (RESVG_INCLUDE_DIRS AND RESVG_LIBRARIES) + set(RESVG_FOUND TRUE) +endif() +set(RESVG_LIBRARIES ${RESVG_LIBRARIES} CACHE STRING "The Resvg library link path") +set(RESVG_INCLUDE_DIRS ${RESVG_INCLUDE_DIRS} CACHE STRING "The Resvg include directories") +set(RESVG_DEFINITIONS "" CACHE STRING "The Resvg CFLAGS") + +mark_as_advanced(RESVG_LIBRARIES RESVG_INCLUDE_DIRS RESVG_DEFINITIONS) + +# Give a nice error message if some of the required vars are missing. +find_package_handle_standard_args(RESVG + "Could NOT find RESVG, using Qt SVG parsing instead" + RESVG_LIBRARIES RESVG_INCLUDE_DIRS ) + +# Export target +if(RESVG_FOUND AND NOT TARGET RESVG::resvg) + message(STATUS "Creating IMPORTED target RESVG::resvg") + add_library(RESVG::resvg UNKNOWN IMPORTED) + + set_target_properties(RESVG::resvg PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${RESVG_INCLUDE_DIRS}") + + set_property(TARGET RESVG::resvg APPEND PROPERTY + INTERFACE_COMPILE_DEFINITIONS "${RESVG_DEFINITIONS}") + + set_property(TARGET RESVG::resvg APPEND PROPERTY + IMPORTED_LOCATION "${RESVG_LIBRARIES}") +endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 41c425c2a..fb62de0a2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -100,20 +100,6 @@ IF (ENABLE_BLACKMAGIC) ENDIF (BLACKMAGIC_FOUND) ENDIF (ENABLE_BLACKMAGIC) - -################### RESVG ##################### -# Find resvg library (used for rendering svg files) -FIND_PACKAGE(RESVG) - -# Include resvg headers (optional SVG library) -if (RESVG_FOUND) - include_directories(${RESVG_INCLUDE_DIRS}) - - # define a global var (used in the C++) - add_definitions( -DUSE_RESVG=1 ) - SET(CMAKE_SWIG_FLAGS "-DUSE_RESVG=1") -endif(RESVG_FOUND) - ############### PROFILING ################# #set(PROFILER "/usr/lib/libprofiler.so.0.3.2") #set(PROFILER "/usr/lib/libtcmalloc.so.4") @@ -357,6 +343,27 @@ if (TARGET cppzmq) target_link_libraries(openshot PUBLIC cppzmq) endif() +################### RESVG ##################### +# Migrate some legacy variable names +if(DEFINED RESVGDIR AND NOT DEFINED RESVG_ROOT) + set(RESVG_ROOT ${RESVGDIR}) +endif() +if(DEFINED ENV{RESVGDIR} AND NOT DEFINED RESVG_ROOT) + set(RESVG_ROOT $ENV{RESVGDIR}) +endif() + +# Find resvg library (used for rendering svg files) +FIND_PACKAGE(RESVG) + +# Include resvg headers (optional SVG library) +if (TARGET RESVG::resvg) + #include_directories(${RESVG_INCLUDE_DIRS}) + target_link_libraries(openshot PUBLIC RESVG::resvg) + + # define a global var (used in the C++) + add_definitions( -DUSE_RESVG=1 ) + set(CMAKE_SWIG_FLAGS "-DUSE_RESVG=1") +endif() ############### LINK LIBRARY ################# # Link remaining dependency libraries @@ -368,10 +375,6 @@ if(ImageMagick_FOUND) target_link_libraries(openshot PUBLIC ${ImageMagick_LIBRARIES}) endif() -if(RESVG_FOUND) - target_link_libraries(openshot PUBLIC ${RESVG_LIBRARIES}) -endif() - if(BLACKMAGIC_FOUND) target_link_libraries(openshot PUBLIC ${BLACKMAGIC_LIBRARY_DIR}) endif() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 12f84bb6c..4b2284f63 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -76,7 +76,7 @@ ENDIF (ImageMagick_FOUND) ################# LIBOPENSHOT-AUDIO ################### # Find JUCE-based openshot Audio libraries -FIND_PACKAGE(OpenShotAudio 0.1.8 REQUIRED) +FIND_PACKAGE(OpenShotAudio 0.1.9 REQUIRED) # Include Juce headers (needed for compile) include_directories(${LIBOPENSHOT_AUDIO_INCLUDE_DIRS}) @@ -94,16 +94,6 @@ IF (ENABLE_BLACKMAGIC) ENDIF (ENABLE_BLACKMAGIC) -################### RESVG ##################### -# Find resvg library (used for rendering svg files) -FIND_PACKAGE(RESVG) - -# Include resvg headers (optional SVG library) -if (RESVG_FOUND) - include_directories(${RESVG_INCLUDE_DIRS}) -endif(RESVG_FOUND) - - ############### SET TEST SOURCE FILES ################# SET ( OPENSHOT_TEST_FILES Cache_Tests.cpp From 4f2800664baaf9e2ac1afec52ff7e184b9784ba5 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Wed, 8 Jan 2020 17:00:46 -0500 Subject: [PATCH 35/45] Change RESVG image format to ARGB32_Pre --- src/QtImageReader.cpp | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/src/QtImageReader.cpp b/src/QtImageReader.cpp index 7163b0979..e2ee5d7ad 100644 --- a/src/QtImageReader.cpp +++ b/src/QtImageReader.cpp @@ -71,7 +71,7 @@ void QtImageReader::Open() if (!is_open) { bool success = true; - image = std::shared_ptr(new QImage()); + bool loaded = false; #if USE_RESVG == 1 // If defined and found in CMake, utilize the libresvg for parsing @@ -80,38 +80,32 @@ void QtImageReader::Open() if (path.toLower().endsWith(".svg") || path.toLower().endsWith(".svgz")) { ResvgRenderer renderer(path); - if (!renderer.isValid()) { - // Attempt to open file (old method using Qt5 limited SVG parsing) - success = image->load(path); - if (success) { - image = std::shared_ptr(new QImage(image->convertToFormat(QImage::Format_RGBA8888))); - } - } else { + if (renderer.isValid()) { - image = std::shared_ptr(new QImage(renderer.defaultSize(), QImage::Format_RGBA8888)); + image = std::shared_ptr(new QImage(renderer.defaultSize(), QImage::Format_ARGB32_Premultiplied)); image->fill(Qt::transparent); QPainter p(image.get()); renderer.render(&p); p.end(); + loaded = true; } + } +#endif - } else { - // Attempt to open file (old method) + if (!loaded) { + // Attempt to open file using Qt's build in image processing capabilities + image = std::shared_ptr(new QImage()); 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(path); - if (success) - image = std::shared_ptr(new QImage(image->convertToFormat(QImage::Format_RGBA8888))); -#endif - if (!success) + if (!success) { // raise exception throw InvalidFile("File could not be opened.", path.toStdString()); + } + + // Convert to proper format + image = std::shared_ptr(new QImage(image->convertToFormat(QImage::Format_RGBA8888))); // Update image properties info.has_audio = false; From 8e2bcd00d5b2c72cfe360965c448e6cbbe3a58db Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Wed, 8 Jan 2020 18:47:19 -0500 Subject: [PATCH 36/45] Set IMPORTED_NO_SONAME on RESVG target --- cmake/Modules/FindRESVG.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmake/Modules/FindRESVG.cmake b/cmake/Modules/FindRESVG.cmake index d9942730c..c70b2e885 100644 --- a/cmake/Modules/FindRESVG.cmake +++ b/cmake/Modules/FindRESVG.cmake @@ -94,7 +94,7 @@ find_package_handle_standard_args(RESVG # Export target if(RESVG_FOUND AND NOT TARGET RESVG::resvg) message(STATUS "Creating IMPORTED target RESVG::resvg") - add_library(RESVG::resvg UNKNOWN IMPORTED) + add_library(RESVG::resvg SHARED IMPORTED) set_target_properties(RESVG::resvg PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${RESVG_INCLUDE_DIRS}") @@ -102,6 +102,10 @@ if(RESVG_FOUND AND NOT TARGET RESVG::resvg) set_property(TARGET RESVG::resvg APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS "${RESVG_DEFINITIONS}") + # libresvg.so doesn't have a SONAME + set_property(TARGET RESVG::resvg APPEND PROPERTY + IMPORTED_NO_SONAME TRUE) + set_property(TARGET RESVG::resvg APPEND PROPERTY IMPORTED_LOCATION "${RESVG_LIBRARIES}") endif() From 5b31ba112efce8f43ff333ca4bef5126f41f5880 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Wed, 8 Jan 2020 18:47:19 -0500 Subject: [PATCH 37/45] Set IMPORTED_NO_SONAME on RESVG target --- cmake/Modules/FindRESVG.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmake/Modules/FindRESVG.cmake b/cmake/Modules/FindRESVG.cmake index d9942730c..c70b2e885 100644 --- a/cmake/Modules/FindRESVG.cmake +++ b/cmake/Modules/FindRESVG.cmake @@ -94,7 +94,7 @@ find_package_handle_standard_args(RESVG # Export target if(RESVG_FOUND AND NOT TARGET RESVG::resvg) message(STATUS "Creating IMPORTED target RESVG::resvg") - add_library(RESVG::resvg UNKNOWN IMPORTED) + add_library(RESVG::resvg SHARED IMPORTED) set_target_properties(RESVG::resvg PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${RESVG_INCLUDE_DIRS}") @@ -102,6 +102,10 @@ if(RESVG_FOUND AND NOT TARGET RESVG::resvg) set_property(TARGET RESVG::resvg APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS "${RESVG_DEFINITIONS}") + # libresvg.so doesn't have a SONAME + set_property(TARGET RESVG::resvg APPEND PROPERTY + IMPORTED_NO_SONAME TRUE) + set_property(TARGET RESVG::resvg APPEND PROPERTY IMPORTED_LOCATION "${RESVG_LIBRARIES}") endif() From 290c7a7e84050c6d7d5d18a543e0245f77295557 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Thu, 9 Jan 2020 01:59:26 -0500 Subject: [PATCH 38/45] Fix FindRESVG for Windows --- cmake/Modules/FindRESVG.cmake | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/cmake/Modules/FindRESVG.cmake b/cmake/Modules/FindRESVG.cmake index c70b2e885..f49ad1f2a 100644 --- a/cmake/Modules/FindRESVG.cmake +++ b/cmake/Modules/FindRESVG.cmake @@ -94,18 +94,28 @@ find_package_handle_standard_args(RESVG # Export target if(RESVG_FOUND AND NOT TARGET RESVG::resvg) message(STATUS "Creating IMPORTED target RESVG::resvg") - add_library(RESVG::resvg SHARED IMPORTED) + if (WIN32) + # Windows mis-links SHARED library targets + add_library(RESVG::resvg UNKNOWN IMPORTED) + message(STATUS " UNKNOWN IMPORTED target for Win32") + else() + # Linux needs SHARED to link because libresvg has no SONAME + add_library(RESVG::resvg SHARED IMPORTED) + set_property(TARGET RESVG::resvg APPEND PROPERTY + IMPORTED_NO_SONAME TRUE) + message(STATUS " SHARED IMPORTED target with IMPORTED_NO_SONAME") + endif() + + message(STATUS " INCLUDE_DIRECTORIES: ${RESVG_INCLUDE_DIRS}") + message(STATUS " COMPILE_DEFINITIONS: ${RESVG_DEFINITIONS}") + message(STATUS " IMPORTED_LOCATION: ${RESVG_LIBRARIES}") - set_target_properties(RESVG::resvg PROPERTIES + set_property(TARGET RESVG::resvg APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${RESVG_INCLUDE_DIRS}") set_property(TARGET RESVG::resvg APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS "${RESVG_DEFINITIONS}") - # libresvg.so doesn't have a SONAME - set_property(TARGET RESVG::resvg APPEND PROPERTY - IMPORTED_NO_SONAME TRUE) - set_property(TARGET RESVG::resvg APPEND PROPERTY IMPORTED_LOCATION "${RESVG_LIBRARIES}") endif() From 48fc7de326d85fce63d46a1948fe725bf7b85b98 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 11 Jan 2020 17:59:03 -0500 Subject: [PATCH 39/45] Fix RESVG format in GetFrame --- src/QtImageReader.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/QtImageReader.cpp b/src/QtImageReader.cpp index e2ee5d7ad..3e51d769b 100644 --- a/src/QtImageReader.cpp +++ b/src/QtImageReader.cpp @@ -218,11 +218,14 @@ std::shared_ptr QtImageReader::GetFrame(int64_t requested_frame) // Scale image smaller (or use a previous scaled image) if (!cached_image || (max_size.width() != max_width || max_size.height() != max_height)) { + + bool rendered = false; #if USE_RESVG == 1 // 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.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 @@ -230,30 +233,25 @@ std::shared_ptr QtImageReader::GetFrame(int64_t requested_frame) svg_size.scale(max_width, max_height, Qt::KeepAspectRatio); // Create empty QImage - cached_image = std::shared_ptr(new QImage(QSize(svg_size.width(), svg_size.height()), QImage::Format_RGBA8888)); + cached_image = std::shared_ptr(new QImage(QSize(svg_size.width(), svg_size.height()), QImage::Format_ARGB32_Premultiplied)); cached_image->fill(Qt::transparent); // Render SVG into QImage QPainter p(cached_image.get()); renderer.render(&p); p.end(); - } else { - // Resize current rasterized SVG (since we failed to parse original SVG file with resvg) - cached_image = std::shared_ptr(new QImage(image->scaled(max_width, max_height, Qt::KeepAspectRatio, Qt::SmoothTransformation))); - cached_image = std::shared_ptr(new QImage(cached_image->convertToFormat(QImage::Format_RGBA8888))); + rendered = true; } - } else { + } +#endif + + if (!rendered) { // We need to resize the original image to a smaller image (for performance reasons) // Only do this once, to prevent tons of unneeded scaling operations cached_image = std::shared_ptr(new QImage(image->scaled(max_width, max_height, Qt::KeepAspectRatio, Qt::SmoothTransformation))); - cached_image = std::shared_ptr(new QImage(cached_image->convertToFormat(QImage::Format_RGBA8888))); } -#else - // We need to resize the original image to a smaller image (for performance reasons) - // Only do this once, to prevent tons of unneeded scaling operations - cached_image = std::shared_ptr(new QImage(image->scaled(max_width, max_height, Qt::KeepAspectRatio, Qt::SmoothTransformation))); + cached_image = std::shared_ptr(new QImage(cached_image->convertToFormat(QImage::Format_RGBA8888))); -#endif // Set max size (to later determine if max_size is changed) max_size.setWidth(max_width); From 63baee14b93be1228a425e5ac4d17e8457a464d7 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 11 Jan 2020 18:11:02 -0500 Subject: [PATCH 40/45] Define USE_RESVG for openshot target --- src/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fb62de0a2..619d78ed6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -360,8 +360,7 @@ if (TARGET RESVG::resvg) #include_directories(${RESVG_INCLUDE_DIRS}) target_link_libraries(openshot PUBLIC RESVG::resvg) - # define a global var (used in the C++) - add_definitions( -DUSE_RESVG=1 ) + target_compile_definitions(openshot PUBLIC "-DUSE_RESVG=1") set(CMAKE_SWIG_FLAGS "-DUSE_RESVG=1") endif() From 43ff40cf27548bae9e41dcb5806d961227bcc692 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Wed, 8 Jan 2020 19:12:16 -0500 Subject: [PATCH 41/45] Travis: Add libjsoncpp-dev to apt package list --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 4635f86c3..36a3cf06a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,6 +66,7 @@ matrix: packages: - *ff_common - qt5-default + - libjsoncpp-dev - name: "FFmpeg 4 GCC (Ubuntu 18.04 Bionic)" env: @@ -83,6 +84,7 @@ matrix: packages: - *ff_common - qt5-default + - libjsoncpp-dev - libavcodec58 - libavformat58 - libavdevice58 From 8c53f25091d9335713e7354391283b2f4d0c5030 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sun, 12 Jan 2020 05:27:17 -0500 Subject: [PATCH 42/45] FindRESVG: Remove debugging messages --- cmake/Modules/FindRESVG.cmake | 6 ------ 1 file changed, 6 deletions(-) diff --git a/cmake/Modules/FindRESVG.cmake b/cmake/Modules/FindRESVG.cmake index f49ad1f2a..0538eacd5 100644 --- a/cmake/Modules/FindRESVG.cmake +++ b/cmake/Modules/FindRESVG.cmake @@ -97,19 +97,13 @@ if(RESVG_FOUND AND NOT TARGET RESVG::resvg) if (WIN32) # Windows mis-links SHARED library targets add_library(RESVG::resvg UNKNOWN IMPORTED) - message(STATUS " UNKNOWN IMPORTED target for Win32") else() # Linux needs SHARED to link because libresvg has no SONAME add_library(RESVG::resvg SHARED IMPORTED) set_property(TARGET RESVG::resvg APPEND PROPERTY IMPORTED_NO_SONAME TRUE) - message(STATUS " SHARED IMPORTED target with IMPORTED_NO_SONAME") endif() - message(STATUS " INCLUDE_DIRECTORIES: ${RESVG_INCLUDE_DIRS}") - message(STATUS " COMPILE_DEFINITIONS: ${RESVG_DEFINITIONS}") - message(STATUS " IMPORTED_LOCATION: ${RESVG_LIBRARIES}") - set_property(TARGET RESVG::resvg APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${RESVG_INCLUDE_DIRS}") From c83c098bc5afe812a2180cd344387a760491ef85 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Wed, 1 Jan 2020 04:00:07 -0500 Subject: [PATCH 43/45] Use Codecov.io for coverage reporting --- .travis.yml | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1034042d9..f4cb329bd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,7 @@ addons: - qtmultimedia5-dev - doxygen - graphviz + - curl packages: &ff_common # Common set of FFmpeg packages - *p_common - libfdk-aac-dev @@ -34,7 +35,10 @@ addons: matrix: include: - name: "FFmpeg 2 GCC (Ubuntu 16.04 Xenial)" - env: BUILD_VERSION=ffmpeg2 + env: + - BUILD_VERSION=ffmpeg2 + - CMAKE_EXTRA_ARGS="" + - TEST_TARGET="os_test" os: linux dist: xenial addons: @@ -46,7 +50,10 @@ matrix: - *ff_common - name: "FFmpeg 3 GCC (Ubuntu 18.04 Bionic)" - env: BUILD_VERSION=ffmpeg3 + env: + - BUILD_VERSION=ffmpeg3 + - CMAKE_EXTRA_ARGS="" + - TEST_TARGET=test os: linux dist: bionic addons: @@ -59,7 +66,10 @@ matrix: - qt5-default - name: "FFmpeg 4 GCC (Ubuntu 18.04 Bionic)" - env: BUILD_VERSION=ffmpeg4 + env: + - BUILD_VERSION=ffmpeg4 + - CMAKE_EXTRA_ARGS="" + - TEST_TARGET=test os: linux dist: bionic addons: @@ -82,7 +92,10 @@ matrix: - libswresample3 - name: "FFmpeg 3 Clang (Ubuntu 18.04 Bionic)" - env: BUILD_VERSION=ffmpeg3 + env: + - BUILD_VERSION=clang_ffmpeg3 + - CMAKE_EXTRA_ARGS="" + - TEST_TARGET=test os: linux dist: bionic compiler: clang @@ -96,9 +109,31 @@ matrix: - qt5-default - libomp-dev + - name: "Coverage (Ubuntu 18.04 Bionic)" + env: + - BUILD_VERSION=coverage_ffmpeg3 + - CMAKE_EXTRA_ARGS="-DENABLE_COVERAGE=1" + - TEST_TARGET=coverage + os: linux + dist: bionic + addons: + apt: + sources: + - sourceline: 'ppa:openshot.developers/libopenshot-daily' + - sourceline: 'ppa:beineri/opt-qt-5.12.3-bionic' + packages: + - *ff_common + - qt5-default + - lcov + - binutils-common # For c++filt + script: - mkdir -p build; cd build; - cmake -DCMAKE_BUILD_TYPE:STRING="Debug" ../ - make VERBOSE=1 - - make os_test + - make ${TEST_TARGET} - make install DESTDIR="$BUILD_VERSION" + - cd .. + +after_success: + - if [ "x$TEST_TARGET" = "xcoverage" ]; then bash <(curl -s https://codecov.io/bash) -f build/coverage.info || echo "Codecov did not collect coverage reports"; fi From 6d95bcef12c22f4ef73dd7cf87916c0da0c99780 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sun, 12 Jan 2020 08:47:08 -0500 Subject: [PATCH 44/45] Configuration for Codecov --- codecov.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 000000000..dfdc93755 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,15 @@ +codecov: + branch: default +coverage: + status: + project: + default: + base: pr # Only post a status to pull requests + informational: true # Don't block PRs based on coverage stats (yet?) +ignore: + - "/src/examples" + - "/src/Qt/demo" + - "/thirdparty" + - "/doc" + - "/cmake" + - "/*.md" From 6b16162b26b2aad72082823a7ec665cd9f483fe3 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sun, 12 Jan 2020 08:53:19 -0500 Subject: [PATCH 45/45] Reorder Travis matrix --- .travis.yml | 58 ++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/.travis.yml b/.travis.yml index b6b63b066..f449c3f0d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,28 +33,13 @@ addons: - libswresample-dev matrix: - include: - - name: "FFmpeg 2 GCC (Ubuntu 16.04 Xenial)" - env: - - BUILD_VERSION=ffmpeg2 - - CMAKE_EXTRA_ARGS="" - - TEST_TARGET="os_test" - os: linux - dist: xenial - addons: - apt: - sources: - - sourceline: 'ppa:openshot.developers/libopenshot-daily' - - sourceline: 'ppa:beineri/opt-qt-5.10.0-xenial' - packages: - - *ff_common - - name: "FFmpeg 3 GCC (Ubuntu 18.04 Bionic)" + - name: "Coverage (Ubuntu 18.04 Bionic)" env: - - BUILD_VERSION=ffmpeg3 - - CMAKE_EXTRA_ARGS="" - - TEST_TARGET=test + - BUILD_VERSION=coverage_ffmpeg3 + - CMAKE_EXTRA_ARGS="-DENABLE_COVERAGE=1" + - TEST_TARGET=coverage os: linux dist: bionic addons: @@ -65,7 +50,8 @@ matrix: packages: - *ff_common - qt5-default - - libjsoncpp-dev + - lcov + - binutils-common # For c++filt - name: "FFmpeg 4 GCC (Ubuntu 18.04 Bionic)" env: @@ -94,6 +80,23 @@ matrix: - libavresample4 - libswresample3 + - name: "FFmpeg 3 GCC (Ubuntu 18.04 Bionic)" + env: + - BUILD_VERSION=ffmpeg3 + - CMAKE_EXTRA_ARGS="" + - TEST_TARGET=test + os: linux + dist: bionic + addons: + apt: + sources: + - sourceline: 'ppa:openshot.developers/libopenshot-daily' + - sourceline: 'ppa:beineri/opt-qt-5.12.3-bionic' + packages: + - *ff_common + - qt5-default + - libjsoncpp-dev + - name: "FFmpeg 3 Clang (Ubuntu 18.04 Bionic)" env: - BUILD_VERSION=clang_ffmpeg3 @@ -112,23 +115,20 @@ matrix: - qt5-default - libomp-dev - - name: "Coverage (Ubuntu 18.04 Bionic)" + - name: "FFmpeg 2 GCC (Ubuntu 16.04 Xenial)" env: - - BUILD_VERSION=coverage_ffmpeg3 - - CMAKE_EXTRA_ARGS="-DENABLE_COVERAGE=1" - - TEST_TARGET=coverage + - BUILD_VERSION=ffmpeg2 + - CMAKE_EXTRA_ARGS="" + - TEST_TARGET="os_test" os: linux - dist: bionic + dist: xenial addons: apt: sources: - sourceline: 'ppa:openshot.developers/libopenshot-daily' - - sourceline: 'ppa:beineri/opt-qt-5.12.3-bionic' + - sourceline: 'ppa:beineri/opt-qt-5.10.0-xenial' packages: - *ff_common - - qt5-default - - lcov - - binutils-common # For c++filt script: - mkdir -p build; cd build;