From b934702c7fad821cd079050c5e94aa692c05c830 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 31 May 2018 15:39:59 +0300 Subject: [PATCH] cmake: support find_package(FFMPEG) Use "OPENCV_FFMPEG_USE_FIND_PACKAGE" variable to specify find_package() parameters --- CMakeLists.txt | 4 +- cmake/OpenCVFindLibsVideo.cmake | 53 +++++++++------ modules/videoio/CMakeLists.txt | 11 ++- modules/videoio/src/cap_ffmpeg.cpp | 92 +++++++++++++++++--------- modules/videoio/src/cap_ffmpeg_api.hpp | 22 +++--- 5 files changed, 114 insertions(+), 68 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5190c5081f..c78abbc247 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1250,7 +1250,9 @@ if(WITH_1394 OR HAVE_DC1394) endif() if(WITH_FFMPEG OR HAVE_FFMPEG) - if(WIN32) + if(OPENCV_FFMPEG_USE_FIND_PACKAGE) + status(" FFMPEG:" HAVE_FFMPEG THEN "YES (find_package)" ELSE "NO (find_package)") + elseif(WIN32) status(" FFMPEG:" HAVE_FFMPEG THEN "YES (prebuilt binaries)" ELSE NO) else() status(" FFMPEG:" HAVE_FFMPEG THEN YES ELSE NO) diff --git a/cmake/OpenCVFindLibsVideo.cmake b/cmake/OpenCVFindLibsVideo.cmake index 9ed9ceb823..b9d15c38b8 100644 --- a/cmake/OpenCVFindLibsVideo.cmake +++ b/cmake/OpenCVFindLibsVideo.cmake @@ -212,12 +212,23 @@ endif(WITH_XIMEA) # --- FFMPEG --- ocv_clear_vars(HAVE_FFMPEG) -if(WITH_FFMPEG) - if(WIN32 AND NOT ARM) +if(WITH_FFMPEG) # try FFmpeg autodetection + if(OPENCV_FFMPEG_USE_FIND_PACKAGE) + if(OPENCV_FFMPEG_USE_FIND_PACKAGE STREQUAL "1" OR OPENCV_FFMPEG_USE_FIND_PACKAGE STREQUAL "ON") + set(OPENCV_FFMPEG_USE_FIND_PACKAGE "FFMPEG") + endif() + find_package(${OPENCV_FFMPEG_USE_FIND_PACKAGE}) # Required components: AVCODEC AVFORMAT AVUTIL SWSCALE + if(FFMPEG_FOUND OR FFmpeg_FOUND) + set(HAVE_FFMPEG TRUE) + else() + message(STATUS "Can't find FFmpeg via find_package(${OPENCV_FFMPEG_USE_FIND_PACKAGE})") + endif() + elseif(WIN32 AND NOT ARM AND NOT OPENCV_FFMPEG_SKIP_DOWNLOAD) include("${OpenCV_SOURCE_DIR}/3rdparty/ffmpeg/ffmpeg.cmake") download_win_ffmpeg(FFMPEG_CMAKE_SCRIPT) if(FFMPEG_CMAKE_SCRIPT) set(HAVE_FFMPEG TRUE) + set(HAVE_FFMPEG_WRAPPER 1) include("${FFMPEG_CMAKE_SCRIPT}") endif() elseif(PKG_CONFIG_FOUND) @@ -226,27 +237,29 @@ if(WITH_FFMPEG) if(FFMPEG_libavresample_FOUND) ocv_append_build_options(FFMPEG FFMPEG_libavresample) endif() - if(HAVE_FFMPEG) - try_compile(__VALID_FFMPEG - "${OpenCV_BINARY_DIR}" - "${OpenCV_SOURCE_DIR}/cmake/checks/ffmpeg_test.cpp" - CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${FFMPEG_INCLUDE_DIRS}" - "-DLINK_DIRECTORIES:STRING=${FFMPEG_LIBRARY_DIRS}" - "-DLINK_LIBRARIES:STRING=${FFMPEG_LIBRARIES}" - OUTPUT_VARIABLE TRY_OUT - ) - if(NOT __VALID_FFMPEG) - #message(FATAL_ERROR "FFMPEG: test check build log:\n${TRY_OUT}") - message(STATUS "WARNING: Can't build ffmpeg test code") - set(HAVE_FFMPEG FALSE) - else() - ocv_append_build_options(VIDEOIO FFMPEG) - endif() - endif() else() message(STATUS "Can't find ffmpeg - 'pkg-config' utility is missing") endif() -endif(WITH_FFMPEG) +endif() +if(HAVE_FFMPEG + AND NOT HAVE_FFMPEG_WRAPPER +) + try_compile(__VALID_FFMPEG + "${OpenCV_BINARY_DIR}" + "${OpenCV_SOURCE_DIR}/cmake/checks/ffmpeg_test.cpp" + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${FFMPEG_INCLUDE_DIRS}" + "-DLINK_DIRECTORIES:STRING=${FFMPEG_LIBRARY_DIRS}" + "-DLINK_LIBRARIES:STRING=${FFMPEG_LIBRARIES}" + OUTPUT_VARIABLE TRY_OUT + ) + if(NOT __VALID_FFMPEG) + #message(FATAL_ERROR "FFMPEG: test check build log:\n${TRY_OUT}") + message(STATUS "WARNING: Can't build ffmpeg test code") + set(HAVE_FFMPEG FALSE) + else() + ocv_append_build_options(VIDEOIO FFMPEG) + endif() +endif() # --- VideoInput/DirectShow --- if(WITH_DSHOW) diff --git a/modules/videoio/CMakeLists.txt b/modules/videoio/CMakeLists.txt index c6fee91924..f5eba046c5 100644 --- a/modules/videoio/CMakeLists.txt +++ b/modules/videoio/CMakeLists.txt @@ -167,6 +167,9 @@ if(HAVE_FFMPEG) if(APPLE) list(APPEND VIDEOIO_LIBRARIES "-framework VideoDecodeAcceleration" bz2) endif() + if(HAVE_FFMPEG_WRAPPER) + add_definitions(-DHAVE_FFMPEG_WRAPPER=1) + endif() endif(HAVE_FFMPEG) if(HAVE_PVAPI) @@ -230,12 +233,6 @@ if(IOS) list(APPEND VIDEOIO_LIBRARIES "-framework Accelerate" "-framework AVFoundation" "-framework CoreGraphics" "-framework CoreImage" "-framework CoreMedia" "-framework CoreVideo" "-framework QuartzCore" "-framework UIKit") endif() -if(WIN32) - link_directories("${OpenCV_SOURCE_DIR}/3rdparty/lib") # for ffmpeg wrapper only - include_directories(AFTER SYSTEM "${OpenCV_SOURCE_DIR}/3rdparty/include") # for directshow in VS2005 and multi-monitor support on MinGW - include_directories(AFTER SYSTEM "${OpenCV_SOURCE_DIR}/3rdparty/include/ffmpeg_") # for tests -endif() - if(UNIX) #these variables are set by CHECK_MODULE macro foreach(P ${VIDEOIO_INCLUDE_DIRS}) @@ -268,7 +265,7 @@ endif() ocv_warnings_disable(CMAKE_CXX_FLAGS -Wno-deprecated-declarations) -if(WIN32 AND HAVE_FFMPEG) +if(WIN32 AND HAVE_FFMPEG_WRAPPER) #copy ffmpeg dll to the output folder if(MSVC64 OR MINGW64) set(FFMPEG_SUFFIX _64) diff --git a/modules/videoio/src/cap_ffmpeg.cpp b/modules/videoio/src/cap_ffmpeg.cpp index 25f7aa60b5..14353ad13c 100644 --- a/modules/videoio/src/cap_ffmpeg.cpp +++ b/modules/videoio/src/cap_ffmpeg.cpp @@ -41,13 +41,28 @@ #include "precomp.hpp" +#if defined(HAVE_FFMPEG) + #include -#if defined HAVE_FFMPEG && !defined _WIN32 +#if !defined(HAVE_FFMPEG_WRAPPER) #include "cap_ffmpeg_impl.hpp" + +#define icvCreateFileCapture_FFMPEG_p cvCreateFileCapture_FFMPEG +#define icvReleaseCapture_FFMPEG_p cvReleaseCapture_FFMPEG +#define icvGrabFrame_FFMPEG_p cvGrabFrame_FFMPEG +#define icvRetrieveFrame_FFMPEG_p cvRetrieveFrame_FFMPEG +#define icvSetCaptureProperty_FFMPEG_p cvSetCaptureProperty_FFMPEG +#define icvGetCaptureProperty_FFMPEG_p cvGetCaptureProperty_FFMPEG +#define icvCreateVideoWriter_FFMPEG_p cvCreateVideoWriter_FFMPEG +#define icvReleaseVideoWriter_FFMPEG_p cvReleaseVideoWriter_FFMPEG +#define icvWriteFrame_FFMPEG_p cvWriteFrame_FFMPEG + #else + #include "cap_ffmpeg_api.hpp" -#endif + +namespace cv { namespace { static CvCreateFileCapture_Plugin icvCreateFileCapture_FFMPEG_p = 0; static CvReleaseCapture_Plugin icvReleaseCapture_FFMPEG_p = 0; @@ -99,7 +114,7 @@ private: icvInitFFMPEG() { - #if defined _WIN32 +#if defined _WIN32 const wchar_t* module_name_ = L"opencv_ffmpeg" CVAUX_STRW(CV_MAJOR_VERSION) CVAUX_STRW(CV_MINOR_VERSION) CVAUX_STRW(CV_SUBMINOR_VERSION) #if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__) @@ -161,7 +176,7 @@ private: (CvReleaseVideoWriter_Plugin)GetProcAddress(icvFFOpenCV, "cvReleaseVideoWriter_FFMPEG"); icvWriteFrame_FFMPEG_p = (CvWriteFrame_Plugin)GetProcAddress(icvFFOpenCV, "cvWriteFrame_FFMPEG"); - +# endif // _WIN32 #if 0 if( icvCreateFileCapture_FFMPEG_p != 0 && icvReleaseCapture_FFMPEG_p != 0 && @@ -181,21 +196,18 @@ private: } #endif } - #elif defined HAVE_FFMPEG - icvCreateFileCapture_FFMPEG_p = (CvCreateFileCapture_Plugin)cvCreateFileCapture_FFMPEG; - icvReleaseCapture_FFMPEG_p = (CvReleaseCapture_Plugin)cvReleaseCapture_FFMPEG; - icvGrabFrame_FFMPEG_p = (CvGrabFrame_Plugin)cvGrabFrame_FFMPEG; - icvRetrieveFrame_FFMPEG_p = (CvRetrieveFrame_Plugin)cvRetrieveFrame_FFMPEG; - icvSetCaptureProperty_FFMPEG_p = (CvSetCaptureProperty_Plugin)cvSetCaptureProperty_FFMPEG; - icvGetCaptureProperty_FFMPEG_p = (CvGetCaptureProperty_Plugin)cvGetCaptureProperty_FFMPEG; - icvCreateVideoWriter_FFMPEG_p = (CvCreateVideoWriter_Plugin)cvCreateVideoWriter_FFMPEG; - icvReleaseVideoWriter_FFMPEG_p = (CvReleaseVideoWriter_Plugin)cvReleaseVideoWriter_FFMPEG; - icvWriteFrame_FFMPEG_p = (CvWriteFrame_Plugin)cvWriteFrame_FFMPEG; - #endif } }; +}} // namespace +#endif // HAVE_FFMPEG_WRAPPER + + + +namespace cv { +namespace { + class CvCapture_FFMPEG_proxy CV_FINAL : public cv::IVideoCapture { public: @@ -228,19 +240,20 @@ public: } virtual bool open( const cv::String& filename ) { - icvInitFFMPEG::Init(); close(); - if( !icvCreateFileCapture_FFMPEG_p ) - return false; ffmpegCapture = icvCreateFileCapture_FFMPEG_p( filename.c_str() ); return ffmpegCapture != 0; } virtual void close() { - if( ffmpegCapture && icvReleaseCapture_FFMPEG_p ) + if (ffmpegCapture +#if defined(HAVE_FFMPEG_WRAPPER) + && icvReleaseCapture_FFMPEG_p +#endif +) icvReleaseCapture_FFMPEG_p( &ffmpegCapture ); - assert( ffmpegCapture == 0 ); + CV_Assert(ffmpegCapture == 0); ffmpegCapture = 0; } @@ -248,18 +261,26 @@ public: virtual int getCaptureDomain() CV_OVERRIDE { return CV_CAP_FFMPEG; } protected: - void* ffmpegCapture; + CvCapture_FFMPEG* ffmpegCapture; }; +} // namespace -cv::Ptr cv::cvCreateFileCapture_FFMPEG_proxy(const cv::String& filename) +cv::Ptr cvCreateFileCapture_FFMPEG_proxy(const cv::String& filename) { +#if defined(HAVE_FFMPEG_WRAPPER) + icvInitFFMPEG::Init(); + if (!icvCreateFileCapture_FFMPEG_p) + return cv::Ptr(); +#endif cv::Ptr capture = cv::makePtr(filename); if (capture && capture->isOpened()) return capture; return cv::Ptr(); } +namespace { + class CvVideoWriter_FFMPEG_proxy CV_FINAL : public cv::IVideoWriter { @@ -278,19 +299,20 @@ public: } virtual bool open( const cv::String& filename, int fourcc, double fps, cv::Size frameSize, bool isColor ) { - icvInitFFMPEG::Init(); close(); - if( !icvCreateVideoWriter_FFMPEG_p ) - return false; ffmpegWriter = icvCreateVideoWriter_FFMPEG_p( filename.c_str(), fourcc, fps, frameSize.width, frameSize.height, isColor ); return ffmpegWriter != 0; } virtual void close() { - if( ffmpegWriter && icvReleaseVideoWriter_FFMPEG_p ) + if (ffmpegWriter +#if defined(HAVE_FFMPEG_WRAPPER) + && icvReleaseVideoWriter_FFMPEG_p +#endif + ) icvReleaseVideoWriter_FFMPEG_p( &ffmpegWriter ); - assert( ffmpegWriter == 0 ); + CV_Assert(ffmpegWriter == 0); ffmpegWriter = 0; } @@ -299,15 +321,25 @@ public: virtual bool isOpened() const CV_OVERRIDE { return ffmpegWriter != 0; } protected: - void* ffmpegWriter; + CvVideoWriter_FFMPEG* ffmpegWriter; }; +} // namespace -cv::Ptr cv::cvCreateVideoWriter_FFMPEG_proxy(const cv::String& filename, int fourcc, - double fps, cv::Size frameSize, int isColor) +cv::Ptr cvCreateVideoWriter_FFMPEG_proxy(const cv::String& filename, int fourcc, + double fps, cv::Size frameSize, int isColor) { +#if defined(HAVE_FFMPEG_WRAPPER) + icvInitFFMPEG::Init(); + if (!icvCreateVideoWriter_FFMPEG_p) + return cv::Ptr(); +#endif cv::Ptr writer = cv::makePtr(filename, fourcc, fps, frameSize, isColor != 0); if (writer && writer->isOpened()) return writer; return cv::Ptr(); } + +} // namespace + +#endif // defined(HAVE_FFMPEG) diff --git a/modules/videoio/src/cap_ffmpeg_api.hpp b/modules/videoio/src/cap_ffmpeg_api.hpp index 7144f4ab9d..96bb8ee47c 100644 --- a/modules/videoio/src/cap_ffmpeg_api.hpp +++ b/modules/videoio/src/cap_ffmpeg_api.hpp @@ -28,6 +28,8 @@ enum CV_FFMPEG_CAP_PROP_SAR_DEN=41 }; +typedef struct CvCapture_FFMPEG CvCapture_FFMPEG; +typedef struct CvVideoWriter_FFMPEG CvVideoWriter_FFMPEG; OPENCV_FFMPEG_API struct CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG(const char* filename); OPENCV_FFMPEG_API struct CvCapture_FFMPEG_2* cvCreateFileCapture_FFMPEG_2(const char* filename); @@ -55,19 +57,19 @@ OPENCV_FFMPEG_API int cvWriteFrame_FFMPEG(struct CvVideoWriter_FFMPEG* writer, c OPENCV_FFMPEG_API void cvReleaseVideoWriter_FFMPEG(struct CvVideoWriter_FFMPEG** writer); -typedef void* (*CvCreateFileCapture_Plugin)( const char* filename ); -typedef void* (*CvCreateCameraCapture_Plugin)( int index ); -typedef int (*CvGrabFrame_Plugin)( void* capture_handle ); -typedef int (*CvRetrieveFrame_Plugin)( void* capture_handle, unsigned char** data, int* step, +typedef CvCapture_FFMPEG* (*CvCreateFileCapture_Plugin)( const char* filename ); +typedef CvCapture_FFMPEG* (*CvCreateCameraCapture_Plugin)( int index ); +typedef int (*CvGrabFrame_Plugin)( CvCapture_FFMPEG* capture_handle ); +typedef int (*CvRetrieveFrame_Plugin)( CvCapture_FFMPEG* capture_handle, unsigned char** data, int* step, int* width, int* height, int* cn ); -typedef int (*CvSetCaptureProperty_Plugin)( void* capture_handle, int prop_id, double value ); -typedef double (*CvGetCaptureProperty_Plugin)( void* capture_handle, int prop_id ); -typedef void (*CvReleaseCapture_Plugin)( void** capture_handle ); -typedef void* (*CvCreateVideoWriter_Plugin)( const char* filename, int fourcc, +typedef int (*CvSetCaptureProperty_Plugin)( CvCapture_FFMPEG* capture_handle, int prop_id, double value ); +typedef double (*CvGetCaptureProperty_Plugin)( CvCapture_FFMPEG* capture_handle, int prop_id ); +typedef void (*CvReleaseCapture_Plugin)( CvCapture_FFMPEG** capture_handle ); +typedef CvVideoWriter_FFMPEG* (*CvCreateVideoWriter_Plugin)( const char* filename, int fourcc, double fps, int width, int height, int iscolor ); -typedef int (*CvWriteFrame_Plugin)( void* writer_handle, const unsigned char* data, int step, +typedef int (*CvWriteFrame_Plugin)( CvVideoWriter_FFMPEG* writer_handle, const unsigned char* data, int step, int width, int height, int cn, int origin); -typedef void (*CvReleaseVideoWriter_Plugin)( void** writer ); +typedef void (*CvReleaseVideoWriter_Plugin)( CvVideoWriter_FFMPEG** writer ); /* * For CUDA encoder