From f63c1e0a65c6d1031cd1a55e0dde1a75fd21830d Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Sun, 16 Feb 2020 10:00:18 -0800 Subject: [PATCH 01/79] Newer codecs --- src/FFmpegWriter.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 8d060d77..dec430d1 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -255,7 +255,7 @@ void FFmpegWriter::SetVideoOptions(bool has_video, std::string codec, Fraction f } if (bit_rate >= 1000) // bit_rate is the bitrate in b/s info.video_bit_rate = bit_rate; - if ((bit_rate >= 0) && (bit_rate < 64)) // bit_rate is the bitrate in crf + if ((bit_rate >= 0) && (bit_rate < 256)) // bit_rate is the bitrate in crf info.video_bit_rate = bit_rate; info.interlaced_frame = interlaced; @@ -341,7 +341,7 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va // Was option found? if (option || (name == "g" || name == "qmin" || name == "qmax" || name == "max_b_frames" || name == "mb_decision" || name == "level" || name == "profile" || name == "slices" || name == "rc_min_rate" || name == "rc_max_rate" || - name == "rc_buffer_size" || name == "crf" || name == "cqp")) { + name == "rc_buffer_size" || name == "crf" || name == "cqp" || name == "qp")) { // Check for specific named options if (name == "g") // Set gop_size @@ -462,6 +462,18 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va case AV_CODEC_ID_AV1 : c->bit_rate = 0; av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0); + if (strstr(info.vcodec.c_str(), "svt_av1") != NULL) { + //av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),63), 0); + av_opt_set_int(c->priv_data, "preset", 6, 0); + av_opt_set_int(c->priv_data, "forced-idr",1,0); + } + if (strstr(info.vcodec.c_str(), "rav1e") != NULL) { + //av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),255), 0); + av_opt_set_int(c->priv_data, "speed", 7, 0); + av_opt_set_int(c->priv_data, "tile-rows", 2, 0); + av_opt_set_int(c->priv_data, "tile-columns", 4, 0); + //av_opt_set(c->priv_data, "tile-row", "", 0); + } break; #endif case AV_CODEC_ID_VP8 : @@ -503,6 +515,36 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va c->bit_rate = (int) (mbs); } } +#endif + } else if (name == "qp") { + // encode quality and special settings like lossless + // This might be better in an extra methods as more options + // and way to set quality are possible +#if (LIBAVCODEC_VERSION_MAJOR >= 58) + switch (c->codec_id) { + case AV_CODEC_ID_AV1 : + c->bit_rate = 0; + av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),63), 0); + if (strstr(info.vcodec.c_str(), "svt_av1") != NULL) { + av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),63), 0); + av_opt_set_int(c->priv_data, "preset", 6, 0); + av_opt_set_int(c->priv_data, "forced-idr",1,0); + } + if (strstr(info.vcodec.c_str(), "rav1e") != NULL) { + av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),255), 0); + av_opt_set_int(c->priv_data, "speed", 7, 0); + av_opt_set_int(c->priv_data, "tile-rows", 2, 0); + av_opt_set_int(c->priv_data, "tile-columns", 4, 0); + //av_opt_set(c->priv_data, "tile-row", "", 0); + } + if (strstr(info.vcodec.c_str(), "aom") != NULL) { + // Hack to set tiles; libaom doesn have qp only crf + av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0); + av_opt_set_int(c->priv_data, "tile-rows", 1, 0); // log2 of number of rows + av_opt_set_int(c->priv_data, "tile-columns", 2, 0); // log2 of number of columns + } + break; + } #endif } else { // Set AVOption From 6711c9c788eea07595b9627fb6e428f841dc557f Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Sun, 16 Feb 2020 19:16:45 -0800 Subject: [PATCH 02/79] Minor improvements --- src/FFmpegWriter.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index dec430d1..b3a0b59c 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -463,16 +463,13 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va c->bit_rate = 0; av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0); if (strstr(info.vcodec.c_str(), "svt_av1") != NULL) { - //av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),63), 0); av_opt_set_int(c->priv_data, "preset", 6, 0); av_opt_set_int(c->priv_data, "forced-idr",1,0); } if (strstr(info.vcodec.c_str(), "rav1e") != NULL) { - //av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),255), 0); av_opt_set_int(c->priv_data, "speed", 7, 0); av_opt_set_int(c->priv_data, "tile-rows", 2, 0); av_opt_set_int(c->priv_data, "tile-columns", 4, 0); - //av_opt_set(c->priv_data, "tile-row", "", 0); } break; #endif @@ -524,25 +521,30 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va switch (c->codec_id) { case AV_CODEC_ID_AV1 : c->bit_rate = 0; - av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),63), 0); if (strstr(info.vcodec.c_str(), "svt_av1") != NULL) { av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),63), 0); av_opt_set_int(c->priv_data, "preset", 6, 0); av_opt_set_int(c->priv_data, "forced-idr",1,0); } - if (strstr(info.vcodec.c_str(), "rav1e") != NULL) { + else if (strstr(info.vcodec.c_str(), "rav1e") != NULL) { + // Set number of tiles to a fixed value + // TODO Let user choose number of tiles av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),255), 0); av_opt_set_int(c->priv_data, "speed", 7, 0); - av_opt_set_int(c->priv_data, "tile-rows", 2, 0); - av_opt_set_int(c->priv_data, "tile-columns", 4, 0); - //av_opt_set(c->priv_data, "tile-row", "", 0); + av_opt_set_int(c->priv_data, "tile-rows", 2, 0); // number of rows + av_opt_set_int(c->priv_data, "tile-columns", 4, 0); // number of columns } - if (strstr(info.vcodec.c_str(), "aom") != NULL) { - // Hack to set tiles; libaom doesn have qp only crf + else if (strstr(info.vcodec.c_str(), "aom") != NULL) { + // Set number of tiles to a fixed value + // TODO Let user choose number of tiles + // libaom doesn't have qp only crf av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0); av_opt_set_int(c->priv_data, "tile-rows", 1, 0); // log2 of number of rows av_opt_set_int(c->priv_data, "tile-columns", 2, 0); // log2 of number of columns } + else { + av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0); + } break; } #endif From e03cd87373faf119057da3914af6dda1d06e9fa2 Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Mon, 17 Feb 2020 10:56:00 -0800 Subject: [PATCH 03/79] Initial svt-hevc (h.265) encoder support added --- src/FFmpegWriter.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index b3a0b59c..beb19534 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -492,7 +492,14 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va } break; case AV_CODEC_ID_HEVC : - av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value), 51), 0); // 0-51 + if (strstr(info.vcodec.c_str(), "svt_hevc") != NULL) { + av_opt_set_int(c->priv_data, "preset", 7, 0); + av_opt_set_int(c->priv_data, "forced-idr",1,0); + av_opt_set_int(c->priv_data, "qp",std::min(std::stoi(value), 51),0); + } + else { + av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value), 51), 0); // 0-51 + } if (std::stoi(value) == 0) { av_opt_set(c->priv_data, "preset", "veryslow", 0); av_opt_set_int(c->priv_data, "lossless", 1, 0); @@ -545,6 +552,13 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va else { av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0); } + case AV_CODEC_ID_HEVC : + c->bit_rate = 0; + if (strstr(info.vcodec.c_str(), "svt_hevc") != NULL) { + av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),51), 0); + av_opt_set_int(c->priv_data, "preset", 7, 0); + av_opt_set_int(c->priv_data, "forced-idr",1,0); + } break; } #endif From e7bd91814a239a0d4a3bc93b655173257f51e21e Mon Sep 17 00:00:00 2001 From: SuslikV Date: Mon, 24 Feb 2020 09:35:13 +0200 Subject: [PATCH 04/79] Change frame rate detection Make FPS detection of the input file similar to the FFmpeg's own re-encoding algorithm. --- src/FFmpegReader.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index b548fa8f..9b0f7bcb 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -706,9 +706,16 @@ void FFmpegReader::UpdateVideoInfo() { info.vcodec = pCodecCtx->codec->name; info.video_bit_rate = (pFormatCtx->bit_rate / 8); - // set frames per second (fps) - info.fps.num = pStream->avg_frame_rate.num; - info.fps.den = pStream->avg_frame_rate.den; + // Frame rate from the container and codec + AVRational framerate = av_guess_frame_rate(pFormatCtx, pStream, NULL); + info.fps.num = framerate.num; + info.fps.den = framerate.den; + + ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::UpdateVideoInfo", "info.fps.num", info.fps.num, "info.fps.den", info.fps.den); + + // TODO: remove excessive debug info in the next releases + // The debug info below is just for comparison and troubleshooting on users side during the transition period + ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::UpdateVideoInfo (pStream->avg_frame_rate)", "num", pStream->avg_frame_rate.num, "den", pStream->avg_frame_rate.den); if (pStream->sample_aspect_ratio.num != 0) { info.pixel_ratio.num = pStream->sample_aspect_ratio.num; From ddd52460e17f37d7078ee5ac4ae3335301c9ea86 Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Sun, 1 Mar 2020 16:59:06 -0800 Subject: [PATCH 05/79] Fix handling of RAWIMAGE under ffmpeg 4 --- src/FFmpegWriter.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index beb19534..cc71e11a 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -842,6 +842,9 @@ void FFmpegWriter::flush_encoders() { #if (LIBAVFORMAT_VERSION_MAJOR < 58) if (info.has_video && video_codec && AV_GET_CODEC_TYPE(video_st) == AVMEDIA_TYPE_VIDEO && (oc->oformat->flags & AVFMT_RAWPICTURE) && AV_FIND_DECODER_CODEC_ID(video_st) == AV_CODEC_ID_RAWVIDEO) return; +#else + if (info.has_video && video_codec && AV_GET_CODEC_TYPE(video_st) == AVMEDIA_TYPE_VIDEO && AV_FIND_DECODER_CODEC_ID(video_st) == AV_CODEC_ID_RAWVIDEO) + return; #endif int error_code = 0; @@ -1991,10 +1994,14 @@ void FFmpegWriter::process_video_packet(std::shared_ptr frame) { bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *frame_final) { #if (LIBAVFORMAT_VERSION_MAJOR >= 58) ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet", "frame->number", frame->number, "oc->oformat->flags", oc->oformat->flags); + + if (video_st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && + video_st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO) { #else ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet", "frame->number", frame->number, "oc->oformat->flags & AVFMT_RAWPICTURE", oc->oformat->flags & AVFMT_RAWPICTURE); if (oc->oformat->flags & AVFMT_RAWPICTURE) { +#endif // Raw video case. AVPacket pkt; av_init_packet(&pkt); @@ -2019,7 +2026,6 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *fra AV_FREE_PACKET(&pkt); } else -#endif { AVPacket pkt; From 6476f930bb601cebe7f8470776e7a4f836e46ca6 Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Sun, 1 Mar 2020 17:10:39 -0800 Subject: [PATCH 06/79] Simplify fix for RAWVIDEO handling for ffmpeg 4+ --- src/FFmpegWriter.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index cc71e11a..cc4b3d3a 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -1995,8 +1995,7 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *fra #if (LIBAVFORMAT_VERSION_MAJOR >= 58) ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet", "frame->number", frame->number, "oc->oformat->flags", oc->oformat->flags); - if (video_st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && - video_st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO) { + if (AV_GET_CODEC_TYPE(video_st) == AVMEDIA_TYPE_VIDEO && AV_FIND_DECODER_CODEC_ID(video_st) == AV_CODEC_ID_RAWVIDEO) { #else ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet", "frame->number", frame->number, "oc->oformat->flags & AVFMT_RAWPICTURE", oc->oformat->flags & AVFMT_RAWPICTURE); From 20fffc404cb920f860d8b208f659d6f06be9e8b0 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Mon, 9 Mar 2020 09:10:55 -0400 Subject: [PATCH 07/79] bindings: Relative paths, overridable --- .gitlab-ci.yml | 15 ++--- src/bindings/python/CMakeLists.txt | 52 ++++++++------- src/bindings/ruby/CMakeLists.txt | 102 +++++++++++++++++------------ 3 files changed, 94 insertions(+), 75 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f998c3d4..6b2645d8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,13 +16,11 @@ linux-builder: - unzip artifacts.zip - 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" -D"CMAKE_BUILD_TYPE:STRING=Release" -D"USE_SYSTEM_JSONCPP=0" ../ + - cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -D"CMAKE_INSTALL_PREFIX:PATH=$CI_PROJECT_DIR/build/install-x64" -D"PYTHON_MODULE_PATH=python" -D"RUBY_MODULE_PATH=ruby" -DCMAKE_BUILD_TYPE:STRING=Release -DUSE_SYSTEM_JSONCPP=0 ../ - make - make install - make doc - ~/auto-update-docs "$CI_PROJECT_DIR/build" "$CI_COMMIT_REF_NAME" - - mv install-x64/lib/python3.4/site-packages/*openshot* install-x64/python - echo -e "CI_PROJECT_NAME:$CI_PROJECT_NAME\nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME\nCI_COMMIT_SHA:$CI_COMMIT_SHA\nCI_JOB_ID:$CI_JOB_ID" > "install-x64/share/$CI_PROJECT_NAME" - git log $(git describe --tags --abbrev=0 @^)..@ --oneline --pretty=format:"%C(auto,yellow)%h%C(auto,magenta)% %C(auto,blue)%>(12,trunc)%ad %C(auto,green)%<(25,trunc)%aN%C(auto,reset)%s%C(auto,red)% gD% D" --date=short > "install-x64/share/$CI_PROJECT_NAME.log" when: always @@ -45,11 +43,9 @@ mac-builder: - unzip artifacts.zip - 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=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" ../ + - 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_MODULE_PATH=python -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 - echo -e "CI_PROJECT_NAME:$CI_PROJECT_NAME\nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME\nCI_COMMIT_SHA:$CI_COMMIT_SHA\nCI_JOB_ID:$CI_JOB_ID" > "install-x64/share/$CI_PROJECT_NAME" - git log $(git describe --tags --abbrev=0 @^)..@ --oneline --pretty=format:"%C(auto,yellow)%h%C(auto,magenta)% %C(auto,blue)%>(12,trunc)%ad %C(auto,green)%<(25,trunc)%aN%C(auto,reset)%s%C(auto,red)% gD% D" --date=short > "install-x64/share/$CI_PROJECT_NAME.log" when: always @@ -73,9 +69,8 @@ windows-builder-x64: - $env:RESVGDIR = "C:\msys64\usr" - $env:Path = "C:\msys64\mingw64\bin;C:\msys64\mingw64\lib;C:\msys64\usr\lib\cmake\UnitTest++;C:\msys64\home\jonathan\depot_tools;C:\msys64\usr;C:\msys64\usr\lib;" + $env:Path; - New-Item -ItemType Directory -Force -Path build - - New-Item -ItemType Directory -Force -Path build\install-x64\python - cd build - - cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -D"CMAKE_INSTALL_PREFIX:PATH=$CI_PROJECT_DIR\build\install-x64" -G "MSYS Makefiles" -DCMAKE_MAKE_PROGRAM=mingw32-make -D"CMAKE_BUILD_TYPE:STRING=Release" ../ + - cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -D"CMAKE_INSTALL_PREFIX:PATH=$CI_PROJECT_DIR\build\install-x64" -D"PYTHON_MODULE_PATH=python" -D"RUBY_MODULE_PATH=ruby" -G "MSYS Makefiles" -DCMAKE_MAKE_PROGRAM=mingw32-make -D"CMAKE_BUILD_TYPE:STRING=Release" ../ - mingw32-make install - Move-Item -Force -path "install-x64\lib\python3.7\site-packages\*openshot*" -destination "install-x64\python\" - New-Item -path "install-x64/share/" -Name "$CI_PROJECT_NAME" -Value "CI_PROJECT_NAME:$CI_PROJECT_NAME`nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME`nCI_COMMIT_SHA:$CI_COMMIT_SHA`nCI_JOB_ID:$CI_JOB_ID" -ItemType file -force @@ -102,11 +97,9 @@ windows-builder-x86: - $env:RESVGDIR = "C:\msys32\usr" - $env:Path = "C:\msys32\mingw32\bin;C:\msys32\mingw32\lib;C:\msys32\usr\lib\cmake\UnitTest++;C:\msys32\home\jonathan\depot_tools;C:\msys32\usr;C:\msys32\usr\lib;" + $env:Path; - New-Item -ItemType Directory -Force -Path build - - New-Item -ItemType Directory -Force -Path build\install-x86\python - cd build - - cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -D"CMAKE_INSTALL_PREFIX:PATH=$CI_PROJECT_DIR\build\install-x86" -G "MSYS Makefiles" -DCMAKE_MAKE_PROGRAM=mingw32-make -D"CMAKE_BUILD_TYPE:STRING=Release" -D"CMAKE_CXX_FLAGS=-m32" -D"CMAKE_EXE_LINKER_FLAGS=-Wl,--large-address-aware" -D"CMAKE_C_FLAGS=-m32" ../ + - cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -D"CMAKE_INSTALL_PREFIX:PATH=$CI_PROJECT_DIR\build\install-x86" -D"PYTHON_MODULE_PATH=python" -D"RUBY_MODULE_PATH=ruby" -G "MSYS Makefiles" -DCMAKE_MAKE_PROGRAM=mingw32-make -D"CMAKE_BUILD_TYPE:STRING=Release" -D"CMAKE_CXX_FLAGS=-m32" -D"CMAKE_EXE_LINKER_FLAGS=-Wl,--large-address-aware" -D"CMAKE_C_FLAGS=-m32" ../ - mingw32-make install - - Move-Item -Force -path "install-x86\lib\python3.7\site-packages\*openshot*" -destination "install-x86\python\" - New-Item -path "install-x86/share/" -Name "$CI_PROJECT_NAME" -Value "CI_PROJECT_NAME:$CI_PROJECT_NAME`nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME`nCI_COMMIT_SHA:$CI_COMMIT_SHA`nCI_JOB_ID:$CI_JOB_ID" -ItemType file -force - $PREV_GIT_LABEL=(git describe --tags --abbrev=0 '@^') - git log "$PREV_GIT_LABEL..@" --oneline --pretty=format:"%C(auto,yellow)%h%C(auto,magenta)% %C(auto,blue)%>(12,trunc)%ad %C(auto,green)%<(25,trunc)%aN%C(auto,reset)%s%C(auto,red)% gD% D" --date=short > "install-x86/share/$CI_PROJECT_NAME.log" diff --git a/src/bindings/python/CMakeLists.txt b/src/bindings/python/CMakeLists.txt index 21405f63..42a15c8e 100644 --- a/src/bindings/python/CMakeLists.txt +++ b/src/bindings/python/CMakeLists.txt @@ -71,36 +71,44 @@ if (PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND) ### Set output name of target set_target_properties(${SWIG_MODULE_pyopenshot_REAL_NAME} PROPERTIES - PREFIX "_" OUTPUT_NAME "openshot") + PREFIX "_" OUTPUT_NAME "openshot") ### Link the new python wrapper library with libopenshot - target_link_libraries(${SWIG_MODULE_pyopenshot_REAL_NAME} - PUBLIC ${PYTHON_LIBRARIES} openshot) + target_link_libraries(${SWIG_MODULE_pyopenshot_REAL_NAME} PUBLIC + ${PYTHON_LIBRARIES} openshot) - ### Check if the following Debian-friendly python module path exists - SET(PYTHON_MODULE_PATH "${CMAKE_INSTALL_PREFIX}/lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/dist-packages") - if (NOT EXISTS ${PYTHON_MODULE_PATH}) + ######### INSTALL PATH ######## + if (NOT DEFINED PYTHON_MODULE_PATH AND DEFINED $ENV{PYTHON_MODULE_PATH}) + set(PYTHON_MODULE_PATH $ENV{PYTHON_MODULE_PATH}) + endif() - ### Calculate the python module path (using distutils) - execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "\ + if (NOT DEFINED PYTHON_MODULE_PATH) + if (WIN32 OR APPLE) + set (PYTHON_MODULE_PATH "python") + endif() + + if (UNIX AND NOT APPLE) + ### Check if the following Debian-friendly python module path exists + set(PYTHON_MODULE_PATH "lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/dist-packages") + if (NOT EXISTS "${CMAKE_INSTALL_PREFIX}/${PYTHON_MODULE_PATH}") + + ### Calculate the python module path (using distutils) + execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "\ from distutils.sysconfig import get_python_lib; \ -print( get_python_lib( plat_specific=True, prefix='${CMAKE_INSTALL_PREFIX}' ) )" - OUTPUT_VARIABLE _ABS_PYTHON_MODULE_PATH - OUTPUT_STRIP_TRAILING_WHITESPACE ) +print( get_python_lib( plat_specific=True, prefix='' ) )" + OUTPUT_VARIABLE PYTHON_MODULE_PATH + OUTPUT_STRIP_TRAILING_WHITESPACE ) + endif() + endif() + endif() - GET_FILENAME_COMPONENT(_ABS_PYTHON_MODULE_PATH - "${_ABS_PYTHON_MODULE_PATH}" ABSOLUTE) - FILE(RELATIVE_PATH _REL_PYTHON_MODULE_PATH - ${CMAKE_INSTALL_PREFIX} ${_ABS_PYTHON_MODULE_PATH}) - SET(PYTHON_MODULE_PATH ${_ABS_PYTHON_MODULE_PATH}) - endif() - message("PYTHON_MODULE_PATH: ${PYTHON_MODULE_PATH}") + message(STATUS "PYTHON_MODULE_PATH: ${CMAKE_INSTALL_PREFIX}/${PYTHON_MODULE_PATH}") ############### INSTALL HEADERS & LIBRARY ################ ### Install Python bindings - INSTALL(TARGETS ${SWIG_MODULE_pyopenshot_REAL_NAME} - LIBRARY DESTINATION ${PYTHON_MODULE_PATH} ) - INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/openshot.py - DESTINATION ${PYTHON_MODULE_PATH} ) + install(TARGETS ${SWIG_MODULE_pyopenshot_REAL_NAME} + DESTINATION ${PYTHON_MODULE_PATH} ) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/openshot.py + DESTINATION ${PYTHON_MODULE_PATH} ) endif () diff --git a/src/bindings/ruby/CMakeLists.txt b/src/bindings/ruby/CMakeLists.txt index bf7e6421..8be7d792 100644 --- a/src/bindings/ruby/CMakeLists.txt +++ b/src/bindings/ruby/CMakeLists.txt @@ -36,56 +36,74 @@ if (POLICY CMP0086) cmake_policy(SET CMP0086 OLD) endif() -FIND_PACKAGE(Ruby) -IF (RUBY_FOUND) +find_package(Ruby) +if (NOT RUBY_FOUND) + return() +endif() - ### Include the Ruby header files - INCLUDE_DIRECTORIES(${RUBY_INCLUDE_DIRS}) - INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) +### Include the Ruby header files +INCLUDE_DIRECTORIES(${RUBY_INCLUDE_DIRS}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) - ### Enable C++ in SWIG - set_property(SOURCE openshot.i PROPERTY CPLUSPLUS ON) - set_property(SOURCE openshot.i PROPERTY SWIG_MODULE_NAME openshot) +### Enable C++ in SWIG +set_property(SOURCE openshot.i PROPERTY CPLUSPLUS ON) +set_property(SOURCE openshot.i PROPERTY SWIG_MODULE_NAME openshot) - ### Suppress a ton of warnings in the generated SWIG C++ code - set(SWIG_CXX_FLAGS "-Wno-unused-variable -Wno-unused-function -Wno-deprecated-copy -Wno-class-memaccess -Wno-cast-function-type \ +### Suppress a ton of warnings in the generated SWIG C++ code +set(SWIG_CXX_FLAGS "-Wno-unused-variable -Wno-unused-function -Wno-deprecated-copy -Wno-class-memaccess -Wno-cast-function-type \ -Wno-unused-parameter -Wno-catch-value -Wno-sign-compare -Wno-ignored-qualifiers") - separate_arguments(sw_flags UNIX_COMMAND ${SWIG_CXX_FLAGS}) - set_property(SOURCE openshot.i PROPERTY GENERATED_COMPILE_OPTIONS ${sw_flags}) +separate_arguments(sw_flags UNIX_COMMAND ${SWIG_CXX_FLAGS}) +set_property(SOURCE openshot.i PROPERTY GENERATED_COMPILE_OPTIONS ${sw_flags}) - ### Take include dirs from target, automatically if possible - if (CMAKE_VERSION VERSION_GREATER 3.13) - set_property(SOURCE openshot.i PROPERTY USE_TARGET_INCLUDE_DIRECTORIES True) - else () - set_property(SOURCE openshot.i PROPERTY INCLUDE_DIRECTORIES $) - endif () +### Take include dirs from target, automatically if possible +if (CMAKE_VERSION VERSION_GREATER 3.13) + set_property(SOURCE openshot.i PROPERTY USE_TARGET_INCLUDE_DIRECTORIES True) +else () + set_property(SOURCE openshot.i PROPERTY INCLUDE_DIRECTORIES $) +endif () - ### Add the SWIG interface file (which defines all the SWIG methods) - if (CMAKE_VERSION VERSION_LESS 3.8.0) - swig_add_module(rbopenshot ruby openshot.i) - else() - swig_add_library(rbopenshot LANGUAGE ruby SOURCES openshot.i) - endif() +### Add the SWIG interface file (which defines all the SWIG methods) +if (CMAKE_VERSION VERSION_LESS 3.8.0) + swig_add_module(rbopenshot ruby openshot.i) +else() + swig_add_library(rbopenshot LANGUAGE ruby SOURCES openshot.i) +endif() - ### Set name of target (with no prefix, since Ruby does not like that) - SET_TARGET_PROPERTIES(${SWIG_MODULE_rbopenshot_REAL_NAME} PROPERTIES - PREFIX "" OUTPUT_NAME "openshot") +### Set name of target (with no prefix, since Ruby does not like that) +set_target_properties(${SWIG_MODULE_rbopenshot_REAL_NAME} PROPERTIES + PREFIX "" OUTPUT_NAME "openshot") - ### Link the new Ruby wrapper library with libopenshot - target_link_libraries(${SWIG_MODULE_rbopenshot_REAL_NAME} - ${RUBY_LIBRARY} openshot) +### Link the new Ruby wrapper library with libopenshot +target_link_libraries(${SWIG_MODULE_rbopenshot_REAL_NAME} PUBLIC + ${RUBY_LIBRARY} openshot) - ### FIND THE RUBY INTERPRETER (AND THE LOAD_PATH FOLDER) - EXECUTE_PROCESS(COMMAND ${RUBY_EXECUTABLE} - -r rbconfig -e "print RbConfig::CONFIG['vendorarchdir']" - OUTPUT_VARIABLE RUBY_VENDOR_ARCH_DIR) - MESSAGE(STATUS "Ruby executable: ${RUBY_EXECUTABLE}") - MESSAGE(STATUS "Ruby vendor arch dir: ${RUBY_VENDOR_ARCH_DIR}") - MESSAGE(STATUS "Ruby include path: ${RUBY_INCLUDE_PATH}") +######### INSTALL PATH ######## +if (NOT DEFINED RUBY_MODULE_PATH AND DEFINED $ENV{RUBY_MODULE_PATH}) + set(RUBY_MODULE_PATH $ENV{RUBY_MODULE_PATH}) +endif() - ############### INSTALL HEADERS & LIBRARY ################ - # Install Ruby bindings - install(TARGETS ${SWIG_MODULE_rbopenshot_REAL_NAME} - LIBRARY DESTINATION ${RUBY_VENDOR_ARCH_DIR} ) +if (NOT DEFINED RUBY_MODULE_PATH) + if (WIN32 OR APPLE) + set (RUBY_MODULE_PATH "ruby") + endif() + + if (UNIX AND NOT APPLE) + ### FIND THE RUBY INTERPRETER (AND THE LOAD_PATH FOLDER) + execute_process(COMMAND ${RUBY_EXECUTABLE} -r rbconfig + -e "dir = RbConfig::CONFIG['vendorarchdir']" + -e "dir.start_with?(RbConfig::CONFIG['prefix']) && dir.sub!(RbConfig::CONFIG['prefix']+'/', '')" + -e "p dir" + OUTPUT_VARIABLE RUBY_MODULE_PATH + OUTPUT_STRIP_TRAILING_WHITESPACE ) + # Ruby quotes its output strings + string(REPLACE "\"" "" RUBY_MODULE_PATH "${RUBY_MODULE_PATH}") + endif() +endif() + +message(STATUS "RUBY_MODULE_PATH: ${CMAKE_INSTALL_PREFIX}/${RUBY_MODULE_PATH}") + +############### INSTALL HEADERS & LIBRARY ################ +# Install Ruby bindings +install(TARGETS ${SWIG_MODULE_rbopenshot_REAL_NAME} + DESTINATION ${RUBY_MODULE_PATH} ) -ENDIF (RUBY_FOUND) From f5ab99fa9e3a0fdf5bf11367468227bc493945d6 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Mon, 9 Mar 2020 09:20:04 -0400 Subject: [PATCH 08/79] Travis: Use CMAKE_INSTALL_PREFIX --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a89aa74f..c7aa1958 100644 --- a/.travis.yml +++ b/.travis.yml @@ -157,10 +157,10 @@ matrix: script: - mkdir -p build; cd build; - - cmake -DCMAKE_BUILD_TYPE:STRING="Debug" ${CMAKE_EXTRA_ARGS} ../ + - cmake -DCMAKE_INSTALL_PREFIX:PATH="$TRAVIS_OS_NAME-x64" -DCMAKE_BUILD_TYPE:STRING="Debug" ${CMAKE_EXTRA_ARGS} ../ - make VERBOSE=1 - make ${TEST_TARGET} - - make install DESTDIR="$BUILD_VERSION" + - make install - cd .. after_success: From c28a8bf4edc82a43c6eabbdd50335d15be4da5c8 Mon Sep 17 00:00:00 2001 From: SuslikV Date: Mon, 16 Mar 2020 14:41:49 +0200 Subject: [PATCH 09/79] Fix float to int16_t conversion Float values after mix or gain applied can exceed the (1.0; -1.0) range. This caused distortion in audio instead of limiting values at max. --- src/FFmpegWriter.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index e6a1d180..2b97ba91 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -1525,11 +1525,23 @@ void FFmpegWriter::write_audio_packets(bool is_final) { // Calculate total samples total_frame_samples = samples_in_frame * channels_in_frame; - // Translate audio sample values back to 16 bit integers - for (int s = 0; s < total_frame_samples; s++, frame_position++) - // Translate sample value and copy into buffer - all_queued_samples[frame_position] = int(frame_samples_float[s] * (1 << 15)); + // Translate audio sample values back to 16 bit integers with saturation + float valF; + int16_t conv; + const int16_t max16 = 32767; + const int16_t min16 = -32768; + for (int s = 0; s < total_frame_samples; s++, frame_position++) { + valF = frame_samples_float[s] * (1 << 15); + if (valF > max16) + conv = max16; + else if (valF < min16) + conv = min16; + else + conv = int(valF + 32768.5) - 32768; // +0.5 is for rounding + // Copy into buffer + all_queued_samples[frame_position] = conv; + } // Deallocate float array delete[] frame_samples_float; From dff42011ff41cc1c2e1799e5e4601c45f743fe7e Mon Sep 17 00:00:00 2001 From: SuslikV Date: Mon, 16 Mar 2020 14:49:41 +0200 Subject: [PATCH 10/79] Restore default gain when adding audio Incorrect conversion of float to int16_t caused distortion that was mistakenly perceived as clipping. Now because the convertion was fixed, there is no more sense to reduce input gain of the source. --- src/FFmpegReader.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index 2b03994b..080a652d 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -1627,9 +1627,8 @@ void FFmpegReader::ProcessAudioPacket(int64_t requested_frame, int64_t target_fr else partial_frame = true; - // Add samples for current channel to the frame. Reduce the volume to 98%, to prevent - // some louder samples from maxing out at 1.0 (not sure why this happens) - f->AddAudio(true, channel_filter, start, iterate_channel_buffer, samples, 0.98f); + // Add samples for current channel to the frame. + f->AddAudio(true, channel_filter, start, iterate_channel_buffer, samples, 1.0f); // Debug output ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ProcessAudioPacket (f->AddAudio)", "frame", starting_frame_number, "start", start, "samples", samples, "channel", channel_filter, "partial_frame", partial_frame, "samples_per_frame", samples_per_frame); From 54a82ff0a68fb39bb875b63157cc91c549771647 Mon Sep 17 00:00:00 2001 From: SuslikV Date: Mon, 16 Mar 2020 16:22:41 +0200 Subject: [PATCH 11/79] Fix test sample values Previously, x0.98 gain was applied for all input audio sources. As it's no longer needed, the new values should be specified as reference for the tests. --- tests/FFmpegReader_Tests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/FFmpegReader_Tests.cpp b/tests/FFmpegReader_Tests.cpp index 0a8620c9..a1f7a42d 100644 --- a/tests/FFmpegReader_Tests.cpp +++ b/tests/FFmpegReader_Tests.cpp @@ -76,8 +76,8 @@ TEST(FFmpegReader_Check_Audio_File) CHECK_CLOSE(0.0f, samples[50], 0.00001); CHECK_CLOSE(0.0f, samples[100], 0.00001); CHECK_CLOSE(0.0f, samples[200], 0.00001); - CHECK_CLOSE(0.160781f, samples[230], 0.00001); - CHECK_CLOSE(-0.06125f, samples[300], 0.00001); + CHECK_CLOSE(0.16406f, samples[230], 0.00001); + CHECK_CLOSE(-0.06250f, samples[300], 0.00001); // Close reader r.Close(); From bb20a9b36993d27c3c5cb5944ff8217e0a786445 Mon Sep 17 00:00:00 2001 From: Frank Dana Date: Mon, 23 Mar 2020 05:26:12 -0400 Subject: [PATCH 12/79] ruby/CMakeLists: Lowercase commands --- src/bindings/ruby/CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bindings/ruby/CMakeLists.txt b/src/bindings/ruby/CMakeLists.txt index 8be7d792..c3c113aa 100644 --- a/src/bindings/ruby/CMakeLists.txt +++ b/src/bindings/ruby/CMakeLists.txt @@ -25,8 +25,8 @@ ################################################################################ ############### RUBY BINDINGS ################ -FIND_PACKAGE(SWIG 3.0 REQUIRED) -INCLUDE(${SWIG_USE_FILE}) +find_package(SWIG 3.0 REQUIRED) +include(${SWIG_USE_FILE}) ### Enable some legacy SWIG behaviors, in newer CMAKEs if (POLICY CMP0078) @@ -42,8 +42,8 @@ if (NOT RUBY_FOUND) endif() ### Include the Ruby header files -INCLUDE_DIRECTORIES(${RUBY_INCLUDE_DIRS}) -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${RUBY_INCLUDE_DIRS}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) ### Enable C++ in SWIG set_property(SOURCE openshot.i PROPERTY CPLUSPLUS ON) @@ -105,5 +105,5 @@ message(STATUS "RUBY_MODULE_PATH: ${CMAKE_INSTALL_PREFIX}/${RUBY_MODULE_PATH}") ############### INSTALL HEADERS & LIBRARY ################ # Install Ruby bindings install(TARGETS ${SWIG_MODULE_rbopenshot_REAL_NAME} - DESTINATION ${RUBY_MODULE_PATH} ) + DESTINATION ${RUBY_MODULE_PATH} ) From 2684015245d04ce3c1cb2ccd31014d3b5b7a8936 Mon Sep 17 00:00:00 2001 From: Frank Dana Date: Mon, 23 Mar 2020 05:30:32 -0400 Subject: [PATCH 13/79] python/CMakeLists: Lowercase commands, indents --- src/bindings/python/CMakeLists.txt | 62 +++++++++++++++--------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/bindings/python/CMakeLists.txt b/src/bindings/python/CMakeLists.txt index 42a15c8e..ea1292fa 100644 --- a/src/bindings/python/CMakeLists.txt +++ b/src/bindings/python/CMakeLists.txt @@ -26,34 +26,34 @@ ############### SWIG PYTHON BINDINGS ################ -FIND_PACKAGE(SWIG 3.0 REQUIRED) -INCLUDE(${SWIG_USE_FILE}) +find_package(SWIG 3.0 REQUIRED) +include(${SWIG_USE_FILE}) ### Enable some legacy SWIG behaviors, in newer CMAKEs if (POLICY CMP0078) - cmake_policy(SET CMP0078 OLD) + cmake_policy(SET CMP0078 OLD) endif() if (POLICY CMP0086) - cmake_policy(SET CMP0086 OLD) + cmake_policy(SET CMP0086 OLD) endif() FIND_PACKAGE(PythonInterp 3) FIND_PACKAGE(PythonLibs 3) if (PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND) - ### Include Python header files - INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}) - INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + ### Include Python header files + include_directories(${PYTHON_INCLUDE_PATH}) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}) - ### Enable C++ support in SWIG - set_property(SOURCE openshot.i PROPERTY CPLUSPLUS ON) - set_property(SOURCE openshot.i PROPERTY SWIG_MODULE_NAME openshot) + ### Enable C++ support in SWIG + set_property(SOURCE openshot.i PROPERTY CPLUSPLUS ON) + set_property(SOURCE openshot.i PROPERTY SWIG_MODULE_NAME openshot) - ### Suppress a ton of warnings in the generated SWIG C++ code - set(SWIG_CXX_FLAGS "-Wno-unused-variable -Wno-unused-function -Wno-deprecated-copy -Wno-class-memaccess -Wno-cast-function-type \ + ### Suppress a ton of warnings in the generated SWIG C++ code + set(SWIG_CXX_FLAGS "-Wno-unused-variable -Wno-unused-function -Wno-deprecated-copy -Wno-class-memaccess -Wno-cast-function-type \ -Wno-unused-parameter -Wno-catch-value -Wno-sign-compare -Wno-ignored-qualifiers") - separate_arguments(sw_flags UNIX_COMMAND ${SWIG_CXX_FLAGS}) - set_property(SOURCE openshot.i PROPERTY GENERATED_COMPILE_OPTIONS ${sw_flags}) + separate_arguments(sw_flags UNIX_COMMAND ${SWIG_CXX_FLAGS}) + set_property(SOURCE openshot.i PROPERTY GENERATED_COMPILE_OPTIONS ${sw_flags}) ### Take include dirs from target, automatically if possible if (CMAKE_VERSION VERSION_GREATER 3.13) @@ -62,19 +62,19 @@ if (PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND) set_property(SOURCE openshot.i PROPERTY INCLUDE_DIRECTORIES $) endif () - ### Add the SWIG interface file (which defines all the SWIG methods) - if (CMAKE_VERSION VERSION_LESS 3.8.0) - swig_add_module(pyopenshot python openshot.i) - else() - swig_add_library(pyopenshot LANGUAGE python SOURCES openshot.i) - endif() + ### Add the SWIG interface file (which defines all the SWIG methods) + if (CMAKE_VERSION VERSION_LESS 3.8.0) + swig_add_module(pyopenshot python openshot.i) + else() + swig_add_library(pyopenshot LANGUAGE python SOURCES openshot.i) + endif() - ### Set output name of target - set_target_properties(${SWIG_MODULE_pyopenshot_REAL_NAME} PROPERTIES + ### Set output name of target + set_target_properties(${SWIG_MODULE_pyopenshot_REAL_NAME} PROPERTIES PREFIX "_" OUTPUT_NAME "openshot") - ### Link the new python wrapper library with libopenshot - target_link_libraries(${SWIG_MODULE_pyopenshot_REAL_NAME} PUBLIC + ### Link the new python wrapper library with libopenshot + target_link_libraries(${SWIG_MODULE_pyopenshot_REAL_NAME} PUBLIC ${PYTHON_LIBRARIES} openshot) ######### INSTALL PATH ######## @@ -88,12 +88,12 @@ if (PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND) endif() if (UNIX AND NOT APPLE) - ### Check if the following Debian-friendly python module path exists - set(PYTHON_MODULE_PATH "lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/dist-packages") - if (NOT EXISTS "${CMAKE_INSTALL_PREFIX}/${PYTHON_MODULE_PATH}") + ### Check if the following Debian-friendly python module path exists + set(PYTHON_MODULE_PATH "lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/dist-packages") + if (NOT EXISTS "${CMAKE_INSTALL_PREFIX}/${PYTHON_MODULE_PATH}") ### Calculate the python module path (using distutils) - execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "\ + execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "\ from distutils.sysconfig import get_python_lib; \ print( get_python_lib( plat_specific=True, prefix='' ) )" OUTPUT_VARIABLE PYTHON_MODULE_PATH @@ -104,9 +104,9 @@ print( get_python_lib( plat_specific=True, prefix='' ) )" message(STATUS "PYTHON_MODULE_PATH: ${CMAKE_INSTALL_PREFIX}/${PYTHON_MODULE_PATH}") - ############### INSTALL HEADERS & LIBRARY ################ - ### Install Python bindings - install(TARGETS ${SWIG_MODULE_pyopenshot_REAL_NAME} + ############### INSTALL HEADERS & LIBRARY ################ + ### Install Python bindings + install(TARGETS ${SWIG_MODULE_pyopenshot_REAL_NAME} DESTINATION ${PYTHON_MODULE_PATH} ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/openshot.py DESTINATION ${PYTHON_MODULE_PATH} ) From 94e9ad3eade8915460c4ae0090ee38ce02e8c7af Mon Sep 17 00:00:00 2001 From: Frank Dana Date: Mon, 23 Mar 2020 08:13:46 -0400 Subject: [PATCH 14/79] bindings: Remove relative header paths (#469) * bindings: Remove relative header paths Use the include paths set on the command line the way they're supposed to be used. * Also remove some redundant include paths * Fix SWIG include dirs --- CMakeLists.txt | 4 - src/bindings/python/CMakeLists.txt | 132 +++++++++++--------- src/bindings/python/openshot.i | 192 ++++++++++++++--------------- src/bindings/ruby/CMakeLists.txt | 23 ++-- src/bindings/ruby/openshot.i | 192 ++++++++++++++--------------- 5 files changed, 276 insertions(+), 267 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a0e8a5fe..124e9e5a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,10 +113,6 @@ IF (WIN32) SET_PROPERTY(GLOBAL PROPERTY WIN32 "WIN32") ENDIF(WIN32) -include_directories( - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${CMAKE_CURRENT_BINARY_DIR}/include) - ############## Code Coverage ######################### if (DISABLE_TESTS AND ENABLE_COVERAGE) message(WARNING "ENABLE_COVERAGE requires tests, overriding DISABLE_TESTS") diff --git a/src/bindings/python/CMakeLists.txt b/src/bindings/python/CMakeLists.txt index ea1292fa..6d7ce79e 100644 --- a/src/bindings/python/CMakeLists.txt +++ b/src/bindings/python/CMakeLists.txt @@ -37,78 +37,88 @@ if (POLICY CMP0086) cmake_policy(SET CMP0086 OLD) endif() -FIND_PACKAGE(PythonInterp 3) -FIND_PACKAGE(PythonLibs 3) -if (PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND) +find_package(PythonInterp 3) +find_package(PythonLibs 3) - ### Include Python header files - include_directories(${PYTHON_INCLUDE_PATH}) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +if (NOT PYTHONLIBS_FOUND OR NOT PYTHONINTERP_FOUND) + return() +endif() - ### Enable C++ support in SWIG - set_property(SOURCE openshot.i PROPERTY CPLUSPLUS ON) - set_property(SOURCE openshot.i PROPERTY SWIG_MODULE_NAME openshot) +### Include Python header files +include_directories(${PYTHON_INCLUDE_PATH}) - ### Suppress a ton of warnings in the generated SWIG C++ code - set(SWIG_CXX_FLAGS "-Wno-unused-variable -Wno-unused-function -Wno-deprecated-copy -Wno-class-memaccess -Wno-cast-function-type \ --Wno-unused-parameter -Wno-catch-value -Wno-sign-compare -Wno-ignored-qualifiers") - separate_arguments(sw_flags UNIX_COMMAND ${SWIG_CXX_FLAGS}) - set_property(SOURCE openshot.i PROPERTY GENERATED_COMPILE_OPTIONS ${sw_flags}) +if (CMAKE_VERSION VERSION_LESS 3.12) + ### Include project headers + include_directories( + "${PROJECT_SOURCE_DIR}/include" + "${PROJECT_BINARY_DIR}/include") +endif() - ### Take include dirs from target, automatically if possible - if (CMAKE_VERSION VERSION_GREATER 3.13) - set_property(SOURCE openshot.i PROPERTY USE_TARGET_INCLUDE_DIRECTORIES True) - else () - set_property(SOURCE openshot.i PROPERTY INCLUDE_DIRECTORIES $) - endif () +### Enable C++ support in SWIG +set_property(SOURCE openshot.i PROPERTY CPLUSPLUS ON) +set_property(SOURCE openshot.i PROPERTY SWIG_MODULE_NAME openshot) - ### Add the SWIG interface file (which defines all the SWIG methods) - if (CMAKE_VERSION VERSION_LESS 3.8.0) - swig_add_module(pyopenshot python openshot.i) - else() - swig_add_library(pyopenshot LANGUAGE python SOURCES openshot.i) +### Suppress a ton of warnings in the generated SWIG C++ code +set(SWIG_CXX_FLAGS "-Wno-unused-variable -Wno-unused-function \ + -Wno-deprecated-copy -Wno-class-memaccess -Wno-cast-function-type \ + -Wno-unused-parameter -Wno-catch-value -Wno-sign-compare -Wno-ignored-qualifiers") +separate_arguments(sw_flags UNIX_COMMAND ${SWIG_CXX_FLAGS}) +set_property(SOURCE openshot.i PROPERTY GENERATED_COMPILE_OPTIONS ${sw_flags}) + +### Take include dirs from target, automatically if possible +if (CMAKE_VERSION VERSION_GREATER 3.13) + set_property(SOURCE openshot.i PROPERTY USE_TARGET_INCLUDE_DIRECTORIES True) +elseif (CMAKE_VERSION VERSION_GREATER 3.12) + set_property(SOURCE openshot.i PROPERTY + INCLUDE_DIRECTORIES $) +endif () + +### Add the SWIG interface file (which defines all the SWIG methods) +if (CMAKE_VERSION VERSION_LESS 3.8.0) + swig_add_module(pyopenshot python openshot.i) +else() + swig_add_library(pyopenshot LANGUAGE python SOURCES openshot.i) +endif() + +### Set output name of target +set_target_properties(${SWIG_MODULE_pyopenshot_REAL_NAME} PROPERTIES + PREFIX "_" OUTPUT_NAME "openshot") + +### Link the new python wrapper library with libopenshot +target_link_libraries(${SWIG_MODULE_pyopenshot_REAL_NAME} PUBLIC + ${PYTHON_LIBRARIES} openshot) + +######### INSTALL PATH ######## +if (NOT DEFINED PYTHON_MODULE_PATH AND DEFINED $ENV{PYTHON_MODULE_PATH}) + set(PYTHON_MODULE_PATH $ENV{PYTHON_MODULE_PATH}) +endif() + +if (NOT DEFINED PYTHON_MODULE_PATH) + if (WIN32 OR APPLE) + set (PYTHON_MODULE_PATH "python") endif() - ### Set output name of target - set_target_properties(${SWIG_MODULE_pyopenshot_REAL_NAME} PROPERTIES - PREFIX "_" OUTPUT_NAME "openshot") + if (UNIX AND NOT APPLE) + ### Check if the following Debian-friendly python module path exists + set(PYTHON_MODULE_PATH + "lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/dist-packages") - ### Link the new python wrapper library with libopenshot - target_link_libraries(${SWIG_MODULE_pyopenshot_REAL_NAME} PUBLIC - ${PYTHON_LIBRARIES} openshot) - - ######### INSTALL PATH ######## - if (NOT DEFINED PYTHON_MODULE_PATH AND DEFINED $ENV{PYTHON_MODULE_PATH}) - set(PYTHON_MODULE_PATH $ENV{PYTHON_MODULE_PATH}) - endif() - - if (NOT DEFINED PYTHON_MODULE_PATH) - if (WIN32 OR APPLE) - set (PYTHON_MODULE_PATH "python") - endif() - - if (UNIX AND NOT APPLE) - ### Check if the following Debian-friendly python module path exists - set(PYTHON_MODULE_PATH "lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/dist-packages") - if (NOT EXISTS "${CMAKE_INSTALL_PREFIX}/${PYTHON_MODULE_PATH}") - - ### Calculate the python module path (using distutils) - execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "\ + if (NOT EXISTS "${CMAKE_INSTALL_PREFIX}/${PYTHON_MODULE_PATH}") + ### Calculate the python module path (using distutils) + execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "\ from distutils.sysconfig import get_python_lib; \ print( get_python_lib( plat_specific=True, prefix='' ) )" - OUTPUT_VARIABLE PYTHON_MODULE_PATH - OUTPUT_STRIP_TRAILING_WHITESPACE ) - endif() + OUTPUT_VARIABLE PYTHON_MODULE_PATH + OUTPUT_STRIP_TRAILING_WHITESPACE ) endif() endif() +endif() - message(STATUS "PYTHON_MODULE_PATH: ${CMAKE_INSTALL_PREFIX}/${PYTHON_MODULE_PATH}") +message(STATUS "PYTHON_MODULE_PATH: ${CMAKE_INSTALL_PREFIX}/${PYTHON_MODULE_PATH}") - ############### INSTALL HEADERS & LIBRARY ################ - ### Install Python bindings - install(TARGETS ${SWIG_MODULE_pyopenshot_REAL_NAME} - DESTINATION ${PYTHON_MODULE_PATH} ) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/openshot.py - DESTINATION ${PYTHON_MODULE_PATH} ) - -endif () +############### INSTALL HEADERS & LIBRARY ################ +### Install Python bindings +install(TARGETS ${SWIG_MODULE_pyopenshot_REAL_NAME} + DESTINATION ${PYTHON_MODULE_PATH} ) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/openshot.py + DESTINATION ${PYTHON_MODULE_PATH} ) diff --git a/src/bindings/python/openshot.i b/src/bindings/python/openshot.i index 44b1953e..53e514c1 100644 --- a/src/bindings/python/openshot.i +++ b/src/bindings/python/openshot.i @@ -59,57 +59,57 @@ %{ #include "OpenShotVersion.h" -#include "../../../include/ReaderBase.h" -#include "../../../include/WriterBase.h" -#include "../../../include/CacheBase.h" -#include "../../../include/CacheDisk.h" -#include "../../../include/CacheMemory.h" -#include "../../../include/ChannelLayouts.h" -#include "../../../include/ChunkReader.h" -#include "../../../include/ChunkWriter.h" -#include "../../../include/ClipBase.h" -#include "../../../include/Clip.h" -#include "../../../include/Coordinate.h" -#include "../../../include/Color.h" -#include "../../../include/DummyReader.h" -#include "../../../include/EffectBase.h" -#include "../../../include/Effects.h" -#include "../../../include/EffectInfo.h" -#include "../../../include/Enums.h" -#include "../../../include/Exceptions.h" -#include "../../../include/FFmpegReader.h" -#include "../../../include/FFmpegWriter.h" -#include "../../../include/Fraction.h" -#include "../../../include/Frame.h" -#include "../../../include/FrameMapper.h" -#include "../../../include/PlayerBase.h" -#include "../../../include/Point.h" -#include "../../../include/Profiles.h" -#include "../../../include/QtHtmlReader.h" -#include "../../../include/QtImageReader.h" -#include "../../../include/QtPlayer.h" -#include "../../../include/QtTextReader.h" -#include "../../../include/KeyFrame.h" -#include "../../../include/RendererBase.h" -#include "../../../include/Settings.h" -#include "../../../include/Timeline.h" -#include "../../../include/ZmqLogger.h" -#include "../../../include/AudioDeviceInfo.h" +#include "ReaderBase.h" +#include "WriterBase.h" +#include "CacheBase.h" +#include "CacheDisk.h" +#include "CacheMemory.h" +#include "ChannelLayouts.h" +#include "ChunkReader.h" +#include "ChunkWriter.h" +#include "ClipBase.h" +#include "Clip.h" +#include "Coordinate.h" +#include "Color.h" +#include "DummyReader.h" +#include "EffectBase.h" +#include "Effects.h" +#include "EffectInfo.h" +#include "Enums.h" +#include "Exceptions.h" +#include "FFmpegReader.h" +#include "FFmpegWriter.h" +#include "Fraction.h" +#include "Frame.h" +#include "FrameMapper.h" +#include "PlayerBase.h" +#include "Point.h" +#include "Profiles.h" +#include "QtHtmlReader.h" +#include "QtImageReader.h" +#include "QtPlayer.h" +#include "QtTextReader.h" +#include "KeyFrame.h" +#include "RendererBase.h" +#include "Settings.h" +#include "Timeline.h" +#include "ZmqLogger.h" +#include "AudioDeviceInfo.h" %} #ifdef USE_BLACKMAGIC %{ - #include "../../../include/DecklinkReader.h" - #include "../../../include/DecklinkWriter.h" + #include "DecklinkReader.h" + #include "DecklinkWriter.h" %} #endif #ifdef USE_IMAGEMAGICK %{ - #include "../../../include/ImageReader.h" - #include "../../../include/ImageWriter.h" - #include "../../../include/TextReader.h" + #include "ImageReader.h" + #include "ImageWriter.h" + #include "TextReader.h" %} #endif @@ -166,68 +166,68 @@ } %include "OpenShotVersion.h" -%include "../../../include/ReaderBase.h" -%include "../../../include/WriterBase.h" -%include "../../../include/CacheBase.h" -%include "../../../include/CacheDisk.h" -%include "../../../include/CacheMemory.h" -%include "../../../include/ChannelLayouts.h" -%include "../../../include/ChunkReader.h" -%include "../../../include/ChunkWriter.h" -%include "../../../include/ClipBase.h" -%include "../../../include/Clip.h" -%include "../../../include/Coordinate.h" -%include "../../../include/Color.h" +%include "ReaderBase.h" +%include "WriterBase.h" +%include "CacheBase.h" +%include "CacheDisk.h" +%include "CacheMemory.h" +%include "ChannelLayouts.h" +%include "ChunkReader.h" +%include "ChunkWriter.h" +%include "ClipBase.h" +%include "Clip.h" +%include "Coordinate.h" +%include "Color.h" #ifdef USE_BLACKMAGIC - %include "../../../include/DecklinkReader.h" - %include "../../../include/DecklinkWriter.h" + %include "DecklinkReader.h" + %include "DecklinkWriter.h" #endif -%include "../../../include/DummyReader.h" -%include "../../../include/EffectBase.h" -%include "../../../include/Effects.h" -%include "../../../include/EffectInfo.h" -%include "../../../include/Enums.h" -%include "../../../include/Exceptions.h" -%include "../../../include/FFmpegReader.h" -%include "../../../include/FFmpegWriter.h" -%include "../../../include/Fraction.h" -%include "../../../include/Frame.h" -%include "../../../include/FrameMapper.h" -%include "../../../include/PlayerBase.h" -%include "../../../include/Point.h" -%include "../../../include/Profiles.h" -%include "../../../include/QtHtmlReader.h" -%include "../../../include/QtImageReader.h" -%include "../../../include/QtPlayer.h" -%include "../../../include/QtTextReader.h" -%include "../../../include/KeyFrame.h" -%include "../../../include/RendererBase.h" -%include "../../../include/Settings.h" -%include "../../../include/Timeline.h" -%include "../../../include/ZmqLogger.h" -%include "../../../include/AudioDeviceInfo.h" +%include "DummyReader.h" +%include "EffectBase.h" +%include "Effects.h" +%include "EffectInfo.h" +%include "Enums.h" +%include "Exceptions.h" +%include "FFmpegReader.h" +%include "FFmpegWriter.h" +%include "Fraction.h" +%include "Frame.h" +%include "FrameMapper.h" +%include "PlayerBase.h" +%include "Point.h" +%include "Profiles.h" +%include "QtHtmlReader.h" +%include "QtImageReader.h" +%include "QtPlayer.h" +%include "QtTextReader.h" +%include "KeyFrame.h" +%include "RendererBase.h" +%include "Settings.h" +%include "Timeline.h" +%include "ZmqLogger.h" +%include "AudioDeviceInfo.h" #ifdef USE_IMAGEMAGICK - %include "../../../include/ImageReader.h" - %include "../../../include/ImageWriter.h" - %include "../../../include/TextReader.h" + %include "ImageReader.h" + %include "ImageWriter.h" + %include "TextReader.h" #endif /* Effects */ -%include "../../../include/effects/Bars.h" -%include "../../../include/effects/Blur.h" -%include "../../../include/effects/Brightness.h" -%include "../../../include/effects/ChromaKey.h" -%include "../../../include/effects/ColorShift.h" -%include "../../../include/effects/Crop.h" -%include "../../../include/effects/Deinterlace.h" -%include "../../../include/effects/Hue.h" -%include "../../../include/effects/Mask.h" -%include "../../../include/effects/Negate.h" -%include "../../../include/effects/Pixelate.h" -%include "../../../include/effects/Saturation.h" -%include "../../../include/effects/Shift.h" -%include "../../../include/effects/Wave.h" +%include "effects/Bars.h" +%include "effects/Blur.h" +%include "effects/Brightness.h" +%include "effects/ChromaKey.h" +%include "effects/ColorShift.h" +%include "effects/Crop.h" +%include "effects/Deinterlace.h" +%include "effects/Hue.h" +%include "effects/Mask.h" +%include "effects/Negate.h" +%include "effects/Pixelate.h" +%include "effects/Saturation.h" +%include "effects/Shift.h" +%include "effects/Wave.h" /* Wrap std templates (list, vector, etc...) */ diff --git a/src/bindings/ruby/CMakeLists.txt b/src/bindings/ruby/CMakeLists.txt index c3c113aa..dc571a81 100644 --- a/src/bindings/ruby/CMakeLists.txt +++ b/src/bindings/ruby/CMakeLists.txt @@ -43,15 +43,22 @@ endif() ### Include the Ruby header files include_directories(${RUBY_INCLUDE_DIRS}) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +if (CMAKE_VERSION VERSION_LESS 3.12) + ### Include Ruby header files and project headers + include_directories( + "${PROJECT_SOURCE_DIR}/include" + "${PROJECT_BINARY_DIR}/include") +endif() ### Enable C++ in SWIG set_property(SOURCE openshot.i PROPERTY CPLUSPLUS ON) set_property(SOURCE openshot.i PROPERTY SWIG_MODULE_NAME openshot) ### Suppress a ton of warnings in the generated SWIG C++ code -set(SWIG_CXX_FLAGS "-Wno-unused-variable -Wno-unused-function -Wno-deprecated-copy -Wno-class-memaccess -Wno-cast-function-type \ --Wno-unused-parameter -Wno-catch-value -Wno-sign-compare -Wno-ignored-qualifiers") +set(SWIG_CXX_FLAGS "-Wno-unused-variable -Wno-unused-function \ + -Wno-deprecated-copy -Wno-class-memaccess -Wno-cast-function-type \ + -Wno-unused-parameter -Wno-catch-value -Wno-sign-compare -Wno-ignored-qualifiers") separate_arguments(sw_flags UNIX_COMMAND ${SWIG_CXX_FLAGS}) set_property(SOURCE openshot.i PROPERTY GENERATED_COMPILE_OPTIONS ${sw_flags}) @@ -59,7 +66,8 @@ set_property(SOURCE openshot.i PROPERTY GENERATED_COMPILE_OPTIONS ${sw_flags}) if (CMAKE_VERSION VERSION_GREATER 3.13) set_property(SOURCE openshot.i PROPERTY USE_TARGET_INCLUDE_DIRECTORIES True) else () - set_property(SOURCE openshot.i PROPERTY INCLUDE_DIRECTORIES $) + set_property(SOURCE openshot.i PROPERTY + INCLUDE_DIRECTORIES $) endif () ### Add the SWIG interface file (which defines all the SWIG methods) @@ -69,10 +77,6 @@ else() swig_add_library(rbopenshot LANGUAGE ruby SOURCES openshot.i) endif() -### Set name of target (with no prefix, since Ruby does not like that) -set_target_properties(${SWIG_MODULE_rbopenshot_REAL_NAME} PROPERTIES - PREFIX "" OUTPUT_NAME "openshot") - ### Link the new Ruby wrapper library with libopenshot target_link_libraries(${SWIG_MODULE_rbopenshot_REAL_NAME} PUBLIC ${RUBY_LIBRARY} openshot) @@ -101,9 +105,8 @@ if (NOT DEFINED RUBY_MODULE_PATH) endif() message(STATUS "RUBY_MODULE_PATH: ${CMAKE_INSTALL_PREFIX}/${RUBY_MODULE_PATH}") - + ############### INSTALL HEADERS & LIBRARY ################ # Install Ruby bindings install(TARGETS ${SWIG_MODULE_rbopenshot_REAL_NAME} DESTINATION ${RUBY_MODULE_PATH} ) - diff --git a/src/bindings/ruby/openshot.i b/src/bindings/ruby/openshot.i index a08ac9ae..2f24d220 100644 --- a/src/bindings/ruby/openshot.i +++ b/src/bindings/ruby/openshot.i @@ -70,42 +70,42 @@ namespace std { #undef RSHIFT #endif #include "OpenShotVersion.h" -#include "../../../include/ReaderBase.h" -#include "../../../include/WriterBase.h" -#include "../../../include/CacheBase.h" -#include "../../../include/CacheDisk.h" -#include "../../../include/CacheMemory.h" -#include "../../../include/ChannelLayouts.h" -#include "../../../include/ChunkReader.h" -#include "../../../include/ChunkWriter.h" -#include "../../../include/ClipBase.h" -#include "../../../include/Clip.h" -#include "../../../include/Coordinate.h" -#include "../../../include/Color.h" -#include "../../../include/DummyReader.h" -#include "../../../include/EffectBase.h" -#include "../../../include/Effects.h" -#include "../../../include/EffectInfo.h" -#include "../../../include/Enums.h" -#include "../../../include/Exceptions.h" -#include "../../../include/FFmpegReader.h" -#include "../../../include/FFmpegWriter.h" -#include "../../../include/Fraction.h" -#include "../../../include/Frame.h" -#include "../../../include/FrameMapper.h" -#include "../../../include/PlayerBase.h" -#include "../../../include/Point.h" -#include "../../../include/Profiles.h" -#include "../../../include/QtHtmlReader.h" -#include "../../../include/QtImageReader.h" -#include "../../../include/QtPlayer.h" -#include "../../../include/QtTextReader.h" -#include "../../../include/KeyFrame.h" -#include "../../../include/RendererBase.h" -#include "../../../include/Settings.h" -#include "../../../include/Timeline.h" -#include "../../../include/ZmqLogger.h" -#include "../../../include/AudioDeviceInfo.h" +#include "ReaderBase.h" +#include "WriterBase.h" +#include "CacheBase.h" +#include "CacheDisk.h" +#include "CacheMemory.h" +#include "ChannelLayouts.h" +#include "ChunkReader.h" +#include "ChunkWriter.h" +#include "ClipBase.h" +#include "Clip.h" +#include "Coordinate.h" +#include "Color.h" +#include "DummyReader.h" +#include "EffectBase.h" +#include "Effects.h" +#include "EffectInfo.h" +#include "Enums.h" +#include "Exceptions.h" +#include "FFmpegReader.h" +#include "FFmpegWriter.h" +#include "Fraction.h" +#include "Frame.h" +#include "FrameMapper.h" +#include "PlayerBase.h" +#include "Point.h" +#include "Profiles.h" +#include "QtHtmlReader.h" +#include "QtImageReader.h" +#include "QtPlayer.h" +#include "QtTextReader.h" +#include "KeyFrame.h" +#include "RendererBase.h" +#include "Settings.h" +#include "Timeline.h" +#include "ZmqLogger.h" +#include "AudioDeviceInfo.h" /* Move FFmpeg's RSHIFT to FF_RSHIFT, if present */ #ifdef RSHIFT @@ -120,42 +120,42 @@ namespace std { #ifdef USE_BLACKMAGIC %{ - #include "../../../include/DecklinkReader.h" - #include "../../../include/DecklinkWriter.h" + #include "DecklinkReader.h" + #include "DecklinkWriter.h" %} #endif #ifdef USE_IMAGEMAGICK %{ - #include "../../../include/ImageReader.h" - #include "../../../include/ImageWriter.h" - #include "../../../include/TextReader.h" + #include "ImageReader.h" + #include "ImageWriter.h" + #include "TextReader.h" %} #endif %include "OpenShotVersion.h" -%include "../../../include/ReaderBase.h" -%include "../../../include/WriterBase.h" -%include "../../../include/CacheBase.h" -%include "../../../include/CacheDisk.h" -%include "../../../include/CacheMemory.h" -%include "../../../include/ChannelLayouts.h" -%include "../../../include/ChunkReader.h" -%include "../../../include/ChunkWriter.h" -%include "../../../include/ClipBase.h" -%include "../../../include/Clip.h" -%include "../../../include/Coordinate.h" -%include "../../../include/Color.h" +%include "ReaderBase.h" +%include "WriterBase.h" +%include "CacheBase.h" +%include "CacheDisk.h" +%include "CacheMemory.h" +%include "ChannelLayouts.h" +%include "ChunkReader.h" +%include "ChunkWriter.h" +%include "ClipBase.h" +%include "Clip.h" +%include "Coordinate.h" +%include "Color.h" #ifdef USE_BLACKMAGIC - %include "../../../include/DecklinkReader.h" - %include "../../../include/DecklinkWriter.h" + %include "DecklinkReader.h" + %include "DecklinkWriter.h" #endif -%include "../../../include/DummyReader.h" -%include "../../../include/EffectBase.h" -%include "../../../include/Effects.h" -%include "../../../include/EffectInfo.h" -%include "../../../include/Enums.h" -%include "../../../include/Exceptions.h" +%include "DummyReader.h" +%include "EffectBase.h" +%include "Effects.h" +%include "EffectInfo.h" +%include "Enums.h" +%include "Exceptions.h" /* Ruby and FFmpeg define competing RSHIFT macros, * so we move Ruby's out of the way for now. We'll @@ -166,8 +166,8 @@ namespace std { #undef RSHIFT #endif -%include "../../../include/FFmpegReader.h" -%include "../../../include/FFmpegWriter.h" +%include "FFmpegReader.h" +%include "FFmpegWriter.h" /* Move FFmpeg's RSHIFT to FF_RSHIFT, if present */ #ifdef RSHIFT @@ -179,45 +179,45 @@ namespace std { #define RSHIFT(a, b) RB_RSHIFT(a, b) #endif -%include "../../../include/Fraction.h" -%include "../../../include/Frame.h" -%include "../../../include/FrameMapper.h" -%include "../../../include/PlayerBase.h" -%include "../../../include/Point.h" -%include "../../../include/Profiles.h" -%include "../../../include/QtHtmlReader.h" -%include "../../../include/QtImageReader.h" -%include "../../../include/QtPlayer.h" -%include "../../../include/QtTextReader.h" -%include "../../../include/KeyFrame.h" -%include "../../../include/RendererBase.h" -%include "../../../include/Settings.h" -%include "../../../include/Timeline.h" -%include "../../../include/ZmqLogger.h" -%include "../../../include/AudioDeviceInfo.h" +%include "Fraction.h" +%include "Frame.h" +%include "FrameMapper.h" +%include "PlayerBase.h" +%include "Point.h" +%include "Profiles.h" +%include "QtHtmlReader.h" +%include "QtImageReader.h" +%include "QtPlayer.h" +%include "QtTextReader.h" +%include "KeyFrame.h" +%include "RendererBase.h" +%include "Settings.h" +%include "Timeline.h" +%include "ZmqLogger.h" +%include "AudioDeviceInfo.h" #ifdef USE_IMAGEMAGICK - %include "../../../include/ImageReader.h" - %include "../../../include/ImageWriter.h" - %include "../../../include/TextReader.h" + %include "ImageReader.h" + %include "ImageWriter.h" + %include "TextReader.h" #endif /* Effects */ -%include "../../../include/effects/Bars.h" -%include "../../../include/effects/Blur.h" -%include "../../../include/effects/Brightness.h" -%include "../../../include/effects/ChromaKey.h" -%include "../../../include/effects/ColorShift.h" -%include "../../../include/effects/Crop.h" -%include "../../../include/effects/Deinterlace.h" -%include "../../../include/effects/Hue.h" -%include "../../../include/effects/Mask.h" -%include "../../../include/effects/Negate.h" -%include "../../../include/effects/Pixelate.h" -%include "../../../include/effects/Saturation.h" -%include "../../../include/effects/Shift.h" -%include "../../../include/effects/Wave.h" +%include "effects/Bars.h" +%include "effects/Blur.h" +%include "effects/Brightness.h" +%include "effects/ChromaKey.h" +%include "effects/ColorShift.h" +%include "effects/Crop.h" +%include "effects/Deinterlace.h" +%include "effects/Hue.h" +%include "effects/Mask.h" +%include "effects/Negate.h" +%include "effects/Pixelate.h" +%include "effects/Saturation.h" +%include "effects/Shift.h" +%include "effects/Wave.h" /* Wrap std templates (list, vector, etc...) */ From 4fad197fbe0ba1239c17a26ace77bb4d2f133e66 Mon Sep 17 00:00:00 2001 From: Frank Dana Date: Mon, 23 Mar 2020 08:16:02 -0400 Subject: [PATCH 15/79] Add version gating for Zmq and Qt deprecations (#470) * ZmqLogger: Avoid deprecated send() in later ZMQ * QtImageReader: byteCount() deprecated in QT 5.10+ --- src/QtImageReader.cpp | 7 ++++++- src/ZmqLogger.cpp | 12 +++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/QtImageReader.cpp b/src/QtImageReader.cpp index 864af23d..cf64ef93 100644 --- a/src/QtImageReader.cpp +++ b/src/QtImageReader.cpp @@ -111,7 +111,12 @@ void QtImageReader::Open() info.has_audio = false; info.has_video = true; info.has_single_image = true; - info.file_size = image->byteCount(); + #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) + // byteCount() is deprecated from Qt 5.10 + info.file_size = image->sizeInBytes(); + #else + info.file_size = image->byteCount(); + #endif info.vcodec = "QImage"; info.width = image->width(); info.height = image->height(); diff --git a/src/ZmqLogger.cpp b/src/ZmqLogger.cpp index 89d2798a..f607d08f 100644 --- a/src/ZmqLogger.cpp +++ b/src/ZmqLogger.cpp @@ -120,14 +120,20 @@ void ZmqLogger::Log(string message) // Create a scoped lock, allowing only a single thread to run the following code at one time const GenericScopedLock lock(loggerCriticalSection); +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 1) // Send message over socket (ZeroMQ) + zmq::message_t reply(message); + + // Set flags for immediate delivery (new API) + publisher->send(reply, zmq::send_flags::dontwait); +#else zmq::message_t reply (message.length()); memcpy (reply.data(), message.c_str(), message.length()); publisher->send(reply); +#endif - // Write to log file (if opened, and force it to write to disk in case of a crash) - if (log_file.is_open()) - log_file << message << std::flush; + // Also log to file, if open + LogToFile(message); } // Log message to a file (if path set) From 54f5fea2013cc3410071be911634304624ae8c21 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Wed, 25 Mar 2020 11:42:19 -0400 Subject: [PATCH 16/79] ZeroMQ's std::string support is too new --- src/ZmqLogger.cpp | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/src/ZmqLogger.cpp b/src/ZmqLogger.cpp index f607d08f..0be04bfa 100644 --- a/src/ZmqLogger.cpp +++ b/src/ZmqLogger.cpp @@ -71,7 +71,7 @@ ZmqLogger *ZmqLogger::Instance() } // Set the connection for this logger -void ZmqLogger::Connection(string new_connection) +void ZmqLogger::Connection(std::string new_connection) { // Create a scoped lock, allowing only a single thread to run the following code at one time const GenericScopedLock lock(loggerCriticalSection); @@ -102,7 +102,7 @@ void ZmqLogger::Connection(string new_connection) publisher->bind(connection.c_str()); } catch (zmq::error_t &e) { - cout << "ZmqLogger::Connection - Error binding to " << connection << ". Switching to an available port." << endl; + std::cout << "ZmqLogger::Connection - Error binding to " << connection << ". Switching to an available port." << std::endl; connection = "tcp://*:*"; publisher->bind(connection.c_str()); } @@ -111,7 +111,7 @@ void ZmqLogger::Connection(string new_connection) usleep(250000); } -void ZmqLogger::Log(string message) +void ZmqLogger::Log(std::string message) { if (!enabled) // Don't do anything @@ -120,15 +120,14 @@ void ZmqLogger::Log(string message) // Create a scoped lock, allowing only a single thread to run the following code at one time const GenericScopedLock lock(loggerCriticalSection); -#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 1) // Send message over socket (ZeroMQ) - zmq::message_t reply(message); + zmq::message_t reply (message.length()); + std::memcpy (reply.data(), message.c_str(), message.length()); +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 1) // Set flags for immediate delivery (new API) publisher->send(reply, zmq::send_flags::dontwait); #else - zmq::message_t reply (message.length()); - memcpy (reply.data(), message.c_str(), message.length()); publisher->send(reply); #endif @@ -137,14 +136,14 @@ void ZmqLogger::Log(string message) } // Log message to a file (if path set) -void ZmqLogger::LogToFile(string message) +void ZmqLogger::LogToFile(std::string message) { // Write to log file (if opened, and force it to write to disk in case of a crash) if (log_file.is_open()) log_file << message << std::flush; } -void ZmqLogger::Path(string new_path) +void ZmqLogger::Path(std::string new_path) { // Update path file_path = new_path; @@ -154,14 +153,14 @@ void ZmqLogger::Path(string new_path) log_file.close(); // Open file (write + append) - log_file.open (file_path.c_str(), ios::out | ios::app); + log_file.open (file_path.c_str(), std::ios::out | std::ios::app); // Get current time and log first message - time_t now = time(0); - tm* localtm = localtime(&now); - log_file << "------------------------------------------" << endl; - log_file << "libopenshot logging: " << asctime(localtm); - log_file << "------------------------------------------" << endl; + std::time_t now = std::time(0); + std::tm* localtm = std::localtime(&now); + log_file << "------------------------------------------" << std::endl; + log_file << "libopenshot logging: " << std::asctime(localtm); + log_file << "------------------------------------------" << std::endl; } void ZmqLogger::Close() @@ -182,13 +181,13 @@ void ZmqLogger::Close() } // Append debug information -void ZmqLogger::AppendDebugMethod(string method_name, - string arg1_name, float arg1_value, - string arg2_name, float arg2_value, - string arg3_name, float arg3_value, - string arg4_name, float arg4_value, - string arg5_name, float arg5_value, - string arg6_name, float arg6_value) +void ZmqLogger::AppendDebugMethod(std::string method_name, + std::string arg1_name, float arg1_value, + std::string arg2_name, float arg2_value, + std::string arg3_name, float arg3_value, + std::string arg4_name, float arg4_value, + std::string arg5_name, float arg5_value, + std::string arg6_name, float arg6_value) { if (!enabled) // Don't do anything @@ -198,8 +197,8 @@ void ZmqLogger::AppendDebugMethod(string method_name, // Create a scoped lock, allowing only a single thread to run the following code at one time const GenericScopedLock lock(loggerCriticalSection); - stringstream message; - message << fixed << setprecision(4); + std::stringstream message; + message << std::fixed << std::setprecision(4); message << method_name << " ("; // Add attributes to method JSON From adf6165083fd2f227d354094b3764a117ca7bb9a Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Wed, 25 Mar 2020 11:57:22 -0400 Subject: [PATCH 17/79] Add version reporting to FindZeroMQ --- cmake/Modules/FindZeroMQ.cmake | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/cmake/Modules/FindZeroMQ.cmake b/cmake/Modules/FindZeroMQ.cmake index 6c366919..1f1dc083 100644 --- a/cmake/Modules/FindZeroMQ.cmake +++ b/cmake/Modules/FindZeroMQ.cmake @@ -5,14 +5,16 @@ pkg_check_modules(PC_LIBZMQ QUIET libzmq) set(ZeroMQ_VERSION ${PC_LIBZMQ_VERSION}) find_path(ZeroMQ_INCLUDE_DIR zmq.h - PATHS ${ZeroMQ_DIR}/include - ${PC_LIBZMQ_INCLUDE_DIRS}) + PATHS + ${ZeroMQ_DIR}/include + ${PC_LIBZMQ_INCLUDE_DIRS}) find_library(ZeroMQ_LIBRARY - NAMES zmq - PATHS ${ZeroMQ_DIR}/lib - ${PC_LIBZMQ_LIBDIR} - ${PC_LIBZMQ_LIBRARY_DIRS}) + NAMES zmq + PATHS + ${ZeroMQ_DIR}/lib + ${PC_LIBZMQ_LIBDIR} + ${PC_LIBZMQ_LIBRARY_DIRS}) if(ZeroMQ_LIBRARY) set(ZeroMQ_FOUND ON) @@ -31,4 +33,9 @@ endif() include ( FindPackageHandleStandardArgs ) # handle the QUIETLY and REQUIRED arguments and set ZMQ_FOUND to TRUE # if all listed variables are TRUE -find_package_handle_standard_args ( ZeroMQ DEFAULT_MSG ZeroMQ_LIBRARIES ZeroMQ_INCLUDE_DIRS ) +find_package_handle_standard_args(ZeroMQ + REQUIRED_VARS + ZeroMQ_LIBRARIES + ZeroMQ_INCLUDE_DIRS + VERSION_VAR + ZeroMQ_VERSION) From 0a5dfd93ad1e576c734541526d2bab3cb1213ceb Mon Sep 17 00:00:00 2001 From: Chiller Dragon Date: Thu, 26 Mar 2020 01:58:11 +0100 Subject: [PATCH 18/79] Fix zmq version check (#478) --- src/ZmqLogger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ZmqLogger.cpp b/src/ZmqLogger.cpp index f607d08f..211f1119 100644 --- a/src/ZmqLogger.cpp +++ b/src/ZmqLogger.cpp @@ -120,7 +120,7 @@ void ZmqLogger::Log(string message) // Create a scoped lock, allowing only a single thread to run the following code at one time const GenericScopedLock lock(loggerCriticalSection); -#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 1) +#if ZMQ_VERSION > ZMQ_MAKE_VERSION(4, 3, 1) // Send message over socket (ZeroMQ) zmq::message_t reply(message); From 5e899bf207b280e334da8fec6349f90898150609 Mon Sep 17 00:00:00 2001 From: Frank Dana Date: Wed, 25 Mar 2020 23:07:03 -0400 Subject: [PATCH 19/79] Add SWIG/Ruby compatibility check & warning (#480) --- src/bindings/ruby/CMakeLists.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/bindings/ruby/CMakeLists.txt b/src/bindings/ruby/CMakeLists.txt index dc571a81..2faa10fc 100644 --- a/src/bindings/ruby/CMakeLists.txt +++ b/src/bindings/ruby/CMakeLists.txt @@ -41,6 +41,23 @@ if (NOT RUBY_FOUND) return() endif() +### Ruby 2.7.0 made API changes that are incompatible with versions of +### SWIG prior to 4.0.3 +option(SILENCE_RUBY_VERSION_WARNING + "Don't warn about possible SWIG incompatibilities with Ruby 2.7.0+" OFF) + +if (${RUBY_VERSION} VERSION_GREATER 2.6.9 AND ${SWIG_VERSION} VERSION_LESS 4.0.3) + if (NOT ${SILENCE_RUBY_VERSION_WARNING}) + message(WARNING " +Ruby 2.7.0+ detected, building the libopenshot Ruby API bindings \ +requires a pre-release version of SWIG 4.0.3 with this commit: \ +https://github.com/swig/swig/commit/5542cc228ad10bdc5c91107afb77c808c43bf2a4") + message(STATUS " +To disable this warning, add -DSILENCE_RUBY_VERSION_WARNING:BOOL=1 to the cmake \ +command line, or enable the option in the CMake GUI.") + endif() +endif() + ### Include the Ruby header files include_directories(${RUBY_INCLUDE_DIRS}) From 455b6e92bff6de715e3a8f3349f43cc54bf1a8ff Mon Sep 17 00:00:00 2001 From: SuslikV Date: Thu, 26 Mar 2020 10:17:22 +0200 Subject: [PATCH 20/79] Fix float to int16_t conversion in resampler The backward conversion int16_t to float in libopenshot has range (1.0; -1.0], thus conversion -1.0f to int16_t should be secured. Float values can exceed the (1.0; -1.0) range. This can cause distortion in audio instead of limiting values at max/min for the int16_t. --- src/FrameMapper.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/FrameMapper.cpp b/src/FrameMapper.cpp index 7c4d04bb..4b213f81 100644 --- a/src/FrameMapper.cpp +++ b/src/FrameMapper.cpp @@ -785,10 +785,23 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr frame, int64_t orig // Create a new array (to hold all S16 audio samples for the current queued frames) int16_t* frame_samples = (int16_t*) av_malloc(sizeof(int16_t)*total_frame_samples); - // Translate audio sample values back to 16 bit integers - for (int s = 0; s < total_frame_samples; s++) - // Translate sample value and copy into buffer - frame_samples[s] = int(frame_samples_float[s] * (1 << 15)); + // Translate audio sample values back to 16 bit integers with saturation + float valF; + int16_t conv; + const int16_t max16 = 32767; + const int16_t min16 = -32768; + for (int s = 0; s < total_frame_samples; s++) { + valF = frame_samples_float[s] * (1 << 15); + if (valF > max16) + conv = max16; + else if (valF < min16) + conv = min16; + else + conv = int(valF + 32768.5) - 32768; // +0.5 is for rounding + + // Copy into buffer + frame_samples[s] = conv; + } // Deallocate float array From fda135725bbf518628fb4daa8af6e9eebd28ff9c Mon Sep 17 00:00:00 2001 From: Chiller Dragon Date: Thu, 26 Mar 2020 13:39:49 +0100 Subject: [PATCH 21/79] Ignore ctags file (#482) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c02a2fb9..58848653 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ .project .cproject /.metadata/ +tags *~ From 2701cf9079919ae3c3db2ece872c9e2fcaf558a4 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Thu, 26 Mar 2020 20:12:10 -0400 Subject: [PATCH 22/79] Add frame rate test to FFmpegReader_Tests --- tests/FFmpegReader_Tests.cpp | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/tests/FFmpegReader_Tests.cpp b/tests/FFmpegReader_Tests.cpp index 0a8620c9..6475e5ca 100644 --- a/tests/FFmpegReader_Tests.cpp +++ b/tests/FFmpegReader_Tests.cpp @@ -36,13 +36,16 @@ using namespace std; using namespace openshot; -TEST(FFmpegReader_Invalid_Path) +SUITE(FFmpegReader) +{ + +TEST(Invalid_Path) { // Check invalid path CHECK_THROW(FFmpegReader(""), InvalidFile); } -TEST(FFmpegReader_GetFrame_Before_Opening) +TEST(GetFrame_Before_Opening) { // Create a reader stringstream path; @@ -53,7 +56,7 @@ TEST(FFmpegReader_GetFrame_Before_Opening) CHECK_THROW(r.GetFrame(1), ReaderClosed); } -TEST(FFmpegReader_Check_Audio_File) +TEST(Check_Audio_File) { // Create a reader stringstream path; @@ -83,7 +86,7 @@ TEST(FFmpegReader_Check_Audio_File) r.Close(); } -TEST(FFmpegReader_Check_Video_File) +TEST(Check_Video_File) { // Create a reader stringstream path; @@ -129,7 +132,7 @@ TEST(FFmpegReader_Check_Video_File) r.Close(); } -TEST(FFmpegReader_Seek) +TEST(Seek) { // Create a reader stringstream path; @@ -186,7 +189,23 @@ TEST(FFmpegReader_Seek) } -TEST(FFmpegReader_Multiple_Open_and_Close) +TEST(Frame_Rate) +{ + // Create a reader + stringstream path; + path << TEST_MEDIA_PATH << "sintel_trailer-720p.mp4"; + FFmpegReader r(path.str()); + r.Open(); + + // Verify detected frame rate + openshot::Fraction rate = r.info.fps; + CHECK_EQUAL(24, rate.num); + CHECK_EQUAL(1, rate.den); + + r.Close(); +} + +TEST(Multiple_Open_and_Close) { // Create a reader stringstream path; @@ -221,3 +240,6 @@ TEST(FFmpegReader_Multiple_Open_and_Close) // Close reader r.Close(); } + +} // SUITE(FFmpegReader) + From c95333bf0afbd5e66ffbb46f03416fcdfa217eb2 Mon Sep 17 00:00:00 2001 From: Frank Dana Date: Fri, 27 Mar 2020 19:06:23 -0400 Subject: [PATCH 23/79] Fix Win64 Gitlab builds (#485) --- .gitlab-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6b2645d8..925bf020 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -72,7 +72,6 @@ windows-builder-x64: - cd build - cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -D"CMAKE_INSTALL_PREFIX:PATH=$CI_PROJECT_DIR\build\install-x64" -D"PYTHON_MODULE_PATH=python" -D"RUBY_MODULE_PATH=ruby" -G "MSYS Makefiles" -DCMAKE_MAKE_PROGRAM=mingw32-make -D"CMAKE_BUILD_TYPE:STRING=Release" ../ - mingw32-make install - - Move-Item -Force -path "install-x64\lib\python3.7\site-packages\*openshot*" -destination "install-x64\python\" - New-Item -path "install-x64/share/" -Name "$CI_PROJECT_NAME" -Value "CI_PROJECT_NAME:$CI_PROJECT_NAME`nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME`nCI_COMMIT_SHA:$CI_COMMIT_SHA`nCI_JOB_ID:$CI_JOB_ID" -ItemType file -force - $PREV_GIT_LABEL=(git describe --tags --abbrev=0 '@^') - git log "$PREV_GIT_LABEL..@" --oneline --pretty=format:"%C(auto,yellow)%h%C(auto,magenta)% %C(auto,blue)%>(12,trunc)%ad %C(auto,green)%<(25,trunc)%aN%C(auto,reset)%s%C(auto,red)% gD% D" --date=short > "install-x64/share/$CI_PROJECT_NAME.log" From 166f69389b6d8a601b51e8d559c418f56a144bba Mon Sep 17 00:00:00 2001 From: Frank Dana Date: Fri, 27 Mar 2020 19:07:23 -0400 Subject: [PATCH 24/79] Travis: Do some YAML syntax linting (#484) --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fca321d6..c93822fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ language: cpp compiler: gcc +os: linux +dist: xenial # This section uses a rather esoteric (and tricky!) feature of YAML, # &aliases and *anchors, to build package lists out of sublists without @@ -32,7 +34,7 @@ addons: - libavresample-dev - libswresample-dev -matrix: +jobs: include: - name: "Coverage + FFmpeg 3.4 GCC (Ubuntu 18.04 Bionic)" From 140e0828b73ab0f4533e661cc52b9f2fcdeb30bf Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Tue, 31 Mar 2020 19:00:12 -0400 Subject: [PATCH 25/79] INSTALL.md: Formatting, markdown cleanup --- INSTALL.md | 198 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 119 insertions(+), 79 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 474fb9c2..9d25603b 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -2,90 +2,120 @@ Operating system specific install instructions are located in: -* doc/INSTALL-LINUX.md -* doc/INSTALL-MAC.md -* doc/INSTALL-WINDOWS.md +* [doc/INSTALL-LINUX.md][INSTALL-LINUX] +* [doc/INSTALL-MAC.md][INSTALL-MAC] +* [doc/INSTALL-WINDOWS.md][INSTALL-WINDOWS] ## Getting Started -The best way to get started with libopenshot, is to learn about our build system, obtain all the source code, -install a development IDE and tools, and better understand our dependencies. So, please read through the -following sections, and follow the instructions. And keep in mind, that your computer is likely different -than the one used when writing these instructions. Your file paths and versions of applications might be +The best way to get started with libopenshot, is to learn about our build system, obtain all the source code, +install a development IDE and tools, and better understand our dependencies. So, please read through the +following sections, and follow the instructions. And keep in mind, that your computer is likely different +than the one used when writing these instructions. Your file paths and versions of applications might be slightly different, so keep an eye out for subtle file path differences in the commands you type. ## Build Tools -CMake is the backbone of our build system. It is a cross-platform build system, which checks for dependencies, -locates header files and libraries, generates makefiles, and supports the cross-platform compiling of -libopenshot and libopenshot-audio. CMake uses an out-of-source build concept, where all temporary build -files, such as makefiles, object files, and even the final binaries, are created outside of the source -code folder, inside a /build/ sub-folder. This prevents the build process from cluttering up the source -code. These instructions have only been tested with the GNU compiler (including MSYS2/MinGW for Windows). +CMake is the backbone of our build system. +It is a cross-platform build system, which checks for dependencies, +locates header files and libraries, and generates a build system in various formats. +We use CMake's Makefile generators to compile libopenshot and libopenshot-audio. -## Dependencies +CMake uses an out-of-source build concept. +This means that the build system, all temporary files, and all generated products are kept separate from the source code. +This includes Makefiles, object files, and even the final binaries. +While it is possible to build in-tree, we highly recommend you use a `/build/` sub-folder to compile each library. +This prevents the build process from cluttering up the source +code. +These instructions have only been tested with the GNU compiler suite (including MSYS2/MinGW for Windows), and the Clang compiler (including AppleClang on MacOS). -The following libraries are required to build libopenshot. Instructions on how to install these -dependencies vary for each operating system. Libraries and Executables have been labeled in the -list below to help distinguish between them. +### Dependencies -* ### FFmpeg (libavformat, libavcodec, libavutil, libavdevice, libavresample, libswscale) - * http://www.ffmpeg.org/ `(Library)` +The following libraries are required to build libopenshot. +Instructions on how to install these dependencies vary for each operating system. +Libraries and Executables have been labeled in the list below to help distinguish between them. + +#### FFmpeg (libavformat, libavcodec, libavutil, libavdevice, libavresample, libswscale) + + * http://www.ffmpeg.org/ **(Library)** * This library is used to decode and encode video, audio, and image files. It is also used to obtain information about media files, such as frame rate, sample rate, aspect ratio, and other common attributes. -* ### ImageMagick++ (libMagick++, libMagickWand, libMagickCore) - * http://www.imagemagick.org/script/magick++.php `(Library)` +#### ImageMagick++ (libMagick++, libMagickWand, libMagickCore) + * http://www.imagemagick.org/script/magick++.php **(Library)** * This library is **optional**, and used to decode and encode images. -* ### OpenShot Audio Library (libopenshot-audio) - * https://github.com/OpenShot/libopenshot-audio/ `(Library)` +#### OpenShot Audio Library (libopenshot-audio) + * https://github.com/OpenShot/libopenshot-audio/ **(Library)** * This library is used to mix, resample, host plug-ins, and play audio. It is based on the JUCE project, which is an outstanding audio library used by many different applications -* ### Qt 5 (libqt5) - * http://www.qt.io/qt5/ `(Library)` +#### Qt 5 (libqt5) + * http://www.qt.io/qt5/ **(Library)** * Qt5 is used to display video, store image data, composite images, apply image effects, and many other utility functions, such as file system manipulation, high resolution timers, etc... -* ### CMake (cmake) - * http://www.cmake.org/ `(Executable)` - * This executable is used to automate the generation of Makefiles, check for dependencies, and is the backbone of libopenshot’s cross-platform build process. - -* ### SWIG (swig) - * http://www.swig.org/ `(Executable)` - * This executable is used to generate the Python and Ruby bindings for libopenshot. It is a simple and powerful wrapper for C++ libraries, and supports many languages. - -* ### Python 3 (libpython) - * http://www.python.org/ `(Executable and Library)` - * This library is used by swig to create the Python (version 3+) bindings for libopenshot. This is also the official language used by OpenShot Video Editor (a graphical interface to libopenshot). - -* ### Doxygen (doxygen) - * http://www.stack.nl/~dimitri/doxygen/ `(Executable)` - * This executable is used to auto-generate the documentation used by libopenshot. - -* ### UnitTest++ (libunittest++) - * https://github.com/unittest-cpp/ `(Library)` - * This library is used to execute unit tests for libopenshot. It contains many macros used to keep our unit testing code very clean and simple. - -* ### ZeroMQ (libzmq) - * http://zeromq.org/ `(Library)` +#### ZeroMQ (libzmq) + * http://zeromq.org/ **(Library)** * This library is used to communicate between libopenshot and other applications (publisher / subscriber). Primarily used to send debug data from libopenshot. -* ### OpenMP (-fopenmp) - * http://openmp.org/wp/ `(Compiler Flag)` +#### OpenMP (`-fopenmp`) + * http://openmp.org/wp/ **(Compiler Flag)** * If your compiler supports this flag (GCC, Clang, and most other compilers), it provides libopenshot with easy methods of using parallel programming techniques to improve performance and take advantage of multi-core processors. -## CMake Flags (Optional) -There are many different build flags that can be passed to cmake to adjust how libopenshot is compiled. Some of these flags might be required when compiling on certain OSes, just depending on how your build environment is setup. To add a build flag, follow this general syntax: $ cmake -DMAGICKCORE_HDRI_ENABLE=1 -DENABLE_TESTS=1 ../ +#### CMake (`cmake`) + * http://www.cmake.org/ **(Executable)** + * This executable is used to automate the generation of Makefiles, check for dependencies, and is the backbone of libopenshot’s cross-platform build process. -* MAGICKCORE_HDRI_ENABLE (default 0) -* MAGICKCORE_QUANTUM_DEPTH (default 0) -* OPENSHOT_IMAGEMAGICK_COMPATIBILITY (default 0) -* DISABLE_TESTS (default 0) -* CMAKE_PREFIX_PATH (`/location/to/missing/library/`) -* PYTHON_INCLUDE_DIR (`/location/to/python/include/`) -* PYTHON_LIBRARY (`/location/to/python/lib.a`) -* PYTHON_FRAMEWORKS (`/usr/local/Cellar/python3/3.3.2/Frameworks/Python.framework/`) -* CMAKE_CXX_COMPILER (`/location/to/mingw/g++`) -* CMAKE_C_COMPILER (`/location/to/mingw/gcc`) +#### SWIG (`swig`) + * http://www.swig.org/ **(Executable)** + * This executable is used to generate the Python and Ruby bindings for libopenshot. It is a simple and powerful wrapper for C++ libraries, and supports many languages. + +#### Python 3 (libpython) + * http://www.python.org/ **(Executable and Library)** + * This library is used by swig to create the Python (version 3+) bindings for libopenshot. This is also the official language used by OpenShot Video Editor (a graphical interface to libopenshot). + +#### Doxygen (doxygen) + * http://www.stack.nl/~dimitri/doxygen/ **(Executable)** + * This executable is used to auto-generate the documentation used by libopenshot. + +#### UnitTest++ (libunittest++) + * https://github.com/unittest-cpp/ **(Library)** + * This library is used to execute unit tests for libopenshot. It contains many macros used to keep our unit testing code very clean and simple. + + +### CMake Flags (Optional) +There are many different build flags that can be passed to cmake to adjust how libopenshot is compiled. Some of these flags might be required when compiling on certain OSes, just depending on how your build environment is setup. + +To add a build flag, follow this general syntax: + +```sh +$ cmake -DMAGICKCORE_HDRI_ENABLE=1 -DENABLE_TESTS=1 .. +``` + +Following are some of the flags you might need to set when generating your build system. + +##### Optional behavior: +* `-DENABLE_TESTS=0` (default: `ON`) +* `-DENABLE_COVERAGE=1` (default: `OFF`) +* `-DENABLE_DOCS=0` (default: `ON` if doxygen found) + +##### Compiler configuration: +* `-DCMAKE_BUILD_TYPE=Debug` (default: `Release`) +* `-DCMAKE_CXX_FLAGS="-Wall -Wextra"` (default: auto for build type) +* `-DCMAKE_CXX_COMPILER=/path/to/g++` +* `-DCMAKE_C_COMPILER=/path/to/gcc` (used by CMake for OS probes) + +##### Dependency configuration: +* `-DCMAKE_PREFIX_PATH=/extra/path/to/search/for/libraries/` +* `-DUSE_SYSTEM_JSONCPP=0` (default: auto if discovered) +* `-DImageMagick_FOUND=0` (default: auto if discovered) + +##### To compile bindings for a specific Python installation: +* `-DPYTHON_INCLUDE_DIR=/location/of/python/includes/` +* `-DPYTHON_LIBRARY=/location/of/libpython*.so` +* `-DPYTHON_FRAMEWORKS=/usr/local/Cellar/python3/3.3.2/Frameworks/Python.framework/` (MacOS only) + +##### Only used when building with ImageMagick enabled: +* `-DMAGICKCORE_HDRI_ENABLE=1` (default `0`) +* `-DMAGICKCORE_QUANTUM_DEPTH=8` (default `16`) ## Obtaining Source Code @@ -96,30 +126,36 @@ git clone https://github.com/OpenShot/libopenshot.git git clone https://github.com/OpenShot/libopenshot-audio.git ``` -## Folder Structure (libopenshot) +### Folder Structure (libopenshot) The source code is divided up into the following folders. -* ### build/ - * This folder needs to be manually created, and is used by cmake to store the temporary build files, such as makefiles, as well as the final binaries (library and test executables). +#### `build/` +This folder needs to be manually created, and is used by cmake to store the temporary build files, such as makefiles, as well as the final binaries (library and test executables). -* ### cmake/ - * This folder contains custom modules not included by default in cmake, used to find dependency libraries and headers and determine if these libraries are installed. +#### `cmake/` +This folder contains custom modules not included by default in cmake. +CMake find modules are used to discover dependency libraries on the system, and to incorporate their headers and object files. +CMake code modules are used to implement build features such as test coverage scanning. -* ### doc/ - * This folder contains documentation and related files, such as logos and images required by the doxygen auto-generated documentation. +#### `doc/` +This folder contains documentation and related files. +This includes logos and images required by the doxygen-generated API documentation. -* ### include/ - * This folder contains all headers (*.h) used by libopenshot. +#### `include/` +This folder contains all headers (*.h) used by libopenshot. -* ### src/ - * This folder contains all source code (*.cpp) used by libopenshot. +#### `src/` +This folder contains all source code (*.cpp) used by libopenshot. -* ### tests/ - * This folder contains all unit test code. Each class has it’s own test file (*.cpp), and uses UnitTest++ macros to keep the test code simple and manageable. +#### `tests/` +This folder contains all unit test code. +Each test file (`_Tests.cpp`) contains the tests for the named class. +We use UnitTest++ macros to keep the test code simple and manageable. -* ### thirdparty/ - * This folder contains code not written by the OpenShot team. For example, jsoncpp, an open-source JSON parser. +#### `thirdparty/` +This folder contains code not written by the OpenShot team. +For example, `jsoncpp`, an open-source JSON parser. ## Linux Build Instructions (libopenshot-audio) To compile libopenshot-audio, we need to go through a few additional steps to manually build and install it. Launch a terminal and enter: @@ -148,6 +184,10 @@ make install For more detailed instructions, please see: -* doc/INSTALL-LINUX.md -* doc/INSTALL-MAC.md -* doc/INSTALL-WINDOWS.md +* [doc/INSTALL-LINUX.md][INSTALL-LINUX] +* [doc/INSTALL-MAC.md][INSTALL-MAC] +* [doc/INSTALL-WINDOWS.md][INSTALL-WINDOWS] + +[INSTALL-LINUX]: https://github.com/OpenShot/libopenshot/blob/develop/doc/INSTALL-LINUX.md +[INSTALL-MAC]: https://github.com/OpenShot/libopenshot/blob/develop/doc/INSTALL-MAC.md +[INSTALL-WINDOWS]: https://github.com/OpenShot/libopenshot/blob/develop/doc/INSTALL-WINDOWS.md From 2bea436f3ea1a3e35f97af4af908750e2bf236d0 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Mon, 13 Apr 2020 16:55:29 -0500 Subject: [PATCH 26/79] Adding keyframable origin point (for shear and rotation) --- include/Clip.h | 24 +++++++++++++----------- src/Clip.cpp | 10 ++++++++++ src/Timeline.cpp | 33 +++++++++++++++------------------ 3 files changed, 38 insertions(+), 29 deletions(-) diff --git a/include/Clip.h b/include/Clip.h index 68d4622a..488f7efa 100644 --- a/include/Clip.h +++ b/include/Clip.h @@ -140,11 +140,11 @@ namespace openshot { void reverse_buffer(juce::AudioSampleBuffer* buffer); public: - openshot::GravityType gravity; ///< The gravity of a clip determines where it snaps to its parent - openshot::ScaleType scale; ///< The scale determines how a clip should be resized to fit its parent - openshot::AnchorType anchor; ///< The anchor determines what parent a clip should snap to - openshot::FrameDisplayType display; ///< The format to display the frame number (if any) - openshot::VolumeMixType mixing; ///< What strategy should be followed when mixing audio with other clips + openshot::GravityType gravity; ///< The gravity of a clip determines where it snaps to its parent + openshot::ScaleType scale; ///< The scale determines how a clip should be resized to fit its parent + openshot::AnchorType anchor; ///< The anchor determines what parent a clip should snap to + openshot::FrameDisplayType display; ///< The format to display the frame number (if any) + openshot::VolumeMixType mixing; ///< What strategy should be followed when mixing audio with other clips /// Default Constructor Clip(); @@ -208,15 +208,19 @@ namespace openshot { bool Waveform() { return waveform; } ///< Get the waveform property of this clip void Waveform(bool value) { waveform = value; } ///< Set the waveform property of this clip - // Scale and Location curves + // Scale, Location, and Alpha curves openshot::Keyframe scale_x; ///< Curve representing the horizontal scaling in percent (0 to 1) openshot::Keyframe scale_y; ///< Curve representing the vertical scaling in percent (0 to 1) openshot::Keyframe location_x; ///< Curve representing the relative X position in percent based on the gravity (-1 to 1) openshot::Keyframe location_y; ///< Curve representing the relative Y position in percent based on the gravity (-1 to 1) - - // Alpha and Rotation curves openshot::Keyframe alpha; ///< Curve representing the alpha (1 to 0) + + // Rotation and Shear curves (origin point (x,y) is adjustable for both rotation and shear) openshot::Keyframe rotation; ///< Curve representing the rotation (0 to 360) + openshot::Keyframe shear_x; ///< Curve representing X shear angle in degrees (-45.0=left, 45.0=right) + openshot::Keyframe shear_y; ///< Curve representing Y shear angle in degrees (-45.0=down, 45.0=up) + openshot::Keyframe origin_x; ///< Curve representing X origin point (0.0=0% (left), 1.0=100% (right)) + openshot::Keyframe origin_y; ///< Curve representing Y origin point (0.0=0% (top), 1.0=100% (bottom)) // Time and Volume curves openshot::Keyframe time; ///< Curve representing the frames over time to play (used for speed and direction of video) @@ -232,9 +236,7 @@ namespace openshot { openshot::Keyframe crop_x; ///< Curve representing X offset in percent (-1.0=-100%, 0.0=0%, 1.0=100%) openshot::Keyframe crop_y; ///< Curve representing Y offset in percent (-1.0=-100%, 0.0=0%, 1.0=100%) - // Shear and perspective curves - openshot::Keyframe shear_x; ///< Curve representing X shear angle in degrees (-45.0=left, 45.0=right) - openshot::Keyframe shear_y; ///< Curve representing Y shear angle in degrees (-45.0=down, 45.0=up) + // Perspective curves openshot::Keyframe perspective_c1_x; ///< Curves representing X for coordinate 1 openshot::Keyframe perspective_c1_y; ///< Curves representing Y for coordinate 1 openshot::Keyframe perspective_c2_x; ///< Curves representing X for coordinate 2 diff --git a/src/Clip.cpp b/src/Clip.cpp index 1968bb3b..f4920ccd 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -89,6 +89,8 @@ void Clip::init_settings() // Init shear and perspective curves shear_x = Keyframe(0.0); shear_y = Keyframe(0.0); + origin_x = Keyframe(0.5); + origin_y = Keyframe(0.5); perspective_c1_x = Keyframe(-1.0); perspective_c1_y = Keyframe(-1.0); perspective_c2_x = Keyframe(-1.0); @@ -718,6 +720,8 @@ std::string Clip::PropertiesJSON(int64_t requested_frame) const { root["shear_x"] = add_property_json("Shear X", shear_x.GetValue(requested_frame), "float", "", &shear_x, -1.0, 1.0, false, requested_frame); root["shear_y"] = add_property_json("Shear Y", shear_y.GetValue(requested_frame), "float", "", &shear_y, -1.0, 1.0, false, requested_frame); root["rotation"] = add_property_json("Rotation", rotation.GetValue(requested_frame), "float", "", &rotation, -360, 360, false, requested_frame); + root["origin_x"] = add_property_json("Origin X", origin_x.GetValue(requested_frame), "float", "", &origin_x, 0.0, 1.0, false, requested_frame); + root["origin_y"] = add_property_json("Origin Y", origin_y.GetValue(requested_frame), "float", "", &origin_y, 0.0, 1.0, false, requested_frame); root["volume"] = add_property_json("Volume", volume.GetValue(requested_frame), "float", "", &volume, 0.0, 1.0, false, requested_frame); root["time"] = add_property_json("Time", time.GetValue(requested_frame), "float", "", &time, 0.0, 30 * 60 * 60 * 48, false, requested_frame); root["channel_filter"] = add_property_json("Channel Filter", channel_filter.GetValue(requested_frame), "int", "", &channel_filter, -1, 10, false, requested_frame); @@ -774,6 +778,8 @@ Json::Value Clip::JsonValue() const { root["crop_y"] = crop_y.JsonValue(); root["shear_x"] = shear_x.JsonValue(); root["shear_y"] = shear_y.JsonValue(); + root["origin_x"] = origin_x.JsonValue(); + root["origin_y"] = origin_y.JsonValue(); root["channel_filter"] = channel_filter.JsonValue(); root["channel_mapping"] = channel_mapping.JsonValue(); root["has_audio"] = has_audio.JsonValue(); @@ -871,6 +877,10 @@ void Clip::SetJsonValue(const Json::Value root) { shear_x.SetJsonValue(root["shear_x"]); if (!root["shear_y"].isNull()) shear_y.SetJsonValue(root["shear_y"]); + if (!root["origin_x"].isNull()) + origin_x.SetJsonValue(root["origin_x"]); + if (!root["origin_y"].isNull()) + origin_y.SetJsonValue(root["origin_y"]); if (!root["channel_filter"].isNull()) channel_filter.SetJsonValue(root["channel_filter"]); if (!root["channel_mapping"].isNull()) diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 61ce31e3..079d2346 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -677,6 +677,8 @@ void Timeline::add_layer(std::shared_ptr new_frame, Clip* source_clip, in y += (Settings::Instance()->MAX_HEIGHT * source_clip->location_y.GetValue(clip_frame_number)); // move in percentage of final height float shear_x = source_clip->shear_x.GetValue(clip_frame_number); float shear_y = source_clip->shear_y.GetValue(clip_frame_number); + float origin_x = source_clip->origin_x.GetValue(clip_frame_number); + float origin_y = source_clip->origin_y.GetValue(clip_frame_number); bool transformed = false; QTransform transform; @@ -684,21 +686,22 @@ void Timeline::add_layer(std::shared_ptr new_frame, Clip* source_clip, in // Transform source image (if needed) ZmqLogger::Instance()->AppendDebugMethod("Timeline::add_layer (Build QTransform - if needed)", "source_frame->number", source_frame->number, "x", x, "y", y, "r", r, "sx", sx, "sy", sy); - if (!isEqual(r, 0)) { - // ROTATE CLIP - float origin_x = x + (scaled_source_width / 2.0); - float origin_y = y + (scaled_source_height / 2.0); - transform.translate(origin_x, origin_y); - transform.rotate(r); - transform.translate(-origin_x,-origin_y); + if (!isEqual(x, 0) || !isEqual(y, 0)) { + // TRANSLATE/MOVE CLIP + transform.translate(x, y); transformed = true; } - if (!isEqual(x, 0) || !isEqual(y, 0)) { - // TRANSLATE/MOVE CLIP - transform.translate(x, y); - transformed = true; - } + if (!isEqual(r, 0) || !isEqual(shear_x, 0) || !isEqual(shear_y, 0)) { + // ROTATE CLIP (around origin_x, origin_y) + float origin_x_value = (scaled_source_width * origin_x); + float origin_y_value = (scaled_source_height * origin_y); + transform.translate(origin_x_value, origin_y_value); + transform.rotate(r); + transform.shear(shear_x, shear_y); + transform.translate(-origin_x_value,-origin_y_value); + transformed = true; + } // SCALE CLIP (if needed) float source_width_scale = (float(source_size.width()) / float(source_image->width())) * sx; @@ -709,12 +712,6 @@ void Timeline::add_layer(std::shared_ptr new_frame, Clip* source_clip, in transformed = true; } - if (!isEqual(shear_x, 0) || !isEqual(shear_y, 0)) { - // SHEAR HEIGHT/WIDTH - transform.shear(shear_x, shear_y); - transformed = true; - } - // Debug output ZmqLogger::Instance()->AppendDebugMethod("Timeline::add_layer (Transform: Composite Image Layer: Prepare)", "source_frame->number", source_frame->number, "new_frame->GetImage()->width()", new_frame->GetImage()->width(), "transformed", transformed); From f354850984e1a6dc64ecc33524129de1a8a5b080 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Wed, 15 Apr 2020 21:44:17 -0400 Subject: [PATCH 27/79] Effects: Mark overridden methods accordingly --- include/effects/Bars.h | 6 +++--- include/effects/Blur.h | 6 +++--- include/effects/Brightness.h | 6 +++--- include/effects/ChromaKey.h | 6 +++--- include/effects/ColorShift.h | 6 +++--- include/effects/Crop.h | 6 +++--- include/effects/Deinterlace.h | 6 +++--- include/effects/Hue.h | 6 +++--- include/effects/Mask.h | 6 +++--- include/effects/Negate.h | 6 +++--- include/effects/Pixelate.h | 6 +++--- include/effects/Saturation.h | 6 +++--- include/effects/Shift.h | 6 +++--- include/effects/Wave.h | 6 +++--- 14 files changed, 42 insertions(+), 42 deletions(-) diff --git a/include/effects/Bars.h b/include/effects/Bars.h index fa9df6f8..7c92255a 100644 --- a/include/effects/Bars.h +++ b/include/effects/Bars.h @@ -86,13 +86,13 @@ namespace openshot /// @returns The modified openshot::Frame object /// @param frame The frame object that needs the effect applied to it /// @param frame_number The frame number (starting at 1) of the effect on the timeline. - std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number); + std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Get all properties for a specific frame (perfect for a UI to display the current state /// of all properties at any time) diff --git a/include/effects/Blur.h b/include/effects/Blur.h index c254b8cd..60a0cd08 100644 --- a/include/effects/Blur.h +++ b/include/effects/Blur.h @@ -98,13 +98,13 @@ namespace openshot /// @returns The modified openshot::Frame object /// @param frame The frame object that needs the effect applied to it /// @param frame_number The frame number (starting at 1) of the effect on the timeline. - std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number); + std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Get all properties for a specific frame (perfect for a UI to display the current state /// of all properties at any time) diff --git a/include/effects/Brightness.h b/include/effects/Brightness.h index 69f2cf34..5f25b94a 100644 --- a/include/effects/Brightness.h +++ b/include/effects/Brightness.h @@ -86,13 +86,13 @@ namespace openshot /// @returns The modified openshot::Frame object /// @param frame The frame object that needs the effect applied to it /// @param frame_number The frame number (starting at 1) of the effect on the timeline. - std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number); + std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Get all properties for a specific frame (perfect for a UI to display the current state /// of all properties at any time) diff --git a/include/effects/ChromaKey.h b/include/effects/ChromaKey.h index dbc81e9c..fcc8c3b1 100644 --- a/include/effects/ChromaKey.h +++ b/include/effects/ChromaKey.h @@ -83,13 +83,13 @@ namespace openshot /// @returns The modified openshot::Frame object /// @param frame The frame object that needs the effect applied to it /// @param frame_number The frame number (starting at 1) of the effect on the timeline. - std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number); + std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object // Get all properties for a specific frame std::string PropertiesJSON(int64_t requested_frame) const override; diff --git a/include/effects/ColorShift.h b/include/effects/ColorShift.h index ada2acd6..4ef56dc6 100644 --- a/include/effects/ColorShift.h +++ b/include/effects/ColorShift.h @@ -90,13 +90,13 @@ namespace openshot /// @returns The modified openshot::Frame object /// @param frame The frame object that needs the effect applied to it /// @param frame_number The frame number (starting at 1) of the effect on the timeline. - std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number); + std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Get all properties for a specific frame (perfect for a UI to display the current state /// of all properties at any time) diff --git a/include/effects/Crop.h b/include/effects/Crop.h index 2d4a2b2e..f5ba07f2 100644 --- a/include/effects/Crop.h +++ b/include/effects/Crop.h @@ -85,13 +85,13 @@ namespace openshot /// @returns The modified openshot::Frame object /// @param frame The frame object that needs the effect applied to it /// @param frame_number The frame number (starting at 1) of the effect on the timeline. - std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number); + std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Get all properties for a specific frame (perfect for a UI to display the current state /// of all properties at any time) diff --git a/include/effects/Deinterlace.h b/include/effects/Deinterlace.h index eff7b2fe..97c77853 100644 --- a/include/effects/Deinterlace.h +++ b/include/effects/Deinterlace.h @@ -79,13 +79,13 @@ namespace openshot /// @returns The modified openshot::Frame object /// @param frame The frame object that needs the effect applied to it /// @param frame_number The frame number (starting at 1) of the effect on the timeline. - std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number); + std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object // Get all properties for a specific frame std::string PropertiesJSON(int64_t requested_frame) const override; diff --git a/include/effects/Hue.h b/include/effects/Hue.h index 9d86d5c2..833bf087 100644 --- a/include/effects/Hue.h +++ b/include/effects/Hue.h @@ -76,13 +76,13 @@ namespace openshot /// @returns The modified openshot::Frame object /// @param frame The frame object that needs the effect applied to it /// @param frame_number The frame number (starting at 1) of the effect on the timeline. - std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number); + std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Get all properties for a specific frame (perfect for a UI to display the current state /// of all properties at any time) diff --git a/include/effects/Mask.h b/include/effects/Mask.h index 390ffa36..8156b843 100644 --- a/include/effects/Mask.h +++ b/include/effects/Mask.h @@ -98,13 +98,13 @@ namespace openshot /// @returns The modified openshot::Frame object /// @param frame The frame object that needs the effect applied to it /// @param frame_number The frame number (starting at 1) of the effect on the timeline. - std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number); + std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Get all properties for a specific frame (perfect for a UI to display the current state /// of all properties at any time) diff --git a/include/effects/Negate.h b/include/effects/Negate.h index 6206a660..c691a86c 100644 --- a/include/effects/Negate.h +++ b/include/effects/Negate.h @@ -67,13 +67,13 @@ namespace openshot /// @returns The modified openshot::Frame object /// @param frame The frame object that needs the effect applied to it /// @param frame_number The frame number (starting at 1) of the effect on the timeline. - std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number); + std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object // Get all properties for a specific frame std::string PropertiesJSON(int64_t requested_frame) const override; diff --git a/include/effects/Pixelate.h b/include/effects/Pixelate.h index 9348ce86..4cdd440f 100644 --- a/include/effects/Pixelate.h +++ b/include/effects/Pixelate.h @@ -85,13 +85,13 @@ namespace openshot /// @returns The modified openshot::Frame object /// @param frame The frame object that needs the effect applied to it /// @param frame_number The frame number (starting at 1) of the effect on the timeline. - std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number); + std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Get all properties for a specific frame (perfect for a UI to display the current state /// of all properties at any time) diff --git a/include/effects/Saturation.h b/include/effects/Saturation.h index e8d0d940..f272305f 100644 --- a/include/effects/Saturation.h +++ b/include/effects/Saturation.h @@ -83,13 +83,13 @@ namespace openshot /// @returns The modified openshot::Frame object /// @param frame The frame object that needs the effect applied to it /// @param frame_number The frame number (starting at 1) of the effect on the timeline. - std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number); + std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Get all properties for a specific frame (perfect for a UI to display the current state /// of all properties at any time) diff --git a/include/effects/Shift.h b/include/effects/Shift.h index 765da755..7a7efbea 100644 --- a/include/effects/Shift.h +++ b/include/effects/Shift.h @@ -79,13 +79,13 @@ namespace openshot /// @returns The modified openshot::Frame object /// @param frame The frame object that needs the effect applied to it /// @param frame_number The frame number (starting at 1) of the effect on the timeline. - std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number); + std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Get all properties for a specific frame (perfect for a UI to display the current state /// of all properties at any time) diff --git a/include/effects/Wave.h b/include/effects/Wave.h index ad516bde..d4759c24 100644 --- a/include/effects/Wave.h +++ b/include/effects/Wave.h @@ -85,13 +85,13 @@ namespace openshot /// @returns The modified openshot::Frame object /// @param frame The frame object that needs the effect applied to it /// @param frame_number The frame number (starting at 1) of the effect on the timeline. - std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number); + std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Get all properties for a specific frame (perfect for a UI to display the current state /// of all properties at any time) From f62f2bac6bf96aa6c22d079eee932eb0d8f89c7e Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Wed, 15 Apr 2020 21:45:04 -0400 Subject: [PATCH 28/79] Overrides for derived-class methods --- include/ChunkReader.h | 16 ++++++++-------- include/Clip.h | 4 ++-- include/DummyReader.h | 16 ++++++++-------- include/FFmpegReader.h | 16 ++++++++-------- include/FrameMapper.h | 16 ++++++++-------- include/ImageReader.h | 18 +++++++++--------- include/QtHtmlReader.h | 16 ++++++++-------- include/QtImageReader.h | 16 ++++++++-------- include/QtTextReader.h | 16 ++++++++-------- include/TextReader.h | 16 ++++++++-------- include/Timeline.h | 16 ++++++++-------- 11 files changed, 83 insertions(+), 83 deletions(-) diff --git a/include/ChunkReader.h b/include/ChunkReader.h index 4d72c31d..cd7cd67f 100644 --- a/include/ChunkReader.h +++ b/include/ChunkReader.h @@ -132,7 +132,7 @@ namespace openshot ChunkReader(std::string path, ChunkVersion chunk_version); /// Close the reader - void Close(); + void Close() override; /// @brief Get the chunk size (number of frames to write in each chunk) /// @returns The number of frames in this chunk @@ -143,27 +143,27 @@ namespace openshot void SetChunkSize(int64_t new_size) { chunk_size = new_size; }; /// Get the cache object used by this reader (always return NULL for this reader) - openshot::CacheMemory* GetCache() { return NULL; }; + openshot::CacheMemory* GetCache() override { return NULL; }; /// @brief Get an openshot::Frame object for a specific frame number of this reader. /// @returns The requested frame (containing the image and audio) /// @param requested_frame The frame number you want to retrieve - std::shared_ptr GetFrame(int64_t requested_frame); + std::shared_ptr GetFrame(int64_t requested_frame) override; /// Determine if reader is open or closed - bool IsOpen() { return is_open; }; + bool IsOpen() override { return is_open; }; /// Return the type name of the class - std::string Name() { return "ChunkReader"; }; + std::string Name() override { return "ChunkReader"; }; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Open the reader. This is required before you can access frames or data from the reader. - void Open(); + void Open() override; }; } diff --git a/include/Clip.h b/include/Clip.h index 68d4622a..1f4cd385 100644 --- a/include/Clip.h +++ b/include/Clip.h @@ -192,9 +192,9 @@ namespace openshot { /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Get all properties for a specific frame (perfect for a UI to display the current state /// of all properties at any time) diff --git a/include/DummyReader.h b/include/DummyReader.h index fd17bed1..4c935103 100644 --- a/include/DummyReader.h +++ b/include/DummyReader.h @@ -68,32 +68,32 @@ namespace openshot virtual ~DummyReader(); /// Close File - void Close(); + void Close() override; /// Get the cache object used by this reader (always returns NULL for this reader) - CacheMemory* GetCache() { return NULL; }; + CacheMemory* GetCache() override { return NULL; }; /// Get an openshot::Frame object for a specific frame number of this reader. All numbers /// return the same Frame, since they all share the same image data. /// /// @returns The requested frame (containing the image) /// @param requested_frame The frame number that is requested. - std::shared_ptr GetFrame(int64_t requested_frame); + std::shared_ptr GetFrame(int64_t requested_frame) override; /// Determine if reader is open or closed - bool IsOpen() { return is_open; }; + bool IsOpen() override { return is_open; }; /// Return the type name of the class - std::string Name() { return "DummyReader"; }; + std::string Name() override { return "DummyReader"; }; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Open File - which is called by the constructor automatically - void Open(); + void Open() override; }; } diff --git a/include/FFmpegReader.h b/include/FFmpegReader.h index e9cee579..ec082965 100644 --- a/include/FFmpegReader.h +++ b/include/FFmpegReader.h @@ -246,31 +246,31 @@ namespace openshot { virtual ~FFmpegReader(); /// Close File - void Close(); + void Close() override; /// Get the cache object used by this reader - CacheMemory *GetCache() { return &final_cache; }; + CacheMemory *GetCache() override { return &final_cache; }; /// Get a shared pointer to a openshot::Frame object for a specific frame number of this reader. /// /// @returns The requested frame of video /// @param requested_frame The frame number that is requested. - std::shared_ptr GetFrame(int64_t requested_frame); + std::shared_ptr GetFrame(int64_t requested_frame) override; /// Determine if reader is open or closed - bool IsOpen() { return is_open; }; + bool IsOpen() override { return is_open; }; /// Return the type name of the class - std::string Name() { return "FFmpegReader"; }; + std::string Name() override { return "FFmpegReader"; }; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Open File - which is called by the constructor automatically - void Open(); + void Open() override; }; } diff --git a/include/FrameMapper.h b/include/FrameMapper.h index 8be4ec1b..c98d7b71 100644 --- a/include/FrameMapper.h +++ b/include/FrameMapper.h @@ -176,13 +176,13 @@ namespace openshot void ChangeMapping(Fraction target_fps, PulldownType pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout); /// Close the openshot::FrameMapper and internal reader - void Close(); + void Close() override; /// Get a frame based on the target frame rate and the new frame number of a frame MappedFrame GetMappedFrame(int64_t TargetFrameNumber); /// Get the cache object used by this reader - CacheMemory* GetCache() { return &final_cache; }; + CacheMemory* GetCache() override { return &final_cache; }; /// @brief This method is required for all derived classes of ReaderBase, and return the /// openshot::Frame object, which contains the image and audio information for that @@ -190,22 +190,22 @@ namespace openshot /// /// @returns The requested frame of video /// @param requested_frame The frame number that is requested. - std::shared_ptr GetFrame(int64_t requested_frame); + std::shared_ptr GetFrame(int64_t requested_frame) override; /// Determine if reader is open or closed - bool IsOpen(); + bool IsOpen() override; /// Return the type name of the class - std::string Name() { return "FrameMapper"; }; + std::string Name() override { return "FrameMapper"; }; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Open the internal reader - void Open(); + void Open() override; /// Print all of the original frames and which new frames they map to void PrintMapping(); diff --git a/include/ImageReader.h b/include/ImageReader.h index bb19dd3d..5aafcc8f 100644 --- a/include/ImageReader.h +++ b/include/ImageReader.h @@ -87,32 +87,32 @@ namespace openshot ImageReader(std::string path, bool inspect_reader); /// Close File - void Close(); + void Close() override; /// Get the cache object used by this reader (always returns NULL for this object) - CacheMemory* GetCache() { return NULL; }; + CacheMemory* GetCache() override { return NULL; }; /// Get an openshot::Frame object for a specific frame number of this reader. All numbers /// return the same Frame, since they all share the same image data. /// /// @returns The requested frame (containing the image) /// @param requested_frame The frame number that is requested. - std::shared_ptr GetFrame(int64_t requested_frame); + std::shared_ptr GetFrame(int64_t requested_frame) override; /// Determine if reader is open or closed - bool IsOpen() { return is_open; }; + bool IsOpen() override { return is_open; }; /// Return the type name of the class - std::string Name() { return "ImageReader"; }; + std::string Name() override { return "ImageReader"; }; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object - Json::Value JsonValue() const; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object + Json::Value JsonValue() const override; ///< Generate Json::Value for this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Open File - which is called by the constructor automatically - void Open(); + void Open() override; }; } diff --git a/include/QtHtmlReader.h b/include/QtHtmlReader.h index d7052d49..3d426afb 100644 --- a/include/QtHtmlReader.h +++ b/include/QtHtmlReader.h @@ -112,32 +112,32 @@ namespace openshot QtHtmlReader(int width, int height, int x_offset, int y_offset, GravityType gravity, std::string html, std::string css, std::string background_color); /// Close Reader - void Close(); + void Close() override; /// Get the cache object used by this reader (always returns NULL for this object) - openshot::CacheMemory* GetCache() { return NULL; }; + openshot::CacheMemory* GetCache() override { return NULL; }; /// Get an openshot::Frame object for a specific frame number of this reader. All numbers /// return the same Frame, since they all share the same image data. /// /// @returns The requested frame (containing the image) /// @param requested_frame The frame number that is requested. - std::shared_ptr GetFrame(int64_t requested_frame); + std::shared_ptr GetFrame(int64_t requested_frame) override; /// Determine if reader is open or closed - bool IsOpen() { return is_open; }; + bool IsOpen() override { return is_open; }; /// Return the type name of the class - std::string Name() { return "QtHtmlReader"; }; + std::string Name() override { return "QtHtmlReader"; }; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Open Reader - which is called by the constructor automatically - void Open(); + void Open() override; }; } diff --git a/include/QtImageReader.h b/include/QtImageReader.h index 3e456e39..3848065a 100644 --- a/include/QtImageReader.h +++ b/include/QtImageReader.h @@ -85,32 +85,32 @@ namespace openshot virtual ~QtImageReader(); /// Close File - void Close(); + void Close() override; /// Get the cache object used by this reader (always returns NULL for this object) - CacheMemory* GetCache() { return NULL; }; + CacheMemory* GetCache() override { return NULL; }; /// Get an openshot::Frame object for a specific frame number of this reader. All numbers /// return the same Frame, since they all share the same image data. /// /// @returns The requested frame (containing the image) /// @param requested_frame The frame number that is requested. - std::shared_ptr GetFrame(int64_t requested_frame); + std::shared_ptr GetFrame(int64_t requested_frame) override; /// Determine if reader is open or closed - bool IsOpen() { return is_open; }; + bool IsOpen() override { return is_open; }; /// Return the type name of the class - std::string Name() { return "QtImageReader"; }; + std::string Name() override { return "QtImageReader"; }; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Open File - which is called by the constructor automatically - void Open(); + void Open() override; }; } diff --git a/include/QtTextReader.h b/include/QtTextReader.h index d226e920..2fd203ad 100644 --- a/include/QtTextReader.h +++ b/include/QtTextReader.h @@ -123,32 +123,32 @@ namespace openshot void SetTextBackgroundColor(std::string color); /// Close Reader - void Close(); + void Close() override; /// Get the cache object used by this reader (always returns NULL for this object) - openshot::CacheMemory* GetCache() { return NULL; }; + openshot::CacheMemory* GetCache() override { return NULL; }; /// Get an openshot::Frame object for a specific frame number of this reader. All numbers /// return the same Frame, since they all share the same image data. /// /// @returns The requested frame (containing the image) /// @param requested_frame The frame number that is requested. - std::shared_ptr GetFrame(int64_t requested_frame); + std::shared_ptr GetFrame(int64_t requested_frame) override; /// Determine if reader is open or closed - bool IsOpen() { return is_open; }; + bool IsOpen() override { return is_open; }; /// Return the type name of the class - std::string Name() { return "QtTextReader"; }; + std::string Name() override { return "QtTextReader"; }; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Open Reader - which is called by the constructor automatically - void Open(); + void Open() override; }; } diff --git a/include/TextReader.h b/include/TextReader.h index b6dbf5cd..b5488f5f 100644 --- a/include/TextReader.h +++ b/include/TextReader.h @@ -123,32 +123,32 @@ namespace openshot void SetTextBackgroundColor(std::string color); /// Close Reader - void Close(); + void Close() override; /// Get the cache object used by this reader (always returns NULL for this object) - openshot::CacheMemory* GetCache() { return NULL; }; + openshot::CacheMemory* GetCache() override { return NULL; }; /// Get an openshot::Frame object for a specific frame number of this reader. All numbers /// return the same Frame, since they all share the same image data. /// /// @returns The requested frame (containing the image) /// @param requested_frame The frame number that is requested. - std::shared_ptr GetFrame(int64_t requested_frame); + std::shared_ptr GetFrame(int64_t requested_frame) override; /// Determine if reader is open or closed - bool IsOpen() { return is_open; }; + bool IsOpen() override { return is_open; }; /// Return the type name of the class - std::string Name() { return "TextReader"; }; + std::string Name() override { return "TextReader"; }; /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value); ///< Load JSON string into this object + void SetJson(const std::string value) override; ///< Load JSON string into this object Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Open Reader - which is called by the constructor automatically - void Open(); + void Open() override; }; } diff --git a/include/Timeline.h b/include/Timeline.h index 56a89586..932b04ac 100644 --- a/include/Timeline.h +++ b/include/Timeline.h @@ -242,13 +242,13 @@ namespace openshot { std::list Clips() { return clips; }; /// Close the timeline reader (and any resources it was consuming) - void Close(); + void Close() override; /// Return the list of effects on the timeline std::list Effects() { return effects; }; /// Get the cache object used by this reader - CacheBase* GetCache() { return final_cache; }; + CacheBase* GetCache() override { return final_cache; }; /// Set the cache object used by this reader. You must now manage the lifecycle /// of this cache object though (Timeline will not delete it for you). @@ -258,7 +258,7 @@ namespace openshot { /// /// @returns The requested frame (containing the image) /// @param requested_frame The frame number that is requested. - std::shared_ptr GetFrame(int64_t requested_frame); + std::shared_ptr GetFrame(int64_t requested_frame) override; // Curves for the viewport Keyframe viewport_scale; ///MAX_WIDTH and Settings::Instance()->MAX_HEIGHT. @@ -291,7 +291,7 @@ namespace openshot { void ApplyJsonDiff(std::string value); /// Open the reader (and start consuming resources) - void Open(); + void Open() override; /// @brief Remove an openshot::Clip from the timeline /// @param clip Remove an openshot::Clip from the timeline. From ad3b1b46992757a878d85a56cf0304853dfd85c9 Mon Sep 17 00:00:00 2001 From: Frank Dana Date: Thu, 16 Apr 2020 19:36:52 -0400 Subject: [PATCH 29/79] Make debug handling match libopenshot-audio (#499) --- CMakeLists.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 124e9e5a..bb3fe8cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,6 +129,16 @@ if (ENABLE_COVERAGE) endif() add_feature_info("Coverage" ENABLE_COVERAGE "analyze test coverage and generate report") +# Juce requires either DEBUG or NDEBUG to be defined on MacOS. +# -DNDEBUG is set by cmake for all release configs, so add +# -DDEBUG for debug builds. We'll do this for all OSes, even +# though only MacOS requires it. +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") +# Make sure we've picked some build type, default to debug +if(NOT DEFINED CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "") + set(CMAKE_BUILD_TYPE "Debug") +endif() + ############## PROCESS src/ DIRECTORIES ############## add_subdirectory(src) From a972b2e67223dabf92564a42718ac2efdd6801c2 Mon Sep 17 00:00:00 2001 From: Frank Dana Date: Thu, 16 Apr 2020 20:04:13 -0400 Subject: [PATCH 30/79] INSTALL doc: Correct some CMake flags, reorder --- INSTALL.md | 105 ++++++++++++++++++++++++++--------------------------- 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 9d25603b..f2d0dda7 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -14,22 +14,7 @@ following sections, and follow the instructions. And keep in mind, that your com than the one used when writing these instructions. Your file paths and versions of applications might be slightly different, so keep an eye out for subtle file path differences in the commands you type. -## Build Tools - -CMake is the backbone of our build system. -It is a cross-platform build system, which checks for dependencies, -locates header files and libraries, and generates a build system in various formats. -We use CMake's Makefile generators to compile libopenshot and libopenshot-audio. - -CMake uses an out-of-source build concept. -This means that the build system, all temporary files, and all generated products are kept separate from the source code. -This includes Makefiles, object files, and even the final binaries. -While it is possible to build in-tree, we highly recommend you use a `/build/` sub-folder to compile each library. -This prevents the build process from cluttering up the source -code. -These instructions have only been tested with the GNU compiler suite (including MSYS2/MinGW for Windows), and the Clang compiler (including AppleClang on MacOS). - -### Dependencies +## Dependencies The following libraries are required to build libopenshot. Instructions on how to install these dependencies vary for each operating system. @@ -80,43 +65,6 @@ Libraries and Executables have been labeled in the list below to help distinguis * https://github.com/unittest-cpp/ **(Library)** * This library is used to execute unit tests for libopenshot. It contains many macros used to keep our unit testing code very clean and simple. - -### CMake Flags (Optional) -There are many different build flags that can be passed to cmake to adjust how libopenshot is compiled. Some of these flags might be required when compiling on certain OSes, just depending on how your build environment is setup. - -To add a build flag, follow this general syntax: - -```sh -$ cmake -DMAGICKCORE_HDRI_ENABLE=1 -DENABLE_TESTS=1 .. -``` - -Following are some of the flags you might need to set when generating your build system. - -##### Optional behavior: -* `-DENABLE_TESTS=0` (default: `ON`) -* `-DENABLE_COVERAGE=1` (default: `OFF`) -* `-DENABLE_DOCS=0` (default: `ON` if doxygen found) - -##### Compiler configuration: -* `-DCMAKE_BUILD_TYPE=Debug` (default: `Release`) -* `-DCMAKE_CXX_FLAGS="-Wall -Wextra"` (default: auto for build type) -* `-DCMAKE_CXX_COMPILER=/path/to/g++` -* `-DCMAKE_C_COMPILER=/path/to/gcc` (used by CMake for OS probes) - -##### Dependency configuration: -* `-DCMAKE_PREFIX_PATH=/extra/path/to/search/for/libraries/` -* `-DUSE_SYSTEM_JSONCPP=0` (default: auto if discovered) -* `-DImageMagick_FOUND=0` (default: auto if discovered) - -##### To compile bindings for a specific Python installation: -* `-DPYTHON_INCLUDE_DIR=/location/of/python/includes/` -* `-DPYTHON_LIBRARY=/location/of/libpython*.so` -* `-DPYTHON_FRAMEWORKS=/usr/local/Cellar/python3/3.3.2/Frameworks/Python.framework/` (MacOS only) - -##### Only used when building with ImageMagick enabled: -* `-DMAGICKCORE_HDRI_ENABLE=1` (default `0`) -* `-DMAGICKCORE_QUANTUM_DEPTH=8` (default `16`) - ## Obtaining Source Code The first step in installing libopenshot is to obtain the most recent source code. The source code is available on [GitHub](https://github.com/OpenShot/libopenshot). Use the following command to obtain the latest libopenshot source code. @@ -157,6 +105,57 @@ We use UnitTest++ macros to keep the test code simple and manageable. This folder contains code not written by the OpenShot team. For example, `jsoncpp`, an open-source JSON parser. +## Build Tools + +CMake is the backbone of our build system. +It is a cross-platform build system, which checks for dependencies, +locates header files and libraries, and generates a build system in various formats. +We use CMake's Makefile generators to compile libopenshot and libopenshot-audio. + +CMake uses an out-of-source build concept. +This means that the build system, all temporary files, and all generated products are kept separate from the source code. +This includes Makefiles, object files, and even the final binaries. +While it is possible to build in-tree, we highly recommend you use a `/build/` sub-folder to compile each library. +This prevents the build process from cluttering up the source +code. +These instructions have only been tested with the GNU compiler suite (including MSYS2/MinGW for Windows), and the Clang compiler (including AppleClang on MacOS). + +## CMake Flags (Optional) +There are many different build flags that can be passed to cmake to adjust how libopenshot is compiled. Some of these flags might be required when compiling on certain OSes, just depending on how your build environment is setup. + +To add a build flag, follow this general syntax: + +```sh +$ cmake -DMAGICKCORE_HDRI_ENABLE=1 -DENABLE_TESTS=1 .. +``` + +Following are some of the flags you might need to set when generating your build system. + +##### Optional behavior: +* `-DENABLE_TESTS=0` (default: `ON`) +* `-DENABLE_COVERAGE=1` (default: `OFF`) +* `-DENABLE_DOCS=0` (default: `ON` if doxygen found) + +##### Compiler configuration: +* `-DCMAKE_BUILD_TYPE=Release`, `-DCMAKE_BUILD_TYPE=Debug` (default: `Debug` if unset) +* `-DCMAKE_CXX_FLAGS="-Wall -Wextra"` (default: CMake builtin defaults for build type) +* `-DCMAKE_CXX_COMPILER=/path/to/g++`, `-DCMAKE_CXX_COMPILER=/path/to/clang++` +* `-DCMAKE_C_COMPILER=/path/to/gcc`, `-DCMAKE_CXX_COMPILER=/path/to/clang` (used by CMake for OS probes) + +##### Dependency configuration: +* `-DCMAKE_PREFIX_PATH=/extra/path/to/search/for/libraries/` +* `-DUSE_SYSTEM_JSONCPP=0` (default: auto if discovered) +* `-DImageMagick_FOUND=0` (default: auto if discovered) + +##### To compile bindings for a specific Python installation: +* `-DPYTHON_INCLUDE_DIR=/location/of/python/includes/` +* `-DPYTHON_LIBRARY=/location/of/libpython*.so` +* `-DPYTHON_FRAMEWORKS=/usr/local/Cellar/python3/3.3.2/Frameworks/Python.framework/` (MacOS only) + +##### Only used when building with ImageMagick enabled: +* `-DMAGICKCORE_HDRI_ENABLE=1` (default `0`) +* `-DMAGICKCORE_QUANTUM_DEPTH=8` (default `16`) + ## Linux Build Instructions (libopenshot-audio) To compile libopenshot-audio, we need to go through a few additional steps to manually build and install it. Launch a terminal and enter: From 9d261f656850f8f97bede9977e1a5cfce45275b5 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Fri, 17 Apr 2020 05:39:00 -0400 Subject: [PATCH 31/79] CMake: Rename, modernize Findjsoncpp.cmake - Rename to match package naming used elsewhere (official configs) - Add IMPORTED target creation to the Find module, along with version number detection - Switch to lowercase variable forms (e.g. jsoncpp_FOUND) --- cmake/Modules/FindJsonCpp.cmake | 64 ---------------- cmake/Modules/Findjsoncpp.cmake | 132 ++++++++++++++++++++++++++++++++ src/CMakeLists.txt | 25 +++--- 3 files changed, 142 insertions(+), 79 deletions(-) delete mode 100644 cmake/Modules/FindJsonCpp.cmake create mode 100644 cmake/Modules/Findjsoncpp.cmake diff --git a/cmake/Modules/FindJsonCpp.cmake b/cmake/Modules/FindJsonCpp.cmake deleted file mode 100644 index 6ce9887e..00000000 --- a/cmake/Modules/FindJsonCpp.cmake +++ /dev/null @@ -1,64 +0,0 @@ -# - Try to find JsonCpp -# -# Once done this will define -# JSONCPP_INCLUDE_DIRS, where to find header, etc. -# JSONCPP_LIBRARIES, the libraries needed to use jsoncpp. -# JSONCPP_FOUND, If false, do not try to use jsoncpp. -# JSONCPP_INCLUDE_PREFIX, include prefix for jsoncpp - -# try to detect using pkg-config, and use as hints later -find_package(PkgConfig) -pkg_check_modules(PC_jsoncpp QUIET jsoncpp) - -find_path( - JSONCPP_INCLUDE_DIR - NAMES json/json.h - HINTS ${PC_jsoncpp_INCLUDE_DIRS} - DOC "jsoncpp include dir" -) - -find_library( - JSONCPP_LIBRARY - NAMES jsoncpp - HINTS ${PC_jsoncpp_LIBRARY_DIR} - DOC "jsoncpp library" -) - -set(JSONCPP_INCLUDE_DIRS ${JSONCPP_INCLUDE_DIR}) -set(JSONCPP_LIBRARIES ${JSONCPP_LIBRARY}) - -# debug library on windows -# same naming convention as in qt (appending debug library with d) -# boost is using the same "hack" as us with "optimized" and "debug" -if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - find_library( - JSONCPP_LIBRARY_DEBUG - NAMES jsoncppd - HINTS ${PC_jsoncpp_LIBDIR} ${PC_jsoncpp_LIBRARY_DIRS} - DOC "jsoncpp debug library" - ) - - set(JSONCPP_LIBRARIES optimized ${JSONCPP_LIBRARIES} debug ${JSONCPP_LIBRARY_DEBUG}) - -endif() - -# find JSONCPP_INCLUDE_PREFIX -find_path( - JSONCPP_INCLUDE_PREFIX - NAMES json.h - PATH_SUFFIXES jsoncpp/json json -) - -if (${JSONCPP_INCLUDE_PREFIX} MATCHES "jsoncpp") - set(JSONCPP_INCLUDE_PREFIX "jsoncpp/json") -else() - set(JSONCPP_INCLUDE_PREFIX "json") -endif() - -# handle the QUIETLY and REQUIRED arguments and set JSONCPP_FOUND to TRUE -# if all listed variables are TRUE, hide their existence from configuration view -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(jsoncpp DEFAULT_MSG - JSONCPP_INCLUDE_DIR JSONCPP_LIBRARY) -mark_as_advanced (JSONCPP_INCLUDE_DIR JSONCPP_LIBRARY) - diff --git a/cmake/Modules/Findjsoncpp.cmake b/cmake/Modules/Findjsoncpp.cmake new file mode 100644 index 00000000..bd30fea7 --- /dev/null +++ b/cmake/Modules/Findjsoncpp.cmake @@ -0,0 +1,132 @@ +# - Try to find jsoncpp +# +# IMPORTED target +# This module will create the target jsoncpp_lib if jsoncpp is found +# +# Legacy Config Variables +# The following variables are defined for backwards compatibility: +# +# JSONCPP_INCLUDE_DIRS, where to find header, etc. +# JSONCPP_LIBRARIES, the libraries needed to use jsoncpp. +# JSONCPP_FOUND, If false, do not try to use jsoncpp. +# JSONCPP_INCLUDE_PREFIX, include prefix for jsoncpp + +# try to detect using pkg-config, and use as hints later +find_package(PkgConfig) +pkg_check_modules(PC_jsoncpp QUIET jsoncpp) + +find_path( + jsoncpp_INCLUDE_DIR + NAMES json/json.h + HINTS ${PC_jsoncpp_INCLUDE_DIRS} + DOC "jsoncpp include dir" +) + +find_library( + jsoncpp_LIBRARY + NAMES jsoncpp + HINTS ${PC_jsoncpp_LIBRARY_DIR} + DOC "jsoncpp library" +) + +set(jsoncpp_INCLUDE_DIRS ${jsoncpp_INCLUDE_DIR}) +set(jsoncpp_LIBRARIES ${jsoncpp_LIBRARY}) + +if (jsoncpp_INCLUDE_DIRS AND jsoncpp_LIBRARIES) + set(jsoncpp_FOUND TRUE) +endif() + +# Create the IMPORTED target +if (jsoncpp_FOUND AND NOT TARGET jsoncpp_lib) + add_library(jsoncpp_lib UNKNOWN IMPORTED) + + set_property(TARGET jsoncpp_lib PROPERTY + INTERFACE_INCLUDE_DIRECTORIES ${JSONCPP_INCLUDE_DIR}) + + set_property(TARGET jsoncpp_lib PROPERTY + IMPORTED_LOCATION ${JSONCPP_LIBRARY}) +endif() + +# debug library on windows +# same naming convention as in qt (appending debug library with d) +# boost is using the same "hack" as us with "optimized" and "debug" +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + find_library( + jsoncpp_LIBRARY_DEBUG + NAMES jsoncppd + HINTS ${PC_jsoncpp_LIBDIR} ${PC_jsoncpp_LIBRARY_DIRS} + DOC "jsoncpp debug library" + ) + + set(jsoncpp_LIBRARIES optimized ${jsoncpp_LIBRARIES} debug ${jsoncpp_LIBRARY_DEBUG}) + + # Add Debug location to IMPORTED target + if(TARGET jsoncpp_lib) + set_property(TARGET jsoncpp_lib APPEND PROPERTY + IMPORTED_LOCATION_Debug ${JSONCPP_LIBRARY_DEBUG}) + endif() +endif() + +# find JSONCPP_INCLUDE_PREFIX +find_path( + jsoncpp_INCLUDE_PREFIX + NAMES json.h + PATH_SUFFIXES jsoncpp/json json +) + +if (${jsoncpp_INCLUDE_PREFIX} MATCHES "jsoncpp") + set(jsoncpp_INCLUDE_PREFIX "jsoncpp/json") +else() + set(jsoncpp_INCLUDE_PREFIX "json") +endif() + +# Check the available version +set(_version_file "${jsoncpp_INCLUDE_DIR}/${jsoncpp_INCLUDE_PREFIX}/version.h") +if (jsoncpp_INCLUDE_DIR AND EXISTS ${_version_file}) + file(STRINGS "${_version_file}" jsoncpp_version_str + REGEX "JSONCPP_VERSION_STRING.*\"[^\"]+\"") + if(jsoncpp_version_str MATCHES "JSONCPP_VERSION_STRING.*\"([^\"]+)\"") + set(jsoncpp_VERSION_STRING ${CMAKE_MATCH_1}) + endif() + unset(jsoncpp_version_str) + string(REGEX REPLACE "^([0-9]+\.[0-9]+\.[0-9]+).*$" "\\1" + jsoncpp_VERSION "${jsoncpp_VERSION_STRING}") +endif() + +if(NOT jsoncpp_VERSION) + unset(jsoncpp_VERSION) + unset(jsoncpp_VERSION_STRING) +endif() + +# Check version requirement, if specified +if(jsoncpp_FIND_VERSION AND jsoncpp_VERSION) + if("${jsoncpp_FIND_VERSION}" STREQUAL "${jsoncpp_VERSION}") + set(jsoncpp_VERSION_EXACT TRUE) + endif() + if("${jsoncpp_FIND_VERSION}" VERSION_GREATER "${jsoncpp_VERSION}") + set(jsoncpp_VERSION_COMPATIBLE FALSE) + else() + set(jsoncpp_VERSION_COMPATIBLE TRUE) + endif() +endif() + +# Legacy +set(JSONCPP_LIBRARY ${jsoncpp_LIBRARY}) +set(JSONCPP_LIBRARIES ${jsoncpp_LIBRARIES}) +set(JSONCPP_INCLUDE_DIR ${jsoncpp_INCLUDE_DIR}) +set(JSONCPP_INCLUDE_DIRS ${jsoncpp_INCLUDE_DIRS}) +set(JSONCPP_INCLUDE_PREFIX ${jsoncpp_INCLUDE_PREFIX}) +set(JSONCPP_VERSION ${jsoncpp_VERSION}) +set(JSONCPP_FOUND ${jsoncpp_FOUND}) + +# handle the QUIETLY and REQUIRED arguments and set JSONCPP_FOUND to TRUE +# if all listed variables are TRUE, hide their existence from configuration view +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(jsoncpp + REQUIRED_VARS + jsoncpp_INCLUDE_DIR + jsoncpp_LIBRARY + VERSION_VAR + jsoncpp_VERSION +) +mark_as_advanced (jsoncpp_INCLUDE_DIR jsoncpp_LIBRARY) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a57780b0..17b73863 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -248,34 +248,29 @@ target_include_directories(openshot ################### JSONCPP ##################### # Include jsoncpp headers (needed for JSON parsing) if (USE_SYSTEM_JSONCPP) - message(STATUS "Looking for system JsonCpp") - find_package(JsonCpp) - if (JSONCPP_FOUND AND NOT TARGET jsoncpp_lib) - # Create the expected target, for older installs that don't - add_library(jsoncpp_lib INTERFACE) - target_include_directories(jsoncpp_lib INTERFACE - ${JSONCPP_INCLUDE_DIRS}) - target_link_libraries(jsoncpp_lib INTERFACE ${JSONCPP_LIBRARY}) - endif () + message(STATUS "Looking for system jsoncpp") + # Either an installed config or our find module will + # create the IMPORTED target jsoncpp_lib if successful + find_package(jsoncpp) endif () -if (NOT JSONCPP_FOUND AND NOT DISABLE_BUNDLED_JSONCPP) - message(STATUS "Using embedded JsonCpp (not found or USE_SYSTEM_JSONCPP disabled)") +if (NOT jsoncpp_FOUND AND NOT DISABLE_BUNDLED_JSONCPP) + message(STATUS "Using embedded jsoncpp (not found or USE_SYSTEM_JSONCPP disabled)") if (NOT TARGET jsoncpp_lib) add_library(jsoncpp_lib INTERFACE) target_include_directories(jsoncpp_lib INTERFACE "${PROJECT_SOURCE_DIR}/thirdparty/jsoncpp") target_sources(jsoncpp_lib INTERFACE "${PROJECT_SOURCE_DIR}/thirdparty/jsoncpp/jsoncpp.cpp") # Because this satisfies the requirement, an installed JsonCpp is optional - set_package_properties(JsonCpp PROPERTIES TYPE OPTIONAL) + set_package_properties(jsoncpp PROPERTIES TYPE OPTIONAL) endif () - add_feature_info("JsonCpp (embedded)" TRUE "JsonCpp will be compiled from the bundled sources") + add_feature_info("jsoncpp (embedded)" TRUE "jsoncpp will be compiled from the bundled sources") endif () -if (JSONCPP_FOUND) +if (jsoncpp_FOUND) # JsonCpp is actually required, even though we probe for it optionally # (This tells feature_summary() to bail if it's not found, later) - set_package_properties(JsonCpp PROPERTIES TYPE REQUIRED) + set_package_properties(jsoncpp PROPERTIES TYPE REQUIRED) endif () # If we found any usable JsonCpp, use it. Otherwise, bail. From b766baf752cdba3df2acaadca511d8e008b4eac0 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Fri, 17 Apr 2020 09:59:41 -0400 Subject: [PATCH 32/79] Findjsoncpp: Fix target --- cmake/Modules/Findjsoncpp.cmake | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cmake/Modules/Findjsoncpp.cmake b/cmake/Modules/Findjsoncpp.cmake index bd30fea7..75f7db4a 100644 --- a/cmake/Modules/Findjsoncpp.cmake +++ b/cmake/Modules/Findjsoncpp.cmake @@ -41,10 +41,10 @@ if (jsoncpp_FOUND AND NOT TARGET jsoncpp_lib) add_library(jsoncpp_lib UNKNOWN IMPORTED) set_property(TARGET jsoncpp_lib PROPERTY - INTERFACE_INCLUDE_DIRECTORIES ${JSONCPP_INCLUDE_DIR}) + INTERFACE_INCLUDE_DIRECTORIES ${jsoncpp_INCLUDE_DIR}) set_property(TARGET jsoncpp_lib PROPERTY - IMPORTED_LOCATION ${JSONCPP_LIBRARY}) + IMPORTED_LOCATION ${jsoncpp_LIBRARY}) endif() # debug library on windows @@ -63,14 +63,15 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # Add Debug location to IMPORTED target if(TARGET jsoncpp_lib) set_property(TARGET jsoncpp_lib APPEND PROPERTY - IMPORTED_LOCATION_Debug ${JSONCPP_LIBRARY_DEBUG}) + IMPORTED_LOCATION_Debug ${jsoncpp_LIBRARY_DEBUG}) endif() endif() -# find JSONCPP_INCLUDE_PREFIX +# find jsoncpp_INCLUDE_PREFIX find_path( jsoncpp_INCLUDE_PREFIX NAMES json.h + HINTS ${jsoncpp_INCLUDE_DIR} PATH_SUFFIXES jsoncpp/json json ) @@ -119,7 +120,7 @@ set(JSONCPP_INCLUDE_PREFIX ${jsoncpp_INCLUDE_PREFIX}) set(JSONCPP_VERSION ${jsoncpp_VERSION}) set(JSONCPP_FOUND ${jsoncpp_FOUND}) -# handle the QUIETLY and REQUIRED arguments and set JSONCPP_FOUND to TRUE +# handle the QUIETLY and REQUIRED arguments and set jsoncpp_FOUND to TRUE # if all listed variables are TRUE, hide their existence from configuration view include(FindPackageHandleStandardArgs) find_package_handle_standard_args(jsoncpp From 9796b82857bfdadeee0fe4bc52b048644eb5d1b0 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Wed, 22 Apr 2020 01:35:09 -0400 Subject: [PATCH 33/79] Travis: Fix package list syntax, contents - Get rid of two-stage definition of apt.packages list, which was never necessary anyway. - Remove deprecated libavresample from package set for FFmpeg 4 --- .travis.yml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index c93822fc..24e772af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,18 +11,12 @@ addons: apt: packages: &p_common # Packages common to all Ubuntu builds - cmake - - swig - libopenshot-audio-dev - libmagick++-dev - libunittest++-dev - libzmq3-dev - qtbase5-dev - qtmultimedia5-dev - - doxygen - - graphviz - - curl - packages: &ff_common # Common set of FFmpeg packages - - *p_common - libfdk-aac-dev - libavcodec-dev - libavformat-dev @@ -31,8 +25,11 @@ addons: - libavfilter-dev - libswscale-dev - libpostproc-dev - - libavresample-dev - libswresample-dev + - swig + - doxygen + - graphviz + - curl jobs: include: @@ -50,8 +47,9 @@ jobs: - sourceline: 'ppa:openshot.developers/libopenshot-daily' - sourceline: 'ppa:beineri/opt-qt-5.12.3-bionic' packages: - - *ff_common + - *p_common - qt5-default + - libavresample-dev - libjsoncpp-dev - lcov - binutils-common # For c++filt @@ -70,7 +68,7 @@ jobs: - sourceline: 'ppa:beineri/opt-qt-5.12.3-bionic' - sourceline: 'ppa:jonathonf/ffmpeg-4' packages: - - *ff_common + - *p_common - qt5-default - libjsoncpp-dev - libavcodec58 @@ -80,7 +78,6 @@ jobs: - libavfilter7 - libswscale5 - libpostproc55 - - libavresample4 - libswresample3 - name: "FFmpeg 3.4 Clang (Ubuntu 18.04 Bionic)" @@ -97,8 +94,9 @@ jobs: - sourceline: 'ppa:openshot.developers/libopenshot-daily' - sourceline: 'ppa:beineri/opt-qt-5.12.3-bionic' packages: - - *ff_common + - *p_common - qt5-default + - libavresample-dev - libomp-dev - name: "FFmpeg 3.2 GCC (Ubuntu 16.04 Xenial)" @@ -115,7 +113,8 @@ jobs: - sourceline: 'ppa:beineri/opt-qt-5.10.0-xenial' - sourceline: 'ppa:jon-hedgerows/ffmpeg-backports' packages: - - *ff_common + - *p_common + - libavresample-dev - libavcodec57 - libavdevice57 - libavfilter6 @@ -139,7 +138,8 @@ jobs: - sourceline: 'ppa:openshot.developers/libopenshot-daily' - sourceline: 'ppa:beineri/opt-qt-5.10.0-xenial' packages: - - *ff_common + - *p_common + - libavresample-dev script: - mkdir -p build; cd build; From f36bb334e27dd6592b40e75e43fe6edfe1e93ad0 Mon Sep 17 00:00:00 2001 From: Frank Dana Date: Wed, 22 Apr 2020 02:01:01 -0400 Subject: [PATCH 34/79] Exceptions: Rename BaseException, for python (#497) BaseException is a python standard library exception class, so it's not a great idea to redefine that name in our bindings. Renamed to ExceptionBase, which is more in keeping with our class naming system anyway. --- include/Exceptions.h | 94 ++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/include/Exceptions.h b/include/Exceptions.h index 28942050..f23cda7a 100644 --- a/include/Exceptions.h +++ b/include/Exceptions.h @@ -38,16 +38,16 @@ namespace openshot { /** * @brief Base exception class with a custom message variable. * - * A custom error message field has been added to the std::exception base class. All - * OpenShot exception classes inherit from this class. + * A std::exception-derived exception class with custom message. + * All OpenShot exception classes inherit from this class. */ - class BaseException : public std::exception //: public exception + class ExceptionBase : public std::exception //: public exception { protected: std::string m_message; public: - BaseException(std::string message) : m_message(message) { } - virtual ~BaseException() noexcept {} + ExceptionBase(std::string message) : m_message(message) { } + virtual ~ExceptionBase() noexcept {} virtual const char* what() const noexcept { // return custom message return m_message.c_str(); @@ -55,7 +55,7 @@ namespace openshot { }; /// Exception when a required chunk is missing - class ChunkNotFound : public BaseException + class ChunkNotFound : public ExceptionBase { public: int64_t frame_number; @@ -70,13 +70,13 @@ namespace openshot { * @param chunk_frame The chunk frame */ ChunkNotFound(std::string message, int64_t frame_number, int64_t chunk_number, int64_t chunk_frame) - : BaseException(message), frame_number(frame_number), chunk_number(chunk_number), chunk_frame(chunk_frame) { } + : ExceptionBase(message), frame_number(frame_number), chunk_number(chunk_number), chunk_frame(chunk_frame) { } virtual ~ChunkNotFound() noexcept {} }; /// Exception when accessing a blackmagic decklink card - class DecklinkError : public BaseException + class DecklinkError : public ExceptionBase { public: /** @@ -85,12 +85,12 @@ namespace openshot { * @param message A message to accompany the exception */ DecklinkError(std::string message) - : BaseException(message) { } + : ExceptionBase(message) { } virtual ~DecklinkError() noexcept {} }; /// Exception when decoding audio packet - class ErrorDecodingAudio : public BaseException + class ErrorDecodingAudio : public ExceptionBase { public: int64_t frame_number; @@ -101,12 +101,12 @@ namespace openshot { * @param frame_number The frame number being processed */ ErrorDecodingAudio(std::string message, int64_t frame_number) - : BaseException(message), frame_number(frame_number) { } + : ExceptionBase(message), frame_number(frame_number) { } virtual ~ErrorDecodingAudio() noexcept {} }; /// Exception when encoding audio packet - class ErrorEncodingAudio : public BaseException + class ErrorEncodingAudio : public ExceptionBase { public: int64_t frame_number; @@ -117,12 +117,12 @@ namespace openshot { * @param frame_number The frame number being processed */ ErrorEncodingAudio(std::string message, int64_t frame_number) - : BaseException(message), frame_number(frame_number) { } + : ExceptionBase(message), frame_number(frame_number) { } virtual ~ErrorEncodingAudio() noexcept {} }; /// Exception when encoding audio packet - class ErrorEncodingVideo : public BaseException + class ErrorEncodingVideo : public ExceptionBase { public: int64_t frame_number; @@ -133,12 +133,12 @@ namespace openshot { * @param frame_number The frame number being processed */ ErrorEncodingVideo(std::string message, int64_t frame_number) - : BaseException(message), frame_number(frame_number) { } + : ExceptionBase(message), frame_number(frame_number) { } virtual ~ErrorEncodingVideo() noexcept {} }; /// Exception when an invalid # of audio channels are detected - class InvalidChannels : public BaseException + class InvalidChannels : public ExceptionBase { public: std::string file_path; @@ -149,12 +149,12 @@ namespace openshot { * @param file_path (optional) The input file being processed */ InvalidChannels(std::string message, std::string file_path="") - : BaseException(message), file_path(file_path) { } + : ExceptionBase(message), file_path(file_path) { } virtual ~InvalidChannels() noexcept {} }; /// Exception when no valid codec is found for a file - class InvalidCodec : public BaseException + class InvalidCodec : public ExceptionBase { public: std::string file_path; @@ -165,12 +165,12 @@ namespace openshot { * @param file_path (optional) The input file being processed */ InvalidCodec(std::string message, std::string file_path="") - : BaseException(message), file_path(file_path) { } + : ExceptionBase(message), file_path(file_path) { } virtual ~InvalidCodec() noexcept {} }; /// Exception for files that can not be found or opened - class InvalidFile : public BaseException + class InvalidFile : public ExceptionBase { public: std::string file_path; @@ -181,12 +181,12 @@ namespace openshot { * @param file_path The input file being processed */ InvalidFile(std::string message, std::string file_path) - : BaseException(message), file_path(file_path) { } + : ExceptionBase(message), file_path(file_path) { } virtual ~InvalidFile() noexcept {} }; /// Exception when no valid format is found for a file - class InvalidFormat : public BaseException + class InvalidFormat : public ExceptionBase { public: std::string file_path; @@ -197,12 +197,12 @@ namespace openshot { * @param file_path (optional) The input file being processed */ InvalidFormat(std::string message, std::string file_path="") - : BaseException(message), file_path(file_path) { } + : ExceptionBase(message), file_path(file_path) { } virtual ~InvalidFormat() noexcept {} }; /// Exception for invalid JSON - class InvalidJSON : public BaseException + class InvalidJSON : public ExceptionBase { public: std::string file_path; @@ -213,12 +213,12 @@ namespace openshot { * @param file_path (optional) The input file being processed */ InvalidJSON(std::string message, std::string file_path="") - : BaseException(message), file_path(file_path) { } + : ExceptionBase(message), file_path(file_path) { } virtual ~InvalidJSON() noexcept {} }; /// Exception when invalid encoding options are used - class InvalidOptions : public BaseException + class InvalidOptions : public ExceptionBase { public: std::string file_path; @@ -229,12 +229,12 @@ namespace openshot { * @param file_path (optional) The input file being processed */ InvalidOptions(std::string message, std::string file_path="") - : BaseException(message), file_path(file_path) { } + : ExceptionBase(message), file_path(file_path) { } virtual ~InvalidOptions() noexcept {} }; /// Exception when invalid sample rate is detected during encoding - class InvalidSampleRate : public BaseException + class InvalidSampleRate : public ExceptionBase { public: std::string file_path; @@ -245,12 +245,12 @@ namespace openshot { * @param file_path (optional) The input file being processed */ InvalidSampleRate(std::string message, std::string file_path="") - : BaseException(message), file_path(file_path) { } + : ExceptionBase(message), file_path(file_path) { } virtual ~InvalidSampleRate() noexcept {} }; /// Exception for missing JSON Change key - class InvalidJSONKey : public BaseException + class InvalidJSONKey : public ExceptionBase { public: std::string json; @@ -261,12 +261,12 @@ namespace openshot { * @param json The json data being processed */ InvalidJSONKey(std::string message, std::string json) - : BaseException(message), json(json) { } + : ExceptionBase(message), json(json) { } virtual ~InvalidJSONKey() noexcept {} }; /// Exception when no streams are found in the file - class NoStreamsFound : public BaseException + class NoStreamsFound : public ExceptionBase { public: std::string file_path; @@ -277,12 +277,12 @@ namespace openshot { * @param file_path (optional) The input file being processed */ NoStreamsFound(std::string message, std::string file_path="") - : BaseException(message), file_path(file_path) { } + : ExceptionBase(message), file_path(file_path) { } virtual ~NoStreamsFound() noexcept {} }; /// Exception for frames that are out of bounds. - class OutOfBoundsFrame : public BaseException + class OutOfBoundsFrame : public ExceptionBase { public: int64_t FrameRequested; @@ -295,12 +295,12 @@ namespace openshot { * @param max_frames The maximum available frame number */ OutOfBoundsFrame(std::string message, int64_t frame_requested, int64_t max_frames) - : BaseException(message), FrameRequested(frame_requested), MaxFrames(max_frames) { } + : ExceptionBase(message), FrameRequested(frame_requested), MaxFrames(max_frames) { } virtual ~OutOfBoundsFrame() noexcept {} }; /// Exception for an out of bounds key-frame point. - class OutOfBoundsPoint : public BaseException + class OutOfBoundsPoint : public ExceptionBase { public: int PointRequested; @@ -313,12 +313,12 @@ namespace openshot { * @param max_points The maximum available point value */ OutOfBoundsPoint(std::string message, int point_requested, int max_points) - : BaseException(message), PointRequested(point_requested), MaxPoints(max_points) { } + : ExceptionBase(message), PointRequested(point_requested), MaxPoints(max_points) { } virtual ~OutOfBoundsPoint() noexcept {} }; /// Exception when memory could not be allocated - class OutOfMemory : public BaseException + class OutOfMemory : public ExceptionBase { public: std::string file_path; @@ -329,12 +329,12 @@ namespace openshot { * @param file_path (optional) The input file being processed */ OutOfMemory(std::string message, std::string file_path="") - : BaseException(message), file_path(file_path) { } + : ExceptionBase(message), file_path(file_path) { } virtual ~OutOfMemory() noexcept {} }; /// Exception when a reader is closed, and a frame is requested - class ReaderClosed : public BaseException + class ReaderClosed : public ExceptionBase { public: std::string file_path; @@ -345,12 +345,12 @@ namespace openshot { * @param file_path (optional) The input file being processed */ ReaderClosed(std::string message, std::string file_path="") - : BaseException(message), file_path(file_path) { } + : ExceptionBase(message), file_path(file_path) { } virtual ~ReaderClosed() noexcept {} }; /// Exception when resample fails - class ResampleError : public BaseException + class ResampleError : public ExceptionBase { public: std::string file_path; @@ -361,12 +361,12 @@ namespace openshot { * @param file_path (optional) The input file being processed */ ResampleError(std::string message, std::string file_path="") - : BaseException(message), file_path(file_path) { } + : ExceptionBase(message), file_path(file_path) { } virtual ~ResampleError() noexcept {} }; /// Exception when too many seek attempts happen - class TooManySeeks : public BaseException + class TooManySeeks : public ExceptionBase { public: std::string file_path; @@ -377,12 +377,12 @@ namespace openshot { * @param file_path (optional) The input file being processed */ TooManySeeks(std::string message, std::string file_path="") - : BaseException(message), file_path(file_path) { } + : ExceptionBase(message), file_path(file_path) { } virtual ~TooManySeeks() noexcept {} }; /// Exception when a writer is closed, and a frame is requested - class WriterClosed : public BaseException + class WriterClosed : public ExceptionBase { public: std::string file_path; @@ -393,7 +393,7 @@ namespace openshot { * @param file_path (optional) The output file being written */ WriterClosed(std::string message, std::string file_path="") - : BaseException(message), file_path(file_path) { } + : ExceptionBase(message), file_path(file_path) { } virtual ~WriterClosed() noexcept {} }; } From 6336f30ee3ea24ccc8fb85c26e8a3d2135cb4545 Mon Sep 17 00:00:00 2001 From: Frank Dana Date: Wed, 22 Apr 2020 02:02:55 -0400 Subject: [PATCH 35/79] Various: Remove unused variables (#467) Several data members and local variables were flagged by static analysis tools as never being used anywhere in the code. --- include/AudioBufferSource.h | 1 - include/AudioReaderSource.h | 1 - include/Clip.h | 1 - include/FFmpegWriter.h | 1 - include/ImageWriter.h | 1 - src/AudioBufferSource.cpp | 2 +- src/AudioReaderSource.cpp | 2 +- src/CacheDisk.cpp | 2 +- src/Clip.cpp | 12 +++--------- src/FFmpegReader.cpp | 5 +---- src/FFmpegWriter.cpp | 3 +-- src/ImageWriter.cpp | 2 +- src/Timeline.cpp | 3 --- src/{bindings/ruby/test.rb => examples/Example.rb} | 0 14 files changed, 9 insertions(+), 27 deletions(-) rename src/{bindings/ruby/test.rb => examples/Example.rb} (100%) diff --git a/include/AudioBufferSource.h b/include/AudioBufferSource.h index 3a17feb3..ae5ce014 100644 --- a/include/AudioBufferSource.h +++ b/include/AudioBufferSource.h @@ -48,7 +48,6 @@ namespace openshot { private: int position; - int start; bool repeat; juce::AudioSampleBuffer *buffer; diff --git a/include/AudioReaderSource.h b/include/AudioReaderSource.h index c4e2d248..d049e1b3 100644 --- a/include/AudioReaderSource.h +++ b/include/AudioReaderSource.h @@ -54,7 +54,6 @@ namespace openshot int speed; /// The speed and direction to playback a reader (1=normal, 2=fast, 3=faster, -1=rewind, etc...) ReaderBase *reader; /// The reader to pull samples from - int64_t original_frame_number; /// The current frame to read from int64_t frame_number; /// The current frame number std::shared_ptr frame; /// The current frame object that is being read int64_t frame_position; /// The position of the current frame's buffer diff --git a/include/Clip.h b/include/Clip.h index 1f4cd385..e153acb4 100644 --- a/include/Clip.h +++ b/include/Clip.h @@ -103,7 +103,6 @@ namespace openshot { // Audio resampler (if time mapping) openshot::AudioResampler *resampler; - juce::AudioSampleBuffer *audio_cache; // File Reader object openshot::ReaderBase* reader; diff --git a/include/FFmpegWriter.h b/include/FFmpegWriter.h index 1dfb21a9..37fa22dc 100644 --- a/include/FFmpegWriter.h +++ b/include/FFmpegWriter.h @@ -167,7 +167,6 @@ namespace openshot { AVCodecContext *video_codec; AVCodecContext *audio_codec; SwsContext *img_convert_ctx; - double audio_pts, video_pts; int16_t *samples; uint8_t *audio_outbuf; uint8_t *audio_encoder_buffer; diff --git a/include/ImageWriter.h b/include/ImageWriter.h index 87e8a9a9..e483cb10 100644 --- a/include/ImageWriter.h +++ b/include/ImageWriter.h @@ -88,7 +88,6 @@ namespace openshot private: std::string path; int cache_size; - bool is_writing; bool is_open; int64_t write_video_count; std::vector frames; diff --git a/src/AudioBufferSource.cpp b/src/AudioBufferSource.cpp index 2f3d14ca..69e5713a 100644 --- a/src/AudioBufferSource.cpp +++ b/src/AudioBufferSource.cpp @@ -35,7 +35,7 @@ using namespace openshot; // Default constructor AudioBufferSource::AudioBufferSource(juce::AudioSampleBuffer *audio_buffer) - : position(0), start(0), repeat(false), buffer(audio_buffer) + : position(0), repeat(false), buffer(audio_buffer) { } // Destructor diff --git a/src/AudioReaderSource.cpp b/src/AudioReaderSource.cpp index c96d0bcc..999d109d 100644 --- a/src/AudioReaderSource.cpp +++ b/src/AudioReaderSource.cpp @@ -35,7 +35,7 @@ using namespace openshot; // Constructor that reads samples from a reader AudioReaderSource::AudioReaderSource(ReaderBase *audio_reader, int64_t starting_frame_number, int buffer_size) - : reader(audio_reader), frame_number(starting_frame_number), original_frame_number(starting_frame_number), + : reader(audio_reader), frame_number(starting_frame_number), size(buffer_size), position(0), frame_position(0), estimated_frame(0), speed(1) { // Initialize an audio buffer (based on reader) diff --git a/src/CacheDisk.cpp b/src/CacheDisk.cpp index 9f67ce99..bb2e12c4 100644 --- a/src/CacheDisk.cpp +++ b/src/CacheDisk.cpp @@ -228,7 +228,7 @@ std::shared_ptr CacheDisk::GetFrame(int64_t frame_number) // Load image file std::shared_ptr image = std::shared_ptr(new QImage()); - bool success = image->load(QString::fromStdString(frame_path.toStdString())); + image->load(frame_path); // Set pixel formatimage-> image = std::shared_ptr(new QImage(image->convertToFormat(QImage::Format_RGBA8888))); diff --git a/src/Clip.cpp b/src/Clip.cpp index 1968bb3b..39aad35d 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -132,14 +132,14 @@ void Clip::init_reader_rotation() { } // Default Constructor for a clip -Clip::Clip() : resampler(NULL), audio_cache(NULL), reader(NULL), allocated_reader(NULL) +Clip::Clip() : resampler(NULL), reader(NULL), allocated_reader(NULL) { // Init all default settings init_settings(); } // Constructor with reader -Clip::Clip(ReaderBase* new_reader) : resampler(NULL), audio_cache(NULL), reader(new_reader), allocated_reader(NULL) +Clip::Clip(ReaderBase* new_reader) : resampler(NULL), reader(new_reader), allocated_reader(NULL) { // Init all default settings init_settings(); @@ -153,7 +153,7 @@ Clip::Clip(ReaderBase* new_reader) : resampler(NULL), audio_cache(NULL), reader( } // Constructor with filepath -Clip::Clip(std::string path) : resampler(NULL), audio_cache(NULL), reader(NULL), allocated_reader(NULL) +Clip::Clip(std::string path) : resampler(NULL), reader(NULL), allocated_reader(NULL) { // Init all default settings init_settings(); @@ -422,7 +422,6 @@ void Clip::get_time_mapped_frame(std::shared_ptr frame, int64_t frame_num int delta = int(round(time.GetDelta(frame_number))); // Init audio vars - int sample_rate = reader->info.sample_rate; int channels = reader->info.channels; int number_of_samples = GetOrCreateFrame(new_frame_number)->GetAudioSamplesCount(); @@ -433,7 +432,6 @@ void Clip::get_time_mapped_frame(std::shared_ptr frame, int64_t frame_num // SLOWING DOWN AUDIO // Resample data, and return new buffer pointer juce::AudioSampleBuffer *resampled_buffer = NULL; - int resampled_buffer_size = 0; // SLOW DOWN audio (split audio) samples = new juce::AudioSampleBuffer(channels, number_of_samples); @@ -455,9 +453,6 @@ void Clip::get_time_mapped_frame(std::shared_ptr frame, int64_t frame_num // Resample the data (since it's the 1st slice) resampled_buffer = resampler->GetResampledBuffer(); - // Get the length of the resampled buffer (if one exists) - resampled_buffer_size = resampled_buffer->getNumSamples(); - // Just take the samples we need for the requested frame int start = (number_of_samples * (time.GetRepeatFraction(frame_number).num - 1)); if (start > 0) @@ -567,7 +562,6 @@ void Clip::get_time_mapped_frame(std::shared_ptr frame, int64_t frame_num // Resample data, and return new buffer pointer juce::AudioSampleBuffer *buffer = resampler->GetResampledBuffer(); - int resampled_buffer_size = buffer->getNumSamples(); // Add the newly resized audio samples to the current frame for (int channel = 0; channel < channels; channel++) diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index 550648a1..c8ce141f 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -1426,8 +1426,6 @@ void FFmpegReader::ProcessAudioPacket(int64_t requested_frame, int64_t target_fr int packet_samples = 0; int data_size = 0; - // re-initialize buffer size (it gets changed in the avcodec_decode_audio2 method call) - int buf_size = AVCODEC_MAX_AUDIO_FRAME_SIZE + MY_INPUT_BUFFER_PADDING_SIZE; #pragma omp critical (ProcessAudioPacket) { #if IS_FFMPEG_3_2 @@ -1465,7 +1463,6 @@ void FFmpegReader::ProcessAudioPacket(int64_t requested_frame, int64_t target_fr if (frame_finished) { // determine how many samples were decoded - int planar = av_sample_fmt_is_planar((AVSampleFormat) AV_GET_CODEC_PIXEL_FORMAT(aStream, aCodecCtx)); int plane_size = -1; data_size = av_samples_get_buffer_size(&plane_size, AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channels, @@ -1554,7 +1551,7 @@ void FFmpegReader::ProcessAudioPacket(int64_t requested_frame, int64_t target_fr av_opt_set_int(avr, "out_sample_rate", info.sample_rate, 0); av_opt_set_int(avr, "in_channels", info.channels, 0); av_opt_set_int(avr, "out_channels", info.channels, 0); - int r = SWR_INIT(avr); + SWR_INIT(avr); // Convert audio samples nb_samples = SWR_CONVERT(avr, // audio resample context diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 2b97ba91..ce8f6557 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -84,7 +84,7 @@ static int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *hw_device_ctx, int6 #endif // HAVE_HW_ACCEL FFmpegWriter::FFmpegWriter(std::string path) : - path(path), fmt(NULL), oc(NULL), audio_st(NULL), video_st(NULL), audio_pts(0), video_pts(0), samples(NULL), + path(path), fmt(NULL), oc(NULL), audio_st(NULL), video_st(NULL), samples(NULL), audio_outbuf(NULL), audio_outbuf_size(0), audio_input_frame_size(0), audio_input_position(0), initial_audio_input_frame_size(0), img_convert_ctx(NULL), cache_size(8), num_of_rescalers(32), rescaler_position(0), video_codec(NULL), audio_codec(NULL), is_writing(false), write_video_count(0), write_audio_count(0), @@ -2030,7 +2030,6 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *fra int error_code = 0; #if IS_FFMPEG_3_2 // Write video packet (latest version of FFmpeg) - int frameFinished = 0; int ret; #if HAVE_HW_ACCEL diff --git a/src/ImageWriter.cpp b/src/ImageWriter.cpp index 376feb62..1b7a01e9 100644 --- a/src/ImageWriter.cpp +++ b/src/ImageWriter.cpp @@ -39,7 +39,7 @@ using namespace openshot; ImageWriter::ImageWriter(std::string path) : - path(path), cache_size(8), is_writing(false), write_video_count(0), image_quality(75), number_of_loops(1), + path(path), cache_size(8), write_video_count(0), image_quality(75), number_of_loops(1), combine_frames(true), is_open(false) { // Disable audio & video (so they can be independently enabled) diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 61ce31e3..0a0806b1 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -524,9 +524,6 @@ void Timeline::add_layer(std::shared_ptr new_frame, Clip* source_clip, in // Loop through pixels for (int pixel = 0, byte_index=0; pixel < source_image->width() * source_image->height(); pixel++, byte_index+=4) { - // Get the alpha values from the pixel - int A = pixels[byte_index + 3]; - // Apply alpha to pixel pixels[byte_index + 3] *= alpha; } diff --git a/src/bindings/ruby/test.rb b/src/examples/Example.rb similarity index 100% rename from src/bindings/ruby/test.rb rename to src/examples/Example.rb From 6e7ad2316b56f6219e67b83e37ed43b5315544ce Mon Sep 17 00:00:00 2001 From: Frank Dana Date: Thu, 7 May 2020 18:24:59 -0400 Subject: [PATCH 36/79] Add version.sh script (#500) --- version.sh | 4 ++++ 1 file changed, 4 insertions(+) create mode 100755 version.sh diff --git a/version.sh b/version.sh new file mode 100755 index 00000000..86a664dc --- /dev/null +++ b/version.sh @@ -0,0 +1,4 @@ +#!/bin/sh +grep 'set.*(.*PROJECT_VERSION_FULL' CMakeLists.txt\ + |sed -e 's#set(PROJECT_VERSION_FULL.*"\(.*\)\")#\1#;q' + From 13290364e7bea54164ab83d973951f2898ad9e23 Mon Sep 17 00:00:00 2001 From: Stefan Strogin Date: Sat, 16 May 2020 02:33:37 +0300 Subject: [PATCH 37/79] FFmpegUtilities: replace variable definition with statement expression It is needed to avoid multiple definitions of AV_GET_CODEC_CONTEXT, which is considered as an error with '-fno-common' which is default since gcc-10. Fixes: #511 --- include/FFmpegUtilities.h | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/include/FFmpegUtilities.h b/include/FFmpegUtilities.h index 62d64df1..b4ec951f 100644 --- a/include/FFmpegUtilities.h +++ b/include/FFmpegUtilities.h @@ -163,11 +163,10 @@ #define AV_FREE_CONTEXT(av_context) avcodec_free_context(&av_context) #define AV_GET_CODEC_TYPE(av_stream) av_stream->codecpar->codec_type #define AV_FIND_DECODER_CODEC_ID(av_stream) av_stream->codecpar->codec_id - auto AV_GET_CODEC_CONTEXT = [](AVStream* av_stream, AVCodec* av_codec) { \ - AVCodecContext *context = avcodec_alloc_context3(av_codec); \ - avcodec_parameters_to_context(context, av_stream->codecpar); \ - return context; \ - }; + #define AV_GET_CODEC_CONTEXT(av_stream, av_codec) \ + ({ AVCodecContext *context = avcodec_alloc_context3(av_codec); \ + avcodec_parameters_to_context(context, av_stream->codecpar); \ + context; }) #define AV_GET_CODEC_PAR_CONTEXT(av_stream, av_codec) av_codec; #define AV_GET_CODEC_FROM_STREAM(av_stream,codec_in) #define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context) av_stream->codecpar @@ -199,11 +198,10 @@ #define AV_FREE_CONTEXT(av_context) avcodec_free_context(&av_context) #define AV_GET_CODEC_TYPE(av_stream) av_stream->codecpar->codec_type #define AV_FIND_DECODER_CODEC_ID(av_stream) av_stream->codecpar->codec_id - auto AV_GET_CODEC_CONTEXT = [](AVStream* av_stream, AVCodec* av_codec) { \ - AVCodecContext *context = avcodec_alloc_context3(av_codec); \ - avcodec_parameters_to_context(context, av_stream->codecpar); \ - return context; \ - }; + #define AV_GET_CODEC_CONTEXT(av_stream, av_codec) \ + ({ AVCodecContext *context = avcodec_alloc_context3(av_codec); \ + avcodec_parameters_to_context(context, av_stream->codecpar); \ + context; }) #define AV_GET_CODEC_PAR_CONTEXT(av_stream, av_codec) av_codec; #define AV_GET_CODEC_FROM_STREAM(av_stream,codec_in) #define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context) av_stream->codecpar From 4e6c1819b0af7e33ac27d22fa02a09ad268f25b1 Mon Sep 17 00:00:00 2001 From: Jeff Shillitto Date: Sat, 16 May 2020 18:55:34 +1000 Subject: [PATCH 38/79] Set clip in constructor to resolve scale crop issue --- src/Clip.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Clip.cpp b/src/Clip.cpp index 39aad35d..cdb83cdc 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -150,6 +150,10 @@ Clip::Clip(ReaderBase* new_reader) : resampler(NULL), reader(new_reader), alloca // Update duration End(reader->info.duration); + + if (new_reader) { + new_reader->SetClip(this); + } } // Constructor with filepath From 5b5950c9913501bfe11feacac32e4a0bdc4ce568 Mon Sep 17 00:00:00 2001 From: Jeff Shillitto Date: Tue, 19 May 2020 19:57:06 +1000 Subject: [PATCH 39/79] use reader instead of new_reader --- src/Clip.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Clip.cpp b/src/Clip.cpp index cdb83cdc..fa1bb7c7 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -148,11 +148,10 @@ Clip::Clip(ReaderBase* new_reader) : resampler(NULL), reader(new_reader), alloca Open(); Close(); - // Update duration - End(reader->info.duration); - - if (new_reader) { - new_reader->SetClip(this); + // Update duration and set parent + if (reader) { + End(reader->info.duration); + reader->SetClip(this); } } @@ -206,9 +205,10 @@ Clip::Clip(std::string path) : resampler(NULL), reader(NULL), allocated_reader(N } } - // Update duration + // Update duration and set parent if (reader) { End(reader->info.duration); + reader->SetClip(this); allocated_reader = reader; init_reader_rotation(); } From 216184dbb98308725b3715c5bc6a0f2ceff87ff3 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Tue, 19 May 2020 06:30:54 -0400 Subject: [PATCH 40/79] Work around Ruby/JUCE isfinite() conflict properly --- src/bindings/ruby/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bindings/ruby/CMakeLists.txt b/src/bindings/ruby/CMakeLists.txt index 2faa10fc..18964486 100644 --- a/src/bindings/ruby/CMakeLists.txt +++ b/src/bindings/ruby/CMakeLists.txt @@ -72,6 +72,9 @@ endif() set_property(SOURCE openshot.i PROPERTY CPLUSPLUS ON) set_property(SOURCE openshot.i PROPERTY SWIG_MODULE_NAME openshot) +### Unbreak std::isfinite() +add_compile_definitions(HAVE_ISFINITE=1) + ### Suppress a ton of warnings in the generated SWIG C++ code set(SWIG_CXX_FLAGS "-Wno-unused-variable -Wno-unused-function \ -Wno-deprecated-copy -Wno-class-memaccess -Wno-cast-function-type \ From 130829a41231b9ccb24493ab74d898e0d5bee339 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Tue, 19 May 2020 06:32:35 -0400 Subject: [PATCH 41/79] Deprecated juce::ScopedPointer => std::unique_ptr --- src/Frame.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Frame.cpp b/src/Frame.cpp index 9577a7f9..36e0af08 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -992,8 +992,8 @@ void Frame::Play() juce::AudioSourcePlayer audioSourcePlayer; deviceManager.addAudioCallback (&audioSourcePlayer); - ScopedPointer my_source; - my_source = new AudioBufferSource(audio.get()); + std::unique_ptr my_source; + my_source.reset (new AudioBufferSource (audio.get())); // Create TimeSliceThread for audio buffering juce::TimeSliceThread my_thread("Audio buffer thread"); @@ -1002,7 +1002,7 @@ void Frame::Play() my_thread.startThread(); AudioTransportSource transport1; - transport1.setSource (my_source, + transport1.setSource (my_source.get(), 5000, // tells it to buffer this many samples ahead &my_thread, (double) sample_rate, From affd4b248898a2958300a08697919e347d75aee0 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Tue, 19 May 2020 06:33:30 -0400 Subject: [PATCH 42/79] Add some missing juce:: prefixing --- include/Qt/AudioPlaybackThread.h | 8 ++++---- src/Frame.cpp | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/include/Qt/AudioPlaybackThread.h b/include/Qt/AudioPlaybackThread.h index 348a0f48..9a159448 100644 --- a/include/Qt/AudioPlaybackThread.h +++ b/include/Qt/AudioPlaybackThread.h @@ -75,7 +75,7 @@ namespace openshot static AudioDeviceManagerSingleton * Instance(); /// Public device manager property - AudioDeviceManager audioDeviceManager; + juce::AudioDeviceManager audioDeviceManager; /// Close audio device void CloseAudioDevice(); @@ -86,9 +86,9 @@ namespace openshot */ class AudioPlaybackThread : juce::Thread { - AudioSourcePlayer player; - AudioTransportSource transport; - MixerAudioSource mixer; + juce::AudioSourcePlayer player; + juce::AudioTransportSource transport; + juce::MixerAudioSource mixer; AudioReaderSource *source; double sampleRate; int numChannels; diff --git a/src/Frame.cpp b/src/Frame.cpp index 36e0af08..ae9f1a4b 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -829,7 +829,7 @@ void Frame::AddImage(std::shared_ptr new_image, bool only_odd_lines) if (ret) { return; } - + // Get the frame's image const GenericScopedLock lock(addingImageSection); #pragma omp critical (AddImage) @@ -979,7 +979,8 @@ void Frame::Play() return; juce::AudioDeviceManager deviceManager; - String error = deviceManager.initialise (0, /* number of input channels */ + juce::String error = deviceManager.initialise ( + 0, /* number of input channels */ 2, /* number of output channels */ 0, /* no XML settings.. */ true /* select default device on failure */); @@ -1001,7 +1002,7 @@ void Frame::Play() // Start thread my_thread.startThread(); - AudioTransportSource transport1; + juce::AudioTransportSource transport1; transport1.setSource (my_source.get(), 5000, // tells it to buffer this many samples ahead &my_thread, From 128bacce708fb01ef9b6a63060b2c1ff29e91bc0 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Tue, 19 May 2020 07:19:01 -0400 Subject: [PATCH 43/79] Support older CMake add_compile_definitions() is CMake 3.12+ only. --- src/bindings/ruby/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings/ruby/CMakeLists.txt b/src/bindings/ruby/CMakeLists.txt index 18964486..4d7b922a 100644 --- a/src/bindings/ruby/CMakeLists.txt +++ b/src/bindings/ruby/CMakeLists.txt @@ -73,7 +73,7 @@ set_property(SOURCE openshot.i PROPERTY CPLUSPLUS ON) set_property(SOURCE openshot.i PROPERTY SWIG_MODULE_NAME openshot) ### Unbreak std::isfinite() -add_compile_definitions(HAVE_ISFINITE=1) +add_definitions(-DHAVE_ISFINITE=1) ### Suppress a ton of warnings in the generated SWIG C++ code set(SWIG_CXX_FLAGS "-Wno-unused-variable -Wno-unused-function \ From e4dd72669f4778b92d139b12ef5c8d166934c94e Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Mon, 1 Jun 2020 13:24:07 -0500 Subject: [PATCH 44/79] Fix FPS setting on FFmpeg 4, which currently is not setting a valid FPS. --- src/FFmpegWriter.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index ce8f6557..cd3185c4 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -1222,6 +1222,13 @@ AVStream *FFmpegWriter::add_video_stream() { st->avg_frame_rate = av_inv_q(c->time_base); st->time_base.num = info.video_timebase.num; st->time_base.den = info.video_timebase.den; +#if (LIBAVFORMAT_VERSION_MAJOR >= 58) + _Pragma ("GCC diagnostic push"); + _Pragma ("GCC diagnostic ignored \"-Wdeprecated-declarations\""); \ + st->codec->time_base.num = info.video_timebase.num; + st->codec->time_base.den = info.video_timebase.den; + _Pragma ("GCC diagnostic pop"); +#endif c->gop_size = 12; /* TODO: add this to "info"... emit one intra frame every twelve frames at most */ c->max_b_frames = 10; From 2a043014824822e74dd4d3710df55609d6919836 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Mon, 1 Jun 2020 15:24:15 -0400 Subject: [PATCH 45/79] Travis: allow_failures for FFmpeg 3.2 --- .travis.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 24e772af..c8af86a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,8 +32,12 @@ addons: - curl jobs: - include: + # The FFmpeg 3.2 backport PPA has gone missing + allow_failures: + - name: "FFmpeg 3.2 GCC (Ubuntu 16.04 Xenial)" + + include: - name: "Coverage + FFmpeg 3.4 GCC (Ubuntu 18.04 Bionic)" env: - BUILD_VERSION=coverage_ffmpeg34 From 58c971a57690b533fba40cd6da077bec538c8c02 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Mon, 1 Jun 2020 15:24:15 -0400 Subject: [PATCH 46/79] Travis: allow_failures for FFmpeg 3.2 --- .travis.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 24e772af..c8af86a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,8 +32,12 @@ addons: - curl jobs: - include: + # The FFmpeg 3.2 backport PPA has gone missing + allow_failures: + - name: "FFmpeg 3.2 GCC (Ubuntu 16.04 Xenial)" + + include: - name: "Coverage + FFmpeg 3.4 GCC (Ubuntu 18.04 Bionic)" env: - BUILD_VERSION=coverage_ffmpeg34 From 456715437a31471209c14a58c03d7a6abea48b1f Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Mon, 1 Jun 2020 17:05:18 -0400 Subject: [PATCH 47/79] Remove unused Qt PPAs --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index c8af86a7..af54662f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,7 +49,6 @@ jobs: apt: sources: - sourceline: 'ppa:openshot.developers/libopenshot-daily' - - sourceline: 'ppa:beineri/opt-qt-5.12.3-bionic' packages: - *p_common - qt5-default @@ -96,7 +95,6 @@ jobs: apt: sources: - sourceline: 'ppa:openshot.developers/libopenshot-daily' - - sourceline: 'ppa:beineri/opt-qt-5.12.3-bionic' packages: - *p_common - qt5-default @@ -114,7 +112,6 @@ jobs: apt: sources: - sourceline: 'ppa:openshot.developers/libopenshot-daily' - - sourceline: 'ppa:beineri/opt-qt-5.10.0-xenial' - sourceline: 'ppa:jon-hedgerows/ffmpeg-backports' packages: - *p_common From 1dd0281deb74d1287da15cf2c4309a76acd3a441 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Mon, 1 Jun 2020 17:06:04 -0400 Subject: [PATCH 48/79] Use Ubuntu 20.04 for FFmpeg 4 --- .travis.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index af54662f..241d5be3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,19 +57,17 @@ jobs: - lcov - binutils-common # For c++filt - - name: "FFmpeg 4 GCC (Ubuntu 18.04 Bionic)" + - name: "FFmpeg 4 GCC (Ubuntu 20.04 Focal)" env: - BUILD_VERSION=ffmpeg4 - CMAKE_EXTRA_ARGS="" - TEST_TARGET=test os: linux - dist: bionic + dist: focal addons: apt: sources: - sourceline: 'ppa:openshot.developers/libopenshot-daily' - - sourceline: 'ppa:beineri/opt-qt-5.12.3-bionic' - - sourceline: 'ppa:jonathonf/ffmpeg-4' packages: - *p_common - qt5-default From 511a6b1da2e349afb593836498b239c5c21dac99 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Mon, 1 Jun 2020 17:58:22 -0400 Subject: [PATCH 49/79] Update Ruby compatibility message --- src/bindings/ruby/CMakeLists.txt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/bindings/ruby/CMakeLists.txt b/src/bindings/ruby/CMakeLists.txt index 4d7b922a..2ec16dcf 100644 --- a/src/bindings/ruby/CMakeLists.txt +++ b/src/bindings/ruby/CMakeLists.txt @@ -48,13 +48,15 @@ option(SILENCE_RUBY_VERSION_WARNING if (${RUBY_VERSION} VERSION_GREATER 2.6.9 AND ${SWIG_VERSION} VERSION_LESS 4.0.3) if (NOT ${SILENCE_RUBY_VERSION_WARNING}) - message(WARNING " + message(WARNING "\ Ruby 2.7.0+ detected, building the libopenshot Ruby API bindings \ -requires a pre-release version of SWIG 4.0.3 with this commit: \ -https://github.com/swig/swig/commit/5542cc228ad10bdc5c91107afb77c808c43bf2a4") - message(STATUS " -To disable this warning, add -DSILENCE_RUBY_VERSION_WARNING:BOOL=1 to the cmake \ -command line, or enable the option in the CMake GUI.") +requires either SWIG 4.0.3 or an older version patched with this commit: \ +https://github.com/swig/swig/commit/5542cc228ad10bdc5c91107afb77c808c43bf2a4 \ +(Recent Fedora and Ubuntu distro packages of SWIG 4.0.1 have already been \ +patched.)") + message(STATUS "To disable the previous warning, add \ +-DSILENCE_RUBY_VERSION_WARNING:BOOL=1 to the cmake command line, \ +or enable the option in the CMake GUI.") endif() endif() From 93d12e7f14e8c4f002e5f98af14412b80a4cd53b Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Tue, 2 Jun 2020 08:53:39 -0700 Subject: [PATCH 50/79] Include data for fps in clip created by ffmpeg 4+ --- src/FFmpegWriter.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index cc4b3d3a..e10b7026 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -1266,6 +1266,13 @@ AVStream *FFmpegWriter::add_video_stream() { st->avg_frame_rate = av_inv_q(c->time_base); st->time_base.num = info.video_timebase.num; st->time_base.den = info.video_timebase.den; +#if (LIBAVFORMAT_VERSION_MAJOR >= 58) + _Pragma ("GCC diagnostic push"); + _Pragma ("GCC diagnostic ignored \"-Wdeprecated-declarations\""); \ + st->codec->time_base.num = info.video_timebase.num; + st->codec->time_base.den = info.video_timebase.den; + _Pragma ("GCC diagnostic pop"); +#endif c->gop_size = 12; /* TODO: add this to "info"... emit one intra frame every twelve frames at most */ c->max_b_frames = 10; From 7ed26cf0223fbfd0a6f4988b9dd1099324496e8a Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Tue, 2 Jun 2020 13:30:05 -0500 Subject: [PATCH 51/79] Replace _Pragma with #pragma Co-authored-by: Frank Dana --- src/FFmpegWriter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index cd3185c4..5b57218f 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -1223,11 +1223,11 @@ AVStream *FFmpegWriter::add_video_stream() { st->time_base.num = info.video_timebase.num; st->time_base.den = info.video_timebase.den; #if (LIBAVFORMAT_VERSION_MAJOR >= 58) - _Pragma ("GCC diagnostic push"); - _Pragma ("GCC diagnostic ignored \"-Wdeprecated-declarations\""); \ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" st->codec->time_base.num = info.video_timebase.num; st->codec->time_base.den = info.video_timebase.den; - _Pragma ("GCC diagnostic pop"); + #pragma GCC diagnostic pop #endif c->gop_size = 12; /* TODO: add this to "info"... emit one intra frame every twelve frames at most */ From d9e6af5cda54ad7d33569563d86653bcfc58a890 Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Tue, 2 Jun 2020 11:35:07 -0700 Subject: [PATCH 52/79] Refert last commit --- src/FFmpegWriter.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index e10b7026..cc4b3d3a 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -1266,13 +1266,6 @@ AVStream *FFmpegWriter::add_video_stream() { st->avg_frame_rate = av_inv_q(c->time_base); st->time_base.num = info.video_timebase.num; st->time_base.den = info.video_timebase.den; -#if (LIBAVFORMAT_VERSION_MAJOR >= 58) - _Pragma ("GCC diagnostic push"); - _Pragma ("GCC diagnostic ignored \"-Wdeprecated-declarations\""); \ - st->codec->time_base.num = info.video_timebase.num; - st->codec->time_base.den = info.video_timebase.den; - _Pragma ("GCC diagnostic pop"); -#endif c->gop_size = 12; /* TODO: add this to "info"... emit one intra frame every twelve frames at most */ c->max_b_frames = 10; From f4b40a4e7749f0d45ff850928ca935d9e6c99682 Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Thu, 4 Jun 2020 08:28:33 -0700 Subject: [PATCH 53/79] Improvements to handling of new codecs --- src/FFmpegWriter.cpp | 61 +++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index e6a7e5ef..9b348aed 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -479,15 +479,6 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va case AV_CODEC_ID_AV1 : c->bit_rate = 0; av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0); - if (strstr(info.vcodec.c_str(), "svt_av1") != NULL) { - av_opt_set_int(c->priv_data, "preset", 6, 0); - av_opt_set_int(c->priv_data, "forced-idr",1,0); - } - if (strstr(info.vcodec.c_str(), "rav1e") != NULL) { - av_opt_set_int(c->priv_data, "speed", 7, 0); - av_opt_set_int(c->priv_data, "tile-rows", 2, 0); - av_opt_set_int(c->priv_data, "tile-columns", 4, 0); - } break; #endif case AV_CODEC_ID_VP8 : @@ -547,24 +538,17 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va c->bit_rate = 0; if (strstr(info.vcodec.c_str(), "svt_av1") != NULL) { av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),63), 0); - av_opt_set_int(c->priv_data, "preset", 6, 0); - av_opt_set_int(c->priv_data, "forced-idr",1,0); } else if (strstr(info.vcodec.c_str(), "rav1e") != NULL) { // Set number of tiles to a fixed value // TODO Let user choose number of tiles av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),255), 0); - av_opt_set_int(c->priv_data, "speed", 7, 0); - av_opt_set_int(c->priv_data, "tile-rows", 2, 0); // number of rows - av_opt_set_int(c->priv_data, "tile-columns", 4, 0); // number of columns } else if (strstr(info.vcodec.c_str(), "aom") != NULL) { // Set number of tiles to a fixed value // TODO Let user choose number of tiles // libaom doesn't have qp only crf av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0); - av_opt_set_int(c->priv_data, "tile-rows", 1, 0); // log2 of number of rows - av_opt_set_int(c->priv_data, "tile-columns", 2, 0); // log2 of number of columns } else { av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0); @@ -1222,7 +1206,11 @@ AVStream *FFmpegWriter::add_video_stream() { #endif /* Init video encoder options */ - if (info.video_bit_rate >= 1000) { + if (info.video_bit_rate >= 1000 +#if (LIBAVCODEC_VERSION_MAJOR >= 58) + && c->codec_id != AV_CODEC_ID_AV1 +#endif + ) { c->bit_rate = info.video_bit_rate; if (info.video_bit_rate >= 1500000) { c->qmin = 2; @@ -1231,11 +1219,48 @@ AVStream *FFmpegWriter::add_video_stream() { // Here should be the setting for low fixed bitrate // Defaults are used because mpeg2 otherwise had problems } else { - // Check if codec supports crf + // Check if codec supports crf or qp switch (c->codec_id) { #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 39, 101) #if (LIBAVCODEC_VERSION_MAJOR >= 58) case AV_CODEC_ID_AV1 : + // TODO: + // set crf or qp according to bitrate as bitrate is not supported by + // these encoders (yet) + if (info.video_bit_rate >= 1000) { + c->bit_rate = 0; + if (strstr(info.vcodec.c_str(), "aom") != NULL) { + int calculated_quality = 35; + if (info.video_bit_rate < 500000) calculated_quality = 50; + if (info.video_bit_rate > 5000000) calculated_quality = 10; + av_opt_set_int(c->priv_data, "crf", calculated_quality, 0); + info.video_bit_rate = calculated_quality; + } else { + int calculated_quality = 50; + if (info.video_bit_rate < 500000) calculated_quality = 60; + if (info.video_bit_rate > 5000000) calculated_quality = 15; + av_opt_set_int(c->priv_data, "qp", calculated_quality, 0); + info.video_bit_rate = calculated_quality; + } // medium + } + if (strstr(info.vcodec.c_str(), "svt_av1") != NULL) { + av_opt_set_int(c->priv_data, "preset", 6, 0); + av_opt_set_int(c->priv_data, "forced-idr",1,0); + } + else if (strstr(info.vcodec.c_str(), "rav1e") != NULL) { + av_opt_set_int(c->priv_data, "speed", 7, 0); + av_opt_set_int(c->priv_data, "tile-rows", 2, 0); + av_opt_set_int(c->priv_data, "tile-columns", 4, 0); + } + else if (strstr(info.vcodec.c_str(), "aom") != NULL) { + // Set number of tiles to a fixed value + // TODO Let user choose number of tiles + av_opt_set_int(c->priv_data, "tile-rows", 1, 0); // log2 of number of rows + av_opt_set_int(c->priv_data, "tile-columns", 2, 0); // log2 of number of columns + av_opt_set_int(c->priv_data, "row-mt", 1, 0); // use multiple cores + av_opt_set_int(c->priv_data, "cpu-used", 3, 0); // default is 1, usable is 4 + } + //break; #endif case AV_CODEC_ID_VP9 : case AV_CODEC_ID_HEVC : From 62d7fb54596219b993cf432d0a437de6e1fdb7a6 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Thu, 4 Jun 2020 18:52:19 -0500 Subject: [PATCH 54/79] Changing some libopenshot code based on Codacy feedback. Small refactoring, scope limiing. --- include/FFmpegWriter.h | 2 +- src/FFmpegWriter.cpp | 42 ++++++++++++------------------------------ 2 files changed, 13 insertions(+), 31 deletions(-) diff --git a/include/FFmpegWriter.h b/include/FFmpegWriter.h index 37fa22dc..b3bec7ad 100644 --- a/include/FFmpegWriter.h +++ b/include/FFmpegWriter.h @@ -253,7 +253,7 @@ namespace openshot { /// @brief Constructor for FFmpegWriter. Throws one of the following exceptions. /// @param path The file path of the video file you want to open and read - FFmpegWriter(std::string path); + FFmpegWriter(const std::string path); /// Close the writer void Close(); diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index e6a7e5ef..5b5c5410 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -83,7 +83,7 @@ static int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *hw_device_ctx, int6 } #endif // HAVE_HW_ACCEL -FFmpegWriter::FFmpegWriter(std::string path) : +FFmpegWriter::FFmpegWriter(const std::string path) : path(path), fmt(NULL), oc(NULL), audio_st(NULL), video_st(NULL), samples(NULL), audio_outbuf(NULL), audio_outbuf_size(0), audio_input_frame_size(0), audio_input_position(0), initial_audio_input_frame_size(0), img_convert_ctx(NULL), cache_size(8), num_of_rescalers(32), @@ -864,9 +864,6 @@ void FFmpegWriter::flush_encoders() { return; #endif - int error_code = 0; - int stop_encoding = 1; - // FLUSH VIDEO ENCODER if (info.has_video) for (;;) { @@ -940,13 +937,9 @@ void FFmpegWriter::flush_encoders() { ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::flush_encoders ERROR [" + (std::string) av_err2str(error_code) + "]", "error_code", error_code); } if (!got_packet) { - stop_encoding = 1; break; } - // Override PTS (in frames and scaled to the codec's timebase) - //pkt.pts = write_video_count; - // set the timestamp if (pkt.pts != AV_NOPTS_VALUE) pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base); @@ -961,10 +954,6 @@ void FFmpegWriter::flush_encoders() { if (error_code < 0) { ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::flush_encoders ERROR [" + (std::string)av_err2str(error_code) + "]", "error_code", error_code); } - - // Deallocate memory (if needed) - if (video_outbuf) - av_freep(&video_outbuf); } // FLUSH AUDIO ENCODER @@ -986,20 +975,15 @@ void FFmpegWriter::flush_encoders() { pkt.pts = pkt.dts = write_audio_count; /* encode the image */ - int got_packet = 0; + int error_code = 0; #if IS_FFMPEG_3_2 - avcodec_send_frame(audio_codec, NULL); - got_packet = 0; + error_code = avcodec_send_frame(audio_codec, NULL); #else error_code = avcodec_encode_audio2(audio_codec, &pkt, NULL, &got_packet); #endif if (error_code < 0) { ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::flush_encoders ERROR [" + (std::string)av_err2str(error_code) + "]", "error_code", error_code); } - if (!got_packet) { - stop_encoding = 1; - break; - } // Since the PTS can change during encoding, set the value again. This seems like a huge hack, // but it fixes lots of PTS related issues when I do this. @@ -1583,29 +1567,27 @@ void FFmpegWriter::write_audio_packets(bool is_final) { channels_in_frame = frame->GetAudioChannelsCount(); channel_layout_in_frame = frame->ChannelsLayout(); - // Get audio sample array float *frame_samples_float = NULL; // Get samples interleaved together (c1 c2 c1 c2 c1 c2) frame_samples_float = frame->GetInterleavedAudioSamples(sample_rate_in_frame, NULL, &samples_in_frame); - // Calculate total samples total_frame_samples = samples_in_frame * channels_in_frame; // Translate audio sample values back to 16 bit integers with saturation - float valF; - int16_t conv; const int16_t max16 = 32767; const int16_t min16 = -32768; for (int s = 0; s < total_frame_samples; s++, frame_position++) { - valF = frame_samples_float[s] * (1 << 15); - if (valF > max16) + float valF = frame_samples_float[s] * (1 << 15); + int16_t conv; + if (valF > max16) { conv = max16; - else if (valF < min16) + } else if (valF < min16) { conv = min16; - else + } else { conv = int(valF + 32768.5) - 32768; // +0.5 is for rounding + } // Copy into buffer all_queued_samples[frame_position] = conv; @@ -1731,10 +1713,11 @@ void FFmpegWriter::write_audio_packets(bool is_final) { // Determine how many samples we need int diff = 0; - if (remaining_frame_samples >= remaining_packet_samples) + if (remaining_frame_samples >= remaining_packet_samples) { diff = remaining_packet_samples; - else if (remaining_frame_samples < remaining_packet_samples) + } else { diff = remaining_frame_samples; + } // Copy frame samples into the packet samples array if (!is_final) @@ -1746,7 +1729,6 @@ void FFmpegWriter::write_audio_packets(bool is_final) { audio_input_position += diff; samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)); remaining_frame_samples -= diff; - remaining_packet_samples -= diff; // Do we have enough samples to proceed? if (audio_input_position < (audio_input_frame_size * info.channels) && !is_final) From 86b83abf5d74f65c67ed6e8c3b5869110e66b43e Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Fri, 5 Jun 2020 15:41:23 -0500 Subject: [PATCH 55/79] Fixing undefined got_packet int --- src/FFmpegWriter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 5b5c5410..7eb24156 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -976,6 +976,7 @@ void FFmpegWriter::flush_encoders() { /* encode the image */ int error_code = 0; + int got_packet = 0; #if IS_FFMPEG_3_2 error_code = avcodec_send_frame(audio_codec, NULL); #else From 51fe8549e6364e8d685dd4e5c3a1f5de2fda50d3 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Fri, 5 Jun 2020 17:53:21 -0500 Subject: [PATCH 56/79] Fix regression caused by Codacy tweaks --- src/FFmpegWriter.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 7eb24156..5a21c6ba 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -985,6 +985,9 @@ void FFmpegWriter::flush_encoders() { if (error_code < 0) { ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::flush_encoders ERROR [" + (std::string)av_err2str(error_code) + "]", "error_code", error_code); } + if (!got_packet) { + break; + } // Since the PTS can change during encoding, set the value again. This seems like a huge hack, // but it fixes lots of PTS related issues when I do this. From 7b94ac838b76f1211ed3c14183fdd15deb354b04 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Fri, 5 Jun 2020 18:07:25 -0500 Subject: [PATCH 57/79] Removing bad suggestion. In theory, we could change this signature to take a const reference to a string, but for now, I'm reverting it. --- include/FFmpegWriter.h | 2 +- src/FFmpegWriter.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/FFmpegWriter.h b/include/FFmpegWriter.h index b3bec7ad..37fa22dc 100644 --- a/include/FFmpegWriter.h +++ b/include/FFmpegWriter.h @@ -253,7 +253,7 @@ namespace openshot { /// @brief Constructor for FFmpegWriter. Throws one of the following exceptions. /// @param path The file path of the video file you want to open and read - FFmpegWriter(const std::string path); + FFmpegWriter(std::string path); /// Close the writer void Close(); diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 5a21c6ba..e3dedb28 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -83,7 +83,7 @@ static int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *hw_device_ctx, int6 } #endif // HAVE_HW_ACCEL -FFmpegWriter::FFmpegWriter(const std::string path) : +FFmpegWriter::FFmpegWriter(std::string path) : path(path), fmt(NULL), oc(NULL), audio_st(NULL), video_st(NULL), samples(NULL), audio_outbuf(NULL), audio_outbuf_size(0), audio_input_frame_size(0), audio_input_position(0), initial_audio_input_frame_size(0), img_convert_ctx(NULL), cache_size(8), num_of_rescalers(32), From 7831cfe9128502ae894d85c14e033991cd9a3d1b Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Sat, 6 Jun 2020 01:55:52 -0500 Subject: [PATCH 58/79] Adding some new functionality and documentation to DummyReader. Adding the ability to add test frames, with fake image and audio data. This will can be used in unittests, and will soon be used to verify some new audio improvements (coming soon). --- include/DummyReader.h | 50 +++++++++++++++++- src/DummyReader.cpp | 31 +++++++++-- src/Frame.cpp | 5 ++ tests/CMakeLists.txt | 1 + tests/DummyReader_Tests.cpp | 102 ++++++++++++++++++++++++++++++++++++ 5 files changed, 185 insertions(+), 4 deletions(-) create mode 100644 tests/DummyReader_Tests.cpp diff --git a/include/DummyReader.h b/include/DummyReader.h index 4c935103..576a0df8 100644 --- a/include/DummyReader.h +++ b/include/DummyReader.h @@ -46,14 +46,58 @@ namespace openshot { /** - * @brief This class is used as a simple, dummy reader, which always returns a blank frame. + * @brief This class is used as a simple, dummy reader, which can be very useful when writing + * unit tests. It can return a single blank frame or it can return custom frame objects + * which were added using the WriteFrame() method. * * A dummy reader can be created with any framerate or samplerate. This is useful in unit * tests that need to test different framerates or samplerates. + * + * @code + * // Create a reader (Fraction fps, int width, int height, int sample_rate, int channels, float duration) + * openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0); + * r.Open(); // Open the reader + * + * // Get a frame (which will be blank, since we haven't added any frames yet) + * std::shared_ptr f = r.GetFrame(1); + * + * // Now let's create some test frames + * for (int64_t frame_number = 1; frame_number <= 30; frame_number++) + * { + * // Create blank frame (with specific frame #, samples, and channels) + * // Sample count should be 44100 / 30 fps = 1470 samples per frame + * int sample_count = 1470; + * std::shared_ptr f(new openshot::Frame(frame_number, sample_count, 2)); + * + * // Create test samples with incrementing value + * float *audio_buffer = new float[sample_count]; + * for (int64_t sample_number = 0; sample_number < sample_count; sample_number++) + * { + * // Generate an incrementing audio sample value (just as an example) + * audio_buffer[sample_number] = float(frame_number) + (float(sample_number) / float(sample_count)); + * } + * + * // Add custom audio samples to Frame (bool replaceSamples, int destChannel, int destStartSample, const float* source, + * // int numSamples, float gainToApplyToSource = 1.0f) + * f->AddAudio(true, 0, 0, audio_buffer, sample_count, 1.0); // add channel 1 + * f->AddAudio(true, 1, 0, audio_buffer, sample_count, 1.0); // add channel 2 + * + * // Write test frame to dummy reader + * r.WriteFrame(f); + * } + * + * // Now let's verify our DummyReader works + * std::shared_ptr f = r.GetFrame(1); + * // r.GetFrame(1)->GetAudioSamples(0)[1] should equal 1.00068033 based on our above calculations + * + * // Close the reader + * r.Close(); + * @endcode */ class DummyReader : public ReaderBase { private: + CacheMemory dummy_cache; std::shared_ptr image_frame; bool is_open; @@ -94,6 +138,10 @@ namespace openshot /// Open File - which is called by the constructor automatically void Open() override; + + /// @brief Add a frame to the dummy reader. This is useful when constructing unit tests that require custom frames. + /// @param frame The openshot::Frame object to write to this image + void WriteFrame(std::shared_ptr frame); }; } diff --git a/src/DummyReader.cpp b/src/DummyReader.cpp index 8fd98bcb..1b663a07 100644 --- a/src/DummyReader.cpp +++ b/src/DummyReader.cpp @@ -99,24 +99,49 @@ void DummyReader::Close() { // Mark as "closed" is_open = false; + + // Clear cache + dummy_cache.Clear(); } } -// Get an openshot::Frame object for a specific frame number of this reader. +// Add Frame objects to DummyReader +void DummyReader::WriteFrame(std::shared_ptr frame) +{ + if (frame) { + dummy_cache.Add(frame); + } +} + +// Get an openshot::Frame object for a specific frame number of this reader. It is either a blank frame +// or a custom frame added with the WriteFrame() method. std::shared_ptr DummyReader::GetFrame(int64_t requested_frame) { // Check for open reader (or throw exception) if (!is_open) throw ReaderClosed("The ImageReader is closed. Call Open() before calling this method.", "dummy"); - if (image_frame) - { + if (dummy_cache.Count() == 0 && image_frame) { // Create a scoped lock, allowing only a single thread to run the following code at one time const GenericScopedLock lock(getFrameCriticalSection); // Always return same frame (regardless of which frame number was requested) image_frame->number = requested_frame; return image_frame; + + } else if (dummy_cache.Count() > 0) { + // Create a scoped lock, allowing only a single thread to run the following code at one time + const GenericScopedLock lock(getFrameCriticalSection); + + // Get a frame from the dummy cache + std::shared_ptr f = dummy_cache.GetFrame(requested_frame); + if (f) { + // return frame from cache (if found) + return f; + } else { + // No cached frame found + throw InvalidFile("Requested frame not found. You can only access Frame numbers added with WriteFrame().", "dummy"); + } } else // no frame loaded diff --git a/src/Frame.cpp b/src/Frame.cpp index ae9f1a4b..764b9651 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -480,6 +480,11 @@ const unsigned char* Frame::GetPixels() // Get pixel data (for only a single scan-line) const unsigned char* Frame::GetPixels(int row) { + // Check for blank image + if (!image) + // Fill with black + AddColor(width, height, color); + // Return array of pixel packets return image->constScanLine(row); } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 480dfb3d..7ccddba8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -109,6 +109,7 @@ set(OPENSHOT_TEST_FILES Clip_Tests.cpp Color_Tests.cpp Coordinate_Tests.cpp + DummyReader_Tests.cpp ReaderBase_Tests.cpp ImageWriter_Tests.cpp FFmpegReader_Tests.cpp diff --git a/tests/DummyReader_Tests.cpp b/tests/DummyReader_Tests.cpp new file mode 100644 index 00000000..ea410ad0 --- /dev/null +++ b/tests/DummyReader_Tests.cpp @@ -0,0 +1,102 @@ +/** + * @file + * @brief Unit tests for openshot::DummyReader + * @author Jonathan Thomas + * + * @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" + +using namespace std; +using namespace openshot; + +TEST (DummyReader_Constructor) { + // Create a default fraction (should be 1/1) + openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0); + r.Open(); // Open the reader + + // Check values + CHECK_EQUAL(1920, r.info.width); + CHECK_EQUAL(1080, r.info.height); + CHECK_EQUAL(30, r.info.fps.num); + CHECK_EQUAL(1, r.info.fps.den); + CHECK_EQUAL(44100, r.info.sample_rate); + CHECK_EQUAL(2, r.info.channels); + CHECK_EQUAL(30.0, r.info.duration); +} + +TEST (DummyReader_Blank_Frame) { + // Create a default fraction (should be 1/1) + openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0); + r.Open(); // Open the reader + + // Get a blank frame (because we have not added any frames using WriteFrame() yet) + // Check values + CHECK_EQUAL(1, r.GetFrame(1)->number); + CHECK_EQUAL(1, r.GetFrame(1)->GetPixels(700)[700] == 0); // black pixel + CHECK_EQUAL(1, r.GetFrame(1)->GetPixels(701)[701] == 0); // black pixel +} + +TEST (DummyReader_Fake_Frame) { + // Create a default fraction (should be 1/1) + openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0); + r.Open(); // Open the reader + + // Let's create some test frames + for (int64_t frame_number = 1; frame_number <= 30; frame_number++) { + // Create blank frame (with specific frame #, samples, and channels) + // Sample count should be 44100 / 30 fps = 1470 samples per frame + int sample_count = 1470; + std::shared_ptr f(new openshot::Frame(frame_number, sample_count, 2)); + + // Create test samples with incrementing value + float *audio_buffer = new float[sample_count]; + for (int64_t sample_number = 0; sample_number < sample_count; sample_number++) { + // Generate an incrementing audio sample value (just as an example) + audio_buffer[sample_number] = float(frame_number) + (float(sample_number) / float(sample_count)); + } + + // Add custom audio samples to Frame (bool replaceSamples, int destChannel, int destStartSample, const float* source, + f->AddAudio(true, 0, 0, audio_buffer, sample_count, 1.0); // add channel 1 + f->AddAudio(true, 1, 0, audio_buffer, sample_count, 1.0); // add channel 2 + + // Write test frame to dummy reader + r.WriteFrame(f); + } + + // Verify our artificial audio sample data is correct + CHECK_EQUAL(1, r.GetFrame(1)->number); + CHECK_EQUAL(1, r.GetFrame(1)->GetAudioSamples(0)[0]); + CHECK_CLOSE(1.00068033, r.GetFrame(1)->GetAudioSamples(0)[1], 0.00001); + CHECK_CLOSE(1.00136054, r.GetFrame(1)->GetAudioSamples(0)[2], 0.00001); + CHECK_EQUAL(2, r.GetFrame(2)->GetAudioSamples(0)[0]); + CHECK_CLOSE(2.00068033, r.GetFrame(2)->GetAudioSamples(0)[1], 0.00001); + CHECK_CLOSE(2.00136054, r.GetFrame(2)->GetAudioSamples(0)[2], 0.00001); +} \ No newline at end of file From d29027ae30466f3aeb6ec0b78cc28754d7630174 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Sat, 6 Jun 2020 02:03:27 -0500 Subject: [PATCH 59/79] Added an additional unittest for DummyReader (for invalid frame) --- tests/DummyReader_Tests.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/DummyReader_Tests.cpp b/tests/DummyReader_Tests.cpp index ea410ad0..6ec11e08 100644 --- a/tests/DummyReader_Tests.cpp +++ b/tests/DummyReader_Tests.cpp @@ -99,4 +99,23 @@ TEST (DummyReader_Fake_Frame) { CHECK_EQUAL(2, r.GetFrame(2)->GetAudioSamples(0)[0]); CHECK_CLOSE(2.00068033, r.GetFrame(2)->GetAudioSamples(0)[1], 0.00001); CHECK_CLOSE(2.00136054, r.GetFrame(2)->GetAudioSamples(0)[2], 0.00001); +} + +TEST (DummyReader_Invalid_Fake_Frame) { + // Create a default fraction (should be 1/1) + openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0); + r.Open(); + + // Create fake frames (with specific frame #, samples, and channels) + std::shared_ptr f1(new openshot::Frame(1, 1470, 2)); + std::shared_ptr f2(new openshot::Frame(2, 1470, 2)); + + // Write test frames to dummy reader + r.WriteFrame(f1); + r.WriteFrame(f2); + + // Verify exception + CHECK_EQUAL(1, r.GetFrame(1)->number); + CHECK_EQUAL(2, r.GetFrame(2)->number); + CHECK_THROW(r.GetFrame(3)->number, InvalidFile); } \ No newline at end of file From 8b12c1fa2173db24246858e744118da544d7e320 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Sat, 6 Jun 2020 17:25:45 -0500 Subject: [PATCH 60/79] Replacing WriteFrame() method with custom constructor which can accept a CacheBase* pointer, for instances where a DummyReader needs some specific test Frame objects --- include/DummyReader.h | 33 ++++++++++--------- src/DummyReader.cpp | 64 ++++++++++++++++++++----------------- tests/DummyReader_Tests.cpp | 58 ++++++++++++++++++++++++--------- 3 files changed, 96 insertions(+), 59 deletions(-) diff --git a/include/DummyReader.h b/include/DummyReader.h index 576a0df8..e9c90968 100644 --- a/include/DummyReader.h +++ b/include/DummyReader.h @@ -48,18 +48,14 @@ namespace openshot /** * @brief This class is used as a simple, dummy reader, which can be very useful when writing * unit tests. It can return a single blank frame or it can return custom frame objects - * which were added using the WriteFrame() method. + * which were passed into the constructor with a Cache object. * * A dummy reader can be created with any framerate or samplerate. This is useful in unit * tests that need to test different framerates or samplerates. * * @code - * // Create a reader (Fraction fps, int width, int height, int sample_rate, int channels, float duration) - * openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0); - * r.Open(); // Open the reader - * - * // Get a frame (which will be blank, since we haven't added any frames yet) - * std::shared_ptr f = r.GetFrame(1); + * // Create cache object to store fake Frame objects + * CacheMemory cache; * * // Now let's create some test frames * for (int64_t frame_number = 1; frame_number <= 30; frame_number++) @@ -82,25 +78,33 @@ namespace openshot * f->AddAudio(true, 0, 0, audio_buffer, sample_count, 1.0); // add channel 1 * f->AddAudio(true, 1, 0, audio_buffer, sample_count, 1.0); // add channel 2 * - * // Write test frame to dummy reader - * r.WriteFrame(f); + * // Add test frame to cache + * cache.Add(f); * } * + * // Create a reader (Fraction fps, int width, int height, int sample_rate, int channels, float duration, CacheBase* cache) + * openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0, &cache); + * r.Open(); // Open the reader + * * // Now let's verify our DummyReader works * std::shared_ptr f = r.GetFrame(1); * // r.GetFrame(1)->GetAudioSamples(0)[1] should equal 1.00068033 based on our above calculations * - * // Close the reader + * // Clean up * r.Close(); + * cache.Clear() * @endcode */ class DummyReader : public ReaderBase { private: - CacheMemory dummy_cache; + CacheBase* dummy_cache; std::shared_ptr image_frame; bool is_open; + /// Initialize variables used by constructor + void init(Fraction fps, int width, int height, int sample_rate, int channels, float duration); + public: /// Blank constructor for DummyReader, with default settings. @@ -109,6 +113,9 @@ namespace openshot /// Constructor for DummyReader. DummyReader(openshot::Fraction fps, int width, int height, int sample_rate, int channels, float duration); + /// Constructor for DummyReader which takes a frame cache object. + DummyReader(openshot::Fraction fps, int width, int height, int sample_rate, int channels, float duration, CacheBase* cache); + virtual ~DummyReader(); /// Close File @@ -138,10 +145,6 @@ namespace openshot /// Open File - which is called by the constructor automatically void Open() override; - - /// @brief Add a frame to the dummy reader. This is useful when constructing unit tests that require custom frames. - /// @param frame The openshot::Frame object to write to this image - void WriteFrame(std::shared_ptr frame); }; } diff --git a/src/DummyReader.cpp b/src/DummyReader.cpp index 1b663a07..8b6f752f 100644 --- a/src/DummyReader.cpp +++ b/src/DummyReader.cpp @@ -32,16 +32,8 @@ using namespace openshot; -// Blank constructor for DummyReader, with default settings. -DummyReader::DummyReader() { - - // Call actual constructor with default values - DummyReader(Fraction(24,1), 1280, 768, 44100, 2, 30.0); -} - -// Constructor for DummyReader. Pass a framerate and samplerate. -DummyReader::DummyReader(Fraction fps, int width, int height, int sample_rate, int channels, float duration) { - +// Initialize variables used by constructor +void DummyReader::init(Fraction fps, int width, int height, int sample_rate, int channels, float duration) { // Set key info settings info.has_audio = false; info.has_video = true; @@ -68,10 +60,30 @@ DummyReader::DummyReader(Fraction fps, int width, int height, int sample_rate, i // Set the ratio based on the reduced fraction info.display_ratio.num = size.num; info.display_ratio.den = size.den; +} - // Open and Close the reader, to populate its attributes (such as height, width, etc...) - Open(); - Close(); +// Blank constructor for DummyReader, with default settings. +DummyReader::DummyReader() : dummy_cache(NULL), is_open(false) { + + // Initialize important variables + init(Fraction(24,1), 1280, 768, 44100, 2, 30.0); +} + +// Constructor for DummyReader. Pass a framerate and samplerate. +DummyReader::DummyReader(Fraction fps, int width, int height, int sample_rate, int channels, float duration) : dummy_cache(NULL), is_open(false) { + + // Initialize important variables + init(fps, width, height, sample_rate, channels, duration); +} + +// Constructor which also takes a cache object +DummyReader::DummyReader(Fraction fps, int width, int height, int sample_rate, int channels, float duration, CacheBase* cache) : is_open(false) { + + // Initialize important variables + init(fps, width, height, sample_rate, channels, duration); + + // Set cache object + dummy_cache = (CacheBase*) cache; } DummyReader::~DummyReader() { @@ -99,29 +111,23 @@ void DummyReader::Close() { // Mark as "closed" is_open = false; - - // Clear cache - dummy_cache.Clear(); - } -} - -// Add Frame objects to DummyReader -void DummyReader::WriteFrame(std::shared_ptr frame) -{ - if (frame) { - dummy_cache.Add(frame); } } // Get an openshot::Frame object for a specific frame number of this reader. It is either a blank frame -// or a custom frame added with the WriteFrame() method. +// or a custom frame added with passing a Cache object to the constructor. std::shared_ptr DummyReader::GetFrame(int64_t requested_frame) { // Check for open reader (or throw exception) if (!is_open) throw ReaderClosed("The ImageReader is closed. Call Open() before calling this method.", "dummy"); - if (dummy_cache.Count() == 0 && image_frame) { + int dummy_cache_count = 0; + if (dummy_cache) { + dummy_cache_count = dummy_cache->Count(); + } + + if (dummy_cache_count == 0 && image_frame) { // Create a scoped lock, allowing only a single thread to run the following code at one time const GenericScopedLock lock(getFrameCriticalSection); @@ -129,18 +135,18 @@ std::shared_ptr DummyReader::GetFrame(int64_t requested_frame) image_frame->number = requested_frame; return image_frame; - } else if (dummy_cache.Count() > 0) { + } else if (dummy_cache_count > 0) { // Create a scoped lock, allowing only a single thread to run the following code at one time const GenericScopedLock lock(getFrameCriticalSection); // Get a frame from the dummy cache - std::shared_ptr f = dummy_cache.GetFrame(requested_frame); + std::shared_ptr f = dummy_cache->GetFrame(requested_frame); if (f) { // return frame from cache (if found) return f; } else { // No cached frame found - throw InvalidFile("Requested frame not found. You can only access Frame numbers added with WriteFrame().", "dummy"); + throw InvalidFile("Requested frame not found. You can only access Frame numbers that exist in the Cache object.", "dummy"); } } else diff --git a/tests/DummyReader_Tests.cpp b/tests/DummyReader_Tests.cpp index 6ec11e08..c72be2d9 100644 --- a/tests/DummyReader_Tests.cpp +++ b/tests/DummyReader_Tests.cpp @@ -37,9 +37,24 @@ using namespace std; using namespace openshot; +TEST (DummyReader_Basic_Constructor) { + // Create a default fraction (should be 1/1) + openshot::DummyReader r; + r.Open(); // Open the reader + + // Check values + CHECK_EQUAL(1280, r.info.width); + CHECK_EQUAL(768, r.info.height); + CHECK_EQUAL(24, r.info.fps.num); + CHECK_EQUAL(1, r.info.fps.den); + CHECK_EQUAL(44100, r.info.sample_rate); + CHECK_EQUAL(2, r.info.channels); + CHECK_EQUAL(30.0, r.info.duration); +} + TEST (DummyReader_Constructor) { // Create a default fraction (should be 1/1) - openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0); + openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 60.0); r.Open(); // Open the reader // Check values @@ -49,7 +64,7 @@ TEST (DummyReader_Constructor) { CHECK_EQUAL(1, r.info.fps.den); CHECK_EQUAL(44100, r.info.sample_rate); CHECK_EQUAL(2, r.info.channels); - CHECK_EQUAL(30.0, r.info.duration); + CHECK_EQUAL(60.0, r.info.duration); } TEST (DummyReader_Blank_Frame) { @@ -57,7 +72,7 @@ TEST (DummyReader_Blank_Frame) { openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0); r.Open(); // Open the reader - // Get a blank frame (because we have not added any frames using WriteFrame() yet) + // Get a blank frame (because we have not passed a Cache object (full of Frame objects) to the constructor // Check values CHECK_EQUAL(1, r.GetFrame(1)->number); CHECK_EQUAL(1, r.GetFrame(1)->GetPixels(700)[700] == 0); // black pixel @@ -65,9 +80,9 @@ TEST (DummyReader_Blank_Frame) { } TEST (DummyReader_Fake_Frame) { - // Create a default fraction (should be 1/1) - openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0); - r.Open(); // Open the reader + + // Create cache object to hold test frames + CacheMemory cache; // Let's create some test frames for (int64_t frame_number = 1; frame_number <= 30; frame_number++) { @@ -87,10 +102,14 @@ TEST (DummyReader_Fake_Frame) { f->AddAudio(true, 0, 0, audio_buffer, sample_count, 1.0); // add channel 1 f->AddAudio(true, 1, 0, audio_buffer, sample_count, 1.0); // add channel 2 - // Write test frame to dummy reader - r.WriteFrame(f); + // Add test frame to dummy reader + cache.Add(f); } + // Create a default fraction (should be 1/1) + openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0, &cache); + r.Open(); // Open the reader + // Verify our artificial audio sample data is correct CHECK_EQUAL(1, r.GetFrame(1)->number); CHECK_EQUAL(1, r.GetFrame(1)->GetAudioSamples(0)[0]); @@ -99,23 +118,32 @@ TEST (DummyReader_Fake_Frame) { CHECK_EQUAL(2, r.GetFrame(2)->GetAudioSamples(0)[0]); CHECK_CLOSE(2.00068033, r.GetFrame(2)->GetAudioSamples(0)[1], 0.00001); CHECK_CLOSE(2.00136054, r.GetFrame(2)->GetAudioSamples(0)[2], 0.00001); + + // Clean up + cache.Clear(); + r.Close(); } TEST (DummyReader_Invalid_Fake_Frame) { - // Create a default fraction (should be 1/1) - openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0); - r.Open(); - // Create fake frames (with specific frame #, samples, and channels) std::shared_ptr f1(new openshot::Frame(1, 1470, 2)); std::shared_ptr f2(new openshot::Frame(2, 1470, 2)); - // Write test frames to dummy reader - r.WriteFrame(f1); - r.WriteFrame(f2); + // Add test frames to cache object + CacheMemory cache; + cache.Add(f1); + cache.Add(f2); + + // Create a default fraction (should be 1/1) + openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0, &cache); + r.Open(); // Verify exception CHECK_EQUAL(1, r.GetFrame(1)->number); CHECK_EQUAL(2, r.GetFrame(2)->number); CHECK_THROW(r.GetFrame(3)->number, InvalidFile); + + // Clean up + cache.Clear(); + r.Close(); } \ No newline at end of file From bec21b1c7719e50d2a0e97f4fee83997cfa8f2f5 Mon Sep 17 00:00:00 2001 From: Daniel Jour Date: Fri, 12 Jun 2020 22:30:54 +0200 Subject: [PATCH 61/79] Add a note about the buffering behavior of Timeline to DummyReader Using DummyReader with a custom cache with a Timeline can lead to strange exceptions due to Timeline's buffering. Therefore adding a note to the DummyReader documentation about that. --- include/DummyReader.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/DummyReader.h b/include/DummyReader.h index e9c90968..9a75751d 100644 --- a/include/DummyReader.h +++ b/include/DummyReader.h @@ -53,6 +53,12 @@ namespace openshot * A dummy reader can be created with any framerate or samplerate. This is useful in unit * tests that need to test different framerates or samplerates. * + * @note Timeline does buffering by requesting more frames than it + * strictly needs. Thus if you use this DummyReader with a custom + * cache in a Timeline, make sure it has enough + * frames. Specifically you need some frames after the last frame + * you plan to access through the Timeline. + * * @code * // Create cache object to store fake Frame objects * CacheMemory cache; From 4e2c08db88f30a195836998aa62f05b7713c819f Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Mon, 15 Jun 2020 14:02:26 -0700 Subject: [PATCH 62/79] Update src/FFmpegWriter.cpp Thanks for fixing that Co-authored-by: Jonathan Thomas --- src/FFmpegWriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 9b348aed..058b7490 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -1254,7 +1254,7 @@ AVStream *FFmpegWriter::add_video_stream() { } else if (strstr(info.vcodec.c_str(), "aom") != NULL) { // Set number of tiles to a fixed value - // TODO Let user choose number of tiles + // TODO: Allow user to chose their own number of tiles av_opt_set_int(c->priv_data, "tile-rows", 1, 0); // log2 of number of rows av_opt_set_int(c->priv_data, "tile-columns", 2, 0); // log2 of number of columns av_opt_set_int(c->priv_data, "row-mt", 1, 0); // use multiple cores From 91647e6d0b702fecec9e653ef342a220aa6d9935 Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Mon, 15 Jun 2020 14:03:29 -0700 Subject: [PATCH 63/79] Update src/FFmpegWriter.cpp Perfect. I forgot that comment. Co-authored-by: Jonathan Thomas --- src/FFmpegWriter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 058b7490..831db284 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -478,6 +478,7 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va #if (LIBAVCODEC_VERSION_MAJOR >= 58) case AV_CODEC_ID_AV1 : c->bit_rate = 0; + // AV1 only supports "crf" quality values av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0); break; #endif From 2491d402df29ab7a91820acc6239f5477346b12a Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Mon, 15 Jun 2020 14:04:49 -0700 Subject: [PATCH 64/79] Update src/FFmpegWriter.cpp I should take more care of the comments. Co-authored-by: Jonathan Thomas --- src/FFmpegWriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 831db284..7ad2eb17 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -1225,7 +1225,7 @@ AVStream *FFmpegWriter::add_video_stream() { #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 39, 101) #if (LIBAVCODEC_VERSION_MAJOR >= 58) case AV_CODEC_ID_AV1 : - // TODO: + // TODO: Set `crf` or `qp` according to bitrate, as bitrate is not supported by these encoders yet. // set crf or qp according to bitrate as bitrate is not supported by // these encoders (yet) if (info.video_bit_rate >= 1000) { From bf0e700ae7ffb0370cc3f7721cb2e9a18c36c5b6 Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Mon, 15 Jun 2020 14:05:43 -0700 Subject: [PATCH 65/79] Update src/FFmpegWriter.cpp Co-authored-by: Jonathan Thomas --- src/FFmpegWriter.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 7ad2eb17..c35edcb4 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -1226,7 +1226,6 @@ AVStream *FFmpegWriter::add_video_stream() { #if (LIBAVCODEC_VERSION_MAJOR >= 58) case AV_CODEC_ID_AV1 : // TODO: Set `crf` or `qp` according to bitrate, as bitrate is not supported by these encoders yet. - // set crf or qp according to bitrate as bitrate is not supported by // these encoders (yet) if (info.video_bit_rate >= 1000) { c->bit_rate = 0; From c037d5c01df664bb41e22a00571a900c1512fa76 Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Mon, 15 Jun 2020 14:07:09 -0700 Subject: [PATCH 66/79] Update src/FFmpegWriter.cpp We might want to leave some kind of comment though. The encoders will (probably) get these options (soon). Co-authored-by: Jonathan Thomas --- src/FFmpegWriter.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index c35edcb4..291ba848 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -1226,7 +1226,6 @@ AVStream *FFmpegWriter::add_video_stream() { #if (LIBAVCODEC_VERSION_MAJOR >= 58) case AV_CODEC_ID_AV1 : // TODO: Set `crf` or `qp` according to bitrate, as bitrate is not supported by these encoders yet. - // these encoders (yet) if (info.video_bit_rate >= 1000) { c->bit_rate = 0; if (strstr(info.vcodec.c_str(), "aom") != NULL) { From 3dfcea1dd527d63b1c93dd0251a0723f4f88e4b5 Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Mon, 15 Jun 2020 14:33:14 -0700 Subject: [PATCH 67/79] Fix indentation --- src/FFmpegWriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 291ba848..cb1c326d 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -1225,7 +1225,7 @@ AVStream *FFmpegWriter::add_video_stream() { #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 39, 101) #if (LIBAVCODEC_VERSION_MAJOR >= 58) case AV_CODEC_ID_AV1 : - // TODO: Set `crf` or `qp` according to bitrate, as bitrate is not supported by these encoders yet. + // TODO: Set `crf` or `qp` according to bitrate, as bitrate is not supported by these encoders yet. if (info.video_bit_rate >= 1000) { c->bit_rate = 0; if (strstr(info.vcodec.c_str(), "aom") != NULL) { From 056a72fa17fadaa7a263ffbfa0100b02dc210de8 Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Mon, 15 Jun 2020 14:41:38 -0700 Subject: [PATCH 68/79] Fix indentation (2) --- src/FFmpegWriter.cpp | 76 ++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index cb1c326d..741f2f26 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -542,12 +542,12 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va } else if (strstr(info.vcodec.c_str(), "rav1e") != NULL) { // Set number of tiles to a fixed value - // TODO Let user choose number of tiles + // TODO Let user choose number of tiles av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),255), 0); } else if (strstr(info.vcodec.c_str(), "aom") != NULL) { // Set number of tiles to a fixed value - // TODO Let user choose number of tiles + // TODO Let user choose number of tiles // libaom doesn't have qp only crf av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0); } @@ -1207,10 +1207,10 @@ AVStream *FFmpegWriter::add_video_stream() { #endif /* Init video encoder options */ - if (info.video_bit_rate >= 1000 + if (info.video_bit_rate >= 1000 #if (LIBAVCODEC_VERSION_MAJOR >= 58) && c->codec_id != AV_CODEC_ID_AV1 -#endif +#endif ) { c->bit_rate = info.video_bit_rate; if (info.video_bit_rate >= 1500000) { @@ -1226,40 +1226,40 @@ AVStream *FFmpegWriter::add_video_stream() { #if (LIBAVCODEC_VERSION_MAJOR >= 58) case AV_CODEC_ID_AV1 : // TODO: Set `crf` or `qp` according to bitrate, as bitrate is not supported by these encoders yet. - if (info.video_bit_rate >= 1000) { - c->bit_rate = 0; - if (strstr(info.vcodec.c_str(), "aom") != NULL) { - int calculated_quality = 35; - if (info.video_bit_rate < 500000) calculated_quality = 50; - if (info.video_bit_rate > 5000000) calculated_quality = 10; - av_opt_set_int(c->priv_data, "crf", calculated_quality, 0); - info.video_bit_rate = calculated_quality; - } else { - int calculated_quality = 50; - if (info.video_bit_rate < 500000) calculated_quality = 60; - if (info.video_bit_rate > 5000000) calculated_quality = 15; - av_opt_set_int(c->priv_data, "qp", calculated_quality, 0); - info.video_bit_rate = calculated_quality; - } // medium - } - if (strstr(info.vcodec.c_str(), "svt_av1") != NULL) { - av_opt_set_int(c->priv_data, "preset", 6, 0); - av_opt_set_int(c->priv_data, "forced-idr",1,0); - } - else if (strstr(info.vcodec.c_str(), "rav1e") != NULL) { - av_opt_set_int(c->priv_data, "speed", 7, 0); - av_opt_set_int(c->priv_data, "tile-rows", 2, 0); - av_opt_set_int(c->priv_data, "tile-columns", 4, 0); - } - else if (strstr(info.vcodec.c_str(), "aom") != NULL) { - // Set number of tiles to a fixed value - // TODO: Allow user to chose their own number of tiles - av_opt_set_int(c->priv_data, "tile-rows", 1, 0); // log2 of number of rows - av_opt_set_int(c->priv_data, "tile-columns", 2, 0); // log2 of number of columns - av_opt_set_int(c->priv_data, "row-mt", 1, 0); // use multiple cores - av_opt_set_int(c->priv_data, "cpu-used", 3, 0); // default is 1, usable is 4 - } - //break; + if (info.video_bit_rate >= 1000) { + c->bit_rate = 0; + if (strstr(info.vcodec.c_str(), "aom") != NULL) { + int calculated_quality = 35; + if (info.video_bit_rate < 500000) calculated_quality = 50; + if (info.video_bit_rate > 5000000) calculated_quality = 10; + av_opt_set_int(c->priv_data, "crf", calculated_quality, 0); + info.video_bit_rate = calculated_quality; + } else { + int calculated_quality = 50; + if (info.video_bit_rate < 500000) calculated_quality = 60; + if (info.video_bit_rate > 5000000) calculated_quality = 15; + av_opt_set_int(c->priv_data, "qp", calculated_quality, 0); + info.video_bit_rate = calculated_quality; + } // medium + } + if (strstr(info.vcodec.c_str(), "svt_av1") != NULL) { + av_opt_set_int(c->priv_data, "preset", 6, 0); + av_opt_set_int(c->priv_data, "forced-idr",1,0); + } + else if (strstr(info.vcodec.c_str(), "rav1e") != NULL) { + av_opt_set_int(c->priv_data, "speed", 7, 0); + av_opt_set_int(c->priv_data, "tile-rows", 2, 0); + av_opt_set_int(c->priv_data, "tile-columns", 4, 0); + } + else if (strstr(info.vcodec.c_str(), "aom") != NULL) { + // Set number of tiles to a fixed value + // TODO: Allow user to chose their own number of tiles + av_opt_set_int(c->priv_data, "tile-rows", 1, 0); // log2 of number of rows + av_opt_set_int(c->priv_data, "tile-columns", 2, 0); // log2 of number of columns + av_opt_set_int(c->priv_data, "row-mt", 1, 0); // use multiple cores + av_opt_set_int(c->priv_data, "cpu-used", 3, 0); // default is 1, usable is 4 + } + //break; #endif case AV_CODEC_ID_VP9 : case AV_CODEC_ID_HEVC : From 001b2d8a71d5d6fa85c5f03c775b016e196fccd3 Mon Sep 17 00:00:00 2001 From: Frank Dana Date: Thu, 18 Jun 2020 05:47:40 -0400 Subject: [PATCH 69/79] MagickUtils: Add #pragma to silence IM6 warning --- include/MagickUtilities.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/MagickUtilities.h b/include/MagickUtilities.h index 74365904..953b85ee 100644 --- a/include/MagickUtilities.h +++ b/include/MagickUtilities.h @@ -32,7 +32,11 @@ #ifdef USE_IMAGEMAGICK +// Exclude a warning message with IM6 headers +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wignored-qualifiers" #include "Magick++.h" +#pragma GCC diagnostic pop // Determine ImageMagick version, as IM7 isn't fully // backwards compatible From 3157d757477edfc14f226a1e3ce430a97176e2d6 Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Thu, 2 Jul 2020 16:54:32 -0700 Subject: [PATCH 70/79] Leave the values for qmin and qmax at their default values except for mpeg2. Changing them for the other codecs resultet in exporting with the wrong bitrate. --- src/FFmpegWriter.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index d960d677..d8695501 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -1202,8 +1202,10 @@ AVStream *FFmpegWriter::add_video_stream() { ) { c->bit_rate = info.video_bit_rate; if (info.video_bit_rate >= 1500000) { - c->qmin = 2; - c->qmax = 30; + if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) { + c->qmin = 3; + c->qmax = 30; + } } // Here should be the setting for low fixed bitrate // Defaults are used because mpeg2 otherwise had problems From accc5a8deb42bcac4ae3caced2bc98a9971f00b6 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Sun, 5 Jul 2020 20:45:41 -0500 Subject: [PATCH 71/79] Updating to gcc 8.4 for MacOS Catalina --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 925bf020..2b8d8299 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -43,7 +43,7 @@ mac-builder: - unzip artifacts.zip - export LIBOPENSHOT_AUDIO_DIR=$CI_PROJECT_DIR/build/install-x64 - mkdir -p build; cd build; - - 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_MODULE_PATH=python -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" ../ + - cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -D"CMAKE_INSTALL_PREFIX:PATH=$CI_PROJECT_DIR/build/install-x64" -DCMAKE_CXX_COMPILER=/usr/local/opt/gcc@8/bin/g++-8 -DCMAKE_C_COMPILER=/usr/local/opt/gcc@8/bin/gcc-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_MODULE_PATH=python -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 - echo -e "CI_PROJECT_NAME:$CI_PROJECT_NAME\nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME\nCI_COMMIT_SHA:$CI_COMMIT_SHA\nCI_JOB_ID:$CI_JOB_ID" > "install-x64/share/$CI_PROJECT_NAME" From 7b322a0948d277749f259ef730835617918bc39c Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Sun, 5 Jul 2020 20:51:18 -0500 Subject: [PATCH 72/79] Making CMake Threads not required. --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 17b73863..f0b0524f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -303,7 +303,7 @@ endforeach() # Threading library -- uses IMPORTED target Threads::Threads (since CMake 3.1) set(CMAKE_THREAD_PREFER_PTHREAD TRUE) set(THREADS_PREFER_PTHREAD_FLAG TRUE) -find_package(Threads REQUIRED) +find_package(Threads) target_link_libraries(openshot PUBLIC Threads::Threads) ################### OPENMP ##################### From bfefe501d0d5a2982172c852bdb2e97a6821b009 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Sun, 5 Jul 2020 21:09:31 -0500 Subject: [PATCH 73/79] Experimenting with Cmake and Threads failure --- src/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f0b0524f..cd2fe142 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -303,8 +303,8 @@ endforeach() # Threading library -- uses IMPORTED target Threads::Threads (since CMake 3.1) set(CMAKE_THREAD_PREFER_PTHREAD TRUE) set(THREADS_PREFER_PTHREAD_FLAG TRUE) -find_package(Threads) -target_link_libraries(openshot PUBLIC Threads::Threads) +#find_package(Threads REQUIRED) +#target_link_libraries(openshot PUBLIC Threads::Threads) ################### OPENMP ##################### # Check for OpenMP (used for multi-core processing) @@ -317,7 +317,7 @@ if(NOT TARGET OpenMP::OpenMP_CXX) add_library(OpenMP_TARGET INTERFACE) add_library(OpenMP::OpenMP_CXX ALIAS OpenMP_TARGET) target_compile_options(OpenMP_TARGET INTERFACE ${OpenMP_CXX_FLAGS}) - target_link_libraries(OpenMP_TARGET INTERFACE Threads::Threads) + #target_link_libraries(OpenMP_TARGET INTERFACE Threads::Threads) target_link_libraries(OpenMP_TARGET INTERFACE ${OpenMP_CXX_FLAGS}) endif() From d2dd3d3e3f21f248043701ed275120afbdcad338 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Sun, 5 Jul 2020 21:46:40 -0500 Subject: [PATCH 74/79] Experimenting with new include folder, since Catalina doesn't have a /usr/include/ --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2b8d8299..1835040c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -43,7 +43,7 @@ mac-builder: - unzip artifacts.zip - export LIBOPENSHOT_AUDIO_DIR=$CI_PROJECT_DIR/build/install-x64 - mkdir -p build; cd build; - - cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -D"CMAKE_INSTALL_PREFIX:PATH=$CI_PROJECT_DIR/build/install-x64" -DCMAKE_CXX_COMPILER=/usr/local/opt/gcc@8/bin/g++-8 -DCMAKE_C_COMPILER=/usr/local/opt/gcc@8/bin/gcc-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_MODULE_PATH=python -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" ../ + - cmake -DCMAKE_CXX_FLAGS=-I\ /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -D"CMAKE_INSTALL_PREFIX:PATH=$CI_PROJECT_DIR/build/install-x64" -DCMAKE_CXX_COMPILER=/usr/local/opt/gcc@8/bin/g++-8 -DCMAKE_C_COMPILER=/usr/local/opt/gcc@8/bin/gcc-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_MODULE_PATH=python -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 - echo -e "CI_PROJECT_NAME:$CI_PROJECT_NAME\nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME\nCI_COMMIT_SHA:$CI_COMMIT_SHA\nCI_JOB_ID:$CI_JOB_ID" > "install-x64/share/$CI_PROJECT_NAME" From b7dd86e63a579c21c2325ceb79fd797312699236 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Mon, 6 Jul 2020 02:10:35 -0500 Subject: [PATCH 75/79] Experimental ABI fix to deal with '__cxx11' --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cd2fe142..ba485e74 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -41,8 +41,8 @@ if (APPLE) # If you still get errors compiling with GCC 4.8, mac headers need to be patched: http://hamelot.co.uk/programming/osx-gcc-dispatch_block_t-has-not-been-declared-invalid-typedef/ set_property(GLOBAL PROPERTY JUCE_MAC "JUCE_MAC") add_definitions(-DNDEBUG) + add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0) set(EXTENSION "mm") - set(JUCE_PLATFORM_SPECIFIC_DIR build/macosx/platform_specific_code) set(JUCE_PLATFORM_SPECIFIC_LIBRARIES "-framework Carbon -framework Cocoa -framework CoreFoundation -framework CoreAudio -framework CoreMidi -framework IOKit -framework AGL -framework AudioToolbox -framework QuartzCore -lobjc -framework Accelerate") endif() From 6e6b60fa22f774a0717423893b798ba1cf6be8c3 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Mon, 6 Jul 2020 02:33:26 -0500 Subject: [PATCH 76/79] Experimental ABI fix to deal with '__cxx11' (take 2) --- src/CMakeLists.txt | 3 +++ tests/CMakeLists.txt | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ba485e74..50143a6f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -45,6 +45,9 @@ if (APPLE) set(EXTENSION "mm") set(JUCE_PLATFORM_SPECIFIC_DIR build/macosx/platform_specific_code) set(JUCE_PLATFORM_SPECIFIC_LIBRARIES "-framework Carbon -framework Cocoa -framework CoreFoundation -framework CoreAudio -framework CoreMidi -framework IOKit -framework AGL -framework AudioToolbox -framework QuartzCore -lobjc -framework Accelerate") + + # Prevent compiling with __cxx11 + add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0) endif() ################ IMAGE MAGICK ################## diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7ccddba8..f75d8ab1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -36,6 +36,11 @@ if(WIN32) set(CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS} -include cmath") endif() +if (APPLE) + # Prevent compiling with __cxx11 + add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0) +endif() + ################### UNITTEST++ ##################### # Find UnitTest++ libraries (used for unit testing) find_package(UnitTest++) From aac43ec038b93496a4fc4ab4457259b6422cb62a Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Tue, 7 Jul 2020 02:34:11 -0500 Subject: [PATCH 77/79] Removing commented out code --- src/CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 50143a6f..6b9dd8ee 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -41,7 +41,6 @@ if (APPLE) # If you still get errors compiling with GCC 4.8, mac headers need to be patched: http://hamelot.co.uk/programming/osx-gcc-dispatch_block_t-has-not-been-declared-invalid-typedef/ set_property(GLOBAL PROPERTY JUCE_MAC "JUCE_MAC") add_definitions(-DNDEBUG) - add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0) set(EXTENSION "mm") set(JUCE_PLATFORM_SPECIFIC_DIR build/macosx/platform_specific_code) set(JUCE_PLATFORM_SPECIFIC_LIBRARIES "-framework Carbon -framework Cocoa -framework CoreFoundation -framework CoreAudio -framework CoreMidi -framework IOKit -framework AGL -framework AudioToolbox -framework QuartzCore -lobjc -framework Accelerate") @@ -306,8 +305,6 @@ endforeach() # Threading library -- uses IMPORTED target Threads::Threads (since CMake 3.1) set(CMAKE_THREAD_PREFER_PTHREAD TRUE) set(THREADS_PREFER_PTHREAD_FLAG TRUE) -#find_package(Threads REQUIRED) -#target_link_libraries(openshot PUBLIC Threads::Threads) ################### OPENMP ##################### # Check for OpenMP (used for multi-core processing) @@ -320,7 +317,6 @@ if(NOT TARGET OpenMP::OpenMP_CXX) add_library(OpenMP_TARGET INTERFACE) add_library(OpenMP::OpenMP_CXX ALIAS OpenMP_TARGET) target_compile_options(OpenMP_TARGET INTERFACE ${OpenMP_CXX_FLAGS}) - #target_link_libraries(OpenMP_TARGET INTERFACE Threads::Threads) target_link_libraries(OpenMP_TARGET INTERFACE ${OpenMP_CXX_FLAGS}) endif() From 9ef8f8478eca5b128c7bf7e6946c134e1ed82762 Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Tue, 7 Jul 2020 10:14:02 -0700 Subject: [PATCH 78/79] Formating --- src/FFmpegWriter.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index d8695501..e737462f 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -1202,10 +1202,10 @@ AVStream *FFmpegWriter::add_video_stream() { ) { c->bit_rate = info.video_bit_rate; if (info.video_bit_rate >= 1500000) { - if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) { - c->qmin = 3; - c->qmax = 30; - } + if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) { + c->qmin = 3; + c->qmax = 30; + } } // Here should be the setting for low fixed bitrate // Defaults are used because mpeg2 otherwise had problems From 6114be5e0ff9fbdd5ab439dbe98840a97afb8d7d Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Tue, 7 Jul 2020 10:20:48 -0700 Subject: [PATCH 79/79] Fixed typo --- src/FFmpegWriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index e737462f..158ef662 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -1203,7 +1203,7 @@ AVStream *FFmpegWriter::add_video_stream() { c->bit_rate = info.video_bit_rate; if (info.video_bit_rate >= 1500000) { if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) { - c->qmin = 3; + c->qmin = 2; c->qmax = 30; } }