From e879188a7d58f09877c4531f2ef0eb0e2d2800cf Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Tue, 11 Sep 2018 00:40:31 -0500 Subject: [PATCH] FFmpeg 3 & 4 support, Travis CI support, OpenMP schedule change (#160) * FFmpeg4 support. Compile warnings fixes. Credit goes to many people, including ferdnyc, peterM, and other awesome folks! * Adding environment checking to enable/disable omp taskwait after each video/audio frame is processed. This is experimental for some users with crashes. * Moving `omp taskwait` to after the ProcessVideoPacket() method, since that is the only place it is useful. * Fixing crashes on missing Clip source file, and changing FFmpeg scaling algorthm from SWS_BILINEAR to SWS_LANCZOS (for higher quality scaling) * Update FindFFmpeg.cmake module, and updating build script. Also enabling debug builds. * Updating experimental travis build script * Fixed unit test for newer version of FFmpeg (audio resampling) * Experimental travis multiple jobs * Adding OMP schedule hint (thanks PeterM), which prevents crashes in some circumstances. --- .travis.yml | 49 ++++++ cmake/Modules/FindFFmpeg.cmake | 306 +++++++++++++++++---------------- include/CrashHandler.h | 8 +- include/FFmpegReader.h | 1 + include/FFmpegUtilities.h | 76 +++++++- include/FFmpegWriter.h | 4 +- include/Frame.h | 2 +- include/FrameMapper.h | 2 +- include/OpenMPUtilities.h | 22 ++- include/ZmqLogger.h | 12 +- src/CMakeLists.txt | 213 ++++++++++++++--------- src/Clip.cpp | 12 +- src/EffectInfo.cpp | 1 + src/FFmpegReader.cpp | 51 ++++-- src/FFmpegWriter.cpp | 53 ++++-- src/FrameMapper.cpp | 15 +- src/Timeline.cpp | 33 ++-- tests/FrameMapper_Tests.cpp | 6 +- tests/ReaderBase_Tests.cpp | 4 +- 19 files changed, 567 insertions(+), 303 deletions(-) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..fa191b2b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,49 @@ +dist: trusty + +matrix: + include: + - language: cpp + name: "FFmpeg 2" + before_script: + - sudo add-apt-repository ppa:openshot.developers/libopenshot-daily -y + - sudo add-apt-repository ppa:beineri/opt-qt58-trusty -y + - sudo apt-get update -qq + - sudo apt-get install gcc-4.8 cmake libavcodec-dev libavformat-dev libswscale-dev libavresample-dev libavutil-dev libopenshot-audio-dev libopenshot-dev libfdk-aac-dev libfdk-aac-dev libjsoncpp-dev libmagick++-dev libopenshot-audio-dev libunittest++-dev libzmq3-dev pkg-config python3-dev qtbase5-dev qtmultimedia5-dev swig -y + - sudo apt autoremove -y + script: + - mkdir -p build; cd build; + - cmake -D"CMAKE_BUILD_TYPE:STRING=Debug" ../ + - make VERBOSE=1 + - make test + + - language: cpp + name: "FFmpeg 3" + before_script: + - sudo add-apt-repository ppa:openshot.developers/libopenshot-daily -y + - sudo add-apt-repository ppa:beineri/opt-qt58-trusty -y + - sudo add-apt-repository ppa:jonathonf/ffmpeg-3 -y + - sudo apt-get update -qq + - sudo apt-get install gcc-4.8 cmake libavcodec-dev libavformat-dev libswscale-dev libavresample-dev libavutil-dev libopenshot-audio-dev libopenshot-dev libfdk-aac-dev libfdk-aac-dev libjsoncpp-dev libmagick++-dev libopenshot-audio-dev libunittest++-dev libzmq3-dev pkg-config python3-dev qtbase5-dev qtmultimedia5-dev swig -y + - sudo apt autoremove -y + script: + - mkdir -p build; cd build; + - cmake -D"CMAKE_BUILD_TYPE:STRING=Debug" ../ + - make VERBOSE=1 + - make test + + - language: cpp + name: "FFmpeg 4" + before_script: + - sudo add-apt-repository ppa:openshot.developers/libopenshot-daily -y + - sudo add-apt-repository ppa:beineri/opt-qt58-trusty -y + - sudo add-apt-repository ppa:jonathonf/ffmpeg -y + - sudo add-apt-repository ppa:jonathonf/ffmpeg-4 -y + - sudo add-apt-repository ppa:jonathonf/backports -y + - sudo apt-get update -qq + - sudo apt-get install gcc-4.8 cmake libavcodec58 libavformat58 libavcodec-dev libavformat-dev libswscale-dev libavresample-dev libavutil-dev libopenshot-audio-dev libopenshot-dev libfdk-aac-dev libfdk-aac-dev libjsoncpp-dev libmagick++-dev libopenshot-audio-dev libunittest++-dev libzmq3-dev pkg-config python3-dev qtbase5-dev qtmultimedia5-dev swig -y + - sudo apt autoremove -y + script: + - mkdir -p build; cd build; + - cmake -D"CMAKE_BUILD_TYPE:STRING=Debug" ../ + - make VERBOSE=1 + - make test diff --git a/cmake/Modules/FindFFmpeg.cmake b/cmake/Modules/FindFFmpeg.cmake index 4af6cc93..34f0a7bd 100644 --- a/cmake/Modules/FindFFmpeg.cmake +++ b/cmake/Modules/FindFFmpeg.cmake @@ -1,151 +1,161 @@ -# - Try to find FFMPEG +# vim: ts=2 sw=2 +# - Try to find the required ffmpeg components(default: AVFORMAT, AVUTIL, AVCODEC) +# # Once done this will define -# -# FFMPEG_FOUND - system has FFMPEG -# FFMPEG_INCLUDE_DIR - the include directory -# FFMPEG_LIBRARY_DIR - the directory containing the libraries -# FFMPEG_LIBRARIES - Link these to use FFMPEG -# - -# FindAvformat -FIND_PATH( AVFORMAT_INCLUDE_DIR libavformat/avformat.h - PATHS /usr/include/ - /usr/include/ffmpeg/ - $ENV{FFMPEGDIR}/include/ - $ENV{FFMPEGDIR}/include/ffmpeg/ ) - -FIND_LIBRARY( AVFORMAT_LIBRARY avformat avformat-55 avformat-57 - PATHS /usr/lib/ - /usr/lib/ffmpeg/ - $ENV{FFMPEGDIR}/lib/ - $ENV{FFMPEGDIR}/lib/ffmpeg/ - $ENV{FFMPEGDIR}/bin/ ) - -#FindAvcodec -FIND_PATH( AVCODEC_INCLUDE_DIR libavcodec/avcodec.h - PATHS /usr/include/ - /usr/include/ffmpeg/ - $ENV{FFMPEGDIR}/include/ - $ENV{FFMPEGDIR}/include/ffmpeg/ ) - -FIND_LIBRARY( AVCODEC_LIBRARY avcodec avcodec-55 avcodec-57 - PATHS /usr/lib/ - /usr/lib/ffmpeg/ - $ENV{FFMPEGDIR}/lib/ - $ENV{FFMPEGDIR}/lib/ffmpeg/ - $ENV{FFMPEGDIR}/bin/ ) - -#FindAvutil -FIND_PATH( AVUTIL_INCLUDE_DIR libavutil/avutil.h - PATHS /usr/include/ - /usr/include/ffmpeg/ - $ENV{FFMPEGDIR}/include/ - $ENV{FFMPEGDIR}/include/ffmpeg/ ) - -FIND_LIBRARY( AVUTIL_LIBRARY avutil avutil-52 avutil-55 - PATHS /usr/lib/ - /usr/lib/ffmpeg/ - $ENV{FFMPEGDIR}/lib/ - $ENV{FFMPEGDIR}/lib/ffmpeg/ - $ENV{FFMPEGDIR}/bin/ ) - -#FindAvdevice -FIND_PATH( AVDEVICE_INCLUDE_DIR libavdevice/avdevice.h - PATHS /usr/include/ - /usr/include/ffmpeg/ - $ENV{FFMPEGDIR}/include/ - $ENV{FFMPEGDIR}/include/ffmpeg/ ) - -FIND_LIBRARY( AVDEVICE_LIBRARY avdevice avdevice-55 avdevice-56 - PATHS /usr/lib/ - /usr/lib/ffmpeg/ - $ENV{FFMPEGDIR}/lib/ - $ENV{FFMPEGDIR}/lib/ffmpeg/ - $ENV{FFMPEGDIR}/bin/ ) - -#FindSwscale -FIND_PATH( SWSCALE_INCLUDE_DIR libswscale/swscale.h - PATHS /usr/include/ - /usr/include/ffmpeg/ - $ENV{FFMPEGDIR}/include/ - $ENV{FFMPEGDIR}/include/ffmpeg/ ) - -FIND_LIBRARY( SWSCALE_LIBRARY swscale swscale-2 swscale-4 - PATHS /usr/lib/ - /usr/lib/ffmpeg/ - $ENV{FFMPEGDIR}/lib/ - $ENV{FFMPEGDIR}/lib/ffmpeg/ - $ENV{FFMPEGDIR}/bin/ ) - -#FindAvresample -FIND_PATH( AVRESAMPLE_INCLUDE_DIR libavresample/avresample.h - PATHS /usr/include/ - /usr/include/ffmpeg/ - $ENV{FFMPEGDIR}/include/ - $ENV{FFMPEGDIR}/include/ffmpeg/ ) - -FIND_LIBRARY( AVRESAMPLE_LIBRARY avresample avresample-2 avresample-3 - PATHS /usr/lib/ - /usr/lib/ffmpeg/ - $ENV{FFMPEGDIR}/lib/ - $ENV{FFMPEGDIR}/lib/ffmpeg/ - $ENV{FFMPEGDIR}/bin/ ) - -SET( FFMPEG_FOUND FALSE ) - -IF ( AVFORMAT_INCLUDE_DIR AND AVFORMAT_LIBRARY ) - SET ( AVFORMAT_FOUND TRUE ) -ENDIF ( AVFORMAT_INCLUDE_DIR AND AVFORMAT_LIBRARY ) - -IF ( AVCODEC_INCLUDE_DIR AND AVCODEC_LIBRARY ) - SET ( AVCODEC_FOUND TRUE) -ENDIF ( AVCODEC_INCLUDE_DIR AND AVCODEC_LIBRARY ) - -IF ( AVUTIL_INCLUDE_DIR AND AVUTIL_LIBRARY ) - SET ( AVUTIL_FOUND TRUE ) -ENDIF ( AVUTIL_INCLUDE_DIR AND AVUTIL_LIBRARY ) - -IF ( AVDEVICE_INCLUDE_DIR AND AVDEVICE_LIBRARY ) - SET ( AVDEVICE_FOUND TRUE ) -ENDIF ( AVDEVICE_INCLUDE_DIR AND AVDEVICE_LIBRARY ) - -IF ( SWSCALE_INCLUDE_DIR AND SWSCALE_LIBRARY ) - SET ( SWSCALE_FOUND TRUE ) -ENDIF ( SWSCALE_INCLUDE_DIR AND SWSCALE_LIBRARY ) - -IF ( AVRESAMPLE_INCLUDE_DIR AND AVRESAMPLE_LIBRARY ) - SET ( AVRESAMPLE_FOUND TRUE ) -ENDIF ( AVRESAMPLE_INCLUDE_DIR AND AVRESAMPLE_LIBRARY ) - -IF ( AVFORMAT_INCLUDE_DIR OR AVCODEC_INCLUDE_DIR OR AVUTIL_INCLUDE_DIR OR AVDEVICE_FOUND OR SWSCALE_FOUND OR AVRESAMPLE_FOUND ) - - SET ( FFMPEG_FOUND TRUE ) - - SET ( FFMPEG_INCLUDE_DIR - ${AVFORMAT_INCLUDE_DIR} - ${AVCODEC_INCLUDE_DIR} - ${AVUTIL_INCLUDE_DIR} - ${AVDEVICE_INCLUDE_DIR} - ${SWSCALE_INCLUDE_DIR} - ${AVRESAMPLE_INCLUDE_DIR} ) - - SET ( FFMPEG_LIBRARIES - ${AVFORMAT_LIBRARY} - ${AVCODEC_LIBRARY} - ${AVUTIL_LIBRARY} - ${AVDEVICE_LIBRARY} - ${SWSCALE_LIBRARY} - ${AVRESAMPLE_LIBRARY} ) - -ENDIF ( AVFORMAT_INCLUDE_DIR OR AVCODEC_INCLUDE_DIR OR AVUTIL_INCLUDE_DIR OR AVDEVICE_FOUND OR SWSCALE_FOUND OR AVRESAMPLE_FOUND ) - -MARK_AS_ADVANCED( - FFMPEG_LIBRARY_DIR - FFMPEG_INCLUDE_DIR -) +# FFMPEG_FOUND - System has the all required components. +# FFMPEG_INCLUDE_DIRS - Include directory necessary for using the required components headers. +# FFMPEG_LIBRARIES - Link these to use the required ffmpeg components. +# FFMPEG_DEFINITIONS - Compiler switches required for using the required ffmpeg components. +# +# For each of the components it will additionally set. +# - AVCODEC +# - AVDEVICE +# - AVFORMAT +# - AVFILTER +# - AVUTIL +# - POSTPROC +# - SWSCALE +# - SWRESAMPLE +# - AVRESAMPLE +# the following variables will be defined +# _FOUND - System has +# _INCLUDE_DIRS - Include directory necessary for using the headers +# _LIBRARIES - Link these to use +# _DEFINITIONS - Compiler switches required for using +# _VERSION - The components version +# +# Copyright (c) 2006, Matthias Kretz, +# Copyright (c) 2008, Alexander Neundorf, +# Copyright (c) 2011, Michael Jansen, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. include(FindPackageHandleStandardArgs) -# handle the QUIETLY and REQUIRED arguments and set FFMPEG_FOUND to TRUE -# if all listed variables are TRUE -find_package_handle_standard_args(FFMPEG DEFAULT_MSG - FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIR) + +# The default components were taken from a survey over other FindFFMPEG.cmake files +if (NOT FFmpeg_FIND_COMPONENTS) + set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL) +endif () + +# +### Macro: set_component_found +# +# Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIRS is present. +# +macro(set_component_found _component ) + if (${_component}_LIBRARIES AND ${_component}_INCLUDE_DIRS) + # message(STATUS " - ${_component} found.") + set(${_component}_FOUND TRUE) + else () + # message(STATUS " - ${_component} not found.") + endif () +endmacro() + +# +### Macro: find_component +# +# Checks for the given component by invoking pkgconfig and then looking up the libraries and +# include directories. +# +macro(find_component _component _pkgconfig _library _header) + + if (NOT WIN32) + # use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(PC_${_component} ${_pkgconfig}) + endif () + endif (NOT WIN32) + + find_path(${_component}_INCLUDE_DIRS ${_header} + HINTS + /opt/ + /opt/include/ + ${PC_LIB${_component}_INCLUDEDIR} + ${PC_LIB${_component}_INCLUDE_DIRS} + $ENV{FFMPEGDIR}/include/ + $ENV{FFMPEGDIR}/include/ffmpeg/ + PATH_SUFFIXES + ffmpeg + ) + + find_library(${_component}_LIBRARIES NAMES ${_library} + HINTS + ${PC_LIB${_component}_LIBDIR} + ${PC_LIB${_component}_LIBRARY_DIRS} + $ENV{FFMPEGDIR}/lib/ + $ENV{FFMPEGDIR}/lib/ffmpeg/ + $ENV{FFMPEGDIR}/bin/ + ) + + set(${_component}_DEFINITIONS ${PC_${_component}_CFLAGS_OTHER} CACHE STRING "The ${_component} CFLAGS.") + set(${_component}_VERSION ${PC_${_component}_VERSION} CACHE STRING "The ${_component} version number.") + + set_component_found(${_component}) + + mark_as_advanced( + ${_component}_INCLUDE_DIRS + ${_component}_LIBRARIES + ${_component}_DEFINITIONS + ${_component}_VERSION) + +endmacro() + + +# Check for cached results. If there are skip the costly part. +if (NOT FFMPEG_LIBRARIES) + + # Check for all possible component. + find_component(AVCODEC libavcodec avcodec libavcodec/avcodec.h) + find_component(AVFORMAT libavformat avformat libavformat/avformat.h) + find_component(AVDEVICE libavdevice avdevice libavdevice/avdevice.h) + find_component(AVUTIL libavutil avutil libavutil/avutil.h) + find_component(AVFILTER libavfilter avfilter libavfilter/avfilter.h) + find_component(SWSCALE libswscale swscale libswscale/swscale.h) + find_component(POSTPROC libpostproc postproc libpostproc/postprocess.h) + find_component(SWRESAMPLE libswresample swresample libswresample/swresample.h) + find_component(AVRESAMPLE libavresample avresample libavresample/avresample.h) + + # Check if the required components were found and add their stuff to the FFMPEG_* vars. + foreach (_component ${FFmpeg_FIND_COMPONENTS}) + if (${_component}_FOUND) + # message(STATUS "Required component ${_component} present.") + set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${${_component}_LIBRARIES}) + set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} ${${_component}_DEFINITIONS}) + list(APPEND FFMPEG_INCLUDE_DIRS ${${_component}_INCLUDE_DIRS}) + else () + # message(STATUS "Required component ${_component} missing.") + endif () + endforeach () + + # Build the include path with duplicates removed. + if (FFMPEG_INCLUDE_DIRS) + list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS) + endif () + + # cache the vars. + set(FFMPEG_INCLUDE_DIRS ${FFMPEG_INCLUDE_DIRS} CACHE STRING "The FFmpeg include directories." FORCE) + set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} CACHE STRING "The FFmpeg libraries." FORCE) + set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} CACHE STRING "The FFmpeg cflags." FORCE) + + mark_as_advanced(FFMPEG_INCLUDE_DIRS + FFMPEG_LIBRARIES + FFMPEG_DEFINITIONS) + +endif () + +# Now set the noncached _FOUND vars for the components. +foreach (_component AVCODEC AVDEVICE AVFORMAT AVUTIL POSTPROCESS SWSCALE SWRESAMPLE AVRESAMPLE) + set_component_found(${_component}) +endforeach () + +# Compile the list of required vars +set(_FFmpeg_REQUIRED_VARS FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIRS) +foreach (_component ${FFmpeg_FIND_COMPONENTS}) + list(APPEND _FFmpeg_REQUIRED_VARS ${_component}_LIBRARIES ${_component}_INCLUDE_DIRS) +endforeach () + +# Give a nice error message if some of the required vars are missing. +find_package_handle_standard_args(FFmpeg DEFAULT_MSG ${_FFmpeg_REQUIRED_VARS}) \ No newline at end of file diff --git a/include/CrashHandler.h b/include/CrashHandler.h index e3a4bbe5..12c79a86 100644 --- a/include/CrashHandler.h +++ b/include/CrashHandler.h @@ -53,13 +53,15 @@ namespace openshot { class CrashHandler { private: /// Default constructor - CrashHandler(){}; // Don't allow user to create an instance of this singleton + CrashHandler(){return;}; // Don't allow user to create an instance of this singleton /// Default copy method - CrashHandler(CrashHandler const&){}; // Don't allow the user to copy this instance + //CrashHandler(CrashHandler const&){}; // Don't allow the user to copy this instance + CrashHandler(CrashHandler const&) = delete; // Don't allow the user to copy this instance /// Default assignment operator - CrashHandler & operator=(CrashHandler const&){}; // Don't allow the user to assign this instance + //CrashHandler & operator=(CrashHandler const&){}; // Don't allow the user to assign this instance + CrashHandler & operator=(CrashHandler const&) = delete; // Don't allow the user to assign this instance /// Private variable to keep track of singleton instance static CrashHandler *m_pInstance; diff --git a/include/FFmpegReader.h b/include/FFmpegReader.h index 6072756a..e2c4863a 100644 --- a/include/FFmpegReader.h +++ b/include/FFmpegReader.h @@ -105,6 +105,7 @@ 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 578c6586..346da541 100644 --- a/include/FFmpegUtilities.h +++ b/include/FFmpegUtilities.h @@ -43,7 +43,15 @@ #include #include #include + // Change this to the first version swrescale works + #if (LIBAVFORMAT_VERSION_MAJOR >= 57) + #define USE_SW + #endif + #ifdef USE_SW + #include + #else #include + #endif #include #include #include @@ -106,7 +114,65 @@ #define PIX_FMT_YUV420P AV_PIX_FMT_YUV420P #endif - #if IS_FFMPEG_3_2 + #ifdef USE_SW + #define SWR_CONVERT(ctx, out, linesize, out_count, in, linesize2, in_count) \ + swr_convert(ctx, out, out_count, (const uint8_t **)in, in_count) + #define SWR_ALLOC() swr_alloc() + #define SWR_CLOSE(ctx) {} + #define SWR_FREE(ctx) swr_free(ctx) + #define SWR_INIT(ctx) swr_init(ctx) + #define SWRCONTEXT SwrContext + #else + #define SWR_CONVERT(ctx, out, linesize, out_count, in, linesize2, in_count) \ + avresample_convert(ctx, out, linesize, out_count, (uint8_t **)in, linesize2, in_count) + #define SWR_ALLOC() avresample_alloc_context() + #define SWR_CLOSE(ctx) avresample_close(ctx) + #define SWR_FREE(ctx) avresample_free(ctx) + #define SWR_INIT(ctx) avresample_open(ctx) + #define SWRCONTEXT AVAudioResampleContext + #endif + + + #if (LIBAVFORMAT_VERSION_MAJOR >= 58) + #define AV_REGISTER_ALL + #define AVCODEC_REGISTER_ALL + #define AV_FILENAME url + #define MY_INPUT_BUFFER_PADDING_SIZE AV_INPUT_BUFFER_PADDING_SIZE + #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_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 + #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_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 + #define AV_GET_CODEC_PIXEL_FORMAT(av_stream, av_context) (AVPixelFormat) av_stream->codecpar->format + #define AV_GET_SAMPLE_FORMAT(av_stream, av_context) av_stream->codecpar->format + #define AV_GET_IMAGE_SIZE(pix_fmt, width, height) av_image_get_buffer_size(pix_fmt, width, height, 1) + #define AV_COPY_PICTURE_DATA(av_frame, buffer, pix_fmt, width, height) av_image_fill_arrays(av_frame->data, av_frame->linesize, buffer, pix_fmt, width, height, 1) + #define AV_OUTPUT_CONTEXT(output_context, path) avformat_alloc_output_context2( output_context, NULL, NULL, path) + #define AV_OPTION_FIND(priv_data, name) av_opt_find(priv_data, name, NULL, 0, 0) + #define AV_OPTION_SET( av_stream, priv_data, name, value, avcodec) av_opt_set(priv_data, name, value, 0); avcodec_parameters_from_context(av_stream->codecpar, avcodec); + #define AV_FORMAT_NEW_STREAM(oc, st_codec, av_codec, av_st) av_st = avformat_new_stream(oc, NULL);\ + if (!av_st) \ + throw OutOfMemory("Could not allocate memory for the video stream.", path); \ + c = avcodec_alloc_context3(av_codec); \ + st_codec = c; \ + av_st->codecpar->codec_id = av_codec->id; + #define AV_COPY_PARAMS_FROM_CONTEXT(av_stream, av_codec) avcodec_parameters_from_context(av_stream->codecpar, av_codec); + #elif IS_FFMPEG_3_2 + #define AV_REGISTER_ALL av_register_all(); + #define AVCODEC_REGISTER_ALL avcodec_register_all(); + #define AV_FILENAME filename + #define MY_INPUT_BUFFER_PADDING_SIZE FF_INPUT_BUFFER_PADDING_SIZE #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) @@ -138,6 +204,10 @@ av_st->codecpar->codec_id = av_codec->id; #define AV_COPY_PARAMS_FROM_CONTEXT(av_stream, av_codec) avcodec_parameters_from_context(av_stream->codecpar, av_codec); #elif LIBAVFORMAT_VERSION_MAJOR >= 55 + #define AV_REGISTER_ALL av_register_all(); + #define AVCODEC_REGISTER_ALL avcodec_register_all(); + #define AV_FILENAME filename + #define MY_INPUT_BUFFER_PADDING_SIZE FF_INPUT_BUFFER_PADDING_SIZE #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) @@ -164,6 +234,10 @@ c = av_st->codec; #define AV_COPY_PARAMS_FROM_CONTEXT(av_stream, av_codec) #else + #define AV_REGISTER_ALL av_register_all(); + #define AVCODEC_REGISTER_ALL avcodec_register_all(); + #define AV_FILENAME filename + #define MY_INPUT_BUFFER_PADDING_SIZE FF_INPUT_BUFFER_PADDING_SIZE #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) diff --git a/include/FFmpegWriter.h b/include/FFmpegWriter.h index 8343002e..7eefacb7 100644 --- a/include/FFmpegWriter.h +++ b/include/FFmpegWriter.h @@ -174,8 +174,8 @@ namespace openshot int initial_audio_input_frame_size; int audio_input_position; int audio_encoder_buffer_size; - AVAudioResampleContext *avr; - AVAudioResampleContext *avr_planar; + SWRCONTEXT *avr; + SWRCONTEXT *avr_planar; /* Resample options */ int original_sample_rate; diff --git a/include/Frame.h b/include/Frame.h index a7ad509f..eba7f8bb 100644 --- a/include/Frame.h +++ b/include/Frame.h @@ -62,7 +62,7 @@ #include "AudioResampler.h" #include "Fraction.h" - +#pragma SWIG nowarn=362 using namespace std; namespace openshot diff --git a/include/FrameMapper.h b/include/FrameMapper.h index 06511666..216fe73f 100644 --- a/include/FrameMapper.h +++ b/include/FrameMapper.h @@ -146,7 +146,7 @@ namespace openshot ReaderBase *reader; // The source video reader CacheMemory final_cache; // Cache of actual Frame objects bool is_dirty; // When this is true, the next call to GetFrame will re-init the mapping - AVAudioResampleContext *avr; // Audio resampling context object + SWRCONTEXT *avr; // Audio resampling context object // Internal methods used by init void AddField(int64_t frame); diff --git a/include/OpenMPUtilities.h b/include/OpenMPUtilities.h index 8a95a950..c0f5597b 100644 --- a/include/OpenMPUtilities.h +++ b/include/OpenMPUtilities.h @@ -29,8 +29,26 @@ #define OPENSHOT_OPENMP_UTILITIES_H #include +#include +#include - // Calculate the # of OpenMP Threads to allow - #define OPEN_MP_NUM_PROCESSORS omp_get_num_procs() +// Calculate the # of OpenMP Threads to allow +#define OPEN_MP_NUM_PROCESSORS omp_get_num_procs() + +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/ZmqLogger.h b/include/ZmqLogger.h index c134f2cf..e825ed0e 100644 --- a/include/ZmqLogger.h +++ b/include/ZmqLogger.h @@ -72,11 +72,19 @@ namespace openshot { /// Default constructor ZmqLogger(){}; // Don't allow user to create an instance of this singleton +#if __GNUC__ >=7 /// Default copy method - ZmqLogger(ZmqLogger const&){}; // Don't allow the user to copy this instance + ZmqLogger(ZmqLogger const&) = delete; // Don't allow the user to assign this instance /// Default assignment operator - ZmqLogger & operator=(ZmqLogger const&){}; // Don't allow the user to assign this instance + ZmqLogger & operator=(ZmqLogger const&) = delete; // Don't allow the user to assign this instance +#else + /// Default copy method + ZmqLogger(ZmqLogger const&) {}; // Don't allow the user to assign this instance + + /// Default assignment operator + ZmqLogger & operator=(ZmqLogger const&); // Don't allow the user to assign this instance +#endif /// Private variable to keep track of singleton instance static ZmqLogger * m_pInstance; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f4e8fba4..d71067a3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -37,12 +37,12 @@ IF (WIN32) ENDIF(WIN32) 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) - 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") + SET_PROPERTY(GLOBAL PROPERTY JUCE_MAC "JUCE_MAC") + ADD_DEFINITIONS(-DNDEBUG) + 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(APPLE) ################ IMAGE MAGICK ################## @@ -74,13 +74,43 @@ IF (ImageMagick_FOUND) SET(CMAKE_SWIG_FLAGS "-DUSE_IMAGEMAGICK=1") ENDIF (ImageMagick_FOUND) - + ################### FFMPEG ##################### # Find FFmpeg libraries (used for video encoding / decoding) FIND_PACKAGE(FFmpeg REQUIRED) # Include FFmpeg headers (needed for compile) -include_directories(${FFMPEG_INCLUDE_DIR}) +message('AVCODEC_FOUND: ${AVCODEC_FOUND}') +message('AVCODEC_INCLUDE_DIRS: ${AVCODEC_INCLUDE_DIRS}') +message('AVCODEC_LIBRARIES: ${AVCODEC_LIBRARIES}') + +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 @@ -112,11 +142,11 @@ add_definitions(${Qt5Gui_DEFINITIONS}) add_definitions(${Qt5Multimedia_DEFINITIONS}) add_definitions(${Qt5MultimediaWidgets_DEFINITIONS}) -SET(QT_LIBRARIES ${Qt5Widgets_LIBRARIES} - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES} - ${Qt5Multimedia_LIBRARIES} - ${Qt5MultimediaWidgets_LIBRARIES}) +SET(QT_LIBRARIES ${Qt5Widgets_LIBRARIES} + ${Qt5Core_LIBRARIES} + ${Qt5Gui_LIBRARIES} + ${Qt5Multimedia_LIBRARIES} + ${Qt5MultimediaWidgets_LIBRARIES}) # Set compiler flags for Qt set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS} ") @@ -133,15 +163,15 @@ qt5_wrap_cpp(MOC_FILES ${QT_HEADER_FILES}) # Find BlackMagic DeckLinkAPI libraries IF (ENABLE_BLACKMAGIC) FIND_PACKAGE(BlackMagic) - + IF (BLACKMAGIC_FOUND) # Include headers (needed for compile) include_directories(${BLACKMAGIC_INCLUDE_DIR}) - + # define a global var (used in the C++) add_definitions( -DUSE_BLACKMAGIC=1 ) SET(CMAKE_SWIG_FLAGS "-DUSE_BLACKMAGIC=1") - + ENDIF (BLACKMAGIC_FOUND) ENDIF (ENABLE_BLACKMAGIC) @@ -150,14 +180,14 @@ ENDIF (ENABLE_BLACKMAGIC) FIND_PACKAGE(OpenMP) if (OPENMP_FOUND) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS} ") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS} ") endif(OPENMP_FOUND) ################### ZEROMQ ##################### # Find ZeroMQ library (used for socket communication & logging) FIND_PACKAGE(ZMQ REQUIRED) -# Include FFmpeg headers (needed for compile) +# Include ZeroMQ headers (needed for compile) include_directories(${ZMQ_INCLUDE_DIRS}) ################### JSONCPP ##################### @@ -182,8 +212,8 @@ FILE(GLOB QT_PLAYER_FILES "${CMAKE_CURRENT_SOURCE_DIR}/Qt/*.cpp") ############### SET LIBRARY SOURCE FILES ################# SET ( OPENSHOT_SOURCE_FILES - AudioBufferSource.cpp - AudioReaderSource.cpp + AudioBufferSource.cpp + AudioReaderSource.cpp AudioResampler.cpp CacheBase.cpp CacheDisk.cpp @@ -215,37 +245,37 @@ SET ( OPENSHOT_SOURCE_FILES QtImageReader.cpp QtPlayer.cpp Timeline.cpp - + # Qt Video Player ${QT_PLAYER_FILES} ${MOC_FILES}) - IF (NOT USE_SYSTEM_JSONCPP) - # Third Party JSON Parser - SET ( OPENSHOT_SOURCE_FILES ${OPENSHOT_SOURCE_FILES} - ../thirdparty/jsoncpp/src/lib_json/json_reader.cpp - ../thirdparty/jsoncpp/src/lib_json/json_value.cpp - ../thirdparty/jsoncpp/src/lib_json/json_writer.cpp) - ENDIF (NOT USE_SYSTEM_JSONCPP) +IF (NOT USE_SYSTEM_JSONCPP) + # Third Party JSON Parser + SET ( OPENSHOT_SOURCE_FILES ${OPENSHOT_SOURCE_FILES} + ../thirdparty/jsoncpp/src/lib_json/json_reader.cpp + ../thirdparty/jsoncpp/src/lib_json/json_value.cpp + ../thirdparty/jsoncpp/src/lib_json/json_writer.cpp) +ENDIF (NOT USE_SYSTEM_JSONCPP) + +# ImageMagic related files +IF (ImageMagick_FOUND) + SET ( OPENSHOT_SOURCE_FILES ${OPENSHOT_SOURCE_FILES} + ImageReader.cpp + ImageWriter.cpp + TextReader.cpp) +ENDIF (ImageMagick_FOUND) + +# BlackMagic related files +IF (BLACKMAGIC_FOUND) + SET ( OPENSHOT_SOURCE_FILES ${OPENSHOT_SOURCE_FILES} + DecklinkInput.cpp + DecklinkReader.cpp + DecklinkOutput.cpp + DecklinkWriter.cpp) +ENDIF (BLACKMAGIC_FOUND) - # ImageMagic related files - IF (ImageMagick_FOUND) - SET ( OPENSHOT_SOURCE_FILES ${OPENSHOT_SOURCE_FILES} - ImageReader.cpp - ImageWriter.cpp - TextReader.cpp) - ENDIF (ImageMagick_FOUND) - # BlackMagic related files - IF (BLACKMAGIC_FOUND) - SET ( OPENSHOT_SOURCE_FILES ${OPENSHOT_SOURCE_FILES} - DecklinkInput.cpp - DecklinkReader.cpp - DecklinkOutput.cpp - DecklinkWriter.cpp) - ENDIF (BLACKMAGIC_FOUND) - - # Get list of headers file(GLOB_RECURSE headers ${CMAKE_SOURCE_DIR}/include/*.h) @@ -254,44 +284,71 @@ SET(CMAKE_MACOSX_RPATH 0) ############### CREATE LIBRARY ################# # Create shared openshot library -add_library(openshot SHARED - ${OPENSHOT_SOURCE_FILES} - ${headers} ) +add_library(openshot SHARED + ${OPENSHOT_SOURCE_FILES} + ${headers} ) # Set SONAME and other library properties set_target_properties(openshot - PROPERTIES - VERSION ${PROJECT_VERSION} - SOVERSION ${SO_VERSION} - INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib" - ) + PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${SO_VERSION} + INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib" + ) ############### LINK LIBRARY ################# SET ( REQUIRED_LIBRARIES - ${FFMPEG_LIBRARIES} ${LIBOPENSHOT_AUDIO_LIBRARIES} ${QT_LIBRARIES} ${PROFILER} ${JSONCPP_LIBRARY} ${ZMQ_LIBRARIES} ) - - IF (OPENMP_FOUND) - SET ( REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} ${OpenMP_CXX_FLAGS} ) - ENDIF (OPENMP_FOUND) - - IF (ImageMagick_FOUND) - SET ( REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} ${ImageMagick_LIBRARIES} ) - ENDIF (ImageMagick_FOUND) - IF (BLACKMAGIC_FOUND) - SET ( REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} ${BLACKMAGIC_LIBRARY_DIR} ) - ENDIF (BLACKMAGIC_FOUND) +IF (AVCODEC_FOUND) + SET ( REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} ${AVCODEC_LIBRARIES} ) +ENDIF (AVCODEC_FOUND) +IF (AVDEVICE_FOUND) + SET ( REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} ${AVDEVICE_LIBRARIES} ) +ENDIF (AVDEVICE_FOUND) +IF (AVFORMAT_FOUND) + SET ( REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} ${AVFORMAT_LIBRARIES} ) +ENDIF (AVFORMAT_FOUND) +IF (AVFILTER_FOUND) + SET ( REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} ${AVFILTER_LIBRARIES} ) +ENDIF (AVFILTER_FOUND) +IF (AVUTIL_FOUND) + SET ( REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} ${AVUTIL_LIBRARIES} ) +ENDIF (AVUTIL_FOUND) +IF (POSTPROC_FOUND) + SET ( REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} ${POSTPROC_LIBRARIES} ) +ENDIF (POSTPROC_FOUND) +IF (SWSCALE_FOUND) + SET ( REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} ${SWSCALE_LIBRARIES} ) +ENDIF (SWSCALE_FOUND) +IF (SWRESAMPLE_FOUND) + SET ( REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} ${SWRESAMPLE_LIBRARIES} ) +ENDIF (SWRESAMPLE_FOUND) +IF (AVRESAMPLE_FOUND) + SET ( REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} ${AVRESAMPLE_LIBRARIES} ) +ENDIF (AVRESAMPLE_FOUND) - IF (WIN32) - # Required for exception handling on Windows - SET ( REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} "imagehlp" "dbghelp" ) - ENDIF(WIN32) +IF (OPENMP_FOUND) + SET ( REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} ${OpenMP_CXX_FLAGS} ) +ENDIF (OPENMP_FOUND) + +IF (ImageMagick_FOUND) + SET ( REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} ${ImageMagick_LIBRARIES} ) +ENDIF (ImageMagick_FOUND) + +IF (BLACKMAGIC_FOUND) + SET ( REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} ${BLACKMAGIC_LIBRARY_DIR} ) +ENDIF (BLACKMAGIC_FOUND) + +IF (WIN32) + # Required for exception handling on Windows + SET ( REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} "imagehlp" "dbghelp" ) +ENDIF(WIN32) # Link all referenced libraries target_link_libraries(openshot ${REQUIRED_LIBRARIES}) @@ -314,9 +371,9 @@ target_link_libraries(openshot-player openshot) ############### TEST BLACKMAGIC CAPTURE APP ################ IF (BLACKMAGIC_FOUND) # Create test executable - add_executable(openshot-blackmagic - examples/ExampleBlackmagic.cpp) - + add_executable(openshot-blackmagic + examples/ExampleBlackmagic.cpp) + # Link test executable to the new library target_link_libraries(openshot-blackmagic openshot) ENDIF (BLACKMAGIC_FOUND) @@ -330,13 +387,13 @@ set(LIB_INSTALL_DIR lib${LIB_SUFFIX}) # determine correct lib folder # Install primary library INSTALL( TARGETS openshot - ARCHIVE DESTINATION ${LIB_INSTALL_DIR} - LIBRARY DESTINATION ${LIB_INSTALL_DIR} - COMPONENT library ) - + ARCHIVE DESTINATION ${LIB_INSTALL_DIR} + LIBRARY DESTINATION ${LIB_INSTALL_DIR} + COMPONENT library ) + INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/include/ - DESTINATION ${CMAKE_INSTALL_PREFIX}/include/libopenshot -FILES_MATCHING PATTERN "*.h") + DESTINATION ${CMAKE_INSTALL_PREFIX}/include/libopenshot + FILES_MATCHING PATTERN "*.h") ############### CPACK PACKAGING ############## IF(MINGW) diff --git a/src/Clip.cpp b/src/Clip.cpp index 913fd71f..8e33f84c 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -671,6 +671,7 @@ std::shared_ptr Clip::GetOrCreateFrame(int64_t number) new_frame = std::make_shared(number, reader->info.width, reader->info.height, "#000000", samples_in_frame, reader->info.channels); new_frame->SampleRate(reader->info.sample_rate); new_frame->ChannelsLayout(reader->info.channel_layout); + new_frame->AddAudioSilence(samples_in_frame); return new_frame; } @@ -925,13 +926,14 @@ void Clip::SetJsonValue(Json::Value root) { if (!existing_effect["type"].isNull()) { // Create instance of effect - e = EffectInfo().CreateEffect(existing_effect["type"].asString()); + if (e = EffectInfo().CreateEffect(existing_effect["type"].asString())) { - // Load Json into Effect - e->SetJsonValue(existing_effect); + // Load Json into Effect + e->SetJsonValue(existing_effect); - // Add Effect to Timeline - AddEffect(e); + // Add Effect to Timeline + AddEffect(e); + } } } } diff --git a/src/EffectInfo.cpp b/src/EffectInfo.cpp index 23bc9d02..f9e4c409 100644 --- a/src/EffectInfo.cpp +++ b/src/EffectInfo.cpp @@ -82,6 +82,7 @@ EffectBase* EffectInfo::CreateEffect(string effect_type) { else if (effect_type == "Wave") return new Wave(); + return NULL; } // Generate Json::JsonValue for this object diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index 0b100050..17a612c1 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -37,11 +37,12 @@ FFmpegReader::FFmpegReader(string path) audio_pts_offset(99999), video_pts_offset(99999), path(path), is_video_seek(true), check_interlace(false), 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) { + 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) { // Initialize FFMpeg, and register all formats and codecs - av_register_all(); - avcodec_register_all(); + AV_REGISTER_ALL + AVCODEC_REGISTER_ALL // Init cache working_cache.SetMaxBytesFromInfo(OPEN_MP_NUM_PROCESSORS * info.fps.ToDouble() * 2, info.width, info.height, info.sample_rate, info.channels); @@ -58,11 +59,12 @@ FFmpegReader::FFmpegReader(string path, bool inspect_reader) audio_pts_offset(99999), video_pts_offset(99999), path(path), is_video_seek(true), check_interlace(false), 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) { + 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) { // Initialize FFMpeg, and register all formats and codecs - av_register_all(); - avcodec_register_all(); + AV_REGISTER_ALL + AVCODEC_REGISTER_ALL // Init cache working_cache.SetMaxBytesFromInfo(OPEN_MP_NUM_PROCESSORS * info.fps.ToDouble() * 2, info.width, info.height, info.sample_rate, info.channels); @@ -227,6 +229,9 @@ 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; } @@ -602,6 +607,12 @@ std::shared_ptr FFmpegReader::ReadStream(int64_t requested_frame) // Process Video Packet ProcessVideoPacket(requested_frame); + + if (!use_omp_threads) { + // 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 + } } } @@ -634,7 +645,6 @@ std::shared_ptr FFmpegReader::ReadStream(int64_t requested_frame) } // Check if working frames are 'finished' - bool is_cache_found = false; if (!is_seeking) { // Check for any missing frames CheckMissingFrame(requested_frame); @@ -644,7 +654,7 @@ std::shared_ptr FFmpegReader::ReadStream(int64_t requested_frame) } // Check if requested 'final' frame is available - is_cache_found = (final_cache.GetFrame(requested_frame) != NULL); + bool is_cache_found = (final_cache.GetFrame(requested_frame) != NULL); // Increment frames processed packets_processed++; @@ -656,6 +666,7 @@ std::shared_ptr FFmpegReader::ReadStream(int64_t requested_frame) } // end while } // end omp single + } // end omp parallel // Debug output @@ -904,7 +915,7 @@ void FFmpegReader::ProcessVideoPacket(int64_t requested_frame) AV_COPY_PICTURE_DATA(pFrameRGB, buffer, PIX_FMT_RGBA, width, height); SwsContext *img_convert_ctx = sws_getContext(info.width, info.height, AV_GET_CODEC_PIXEL_FORMAT(pStream, pCodecCtx), width, - height, PIX_FMT_RGBA, SWS_BILINEAR, NULL, NULL, NULL); + height, PIX_FMT_RGBA, SWS_LANCZOS, NULL, NULL, NULL); // Resize / Convert to RGB sws_scale(img_convert_ctx, my_frame->data, my_frame->linesize, 0, @@ -974,7 +985,7 @@ void FFmpegReader::ProcessAudioPacket(int64_t requested_frame, int64_t target_fr 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 + FF_INPUT_BUFFER_PADDING_SIZE; + int buf_size = AVCODEC_MAX_AUDIO_FRAME_SIZE + MY_INPUT_BUFFER_PADDING_SIZE; #pragma omp critical (ProcessAudioPacket) { #if IS_FFMPEG_3_2 @@ -1079,7 +1090,7 @@ void FFmpegReader::ProcessAudioPacket(int64_t requested_frame, int64_t target_fr // Allocate audio buffer - int16_t *audio_buf = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; + int16_t *audio_buf = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE + MY_INPUT_BUFFER_PADDING_SIZE]; ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ProcessAudioPacket (ReSample)", "packet_samples", packet_samples, "info.channels", info.channels, "info.sample_rate", info.sample_rate, "aCodecCtx->sample_fmt", AV_GET_SAMPLE_FORMAT(aStream, aCodecCtx), "AV_SAMPLE_FMT_S16", AV_SAMPLE_FMT_S16, "", -1); @@ -1089,11 +1100,11 @@ void FFmpegReader::ProcessAudioPacket(int64_t requested_frame, int64_t target_fr audio_converted->nb_samples = audio_frame->nb_samples; av_samples_alloc(audio_converted->data, audio_converted->linesize, info.channels, audio_frame->nb_samples, AV_SAMPLE_FMT_S16, 0); - AVAudioResampleContext *avr = NULL; + SWRCONTEXT *avr = NULL; int nb_samples = 0; // setup resample context - avr = avresample_alloc_context(); + avr = SWR_ALLOC(); av_opt_set_int(avr, "in_channel_layout", AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout, 0); av_opt_set_int(avr, "out_channel_layout", AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout, 0); av_opt_set_int(avr, "in_sample_fmt", AV_GET_SAMPLE_FORMAT(aStream, aCodecCtx), 0); @@ -1102,10 +1113,10 @@ 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 = avresample_open(avr); + int r = SWR_INIT(avr); // Convert audio samples - nb_samples = avresample_convert(avr, // audio resample context + nb_samples = SWR_CONVERT(avr, // audio resample context audio_converted->data, // output data pointers audio_converted->linesize[0], // output plane size, in bytes. (0 if unknown) audio_converted->nb_samples, // maximum number of samples that the output buffer can hold @@ -1117,8 +1128,8 @@ void FFmpegReader::ProcessAudioPacket(int64_t requested_frame, int64_t target_fr memcpy(audio_buf, audio_converted->data[0], audio_converted->nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * info.channels); // Deallocate resample buffer - avresample_close(avr); - avresample_free(&avr); + SWR_CLOSE(avr); + SWR_FREE(&avr); avr = NULL; // Free AVFrames @@ -1344,7 +1355,7 @@ void FFmpegReader::Seek(int64_t requested_frame) { seek_target = ConvertFrameToVideoPTS(requested_frame - buffer_amount); if (av_seek_frame(pFormatCtx, info.video_stream_index, seek_target, AVSEEK_FLAG_BACKWARD) < 0) { - fprintf(stderr, "%s: error while seeking video stream\n", pFormatCtx->filename); + fprintf(stderr, "%s: error while seeking video stream\n", pFormatCtx->AV_FILENAME); } else { // VIDEO SEEK @@ -1358,7 +1369,7 @@ void FFmpegReader::Seek(int64_t requested_frame) { seek_target = ConvertFrameToAudioPTS(requested_frame - buffer_amount); if (av_seek_frame(pFormatCtx, info.audio_stream_index, seek_target, AVSEEK_FLAG_BACKWARD) < 0) { - fprintf(stderr, "%s: error while seeking audio stream\n", pFormatCtx->filename); + fprintf(stderr, "%s: error while seeking audio stream\n", pFormatCtx->AV_FILENAME); } else { // AUDIO SEEK @@ -1853,6 +1864,8 @@ void FFmpegReader::CheckWorkingFrames(bool end_of_stream, int64_t requested_fram void FFmpegReader::CheckFPS() { check_fps = true; + AV_ALLOCATE_IMAGE(pFrame, AV_GET_CODEC_PIXEL_FORMAT(pStream, pCodecCtx), info.width, info.height); + int first_second_counter = 0; int second_second_counter = 0; int third_second_counter = 0; diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index ede07a43..11017219 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -46,7 +46,7 @@ FFmpegWriter::FFmpegWriter(string path) : info.has_video = false; // Initialize FFMpeg, and register all formats and codecs - av_register_all(); + AV_REGISTER_ALL // auto detect format auto_detect_format(); @@ -299,7 +299,7 @@ void FFmpegWriter::SetOption(StreamType stream, string name, string value) /// Determine if codec name is valid bool FFmpegWriter::IsValidCodec(string codec_name) { // Initialize FFMpeg, and register all formats and codecs - av_register_all(); + AV_REGISTER_ALL // Find the codec (if any) if (avcodec_find_encoder_by_name(codec_name.c_str()) == NULL) @@ -342,7 +342,7 @@ void FFmpegWriter::WriteHeader() } // Force the output filename (which doesn't always happen for some reason) - snprintf(oc->filename, sizeof(oc->filename), "%s", path.c_str()); + snprintf(oc->AV_FILENAME, sizeof(oc->AV_FILENAME), "%s", path.c_str()); // Write the stream header, if any // TODO: add avoptions / parameters instead of NULL @@ -559,8 +559,10 @@ void FFmpegWriter::flush_encoders() { if (info.has_audio && audio_codec && AV_GET_CODEC_TYPE(audio_st) == AVMEDIA_TYPE_AUDIO && AV_GET_CODEC_ATTRIBUTES(audio_st, audio_codec)->frame_size <= 1) return; +#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; +#endif int error_code = 0; int stop_encoding = 1; @@ -751,14 +753,14 @@ void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st) // Deallocate resample buffer if (avr) { - avresample_close(avr); - avresample_free(&avr); + SWR_CLOSE(avr); + SWR_FREE(&avr); avr = NULL; } if (avr_planar) { - avresample_close(avr_planar); - avresample_free(&avr_planar); + SWR_CLOSE(avr_planar); + SWR_FREE(&avr_planar); avr_planar = NULL; } } @@ -898,7 +900,11 @@ AVStream* FFmpegWriter::add_audio_stream() // some formats want stream headers to be separate if (oc->oformat->flags & AVFMT_GLOBALHEADER) +#if (LIBAVCODEC_VERSION_MAJOR >= 57) + c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; +#else c->flags |= CODEC_FLAG_GLOBAL_HEADER; +#endif AV_COPY_PARAMS_FROM_CONTEXT(st, c); ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::add_audio_stream", "c->codec_id", c->codec_id, "c->bit_rate", c->bit_rate, "c->channels", c->channels, "c->sample_fmt", c->sample_fmt, "c->channel_layout", c->channel_layout, "c->sample_rate", c->sample_rate); @@ -970,7 +976,11 @@ AVStream* FFmpegWriter::add_video_stream() c->mb_decision = 2; // some formats want stream headers to be separate if (oc->oformat->flags & AVFMT_GLOBALHEADER) +#if (LIBAVCODEC_VERSION_MAJOR >= 57) + c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; +#else c->flags |= CODEC_FLAG_GLOBAL_HEADER; +#endif // Find all supported pixel formats for this codec const PixelFormat* supported_pixel_formats = codec->pix_fmts; @@ -987,10 +997,12 @@ AVStream* FFmpegWriter::add_video_stream() // Raw video should use RGB24 c->pix_fmt = PIX_FMT_RGB24; +#if (LIBAVFORMAT_VERSION_MAJOR < 58) if (strcmp(fmt->name, "gif") != 0) // If not GIF format, skip the encoding process // Set raw picture flag (so we don't encode this video) oc->oformat->flags |= AVFMT_RAWPICTURE; +#endif } else { // Set the default codec c->pix_fmt = PIX_FMT_YUV420P; @@ -998,7 +1010,11 @@ AVStream* FFmpegWriter::add_video_stream() } AV_COPY_PARAMS_FROM_CONTEXT(st, c); +#if (LIBAVFORMAT_VERSION_MAJOR < 58) ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::add_video_stream (" + (string)fmt->name + " : " + (string)av_get_pix_fmt_name(c->pix_fmt) + ")", "c->codec_id", c->codec_id, "c->bit_rate", c->bit_rate, "c->pix_fmt", c->pix_fmt, "oc->oformat->flags", oc->oformat->flags, "AVFMT_RAWPICTURE", AVFMT_RAWPICTURE, "", -1); +#else + ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::add_video_stream (" + (string)fmt->name + " : " + (string)av_get_pix_fmt_name(c->pix_fmt) + ")", "c->codec_id", c->codec_id, "c->bit_rate", c->bit_rate, "c->pix_fmt", c->pix_fmt, "oc->oformat->flags", oc->oformat->flags, "", -1, "", -1); +#endif return st; } @@ -1073,7 +1089,7 @@ void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st) av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0); } - ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::open_audio", "audio_codec->thread_count", audio_codec->thread_count, "audio_input_frame_size", audio_input_frame_size, "buffer_size", AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE, "", -1, "", -1, "", -1); + ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::open_audio", "audio_codec->thread_count", audio_codec->thread_count, "audio_input_frame_size", audio_input_frame_size, "buffer_size", AVCODEC_MAX_AUDIO_FRAME_SIZE + MY_INPUT_BUFFER_PADDING_SIZE, "", -1, "", -1, "", -1); } @@ -1239,7 +1255,7 @@ void FFmpegWriter::write_audio_packets(bool final) // setup resample context if (!avr) { - avr = avresample_alloc_context(); + avr = SWR_ALLOC(); av_opt_set_int(avr, "in_channel_layout", channel_layout_in_frame, 0); av_opt_set_int(avr, "out_channel_layout", info.channel_layout, 0); av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); @@ -1248,12 +1264,12 @@ void FFmpegWriter::write_audio_packets(bool final) av_opt_set_int(avr, "out_sample_rate", info.sample_rate, 0); av_opt_set_int(avr, "in_channels", channels_in_frame, 0); av_opt_set_int(avr, "out_channels", info.channels, 0); - avresample_open(avr); + SWR_INIT(avr); } int nb_samples = 0; // Convert audio samples - nb_samples = avresample_convert(avr, // audio resample context + nb_samples = SWR_CONVERT(avr, // audio resample context audio_converted->data, // output data pointers audio_converted->linesize[0], // output plane size, in bytes. (0 if unknown) audio_converted->nb_samples, // maximum number of samples that the output buffer can hold @@ -1314,7 +1330,7 @@ void FFmpegWriter::write_audio_packets(bool final) // setup resample context if (!avr_planar) { - avr_planar = avresample_alloc_context(); + avr_planar = SWR_ALLOC(); av_opt_set_int(avr_planar, "in_channel_layout", info.channel_layout, 0); av_opt_set_int(avr_planar, "out_channel_layout", info.channel_layout, 0); av_opt_set_int(avr_planar, "in_sample_fmt", output_sample_fmt, 0); @@ -1323,7 +1339,7 @@ void FFmpegWriter::write_audio_packets(bool final) av_opt_set_int(avr_planar, "out_sample_rate", info.sample_rate, 0); av_opt_set_int(avr_planar, "in_channels", info.channels, 0); av_opt_set_int(avr_planar, "out_channels", info.channels, 0); - avresample_open(avr_planar); + SWR_INIT(avr_planar); } // Create input frame (and allocate arrays) @@ -1346,7 +1362,7 @@ void FFmpegWriter::write_audio_packets(bool final) av_samples_alloc(frame_final->data, frame_final->linesize, info.channels, frame_final->nb_samples, audio_codec->sample_fmt, 0); // Convert audio samples - int nb_samples = avresample_convert(avr_planar, // audio resample context + int nb_samples = SWR_CONVERT(avr_planar, // audio resample context frame_final->data, // output data pointers frame_final->linesize[0], // output plane size, in bytes. (0 if unknown) frame_final->nb_samples, // maximum number of samples that the output buffer can hold @@ -1577,6 +1593,9 @@ void FFmpegWriter::process_video_packet(std::shared_ptr frame) // write video 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, "", -1, "", -1, "", -1, "", -1); +#else ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet", "frame->number", frame->number, "oc->oformat->flags & AVFMT_RAWPICTURE", oc->oformat->flags & AVFMT_RAWPICTURE, "", -1, "", -1, "", -1, "", -1); if (oc->oformat->flags & AVFMT_RAWPICTURE) { @@ -1604,7 +1623,9 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame* fra // Deallocate packet AV_FREE_PACKET(&pkt); - } else { + } else +#endif + { AVPacket pkt; av_init_packet(&pkt); @@ -1731,7 +1752,7 @@ void FFmpegWriter::InitScalers(int source_width, int source_height) for (int x = 0; x < num_of_rescalers; x++) { // Init the software scaler from FFMpeg - img_convert_ctx = sws_getContext(source_width, source_height, PIX_FMT_RGBA, info.width, info.height, AV_GET_CODEC_PIXEL_FORMAT(video_st, video_st->codec), SWS_BILINEAR, NULL, NULL, NULL); + img_convert_ctx = sws_getContext(source_width, source_height, PIX_FMT_RGBA, info.width, info.height, AV_GET_CODEC_PIXEL_FORMAT(video_st, video_st->codec), SWS_LANCZOS, NULL, NULL, NULL); // Add rescaler to vector image_rescalers.push_back(img_convert_ctx); diff --git a/src/FrameMapper.cpp b/src/FrameMapper.cpp index f49cbc4d..1817c049 100644 --- a/src/FrameMapper.cpp +++ b/src/FrameMapper.cpp @@ -376,6 +376,7 @@ std::shared_ptr FrameMapper::GetOrCreateFrame(int64_t number) new_frame = std::make_shared(number, info.width, info.height, "#000000", samples_in_frame, reader->info.channels); new_frame->SampleRate(reader->info.sample_rate); new_frame->ChannelsLayout(info.channel_layout); + new_frame->AddAudioSilence(samples_in_frame); return new_frame; } @@ -650,8 +651,8 @@ void FrameMapper::Close() // Deallocate resample buffer if (avr) { - avresample_close(avr); - avresample_free(&avr); + SWR_CLOSE(avr); + SWR_FREE(&avr); avr = NULL; } } @@ -741,8 +742,8 @@ void FrameMapper::ChangeMapping(Fraction target_fps, PulldownType target_pulldow // Deallocate resample buffer if (avr) { - avresample_close(avr); - avresample_free(&avr); + SWR_CLOSE(avr); + SWR_FREE(&avr); avr = NULL; } @@ -817,7 +818,7 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr frame, int64_t orig // setup resample context if (!avr) { - avr = avresample_alloc_context(); + avr = SWR_ALLOC(); av_opt_set_int(avr, "in_channel_layout", channel_layout_in_frame, 0); av_opt_set_int(avr, "out_channel_layout", info.channel_layout, 0); av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); @@ -826,11 +827,11 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr frame, int64_t orig av_opt_set_int(avr, "out_sample_rate", info.sample_rate, 0); av_opt_set_int(avr, "in_channels", channels_in_frame, 0); av_opt_set_int(avr, "out_channels", info.channels, 0); - avresample_open(avr); + SWR_INIT(avr); } // Convert audio samples - nb_samples = avresample_convert(avr, // audio resample context + nb_samples = SWR_CONVERT(avr, // audio resample context audio_converted->data, // output data pointers audio_converted->linesize[0], // output plane size, in bytes. (0 if unknown) audio_converted->nb_samples, // maximum number of samples that the output buffer can hold diff --git a/src/Timeline.cpp b/src/Timeline.cpp index d042aeeb..db406efc 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -576,8 +576,13 @@ void Timeline::update_open_clips(Clip *clip, bool does_clip_intersect) // Add clip to 'opened' list, because it's missing open_clips[clip] = clip; - // Open the clip - clip->Open(); + try { + // Open the clip + clip->Open(); + + } catch (const InvalidFile & e) { + // ... + } } // Debug output @@ -717,7 +722,7 @@ std::shared_ptr Timeline::GetFrame(int64_t requested_frame) #pragma omp parallel { // Loop through all requested frames - #pragma omp for ordered firstprivate(nearby_clips, requested_frame, minimum_frames) + #pragma omp for ordered firstprivate(nearby_clips, requested_frame, minimum_frames) schedule(static,1) for (int64_t frame_number = requested_frame; frame_number < requested_frame + minimum_frames; frame_number++) { // Debug output @@ -1000,13 +1005,14 @@ void Timeline::SetJsonValue(Json::Value root) { if (!existing_effect["type"].isNull()) { // Create instance of effect - e = EffectInfo().CreateEffect(existing_effect["type"].asString()); + if (e = EffectInfo().CreateEffect(existing_effect["type"].asString())) { - // Load Json into Effect - e->SetJsonValue(existing_effect); + // Load Json into Effect + e->SetJsonValue(existing_effect); - // Add Effect to Timeline - AddEffect(e); + // Add Effect to Timeline + AddEffect(e); + } } } } @@ -1270,13 +1276,14 @@ void Timeline::apply_json_to_effects(Json::Value change, EffectBase* existing_ef EffectBase *e = NULL; // Init the matching effect object - e = EffectInfo().CreateEffect(effect_type); + if (e = EffectInfo().CreateEffect(effect_type)) { - // Load Json into Effect - e->SetJsonValue(change["value"]); + // Load Json into Effect + e->SetJsonValue(change["value"]); - // Add Effect to Timeline - AddEffect(e); + // Add Effect to Timeline + AddEffect(e); + } } else if (change_type == "update") { diff --git a/tests/FrameMapper_Tests.cpp b/tests/FrameMapper_Tests.cpp index 2f61179d..053df31f 100644 --- a/tests/FrameMapper_Tests.cpp +++ b/tests/FrameMapper_Tests.cpp @@ -199,9 +199,9 @@ TEST(FrameMapper_resample_audio_48000_to_41000) // Check details CHECK_EQUAL(1, map.GetFrame(1)->GetAudioChannelsCount()); - CHECK_EQUAL(882, map.GetFrame(1)->GetAudioSamplesCount()); - CHECK_EQUAL(882, map.GetFrame(2)->GetAudioSamplesCount()); - CHECK_EQUAL(882, map.GetFrame(50)->GetAudioSamplesCount()); + CHECK_CLOSE(882, map.GetFrame(1)->GetAudioSamplesCount(), 10.0); + CHECK_CLOSE(882, map.GetFrame(2)->GetAudioSamplesCount(), 10.0); + CHECK_CLOSE(882, map.GetFrame(50)->GetAudioSamplesCount(), 10.0); // Close mapper map.Close(); diff --git a/tests/ReaderBase_Tests.cpp b/tests/ReaderBase_Tests.cpp index 9d435304..70ca90d5 100644 --- a/tests/ReaderBase_Tests.cpp +++ b/tests/ReaderBase_Tests.cpp @@ -44,9 +44,9 @@ TEST(ReaderBase_Derived_Class) std::shared_ptr GetFrame(int64_t number) { std::shared_ptr f(new Frame()); return f; } void Close() { }; void Open() { }; - string Json() { }; + string Json() { return NULL; }; void SetJson(string value) { }; - Json::Value JsonValue() { }; + Json::Value JsonValue() { return (int) NULL; }; void SetJsonValue(Json::Value root) { }; bool IsOpen() { return true; }; string Name() { return "TestReader"; };