diff --git a/.cproject b/.cproject deleted file mode 100644 index 1028fe17..00000000 --- a/.cproject +++ /dev/null @@ -1,405 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cmake - -G "Unix Makefiles" ../ -D"CMAKE_BUILD_TYPE:STRING=Release" - true - false - true - - - cmake - -G "Unix Makefiles" ../ -D"MAGICKCORE_HDRI_ENABLE=0" -D"MAGICKCORE_QUANTUM_DEPTH=16" -D"OPENSHOT_IMAGEMAGICK_COMPATIBILITY=0" -D"ENABLE_BLACKMAGIC=1" -D"CMAKE_BUILD_TYPE:STRING=Debug" -D"DISABLE_TESTS=0" - - true - false - true - - - make - test - true - false - true - - - make - help - true - false - true - - - make - doc - true - false - true - - - cmake - -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/Cellar/qt5/5.1.1/ -DPYTHON_INCLUDE_DIR=/usr/local/Cellar/python3/3.3.2/Frameworks/Python.framework/Versions/3.3/include/python3.3m/ -DPYTHON_LIBRARY=/usr/local/Cellar/python3/3.3.2/Frameworks/Python.framework/Versions/3.3/lib/libpython3.3.dylib -DPython_FRAMEWORKS=/usr/local/Cellar/python3/3.3.2/Frameworks/Python.framework/ ../ -D"CMAKE_BUILD_TYPE:STRING=Debug" - true - false - true - - - cmake - -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/Cellar/qt5/5.1.1/ -DPYTHON_INCLUDE_DIR=/usr/local/Cellar/python3/3.3.2/Frameworks/Python.framework/Versions/3.3/include/python3.3m/ -DPYTHON_LIBRARY=/usr/local/Cellar/python3/3.3.2/Frameworks/Python.framework/Versions/3.3/lib/libpython3.3.dylib -DPython_FRAMEWORKS=/usr/local/Cellar/python3/3.3.2/Frameworks/Python.framework/ ../ -D"CMAKE_BUILD_TYPE:STRING=Release" - true - false - true - - - cmake - -G "MinGW Makefiles" ../ -D"CMAKE_BUILD_TYPE:STRING=Debug" - true - false - true - - - cmake - -G "MinGW Makefiles" ../ -D"CMAKE_BUILD_TYPE:STRING=Release" - true - false - true - - - - diff --git a/.gitignore b/.gitignore index e7f24925..a11656cf 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,7 @@ build/* *.DS_Store .pydevproject .settings -.idea/* \ No newline at end of file +.idea/* +.project +.cproject +/.metadata/ diff --git a/.project b/.project deleted file mode 100644 index 5e324854..00000000 --- a/.project +++ /dev/null @@ -1,94 +0,0 @@ - - - libopenshot - - - - - - com.aptana.ide.core.unifiedBuilder - - - - - org.python.pydev.PyDevBuilder - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - ?name? - - - - org.eclipse.cdt.make.core.append_environment - true - - - org.eclipse.cdt.make.core.autoBuildTarget - all - - - org.eclipse.cdt.make.core.buildArguments - - - - org.eclipse.cdt.make.core.buildCommand - make - - - org.eclipse.cdt.make.core.buildLocation - ${workspace_loc:/libopenshot/build} - - - org.eclipse.cdt.make.core.cleanBuildTarget - clean - - - org.eclipse.cdt.make.core.contents - org.eclipse.cdt.make.core.activeConfigSettings - - - org.eclipse.cdt.make.core.enableAutoBuild - false - - - org.eclipse.cdt.make.core.enableCleanBuild - true - - - org.eclipse.cdt.make.core.enableFullBuild - true - - - org.eclipse.cdt.make.core.fullBuildTarget - all - - - org.eclipse.cdt.make.core.stopOnError - true - - - org.eclipse.cdt.make.core.useDefaultBuildCmd - true - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - org.python.pydev.pythonNature - com.aptana.ruby.core.rubynature - - diff --git a/README b/README deleted file mode 100644 index 8c05f753..00000000 --- a/README +++ /dev/null @@ -1,66 +0,0 @@ -#################################################################### - OpenShot Library -#################################################################### - -OpenShot Library (libopenshot) is an open-source project dedicated to -delivering high quality video editing, animation, and playback solutions -to the world. For more information visit . - -#################################################################### - License -#################################################################### - -Copyright (c) 2008-2014 OpenShot Studios, LLC -. - -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 . - -#################################################################### - - To release a closed-source product which uses libopenshot (i.e. video - editing and playback), commercial licenses are available: contact - sales@openshot.org for more information. - - -#################################################################### - Install -#################################################################### - -Please see /doc/InstallationGuide.pdf for a very detailed -Linux, Mac, and Windows compiling instruction guide. An online version -is also available: -https://docs.google.com/document/d/1V6nq-IuS9zxqO1-OSt8iTS_cw_HMCpsUNofHLYtUNjM/pub - - -#################################################################### - Documentation -#################################################################### - -Documentation is auto-generated by Doxygen, and can be created with -$ make doc (Also available online: ) - - -#################################################################### - Authors -#################################################################### - -Please see AUTHORS file for a full list of authors. - - -#################################################################### - www.openshot.org | www.openshotstudios.com -#################################################################### - - Copyright (c) 2008-2014 OpenShot Studios, LLC - . diff --git a/README.md b/README.md new file mode 100644 index 00000000..1baf3cb4 --- /dev/null +++ b/README.md @@ -0,0 +1,60 @@ +# OpenShot Library + +OpenShot Library (libopenshot) is an open-source project dedicated to +delivering high quality video editing, animation, and playback solutions +to the world. For more information visit [http://www.openshot.org/](http://www.openshot.org/). + +### License + +Copyright (c) 2008-2019 OpenShot Studios, LLC +[http://www.openshotstudios.com/](http://www.openshotstudios.com/). + +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 [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/). + +--- +To release a closed-source product which uses libopenshot (i.e. video +editing and playback), commercial licenses are available: contact +sales@openshot.org for more information. + +--- + +### Install + +Please see /doc/InstallationGuide.pdf for a very detailed +Linux, Mac, and Windows compiling instruction guide. An online version +is also available: +[https://docs.google.com/document/d/1V6nq-IuS9zxqO1-OSt8iTS_cw_HMCpsUNofHLYtUNjM/pub](https://docs.google.com/document/d/1V6nq-IuS9zxqO1-OSt8iTS_cw_HMCpsUNofHLYtUNjM/pub) + + +### Documentation + +Documentation is auto-generated by Doxygen, and can be created with +``` +make doc +``` +(Also available online: [http://openshot.org/files/libopenshot/](http://openshot.org/files/libopenshot/)) + + +### Authors + +Please see AUTHORS file for a full list of authors. + + +--- +[www.openshot.org](http://www.openshot.org) | [www.openshotstudios.com](http://www.openshotstudios.com) + +--- +Copyright (c) 2008-2019 OpenShot Studios, LLC + +[www.openshotstudios.com](http://www.openshotstudios.com). diff --git a/include/FFmpegReader.h b/include/FFmpegReader.h index 62437d7a..c1360705 100644 --- a/include/FFmpegReader.h +++ b/include/FFmpegReader.h @@ -44,6 +44,7 @@ #include "CacheMemory.h" #include "Exceptions.h" #include "OpenMPUtilities.h" +#include "Settings.h" using namespace std; @@ -108,7 +109,6 @@ namespace openshot bool check_interlace; bool check_fps; bool has_missing_frames; - bool use_omp_threads; CacheMemory working_cache; CacheMemory missing_frames; diff --git a/include/FFmpegUtilities.h b/include/FFmpegUtilities.h index 0cc08f52..e45dfe68 100644 --- a/include/FFmpegUtilities.h +++ b/include/FFmpegUtilities.h @@ -144,7 +144,7 @@ #define AV_ALLOCATE_FRAME() av_frame_alloc() #define AV_ALLOCATE_IMAGE(av_frame, pix_fmt, width, height) av_image_alloc(av_frame->data, av_frame->linesize, width, height, pix_fmt, 1) #define AV_RESET_FRAME(av_frame) av_frame_unref(av_frame) - #define AV_FREE_FRAME(av_frame) av_frame_free(av_frame) + #define AV_FREE_FRAME(av_frame) if (av_frame) av_frame_free(av_frame) #define AV_FREE_PACKET(av_packet) av_packet_unref(av_packet) #define AV_FREE_CONTEXT(av_context) avcodec_free_context(&av_context) #define AV_GET_CODEC_TYPE(av_stream) av_stream->codecpar->codec_type @@ -179,7 +179,7 @@ #define AV_ALLOCATE_FRAME() av_frame_alloc() #define AV_ALLOCATE_IMAGE(av_frame, pix_fmt, width, height) av_image_alloc(av_frame->data, av_frame->linesize, width, height, pix_fmt, 1) #define AV_RESET_FRAME(av_frame) av_frame_unref(av_frame) - #define AV_FREE_FRAME(av_frame) av_frame_free(av_frame) + #define AV_FREE_FRAME(av_frame) if(av_frame) av_frame_free(av_frame) #define AV_FREE_PACKET(av_packet) av_packet_unref(av_packet) #define AV_FREE_CONTEXT(av_context) avcodec_free_context(&av_context) #define AV_GET_CODEC_TYPE(av_stream) av_stream->codecpar->codec_type @@ -214,7 +214,7 @@ #define AV_ALLOCATE_FRAME() av_frame_alloc() #define AV_ALLOCATE_IMAGE(av_frame, pix_fmt, width, height) avpicture_alloc((AVPicture *) av_frame, pix_fmt, width, height) #define AV_RESET_FRAME(av_frame) av_frame_unref(av_frame) - #define AV_FREE_FRAME(av_frame) av_frame_free(av_frame) + #define AV_FREE_FRAME(av_frame) if (av_frame) av_frame_free(av_frame) #define AV_FREE_PACKET(av_packet) av_packet_unref(av_packet) #define AV_FREE_CONTEXT(av_context) avcodec_close(av_context) #define AV_GET_CODEC_TYPE(av_stream) av_stream->codec->codec_type @@ -244,7 +244,7 @@ #define AV_ALLOCATE_FRAME() avcodec_alloc_frame() #define AV_ALLOCATE_IMAGE(av_frame, pix_fmt, width, height) avpicture_alloc((AVPicture *) av_frame, pix_fmt, width, height) #define AV_RESET_FRAME(av_frame) avcodec_get_frame_defaults(av_frame) - #define AV_FREE_FRAME(av_frame) avcodec_free_frame(av_frame) + #define AV_FREE_FRAME(av_frame) if(av_frame) avcodec_free_frame(av_frame) #define AV_FREE_PACKET(av_packet) av_free_packet(av_packet) #define AV_FREE_CONTEXT(av_context) avcodec_close(av_context) #define AV_GET_CODEC_TYPE(av_stream) av_stream->codec->codec_type diff --git a/include/FFmpegWriter.h b/include/FFmpegWriter.h index 7eefacb7..e219f72c 100644 --- a/include/FFmpegWriter.h +++ b/include/FFmpegWriter.h @@ -51,6 +51,7 @@ #include "Exceptions.h" #include "OpenMPUtilities.h" #include "ZmqLogger.h" +#include "Settings.h" using namespace std; diff --git a/include/OpenMPUtilities.h b/include/OpenMPUtilities.h index 6ebde218..9af58150 100644 --- a/include/OpenMPUtilities.h +++ b/include/OpenMPUtilities.h @@ -36,20 +36,6 @@ #define OPEN_MP_NUM_PROCESSORS ((getenv( "LIMIT_OMP_THREADS" )==NULL) ? omp_get_num_procs() : (min(omp_get_num_procs(), max(2, atoi(getenv( "LIMIT_OMP_THREADS" ))) ))) #define FF_NUM_PROCESSORS ((getenv( "LIMIT_FF_THREADS" )==NULL) ? omp_get_num_procs() : (min(omp_get_num_procs(), max(2, atoi(getenv( "LIMIT_FF_THREADS" ))) ))) -using namespace std; -namespace openshot { - - // Check if OS2_OMP_THREADS environment variable is present, and return - // if multiple threads should be used with OMP - static bool IsOMPEnabled() { - char* OS2_OMP_THREADS = getenv("OS2_OMP_THREADS"); - if (OS2_OMP_THREADS != NULL && strcmp(OS2_OMP_THREADS, "0") == 0) - return false; - else - return true; - } - -} #endif diff --git a/include/OpenShot.h b/include/OpenShot.h index e4b60f3e..207f4b42 100644 --- a/include/OpenShot.h +++ b/include/OpenShot.h @@ -134,5 +134,6 @@ #include "Profiles.h" #include "QtImageReader.h" #include "Timeline.h" +#include "Settings.h" #endif diff --git a/include/Settings.h b/include/Settings.h new file mode 100644 index 00000000..6a7940eb --- /dev/null +++ b/include/Settings.h @@ -0,0 +1,97 @@ +/** + * @file + * @brief Header file for global Settings class + * @author Jonathan Thomas + * + * @section LICENSE + * + * Copyright (c) 2008-2014 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 . + */ + +#ifndef OPENSHOT_SETTINGS_H +#define OPENSHOT_SETTINGS_H + + +#include "JuceLibraryCode/JuceHeader.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace std; + +namespace openshot { + + /** + * @brief This class is contains settings used by libopenshot (and can be safely toggled at any point) + * + * Settings class is used primarily to toggle scale settings between preview and rendering, and adjust + * other runtime related settings. + */ + class Settings { + private: + + /// Default constructor + Settings(){}; // Don't allow user to create an instance of this singleton + +#if __GNUC__ >=7 + /// Default copy method + Settings(Settings const&) = delete; // Don't allow the user to assign this instance + + /// Default assignment operator + Settings & operator=(Settings const&) = delete; // Don't allow the user to assign this instance +#else + /// Default copy method + Settings(Settings const&) {}; // Don't allow the user to assign this instance + + /// Default assignment operator + Settings & operator=(Settings const&); // Don't allow the user to assign this instance +#endif + + /// Private variable to keep track of singleton instance + static Settings * m_pInstance; + + public: + /// Use video card for faster video decoding (if supported) + bool HARDWARE_DECODE = false; + + /// Use video card for faster video encoding (if supported) + bool HARDWARE_ENCODE = false; + + /// Scale mode used in FFmpeg decoding and encoding (used as an optimization for faster previews) + bool HIGH_QUALITY_SCALING = false; + + /// Wait for OpenMP task to finish before continuing (used to limit threads on slower systems) + bool WAIT_FOR_VIDEO_PROCESSING_TASK = false; + + /// Create or get an instance of this logger singleton (invoke the class with this method) + static Settings * Instance(); + }; + +} + +#endif diff --git a/include/ZmqLogger.h b/include/ZmqLogger.h index e825ed0e..62773e68 100644 --- a/include/ZmqLogger.h +++ b/include/ZmqLogger.h @@ -47,11 +47,10 @@ using namespace std; namespace openshot { /** - * @brief This abstract class is the base class, used by all readers in libopenshot. + * @brief This class is used for logging and sending those logs over a ZemoMQ socket to a listener * - * Readers are types of classes that read video, audio, and image files, and - * return openshot::Frame objects. The only requirements for a 'reader', are to - * derive from this base class, implement the GetFrame method, and call the InitFileInfo() method. + * OpenShot desktop editor listens to this port, to receive libopenshot debug output. It both logs to + * a file and sends the stdout over a socket. */ class ZmqLogger { private: diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d71067a3..7752df15 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -244,6 +244,7 @@ SET ( OPENSHOT_SOURCE_FILES Profiles.cpp QtImageReader.cpp QtPlayer.cpp + Settings.cpp Timeline.cpp # Qt Video Player diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index 859f4cf6..d5a05b89 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -88,7 +88,7 @@ FFmpegReader::FFmpegReader(string path) check_fps(false), enable_seek(true), is_open(false), seek_audio_frame_found(0), seek_video_frame_found(0), prev_samples(0), prev_pts(0), pts_total(0), pts_counter(0), is_duration_known(false), largest_frame_processed(0), current_video_frame(0), has_missing_frames(false), num_packets_since_video_frame(0), num_checks_since_final(0), - packet(NULL), use_omp_threads(true) { + packet(NULL) { // Initialize FFMpeg, and register all formats and codecs AV_REGISTER_ALL @@ -110,7 +110,7 @@ FFmpegReader::FFmpegReader(string path, bool inspect_reader) check_fps(false), enable_seek(true), is_open(false), seek_audio_frame_found(0), seek_video_frame_found(0), prev_samples(0), prev_pts(0), pts_total(0), pts_counter(0), is_duration_known(false), largest_frame_processed(0), current_video_frame(0), has_missing_frames(false), num_packets_since_video_frame(0), num_checks_since_final(0), - packet(NULL), use_omp_threads(true) { + packet(NULL) { // Initialize FFMpeg, and register all formats and codecs AV_REGISTER_ALL @@ -633,9 +633,6 @@ void FFmpegReader::Open() missing_frames.SetMaxBytesFromInfo(OPEN_MP_NUM_PROCESSORS * 2, info.width, info.height, info.sample_rate, info.channels); final_cache.SetMaxBytesFromInfo(OPEN_MP_NUM_PROCESSORS * 2, info.width, info.height, info.sample_rate, info.channels); - // Initialize OMP threading support - use_omp_threads = openshot::IsOMPEnabled(); - // Mark as "open" is_open = true; } @@ -1025,7 +1022,7 @@ std::shared_ptr FFmpegReader::ReadStream(int64_t requested_frame) // Process Video Packet ProcessVideoPacket(requested_frame); - if (!use_omp_threads) { + if (openshot::Settings::Instance()->WAIT_FOR_VIDEO_PROCESSING_TASK) { // Wait on each OMP task to complete before moving on to the next one. This slows // down processing considerably, but might be more stable on some systems. #pragma omp taskwait @@ -1040,16 +1037,16 @@ std::shared_ptr FFmpegReader::ReadStream(int64_t requested_frame) num_packets_since_video_frame++; // Check the status of a seek (if any) - if (is_seeking) - #pragma omp critical (openshot_seek) - check_seek = CheckSeek(false); - else - check_seek = false; + if (is_seeking) + #pragma omp critical (openshot_seek) + check_seek = CheckSeek(false); + else + check_seek = false; - if (check_seek) { - // Jump to the next iteration of this loop - continue; - } + if (check_seek) { + // Jump to the next iteration of this loop + continue; + } // Update PTS / Frame Offset (if any) UpdatePTSOffset(false); @@ -1371,8 +1368,12 @@ void FFmpegReader::ProcessVideoPacket(int64_t requested_frame) // Copy picture data from one AVFrame (or AVPicture) to another one. AV_COPY_PICTURE_DATA(pFrameRGB, buffer, PIX_FMT_RGBA, width, height); + int scale_mode = SWS_FAST_BILINEAR; + if (openshot::Settings::Instance()->HIGH_QUALITY_SCALING) { + scale_mode = SWS_LANCZOS; + } SwsContext *img_convert_ctx = sws_getContext(info.width, info.height, AV_GET_CODEC_PIXEL_FORMAT(pStream, pCodecCtx), width, - height, PIX_FMT_RGBA, SWS_LANCZOS, NULL, NULL, NULL); + height, PIX_FMT_RGBA, scale_mode, NULL, NULL, NULL); // Resize / Convert to RGB sws_scale(img_convert_ctx, my_frame->data, my_frame->linesize, 0, @@ -2426,7 +2427,7 @@ void FFmpegReader::RemoveAVFrame(AVFrame* remove_frame) { // Free memory av_freep(&remove_frame->data[0]); - AV_FREE_FRAME(&remove_frame); + AV_FREE_FRAME(&remove_frame); } } diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 8e29dc59..5cba9982 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -1615,8 +1615,8 @@ void FFmpegWriter::write_audio_packets(bool final) } else { // Create a new array - //final_samples = new int16_t[audio_input_position * (av_get_bytes_per_sample(audio_codec->sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16))]; - final_samples = (int16_t*)av_malloc(sizeof(int16_t) * audio_input_position * (av_get_bytes_per_sample(audio_codec->sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16))); + final_samples = (int16_t*)av_malloc(sizeof(int16_t) * audio_input_position * (av_get_bytes_per_sample(audio_codec->sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16))); + // Copy audio into buffer for frame memcpy(final_samples, samples, audio_input_position * av_get_bytes_per_sample(audio_codec->sample_fmt)); @@ -2030,6 +2030,11 @@ void FFmpegWriter::OutputStreamInfo() // Init a collection of software rescalers (thread safe) void FFmpegWriter::InitScalers(int source_width, int source_height) { + int scale_mode = SWS_FAST_BILINEAR; + if (openshot::Settings::Instance()->HIGH_QUALITY_SCALING) { + scale_mode = SWS_LANCZOS; + } + // Init software rescalers vector (many of them, one for each thread) for (int x = 0; x < num_of_rescalers; x++) { diff --git a/src/Qt/PlayerPrivate.cpp b/src/Qt/PlayerPrivate.cpp index 63d20e99..1839f1eb 100644 --- a/src/Qt/PlayerPrivate.cpp +++ b/src/Qt/PlayerPrivate.cpp @@ -149,7 +149,7 @@ namespace openshot else { // Update cache on which frame was retrieved - videoCache->current_display_frame = video_position; + videoCache->setCurrentFramePosition(video_position); // return frame from reader return reader->GetFrame(video_position); diff --git a/src/Qt/VideoCacheThread.cpp b/src/Qt/VideoCacheThread.cpp index ed224de5..208fcaab 100644 --- a/src/Qt/VideoCacheThread.cpp +++ b/src/Qt/VideoCacheThread.cpp @@ -102,6 +102,12 @@ namespace openshot // Ignore out of bounds frame exceptions } + // Is cache position behind current display frame? + if (position < current_display_frame) { + // Jump ahead + position = current_display_frame; + } + // Increment frame number position++; } diff --git a/src/Settings.cpp b/src/Settings.cpp new file mode 100644 index 00000000..e6749d5c --- /dev/null +++ b/src/Settings.cpp @@ -0,0 +1,50 @@ +/** + * @file + * @brief Source file for global Settings class + * @author Jonathan Thomas + * + * @section LICENSE + * + * Copyright (c) 2008-2014 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 "../include/Settings.h" + +using namespace std; +using namespace openshot; + + +// Global reference to logger +Settings *Settings::m_pInstance = NULL; + +// Create or Get an instance of the logger singleton +Settings *Settings::Instance() +{ + if (!m_pInstance) { + // Create the actual instance of logger only once + m_pInstance = new Settings; + m_pInstance->HARDWARE_DECODE = false; + m_pInstance->HARDWARE_ENCODE = false; + m_pInstance->HIGH_QUALITY_SCALING = false; + m_pInstance->WAIT_FOR_VIDEO_PROCESSING_TASK = false; + } + + return m_pInstance; +} diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 19ae8a6f..7a34da0e 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -388,35 +388,48 @@ void Timeline::add_layer(std::shared_ptr new_frame, Clip* source_clip, in QSize source_size = source_image->size(); switch (source_clip->scale) { - case (SCALE_FIT): - // keep aspect ratio - source_size.scale(max_width, max_height, Qt::KeepAspectRatio); + case (SCALE_FIT): { + // keep aspect ratio + source_size.scale(max_width, max_height, Qt::KeepAspectRatio); - // Debug output - ZmqLogger::Instance()->AppendDebugMethod("Timeline::add_layer (Scale: SCALE_FIT)", "source_frame->number", source_frame->number, "source_width", source_size.width(), "source_height", source_size.height(), "", -1, "", -1, "", -1); - break; + // Debug output + ZmqLogger::Instance()->AppendDebugMethod("Timeline::add_layer (Scale: SCALE_FIT)", "source_frame->number", source_frame->number, "source_width", source_size.width(), "source_height", source_size.height(), "", -1, "", -1, "", -1); + break; + } + case (SCALE_STRETCH): { + // ignore aspect ratio + source_size.scale(max_width, max_height, Qt::IgnoreAspectRatio); - case (SCALE_STRETCH): - // ignore aspect ratio - source_size.scale(max_width, max_height, Qt::IgnoreAspectRatio); + // Debug output + ZmqLogger::Instance()->AppendDebugMethod("Timeline::add_layer (Scale: SCALE_STRETCH)", "source_frame->number", source_frame->number, "source_width", source_size.width(), "source_height", source_size.height(), "", -1, "", -1, "", -1); + break; + } + case (SCALE_CROP): { + QSize width_size(max_width, round(max_width / (float(source_size.width()) / float(source_size.height())))); + QSize height_size(round(max_height / (float(source_size.height()) / float(source_size.width()))), max_height); - // Debug output - ZmqLogger::Instance()->AppendDebugMethod("Timeline::add_layer (Scale: SCALE_STRETCH)", "source_frame->number", source_frame->number, "source_width", source_size.width(), "source_height", source_size.height(), "", -1, "", -1, "", -1); - break; + // respect aspect ratio + if (width_size.width() >= max_width && width_size.height() >= max_height) + source_size.scale(width_size.width(), width_size.height(), Qt::KeepAspectRatio); + else + source_size.scale(height_size.width(), height_size.height(), Qt::KeepAspectRatio); - case (SCALE_CROP): - QSize width_size(max_width, round(max_width / (float(source_size.width()) / float(source_size.height())))); - QSize height_size(round(max_height / (float(source_size.height()) / float(source_size.width()))), max_height); + // Debug output + ZmqLogger::Instance()->AppendDebugMethod("Timeline::add_layer (Scale: SCALE_CROP)", "source_frame->number", source_frame->number, "source_width", source_size.width(), "source_height", source_size.height(), "", -1, "", -1, "", -1); + break; + } + case (SCALE_NONE): { + // Calculate ratio of source size to project size + // Even with no scaling, previews need to be adjusted correctly + // (otherwise NONE scaling draws the frame image outside of the preview) + float source_width_ratio = source_size.width() / float(info.width); + float source_height_ratio = source_size.height() / float(info.height); + source_size.scale(max_width * source_width_ratio, max_height * source_height_ratio, Qt::KeepAspectRatio); - // respect aspect ratio - if (width_size.width() >= max_width && width_size.height() >= max_height) - source_size.scale(width_size.width(), width_size.height(), Qt::KeepAspectRatio); - else - source_size.scale(height_size.width(), height_size.height(), Qt::KeepAspectRatio); - - // Debug output - ZmqLogger::Instance()->AppendDebugMethod("Timeline::add_layer (Scale: SCALE_CROP)", "source_frame->number", source_frame->number, "source_width", source_size.width(), "source_height", source_size.height(), "", -1, "", -1, "", -1); - break; + // Debug output + ZmqLogger::Instance()->AppendDebugMethod("Timeline::add_layer (Scale: SCALE_NONE)", "source_frame->number", source_frame->number, "source_width", source_size.width(), "source_height", source_size.height(), "", -1, "", -1, "", -1); + break; + } } /* GRAVITY LOCATION - Initialize X & Y to the correct values (before applying location curves) */ diff --git a/src/bindings/python/openshot.i b/src/bindings/python/openshot.i index f338f18a..de1f020c 100644 --- a/src/bindings/python/openshot.i +++ b/src/bindings/python/openshot.i @@ -84,6 +84,7 @@ #include "../../../include/QtPlayer.h" #include "../../../include/KeyFrame.h" #include "../../../include/RendererBase.h" +#include "../../../include/Settings.h" #include "../../../include/Timeline.h" #include "../../../include/ZmqLogger.h" @@ -150,6 +151,7 @@ %include "../../../include/QtPlayer.h" %include "../../../include/KeyFrame.h" %include "../../../include/RendererBase.h" +%include "../../../include/Settings.h" %include "../../../include/Timeline.h" %include "../../../include/ZmqLogger.h" diff --git a/src/bindings/ruby/openshot.i b/src/bindings/ruby/openshot.i index c2f6fdf9..b9a35d41 100644 --- a/src/bindings/ruby/openshot.i +++ b/src/bindings/ruby/openshot.i @@ -88,6 +88,7 @@ namespace std { #include "../../../include/QtPlayer.h" #include "../../../include/KeyFrame.h" #include "../../../include/RendererBase.h" +#include "../../../include/Settings.h" #include "../../../include/Timeline.h" #include "../../../include/ZmqLogger.h" @@ -143,6 +144,7 @@ namespace std { %include "../../../include/QtPlayer.h" %include "../../../include/KeyFrame.h" %include "../../../include/RendererBase.h" +%include "../../../include/Settings.h" %include "../../../include/Timeline.h" %include "../../../include/ZmqLogger.h" diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2c455503..bb2f8c2a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -79,7 +79,33 @@ ENDIF (ImageMagick_FOUND) FIND_PACKAGE(FFmpeg REQUIRED) # Include FFmpeg headers (needed for compile) -include_directories(${FFMPEG_INCLUDE_DIR}) +IF (AVCODEC_FOUND) + include_directories(${AVCODEC_INCLUDE_DIRS}) +ENDIF (AVCODEC_FOUND) +IF (AVDEVICE_FOUND) + include_directories(${AVDEVICE_INCLUDE_DIRS}) +ENDIF (AVDEVICE_FOUND) +IF (AVFORMAT_FOUND) + include_directories(${AVFORMAT_INCLUDE_DIRS}) +ENDIF (AVFORMAT_FOUND) +IF (AVFILTER_FOUND) + include_directories(${AVFILTER_INCLUDE_DIRS}) +ENDIF (AVFILTER_FOUND) +IF (AVUTIL_FOUND) + include_directories(${AVUTIL_INCLUDE_DIRS}) +ENDIF (AVUTIL_FOUND) +IF (POSTPROC_FOUND) + include_directories(${POSTPROC_INCLUDE_DIRS}) +ENDIF (POSTPROC_FOUND) +IF (SWSCALE_FOUND) + include_directories(${SWSCALE_INCLUDE_DIRS}) +ENDIF (SWSCALE_FOUND) +IF (SWRESAMPLE_FOUND) + include_directories(${SWRESAMPLE_INCLUDE_DIRS}) +ENDIF (SWRESAMPLE_FOUND) +IF (AVRESAMPLE_FOUND) + include_directories(${AVRESAMPLE_INCLUDE_DIRS}) +ENDIF (AVRESAMPLE_FOUND) ################# LIBOPENSHOT-AUDIO ################### # Find JUCE-based openshot Audio libraries @@ -150,12 +176,18 @@ endif(OPENMP_FOUND) # Find ZeroMQ library (used for socket communication & logging) FIND_PACKAGE(ZMQ REQUIRED) -# Include FFmpeg headers (needed for compile) +# Include ZeroMQ headers (needed for compile) include_directories(${ZMQ_INCLUDE_DIRS}) ################### JSONCPP ##################### # Include jsoncpp headers (needed for JSON parsing) -include_directories("../thirdparty/jsoncpp/include") +if (USE_SYSTEM_JSONCPP) + find_package(JsonCpp REQUIRED) + include_directories(${JSONCPP_INCLUDE_DIRS}) +else() + message("Using embedded JsonCpp") + include_directories("../thirdparty/jsoncpp/include") +endif(USE_SYSTEM_JSONCPP) IF (NOT DISABLE_TESTS) ############### SET TEST SOURCE FILES ################# @@ -172,6 +204,7 @@ IF (NOT DISABLE_TESTS) FrameMapper_Tests.cpp KeyFrame_Tests.cpp Point_Tests.cpp + Settings_Tests.cpp Timeline_Tests.cpp ) ################ TESTER EXECUTABLE ################# diff --git a/tests/Settings_Tests.cpp b/tests/Settings_Tests.cpp new file mode 100644 index 00000000..86790653 --- /dev/null +++ b/tests/Settings_Tests.cpp @@ -0,0 +1,63 @@ +/** + * @file + * @brief Unit tests for openshot::Color + * @author Jonathan Thomas + * + * @section LICENSE + * + * Copyright (c) 2008-2014 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" +#include "../include/OpenShot.h" + +using namespace std; +using namespace openshot; + +TEST(Settings_Default_Constructor) +{ + // Create an empty color + Settings *s = Settings::Instance(); + + CHECK_EQUAL(false, s->HARDWARE_DECODE); + CHECK_EQUAL(false, s->HARDWARE_ENCODE); + CHECK_EQUAL(false, s->HIGH_QUALITY_SCALING); + CHECK_EQUAL(false, s->WAIT_FOR_VIDEO_PROCESSING_TASK); +} + +TEST(Settings_Change_Settings) +{ + // Create an empty color + Settings *s = Settings::Instance(); + s->HARDWARE_DECODE = true; + s->HARDWARE_ENCODE = true; + s->HIGH_QUALITY_SCALING = true; + s->WAIT_FOR_VIDEO_PROCESSING_TASK = true; + + CHECK_EQUAL(true, s->HARDWARE_DECODE); + CHECK_EQUAL(true, s->HARDWARE_ENCODE); + CHECK_EQUAL(true, s->HIGH_QUALITY_SCALING); + CHECK_EQUAL(true, s->WAIT_FOR_VIDEO_PROCESSING_TASK); + + CHECK_EQUAL(true, s->HARDWARE_DECODE); + CHECK_EQUAL(true, s->HARDWARE_ENCODE); + CHECK_EQUAL(true, Settings::Instance()->HIGH_QUALITY_SCALING); + CHECK_EQUAL(true, Settings::Instance()->WAIT_FOR_VIDEO_PROCESSING_TASK); +} \ No newline at end of file