videoio: plugins support on Win32
authorAlexander Alekhin <alexander.alekhin@intel.com>
Fri, 31 May 2019 13:18:00 +0000 (16:18 +0300)
committerAlexander Alekhin <alexander.a.alekhin@gmail.com>
Sun, 16 Jun 2019 15:25:25 +0000 (15:25 +0000)
16 files changed:
modules/core/include/opencv2/core/operations.hpp
modules/core/include/opencv2/core/private.hpp
modules/core/include/opencv2/core/utils/filesystem.hpp
modules/core/src/utils/datafile.cpp
modules/core/src/utils/filesystem.cpp
modules/videoio/CMakeLists.txt
modules/videoio/cmake/detect_ffmpeg.cmake
modules/videoio/cmake/plugin.cmake
modules/videoio/cmake/plugin_standalone.cmake
modules/videoio/src/backend_plugin.cpp
modules/videoio/src/cap_ffmpeg.cpp
modules/videoio/src/cap_ffmpeg_api.hpp [deleted file]
modules/videoio/src/cap_ffmpeg_impl.hpp
modules/videoio/src/cap_ffmpeg_legacy_api.hpp [new file with mode: 0644]
modules/videoio/src/precomp.hpp
modules/videoio/src/videoio_registry.cpp

index 64f7156..92943a6 100644 (file)
 #include <cstdio>
 
 #if defined(__GNUC__) || defined(__clang__) // at least GCC 3.1+, clang 3.5+
-#  define CV_FORMAT_PRINTF(string_idx, first_to_check) __attribute__ ((format (printf, string_idx, first_to_check)))
+#  if defined(__MINGW_PRINTF_FORMAT)  // https://sourceforge.net/p/mingw-w64/wiki2/gnu%20printf/.
+#    define CV_FORMAT_PRINTF(string_idx, first_to_check) __attribute__ ((format (__MINGW_PRINTF_FORMAT, string_idx, first_to_check)))
+#  else
+#    define CV_FORMAT_PRINTF(string_idx, first_to_check) __attribute__ ((format (printf, string_idx, first_to_check)))
+#  endif
 #else
 #  define CV_FORMAT_PRINTF(A, B)
 #endif
index 7762e07..5c10ba1 100644 (file)
@@ -872,9 +872,17 @@ Passed subdirectories are used in LIFO order.
 */
 CV_EXPORTS void addDataSearchSubDirectory(const cv::String& subdir);
 
-/** @brief Return location of OpenCV libraries or current executable
+/** @brief Retrieve location of OpenCV libraries or current executable
  */
-CV_EXPORTS std::string getBinLocation();
+CV_EXPORTS bool getBinLocation(std::string& dst);
+
+#if defined(_WIN32)
+/** @brief Retrieve location of OpenCV libraries or current executable
+
+@note WIN32 only
+ */
+CV_EXPORTS bool getBinLocation(std::wstring& dst);
+#endif
 
 //! @}
 
index 9f043be..a98d220 100644 (file)
@@ -28,6 +28,7 @@ CV_EXPORTS cv::String join(const cv::String& base, const cv::String& path);
 
 /** Get parent directory */
 CV_EXPORTS cv::String getParent(const cv::String &path);
+CV_EXPORTS std::wstring getParent(const std::wstring& path);
 
 /**
  * Generate a list of all files that match the globbing pattern.
index b3dc31f..aafbfdf 100644 (file)
@@ -144,11 +144,38 @@ static cv::String getModuleLocation(const void* addr)
     return cv::String();
 }
 
-std::string getBinLocation()
+bool getBinLocation(std::string& dst)
 {
-    return getModuleLocation((void*)getModuleLocation); // use code addr, doesn't work with static linkage!
+    dst = getModuleLocation((void*)getModuleLocation); // using code address, doesn't work with static linkage!
+    return !dst.empty();
 }
 
+#ifdef _WIN32
+bool getBinLocation(std::wstring& dst)
+{
+    void* addr = (void*)getModuleLocation; // using code address, doesn't work with static linkage!
+    HMODULE m = 0;
+#if _WIN32_WINNT >= 0x0501
+    ::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+        reinterpret_cast<LPCTSTR>(addr),
+        &m);
+#endif
+    if (m)
+    {
+        wchar_t path[4096];
+        const size_t path_size = sizeof(path)/sizeof(*path);
+        size_t sz = GetModuleFileNameW(m, path, path_size);
+        if (sz > 0 && sz < path_size)
+        {
+            path[sz] = '\0';
+            dst.assign(path, sz);
+            return true;
+        }
+    }
+    return false;
+}
+#endif
+
 cv::String findDataFile(const cv::String& relative_path,
                         const char* configuration_parameter,
                         const std::vector<String>* search_paths,
@@ -292,8 +319,15 @@ cv::String findDataFile(const cv::String& relative_path,
         }
     }
 
-    cv::String module_path = getBinLocation();
-    CV_LOG_DEBUG(NULL, "Detected module path: '" << module_path << '\'');
+    cv::String module_path;
+    if (getBinLocation(module_path))
+    {
+        CV_LOG_DEBUG(NULL, "Detected module path: '" << module_path << '\'');
+    }
+    else
+    {
+        CV_LOG_INFO(NULL, "Can't detect module binaries location");
+    }
 
     if (!has_tested_build_directory &&
         (isSubDirectory(build_dir, module_path) || isSubDirectory(utils::fs::canonical(build_dir), utils::fs::canonical(module_path)))
index a1f8396..9e606dc 100644 (file)
@@ -91,6 +91,14 @@ CV_EXPORTS cv::String getParent(const cv::String &path)
     return std::string(path, 0, loc);
 }
 
+CV_EXPORTS std::wstring getParent(const std::wstring& path)
+{
+    std::wstring::size_type loc = path.find_last_of(L"/\\");
+    if (loc == std::wstring::npos)
+        return std::wstring();
+    return std::wstring(path, 0, loc);
+}
+
 #if OPENCV_HAVE_FILESYSTEM_SUPPORT
 
 cv::String canonical(const cv::String& path)
index 24b5caf..23cf0f9 100644 (file)
@@ -131,7 +131,9 @@ if(TARGET ocv.3rdparty.ximea)
 endif()
 
 if(TARGET ocv.3rdparty.ffmpeg)
-  if("ffmpeg" IN_LIST VIDEOIO_PLUGIN_LIST)
+  if(HAVE_FFMPEG_WRAPPER)
+    list(APPEND tgts ocv.3rdparty.ffmpeg)
+  elseif("ffmpeg" IN_LIST VIDEOIO_PLUGIN_LIST)
     ocv_create_builtin_videoio_plugin("opencv_videoio_ffmpeg" ocv.3rdparty.ffmpeg "cap_ffmpeg.cpp")
   else()
     list(APPEND videoio_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/cap_ffmpeg_impl.hpp)
@@ -202,7 +204,7 @@ ocv_target_link_libraries(${the_module} LINK_PRIVATE ${tgts})
 # copy FFmpeg dll to the output folder
 if(WIN32 AND HAVE_FFMPEG_WRAPPER)
   if(MSVC64 OR MINGW64)
-    set(FFMPEG_SUFFIX _64)
+    set(FFMPEG_SUFFIX "_64")
   endif()
   set(ffmpeg_dir "${OpenCV_BINARY_DIR}/3rdparty/ffmpeg")
   set(ffmpeg_bare_name "opencv_ffmpeg${FFMPEG_SUFFIX}.dll")
index 57dd95c..58e1614 100644 (file)
@@ -54,12 +54,10 @@ endif()
 
 #==================================
 
-if(HAVE_FFMPEG)
-  set(defs "HAVE_FFMPEG")
-  if(HAVE_FFMPEG_WRAPPER)
-    list(APPEND defs "HAVE_FFMPEG_WRAPPER")
-  endif()
-  ocv_add_external_target(ffmpeg "${FFMPEG_INCLUDE_DIRS}" "${FFMPEG_LIBRARIES}" "${defs}")
+if(HAVE_FFMPEG_WRAPPER)
+  ocv_add_external_target(ffmpeg "" "" "HAVE_FFMPEG_WRAPPER")
+elseif(HAVE_FFMPEG)
+  ocv_add_external_target(ffmpeg "${FFMPEG_INCLUDE_DIRS}" "${FFMPEG_LIBRARIES}" "HAVE_FFMPEG")
 endif()
 
 set(HAVE_FFMPEG ${HAVE_FFMPEG} PARENT_SCOPE)
index f7cdd62..445ce7d 100644 (file)
@@ -25,9 +25,22 @@ function(ocv_create_builtin_videoio_plugin name target)
     ocv_target_include_directories(${name} PRIVATE "${OPENCV_MODULE_${mod}_LOCATION}/include")
   endforeach()
 
+  if(WIN32)
+    set(OPENCV_PLUGIN_VERSION "${OPENCV_DLLVERSION}" CACHE STRING "")
+    if(CMAKE_CXX_SIZEOF_DATA_PTR EQUAL 8)
+      set(OPENCV_PLUGIN_ARCH "_64" CACHE STRING "")
+    else()
+      set(OPENCV_PLUGIN_ARCH "" CACHE STRING "")
+    endif()
+  else()
+    set(OPENCV_PLUGIN_VERSION "" CACHE STRING "")
+    set(OPENCV_PLUGIN_ARCH "" CACHE STRING "")
+  endif()
+
   set_target_properties(${name} PROPERTIES
     CXX_STANDARD 11
     CXX_VISIBILITY_PRESET hidden
+    OUTPUT_NAME "${name}${OPENCV_PLUGIN_VERSION}${OPENCV_PLUGIN_ARCH}"
   )
 
   if(WIN32)
index 045d029..a1b4d7a 100644 (file)
@@ -28,7 +28,7 @@ function(ocv_create_videoio_plugin default_name target target_desc videoio_src_f
     message(FATAL_ERROR "${target_desc} was not found!")
   endif()
 
-  set(modules_ROOT "${CMAKE_CURRENT_LIST_DIR}/../../..")
+  get_filename_component(modules_ROOT "${CMAKE_CURRENT_LIST_DIR}/../../.." ABSOLUTE)
   set(videoio_ROOT "${modules_ROOT}/videoio")
   set(core_ROOT "${modules_ROOT}/core")
   set(imgproc_ROOT "${modules_ROOT}/imgproc")
@@ -45,22 +45,20 @@ function(ocv_create_videoio_plugin default_name target target_desc videoio_src_f
   )
   target_compile_definitions(${OPENCV_PLUGIN_NAME} PRIVATE BUILD_PLUGIN)
 
-  # Fixes for build
-  target_compile_definitions(${OPENCV_PLUGIN_NAME} PRIVATE __OPENCV_BUILD)
-  file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cvconfig.h" "#pragma once")
-  file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cv_cpu_config.h" "#pragma once")
-  file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/opencv2/opencv_modules.hpp" "#pragma once")
-
   target_link_libraries(${OPENCV_PLUGIN_NAME} PRIVATE ${target})
   set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES
     CXX_STANDARD 11
     CXX_VISIBILITY_PRESET hidden
   )
 
+  if(DEFINED OPENCV_PLUGIN_MODULE_PREFIX)
+    set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES PREFIX "${OPENCV_PLUGIN_MODULE_PREFIX}")
+  endif()
+
   # Hack for Windows
   if(WIN32)
     find_package(OpenCV REQUIRED core imgproc videoio)
-    target_link_libraries(${OPENCV_PLUGIN_NAME} ${OpenCV_LIBS})
+    target_link_libraries(${OPENCV_PLUGIN_NAME} PRIVATE ${OpenCV_LIBS})
   endif()
 
   if(OPENCV_PLUGIN_DESTINATION)
@@ -68,6 +66,8 @@ function(ocv_create_videoio_plugin default_name target target_desc videoio_src_f
     message(STATUS "Output destination: ${OPENCV_PLUGIN_DESTINATION}")
   endif()
 
+  install(TARGETS ${OPENCV_PLUGIN_NAME} LIBRARY DESTINATION . COMPONENT plugins)
+
   message(STATUS "Library name: ${OPENCV_PLUGIN_NAME}")
 
 endfunction()
index a29e360..17f7a1d 100644 (file)
@@ -29,10 +29,43 @@ namespace cv { namespace impl {
 
 #if defined(_WIN32)
 typedef HMODULE LibHandle_t;
-#elif defined(__linux__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__)
+typedef wchar_t FileSystemChar_t;
+typedef std::wstring FileSystemPath_t;
+
+static
+FileSystemPath_t toFileSystemPath(const std::string& p)
+{
+    FileSystemPath_t result;
+    result.resize(p.size());
+    for (size_t i = 0; i < p.size(); i++)
+        result[i] = (wchar_t)p[i];
+    return result;
+}
+static
+std::string toPrintablePath(const FileSystemPath_t& p)
+{
+    std::string result;
+    result.resize(p.size());
+    for (size_t i = 0; i < p.size(); i++)
+    {
+        wchar_t ch = p[i];
+        if ((int)ch >= ' ' && (int)ch < 128)
+            result[i] = (char)ch;
+        else
+            result[i] = '?';
+    }
+    return result;
+}
+#else  // !_WIN32
 typedef void* LibHandle_t;
+typedef char FileSystemChar_t;
+typedef std::string FileSystemPath_t;
+
+static inline FileSystemPath_t toFileSystemPath(const std::string& p) { return p; }
+static inline std::string toPrintablePath(const FileSystemPath_t& p) { return p; }
 #endif
 
+
 static Mutex& getInitializationMutex()
 {
     static Mutex initializationMutex;
@@ -50,12 +83,16 @@ void* getSymbol_(LibHandle_t h, const char* symbolName)
 }
 
 static inline
-LibHandle_t libraryLoad_(const char* filename)
+LibHandle_t libraryLoad_(const FileSystemPath_t& filename)
 {
 #if defined(_WIN32)
-    return LoadLibraryA(filename);
+# ifdef WINRT
+    return LoadPackagedLibrary(filename.c_str(), 0);
+# else
+    return LoadLibraryW(filename.c_str());
+#endif
 #elif defined(__linux__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__)
-    return dlopen(filename, RTLD_LAZY);
+    return dlopen(filename.c_str(), RTLD_LAZY);
 #endif
 }
 
@@ -73,7 +110,7 @@ static inline
 std::string libraryPrefix()
 {
 #if defined(_WIN32)
-    return string();
+    return "";
 #else
     return "lib";
 #endif
@@ -82,9 +119,13 @@ static inline
 std::string librarySuffix()
 {
 #if defined(_WIN32)
-    return ".dll";
-#elif defined(__APPLE__)
-    return ".dylib";
+    const char* suffix = ""
+        CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) CVAUX_STR(CV_SUBMINOR_VERSION)
+    #if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__)
+        "_64"
+    #endif
+        ".dll";
+    return suffix;
 #else
     return ".so";
 #endif
@@ -96,10 +137,10 @@ class DynamicLib
 {
 private:
     LibHandle_t handle;
-    const std::string fname;
+    const FileSystemPath_t fname;
 
 public:
-    DynamicLib(const std::string &filename)
+    DynamicLib(const FileSystemPath_t& filename)
         : handle(0), fname(filename)
     {
         libraryLoad(filename);
@@ -120,21 +161,21 @@ public:
         }
         void * res = getSymbol_(handle, symbolName);
         if (!res)
-            CV_LOG_ERROR(NULL, "No symbol '" << symbolName << "' in " << fname);
+            CV_LOG_ERROR(NULL, "No symbol '" << symbolName << "' in " << toPrintablePath(fname));
         return res;
     }
-    const std::string& getName() const { return fname; }
+    const std::string getName() const { return toPrintablePath(fname); }
 private:
-    void libraryLoad(const std::string &filename)
+    void libraryLoad(const FileSystemPath_t& filename)
     {
-        handle = libraryLoad_(filename.c_str());
-        CV_LOG_INFO(NULL, "load " << filename << " => " << (handle ? "OK" : "FAILED"));
+        handle = libraryLoad_(filename);
+        CV_LOG_INFO(NULL, "load " << toPrintablePath(filename) << " => " << (handle ? "OK" : "FAILED"));
     }
     void libraryRelease()
     {
-        CV_LOG_INFO(NULL, "unload "<< fname);
         if (handle)
         {
+            CV_LOG_INFO(NULL, "unload "<< toPrintablePath(fname));
             libraryRelease_(handle);
             handle = 0;
         }
@@ -230,39 +271,79 @@ protected:
 };
 
 static
-std::vector<string> getPluginCandidates(const std::string& baseName)
+std::vector<FileSystemPath_t> getPluginCandidates(const std::string& baseName)
 {
     using namespace cv::utils;
     using namespace cv::utils::fs;
+    const string baseName_l = toLowerCase(baseName);
+    const string baseName_u = toUpperCase(baseName);
+    const FileSystemPath_t baseName_l_fs = toFileSystemPath(baseName_l);
+    vector<FileSystemPath_t> paths;
+    const vector<string> paths_ = getConfigurationParameterPaths("OPENCV_VIDEOIO_PLUGIN_PATH", vector<string>());
+    if (paths_.size() != 0)
+    {
+        for (size_t i = 0; i < paths_.size(); i++)
+        {
+            paths.push_back(toFileSystemPath(paths_[i]));
+        }
+    }
+    else
+    {
+        FileSystemPath_t binaryLocation;
+        if (getBinLocation(binaryLocation))
+        {
+            binaryLocation = getParent(binaryLocation);
 #ifndef CV_VIDEOIO_PLUGIN_SUBDIRECTORY
-#define CV_VIDEOIO_PLUGIN_SUBDIRECTORY_STR ""
+            paths.push_back(binaryLocation);
 #else
-#define CV_VIDEOIO_PLUGIN_SUBDIRECTORY_STR CVAUX_STR(CV_VIDEOIO_PLUGIN_SUBDIRECTORY)
+            paths.push_back(binaryLocation + toFileSystemPath("/") + toFileSystemPath(CV_VIDEOIO_PLUGIN_SUBDIRECTORY_STR));
 #endif
-    const vector<string> default_paths = { utils::fs::join(getParent(getBinLocation()), CV_VIDEOIO_PLUGIN_SUBDIRECTORY_STR) };
-    const vector<string> paths = getConfigurationParameterPaths("OPENCV_VIDEOIO_PLUGIN_PATH", default_paths);
-    const string baseName_l = toLowerCase(baseName);
-    const string baseName_u = toUpperCase(baseName);
+        }
+    }
     const string default_expr = libraryPrefix() + "opencv_videoio_" + baseName_l + "*" + librarySuffix();
-    const string expr = getConfigurationParameterString((std::string("OPENCV_VIDEOIO_PLUGIN_") + baseName_u).c_str(), default_expr.c_str());
-    CV_LOG_INFO(NULL, "VideoIO pluigin (" << baseName << "): glob is '" << expr << "', " << paths.size() << " location(s)");
-    vector<string> results;
-    for(const string & path : paths)
+    const string plugin_expr = getConfigurationParameterString((std::string("OPENCV_VIDEOIO_PLUGIN_") + baseName_u).c_str(), default_expr.c_str());
+    vector<FileSystemPath_t> results;
+#ifdef _WIN32
+    FileSystemPath_t moduleName = toFileSystemPath(libraryPrefix() + "opencv_videoio_" + baseName_l + librarySuffix());
+#ifndef WINRT
+    if (baseName_u == "FFMPEG")  // backward compatibility
+    {
+        const wchar_t* ffmpeg_env_path = _wgetenv(L"OPENCV_FFMPEG_DLL_DIR");
+        if (ffmpeg_env_path)
+        {
+            results.push_back(FileSystemPath_t(ffmpeg_env_path) + L"\\" + moduleName);
+        }
+    }
+#endif
+    if (plugin_expr != default_expr)
+    {
+        moduleName = toFileSystemPath(plugin_expr);
+        results.push_back(moduleName);
+    }
+    for (const FileSystemPath_t& path : paths)
+    {
+        results.push_back(path + L"\\" + moduleName);
+    }
+    results.push_back(moduleName);
+#else
+    CV_LOG_INFO(NULL, "VideoIO pluigin (" << baseName << "): glob is '" << plugin_expr << "', " << paths.size() << " location(s)");
+    for (const string & path : paths)
     {
         if (path.empty())
             continue;
         vector<string> candidates;
-        cv::glob(utils::fs::join(path, expr), candidates);
+        cv::glob(utils::fs::join(path, plugin_expr), candidates);
         CV_LOG_INFO(NULL, "    - " << path << ": " << candidates.size());
         copy(candidates.begin(), candidates.end(), back_inserter(results));
     }
+#endif
     CV_LOG_INFO(NULL, "Found " << results.size() << " plugin(s) for " << baseName);
     return results;
 }
 
 void PluginBackendFactory::loadPlugin()
 {
-    for(const std::string & plugin : getPluginCandidates(baseName_))
+    for (const FileSystemPath_t& plugin : getPluginCandidates(baseName_))
     {
         Ptr<DynamicLib> lib = makePtr<DynamicLib>(plugin);
         if (!lib->isLoaded())
@@ -287,7 +368,7 @@ void PluginBackendFactory::loadPlugin()
         }
         catch (...)
         {
-            CV_LOG_INFO(NULL, "Video I/O: exception during plugin initialization: " << plugin << ". SKIP");
+            CV_LOG_WARNING(NULL, "Video I/O: exception during plugin initialization: " << toPrintablePath(plugin) << ". SKIP");
         }
     }
 }
index 16e6637..5d8003c 100644 (file)
 
 #include "precomp.hpp"
 
-#if defined(HAVE_FFMPEG)
+#if !defined(HAVE_FFMPEG)
+#error "Build configuration error"
+#endif
 
 #include <string>
 
-#if !defined(HAVE_FFMPEG_WRAPPER)
 #include "cap_ffmpeg_impl.hpp"
 
 #define icvCreateFileCapture_FFMPEG_p cvCreateFileCapture_FFMPEG
 #define icvReleaseVideoWriter_FFMPEG_p cvReleaseVideoWriter_FFMPEG
 #define icvWriteFrame_FFMPEG_p cvWriteFrame_FFMPEG
 
-#else
-
-#include "cap_ffmpeg_api.hpp"
-
-namespace cv { namespace {
-
-static CvCreateFileCapture_Plugin icvCreateFileCapture_FFMPEG_p = 0;
-static CvReleaseCapture_Plugin icvReleaseCapture_FFMPEG_p = 0;
-static CvGrabFrame_Plugin icvGrabFrame_FFMPEG_p = 0;
-static CvRetrieveFrame_Plugin icvRetrieveFrame_FFMPEG_p = 0;
-static CvSetCaptureProperty_Plugin icvSetCaptureProperty_FFMPEG_p = 0;
-static CvGetCaptureProperty_Plugin icvGetCaptureProperty_FFMPEG_p = 0;
-static CvCreateVideoWriter_Plugin icvCreateVideoWriter_FFMPEG_p = 0;
-static CvReleaseVideoWriter_Plugin icvReleaseVideoWriter_FFMPEG_p = 0;
-static CvWriteFrame_Plugin icvWriteFrame_FFMPEG_p = 0;
-
-static cv::Mutex _icvInitFFMPEG_mutex;
-
-#if defined _WIN32
-static const HMODULE cv_GetCurrentModule()
-{
-    HMODULE h = 0;
-#if _WIN32_WINNT >= 0x0501
-    ::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
-        reinterpret_cast<LPCTSTR>(cv_GetCurrentModule),
-        &h);
-#endif
-    return h;
-}
-#endif
-
-class icvInitFFMPEG
-{
-public:
-    static void Init()
-    {
-        cv::AutoLock al(_icvInitFFMPEG_mutex);
-        static icvInitFFMPEG init;
-    }
-
-private:
-    #if defined _WIN32
-    HMODULE icvFFOpenCV;
-
-    ~icvInitFFMPEG()
-    {
-        if (icvFFOpenCV)
-        {
-            FreeLibrary(icvFFOpenCV);
-            icvFFOpenCV = 0;
-        }
-    }
-    #endif
-
-    icvInitFFMPEG()
-    {
-#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__)
-            L"_64"
-        #endif
-            L".dll";
-    # ifdef WINRT
-        icvFFOpenCV = LoadPackagedLibrary( module_name_, 0 );
-    # else
-        const std::wstring module_name(module_name_);
-
-        const wchar_t* ffmpeg_env_path = _wgetenv(L"OPENCV_FFMPEG_DLL_DIR");
-        std::wstring module_path =
-                ffmpeg_env_path
-                ? ((std::wstring(ffmpeg_env_path) + L"\\") + module_name)
-                : module_name;
-
-        icvFFOpenCV = LoadLibraryW(module_path.c_str());
-        if(!icvFFOpenCV && !ffmpeg_env_path)
-        {
-            HMODULE m = cv_GetCurrentModule();
-            if (m)
-            {
-                wchar_t path[MAX_PATH];
-                const size_t path_size = sizeof(path)/sizeof(*path);
-                size_t sz = GetModuleFileNameW(m, path, path_size);
-                /* Don't handle paths longer than MAX_PATH until that becomes a real issue */
-                if (sz > 0 && sz < path_size)
-                {
-                    wchar_t* s = wcsrchr(path, L'\\');
-                    if (s)
-                    {
-                        s[0] = 0;
-                        module_path = (std::wstring(path) + L"\\") + module_name;
-                        icvFFOpenCV = LoadLibraryW(module_path.c_str());
-                    }
-                }
-            }
-        }
-    # endif
-
-        if( icvFFOpenCV )
-        {
-            icvCreateFileCapture_FFMPEG_p =
-                (CvCreateFileCapture_Plugin)GetProcAddress(icvFFOpenCV, "cvCreateFileCapture_FFMPEG");
-            icvReleaseCapture_FFMPEG_p =
-                (CvReleaseCapture_Plugin)GetProcAddress(icvFFOpenCV, "cvReleaseCapture_FFMPEG");
-            icvGrabFrame_FFMPEG_p =
-                (CvGrabFrame_Plugin)GetProcAddress(icvFFOpenCV, "cvGrabFrame_FFMPEG");
-            icvRetrieveFrame_FFMPEG_p =
-                (CvRetrieveFrame_Plugin)GetProcAddress(icvFFOpenCV, "cvRetrieveFrame_FFMPEG");
-            icvSetCaptureProperty_FFMPEG_p =
-                (CvSetCaptureProperty_Plugin)GetProcAddress(icvFFOpenCV, "cvSetCaptureProperty_FFMPEG");
-            icvGetCaptureProperty_FFMPEG_p =
-                (CvGetCaptureProperty_Plugin)GetProcAddress(icvFFOpenCV, "cvGetCaptureProperty_FFMPEG");
-            icvCreateVideoWriter_FFMPEG_p =
-                (CvCreateVideoWriter_Plugin)GetProcAddress(icvFFOpenCV, "cvCreateVideoWriter_FFMPEG");
-            icvReleaseVideoWriter_FFMPEG_p =
-                (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 &&
-                icvGrabFrame_FFMPEG_p != 0 &&
-                icvRetrieveFrame_FFMPEG_p != 0 &&
-                icvSetCaptureProperty_FFMPEG_p != 0 &&
-                icvGetCaptureProperty_FFMPEG_p != 0 &&
-                icvCreateVideoWriter_FFMPEG_p != 0 &&
-                icvReleaseVideoWriter_FFMPEG_p != 0 &&
-                icvWriteFrame_FFMPEG_p != 0 )
-            {
-                printf("Successfully initialized ffmpeg plugin!\n");
-            }
-            else
-            {
-                printf("Failed to load FFMPEG plugin: module handle=%p\n", icvFFOpenCV);
-            }
-#endif
-        }
-    }
-};
-
-
-}} // namespace
-#endif // HAVE_FFMPEG_WRAPPER
-
-
 
 namespace cv {
 namespace {
@@ -247,11 +102,7 @@ public:
     }
     virtual void close()
     {
-        if (ffmpegCapture
-#if defined(HAVE_FFMPEG_WRAPPER)
-                && icvReleaseCapture_FFMPEG_p
-#endif
-)
+        if (ffmpegCapture)
             icvReleaseCapture_FFMPEG_p( &ffmpegCapture );
         CV_Assert(ffmpegCapture == 0);
         ffmpegCapture = 0;
@@ -268,11 +119,6 @@ protected:
 
 cv::Ptr<cv::IVideoCapture> cvCreateFileCapture_FFMPEG_proxy(const std::string &filename)
 {
-#if defined(HAVE_FFMPEG_WRAPPER)
-    icvInitFFMPEG::Init();
-    if (!icvCreateFileCapture_FFMPEG_p)
-        return cv::Ptr<cv::IVideoCapture>();
-#endif
     cv::Ptr<CvCapture_FFMPEG_proxy> capture = cv::makePtr<CvCapture_FFMPEG_proxy>(filename);
     if (capture && capture->isOpened())
         return capture;
@@ -308,11 +154,7 @@ public:
 
     virtual void close()
     {
-        if (ffmpegWriter
-#if defined(HAVE_FFMPEG_WRAPPER)
-                && icvReleaseVideoWriter_FFMPEG_p
-#endif
-        )
+        if (ffmpegWriter)
             icvReleaseVideoWriter_FFMPEG_p( &ffmpegWriter );
         CV_Assert(ffmpegWriter == 0);
         ffmpegWriter = 0;
@@ -330,11 +172,6 @@ protected:
 
 cv::Ptr<cv::IVideoWriter> cvCreateVideoWriter_FFMPEG_proxy(const std::string& filename, int fourcc, double fps, const cv::Size &frameSize, bool isColor)
 {
-#if defined(HAVE_FFMPEG_WRAPPER)
-    icvInitFFMPEG::Init();
-    if (!icvCreateVideoWriter_FFMPEG_p)
-        return cv::Ptr<cv::IVideoWriter>();
-#endif
     cv::Ptr<CvVideoWriter_FFMPEG_proxy> writer = cv::makePtr<CvVideoWriter_FFMPEG_proxy>(filename, fourcc, fps, frameSize, isColor != 0);
     if (writer && writer->isOpened())
         return writer;
@@ -343,7 +180,7 @@ cv::Ptr<cv::IVideoWriter> cvCreateVideoWriter_FFMPEG_proxy(const std::string& fi
 
 } // namespace
 
-#endif // defined(HAVE_FFMPEG)
+
 
 //==================================================================================================
 
diff --git a/modules/videoio/src/cap_ffmpeg_api.hpp b/modules/videoio/src/cap_ffmpeg_api.hpp
deleted file mode 100644 (file)
index fe246ac..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-#ifndef __OPENCV_FFMPEG_H__
-#define __OPENCV_FFMPEG_H__
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#ifndef OPENCV_FFMPEG_API
-#if defined(__OPENCV_BUILD) || defined(BUILD_PLUGIN)
-#   define OPENCV_FFMPEG_API
-#elif defined _WIN32
-#   define OPENCV_FFMPEG_API __declspec(dllexport)
-#elif defined __GNUC__ && __GNUC__ >= 4
-#   define OPENCV_FFMPEG_API __attribute__ ((visibility ("default")))
-#else
-#   define OPENCV_FFMPEG_API
-#endif
-#endif
-
-enum
-{
-    CV_FFMPEG_CAP_PROP_POS_MSEC=0,
-    CV_FFMPEG_CAP_PROP_POS_FRAMES=1,
-    CV_FFMPEG_CAP_PROP_POS_AVI_RATIO=2,
-    CV_FFMPEG_CAP_PROP_FRAME_WIDTH=3,
-    CV_FFMPEG_CAP_PROP_FRAME_HEIGHT=4,
-    CV_FFMPEG_CAP_PROP_FPS=5,
-    CV_FFMPEG_CAP_PROP_FOURCC=6,
-    CV_FFMPEG_CAP_PROP_FRAME_COUNT=7,
-    CV_FFMPEG_CAP_PROP_SAR_NUM=40,
-    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 int cvSetCaptureProperty_FFMPEG(struct CvCapture_FFMPEG* cap,
-                                                  int prop, double value);
-OPENCV_FFMPEG_API double cvGetCaptureProperty_FFMPEG(struct CvCapture_FFMPEG* cap, int prop);
-OPENCV_FFMPEG_API int cvGrabFrame_FFMPEG(struct CvCapture_FFMPEG* cap);
-OPENCV_FFMPEG_API int cvRetrieveFrame_FFMPEG(struct CvCapture_FFMPEG* capture, unsigned char** data,
-                                             int* step, int* width, int* height, int* cn);
-OPENCV_FFMPEG_API void cvReleaseCapture_FFMPEG(struct CvCapture_FFMPEG** cap);
-
-OPENCV_FFMPEG_API struct CvVideoWriter_FFMPEG* cvCreateVideoWriter_FFMPEG(const char* filename,
-            int fourcc, double fps, int width, int height, int isColor );
-OPENCV_FFMPEG_API int cvWriteFrame_FFMPEG(struct CvVideoWriter_FFMPEG* writer, const unsigned char* data,
-                                          int step, int width, int height, int cn, int origin);
-OPENCV_FFMPEG_API void cvReleaseVideoWriter_FFMPEG(struct CvVideoWriter_FFMPEG** writer);
-
-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)( 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)( CvVideoWriter_FFMPEG* writer_handle, const unsigned char* data, int step,
-                                    int width, int height, int cn, int origin);
-typedef void (*CvReleaseVideoWriter_Plugin)( CvVideoWriter_FFMPEG** writer );
-
-/*
- * For CUDA encoder
- */
-
-OPENCV_FFMPEG_API struct OutputMediaStream_FFMPEG* create_OutputMediaStream_FFMPEG(const char* fileName, int width, int height, double fps);
-OPENCV_FFMPEG_API void release_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream);
-OPENCV_FFMPEG_API void write_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream, unsigned char* data, int size, int keyFrame);
-
-typedef struct OutputMediaStream_FFMPEG* (*Create_OutputMediaStream_FFMPEG_Plugin)(const char* fileName, int width, int height, double fps);
-typedef void (*Release_OutputMediaStream_FFMPEG_Plugin)(struct OutputMediaStream_FFMPEG* stream);
-typedef void (*Write_OutputMediaStream_FFMPEG_Plugin)(struct OutputMediaStream_FFMPEG* stream, unsigned char* data, int size, int keyFrame);
-
-/*
- * For CUDA decoder
- */
-
-OPENCV_FFMPEG_API struct InputMediaStream_FFMPEG* create_InputMediaStream_FFMPEG(const char* fileName, int* codec, int* chroma_format, int* width, int* height);
-OPENCV_FFMPEG_API void release_InputMediaStream_FFMPEG(struct InputMediaStream_FFMPEG* stream);
-OPENCV_FFMPEG_API int read_InputMediaStream_FFMPEG(struct InputMediaStream_FFMPEG* stream, unsigned char** data, int* size, int* endOfFile);
-
-typedef struct InputMediaStream_FFMPEG* (*Create_InputMediaStream_FFMPEG_Plugin)(const char* fileName, int* codec, int* chroma_format, int* width, int* height);
-typedef void (*Release_InputMediaStream_FFMPEG_Plugin)(struct InputMediaStream_FFMPEG* stream);
-typedef int (*Read_InputMediaStream_FFMPEG_Plugin)(struct InputMediaStream_FFMPEG* stream, unsigned char** data, int* size, int* endOfFile);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
index ef2d818..0239650 100644 (file)
 //
 //M*/
 
-#include "cap_ffmpeg_api.hpp"
+#include "cap_ffmpeg_legacy_api.hpp"
+
+using namespace cv;
+
 #if !(defined(_WIN32) || defined(WINCE))
 # include <pthread.h>
 #endif
@@ -631,6 +634,9 @@ void CvCapture_FFMPEG::close()
 #define AVSEEK_FLAG_ANY 1
 #endif
 
+#if defined(__OPENCV_BUILD) || defined(BUILD_PLUGIN)
+typedef cv::Mutex ImplMutex;
+#else
 class ImplMutex
 {
 public:
@@ -751,16 +757,30 @@ void ImplMutex::lock() { impl->lock(); }
 void ImplMutex::unlock() { impl->unlock(); }
 bool ImplMutex::trylock() { return impl->trylock(); }
 
+class AutoLock
+{
+public:
+    AutoLock(ImplMutex& m) : mutex(&m) { mutex->lock(); }
+    ~AutoLock() { mutex->unlock(); }
+protected:
+    ImplMutex* mutex;
+private:
+    AutoLock(const AutoLock&); // disabled
+    AutoLock& operator = (const AutoLock&); // disabled
+};
+#endif
+
+static ImplMutex _mutex;
+
 static int LockCallBack(void **mutex, AVLockOp op)
 {
     ImplMutex* localMutex = reinterpret_cast<ImplMutex*>(*mutex);
     switch (op)
     {
         case AV_LOCK_CREATE:
-            localMutex = reinterpret_cast<ImplMutex*>(malloc(sizeof(ImplMutex)));
+            localMutex = new ImplMutex();
             if (!localMutex)
                 return 1;
-            localMutex->init();
             *mutex = localMutex;
             if (!*mutex)
                 return 1;
@@ -775,8 +795,7 @@ static int LockCallBack(void **mutex, AVLockOp op)
         break;
 
         case AV_LOCK_DESTROY:
-            localMutex->destroy();
-            free(localMutex);
+            delete localMutex;
             localMutex = NULL;
             *mutex = NULL;
         break;
@@ -784,19 +803,6 @@ static int LockCallBack(void **mutex, AVLockOp op)
     return 0;
 }
 
-static ImplMutex _mutex;
-
-class AutoLock
-{
-public:
-    AutoLock(ImplMutex& m) : mutex(&m) { mutex->lock(); }
-    ~AutoLock() { mutex->unlock(); }
-protected:
-    ImplMutex* mutex;
-private:
-    AutoLock(const AutoLock&); // disabled
-    AutoLock& operator = (const AutoLock&); // disabled
-};
 
 static void ffmpeg_log_callback(void *ptr, int level, const char *fmt, va_list vargs)
 {
@@ -1161,21 +1167,21 @@ double CvCapture_FFMPEG::getProperty( int property_id ) const
 
     switch( property_id )
     {
-    case CV_FFMPEG_CAP_PROP_POS_MSEC:
+    case CAP_PROP_POS_MSEC:
         return 1000.0*(double)frame_number/get_fps();
-    case CV_FFMPEG_CAP_PROP_POS_FRAMES:
+    case CAP_PROP_POS_FRAMES:
         return (double)frame_number;
-    case CV_FFMPEG_CAP_PROP_POS_AVI_RATIO:
+    case CAP_PROP_POS_AVI_RATIO:
         return r2d(ic->streams[video_stream]->time_base);
-    case CV_FFMPEG_CAP_PROP_FRAME_COUNT:
+    case CAP_PROP_FRAME_COUNT:
         return (double)get_total_frames();
-    case CV_FFMPEG_CAP_PROP_FRAME_WIDTH:
+    case CAP_PROP_FRAME_WIDTH:
         return (double)frame.width;
-    case CV_FFMPEG_CAP_PROP_FRAME_HEIGHT:
+    case CAP_PROP_FRAME_HEIGHT:
         return (double)frame.height;
-    case CV_FFMPEG_CAP_PROP_FPS:
+    case CAP_PROP_FPS:
         return get_fps();
-    case CV_FFMPEG_CAP_PROP_FOURCC:
+    case CAP_PROP_FOURCC:
 #if LIBAVFORMAT_BUILD > 4628
         codec_id = video_st->codec->codec_id;
         codec_tag = (double) video_st->codec->codec_tag;
@@ -1196,9 +1202,9 @@ double CvCapture_FFMPEG::getProperty( int property_id ) const
         }
 
         return (double) CV_FOURCC(codec_fourcc[0], codec_fourcc[1], codec_fourcc[2], codec_fourcc[3]);
-    case CV_FFMPEG_CAP_PROP_SAR_NUM:
+    case CAP_PROP_SAR_NUM:
         return _opencv_ffmpeg_get_sample_aspect_ratio(ic->streams[video_stream]).num;
-    case CV_FFMPEG_CAP_PROP_SAR_DEN:
+    case CAP_PROP_SAR_DEN:
         return _opencv_ffmpeg_get_sample_aspect_ratio(ic->streams[video_stream]).den;
     default:
         break;
@@ -1347,21 +1353,21 @@ bool CvCapture_FFMPEG::setProperty( int property_id, double value )
 
     switch( property_id )
     {
-    case CV_FFMPEG_CAP_PROP_POS_MSEC:
-    case CV_FFMPEG_CAP_PROP_POS_FRAMES:
-    case CV_FFMPEG_CAP_PROP_POS_AVI_RATIO:
+    case CAP_PROP_POS_MSEC:
+    case CAP_PROP_POS_FRAMES:
+    case CAP_PROP_POS_AVI_RATIO:
         {
             switch( property_id )
             {
-            case CV_FFMPEG_CAP_PROP_POS_FRAMES:
+            case CAP_PROP_POS_FRAMES:
                 seek((int64_t)value);
                 break;
 
-            case CV_FFMPEG_CAP_PROP_POS_MSEC:
+            case CAP_PROP_POS_MSEC:
                 seek(value/1000.0);
                 break;
 
-            case CV_FFMPEG_CAP_PROP_POS_AVI_RATIO:
+            case CAP_PROP_POS_AVI_RATIO:
                 seek((int64_t)(value*ic->duration));
                 break;
             }
@@ -2433,577 +2439,3 @@ int cvWriteFrame_FFMPEG( CvVideoWriter_FFMPEG* writer,
 {
     return writer->writeFrame(data, step, width, height, cn, origin);
 }
-
-
-
-/*
- * For CUDA encoder
- */
-
-struct OutputMediaStream_FFMPEG
-{
-    bool open(const char* fileName, int width, int height, double fps);
-    void close();
-
-    void write(unsigned char* data, int size, int keyFrame);
-
-    // add a video output stream to the container
-    static AVStream* addVideoStream(AVFormatContext *oc, CV_CODEC_ID codec_id, int w, int h, int bitrate, double fps, AVPixelFormat pixel_format);
-
-    AVOutputFormat* fmt_;
-    AVFormatContext* oc_;
-    AVStream* video_st_;
-};
-
-void OutputMediaStream_FFMPEG::close()
-{
-    // no more frame to compress. The codec has a latency of a few
-    // frames if using B frames, so we get the last frames by
-    // passing the same picture again
-
-    // TODO -- do we need to account for latency here?
-
-    if (oc_)
-    {
-        // write the trailer, if any
-        av_write_trailer(oc_);
-
-        // free the streams
-        for (unsigned int i = 0; i < oc_->nb_streams; ++i)
-        {
-            av_freep(&oc_->streams[i]->codec);
-            av_freep(&oc_->streams[i]);
-        }
-
-        if (!(fmt_->flags & AVFMT_NOFILE) && oc_->pb)
-        {
-            // close the output file
-
-            #if LIBAVCODEC_VERSION_INT < ((52<<16)+(123<<8)+0)
-                #if LIBAVCODEC_VERSION_INT >= ((51<<16)+(49<<8)+0)
-                    url_fclose(oc_->pb);
-                #else
-                    url_fclose(&oc_->pb);
-                #endif
-            #else
-                avio_close(oc_->pb);
-            #endif
-        }
-
-        // free the stream
-        av_free(oc_);
-    }
-}
-
-AVStream* OutputMediaStream_FFMPEG::addVideoStream(AVFormatContext *oc, CV_CODEC_ID codec_id, int w, int h, int bitrate, double fps, AVPixelFormat pixel_format)
-{
-    AVCodec* codec = avcodec_find_encoder(codec_id);
-    if (!codec)
-    {
-        fprintf(stderr, "Could not find encoder for codec id %d\n", codec_id);
-        return NULL;
-    }
-
-    #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 10, 0)
-        AVStream* st = avformat_new_stream(oc, 0);
-    #else
-        AVStream* st = av_new_stream(oc, 0);
-    #endif
-    if (!st)
-        return 0;
-
-    #if LIBAVFORMAT_BUILD > 4628
-        AVCodecContext* c = st->codec;
-    #else
-        AVCodecContext* c = &(st->codec);
-    #endif
-
-    c->codec_id = codec_id;
-    c->codec_type = AVMEDIA_TYPE_VIDEO;
-
-    // put sample parameters
-    c->bit_rate = bitrate;
-
-    // took advice from
-    // http://ffmpeg-users.933282.n4.nabble.com/warning-clipping-1-dct-coefficients-to-127-127-td934297.html
-    c->qmin = 3;
-
-    // resolution must be a multiple of two
-    c->width = w;
-    c->height = h;
-
-    // time base: this is the fundamental unit of time (in seconds) in terms
-    // of which frame timestamps are represented. for fixed-fps content,
-    // timebase should be 1/framerate and timestamp increments should be
-    // identically 1
-
-    int frame_rate = static_cast<int>(fps+0.5);
-    int frame_rate_base = 1;
-    while (fabs((static_cast<double>(frame_rate)/frame_rate_base) - fps) > 0.001)
-    {
-        frame_rate_base *= 10;
-        frame_rate = static_cast<int>(fps*frame_rate_base + 0.5);
-    }
-    c->time_base.den = frame_rate;
-    c->time_base.num = frame_rate_base;
-
-    #if LIBAVFORMAT_BUILD > 4752
-        // adjust time base for supported framerates
-        if (codec && codec->supported_framerates)
-        {
-            AVRational req = {frame_rate, frame_rate_base};
-            const AVRational* best = NULL;
-            AVRational best_error = {INT_MAX, 1};
-
-            for (const AVRational* p = codec->supported_framerates; p->den!=0; ++p)
-            {
-                AVRational error = av_sub_q(req, *p);
-
-                if (error.num < 0)
-                    error.num *= -1;
-
-                if (av_cmp_q(error, best_error) < 0)
-                {
-                    best_error= error;
-                    best= p;
-                }
-            }
-
-            if (best == NULL)
-                return NULL;
-            c->time_base.den= best->num;
-            c->time_base.num= best->den;
-        }
-    #endif
-
-    c->gop_size = 12; // emit one intra frame every twelve frames at most
-    c->pix_fmt = pixel_format;
-
-    if (c->codec_id == CV_CODEC(CODEC_ID_MPEG2VIDEO))
-        c->max_b_frames = 2;
-
-    if (c->codec_id == CV_CODEC(CODEC_ID_MPEG1VIDEO) || c->codec_id == CV_CODEC(CODEC_ID_MSMPEG4V3))
-    {
-        // needed to avoid using macroblocks in which some coeffs overflow
-        // this doesn't happen with normal video, it just happens here as the
-        // motion of the chroma plane doesn't match the luma plane
-
-        // avoid FFMPEG warning 'clipping 1 dct coefficients...'
-
-        c->mb_decision = 2;
-    }
-
-    #if LIBAVCODEC_VERSION_INT > 0x000409
-        // some formats want stream headers to be separate
-        if (oc->oformat->flags & AVFMT_GLOBALHEADER)
-        {
-            #if LIBAVCODEC_BUILD > CALC_FFMPEG_VERSION(56, 35, 0)
-                c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
-            #else
-                c->flags |= CODEC_FLAG_GLOBAL_HEADER;
-            #endif
-        }
-    #endif
-
-    return st;
-}
-
-bool OutputMediaStream_FFMPEG::open(const char* fileName, int width, int height, double fps)
-{
-    fmt_ = 0;
-    oc_ = 0;
-    video_st_ = 0;
-
-    // auto detect the output format from the name and fourcc code
-    #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
-        fmt_ = av_guess_format(NULL, fileName, NULL);
-    #else
-        fmt_ = guess_format(NULL, fileName, NULL);
-    #endif
-    if (!fmt_)
-        return false;
-
-    CV_CODEC_ID codec_id = CV_CODEC(CODEC_ID_H264);
-
-    // alloc memory for context
-    #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
-        oc_ = avformat_alloc_context();
-    #else
-        oc_ = av_alloc_format_context();
-    #endif
-    if (!oc_)
-        return false;
-
-    // set some options
-    oc_->oformat = fmt_;
-    snprintf(oc_->filename, sizeof(oc_->filename), "%s", fileName);
-
-    oc_->max_delay = (int)(0.7 * AV_TIME_BASE); // This reduces buffer underrun warnings with MPEG
-
-    // set a few optimal pixel formats for lossless codecs of interest..
-    AVPixelFormat codec_pix_fmt = AV_PIX_FMT_YUV420P;
-    int bitrate_scale = 64;
-
-    // TODO -- safe to ignore output audio stream?
-    video_st_ = addVideoStream(oc_, codec_id, width, height, width * height * bitrate_scale, fps, codec_pix_fmt);
-    if (!video_st_)
-        return false;
-
-    // set the output parameters (must be done even if no parameters)
-    #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
-        if (av_set_parameters(oc_, NULL) < 0)
-            return false;
-    #endif
-
-    // now that all the parameters are set, we can open the audio and
-    // video codecs and allocate the necessary encode buffers
-
-    #if LIBAVFORMAT_BUILD > 4628
-        AVCodecContext* c = (video_st_->codec);
-    #else
-        AVCodecContext* c = &(video_st_->codec);
-    #endif
-
-    c->codec_tag = MKTAG('H', '2', '6', '4');
-    c->bit_rate_tolerance = c->bit_rate;
-
-    // open the output file, if needed
-    if (!(fmt_->flags & AVFMT_NOFILE))
-    {
-        #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
-            int err = url_fopen(&oc_->pb, fileName, URL_WRONLY);
-        #else
-            int err = avio_open(&oc_->pb, fileName, AVIO_FLAG_WRITE);
-        #endif
-
-        if (err != 0)
-            return false;
-    }
-
-    // write the stream header, if any
-    int header_err =
-    #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
-        av_write_header(oc_);
-    #else
-        avformat_write_header(oc_, NULL);
-    #endif
-    if (header_err != 0)
-        return false;
-
-    return true;
-}
-
-void OutputMediaStream_FFMPEG::write(unsigned char* data, int size, int keyFrame)
-{
-    // if zero size, it means the image was buffered
-    if (size > 0)
-    {
-        AVPacket pkt;
-        av_init_packet(&pkt);
-
-        if (keyFrame)
-            pkt.flags |= PKT_FLAG_KEY;
-
-        pkt.stream_index = video_st_->index;
-        pkt.data = data;
-        pkt.size = size;
-
-        // write the compressed frame in the media file
-        av_write_frame(oc_, &pkt);
-    }
-}
-
-struct OutputMediaStream_FFMPEG* create_OutputMediaStream_FFMPEG(const char* fileName, int width, int height, double fps)
-{
-    OutputMediaStream_FFMPEG* stream = (OutputMediaStream_FFMPEG*) malloc(sizeof(OutputMediaStream_FFMPEG));
-    if (!stream)
-        return 0;
-
-    if (stream->open(fileName, width, height, fps))
-        return stream;
-
-    stream->close();
-    free(stream);
-
-    return 0;
-}
-
-void release_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream)
-{
-    stream->close();
-    free(stream);
-}
-
-void write_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream, unsigned char* data, int size, int keyFrame)
-{
-    stream->write(data, size, keyFrame);
-}
-
-/*
- * For CUDA decoder
- */
-
-enum
-{
-    VideoCodec_MPEG1 = 0,
-    VideoCodec_MPEG2,
-    VideoCodec_MPEG4,
-    VideoCodec_VC1,
-    VideoCodec_H264,
-    VideoCodec_JPEG,
-    VideoCodec_H264_SVC,
-    VideoCodec_H264_MVC,
-
-    // Uncompressed YUV
-    VideoCodec_YUV420 = (('I'<<24)|('Y'<<16)|('U'<<8)|('V')),   // Y,U,V (4:2:0)
-    VideoCodec_YV12   = (('Y'<<24)|('V'<<16)|('1'<<8)|('2')),   // Y,V,U (4:2:0)
-    VideoCodec_NV12   = (('N'<<24)|('V'<<16)|('1'<<8)|('2')),   // Y,UV  (4:2:0)
-    VideoCodec_YUYV   = (('Y'<<24)|('U'<<16)|('Y'<<8)|('V')),   // YUYV/YUY2 (4:2:2)
-    VideoCodec_UYVY   = (('U'<<24)|('Y'<<16)|('V'<<8)|('Y'))    // UYVY (4:2:2)
-};
-
-enum
-{
-    VideoChromaFormat_Monochrome = 0,
-    VideoChromaFormat_YUV420,
-    VideoChromaFormat_YUV422,
-    VideoChromaFormat_YUV444
-};
-
-struct InputMediaStream_FFMPEG
-{
-public:
-    bool open(const char* fileName, int* codec, int* chroma_format, int* width, int* height);
-    void close();
-
-    bool read(unsigned char** data, int* size, int* endOfFile);
-
-private:
-    InputMediaStream_FFMPEG(const InputMediaStream_FFMPEG&);
-    InputMediaStream_FFMPEG& operator =(const InputMediaStream_FFMPEG&);
-
-    AVFormatContext* ctx_;
-    int video_stream_id_;
-    AVPacket pkt_;
-
-#if USE_AV_INTERRUPT_CALLBACK
-    AVInterruptCallbackMetadata interrupt_metadata;
-#endif
-};
-
-bool InputMediaStream_FFMPEG::open(const char* fileName, int* codec, int* chroma_format, int* width, int* height)
-{
-    int err;
-
-    ctx_ = 0;
-    video_stream_id_ = -1;
-    memset(&pkt_, 0, sizeof(AVPacket));
-
-#if USE_AV_INTERRUPT_CALLBACK
-    /* interrupt callback */
-    interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_OPEN_TIMEOUT_MS;
-    get_monotonic_time(&interrupt_metadata.value);
-
-    ctx_ = avformat_alloc_context();
-    ctx_->interrupt_callback.callback = _opencv_ffmpeg_interrupt_callback;
-    ctx_->interrupt_callback.opaque = &interrupt_metadata;
-#endif
-
-    #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 13, 0)
-        avformat_network_init();
-    #endif
-
-    #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 6, 0)
-        err = avformat_open_input(&ctx_, fileName, 0, 0);
-    #else
-        err = av_open_input_file(&ctx_, fileName, 0, 0, 0);
-    #endif
-    if (err < 0)
-        return false;
-
-    #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 6, 0)
-        err = avformat_find_stream_info(ctx_, 0);
-    #else
-        err = av_find_stream_info(ctx_);
-    #endif
-    if (err < 0)
-        return false;
-
-    for (unsigned int i = 0; i < ctx_->nb_streams; ++i)
-    {
-        #if LIBAVFORMAT_BUILD > 4628
-            AVCodecContext *enc = ctx_->streams[i]->codec;
-        #else
-            AVCodecContext *enc = &ctx_->streams[i]->codec;
-        #endif
-
-        if (enc->codec_type == AVMEDIA_TYPE_VIDEO)
-        {
-            video_stream_id_ = static_cast<int>(i);
-
-            switch (enc->codec_id)
-            {
-            case CV_CODEC(CODEC_ID_MPEG1VIDEO):
-                *codec = ::VideoCodec_MPEG1;
-                break;
-
-            case CV_CODEC(CODEC_ID_MPEG2VIDEO):
-                *codec = ::VideoCodec_MPEG2;
-                break;
-
-            case CV_CODEC(CODEC_ID_MPEG4):
-                *codec = ::VideoCodec_MPEG4;
-                break;
-
-            case CV_CODEC(CODEC_ID_VC1):
-                *codec = ::VideoCodec_VC1;
-                break;
-
-            case CV_CODEC(CODEC_ID_H264):
-                *codec = ::VideoCodec_H264;
-                break;
-
-            default:
-                return false;
-            };
-
-            switch (enc->pix_fmt)
-            {
-            case AV_PIX_FMT_YUV420P:
-                *chroma_format = ::VideoChromaFormat_YUV420;
-                break;
-
-            case AV_PIX_FMT_YUV422P:
-                *chroma_format = ::VideoChromaFormat_YUV422;
-                break;
-
-            case AV_PIX_FMT_YUV444P:
-                *chroma_format = ::VideoChromaFormat_YUV444;
-                break;
-
-            default:
-                return false;
-            }
-
-            *width = enc->coded_width;
-            *height = enc->coded_height;
-
-            break;
-        }
-    }
-
-    if (video_stream_id_ < 0)
-        return false;
-
-    av_init_packet(&pkt_);
-
-#if USE_AV_INTERRUPT_CALLBACK
-    // deactivate interrupt callback
-    interrupt_metadata.timeout_after_ms = 0;
-#endif
-
-    return true;
-}
-
-void InputMediaStream_FFMPEG::close()
-{
-    if (ctx_)
-    {
-        #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 24, 2)
-            avformat_close_input(&ctx_);
-        #else
-            av_close_input_file(ctx_);
-        #endif
-    }
-
-    // free last packet if exist
-    if (pkt_.data)
-        _opencv_ffmpeg_av_packet_unref(&pkt_);
-}
-
-bool InputMediaStream_FFMPEG::read(unsigned char** data, int* size, int* endOfFile)
-{
-    bool result = false;
-
-#if USE_AV_INTERRUPT_CALLBACK
-    // activate interrupt callback
-    get_monotonic_time(&interrupt_metadata.value);
-    interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_READ_TIMEOUT_MS;
-#endif
-
-    // free last packet if exist
-    if (pkt_.data)
-        _opencv_ffmpeg_av_packet_unref(&pkt_);
-
-    // get the next frame
-    for (;;)
-    {
-#if USE_AV_INTERRUPT_CALLBACK
-        if(interrupt_metadata.timeout)
-        {
-            break;
-        }
-#endif
-
-        int ret = av_read_frame(ctx_, &pkt_);
-
-        if (ret == AVERROR(EAGAIN))
-            continue;
-
-        if (ret < 0)
-        {
-            if (ret == (int)AVERROR_EOF)
-                *endOfFile = true;
-            break;
-        }
-
-        if (pkt_.stream_index != video_stream_id_)
-        {
-            _opencv_ffmpeg_av_packet_unref(&pkt_);
-            continue;
-        }
-
-        result = true;
-        break;
-    }
-
-#if USE_AV_INTERRUPT_CALLBACK
-    // deactivate interrupt callback
-    interrupt_metadata.timeout_after_ms = 0;
-#endif
-
-    if (result)
-    {
-        *data = pkt_.data;
-        *size = pkt_.size;
-        *endOfFile = false;
-    }
-
-    return result;
-}
-
-InputMediaStream_FFMPEG* create_InputMediaStream_FFMPEG(const char* fileName, int* codec, int* chroma_format, int* width, int* height)
-{
-    InputMediaStream_FFMPEG* stream = (InputMediaStream_FFMPEG*) malloc(sizeof(InputMediaStream_FFMPEG));
-    if (!stream)
-        return 0;
-
-    if (stream && stream->open(fileName, codec, chroma_format, width, height))
-        return stream;
-
-    stream->close();
-    free(stream);
-
-    return 0;
-}
-
-void release_InputMediaStream_FFMPEG(InputMediaStream_FFMPEG* stream)
-{
-    stream->close();
-    free(stream);
-}
-
-int read_InputMediaStream_FFMPEG(InputMediaStream_FFMPEG* stream, unsigned char** data, int* size, int* endOfFile)
-{
-    return stream->read(data, size, endOfFile);
-}
diff --git a/modules/videoio/src/cap_ffmpeg_legacy_api.hpp b/modules/videoio/src/cap_ffmpeg_legacy_api.hpp
new file mode 100644 (file)
index 0000000..d918765
--- /dev/null
@@ -0,0 +1,46 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+#ifndef __OPENCV_FFMPEG_LEGACY_API_H__
+#define __OPENCV_FFMPEG_LEGACY_API_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifndef OPENCV_FFMPEG_API
+#if defined(__OPENCV_BUILD)
+#   define OPENCV_FFMPEG_API
+#elif defined _WIN32
+#   define OPENCV_FFMPEG_API __declspec(dllexport)
+#elif defined __GNUC__ && __GNUC__ >= 4
+#   define OPENCV_FFMPEG_API __attribute__ ((visibility ("default")))
+#else
+#   define OPENCV_FFMPEG_API
+#endif
+#endif
+
+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 int cvSetCaptureProperty_FFMPEG(struct CvCapture_FFMPEG* cap,
+                                                  int prop, double value);
+OPENCV_FFMPEG_API double cvGetCaptureProperty_FFMPEG(struct CvCapture_FFMPEG* cap, int prop);
+OPENCV_FFMPEG_API int cvGrabFrame_FFMPEG(struct CvCapture_FFMPEG* cap);
+OPENCV_FFMPEG_API int cvRetrieveFrame_FFMPEG(struct CvCapture_FFMPEG* capture, unsigned char** data,
+                                             int* step, int* width, int* height, int* cn);
+OPENCV_FFMPEG_API void cvReleaseCapture_FFMPEG(struct CvCapture_FFMPEG** cap);
+
+OPENCV_FFMPEG_API struct CvVideoWriter_FFMPEG* cvCreateVideoWriter_FFMPEG(const char* filename,
+            int fourcc, double fps, int width, int height, int isColor );
+OPENCV_FFMPEG_API int cvWriteFrame_FFMPEG(struct CvVideoWriter_FFMPEG* writer, const unsigned char* data,
+                                          int step, int width, int height, int cn, int origin);
+OPENCV_FFMPEG_API void cvReleaseVideoWriter_FFMPEG(struct CvVideoWriter_FFMPEG** writer);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // __OPENCV_FFMPEG_LEGACY_API_H__
index f4eb697..f044c63 100644 (file)
@@ -46,7 +46,9 @@
 #include "opencv2/videoio/legacy/constants_c.h"
 
 #include "opencv2/core/utility.hpp"
+#ifdef __OPENCV_BUILD
 #include "opencv2/core/private.hpp"
+#endif
 
 #include <opencv2/core/utils/configuration.private.hpp>
 #include <opencv2/core/utils/logger.hpp>
index c35f2b2..a98b907 100644 (file)
@@ -58,7 +58,7 @@ static const struct VideoBackendInfo builtin_backends[] =
 {
 #ifdef HAVE_FFMPEG
     DECLARE_STATIC_BACKEND(CAP_FFMPEG, "FFMPEG", MODE_CAPTURE_BY_FILENAME | MODE_WRITER, cvCreateFileCapture_FFMPEG_proxy, 0, cvCreateVideoWriter_FFMPEG_proxy),
-#elif defined(ENABLE_PLUGINS)
+#elif defined(ENABLE_PLUGINS) || defined(HAVE_FFMPEG_WRAPPER)
     DECLARE_DYNAMIC_BACKEND(CAP_FFMPEG, "FFMPEG", MODE_CAPTURE_BY_FILENAME | MODE_WRITER),
 #endif