videoio: revert registry chages, update cap.cpp

This commit is contained in:
Alexander Alekhin 2019-03-04 21:37:09 +00:00
commit 11fd9e5fdc
67 changed files with 2577 additions and 1355 deletions

View File

@ -92,6 +92,7 @@
@{
@defgroup core_hal_intrin_impl Private implementation helpers
@}
@defgroup core_lowlevel_api Low-level API for external libraries / plugins
@}
@}
*/

View File

@ -0,0 +1,94 @@
// 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_CORE_LLAPI_LLAPI_H
#define OPENCV_CORE_LLAPI_LLAPI_H
/**
@addtogroup core_lowlevel_api
API for OpenCV external plugins:
- HAL accelerators
- VideoIO camera backends / decoders / encoders
- Imgcodecs encoders / decoders
Plugins are usually built separately or before OpenCV (OpenCV can depend on them - like HAL libraries).
Using this approach OpenCV provides some basic low level functionality for external plugins.
@note Preview only (no backward compatibility)
@{
*/
#ifndef CV_API_CALL
//! calling convention (including callbacks)
#define CV_API_CALL
#endif
typedef enum cvResult
{
CV_ERROR_FAIL = -1, //!< Some error occured (TODO Require to fill exception information)
CV_ERROR_OK = 0 //!< No error
} CvResult;
typedef struct OpenCV_API_Header_t
{
/** @brief valid size of this structure
@details `assert(api.header.valid_size >= sizeof(OpenCV_<Name>_API_v<N>));`
*/
size_t valid_size;
unsigned min_api_version; //!< backward compatible API version
unsigned api_version; //!< provided API version (features)
unsigned opencv_version_major; //!< compiled OpenCV version
unsigned opencv_version_minor; //!< compiled OpenCV version
unsigned opencv_version_patch; //!< compiled OpenCV version
const char* opencv_version_status; //!< compiled OpenCV version
const char* api_description; //!< API description (debug purposes only)
} OpenCV_API_Header;
#if 0
typedef int (CV_API_CALL *cv_example_callback1_cb_t)(unsigned const char* cb_result, void* cb_context);
struct OpenCV_Example_API_v1
{
OpenCV_API_Header header;
/** @brief Some API call
@param param1 description1
@param param2 description2
@note API-CALL 1, API-Version >=1
*/
CvResult (CV_API_CALL *Request1)(int param1, const char* param2);
/** @brief Register callback
@param callback function to handle callback
@param cb_context context data passed to callback function
@param[out] cb_handle callback id (used to unregister callback)
@note API-CALL 2, API-Version >=1
*/
CvResult (CV_API_CALL *RegisterCallback)(cv_example_callback1_cb_t callback, void* cb_context, CV_OUT unsigned* cb_handle);
/** @brief Unregister callback
@param cb_handle callback handle
@note API-CALL 3, API-Version >=1
*/
CvResult (CV_API_CALL *UnegisterCallback)(unsigned cb_handle);
...
};
#endif // 0
//! @}
#endif // OPENCV_CORE_LLAPI_LLAPI_H

View File

@ -865,6 +865,10 @@ Passed subdirectories are used in LIFO order.
*/
CV_EXPORTS void addDataSearchSubDirectory(const cv::String& subdir);
/** @brief Return location of OpenCV libraries or current executable
*/
CV_EXPORTS std::string getBinLocation();
//! @}
} // namespace utils

View File

@ -26,6 +26,9 @@ CV_EXPORTS cv::String canonical(const cv::String& path);
/** Join path components */
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);
/**
* Generate a list of all files that match the globbing pattern.
*

View File

@ -144,6 +144,11 @@ static cv::String getModuleLocation(const void* addr)
return cv::String();
}
std::string getBinLocation()
{
return getModuleLocation((void*)getModuleLocation); // use code addr, doesn't work with static linkage!
}
cv::String findDataFile(const cv::String& relative_path,
const char* configuration_parameter,
const std::vector<String>* search_paths,
@ -287,7 +292,7 @@ cv::String findDataFile(const cv::String& relative_path,
}
}
cv::String module_path = getModuleLocation((void*)getModuleLocation); // use code addr, doesn't work with static linkage!
cv::String module_path = getBinLocation();
CV_LOG_DEBUG(NULL, "Detected module path: '" << module_path << '\'');
if (!has_tested_build_directory &&

View File

@ -83,6 +83,14 @@ cv::String join(const cv::String& base, const cv::String& path)
return result;
}
CV_EXPORTS cv::String getParent(const cv::String &path)
{
std::string::size_type loc = path.find_last_of("/\\");
if (loc == std::string::npos)
return std::string();
return std::string(path, 0, loc);
}
#if OPENCV_HAVE_FILESYSTEM_SUPPORT
cv::String canonical(const cv::String& path)

View File

@ -1,3 +1,8 @@
set(VIDEOIO_PLUGIN_LIST "" CACHE STRING "List of videoio backends to be compiled as plugins (ffmpeg, gstreamer)")
set(VIDEOIO_ENABLE_PLUGINS "ON" CACHE BOOL "Allow building videoio plugin support")
set(VIDEOIO_ENABLE_STRICT_PLUGIN_CHECK "ON" CACHE BOOL "Make sure OpenCV version is the same in plugin and host code")
mark_as_advanced(VIDEOIO_PLUGIN_LIST VIDEOIO_ENABLE_PLUGINS VIDEOIO_ENABLE_STRICT_PLUGIN_CHECK)
ocv_add_module(videoio opencv_imgproc opencv_imgcodecs WRAP java python)
set(videoio_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/precomp.hpp)
@ -9,6 +14,8 @@ set(videoio_srcs
"${CMAKE_CURRENT_LIST_DIR}/src/cap_images.cpp"
"${CMAKE_CURRENT_LIST_DIR}/src/cap_mjpeg_encoder.cpp"
"${CMAKE_CURRENT_LIST_DIR}/src/cap_mjpeg_decoder.cpp"
"${CMAKE_CURRENT_LIST_DIR}/src/backend_plugin.cpp"
"${CMAKE_CURRENT_LIST_DIR}/src/backend_static.cpp"
"${CMAKE_CURRENT_LIST_DIR}/src/container_avi.cpp")
file(GLOB videoio_ext_hdrs
@ -86,9 +93,15 @@ if(TARGET ocv.3rdparty.dc1394_2)
list(APPEND tgts ocv.3rdparty.dc1394_2)
endif()
include(${CMAKE_CURRENT_LIST_DIR}/cmake/plugin.cmake)
if(TARGET ocv.3rdparty.gstreamer)
list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_gstreamer.cpp)
list(APPEND tgts ocv.3rdparty.gstreamer)
if("gstreamer" IN_LIST VIDEOIO_PLUGIN_LIST)
ocv_create_builtin_videoio_plugin("opencv_videoio_gstreamer" ocv.3rdparty.gstreamer "cap_gstreamer.cpp")
else()
list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_gstreamer.cpp)
list(APPEND tgts ocv.3rdparty.gstreamer)
endif()
endif()
if(TARGET ocv.3rdparty.v4l)
@ -107,9 +120,13 @@ if(TARGET ocv.3rdparty.ximea)
endif()
if(TARGET ocv.3rdparty.ffmpeg)
list(APPEND videoio_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/cap_ffmpeg_impl.hpp)
list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_ffmpeg.cpp)
list(APPEND tgts ocv.3rdparty.ffmpeg)
if("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)
list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_ffmpeg.cpp)
list(APPEND tgts ocv.3rdparty.ffmpeg)
endif()
endif()
if(TARGET ocv.3rdparty.pvapi)
@ -155,6 +172,14 @@ ocv_create_module()
ocv_add_accuracy_tests(${tgts})
ocv_add_perf_tests(${tgts})
if(VIDEOIO_ENABLE_PLUGINS)
ocv_target_compile_definitions(${the_module} PRIVATE ENABLE_PLUGINS)
endif()
if(VIDEOIO_ENABLE_STRICT_PLUGIN_CHECK)
ocv_target_compile_definitions(${the_module} PRIVATE STRICT_PLUGIN_CHECK)
endif()
ocv_target_link_libraries(${the_module} LINK_PRIVATE ${tgts})
# copy FFmpeg dll to the output folder

View File

@ -31,10 +31,9 @@ if(NOT HAVE_FFMPEG AND PKG_CONFIG_FOUND)
if(FFMPEG_libavresample_FOUND)
list(APPEND FFMPEG_LIBRARIES ${FFMPEG_libavresample_LIBRARIES})
endif()
# rewrite libraries to absolute paths
foreach(lib ${FFMPEG_LIBRARIES})
find_library(FFMPEG_ABSOLUTE_${lib} "${lib}" PATHS "${FFMPEG_lib${lib}_LIBDIR}" NO_DEFAULT_PATH)
find_library(FFMPEG_ABSOLUTE_${lib} "${lib}" PATHS "${FFMPEG_lib${lib}_LIBDIR}" "${FFMPEG_LIBRARY_DIRS}" NO_DEFAULT_PATH)
if(FFMPEG_ABSOLUTE_${lib})
list(APPEND ffmpeg_abs_libs "${FFMPEG_ABSOLUTE_${lib}}")
else()
@ -49,7 +48,7 @@ endif()
#==================================
if(HAVE_FFMPEG AND NOT HAVE_FFMPEG_WRAPPER)
if(HAVE_FFMPEG AND NOT HAVE_FFMPEG_WRAPPER AND NOT OPENCV_FFMPEG_SKIP_BUILD_CHECK)
try_compile(__VALID_FFMPEG
"${OpenCV_BINARY_DIR}"
"${OpenCV_SOURCE_DIR}/cmake/checks/ffmpeg_test.cpp"

View File

@ -19,6 +19,8 @@ function(ocv_add_external_target name inc link def)
endif()
endfunction()
include(FindPkgConfig)
add_backend("ffmpeg" WITH_FFMPEG)
add_backend("gstreamer" WITH_GSTREAMER)
add_backend("v4l" WITH_V4L)

View File

@ -0,0 +1,99 @@
#=============================================
# build with OpenCV
function(ocv_create_builtin_videoio_plugin name target videoio_src_file)
if(NOT TARGET ${target})
message(FATAL_ERROR "${target} does not exist!")
endif()
if(NOT OpenCV_SOURCE_DIR)
message(FATAL_ERROR "OpenCV_SOURCE_DIR must be set to build the plugin!")
endif()
add_library(${name} MODULE
"${CMAKE_CURRENT_LIST_DIR}/src/${videoio_src_file}"
)
target_include_directories(${name} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
target_compile_definitions(${name} PRIVATE BUILD_PLUGIN)
target_link_libraries(${name} PRIVATE ${target})
foreach(mod opencv_videoio opencv_core opencv_imgproc opencv_imgcodecs)
target_link_libraries(${name} PRIVATE ${mod})
target_include_directories(${name} PRIVATE "${OPENCV_MODULE_${mod}_LOCATION}/include")
endforeach()
set_target_properties(${name} PROPERTIES
CXX_STANDARD 11
CXX_VISIBILITY_PRESET hidden
)
install(TARGETS ${name} LIBRARY DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT plugins OPTIONAL)
endfunction()
#=============================================
# standalone build
function(ocv_create_videoio_plugin default_name target target_desc videoio_src_file)
set(OPENCV_PLUGIN_NAME ${default_name} CACHE STRING "")
set(OPENCV_PLUGIN_DESTINATION "" CACHE PATH "")
project(${OPENCV_PLUGIN_NAME} LANGUAGES CXX)
set(BUILD_SHARED_LIBS ON CACHE BOOL "")
if(NOT BUILD_SHARED_LIBS)
message(FATAL_ERROR "Static plugin build does not make sense")
endif()
if(NOT OpenCV_SOURCE_DIR)
message(FATAL_ERROR "OpenCV_SOURCE_DIR must be set to build the plugin!")
endif()
include("${OpenCV_SOURCE_DIR}/modules/videoio/cmake/init.cmake")
if(NOT TARGET ${target})
message(FATAL_ERROR "${target_desc} was not found!")
endif()
set(modules_ROOT "${CMAKE_CURRENT_LIST_DIR}/../../..")
set(videoio_ROOT "${modules_ROOT}/videoio")
set(core_ROOT "${modules_ROOT}/core")
set(imgproc_ROOT "${modules_ROOT}/imgproc")
set(imgcodecs_ROOT "${modules_ROOT}/imgcodecs")
add_library(${OPENCV_PLUGIN_NAME} MODULE "${videoio_ROOT}/src/${videoio_src_file}")
target_include_directories(${OPENCV_PLUGIN_NAME} PRIVATE
"${CMAKE_CURRENT_BINARY_DIR}"
"${videoio_ROOT}/src"
"${videoio_ROOT}/include"
"${core_ROOT}/include"
"${imgproc_ROOT}/include"
"${imgcodecs_ROOT}/include"
)
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
)
# Hack for Windows
if(WIN32)
find_package(OpenCV REQUIRED core imgproc videoio)
target_link_libraries(${OPENCV_PLUGIN_NAME} ${OpenCV_LIBS})
endif()
if(OPENCV_PLUGIN_DESTINATION)
set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${OPENCV_PLUGIN_DESTINATION}")
message(STATUS "Output destination: ${OPENCV_PLUGIN_DESTINATION}")
endif()
message(STATUS "Library name: ${OPENCV_PLUGIN_NAME}")
endfunction()

View File

@ -38,6 +38,9 @@ CV_EXPORTS_W std::vector<VideoCaptureAPIs> getStreamBackends();
/** @brief Returns list of available backends which works via `cv::VideoWriter()` */
CV_EXPORTS_W std::vector<VideoCaptureAPIs> getWriterBackends();
/** @brief Returns true if backend is available */
CV_EXPORTS bool hasBackend(VideoCaptureAPIs api);
//! @}
}} // namespace

View File

@ -0,0 +1,81 @@
#!/bin/bash
set -e
if [ -z $1 ] ; then
echo "<script> <destination directory>"
exit 1
fi
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
OCV="$( cd "${DIR}/../../.." >/dev/null 2>&1 && pwd )"
mkdir -p "${1}" # Docker creates non-existed mounts with 'root' owner, lets ensure that dir exists under the current user to avoid "Permission denied" problem
DST="$( cd "$1" >/dev/null 2>&1 && pwd )"
CFG=$2
do_build()
{
TAG=$1
D=$2
F=$3
shift 3
docker build \
--build-arg http_proxy \
--build-arg https_proxy \
$@ \
-t $TAG \
-f "${D}/${F}" \
"${D}"
}
do_run()
{
TAG=$1
shift 1
docker run \
-it \
--rm \
-v "${OCV}":/opencv:ro \
-v "${DST}":/dst \
-e CFG=$CFG \
--user $(id -u):$(id -g) \
$TAG \
$@
}
build_gstreamer()
{
TAG=opencv_gstreamer_builder
do_build $TAG "${DIR}/plugin_gstreamer" Dockerfile
do_run $TAG /opencv/modules/videoio/misc/plugin_gstreamer/build.sh /dst $CFG
}
build_ffmpeg_ubuntu()
{
VER=$1
TAG=opencv_ffmpeg_ubuntu_builder:${VER}
do_build $TAG "${DIR}/plugin_ffmpeg" Dockerfile-ubuntu --build-arg VER=${VER}
do_run $TAG /opencv/modules/videoio/misc/plugin_ffmpeg/build-ubuntu.sh /dst ${VER} ${CFG}
}
build_ffmpeg()
{
VER=$1
TAG=opencv_ffmpeg_builder:${VER}
ARCHIVE="${DIR}/plugin_ffmpeg/ffmpeg-${VER}.tar.xz"
if [ ! -f "${ARCHIVE}" ] ; then
wget https://www.ffmpeg.org/releases/ffmpeg-${VER}.tar.xz -O "${ARCHIVE}"
fi
do_build $TAG "${DIR}/plugin_ffmpeg" Dockerfile-ffmpeg --build-arg VER=${VER}
do_run $TAG /opencv/modules/videoio/misc/plugin_ffmpeg/build-standalone.sh /dst ${VER} ${CFG}
}
echo "OpenCV: ${OCV}"
echo "Destination: ${DST}"
build_gstreamer
build_ffmpeg_ubuntu 18.04
build_ffmpeg_ubuntu 16.04
build_ffmpeg 4.1
build_ffmpeg 3.4.5
build_ffmpeg 2.8.15

View File

@ -0,0 +1 @@
*.tar.xz

View File

@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.5)
set(OpenCV_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../..")
set(WITH_FFMPEG ON)
set(OPENCV_FFMPEG_SKIP_BUILD_CHECK ON)
include("${OpenCV_SOURCE_DIR}/modules/videoio/cmake/plugin.cmake")
ocv_create_videoio_plugin("opencv_videoio_ffmpeg" "ocv.3rdparty.ffmpeg" "FFmpeg" "cap_ffmpeg.cpp")
message(STATUS "FFMPEG_libavcodec_VERSION=${FFMPEG_libavcodec_VERSION}")
message(STATUS "FFMPEG_libavformat_VERSION=${FFMPEG_libavformat_VERSION}")
message(STATUS "FFMPEG_libavutil_VERSION=${FFMPEG_libavutil_VERSION}")
message(STATUS "FFMPEG_libswscale_VERSION=${FFMPEG_libswscale_VERSION}")
message(STATUS "FFMPEG_libavresample_VERSION=${FFMPEG_libavresample_VERSION}")

View File

@ -0,0 +1,45 @@
FROM ubuntu:18.04
RUN apt-get update && apt-get install -y \
pkg-config \
cmake \
g++ \
ninja-build \
make \
nasm \
&& \
rm -rf /var/lib/apt/lists/*
ARG VER
ADD ffmpeg-${VER}.tar.xz /ffmpeg/
WORKDIR /ffmpeg/ffmpeg-${VER}
RUN ./configure \
--enable-avresample \
--prefix=/ffmpeg-shared \
--enable-shared \
--disable-static \
--disable-programs \
--disable-doc \
--disable-avdevice \
--disable-postproc \
&& make -j8 install \
&& make clean \
&& make distclean
RUN ./configure \
--enable-avresample \
--prefix=/ffmpeg-static \
--disable-shared \
--enable-static \
--enable-pic \
--disable-programs \
--disable-doc \
--disable-avdevice \
--disable-postproc \
&& make -j8 install \
&& make clean \
&& make distclean
WORKDIR /tmp

View File

@ -0,0 +1,17 @@
ARG VER
FROM ubuntu:$VER
RUN apt-get update && apt-get install -y \
libavcodec-dev \
libavfilter-dev \
libavformat-dev \
libavresample-dev \
libavutil-dev \
pkg-config \
cmake \
g++ \
ninja-build \
&& \
rm -rf /var/lib/apt/lists/*
WORKDIR /tmp

View File

@ -0,0 +1,24 @@
#!/bin/bash
set -e
mkdir -p build_shared && pushd build_shared
PKG_CONFIG_PATH=/ffmpeg-shared/lib/pkgconfig \
cmake -GNinja \
-DOPENCV_PLUGIN_NAME=opencv_videoio_ffmpeg_shared_$2 \
-DOPENCV_PLUGIN_DESTINATION=$1 \
-DCMAKE_BUILD_TYPE=$3 \
/opencv/modules/videoio/misc/plugin_ffmpeg
ninja
popd
mkdir -p build_static && pushd build_static
PKG_CONFIG_PATH=/ffmpeg-static/lib/pkgconfig \
cmake -GNinja \
-DOPENCV_PLUGIN_NAME=opencv_videoio_ffmpeg_static_$2 \
-DOPENCV_PLUGIN_DESTINATION=$1 \
-DCMAKE_MODULE_LINKER_FLAGS=-Wl,-Bsymbolic \
-DCMAKE_BUILD_TYPE=$3 \
/opencv/modules/videoio/misc/plugin_ffmpeg
ninja
popd

View File

@ -0,0 +1,10 @@
#!/bin/bash
set -e
cmake -GNinja \
-DOPENCV_PLUGIN_NAME=opencv_videoio_ffmpeg_ubuntu_$2 \
-DOPENCV_PLUGIN_DESTINATION=$1 \
-DCMAKE_BUILD_TYPE=$3 \
/opencv/modules/videoio/misc/plugin_ffmpeg
ninja

View File

@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.5)
set(OpenCV_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../..")
set(WITH_GSTREAMER ON)
include("${OpenCV_SOURCE_DIR}/modules/videoio/cmake/plugin.cmake")
ocv_create_videoio_plugin("opencv_videoio_gstreamer" "ocv.3rdparty.gstreamer" "GStreamer" "cap_gstreamer.cpp")
message(STATUS "Using GStreamer: ${GSTREAMER_VERSION}")

View File

@ -0,0 +1,13 @@
FROM ubuntu:18.04
RUN apt-get update && apt-get install -y \
libgstreamer-plugins-base1.0-dev \
libgstreamer-plugins-good1.0-dev \
libgstreamer1.0-dev \
cmake \
g++ \
ninja-build \
&& \
rm -rf /var/lib/apt/lists/*
WORKDIR /tmp

View File

@ -0,0 +1,11 @@
#!/bin/bash
set -e
cmake -GNinja \
-DOPENCV_PLUGIN_NAME=opencv_videoio_gstreamer \
-DOPENCV_PLUGIN_DESTINATION=$1 \
-DCMAKE_BUILD_TYPE=$2 \
/opencv/modules/videoio/misc/plugin_gstreamer
ninja

View File

@ -0,0 +1,44 @@
// 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 BACKEND_HPP_DEFINED
#define BACKEND_HPP_DEFINED
#include "cap_interface.hpp"
#include "opencv2/videoio/registry.hpp"
namespace cv {
// TODO: move to public interface
// TODO: allow runtime backend registration
class IBackend
{
public:
virtual ~IBackend() {}
virtual Ptr<IVideoCapture> createCapture(int camera) const = 0;
virtual Ptr<IVideoCapture> createCapture(const std::string &filename) const = 0;
virtual Ptr<IVideoWriter> createWriter(const std::string &filename, int fourcc, double fps, const cv::Size &sz, bool isColor) const = 0;
};
class IBackendFactory
{
public:
virtual ~IBackendFactory() {}
virtual Ptr<IBackend> getBackend() const = 0;
};
//=============================================================================
typedef Ptr<IVideoCapture> (*FN_createCaptureFile)(const std::string & filename);
typedef Ptr<IVideoCapture> (*FN_createCaptureCamera)(int camera);
typedef Ptr<IVideoWriter> (*FN_createWriter)(const std::string& filename, int fourcc, double fps, const Size& sz, bool isColor);
Ptr<IBackendFactory> createBackendFactory(FN_createCaptureFile createCaptureFile,
FN_createCaptureCamera createCaptureCamera,
FN_createWriter createWriter);
Ptr<IBackendFactory> createPluginBackendFactory(VideoCaptureAPIs id, const char* baseName);
} // namespace cv::
#endif // BACKEND_HPP_DEFINED

View File

@ -0,0 +1,493 @@
// 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.
#include "precomp.hpp"
#include "backend.hpp"
#include "plugin_api.hpp"
#include "opencv2/core/utils/filesystem.hpp"
#include "opencv2/core/utils/configuration.private.hpp"
#include "opencv2/core/private.hpp"
#include "videoio_registry.hpp"
//==================================================================================================
// Dynamic backend implementation
#include "opencv2/core/utils/logger.hpp"
#include <sstream>
using namespace std;
#if defined(_WIN32)
#include <windows.h>
#elif defined(__linux__) || defined(__APPLE__)
#include <dlfcn.h>
#endif
namespace cv { namespace impl {
#if defined(_WIN32)
typedef HMODULE LibHandle_t;
#elif defined(__linux__) || defined(__APPLE__)
typedef void* LibHandle_t;
#endif
static Mutex& getInitializationMutex()
{
static Mutex initializationMutex;
return initializationMutex;
}
static inline
void* getSymbol_(LibHandle_t h, const char* symbolName)
{
#if defined(_WIN32)
return (void*)GetProcAddress(h, symbolName);
#elif defined(__linux__) || defined(__APPLE__)
return dlsym(h, symbolName);
#endif
}
static inline
LibHandle_t libraryLoad_(const char* filename)
{
#if defined(_WIN32)
return LoadLibraryA(filename);
#elif defined(__linux__) || defined(__APPLE__)
return dlopen(filename, RTLD_LAZY);
#endif
}
static inline
void libraryRelease_(LibHandle_t h)
{
#if defined(_WIN32)
FreeLibrary(h);
#elif defined(__linux__) || defined(__APPLE__)
dlclose(h);
#endif
}
static inline
std::string libraryPrefix()
{
#if defined(_WIN32)
return string();
#else
return "lib";
#endif
}
static inline
std::string librarySuffix()
{
#if defined(_WIN32)
return ".dll";
#elif defined(__APPLE__)
return ".dylib";
#else
return ".so";
#endif
}
//============================
class DynamicLib
{
private:
LibHandle_t handle;
const std::string fname;
public:
DynamicLib(const std::string &filename)
: handle(0), fname(filename)
{
libraryLoad(filename);
}
~DynamicLib()
{
libraryRelease();
}
bool isLoaded() const
{
return handle != NULL;
}
void* getSymbol(const char* symbolName) const
{
if (!handle)
{
return 0;
}
void * res = getSymbol_(handle, symbolName);
if (!res)
CV_LOG_ERROR(NULL, "No symbol '" << symbolName << "' in " << fname);
return res;
}
const std::string& getName() const { return fname; }
private:
void libraryLoad(const std::string &filename)
{
handle = libraryLoad_(filename.c_str());
CV_LOG_INFO(NULL, "load " << filename << " => " << (handle ? "OK" : "FAILED"));
}
void libraryRelease()
{
CV_LOG_INFO(NULL, "unload "<< fname);
if (handle)
{
libraryRelease_(handle);
handle = 0;
}
}
private:
DynamicLib(const DynamicLib &);
DynamicLib &operator=(const DynamicLib &);
};
//============================
class PluginBackend: public IBackend
{
public:
Ptr<DynamicLib> lib_;
const OpenCV_VideoIO_Plugin_API_preview* plugin_api_;
PluginBackend(const Ptr<DynamicLib>& lib) :
lib_(lib), plugin_api_(NULL)
{
const char* init_name = "opencv_videoio_plugin_init_v0";
FN_opencv_videoio_plugin_init_t fn_init = reinterpret_cast<FN_opencv_videoio_plugin_init_t>(lib_->getSymbol(init_name));
if (fn_init)
{
plugin_api_ = fn_init(ABI_VERSION, API_VERSION, NULL);
if (!plugin_api_)
{
CV_LOG_INFO(NULL, "Video I/O: plugin is incompatible: " << lib->getName());
return;
}
// TODO Preview: add compatibility API/ABI checks
CV_LOG_INFO(NULL, "Video I/O: loaded plugin '" << plugin_api_->api_header.api_description << "'");
}
else
{
CV_LOG_INFO(NULL, "Video I/O: plugin is incompatible, missing init function: '" << init_name << "', file: " << lib->getName());
}
}
Ptr<IVideoCapture> createCapture(int camera) const CV_OVERRIDE;
Ptr<IVideoCapture> createCapture(const std::string &filename) const CV_OVERRIDE;
Ptr<IVideoWriter> createWriter(const std::string &filename, int fourcc, double fps, const cv::Size &sz, bool isColor) const CV_OVERRIDE;
};
class PluginBackendFactory : public IBackendFactory
{
public:
VideoCaptureAPIs id_;
const char* baseName_;
Ptr<PluginBackend> backend;
bool initialized;
public:
PluginBackendFactory(VideoCaptureAPIs id, const char* baseName) :
id_(id), baseName_(baseName),
initialized(false)
{
// nothing, plugins are loaded on demand
}
Ptr<IBackend> getBackend() const CV_OVERRIDE
{
if (!initialized)
{
const_cast<PluginBackendFactory*>(this)->initBackend();
}
return backend.staticCast<IBackend>();
}
protected:
void initBackend()
{
AutoLock lock(getInitializationMutex());
try {
if (!initialized)
loadPlugin();
}
catch (...)
{
CV_LOG_INFO(NULL, "Video I/O: exception during plugin loading: " << baseName_ << ". SKIP");
}
initialized = true;
}
void loadPlugin();
};
static
std::vector<string> getPluginCandidates(const std::string& baseName)
{
using namespace cv::utils;
using namespace cv::utils::fs;
#ifndef CV_VIDEOIO_PLUGIN_SUBDIRECTORY
#define CV_VIDEOIO_PLUGIN_SUBDIRECTORY_STR ""
#else
#define CV_VIDEOIO_PLUGIN_SUBDIRECTORY_STR CVAUX_STR(CV_VIDEOIO_PLUGIN_SUBDIRECTORY)
#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)
{
if (path.empty())
continue;
vector<string> candidates;
cv::glob(utils::fs::join(path, expr), candidates);
CV_LOG_INFO(NULL, " - " << path << ": " << candidates.size());
copy(candidates.begin(), candidates.end(), back_inserter(results));
}
CV_LOG_INFO(NULL, "Found " << results.size() << " plugin(s) for " << baseName);
return results;
}
void PluginBackendFactory::loadPlugin()
{
for(const std::string & plugin : getPluginCandidates(baseName_))
{
Ptr<DynamicLib> lib = makePtr<DynamicLib>(plugin);
if (!lib->isLoaded())
continue;
try
{
Ptr<PluginBackend> pluginBackend = makePtr<PluginBackend>(lib);
if (pluginBackend && pluginBackend->plugin_api_)
{
backend = pluginBackend;
return;
}
}
catch (...)
{
CV_LOG_INFO(NULL, "Video I/O: exception during plugin initialization: " << plugin << ". SKIP");
}
}
}
//==================================================================================================
class PluginCapture : public cv::IVideoCapture
{
const OpenCV_VideoIO_Plugin_API_preview* plugin_api_;
CvPluginCapture capture_;
public:
static
Ptr<PluginCapture> create(const OpenCV_VideoIO_Plugin_API_preview* plugin_api,
const std::string &filename, int camera)
{
CV_Assert(plugin_api);
CvPluginCapture capture = NULL;
if (plugin_api->Capture_open)
{
CV_Assert(plugin_api->Capture_release);
if (CV_ERROR_OK == plugin_api->Capture_open(filename.empty() ? 0 : filename.c_str(), camera, &capture))
{
CV_Assert(capture);
return makePtr<PluginCapture>(plugin_api, capture);
}
}
return Ptr<PluginCapture>();
}
PluginCapture(const OpenCV_VideoIO_Plugin_API_preview* plugin_api, CvPluginCapture capture)
: plugin_api_(plugin_api), capture_(capture)
{
CV_Assert(plugin_api_); CV_Assert(capture_);
}
~PluginCapture()
{
CV_DbgAssert(plugin_api_->Capture_release);
if (CV_ERROR_OK != plugin_api_->Capture_release(capture_))
CV_LOG_ERROR(NULL, "Video I/O: Can't release capture by plugin '" << plugin_api_->api_header.api_description << "'");
capture_ = NULL;
}
double getProperty(int prop) const CV_OVERRIDE
{
double val = -1;
if (plugin_api_->Capture_getProperty)
if (CV_ERROR_OK != plugin_api_->Capture_getProperty(capture_, prop, &val))
val = -1;
return val;
}
bool setProperty(int prop, double val) CV_OVERRIDE
{
if (plugin_api_->Capture_setProperty)
if (CV_ERROR_OK == plugin_api_->Capture_setProperty(capture_, prop, val))
return true;
return false;
}
bool grabFrame() CV_OVERRIDE
{
if (plugin_api_->Capture_grab)
if (CV_ERROR_OK == plugin_api_->Capture_grab(capture_))
return true;
return false;
}
static CvResult CV_API_CALL retrieve_callback(int stream_idx, const unsigned char* data, int step, int width, int height, int cn, void* userdata)
{
CV_UNUSED(stream_idx);
cv::_OutputArray* dst = static_cast<cv::_OutputArray*>(userdata);
if (!dst)
return CV_ERROR_FAIL;
cv::Mat(cv::Size(width, height), CV_MAKETYPE(CV_8U, cn), (void*)data, step).copyTo(*dst);
return CV_ERROR_OK;
}
bool retrieveFrame(int idx, cv::OutputArray img) CV_OVERRIDE
{
bool res = false;
if (plugin_api_->Capture_retreive)
if (CV_ERROR_OK == plugin_api_->Capture_retreive(capture_, idx, retrieve_callback, (cv::_OutputArray*)&img))
res = true;
return res;
}
bool isOpened() const CV_OVERRIDE
{
return capture_ != NULL; // TODO always true
}
int getCaptureDomain() CV_OVERRIDE
{
return plugin_api_->captureAPI;
}
};
//==================================================================================================
class PluginWriter : public cv::IVideoWriter
{
const OpenCV_VideoIO_Plugin_API_preview* plugin_api_;
CvPluginWriter writer_;
public:
static
Ptr<PluginWriter> create(const OpenCV_VideoIO_Plugin_API_preview* plugin_api,
const std::string &filename, int fourcc, double fps, const cv::Size &sz, bool isColor)
{
CV_Assert(plugin_api);
CvPluginWriter writer = NULL;
if (plugin_api->Writer_open)
{
CV_Assert(plugin_api->Writer_release);
if (CV_ERROR_OK == plugin_api->Writer_open(filename.empty() ? 0 : filename.c_str(), fourcc, fps, sz.width, sz.height, isColor, &writer))
{
CV_Assert(writer);
return makePtr<PluginWriter>(plugin_api, writer);
}
}
return Ptr<PluginWriter>();
}
PluginWriter(const OpenCV_VideoIO_Plugin_API_preview* plugin_api, CvPluginWriter writer)
: plugin_api_(plugin_api), writer_(writer)
{
CV_Assert(plugin_api_); CV_Assert(writer_);
}
~PluginWriter()
{
CV_DbgAssert(plugin_api_->Writer_release);
if (CV_ERROR_OK != plugin_api_->Writer_release(writer_))
CV_LOG_ERROR(NULL, "Video I/O: Can't release writer by plugin '" << plugin_api_->api_header.api_description << "'");
writer_ = NULL;
}
double getProperty(int prop) const CV_OVERRIDE
{
double val = -1;
if (plugin_api_->Writer_getProperty)
if (CV_ERROR_OK != plugin_api_->Writer_getProperty(writer_, prop, &val))
val = -1;
return val;
}
bool setProperty(int prop, double val) CV_OVERRIDE
{
if (plugin_api_->Writer_setProperty)
if (CV_ERROR_OK == plugin_api_->Writer_setProperty(writer_, prop, val))
return true;
return false;
}
bool isOpened() const CV_OVERRIDE
{
return writer_ != NULL; // TODO always true
}
void write(cv::InputArray arr) CV_OVERRIDE
{
cv::Mat img = arr.getMat();
CV_DbgAssert(writer_);
CV_Assert(plugin_api_->Writer_write);
if (CV_ERROR_OK != plugin_api_->Writer_write(writer_, img.data, (int)img.step[0], img.cols, img.rows, img.channels()))
{
CV_LOG_DEBUG(NULL, "Video I/O: Can't write frame by plugin '" << plugin_api_->api_header.api_description << "'");
}
// TODO return bool result?
}
int getCaptureDomain() const CV_OVERRIDE
{
return plugin_api_->captureAPI;
}
};
Ptr<IVideoCapture> PluginBackend::createCapture(int camera) const
{
try
{
if (plugin_api_)
return PluginCapture::create(plugin_api_, std::string(), camera); //.staticCast<IVideoCapture>();
}
catch (...)
{
CV_LOG_DEBUG(NULL, "Video I/O: can't create camera capture: " << camera);
}
return Ptr<IVideoCapture>();
}
Ptr<IVideoCapture> PluginBackend::createCapture(const std::string &filename) const
{
try
{
if (plugin_api_)
return PluginCapture::create(plugin_api_, filename, 0); //.staticCast<IVideoCapture>();
}
catch (...)
{
CV_LOG_DEBUG(NULL, "Video I/O: can't open file capture: " << filename);
}
return Ptr<IVideoCapture>();
}
Ptr<IVideoWriter> PluginBackend::createWriter(const std::string &filename, int fourcc, double fps, const cv::Size &sz, bool isColor) const
{
try
{
if (plugin_api_)
return PluginWriter::create(plugin_api_, filename, fourcc, fps, sz, isColor); //.staticCast<IVideoWriter>();
}
catch (...)
{
CV_LOG_DEBUG(NULL, "Video I/O: can't open writer: " << filename);
}
return Ptr<IVideoWriter>();
}
} // namespace
Ptr<IBackendFactory> createPluginBackendFactory(VideoCaptureAPIs id, const char* baseName)
{
return makePtr<impl::PluginBackendFactory>(id, baseName); //.staticCast<IBackendFactory>();
}
} // namespace

View File

@ -0,0 +1,72 @@
// 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.
#include "precomp.hpp"
#include "backend.hpp"
namespace cv {
class StaticBackend: public IBackend
{
public:
FN_createCaptureFile fn_createCaptureFile_;
FN_createCaptureCamera fn_createCaptureCamera_;
FN_createWriter fn_createWriter_;
StaticBackend(FN_createCaptureFile fn_createCaptureFile, FN_createCaptureCamera fn_createCaptureCamera, FN_createWriter fn_createWriter)
: fn_createCaptureFile_(fn_createCaptureFile), fn_createCaptureCamera_(fn_createCaptureCamera), fn_createWriter_(fn_createWriter)
{
// nothing
}
~StaticBackend() CV_OVERRIDE {}
Ptr<IVideoCapture> createCapture(int camera) const CV_OVERRIDE
{
if (fn_createCaptureCamera_)
return fn_createCaptureCamera_(camera);
return Ptr<IVideoCapture>();
}
Ptr<IVideoCapture> createCapture(const std::string &filename) const CV_OVERRIDE
{
if (fn_createCaptureFile_)
return fn_createCaptureFile_(filename);
return Ptr<IVideoCapture>();
}
Ptr<IVideoWriter> createWriter(const std::string &filename, int fourcc, double fps, const cv::Size &sz, bool isColor) const CV_OVERRIDE
{
if (fn_createWriter_)
return fn_createWriter_(filename, fourcc, fps, sz, isColor);
return Ptr<IVideoWriter>();
}
}; // StaticBackend
class StaticBackendFactory : public IBackendFactory
{
protected:
Ptr<StaticBackend> backend;
public:
StaticBackendFactory(FN_createCaptureFile createCaptureFile, FN_createCaptureCamera createCaptureCamera, FN_createWriter createWriter)
: backend(makePtr<StaticBackend>(createCaptureFile, createCaptureCamera, createWriter))
{
// nothing
}
~StaticBackendFactory() CV_OVERRIDE {}
Ptr<IBackend> getBackend() const CV_OVERRIDE
{
return backend.staticCast<IBackend>();
}
};
Ptr<IBackendFactory> createBackendFactory(FN_createCaptureFile createCaptureFile,
FN_createCaptureCamera createCaptureCamera,
FN_createWriter createWriter)
{
return makePtr<StaticBackendFactory>(createCaptureFile, createCaptureCamera, createWriter).staticCast<IBackendFactory>();
}
} // namespace

View File

@ -46,6 +46,11 @@
namespace cv {
static bool param_VIDEOIO_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOIO_DEBUG", false);
static bool param_VIDEOCAPTURE_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOCAPTURE_DEBUG", false);
static bool param_VIDEOWRITER_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOWRITER_DEBUG", false);
void DefaultDeleter<CvCapture>::operator ()(CvCapture* obj) const { cvReleaseCapture(&obj); }
void DefaultDeleter<CvVideoWriter>::operator ()(CvVideoWriter* obj) const { cvReleaseVideoWriter(&obj); }
@ -68,9 +73,7 @@ VideoCapture::VideoCapture(int index, int apiPreference)
VideoCapture::~VideoCapture()
{
CV_TRACE_FUNCTION();
icap.release();
cap.release();
}
bool VideoCapture::open(const String& filename, int apiPreference)
@ -85,19 +88,41 @@ bool VideoCapture::open(const String& filename, int apiPreference)
const VideoBackendInfo& info = backends[i];
if (apiPreference == CAP_ANY || apiPreference == info.id)
{
CvCapture* capture = NULL;
VideoCapture_create(capture, icap, info.id, filename);
if (!icap.empty())
if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG)
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying capture filename='%s' ...", info.name, filename.c_str()));
CV_Assert(!info.backendFactory.empty());
const Ptr<IBackend> backend = info.backendFactory->getBackend();
if (!backend.empty())
{
if (icap->isOpened())
return true;
icap.release();
try
{
icap = backend->createCapture(filename);
if (!icap.empty())
{
if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG)
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): created, isOpened=%d",
info.name, icap->isOpened()));
if (icap->isOpened())
return true;
icap.release();
}
else
{
if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG)
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): can't create capture", info.name));
}
} catch(const cv::Exception& e) {
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", info.name, e.what()));
} catch (const std::exception& e) {
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", info.name, e.what()));
} catch(...) {
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", info.name));
}
}
if (capture)
else
{
cap.reset(capture);
// assume it is opened
return true;
if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): backend is not available (plugin is missing, or can't be loaded due dependencies or it is not compatible)", info.name));
}
}
}
@ -127,19 +152,41 @@ bool VideoCapture::open(int cameraNum, int apiPreference)
const VideoBackendInfo& info = backends[i];
if (apiPreference == CAP_ANY || apiPreference == info.id)
{
CvCapture* capture = NULL;
VideoCapture_create(capture, icap, info.id, cameraNum);
if (!icap.empty())
if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG)
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying capture cameraNum=%d ...", info.name, cameraNum));
CV_Assert(!info.backendFactory.empty());
const Ptr<IBackend> backend = info.backendFactory->getBackend();
if (!backend.empty())
{
if (icap->isOpened())
return true;
icap.release();
try
{
icap = backend->createCapture(cameraNum);
if (!icap.empty())
{
if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG)
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): created, isOpened=%d",
info.name, icap->isOpened()));
if (icap->isOpened())
return true;
icap.release();
}
else
{
if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG)
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): can't create capture", info.name));
}
} catch(const cv::Exception& e) {
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", info.name, e.what()));
} catch (const std::exception& e) {
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", info.name, e.what()));
} catch(...) {
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", info.name));
}
}
if (capture)
else
{
cap.reset(capture);
// assume it is opened
return true;
if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): backend is not available (plugin is missing, or can't be loaded due dependencies or it is not compatible)", info.name));
}
}
}
@ -148,9 +195,7 @@ bool VideoCapture::open(int cameraNum, int apiPreference)
bool VideoCapture::isOpened() const
{
if (!icap.empty())
return icap->isOpened();
return !cap.empty(); // legacy interface doesn't support closed files
return !icap.empty() ? icap->isOpened() : false;
}
String VideoCapture::getBackendName() const
@ -158,8 +203,6 @@ String VideoCapture::getBackendName() const
int api = 0;
if (icap)
api = icap->isOpened() ? icap->getCaptureDomain() : 0;
else if (cap)
api = cap->getCaptureDomain();
CV_Assert(api != 0);
return cv::videoio_registry::getBackendName((VideoCaptureAPIs)api);
}
@ -168,39 +211,20 @@ void VideoCapture::release()
{
CV_TRACE_FUNCTION();
icap.release();
cap.release();
}
bool VideoCapture::grab()
{
CV_INSTRUMENT_REGION();
if (!icap.empty())
return icap->grabFrame();
return cvGrabFrame(cap) != 0;
return !icap.empty() ? icap->grabFrame() : false;
}
bool VideoCapture::retrieve(OutputArray image, int channel)
{
CV_INSTRUMENT_REGION();
if (!icap.empty())
return icap->retrieveFrame(channel, image);
IplImage* _img = cvRetrieveFrame(cap, channel);
if( !_img )
{
image.release();
return false;
}
if(_img->origin == IPL_ORIGIN_TL)
cv::cvarrToMat(_img).copyTo(image);
else
{
Mat temp = cv::cvarrToMat(_img);
flip(temp, image, 0);
}
return true;
return false;
}
bool VideoCapture::read(OutputArray image)
@ -253,10 +277,7 @@ VideoCapture& VideoCapture::operator >> (UMat& image)
bool VideoCapture::set(int propId, double value)
{
CV_CheckNE(propId, (int)CAP_PROP_BACKEND, "Can't set read-only property");
if (!icap.empty())
return icap->setProperty(propId, value);
return cvSetCaptureProperty(cap, propId, value) != 0;
return !icap.empty() ? icap->setProperty(propId, value) : false;
}
double VideoCapture::get(int propId) const
@ -266,15 +287,11 @@ double VideoCapture::get(int propId) const
int api = 0;
if (icap)
api = icap->isOpened() ? icap->getCaptureDomain() : 0;
else if (cap)
api = cap->getCaptureDomain();
if (api <= 0)
return -1.0;
return (double)api;
}
if (!icap.empty())
return icap->getProperty(propId);
return cap ? cap->getProperty(propId) : 0;
return !icap.empty() ? icap->getProperty(propId) : 0;
}
@ -299,7 +316,6 @@ VideoWriter::VideoWriter(const String& filename, int apiPreference, int _fourcc,
void VideoWriter::release()
{
iwriter.release();
writer.release();
}
VideoWriter::~VideoWriter()
@ -324,19 +340,42 @@ bool VideoWriter::open(const String& filename, int apiPreference, int _fourcc, d
const VideoBackendInfo& info = backends[i];
if (apiPreference == CAP_ANY || apiPreference == info.id)
{
CvVideoWriter* writer_ = NULL;
VideoWriter_create(writer_, iwriter, info.id, filename, _fourcc, fps, frameSize, isColor);
if (!iwriter.empty())
if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG)
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying writer with filename='%s' fourcc=0x%08x fps=%g sz=%dx%d isColor=%d...",
info.name, filename.c_str(), (unsigned)_fourcc, fps, frameSize.width, frameSize.height, (int)isColor));
CV_Assert(!info.backendFactory.empty());
const Ptr<IBackend> backend = info.backendFactory->getBackend();
if (!backend.empty())
{
if (iwriter->isOpened())
return true;
iwriter.release();
try
{
iwriter = backend->createWriter(filename, _fourcc, fps, frameSize, isColor);
if (!iwriter.empty())
{
if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG)
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): created, isOpened=%d",
info.name, iwriter->isOpened()));
if (iwriter->isOpened())
return true;
iwriter.release();
}
else
{
if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG)
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): can't create writer", info.name));
}
} catch(const cv::Exception& e) {
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", info.name, e.what()));
} catch (const std::exception& e) {
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", info.name, e.what()));
} catch(...) {
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", info.name));
}
}
if (writer_)
else
{
// assume it is opened
writer.reset(writer_);
return true;
if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): backend is not available (plugin is missing, or can't be loaded due dependencies or it is not compatible)", info.name));
}
}
}
@ -345,7 +384,7 @@ bool VideoWriter::open(const String& filename, int apiPreference, int _fourcc, d
bool VideoWriter::isOpened() const
{
return !iwriter.empty() || !writer.empty();
return !iwriter.empty();
}
@ -365,8 +404,6 @@ double VideoWriter::get(int propId) const
int api = 0;
if (iwriter)
api = iwriter->getCaptureDomain();
else if (writer)
api = writer->getCaptureDomain();
if (api <= 0)
return -1.0;
return (double)api;
@ -381,8 +418,6 @@ String VideoWriter::getBackendName() const
int api = 0;
if (iwriter)
api = iwriter->getCaptureDomain();
else if (writer)
api = writer->getCaptureDomain();
CV_Assert(api != 0);
return cv::videoio_registry::getBackendName((VideoCaptureAPIs)api);
}
@ -393,11 +428,6 @@ void VideoWriter::write(InputArray image)
if( iwriter )
iwriter->write(image);
else
{
IplImage _img = cvIplImage(image.getMat());
cvWriteFrame(writer, &_img);
}
}
VideoWriter& VideoWriter::operator << (const Mat& image)

View File

@ -44,6 +44,7 @@
//
#include "precomp.hpp"
#include "cap_interface.hpp"
#ifdef HAVE_ARAVIS_API
@ -606,12 +607,12 @@ bool CvCaptureCAM_Aravis::startCapture()
return false;
}
CvCapture* cvCreateCameraCapture_Aravis( int index )
cv::Ptr<cv::IVideoCapture> cv::create_Aravis_capture( int index )
{
CvCaptureCAM_Aravis* capture = new CvCaptureCAM_Aravis;
if(capture->open(index)) {
return capture;
return cv::makePtr<cv::LegacyCapture>(capture);
}
delete capture;

View File

@ -34,6 +34,7 @@
#include "precomp.hpp"
#include "opencv2/imgproc.hpp"
#include "cap_interface.hpp"
#include <iostream>
#import <AVFoundation/AVFoundation.h>
#import <Foundation/NSException.h>
@ -197,28 +198,30 @@ class CvVideoWriter_AVFoundation : public CvVideoWriter{
/****************** Implementation of interface functions ********************/
CvCapture* cvCreateFileCapture_AVFoundation(const char* filename) {
CvCaptureFile *retval = new CvCaptureFile(filename);
cv::Ptr<cv::IVideoCapture> cv::create_AVFoundation_capture_file(const std::string &filename)
{
CvCaptureFile *retval = new CvCaptureFile(filename.c_str());
if(retval->didStart())
return retval;
return makePtr<LegacyCapture>(retval);
delete retval;
return NULL;
}
CvCapture* cvCreateCameraCapture_AVFoundation(int index ) {
CvCapture* retval = new CvCaptureCAM(index);
if (!((CvCaptureCAM *)retval)->didStart())
cvReleaseCapture(&retval);
return retval;
}
CvVideoWriter* cvCreateVideoWriter_AVFoundation(const char* filename, int fourcc,
double fps, CvSize frame_size,
int is_color) {
return new CvVideoWriter_AVFoundation(filename, fourcc, fps, frame_size,is_color);
cv::Ptr<cv::IVideoCapture> cv::create_AVFoundation_capture_cam(int index)
{
CvCaptureCAM* retval = new CvCaptureCAM(index);
if (retval->didStart())
return cv::makePtr<cv::LegacyCapture>(retval);
delete retval;
return 0;
}
cv::Ptr<cv::IVideoWriter> cv::create_AVFoundation_writer(const std::string& filename, int fourcc, double fps, const cv::Size &frameSize, bool isColor)
{
CvSize sz = { frameSize.width, frameSize.height };
CvVideoWriter_AVFoundation* wrt = new CvVideoWriter_AVFoundation(filename.c_str(), fourcc, fps, sz, isColor);
return cv::makePtr<cv::LegacyWriter>(wrt);
}
/********************** Implementation of Classes ****************************/

View File

@ -208,27 +208,30 @@ class CvVideoWriter_AVFoundation : public CvVideoWriter {
/****************** Implementation of interface functions ********************/
CvCapture* cvCreateFileCapture_AVFoundation(const char* filename) {
CvCaptureFile *retval = new CvCaptureFile(filename);
cv::Ptr<cv::IVideoCapture> cv::create_AVFoundation_capture_file(const std::string &filename)
{
CvCaptureFile *retval = new CvCaptureFile(filename.c_str());
if(retval->didStart())
return retval;
return makePtr<LegacyCapture>(retval);
delete retval;
return NULL;
}
CvCapture* cvCreateCameraCapture_AVFoundation(int index ) {
CvCapture* retval = new CvCaptureCAM(index);
if (!((CvCaptureCAM *)retval)->didStart())
cvReleaseCapture(&retval);
return retval;
cv::Ptr<cv::IVideoCapture> cv::create_AVFoundation_capture_cam(int index)
{
CvCaptureCAM* retval = new CvCaptureCAM(index);
if (retval->didStart())
return cv::makePtr<cv::LegacyCapture>(retval);
delete retval;
return 0;
}
CvVideoWriter* cvCreateVideoWriter_AVFoundation(const char* filename, int fourcc,
double fps, CvSize frame_size,
int is_color) {
return new CvVideoWriter_AVFoundation(filename, fourcc, fps, frame_size,is_color);
cv::Ptr<cv::IVideoWriter> cv::create_AVFoundation_writer(const std::string& filename, int fourcc, double fps, const cv::Size &frameSize, bool isColor)
{
CvSize sz = { frameSize.width, frameSize.height };
CvVideoWriter_AVFoundation* wrt = new CvVideoWriter_AVFoundation(filename.c_str(), fourcc, fps, sz, isColor);
return cv::makePtr<cv::LegacyWriter>(wrt);
}
/********************** Implementation of Classes ****************************/

View File

@ -40,6 +40,7 @@
//M*/
#include "precomp.hpp"
#include "cap_interface.hpp"
#ifdef HAVE_DC1394_2
@ -797,13 +798,11 @@ bool CvCaptureCAM_DC1394_v2_CPP::setProperty(int propId, double value)
}
CvCapture* cvCreateCameraCapture_DC1394_2(int index)
cv::Ptr<cv::IVideoCapture> cv::create_DC1394_capture(int index)
{
CvCaptureCAM_DC1394_v2_CPP* capture = new CvCaptureCAM_DC1394_v2_CPP;
if (capture->open(index))
return capture;
return cv::makePtr<cv::LegacyCapture>(capture);
delete capture;
return 0;
}

View File

@ -3580,6 +3580,12 @@ void VideoCapture_DShow::close()
m_widthSet = m_heightSet = m_width = m_height = -1;
}
Ptr<IVideoCapture> create_DShow_capture(int index)
{
return makePtr<VideoCapture_DShow>(index);
}
}
#endif

View File

@ -43,4 +43,4 @@ protected:
}
#endif //HAVE_DSHOW
#endif //_CAP_DSHOW_HPP_
#endif //_CAP_DSHOW_HPP_

View File

@ -266,7 +266,7 @@ protected:
} // namespace
cv::Ptr<cv::IVideoCapture> cvCreateFileCapture_FFMPEG_proxy(const cv::String& filename)
cv::Ptr<cv::IVideoCapture> cvCreateFileCapture_FFMPEG_proxy(const std::string &filename)
{
#if defined(HAVE_FFMPEG_WRAPPER)
icvInitFFMPEG::Init();
@ -328,8 +328,7 @@ protected:
} // namespace
cv::Ptr<cv::IVideoWriter> cvCreateVideoWriter_FFMPEG_proxy(const cv::String& filename, int fourcc,
double fps, cv::Size frameSize, int isColor)
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();
@ -345,3 +344,217 @@ cv::Ptr<cv::IVideoWriter> cvCreateVideoWriter_FFMPEG_proxy(const cv::String& fil
} // namespace
#endif // defined(HAVE_FFMPEG)
//==================================================================================================
#if defined(BUILD_PLUGIN)
#include "plugin_api.hpp"
namespace cv {
static
CvResult CV_API_CALL cv_capture_open(const char* filename, int camera_index, CV_OUT CvPluginCapture* handle)
{
if (!handle)
return CV_ERROR_FAIL;
*handle = NULL;
if (!filename)
return CV_ERROR_FAIL;
CV_UNUSED(camera_index);
CvCapture_FFMPEG_proxy *cap = 0;
try
{
cap = new CvCapture_FFMPEG_proxy(filename);
if (cap->isOpened())
{
*handle = (CvPluginCapture)cap;
return CV_ERROR_OK;
}
}
catch (...)
{
}
if (cap)
delete cap;
return CV_ERROR_FAIL;
}
static
CvResult CV_API_CALL cv_capture_release(CvPluginCapture handle)
{
if (!handle)
return CV_ERROR_FAIL;
CvCapture_FFMPEG_proxy* instance = (CvCapture_FFMPEG_proxy*)handle;
delete instance;
return CV_ERROR_OK;
}
static
CvResult CV_API_CALL cv_capture_get_prop(CvPluginCapture handle, int prop, CV_OUT double* val)
{
if (!handle)
return CV_ERROR_FAIL;
if (!val)
return CV_ERROR_FAIL;
try
{
CvCapture_FFMPEG_proxy* instance = (CvCapture_FFMPEG_proxy*)handle;
*val = instance->getProperty(prop);
return CV_ERROR_OK;
}
catch (...)
{
return CV_ERROR_FAIL;
}
}
static
CvResult CV_API_CALL cv_capture_set_prop(CvPluginCapture handle, int prop, double val)
{
if (!handle)
return CV_ERROR_FAIL;
try
{
CvCapture_FFMPEG_proxy* instance = (CvCapture_FFMPEG_proxy*)handle;
return instance->setProperty(prop, val) ? CV_ERROR_OK : CV_ERROR_FAIL;
}
catch(...)
{
return CV_ERROR_FAIL;
}
}
static
CvResult CV_API_CALL cv_capture_grab(CvPluginCapture handle)
{
if (!handle)
return CV_ERROR_FAIL;
try
{
CvCapture_FFMPEG_proxy* instance = (CvCapture_FFMPEG_proxy*)handle;
return instance->grabFrame() ? CV_ERROR_OK : CV_ERROR_FAIL;
}
catch(...)
{
return CV_ERROR_FAIL;
}
}
static
CvResult CV_API_CALL cv_capture_retrieve(CvPluginCapture handle, int stream_idx, cv_videoio_retrieve_cb_t callback, void* userdata)
{
if (!handle)
return CV_ERROR_FAIL;
try
{
CvCapture_FFMPEG_proxy* instance = (CvCapture_FFMPEG_proxy*)handle;
Mat img;
// TODO: avoid unnecessary copying
if (instance->retrieveFrame(stream_idx, img))
return callback(stream_idx, img.data, img.step, img.cols, img.rows, img.channels(), userdata);
return CV_ERROR_FAIL;
}
catch(...)
{
return CV_ERROR_FAIL;
}
}
static
CvResult CV_API_CALL cv_writer_open(const char* filename, int fourcc, double fps, int width, int height, int isColor,
CV_OUT CvPluginWriter* handle)
{
Size sz(width, height);
CvVideoWriter_FFMPEG_proxy* wrt = 0;
try
{
wrt = new CvVideoWriter_FFMPEG_proxy(filename, fourcc, fps, sz, isColor != 0);
if(wrt && wrt->isOpened())
{
*handle = (CvPluginWriter)wrt;
return CV_ERROR_OK;
}
}
catch(...)
{
}
if (wrt)
delete wrt;
return CV_ERROR_FAIL;
}
static
CvResult CV_API_CALL cv_writer_release(CvPluginWriter handle)
{
if (!handle)
return CV_ERROR_FAIL;
CvVideoWriter_FFMPEG_proxy* instance = (CvVideoWriter_FFMPEG_proxy*)handle;
delete instance;
return CV_ERROR_OK;
}
static
CvResult CV_API_CALL cv_writer_get_prop(CvPluginWriter /*handle*/, int /*prop*/, CV_OUT double* /*val*/)
{
return CV_ERROR_FAIL;
}
static
CvResult CV_API_CALL cv_writer_set_prop(CvPluginWriter /*handle*/, int /*prop*/, double /*val*/)
{
return CV_ERROR_FAIL;
}
static
CvResult CV_API_CALL cv_writer_write(CvPluginWriter handle, const unsigned char *data, int step, int width, int height, int cn)
{
if (!handle)
return CV_ERROR_FAIL;
try
{
CvVideoWriter_FFMPEG_proxy* instance = (CvVideoWriter_FFMPEG_proxy*)handle;
Mat img(Size(width, height), CV_MAKETYPE(CV_8U, cn), const_cast<uchar*>(data), step);
instance->write(img);
return CV_ERROR_OK;
}
catch(...)
{
return CV_ERROR_FAIL;
}
}
static const OpenCV_VideoIO_Plugin_API_preview plugin_api_v0 =
{
{
sizeof(OpenCV_VideoIO_Plugin_API_preview), ABI_VERSION, API_VERSION,
CV_VERSION_MAJOR, CV_VERSION_MINOR, CV_VERSION_REVISION, CV_VERSION_STATUS,
"FFmpeg OpenCV Video I/O plugin"
},
/* 1*/CAP_FFMPEG,
/* 2*/cv_capture_open,
/* 3*/cv_capture_release,
/* 4*/cv_capture_get_prop,
/* 5*/cv_capture_set_prop,
/* 6*/cv_capture_grab,
/* 7*/cv_capture_retrieve,
/* 8*/cv_writer_open,
/* 9*/cv_writer_release,
/* 10*/cv_writer_get_prop,
/* 11*/cv_writer_set_prop,
/* 12*/cv_writer_write
};
} // namespace
const OpenCV_VideoIO_Plugin_API_preview* opencv_videoio_plugin_init_v0(int requested_abi_version, int requested_api_version, void* /*reserved=NULL*/) CV_NOEXCEPT
{
if (requested_abi_version != 0)
return NULL;
if (requested_api_version != 0)
return NULL;
return &cv::plugin_api_v0;
}
#endif // BUILD_PLUGIN

View File

@ -6,13 +6,17 @@ extern "C"
{
#endif
#if defined _WIN32
#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
{

View File

@ -785,7 +785,6 @@ static int LockCallBack(void **mutex, AVLockOp op)
}
static ImplMutex _mutex;
static bool _initialized = false;
class AutoLock
{
@ -814,49 +813,45 @@ static void ffmpeg_log_callback(void *ptr, int level, const char *fmt, va_list v
class InternalFFMpegRegister
{
public:
InternalFFMpegRegister()
static void init()
{
AutoLock lock(_mutex);
if (!_initialized)
{
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 13, 0)
avformat_network_init();
#endif
static InternalFFMpegRegister instance;
}
InternalFFMpegRegister()
{
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 13, 0)
avformat_network_init();
#endif
/* register all codecs, demux and protocols */
av_register_all();
/* register all codecs, demux and protocols */
av_register_all();
/* register a callback function for synchronization */
av_lockmgr_register(&LockCallBack);
/* register a callback function for synchronization */
av_lockmgr_register(&LockCallBack);
#ifndef NO_GETENV
char* debug_option = getenv("OPENCV_FFMPEG_DEBUG");
if (debug_option != NULL)
{
av_log_set_level(AV_LOG_VERBOSE);
av_log_set_callback(ffmpeg_log_callback);
}
else
char* debug_option = getenv("OPENCV_FFMPEG_DEBUG");
if (debug_option != NULL)
{
av_log_set_level(AV_LOG_VERBOSE);
av_log_set_callback(ffmpeg_log_callback);
}
else
#endif
{
av_log_set_level(AV_LOG_ERROR);
}
_initialized = true;
{
av_log_set_level(AV_LOG_ERROR);
}
}
~InternalFFMpegRegister()
{
_initialized = false;
av_lockmgr_register(NULL);
}
};
static InternalFFMpegRegister _init;
bool CvCapture_FFMPEG::open( const char* _filename )
{
InternalFFMpegRegister::init();
AutoLock lock(_mutex);
unsigned i;
bool valid = false;
@ -1997,6 +1992,7 @@ static inline void cv_ff_codec_tag_dump(const AVCodecTag *const *tags)
bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
double fps, int width, int height, bool is_color )
{
InternalFFMpegRegister::init();
CV_CODEC_ID codec_id = CV_CODEC(CODEC_ID_NONE);
int err, codec_pix_fmt;
double bitrate_scale = 1;

View File

@ -1207,7 +1207,7 @@ Ptr<IVideoCapture> createGPhoto2Capture(int index)
*
* @param deviceName is a substring in digital camera model name.
*/
Ptr<IVideoCapture> createGPhoto2Capture(const String & deviceName)
Ptr<IVideoCapture> createGPhoto2Capture(const std::string & deviceName)
{
Ptr<IVideoCapture> capture = makePtr<gphoto2::DigitalCameraCapture>(deviceName);

View File

@ -71,7 +71,7 @@ using namespace std;
#ifdef NDEBUG
#define CV_WARN(message)
#else
#define CV_WARN(message) fprintf(stderr, "OpenCV | GStreamer warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
#define CV_WARN(message) CV_LOG_WARNING(0, message)
#endif
#define COLOR_ELEM "videoconvert"
@ -232,7 +232,7 @@ GStreamerCapture::~GStreamerCapture()
*/
bool GStreamerCapture::grabFrame()
{
if(!pipeline)
if(!GST_IS_ELEMENT(pipeline))
return false;
// start the pipeline if it was not in playing state yet
@ -372,6 +372,11 @@ bool GStreamerCapture::determineFrameDims(Size &sz)
*/
bool GStreamerCapture::isPipelinePlaying()
{
if (!GST_IS_ELEMENT(pipeline))
{
CV_WARN("GStreamer: pipeline have not been created");
return false;
}
GstState current, pending;
GstClockTime timeout = 5*GST_SECOND;
GstStateChangeReturn ret = gst_element_get_state(pipeline, &current, &pending, timeout);
@ -389,8 +394,12 @@ bool GStreamerCapture::isPipelinePlaying()
*/
void GStreamerCapture::startPipeline()
{
//fprintf(stderr, "relinked, pausing\n");
GstStateChangeReturn status = gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PLAYING);
if (!GST_IS_ELEMENT(pipeline))
{
CV_WARN("GStreamer: pipeline have not been created");
return;
}
GstStateChangeReturn status = gst_element_set_state(pipeline, GST_STATE_PLAYING);
if (status == GST_STATE_CHANGE_ASYNC)
{
// wait for status update
@ -408,7 +417,6 @@ void GStreamerCapture::startPipeline()
if (isPosFramesEmulated)
emulatedFrameNumber = 0;
//printf("state now playing\n");
handleMessage(pipeline);
}
@ -418,8 +426,12 @@ void GStreamerCapture::startPipeline()
*/
void GStreamerCapture::stopPipeline()
{
//fprintf(stderr, "restarting pipeline, going to ready\n");
if(gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_NULL) == GST_STATE_CHANGE_FAILURE)
if (!GST_IS_ELEMENT(pipeline))
{
CV_WARN("GStreamer: pipeline have not been created");
return;
}
if(gst_element_set_state(pipeline, GST_STATE_NULL) == GST_STATE_CHANGE_FAILURE)
{
CV_WARN("GStreamer: unable to stop pipeline");
gst_object_unref(pipeline);
@ -449,7 +461,6 @@ void GStreamerCapture::restartPipeline()
*/
void GStreamerCapture::setFilter(const char *prop, int type, int v1, int v2)
{
//printf("GStreamer: setFilter \n");
if(!caps || !( GST_IS_CAPS (caps) ))
{
if(type == G_TYPE_INT)
@ -475,7 +486,6 @@ void GStreamerCapture::setFilter(const char *prop, int type, int v1, int v2)
caps = gst_caps_fixate(caps);
gst_app_sink_set_caps(GST_APP_SINK(sink), caps);
//printf("filtering with %s\n", gst_caps_to_string(caps));
}
/*!
@ -511,7 +521,6 @@ void GStreamerCapture::newPad(GstElement *, GstPad *pad, gpointer data)
sinkpad = gst_element_get_static_pad (color, "sink");
if (!sinkpad){
//fprintf(stderr, "Gstreamer: no pad named sink\n");
return;
}
@ -622,7 +631,7 @@ bool GStreamerCapture::open(const String &filename_)
uridecodebin = gst_parse_launch(filename, &err);
if(!uridecodebin)
{
fprintf(stderr, "GStreamer: Error opening bin: %s\n", err->message);
CV_WARN("GStreamer: Error opening bin: " << err->message);
return false;
}
//stream = true;
@ -835,11 +844,11 @@ bool GStreamerCapture::open(const String &filename_)
gboolean status_;
format_ = GST_FORMAT_DEFAULT;
status_ = gst_element_query_position(sink, format_, &value_);
if (!status_ || value_ != 0 || duration < 0)
{
CV_WARN(cv::format("Cannot query video position: status=%d value=%lld duration=%lld\n",
(int)status_, (long long int)value_, (long long int)duration).c_str());
CV_WARN("Cannot query video position: status=" << status_ << ", value=" << value_ << ", duration=" << duration);
isPosFramesSupported = false;
isPosFramesEmulated = true;
emulatedFrameNumber = 0;
@ -1099,7 +1108,7 @@ bool GStreamerCapture::setProperty(int propId, double value)
}
Ptr<IVideoCapture> cv::createGStreamerCapture(const String& filename)
Ptr<IVideoCapture> cv::createGStreamerCapture_file(const String& filename)
{
Ptr<GStreamerCapture> cap = makePtr<GStreamerCapture>();
if (cap && cap->open(filename))
@ -1107,7 +1116,7 @@ Ptr<IVideoCapture> cv::createGStreamerCapture(const String& filename)
return Ptr<IVideoCapture>();
}
Ptr<IVideoCapture> cv::createGStreamerCapture(int index)
Ptr<IVideoCapture> cv::createGStreamerCapture_cam(int index)
{
Ptr<GStreamerCapture> cap = makePtr<GStreamerCapture>();
if (cap && cap->open(index))
@ -1133,10 +1142,10 @@ public:
int getCaptureDomain() const CV_OVERRIDE { return cv::CAP_GSTREAMER; }
virtual bool open( const char* filename, int fourcc,
double fps, CvSize frameSize, bool isColor );
virtual void close();
virtual bool writeFrame( const IplImage* image ) CV_OVERRIDE;
bool open(const char* filename, int fourcc,
double fps, const Size &frameSize, bool isColor );
void close();
bool writeFrame( const IplImage* image ) CV_OVERRIDE;
protected:
const char* filenameToMimetype(const char* filename);
GstElement* pipeline;
@ -1272,7 +1281,7 @@ const char* CvVideoWriter_GStreamer::filenameToMimetype(const char *filename)
*
*/
bool CvVideoWriter_GStreamer::open( const char * filename, int fourcc,
double fps, CvSize frameSize, bool is_color )
double fps, const cv::Size &frameSize, bool is_color )
{
// check arguments
assert (filename);
@ -1532,22 +1541,11 @@ bool CvVideoWriter_GStreamer::writeFrame( const IplImage * image )
return true;
}
/*!
* \brief cvCreateVideoWriter_GStreamer
* \param filename
* \param fourcc
* \param fps
* \param frameSize
* \param isColor
* \return
* Constructor
*/
CvVideoWriter* cvCreateVideoWriter_GStreamer(const char* filename, int fourcc, double fps,
CvSize frameSize, int isColor )
Ptr<IVideoWriter> cv::create_GStreamer_writer(const std::string& filename, int fourcc, double fps, const cv::Size &frameSize, bool isColor)
{
CvVideoWriter_GStreamer* wrt = new CvVideoWriter_GStreamer;
if( wrt->open(filename, fourcc, fps,frameSize, isColor))
return wrt;
if (wrt->open(filename.c_str(), fourcc, fps, frameSize, isColor))
return makePtr<LegacyWriter>(wrt);
delete wrt;
return 0;
@ -1593,8 +1591,6 @@ void handleMessage(GstElement * pipeline)
while(gst_bus_have_pending(bus)) {
msg = gst_bus_pop(bus);
//printf("\t\tGot %s message\n", GST_MESSAGE_TYPE_NAME(msg));
if(gst_is_missing_plugin_message(msg))
{
CV_WARN("your gstreamer installation is missing a required plugin\n");
@ -1605,30 +1601,19 @@ void handleMessage(GstElement * pipeline)
case GST_MESSAGE_STATE_CHANGED:
GstState oldstate, newstate, pendstate;
gst_message_parse_state_changed(msg, &oldstate, &newstate, &pendstate);
//fprintf(stderr, "\t\t%s: state changed from %s to %s (pending: %s)\n",
// gst_element_get_name(GST_MESSAGE_SRC (msg)),
// gst_element_state_get_name(oldstate),
// gst_element_state_get_name(newstate), gst_element_state_get_name(pendstate));
break;
case GST_MESSAGE_ERROR:
gst_message_parse_error(msg, &err, &debug);
//fprintf(stderr, "\t\tGStreamer Plugin: Embedded video playback halted; module %s reported: %s\n",
// gst_element_get_name(GST_MESSAGE_SRC (msg)), err->message);
g_error_free(err);
g_free(debug);
gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_NULL);
break;
case GST_MESSAGE_EOS:
//fprintf(stderr, "\t\treached the end of the stream.");
break;
case GST_MESSAGE_STREAM_STATUS:
gst_message_parse_stream_status(msg,&tp,&elem);
//fprintf(stderr, "\t\tstream status: elem %s, %i\n", GST_ELEMENT_NAME(elem), tp);
break;
default:
//fprintf(stderr, "\t\tunhandled message %s\n",GST_MESSAGE_TYPE_NAME(msg));
break;
}
}
@ -1637,3 +1622,223 @@ void handleMessage(GstElement * pipeline)
gst_object_unref(GST_OBJECT(bus));
}
//==================================================================================================
#if defined(BUILD_PLUGIN)
#include "plugin_api.hpp"
namespace cv {
static
CvResult CV_API_CALL cv_capture_open(const char* filename, int camera_index, CV_OUT CvPluginCapture* handle)
{
if (!handle)
return CV_ERROR_FAIL;
*handle = NULL;
if (!filename)
return CV_ERROR_FAIL;
GStreamerCapture *cap = 0;
try
{
cap = new GStreamerCapture();
bool res;
if (filename)
res = cap->open(string(filename));
else
res = cap->open(camera_index);
if (res)
{
*handle = (CvPluginCapture)cap;
return CV_ERROR_OK;
}
}
catch (...)
{
}
if (cap)
delete cap;
return CV_ERROR_FAIL;
}
static
CvResult CV_API_CALL cv_capture_release(CvPluginCapture handle)
{
if (!handle)
return CV_ERROR_FAIL;
GStreamerCapture* instance = (GStreamerCapture*)handle;
delete instance;
return CV_ERROR_OK;
}
static
CvResult CV_API_CALL cv_capture_get_prop(CvPluginCapture handle, int prop, CV_OUT double* val)
{
if (!handle)
return CV_ERROR_FAIL;
if (!val)
return CV_ERROR_FAIL;
try
{
GStreamerCapture* instance = (GStreamerCapture*)handle;
*val = instance->getProperty(prop);
return CV_ERROR_OK;
}
catch (...)
{
return CV_ERROR_FAIL;
}
}
static
CvResult CV_API_CALL cv_capture_set_prop(CvPluginCapture handle, int prop, double val)
{
if (!handle)
return CV_ERROR_FAIL;
try
{
GStreamerCapture* instance = (GStreamerCapture*)handle;
return instance->setProperty(prop, val) ? CV_ERROR_OK : CV_ERROR_FAIL;
}
catch(...)
{
return CV_ERROR_FAIL;
}
}
static
CvResult CV_API_CALL cv_capture_grab(CvPluginCapture handle)
{
if (!handle)
return CV_ERROR_FAIL;
try
{
GStreamerCapture* instance = (GStreamerCapture*)handle;
return instance->grabFrame() ? CV_ERROR_OK : CV_ERROR_FAIL;
}
catch(...)
{
return CV_ERROR_FAIL;
}
}
static
CvResult CV_API_CALL cv_capture_retrieve(CvPluginCapture handle, int stream_idx, cv_videoio_retrieve_cb_t callback, void* userdata)
{
if (!handle)
return CV_ERROR_FAIL;
try
{
GStreamerCapture* instance = (GStreamerCapture*)handle;
Mat img;
// TODO: avoid unnecessary copying - implement lower level GStreamerCapture::retrieve
if (instance->retrieveFrame(stream_idx, img))
return callback(stream_idx, img.data, img.step, img.cols, img.rows, img.channels(), userdata);
return CV_ERROR_FAIL;
}
catch(...)
{
return CV_ERROR_FAIL;
}
}
static
CvResult CV_API_CALL cv_writer_open(const char* filename, int fourcc, double fps, int width, int height, int isColor,
CV_OUT CvPluginWriter* handle)
{
CvVideoWriter_GStreamer* wrt = 0;
try
{
wrt = new CvVideoWriter_GStreamer();
CvSize sz = { width, height };
if(wrt && wrt->open(filename, fourcc, fps, sz, isColor))
{
*handle = (CvPluginWriter)wrt;
return CV_ERROR_OK;
}
}
catch(...)
{
}
if (wrt)
delete wrt;
return CV_ERROR_FAIL;
}
static
CvResult CV_API_CALL cv_writer_release(CvPluginWriter handle)
{
if (!handle)
return CV_ERROR_FAIL;
CvVideoWriter_GStreamer* instance = (CvVideoWriter_GStreamer*)handle;
delete instance;
return CV_ERROR_OK;
}
static
CvResult CV_API_CALL cv_writer_get_prop(CvPluginWriter /*handle*/, int /*prop*/, CV_OUT double* /*val*/)
{
return CV_ERROR_FAIL;
}
static
CvResult CV_API_CALL cv_writer_set_prop(CvPluginWriter /*handle*/, int /*prop*/, double /*val*/)
{
return CV_ERROR_FAIL;
}
static
CvResult CV_API_CALL cv_writer_write(CvPluginWriter handle, const unsigned char *data, int step, int width, int height, int cn)
{
if (!handle)
return CV_ERROR_FAIL;
try
{
CvVideoWriter_GStreamer* instance = (CvVideoWriter_GStreamer*)handle;
CvSize sz = { width, height };
IplImage img;
cvInitImageHeader(&img, sz, IPL_DEPTH_8U, cn);
cvSetData(&img, const_cast<unsigned char*>(data), step);
return instance->writeFrame(&img) ? CV_ERROR_OK : CV_ERROR_FAIL;
}
catch(...)
{
return CV_ERROR_FAIL;
}
}
static const OpenCV_VideoIO_Plugin_API_preview plugin_api_v0 =
{
{
sizeof(OpenCV_VideoIO_Plugin_API_preview), ABI_VERSION, API_VERSION,
CV_VERSION_MAJOR, CV_VERSION_MINOR, CV_VERSION_REVISION, CV_VERSION_STATUS,
"GStreamer OpenCV Video I/O plugin"
},
/* 1*/CAP_GSTREAMER,
/* 2*/cv_capture_open,
/* 3*/cv_capture_release,
/* 4*/cv_capture_get_prop,
/* 5*/cv_capture_set_prop,
/* 6*/cv_capture_grab,
/* 7*/cv_capture_retrieve,
/* 8*/cv_writer_open,
/* 9*/cv_writer_release,
/* 10*/cv_writer_get_prop,
/* 11*/cv_writer_set_prop,
/* 12*/cv_writer_write
};
} // namespace
const OpenCV_VideoIO_Plugin_API_preview* opencv_videoio_plugin_init_v0(int requested_abi_version, int requested_api_version, void* /*reserved=NULL*/) CV_NOEXCEPT
{
if (requested_abi_version != 0)
return NULL;
if (requested_api_version != 0)
return NULL;
return &cv::plugin_api_v0;
}
#endif // BUILD_PLUGIN

View File

@ -315,14 +315,9 @@ bool CvCapture_Images::isOpened() const
return !filename.empty();
}
Ptr<IVideoCapture> createFileCapture_Images(const String& filename)
Ptr<IVideoCapture> create_Images_capture(const std::string &filename)
{
Ptr<IVideoCapture> capture(new CvCapture_Images(filename));
if( capture->isOpened() )
return capture;
return Ptr<IVideoCapture>();
}
return makePtr<CvCapture_Images>(filename);
}
//
@ -410,14 +405,15 @@ bool CvVideoWriter_Images::setProperty( int id, double value )
return false; // not supported
}
CvVideoWriter* cvCreateVideoWriter_Images( const char* filename )
Ptr<IVideoWriter> create_Images_writer(const std::string &filename, int, double, const Size &, bool)
{
CvVideoWriter_Images *writer = new CvVideoWriter_Images;
if( writer->open( filename ))
return writer;
if( writer->open( filename.c_str() ))
return makePtr<LegacyWriter>(writer);
delete writer;
return 0;
}
} // cv::

View File

@ -0,0 +1,211 @@
// 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 CAP_INTERFACE_HPP
#define CAP_INTERFACE_HPP
#include "opencv2/core.hpp"
#include "opencv2/core/core_c.h"
#include "opencv2/videoio.hpp"
#include "opencv2/videoio/videoio_c.h"
//===================================================
// Legacy structs
struct CvCapture
{
virtual ~CvCapture() {}
virtual double getProperty(int) const { return 0; }
virtual bool setProperty(int, double) { return 0; }
virtual bool grabFrame() { return true; }
virtual IplImage* retrieveFrame(int) { return 0; }
virtual int getCaptureDomain() { return cv::CAP_ANY; } // Return the type of the capture object: CAP_DSHOW, etc...
};
struct CvVideoWriter
{
virtual ~CvVideoWriter() {}
virtual bool writeFrame(const IplImage*) { return false; }
virtual int getCaptureDomain() const { return cv::CAP_ANY; } // Return the type of the capture object: CAP_FFMPEG, etc...
};
//===================================================
// Modern classes
namespace cv
{
class IVideoCapture
{
public:
virtual ~IVideoCapture() {}
virtual double getProperty(int) const { return 0; }
virtual bool setProperty(int, double) { return false; }
virtual bool grabFrame() = 0;
virtual bool retrieveFrame(int, OutputArray) = 0;
virtual bool isOpened() const = 0;
virtual int getCaptureDomain() { return CAP_ANY; } // Return the type of the capture object: CAP_DSHOW, etc...
};
class IVideoWriter
{
public:
virtual ~IVideoWriter() {}
virtual double getProperty(int) const { return 0; }
virtual bool setProperty(int, double) { return false; }
virtual bool isOpened() const = 0;
virtual void write(InputArray) = 0;
virtual int getCaptureDomain() const { return cv::CAP_ANY; } // Return the type of the capture object: CAP_FFMPEG, etc...
};
//===================================================
// Wrapper
class LegacyCapture : public IVideoCapture
{
private:
CvCapture * cap;
LegacyCapture(const LegacyCapture &);
LegacyCapture& operator=(const LegacyCapture &);
public:
LegacyCapture(CvCapture * cap_) : cap(cap_) {}
~LegacyCapture()
{
cvReleaseCapture(&cap);
}
double getProperty(int propId) const CV_OVERRIDE
{
return cap ? cap->getProperty(propId) : 0;
}
bool setProperty(int propId, double value) CV_OVERRIDE
{
return cvSetCaptureProperty(cap, propId, value) != 0;
}
bool grabFrame() CV_OVERRIDE
{
return cap ? cvGrabFrame(cap) != 0 : false;
}
bool retrieveFrame(int channel, OutputArray image) CV_OVERRIDE
{
IplImage* _img = cvRetrieveFrame(cap, channel);
if( !_img )
{
image.release();
return false;
}
if(_img->origin == IPL_ORIGIN_TL)
{
cv::cvarrToMat(_img).copyTo(image);
}
else
{
Mat temp = cv::cvarrToMat(_img);
flip(temp, image, 0);
}
return true;
}
bool isOpened() const CV_OVERRIDE
{
return cap != 0; // legacy interface doesn't support closed files
}
int getCaptureDomain() CV_OVERRIDE
{
return cap ? cap->getCaptureDomain() : 0;
}
};
class LegacyWriter : public IVideoWriter
{
private:
CvVideoWriter * writer;
LegacyWriter(const LegacyWriter &);
LegacyWriter& operator=(const LegacyWriter &);
public:
LegacyWriter(CvVideoWriter * wri_) : writer(wri_)
{}
~LegacyWriter()
{
cvReleaseVideoWriter(&writer);
}
double getProperty(int) const CV_OVERRIDE
{
return 0.;
}
bool setProperty(int, double) CV_OVERRIDE
{
return false;
}
bool isOpened() const CV_OVERRIDE
{
return writer != NULL;
}
void write(InputArray image) CV_OVERRIDE
{
IplImage _img = cvIplImage(image.getMat());
cvWriteFrame(writer, &_img);
}
int getCaptureDomain() const CV_OVERRIDE
{
return writer ? writer->getCaptureDomain() : 0;
}
};
//==================================================================================================
Ptr<IVideoCapture> cvCreateFileCapture_FFMPEG_proxy(const std::string &filename);
Ptr<IVideoWriter> cvCreateVideoWriter_FFMPEG_proxy(const std::string& filename, int fourcc, double fps, const Size &frameSize, bool isColor);
Ptr<IVideoCapture> createGStreamerCapture_file(const std::string& filename);
Ptr<IVideoCapture> createGStreamerCapture_cam(int index);
Ptr<IVideoWriter> create_GStreamer_writer(const std::string& filename, int fourcc, double fps, const Size &frameSize, bool isColor);
Ptr<IVideoCapture> create_MFX_capture(const std::string &filename);
Ptr<IVideoWriter> create_MFX_writer(const std::string &filename, int _fourcc, double fps, const Size &frameSize, bool isColor);
Ptr<IVideoCapture> create_AVFoundation_capture_file(const std::string &filename);
Ptr<IVideoCapture> create_AVFoundation_capture_cam(int index);
Ptr<IVideoWriter> create_AVFoundation_writer(const std::string& filename, int fourcc, double fps, const Size &frameSize, bool isColor);
Ptr<IVideoCapture> create_WRT_capture(int device);
Ptr<IVideoCapture> cvCreateCapture_MSMF(int index);
Ptr<IVideoCapture> cvCreateCapture_MSMF(const std::string& filename);
Ptr<IVideoWriter> cvCreateVideoWriter_MSMF(const std::string& filename, int fourcc, double fps, const Size &frameSize, bool is_color);
Ptr<IVideoCapture> create_DShow_capture(int index);
Ptr<IVideoCapture> create_V4L_capture_cam(int index);
Ptr<IVideoCapture> create_V4L_capture_file(const std::string &filename);
Ptr<IVideoCapture> create_OpenNI2_capture_cam( int index );
Ptr<IVideoCapture> create_OpenNI2_capture_file( const std::string &filename );
Ptr<IVideoCapture> create_Images_capture(const std::string &filename);
Ptr<IVideoWriter> create_Images_writer(const std::string &filename, int fourcc, double fps, const Size &frameSize, bool iscolor);
Ptr<IVideoCapture> create_DC1394_capture(int index);
Ptr<IVideoCapture> create_RealSense_capture(int index);
Ptr<IVideoCapture> create_PvAPI_capture( int index );
Ptr<IVideoCapture> create_XIMEA_capture_cam( int index );
Ptr<IVideoCapture> create_XIMEA_capture_file( const std::string &serialNumber );
Ptr<IVideoCapture> create_Aravis_capture( int index );
Ptr<IVideoCapture> createMotionJpegCapture(const std::string& filename);
Ptr<IVideoWriter> createMotionJpegWriter(const std::string &filename, int fourcc, double fps, const Size &frameSize, bool iscolor);
Ptr<IVideoCapture> createGPhoto2Capture(int index);
Ptr<IVideoCapture> createGPhoto2Capture(const std::string& deviceName);
Ptr<IVideoCapture> createXINECapture(const std::string &filename);
} // cv::
#endif // CAP_INTERFACE_HPP

View File

@ -238,6 +238,12 @@ bool VideoCapture_LibRealsense::isOpened() const
return bool(std::shared_ptr<rs2_pipeline>(mPipe));
}
Ptr<IVideoCapture> create_RealSense_capture(int index)
{
return makePtr<VideoCapture_LibRealsense>(index);
}
}
#endif

View File

@ -25,6 +25,7 @@ public:
virtual bool retrieveFrame(int outputType, OutputArray frame) CV_OVERRIDE;
virtual int getCaptureDomain() CV_OVERRIDE;
virtual bool isOpened() const CV_OVERRIDE;
protected:
rs2::pipeline mPipe;
rs2::frameset mData;

View File

@ -298,7 +298,7 @@ public:
private:
VAHandle(const VAHandle &);
VAHandle &operator=(const VAHandle &);
virtual bool initDeviceSession(MFXVideoSession &session);
bool initDeviceSession(MFXVideoSession &session) CV_OVERRIDE;
private:
VADisplay display;
int file;
@ -319,7 +319,7 @@ public:
private:
DXHandle(const DXHandle &);
DXHandle &operator=(const DXHandle &);
virtual bool initDeviceSession(MFXVideoSession &) { return true; }
bool initDeviceSession(MFXVideoSession &) CV_OVERRIDE { return true; }
};
#endif // _WIN32

View File

@ -6,6 +6,7 @@
#include "opencv2/core/base.hpp"
#include "cap_mfx_common.hpp"
#include "opencv2/imgproc/hal/hal.hpp"
#include "cap_interface.hpp"
using namespace cv;
using namespace std;
@ -264,3 +265,8 @@ int VideoCapture_IntelMFX::getCaptureDomain()
}
//==================================================================================================
cv::Ptr<IVideoCapture> cv::create_MFX_capture(const std::string &filename)
{
return cv::makePtr<VideoCapture_IntelMFX>(filename);
}

View File

@ -19,13 +19,13 @@ class VideoCapture_IntelMFX : public cv::IVideoCapture
{
public:
VideoCapture_IntelMFX(const cv::String &filename);
virtual ~VideoCapture_IntelMFX();
virtual double getProperty(int) const CV_OVERRIDE;
virtual bool setProperty(int, double) CV_OVERRIDE;
virtual bool grabFrame() CV_OVERRIDE;
virtual bool retrieveFrame(int, cv::OutputArray out) CV_OVERRIDE;
virtual bool isOpened() const CV_OVERRIDE;
virtual int getCaptureDomain() CV_OVERRIDE;
~VideoCapture_IntelMFX();
double getProperty(int) const CV_OVERRIDE;
bool setProperty(int, double) CV_OVERRIDE;
bool grabFrame() CV_OVERRIDE;
bool retrieveFrame(int, cv::OutputArray out) CV_OVERRIDE;
bool isOpened() const CV_OVERRIDE;
int getCaptureDomain() CV_OVERRIDE;
private:
MFXVideoSession *session;
Plugin *plugin;

View File

@ -6,6 +6,7 @@
#include "opencv2/core/base.hpp"
#include "cap_mfx_common.hpp"
#include "opencv2/imgproc/hal/hal.hpp"
#include "cap_interface.hpp"
using namespace std;
using namespace cv;
@ -244,7 +245,7 @@ bool VideoWriter_IntelMFX::write_one(cv::InputArray bgr)
}
}
Ptr<VideoWriter_IntelMFX> VideoWriter_IntelMFX::create(const String &filename, int _fourcc, double fps, Size frameSize, bool isColor)
Ptr<IVideoWriter> cv::create_MFX_writer(const std::string &filename, int _fourcc, double fps, const Size &frameSize, bool isColor)
{
if (codecIdByFourCC(_fourcc) > 0)
{

View File

@ -19,14 +19,12 @@ class VideoWriter_IntelMFX : public cv::IVideoWriter
{
public:
VideoWriter_IntelMFX(const cv::String &filename, int _fourcc, double fps, cv::Size frameSize, bool isColor);
virtual ~VideoWriter_IntelMFX();
virtual double getProperty(int) const;
virtual bool setProperty(int, double);
virtual bool isOpened() const;
virtual void write(cv::InputArray input);
static cv::Ptr<VideoWriter_IntelMFX> create(const cv::String& filename, int _fourcc, double fps, cv::Size frameSize, bool isColor);
virtual int getCaptureDomain() const { return cv::CAP_INTEL_MFX; }
~VideoWriter_IntelMFX() CV_OVERRIDE;
double getProperty(int) const CV_OVERRIDE;
bool setProperty(int, double) CV_OVERRIDE;
bool isOpened() const CV_OVERRIDE;
void write(cv::InputArray input) CV_OVERRIDE;
int getCaptureDomain() const CV_OVERRIDE { return cv::CAP_INTEL_MFX; }
protected:
bool write_one(cv::InputArray bgr);

View File

@ -1532,7 +1532,7 @@ void MotionJpegWriter::writeFrameData( const uchar* data, int step, int colorspa
}
Ptr<IVideoWriter> createMotionJpegWriter(const String& filename, int fourcc, double fps, Size frameSize, bool iscolor)
Ptr<IVideoWriter> createMotionJpegWriter(const std::string &filename, int fourcc, double fps, const Size &frameSize, bool iscolor)
{
if (fourcc != CV_FOURCC('M', 'J', 'P', 'G'))
return Ptr<IVideoWriter>();

View File

@ -2159,13 +2159,13 @@ void CvVideoWriter_MSMF::write(cv::InputArray img)
}
}
cv::Ptr<cv::IVideoWriter> cv::cvCreateVideoWriter_MSMF( const cv::String& filename, int fourcc,
double fps, cv::Size frameSize, int isColor )
cv::Ptr<cv::IVideoWriter> cv::cvCreateVideoWriter_MSMF( const std::string& filename, int fourcc,
double fps, const cv::Size &frameSize, bool isColor )
{
cv::Ptr<CvVideoWriter_MSMF> writer = cv::makePtr<CvVideoWriter_MSMF>();
if (writer)
{
writer->open(filename, fourcc, fps, frameSize, isColor != 0);
writer->open(filename, fourcc, fps, frameSize, isColor);
if (writer->isOpened())
return writer;
}

View File

@ -39,6 +39,7 @@
//
//M*/
#include "precomp.hpp"
#include "cap_interface.hpp"
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
@ -1100,23 +1101,23 @@ IplImage* CvCapture_OpenNI2::retrieveFrame( int outputType )
return image;
}
CvCapture* cvCreateCameraCapture_OpenNI2( int index )
cv::Ptr<cv::IVideoCapture> cv::create_OpenNI2_capture_cam( int index )
{
CvCapture_OpenNI2* capture = new CvCapture_OpenNI2( index );
if( capture->isOpened() )
return capture;
return cv::makePtr<cv::LegacyCapture>(capture);
delete capture;
return 0;
}
CvCapture* cvCreateFileCapture_OpenNI2( const char* filename )
cv::Ptr<cv::IVideoCapture> cv::create_OpenNI2_capture_file( const std::string &filename )
{
CvCapture_OpenNI2* capture = new CvCapture_OpenNI2( filename );
CvCapture_OpenNI2* capture = new CvCapture_OpenNI2( filename.c_str() );
if( capture->isOpened() )
return capture;
return cv::makePtr<cv::LegacyCapture>(capture);
delete capture;
return 0;

View File

@ -44,6 +44,7 @@
//
#include "precomp.hpp"
#include "cap_interface.hpp"
#ifdef HAVE_PVAPI
#if !defined _WIN32 && !defined _LINUX
@ -599,12 +600,12 @@ bool CvCaptureCAM_PvAPI::resizeCaptureFrame (int frameWidth, int frameHeight)
return true;
}
CvCapture* cvCreateCameraCapture_PvAPI( int index )
cv::Ptr<cv::IVideoCapture> cv::create_PvAPI_capture( int index )
{
CvCaptureCAM_PvAPI* capture = new CvCaptureCAM_PvAPI;
if ( capture->open( index ))
return capture;
return cv::makePtr<cv::LegacyCapture>(capture);
delete capture;
return NULL;

View File

@ -1930,28 +1930,28 @@ IplImage *CvCaptureCAM_V4L::retrieveFrame(int)
return &frame;
}
} // end namespace cv
CvCapture* cvCreateCameraCapture_V4L( int index )
Ptr<IVideoCapture> create_V4L_capture_cam(int index)
{
cv::CvCaptureCAM_V4L* capture = new cv::CvCaptureCAM_V4L();
if(capture->open(index))
return capture;
if (capture->open(index))
return makePtr<LegacyCapture>(capture);
delete capture;
return NULL;
}
CvCapture* cvCreateCameraCapture_V4L( const char * deviceName )
Ptr<IVideoCapture> create_V4L_capture_file(const std::string &filename)
{
cv::CvCaptureCAM_V4L* capture = new cv::CvCaptureCAM_V4L();
if(capture->open( deviceName ))
return capture;
if (capture->open(filename.c_str()))
return makePtr<LegacyCapture>(capture);
delete capture;
return NULL;
}
} // cv::
#endif

View File

@ -195,6 +195,12 @@ namespace cv {
}
return true;
}
Ptr<IVideoCapture> create_WRT_capture(int device)
{
return makePtr<VideoCapture_WinRT>(device);
}
// end
}
// end

View File

@ -67,4 +67,4 @@ namespace cv {
unsigned long frameCurrent;
std::atomic<bool> isFrameNew;
};
}
}

View File

@ -42,23 +42,23 @@ private:
/**********************************************************************************/
CvCapture* cvCreateCameraCapture_XIMEA( int index )
cv::Ptr<cv::IVideoCapture> cv::create_XIMEA_capture_cam( int index )
{
CvCaptureCAM_XIMEA* capture = new CvCaptureCAM_XIMEA;
if( capture->open( index ))
return capture;
return cv::makePtr<cv::LegacyCapture>(capture);
delete capture;
return 0;
}
CvCapture* cvCreateCameraCapture_XIMEA( const char* serialNumber )
cv::Ptr<cv::IVideoCapture> cv::create_XIMEA_capture_file( const std::string &serialNumber )
{
CvCaptureCAM_XIMEA* capture = new CvCaptureCAM_XIMEA;
if( capture->open( serialNumber ))
return capture;
if( capture->open( serialNumber.c_str() ))
return cv::makePtr<cv::LegacyCapture>(capture);
delete capture;
return 0;
@ -1791,4 +1791,4 @@ void CvCaptureCAM_XIMEA::errMsg(const char* msg, int errNum) const
#endif
}
/**********************************************************************************/
/**********************************************************************************/

View File

@ -346,10 +346,10 @@ protected:
}
};
Ptr<IVideoCapture> cv::createXINECapture(const char *filename)
Ptr<IVideoCapture> cv::createXINECapture(const std::string &filename)
{
Ptr<XINECapture> res = makePtr<XINECapture>();
if (res && res->open(filename))
if (res && res->open(filename.c_str()))
return res;
return Ptr<IVideoCapture>();
}

View File

@ -0,0 +1,172 @@
// 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 PLUGIN_API_HPP
#define PLUGIN_API_HPP
#include <opencv2/core/cvdef.h>
#include <opencv2/core/llapi/llapi.h>
// increase for backward-compatible changes, e.g. add new function
// Main API <= Plugin API -> plugin is compatible
#define API_VERSION 0 // preview
// increase for incompatible changes, e.g. remove function argument
// Main ABI == Plugin ABI -> plugin is compatible
#define ABI_VERSION 0 // preview
#ifdef __cplusplus
extern "C" {
#endif
typedef CvResult (CV_API_CALL *cv_videoio_retrieve_cb_t)(int stream_idx, unsigned const char* data, int step, int width, int height, int cn, void* userdata);
typedef struct CvPluginCapture_t* CvPluginCapture;
typedef struct CvPluginWriter_t* CvPluginWriter;
typedef struct OpenCV_VideoIO_Plugin_API_preview
{
OpenCV_API_Header api_header;
/** OpenCV capture ID (VideoCaptureAPIs)
@note API-ENTRY 1, API-Version == 0
*/
int captureAPI;
/** @brief Open video capture
@param filename File name or NULL to use camera_index instead
@param camera_index Camera index (used if filename == NULL)
@param[out] handle pointer on Capture handle
@note API-CALL 2, API-Version == 0
*/
CvResult (CV_API_CALL *Capture_open)(const char* filename, int camera_index, CV_OUT CvPluginCapture* handle);
/** @brief Release Capture handle
@param handle Capture handle
@note API-CALL 3, API-Version == 0
*/
CvResult (CV_API_CALL *Capture_release)(CvPluginCapture handle);
/** @brief Get property value
@param handle Capture handle
@param prop Property index
@param[out] val property value
@note API-CALL 4, API-Version == 0
*/
CvResult (CV_API_CALL *Capture_getProperty)(CvPluginCapture handle, int prop, CV_OUT double* val);
/** @brief Set property value
@param handle Capture handle
@param prop Property index
@param val property value
@note API-CALL 5, API-Version == 0
*/
CvResult (CV_API_CALL *Capture_setProperty)(CvPluginCapture handle, int prop, double val);
/** @brief Grab frame
@param handle Capture handle
@note API-CALL 6, API-Version == 0
*/
CvResult (CV_API_CALL *Capture_grab)(CvPluginCapture handle);
/** @brief Retrieve frame
@param handle Capture handle
@param stream_idx stream index to retrieve (BGR/IR/depth data)
@param callback retrieve callback (synchronous)
@param userdata callback context data
@note API-CALL 7, API-Version == 0
*/
CvResult (CV_API_CALL *Capture_retreive)(CvPluginCapture handle, int stream_idx, cv_videoio_retrieve_cb_t callback, void* userdata);
/** @brief Try to open video writer
@param filename File name or NULL to use camera_index instead
@param camera_index Camera index (used if filename == NULL)
@param[out] handle pointer on Writer handle
@note API-CALL 8, API-Version == 0
*/
CvResult (CV_API_CALL *Writer_open)(const char* filename, int fourcc, double fps, int width, int height, int isColor,
CV_OUT CvPluginWriter* handle);
/** @brief Release Writer handle
@param handle Writer handle
@note API-CALL 9, API-Version == 0
*/
CvResult (CV_API_CALL *Writer_release)(CvPluginWriter handle);
/** @brief Get property value
@param handle Capture handle
@param prop Property index
@param[out] val property value
@note API-CALL 10, API-Version == 0
*/
CvResult (CV_API_CALL *Writer_getProperty)(CvPluginWriter handle, int prop, CV_OUT double* val);
/** @brief Set property value
@param handle Capture handle
@param prop Property index
@param val property value
@note API-CALL 11, API-Version == 0
*/
CvResult (CV_API_CALL *Writer_setProperty)(CvPluginWriter handle, int prop, double val);
/** @brief Write frame
@param handle Capture handle
@param data Capture handle
@param step step in bytes
@param width frame width in pixels
@param height frame height
@param cn number of channels per pixel
@note API-CALL 12, API-Version == 0
*/
CvResult (CV_API_CALL *Writer_write)(CvPluginWriter handle, const unsigned char *data, int step, int width, int height, int cn);
} OpenCV_VideoIO_Plugin_API_preview;
#ifdef BUILD_PLUGIN
#ifndef CV_PLUGIN_EXPORTS
#if (defined _WIN32 || defined WINCE || defined __CYGWIN__)
# define CV_PLUGIN_EXPORTS __declspec(dllexport)
#elif defined __GNUC__ && __GNUC__ >= 4
# define CV_PLUGIN_EXPORTS __attribute__ ((visibility ("default")))
#endif
#endif
CV_PLUGIN_EXPORTS
const OpenCV_VideoIO_Plugin_API_preview* CV_API_CALL opencv_videoio_plugin_init_v0
(int requested_abi_version, int requested_api_version, void* reserved /*NULL*/) CV_NOEXCEPT;
#else // BUILD_PLUGIN
typedef const OpenCV_VideoIO_Plugin_API_preview* (CV_API_CALL *FN_opencv_videoio_plugin_init_t)
(int requested_abi_version, int requested_api_version, void* reserved /*NULL*/);
#endif // BUILD_PLUGIN
#ifdef __cplusplus
}
#endif
#endif // PLUGIN_API_HPP

View File

@ -80,121 +80,6 @@
#undef abs
#endif
#define __BEGIN__ __CV_BEGIN__
#define __END__ __CV_END__
#define EXIT __CV_EXIT__
/***************************** CvCapture structure ******************************/
struct CvCapture
{
virtual ~CvCapture() {}
virtual double getProperty(int) const { return 0; }
virtual bool setProperty(int, double) { return 0; }
virtual bool grabFrame() { return true; }
virtual IplImage* retrieveFrame(int) { return 0; }
virtual int getCaptureDomain() { return cv::CAP_ANY; } // Return the type of the capture object: CAP_DSHOW, etc...
};
/*************************** CvVideoWriter structure ****************************/
struct CvVideoWriter
{
virtual ~CvVideoWriter() {}
virtual bool writeFrame(const IplImage*) { return false; }
virtual int getCaptureDomain() const { return cv::CAP_ANY; } // Return the type of the capture object: CAP_FFMPEG, etc...
};
CvCapture * cvCreateCameraCapture_V4L( int index );
CvCapture * cvCreateCameraCapture_V4L( const char* deviceName );
CvCapture * cvCreateCameraCapture_DC1394_2( int index );
CvCapture* cvCreateCameraCapture_MIL( int index );
CvCapture* cvCreateCameraCapture_Giganetix( int index );
CvCapture* cvCreateFileCapture_Win32( const char* filename );
CvVideoWriter* cvCreateVideoWriter_Win32( const char* filename, int fourcc,
double fps, CvSize frameSize, int is_color );
CvCapture* cvCreateCameraCapture_DShow( int index );
CvCapture* cvCreateCameraCapture_OpenNI( int index );
CvCapture* cvCreateCameraCapture_OpenNI2( int index );
CvCapture* cvCreateFileCapture_OpenNI( const char* filename );
CvCapture* cvCreateFileCapture_OpenNI2( const char* filename );
CvCapture* cvCreateCameraCapture_Android( int index );
CvCapture* cvCreateCameraCapture_XIMEA( int index );
CvCapture* cvCreateCameraCapture_XIMEA( const char* serialNumber );
CvCapture* cvCreateCameraCapture_AVFoundation(int index);
CvCapture* cvCreateCameraCapture_Aravis( int index );
CvVideoWriter* cvCreateVideoWriter_Images(const char* filename);
#define CV_CAP_GSTREAMER_1394 0
#define CV_CAP_GSTREAMER_V4L 1
#define CV_CAP_GSTREAMER_V4L2 2
#define CV_CAP_GSTREAMER_FILE 3
CvCapture * cvCreateFileCapture_QT (const char * filename);
CvCapture * cvCreateCameraCapture_QT (const int index);
CvVideoWriter* cvCreateVideoWriter_QT ( const char* filename, int fourcc,
double fps, CvSize frameSize, int is_color );
CvCapture* cvCreateFileCapture_AVFoundation (const char * filename);
CvVideoWriter* cvCreateVideoWriter_AVFoundation( const char* filename, int fourcc,
double fps, CvSize frameSize, int is_color );
CvCapture * cvCreateCameraCapture_PvAPI (const int index);
CvVideoWriter* cvCreateVideoWriter_GStreamer( const char* filename, int fourcc,
double fps, CvSize frameSize, int is_color );
namespace cv
{
class IVideoCapture
{
public:
virtual ~IVideoCapture() {}
virtual double getProperty(int) const { return 0; }
virtual bool setProperty(int, double) { return false; }
virtual bool grabFrame() = 0;
virtual bool retrieveFrame(int, OutputArray) = 0;
virtual bool isOpened() const = 0;
virtual int getCaptureDomain() { return CAP_ANY; } // Return the type of the capture object: CAP_DSHOW, etc...
};
class IVideoWriter
{
public:
virtual ~IVideoWriter() {}
virtual double getProperty(int) const { return 0; }
virtual bool setProperty(int, double) { return false; }
virtual bool isOpened() const = 0;
virtual void write(InputArray) = 0;
virtual int getCaptureDomain() const { return cv::CAP_ANY; } // Return the type of the capture object: CAP_FFMPEG, etc...
};
Ptr<IVideoCapture> createFileCapture_Images(const String& filename);
Ptr<IVideoCapture> createMotionJpegCapture(const String& filename);
Ptr<IVideoWriter> createMotionJpegWriter(const String& filename, int fourcc, double fps, Size frameSize, bool iscolor);
Ptr<IVideoCapture> createGPhoto2Capture(int index);
Ptr<IVideoCapture> createGPhoto2Capture(const String& deviceName);
Ptr<IVideoCapture> createXINECapture(const char* filename);
Ptr<IVideoCapture> createGStreamerCapture(const String& filename);
Ptr<IVideoCapture> createGStreamerCapture(int index);
Ptr<cv::IVideoCapture> cvCreateFileCapture_FFMPEG_proxy(const String& filename);
Ptr<IVideoWriter> cvCreateVideoWriter_FFMPEG_proxy(const String& filename, int fourcc, double fps, Size frameSize, int isColor);
Ptr<IVideoCapture> cvCreateCapture_MSMF(int index);
Ptr<IVideoCapture> cvCreateCapture_MSMF(const String& filename);
Ptr<IVideoWriter> cvCreateVideoWriter_MSMF(const String& filename, int fourcc, double fps, Size frameSize, int is_color);
}
#include "cap_interface.hpp"
#endif /* __VIDEOIO_H_ */

View File

@ -3,65 +3,22 @@
// of this distribution and at http://opencv.org/license.html.
#include "precomp.hpp"
#include "opencv2/videoio/registry.hpp"
#include "videoio_registry.hpp"
using namespace cv;
// Legacy C-like API
CV_IMPL CvCapture* cvCreateCameraCapture(int index)
CV_IMPL CvCapture* cvCreateCameraCapture(int)
{
// interpret preferred interface (0 = autodetect)
int apiPreference = (index / 100) * 100;
if (apiPreference)
{
index %= 100;
}
const std::vector<VideoBackendInfo> backends = cv::videoio_registry::getAvailableBackends_CaptureByIndex();
for (size_t i = 0; i < backends.size(); i++)
{
const VideoBackendInfo& info = backends[i];
if (apiPreference == CAP_ANY || apiPreference == info.id)
{
CvCapture* capture = NULL;
Ptr<IVideoCapture> icap; // unused
VideoCapture_create(capture, icap, info.id, index);
if (capture)
{
return capture;
}
if (!icap.empty())
{
CV_LOG_WARNING(NULL, "cvCreateFileCaptureWithPreference: backend " << info.name << " doesn't support legacy API anymore.")
}
}
}
CV_LOG_WARNING(NULL, "cvCreateCameraCapture doesn't support legacy API anymore.")
return NULL;
}
CV_IMPL CvCapture* cvCreateFileCaptureWithPreference(const char* filename, int apiPreference)
CV_IMPL CvCapture* cvCreateFileCaptureWithPreference(const char*, int)
{
const std::vector<VideoBackendInfo> backends = cv::videoio_registry::getAvailableBackends_CaptureByFilename();
for (size_t i = 0; i < backends.size(); i++)
{
const VideoBackendInfo& info = backends[i];
if (apiPreference == CAP_ANY || apiPreference == info.id)
{
CvCapture* capture = NULL;
Ptr<IVideoCapture> icap; // unused
VideoCapture_create(capture, icap, info.id, filename);
if (capture)
{
return capture;
}
if (!icap.empty())
{
CV_LOG_WARNING(NULL, "cvCreateFileCaptureWithPreference: backend " << info.name << " doesn't support legacy API anymore.")
}
}
}
CV_LOG_WARNING(NULL, "cvCreateFileCaptureWithPreference doesn't support legacy API anymore.")
return NULL;
}
@ -70,27 +27,9 @@ CV_IMPL CvCapture* cvCreateFileCapture(const char * filename)
return cvCreateFileCaptureWithPreference(filename, CAP_ANY);
}
CV_IMPL CvVideoWriter* cvCreateVideoWriter(const char* filename, int fourcc,
double fps, CvSize frameSize, int is_color)
CV_IMPL CvVideoWriter* cvCreateVideoWriter(const char*, int, double, CvSize, int)
{
const std::vector<VideoBackendInfo> backends = cv::videoio_registry::getAvailableBackends_Writer();
for (size_t i = 0; i < backends.size(); i++)
{
const VideoBackendInfo& info = backends[i];
{
CvVideoWriter* writer_ = NULL;
Ptr<IVideoWriter> iwriter; // unused
VideoWriter_create(writer_, iwriter, info.id, filename, fourcc, fps, frameSize, is_color != 0);
if (writer_)
{
return writer_;
}
if (!iwriter.empty())
{
CV_LOG_WARNING(NULL, "cvCreateVideoWriter: backend " << info.name << " doesn't support legacy API anymore.")
}
}
}
CV_LOG_WARNING(NULL, "cvCreateVideoWriter doesn't support legacy API anymore.")
return NULL;
}

View File

@ -16,6 +16,8 @@
#include "cap_mfx_writer.hpp"
#endif
#include "plugin_api.hpp"
// All WinRT versions older than 8.0 should provide classes used for video support
#if defined(WINRT) && !defined(WINRT_8_0) && defined(__cplusplus_winrt)
# include "cap_winrt_capture.hpp"
@ -30,16 +32,19 @@
using namespace cv;
namespace cv
{
static bool param_VIDEOIO_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOIO_DEBUG", false);
static bool param_VIDEOCAPTURE_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOCAPTURE_DEBUG", false);
static bool param_VIDEOWRITER_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOWRITER_DEBUG", false);
namespace cv {
namespace {
#define DECLARE_BACKEND(cap, name, mode) { cap, (BackendMode)(mode), 1000, name }
#define DECLARE_DYNAMIC_BACKEND(cap, name, mode) \
{ \
cap, (BackendMode)(mode), 1000, name, createPluginBackendFactory(cap, name) \
}
#define DECLARE_STATIC_BACKEND(cap, name, mode, createCaptureFile, createCaptureCamera, createWriter) \
{ \
cap, (BackendMode)(mode), 1000, name, createBackendFactory(createCaptureFile, createCaptureCamera, createWriter) \
}
/** Ordering guidelines:
- modern optimized, multi-platform libraries: ffmpeg, gstreamer, Media SDK
@ -52,73 +57,78 @@ namespace {
static const struct VideoBackendInfo builtin_backends[] =
{
#ifdef HAVE_FFMPEG
DECLARE_BACKEND(CAP_FFMPEG, "FFMPEG", MODE_CAPTURE_BY_FILENAME | MODE_WRITER),
#endif
#ifdef HAVE_GSTREAMER
DECLARE_BACKEND(CAP_GSTREAMER, "GSTREAMER", MODE_CAPTURE_ALL | MODE_WRITER),
#endif
#ifdef HAVE_MFX // Media SDK
DECLARE_BACKEND(CAP_INTEL_MFX, "INTEL_MFX", MODE_CAPTURE_BY_FILENAME | MODE_WRITER),
DECLARE_STATIC_BACKEND(CAP_FFMPEG, "FFMPEG", MODE_CAPTURE_BY_FILENAME | MODE_WRITER, cvCreateFileCapture_FFMPEG_proxy, 0, cvCreateVideoWriter_FFMPEG_proxy),
#elif defined(ENABLE_PLUGINS)
DECLARE_DYNAMIC_BACKEND(CAP_FFMPEG, "FFMPEG", MODE_CAPTURE_BY_FILENAME | MODE_WRITER),
#endif
#ifdef HAVE_GSTREAMER
DECLARE_STATIC_BACKEND(CAP_GSTREAMER, "GSTREAMER", MODE_CAPTURE_ALL | MODE_WRITER, createGStreamerCapture_file, createGStreamerCapture_cam, create_GStreamer_writer),
#elif defined(ENABLE_PLUGINS)
DECLARE_DYNAMIC_BACKEND(CAP_GSTREAMER, "GSTREAMER", MODE_CAPTURE_ALL | MODE_WRITER),
#endif
#ifdef HAVE_MFX // Media SDK
DECLARE_STATIC_BACKEND(CAP_INTEL_MFX, "INTEL_MFX", MODE_CAPTURE_BY_FILENAME | MODE_WRITER, create_MFX_capture, 0, create_MFX_writer),
#endif
// Apple platform
#ifdef HAVE_AVFOUNDATION
DECLARE_BACKEND(CAP_AVFOUNDATION, "AVFOUNDATION", MODE_CAPTURE_ALL | MODE_WRITER),
DECLARE_STATIC_BACKEND(CAP_AVFOUNDATION, "AVFOUNDATION", MODE_CAPTURE_ALL | MODE_WRITER, create_AVFoundation_capture_file, create_AVFoundation_capture_cam, create_AVFoundation_writer),
#endif
// Windows
#ifdef WINRT_VIDEO
DECLARE_BACKEND(CAP_WINRT, "WINRT", MODE_CAPTURE_BY_INDEX),
DECLARE_STATIC_BACKEND(CAP_WINRT, "WINRT", MODE_CAPTURE_BY_INDEX, 0, create_WRT_capture, 0),
#endif
#ifdef HAVE_MSMF
DECLARE_BACKEND(CAP_MSMF, "MSMF", MODE_CAPTURE_ALL | MODE_WRITER),
DECLARE_STATIC_BACKEND(CAP_MSMF, "MSMF", MODE_CAPTURE_ALL | MODE_WRITER, cvCreateCapture_MSMF, cvCreateCapture_MSMF, cvCreateVideoWriter_MSMF),
#endif
#ifdef HAVE_DSHOW
DECLARE_BACKEND(CAP_DSHOW, "DSHOW", MODE_CAPTURE_BY_INDEX),
DECLARE_STATIC_BACKEND(CAP_DSHOW, "DSHOW", MODE_CAPTURE_BY_INDEX, 0, create_DShow_capture, 0),
#endif
// Linux, some Unix
#if defined HAVE_CAMV4L2
DECLARE_BACKEND(CAP_V4L2, "V4L2", MODE_CAPTURE_ALL),
DECLARE_STATIC_BACKEND(CAP_V4L2, "V4L2", MODE_CAPTURE_ALL, create_V4L_capture_file, create_V4L_capture_cam, 0),
#elif defined HAVE_VIDEOIO
DECLARE_BACKEND(CAP_V4L, "V4L_BSD", MODE_CAPTURE_ALL),
DECLARE_STATIC_BACKEND(CAP_V4L, "V4L_BSD", MODE_CAPTURE_ALL, create_V4L_capture_file, create_V4L_capture_cam, 0),
#endif
// RGB-D universal
#ifdef HAVE_OPENNI2
DECLARE_BACKEND(CAP_OPENNI2, "OPENNI2", MODE_CAPTURE_ALL),
DECLARE_STATIC_BACKEND(CAP_OPENNI2, "OPENNI2", MODE_CAPTURE_ALL, create_OpenNI2_capture_file, create_OpenNI2_capture_cam, 0),
#endif
#ifdef HAVE_LIBREALSENSE
DECLARE_BACKEND(CAP_REALSENSE, "INTEL_REALSENSE", MODE_CAPTURE_BY_INDEX),
DECLARE_STATIC_BACKEND(CAP_REALSENSE, "INTEL_REALSENSE", MODE_CAPTURE_BY_INDEX, 0, create_RealSense_capture, 0),
#endif
// OpenCV file-based only
DECLARE_BACKEND(CAP_IMAGES, "CV_IMAGES", MODE_CAPTURE_BY_FILENAME | MODE_WRITER),
DECLARE_BACKEND(CAP_OPENCV_MJPEG, "CV_MJPEG", MODE_CAPTURE_BY_FILENAME | MODE_WRITER),
DECLARE_STATIC_BACKEND(CAP_IMAGES, "CV_IMAGES", MODE_CAPTURE_BY_FILENAME | MODE_WRITER, create_Images_capture, 0, create_Images_writer),
DECLARE_STATIC_BACKEND(CAP_OPENCV_MJPEG, "CV_MJPEG", MODE_CAPTURE_BY_FILENAME | MODE_WRITER, createMotionJpegCapture, 0, createMotionJpegWriter),
// special interfaces / stereo cameras / other SDKs
#if defined(HAVE_DC1394_2)
DECLARE_BACKEND(CAP_FIREWIRE, "FIREWIRE", MODE_CAPTURE_BY_INDEX),
DECLARE_STATIC_BACKEND(CAP_FIREWIRE, "FIREWIRE", MODE_CAPTURE_BY_INDEX, 0, create_DC1394_capture, 0),
#endif
// GigE
#ifdef HAVE_PVAPI
DECLARE_BACKEND(CAP_PVAPI, "PVAPI", MODE_CAPTURE_BY_INDEX),
DECLARE_STATIC_BACKEND(CAP_PVAPI, "PVAPI", MODE_CAPTURE_BY_INDEX, 0, create_PvAPI_capture, 0),
#endif
#ifdef HAVE_XIMEA
DECLARE_BACKEND(CAP_XIAPI, "XIMEA", MODE_CAPTURE_ALL),
DECLARE_STATIC_BACKEND(CAP_XIAPI, "XIMEA", MODE_CAPTURE_ALL, create_XIMEA_capture_file, create_XIMEA_capture_cam, 0),
#endif
#ifdef HAVE_ARAVIS_API
DECLARE_BACKEND(CAP_ARAVIS, "ARAVIS", MODE_CAPTURE_BY_INDEX),
DECLARE_STATIC_BACKEND(CAP_ARAVIS, "ARAVIS", MODE_CAPTURE_BY_INDEX, 0, create_Aravis_capture, 0),
#endif
#ifdef HAVE_GPHOTO2
DECLARE_BACKEND(CAP_GPHOTO2, "GPHOTO2", MODE_CAPTURE_ALL),
DECLARE_STATIC_BACKEND(CAP_GPHOTO2, "GPHOTO2", MODE_CAPTURE_ALL, createGPhoto2Capture, createGPhoto2Capture, 0),
#endif
#ifdef HAVE_XINE
DECLARE_BACKEND(CAP_XINE, "XINE", MODE_CAPTURE_BY_FILENAME),
DECLARE_STATIC_BACKEND(CAP_XINE, "XINE", MODE_CAPTURE_BY_FILENAME, createXINECapture, 0, 0),
#endif
// dropped backends: MIL, TYZX, Android
@ -344,279 +354,21 @@ std::vector<VideoCaptureAPIs> getWriterBackends()
return result;
}
bool hasBackend(VideoCaptureAPIs api)
{
std::vector<VideoBackendInfo> backends = VideoBackendRegistry::getInstance().getEnabledBackends();
for (size_t i = 0; i < backends.size(); i++)
{
const VideoBackendInfo& info = backends[i];
if (api == info.id)
{
CV_Assert(!info.backendFactory.empty());
return !info.backendFactory->getBackend().empty();
}
}
return false;
}
} // namespace registry
#define TRY_OPEN(backend_func) \
{ \
try { \
if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying ...\n", #backend_func)); \
icap = backend_func; \
if (param_VIDEOIO_DEBUG ||param_VIDEOCAPTURE_DEBUG) \
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): result=%p isOpened=%d ...\n", \
#backend_func, icap.empty() ? NULL : icap.get(), icap.empty() ? -1: icap->isOpened())); \
} catch(const cv::Exception& e) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", #backend_func, e.what())); \
} catch (const std::exception& e) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", #backend_func, e.what())); \
} catch(...) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", #backend_func)); \
} \
break; \
}
#define TRY_OPEN_LEGACY(backend_func) \
{ \
try { \
if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying ...\n", #backend_func)); \
capture = backend_func; \
if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): result=%p ...\n", #backend_func, capture)); \
} catch(const cv::Exception& e) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", #backend_func, e.what())); \
} catch (const std::exception& e) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", #backend_func, e.what())); \
} catch(...) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", #backend_func)); \
} \
break; \
}
void VideoCapture_create(CvCapture*& capture, Ptr<IVideoCapture>& icap, VideoCaptureAPIs api, int index)
{
CV_UNUSED(capture); CV_UNUSED(icap);
switch (api)
{
default:
CV_LOG_WARNING(NULL, "VideoCapture(index=" << index << ") was built without support of requested backendID=" << (int)api);
break;
#ifdef HAVE_GSTREAMER
case CAP_GSTREAMER:
TRY_OPEN(createGStreamerCapture(index));
break;
#endif
#ifdef HAVE_MSMF
case CAP_MSMF:
TRY_OPEN(cvCreateCapture_MSMF(index));
break;
#endif
#ifdef HAVE_DSHOW
case CAP_DSHOW:
TRY_OPEN(makePtr<VideoCapture_DShow>(index));
break;
#endif
#ifdef HAVE_LIBREALSENSE
case CAP_REALSENSE:
TRY_OPEN(makePtr<VideoCapture_LibRealsense>(index));
break;
#endif
#ifdef WINRT_VIDEO
case CAP_WINRT:
TRY_OPEN(makePtr<cv::VideoCapture_WinRT>(index));
break;
#endif
#ifdef HAVE_GPHOTO2
case CAP_GPHOTO2:
TRY_OPEN(createGPhoto2Capture(index));
break;
#endif
#if defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO
case CAP_V4L:
TRY_OPEN_LEGACY(cvCreateCameraCapture_V4L(index))
break;
#endif
case CAP_FIREWIRE:
#ifdef HAVE_DC1394_2
TRY_OPEN_LEGACY(cvCreateCameraCapture_DC1394_2(index))
#endif
break; // CAP_FIREWIRE
#ifdef HAVE_MIL
case CAP_MIL:
TRY_OPEN_LEGACY(cvCreateCameraCapture_MIL(index))
break;
#endif
#ifdef HAVE_PVAPI
case CAP_PVAPI:
TRY_OPEN_LEGACY(cvCreateCameraCapture_PvAPI(index))
break;
#endif
#ifdef HAVE_OPENNI2
case CAP_OPENNI2:
TRY_OPEN_LEGACY(cvCreateCameraCapture_OpenNI2(index))
break;
#endif
#ifdef HAVE_XIMEA
case CAP_XIAPI:
TRY_OPEN_LEGACY(cvCreateCameraCapture_XIMEA(index))
break;
#endif
#ifdef HAVE_AVFOUNDATION
case CAP_AVFOUNDATION:
TRY_OPEN_LEGACY(cvCreateCameraCapture_AVFoundation(index))
break;
#endif
#ifdef HAVE_ARAVIS_API
case CAP_ARAVIS:
TRY_OPEN_LEGACY(cvCreateCameraCapture_Aravis(index))
break;
#endif
} // switch (api)
}
void VideoCapture_create(CvCapture*& capture, Ptr<IVideoCapture>& icap, VideoCaptureAPIs api, const cv::String& filename)
{
CV_UNUSED(capture);
switch (api)
{
default:
CV_LOG_WARNING(NULL, "VideoCapture(filename=" << filename << ") was built without support of requested backendID=" << (int)api);
break;
#if defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO
case CAP_V4L:
TRY_OPEN_LEGACY(cvCreateCameraCapture_V4L(filename.c_str()))
break;
#endif
#ifdef HAVE_AVFOUNDATION
case CAP_AVFOUNDATION:
TRY_OPEN_LEGACY(cvCreateFileCapture_AVFoundation(filename.c_str()))
break;
#endif
#ifdef HAVE_OPENNI2
case CAP_OPENNI2:
TRY_OPEN_LEGACY(cvCreateFileCapture_OpenNI2(filename.c_str()))
break;
#endif
#ifdef HAVE_XIMEA
case CAP_XIAPI:
TRY_OPEN_LEGACY(cvCreateCameraCapture_XIMEA(filename.c_str()))
break;
#endif
case CAP_IMAGES:
TRY_OPEN(createFileCapture_Images(filename))
break;
#ifdef HAVE_FFMPEG
case CAP_FFMPEG:
TRY_OPEN(cvCreateFileCapture_FFMPEG_proxy(filename))
break;
#endif
#ifdef HAVE_GSTREAMER
case CAP_GSTREAMER:
TRY_OPEN(createGStreamerCapture(filename))
break;
#endif
#ifdef HAVE_XINE
case CAP_XINE:
TRY_OPEN(createXINECapture(filename.c_str()))
break;
#endif
#ifdef HAVE_MSMF
case CAP_MSMF:
TRY_OPEN(cvCreateCapture_MSMF(filename))
break;
#endif
#ifdef HAVE_GPHOTO2
case CAP_GPHOTO2:
TRY_OPEN(createGPhoto2Capture(filename))
break;
#endif
#ifdef HAVE_MFX
case CAP_INTEL_MFX:
TRY_OPEN(makePtr<VideoCapture_IntelMFX>(filename))
break;
#endif
case CAP_OPENCV_MJPEG:
TRY_OPEN(createMotionJpegCapture(filename))
break;
} // switch
}
void VideoWriter_create(CvVideoWriter*& writer, Ptr<IVideoWriter>& iwriter, VideoCaptureAPIs api,
const String& filename, int fourcc, double fps, const Size& frameSize, bool isColor)
{
#define CREATE_WRITER(backend_func) \
{ \
try { \
if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying ...\n", #backend_func)); \
iwriter = backend_func; \
if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): result=%p isOpened=%d...\n", #backend_func, iwriter.empty() ? NULL : iwriter.get(), iwriter.empty() ? iwriter->isOpened() : -1)); \
} catch(const cv::Exception& e) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", #backend_func, e.what())); \
} catch (const std::exception& e) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", #backend_func, e.what())); \
} catch(...) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", #backend_func)); \
} \
break; \
}
#define CREATE_WRITER_LEGACY(backend_func) \
{ \
try { \
if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying ...\n", #backend_func)); \
writer = backend_func; \
if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): result=%p...\n", #backend_func, writer)); \
} catch(const cv::Exception& e) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", #backend_func, e.what())); \
} catch (const std::exception& e) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", #backend_func, e.what())); \
} catch(...) { \
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", #backend_func)); \
} \
break; \
}
switch (api)
{
default:
CV_LOG_ERROR(NULL, "Unknown VideoWriter backend (check getBuildInformation()): " << (int)api);
break;
#ifdef HAVE_FFMPEG
case CAP_FFMPEG:
CREATE_WRITER(cvCreateVideoWriter_FFMPEG_proxy(filename, fourcc, fps, frameSize, isColor));
break;
#endif
#ifdef HAVE_MSMF
case CAP_MSMF:
CREATE_WRITER(cvCreateVideoWriter_MSMF(filename, fourcc, fps, frameSize, isColor));
break;
#endif
#ifdef HAVE_MFX
case CAP_INTEL_MFX:
CREATE_WRITER(VideoWriter_IntelMFX::create(filename, fourcc, fps, frameSize, isColor));
break;
#endif
#ifdef HAVE_AVFOUNDATION
case CAP_AVFOUNDATION:
CREATE_WRITER_LEGACY(cvCreateVideoWriter_AVFoundation(filename.c_str(), fourcc, fps, cvSize(frameSize), isColor))
break;
#endif
#ifdef HAVE_GSTREAMER
case CAP_GSTREAMER:
CREATE_WRITER_LEGACY(cvCreateVideoWriter_GStreamer (filename.c_str(), fourcc, fps, cvSize(frameSize), isColor))
break;
#endif
case CAP_OPENCV_MJPEG:
CREATE_WRITER(createMotionJpegWriter(filename, fourcc, fps, frameSize, isColor));
break;
case CAP_IMAGES:
if(!fourcc || !fps)
{
CREATE_WRITER_LEGACY(cvCreateVideoWriter_Images(filename.c_str()));
}
break;
} // switch(api)
}
} // namespace

View File

@ -5,6 +5,8 @@
#ifndef __OPENCV_VIDEOIO_VIDEOIO_REGISTRY_HPP__
#define __OPENCV_VIDEOIO_VIDEOIO_REGISTRY_HPP__
#include "backend.hpp"
namespace cv
{
@ -24,6 +26,7 @@ struct VideoBackendInfo {
// 0 - disabled (OPENCV_VIDEOIO_PRIORITY_<name> = 0)
// >10000 - prioritized list (OPENCV_VIDEOIO_PRIORITY_LIST)
const char* name;
Ptr<IBackendFactory> backendFactory;
};
namespace videoio_registry {
@ -34,10 +37,5 @@ std::vector<VideoBackendInfo> getAvailableBackends_Writer();
} // namespace
void VideoCapture_create(CvCapture*& capture, Ptr<IVideoCapture>& icap, VideoCaptureAPIs api, int index);
void VideoCapture_create(CvCapture*& capture, Ptr<IVideoCapture>& icap, VideoCaptureAPIs api, const cv::String& filename);
void VideoWriter_create(CvVideoWriter*& writer, Ptr<IVideoWriter>& iwriter, VideoCaptureAPIs api,
const String& filename, int fourcc, double fps, const Size& frameSize, bool isColor);
} // namespace
#endif // __OPENCV_VIDEOIO_VIDEOIO_REGISTRY_HPP__

View File

@ -5,7 +5,7 @@
// Note: all tests here are DISABLED by default due specific requirements.
// Don't use #if 0 - these tests should be tested for compilation at least.
//
// Usage: opencv_test_videoio --gtest_also_run_disabled_tests --gtest_filter=*VideoIO_Camera*<tested case>*
// Usage: opencv_test_videoio --gtest_also_run_disabled_tests --gtest_filter=*videoio_camera*<tested case>*
#include "test_precomp.hpp"
@ -29,7 +29,7 @@ static void test_readFrames(/*const*/ VideoCapture& capture, const int N = 100,
if (lastFrame) *lastFrame = frame.clone();
}
TEST(DISABLED_VideoIO_Camera, basic)
TEST(DISABLED_videoio_camera, basic)
{
VideoCapture capture(0);
ASSERT_TRUE(capture.isOpened());
@ -41,7 +41,7 @@ TEST(DISABLED_VideoIO_Camera, basic)
capture.release();
}
TEST(DISABLED_VideoIO_Camera, validate_V4L2_MJPEG)
TEST(DISABLED_videoio_camera, v4l_read_mjpg)
{
VideoCapture capture(CAP_V4L2);
ASSERT_TRUE(capture.isOpened());
@ -57,7 +57,7 @@ TEST(DISABLED_VideoIO_Camera, validate_V4L2_MJPEG)
}
//Following test if for capture device using PhysConn_Video_SerialDigital as crossbar input pin
TEST(DISABLED_VideoIO_Camera, dshow_avermedia_capture)
TEST(DISABLED_videoio_camera, channel6)
{
VideoCapture capture(0);
ASSERT_TRUE(capture.isOpened());
@ -70,7 +70,7 @@ TEST(DISABLED_VideoIO_Camera, dshow_avermedia_capture)
capture.release();
}
TEST(DISABLED_VideoIO_Camera, validate_V4L2_FrameSize)
TEST(DISABLED_videoio_camera, v4l_read_framesize)
{
VideoCapture capture(CAP_V4L2);
ASSERT_TRUE(capture.isOpened());

View File

@ -8,10 +8,10 @@
using namespace cv;
namespace opencv_test
{
namespace opencv_test { namespace {
TEST(videoio_avi, good_MJPG) {
TEST(videoio_builtin, basic_avi)
{
String filename = BunnyParameters::getFilename(".mjpg.avi");
AVIReadContainer in;
in.initStream(filename);
@ -23,7 +23,8 @@ TEST(videoio_avi, good_MJPG) {
EXPECT_EQ(in.getFps(), static_cast<unsigned>(BunnyParameters::getFps()));
}
TEST(videoio_avi, bad_MJPG) {
TEST(videoio_builtin, invalid_avi)
{
String filename = BunnyParameters::getFilename(".avi");
AVIReadContainer in;
in.initStream(filename);
@ -32,7 +33,7 @@ TEST(videoio_avi, bad_MJPG) {
EXPECT_EQ(frames.size(), static_cast<unsigned>(0));
}
TEST(videoio_avi, basic)
TEST(videoio_builtin, read_write_avi)
{
const String filename = cv::tempfile("test.avi");
const double fps = 100;
@ -84,4 +85,4 @@ TEST(videoio_avi, basic)
remove(filename.c_str());
}
}
}} // opencv_test::<anonymous>::

View File

@ -0,0 +1,83 @@
// 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.
#include "test_precomp.hpp"
using namespace std;
namespace opencv_test { namespace {
const int FRAME_COUNT = 120;
inline void generateFrame(int i, Mat & frame)
{
::generateFrame(i, FRAME_COUNT, frame);
}
TEST(videoio_dynamic, basic_write)
{
const Size FRAME_SIZE(640, 480);
const double FPS = 100;
const String filename = cv::tempfile(".avi");
const int fourcc = VideoWriter::fourcc('M', 'J', 'P', 'G');
bool fileExists = false;
{
vector<VideoCaptureAPIs> backends = videoio_registry::getWriterBackends();
for (VideoCaptureAPIs be : backends)
{
VideoWriter writer;
writer.open(filename, be, fourcc, FPS, FRAME_SIZE, true);
if (writer.isOpened())
{
Mat frame(FRAME_SIZE, CV_8UC3);
for (int j = 0; j < FRAME_COUNT; ++j)
{
generateFrame(j, frame);
writer << frame;
}
writer.release();
fileExists = true;
}
EXPECT_FALSE(writer.isOpened());
}
}
if (!fileExists)
{
cout << "None of backends has been able to write video file - SKIP reading part" << endl;
return;
}
{
vector<VideoCaptureAPIs> backends = videoio_registry::getStreamBackends();
for (VideoCaptureAPIs be : backends)
{
VideoCapture cap;
cap.open(filename, be);
if(cap.isOpened())
{
int count = 0;
while (true)
{
Mat frame;
if (cap.grab())
{
if (cap.retrieve(frame))
{
++count;
continue;
}
}
break;
}
EXPECT_EQ(count, FRAME_COUNT);
cap.release();
}
EXPECT_FALSE(cap.isOpened());
}
}
remove(filename.c_str());
}
}} // opencv_test::<anonymous>::

View File

@ -1,447 +1,202 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
// 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.
#include "test_precomp.hpp"
namespace opencv_test { namespace {
#ifdef HAVE_FFMPEG
using namespace std;
static const char* AVI_EXT = ".avi";
static const char* MP4_EXT = ".mp4";
namespace opencv_test { namespace {
class CV_FFmpegWriteBigVideoTest : public cvtest::BaseTest
static inline long long getFileSize(const string &filename)
{
struct TestFormatEntry {
int tag;
const char* ext;
bool required;
};
static long int getFileSize(string filename)
{
FILE *p_file = NULL;
p_file = fopen(filename.c_str(), "rb");
if (p_file == NULL)
return -1;
fseek(p_file, 0, SEEK_END);
long int size = ftell(p_file);
fclose(p_file);
return size;
}
public:
void run(int)
{
const int img_r = 4096;
const int img_c = 4096;
const double fps0 = 15;
const double time_sec = 1;
const TestFormatEntry entries[] = {
{0, AVI_EXT, true},
//{VideoWriter::fourcc('D', 'I', 'V', '3'), AVI_EXT, true},
//{VideoWriter::fourcc('D', 'I', 'V', 'X'), AVI_EXT, true},
{VideoWriter::fourcc('D', 'X', '5', '0'), AVI_EXT, true},
{VideoWriter::fourcc('F', 'L', 'V', '1'), AVI_EXT, true},
{VideoWriter::fourcc('H', '2', '6', '1'), AVI_EXT, true},
{VideoWriter::fourcc('H', '2', '6', '3'), AVI_EXT, true},
{VideoWriter::fourcc('I', '4', '2', '0'), AVI_EXT, true},
//{VideoWriter::fourcc('j', 'p', 'e', 'g'), AVI_EXT, true},
{VideoWriter::fourcc('M', 'J', 'P', 'G'), AVI_EXT, true},
{VideoWriter::fourcc('m', 'p', '4', 'v'), AVI_EXT, true},
{VideoWriter::fourcc('M', 'P', 'E', 'G'), AVI_EXT, true},
//{VideoWriter::fourcc('W', 'M', 'V', '1'), AVI_EXT, true},
//{VideoWriter::fourcc('W', 'M', 'V', '2'), AVI_EXT, true},
{VideoWriter::fourcc('X', 'V', 'I', 'D'), AVI_EXT, true},
//{VideoWriter::fourcc('Y', 'U', 'Y', '2'), AVI_EXT, true},
{VideoWriter::fourcc('H', '2', '6', '4'), MP4_EXT, false}
};
const size_t n = sizeof(entries)/sizeof(entries[0]);
for (size_t j = 0; j < n; ++j)
{
int tag = entries[j].tag;
const char* ext = entries[j].ext;
string s = cv::format("%08x%s", tag, ext);
const string filename = tempfile(s.c_str());
try
{
double fps = fps0;
Size frame_s = Size(img_c, img_r);
if( tag == VideoWriter::fourcc('H', '2', '6', '1') )
frame_s = Size(352, 288);
else if( tag == VideoWriter::fourcc('H', '2', '6', '3') )
frame_s = Size(704, 576);
else if( tag == VideoWriter::fourcc('H', '2', '6', '4') )
// OpenH264 1.5.0 has resolution limitations, so lets use DCI 4K resolution
frame_s = Size(4096, 2160);
/*else if( tag == CV_FOURCC('M', 'J', 'P', 'G') ||
tag == CV_FOURCC('j', 'p', 'e', 'g') )
frame_s = Size(1920, 1080);*/
if( tag == VideoWriter::fourcc('M', 'P', 'E', 'G') )
{
frame_s = Size(720, 576);
fps = 25;
}
VideoWriter writer(filename, CAP_FFMPEG, tag, fps, frame_s);
if (writer.isOpened() == false)
{
fprintf(stderr, "\n\nFile name: %s\n", filename.c_str());
fprintf(stderr, "Codec id: %d Codec tag: %c%c%c%c\n", (int)j,
tag & 255, (tag >> 8) & 255, (tag >> 16) & 255, (tag >> 24) & 255);
fprintf(stderr, "Error: cannot create video file.\n");
if (entries[j].required)
ts->set_failed_test_info(ts->FAIL_INVALID_OUTPUT);
}
else
{
Mat img(frame_s, CV_8UC3, Scalar::all(0));
const int coeff = cvRound(min(frame_s.width, frame_s.height)/(fps0 * time_sec));
for (int i = 0 ; i < static_cast<int>(fps * time_sec); i++ )
{
//circle(img, Point2i(img_c / 2, img_r / 2), min(img_r, img_c) / 2 * (i + 1), Scalar(255, 0, 0, 0), 2);
rectangle(img, Point2i(coeff * i, coeff * i), Point2i(coeff * (i + 1), coeff * (i + 1)),
Scalar::all(255 * (1.0 - static_cast<double>(i) / (fps * time_sec * 2) )), -1);
writer << img;
}
writer.release();
long int sz = getFileSize(filename);
if (sz < 0)
{
fprintf(stderr, "ERROR: File name: %s was not created\n", filename.c_str());
if (entries[j].required)
ts->set_failed_test_info(ts->FAIL_INVALID_OUTPUT);
}
else
{
printf("Case: '%s' (frame size %dx%d fps=%g). FileSize=%lld bytes\n",
s.c_str(), frame_s.width, frame_s.height, fps, (long long int)sz);
if (sz < 8192)
{
fprintf(stderr, "ERROR: File name: %s is very small (data write problems?)\n", filename.c_str());
if (entries[j].required)
ts->set_failed_test_info(ts->FAIL_INVALID_OUTPUT);
}
remove(filename.c_str());
}
}
}
catch(...)
{
ts->set_failed_test_info(ts->FAIL_INVALID_OUTPUT);
}
ts->set_failed_test_info(cvtest::TS::OK);
}
}
};
TEST(Videoio_Video, ffmpeg_writebig) { CV_FFmpegWriteBigVideoTest test; test.safe_run(); }
class CV_FFmpegReadImageTest : public cvtest::BaseTest
{
public:
void run(int)
{
try
{
string filename = ts->get_data_path() + "readwrite/ordinary.bmp";
VideoCapture cap(filename, CAP_FFMPEG);
Mat img0 = imread(filename, 1);
Mat img, img_next;
cap >> img;
cap >> img_next;
CV_Assert( !img0.empty() && !img.empty() && img_next.empty() );
double diff = cvtest::norm(img0, img, CV_C);
CV_Assert( diff == 0 );
}
catch(...)
{
ts->set_failed_test_info(ts->FAIL_INVALID_OUTPUT);
}
ts->set_failed_test_info(cvtest::TS::OK);
}
};
TEST(Videoio_Video, ffmpeg_image) { CV_FFmpegReadImageTest test; test.safe_run(); }
#endif
#if defined(HAVE_FFMPEG)
//////////////////////////////// Parallel VideoWriters and VideoCaptures ////////////////////////////////////
class CreateVideoWriterInvoker :
public ParallelLoopBody
{
public:
const static Size FrameSize;
static std::string TmpDirectory;
CreateVideoWriterInvoker(std::vector<VideoWriter*>& _writers, std::vector<std::string>& _files) :
writers(_writers), files(_files)
{
}
virtual void operator() (const Range& range) const CV_OVERRIDE
{
for (int i = range.start; i != range.end; ++i)
{
std::ostringstream stream;
stream << i << ".avi";
std::string fileName = tempfile(stream.str().c_str());
files[i] = fileName;
writers[i] = new VideoWriter(fileName, CAP_FFMPEG, VideoWriter::fourcc('X','V','I','D'), 25.0f, FrameSize);
CV_Assert(writers[i]->isOpened());
}
}
private:
std::vector<VideoWriter*>& writers;
std::vector<std::string>& files;
};
std::string CreateVideoWriterInvoker::TmpDirectory;
const Size CreateVideoWriterInvoker::FrameSize(1020, 900);
class WriteVideo_Invoker :
public ParallelLoopBody
{
public:
enum { FrameCount = 300 };
static const Scalar ObjectColor;
static const Point Center;
WriteVideo_Invoker(const std::vector<VideoWriter*>& _writers) :
ParallelLoopBody(), writers(&_writers)
{
}
static void GenerateFrame(Mat& frame, unsigned int i)
{
frame = Scalar::all(i % 255);
std::string text = to_string(i);
putText(frame, text, Point(50, Center.y), FONT_HERSHEY_SIMPLEX, 5.0, ObjectColor, 5, CV_AA);
circle(frame, Center, i + 2, ObjectColor, 2, CV_AA);
}
virtual void operator() (const Range& range) const CV_OVERRIDE
{
for (int j = range.start; j < range.end; ++j)
{
VideoWriter* writer = writers->operator[](j);
CV_Assert(writer != NULL);
CV_Assert(writer->isOpened());
Mat frame(CreateVideoWriterInvoker::FrameSize, CV_8UC3);
for (unsigned int i = 0; i < FrameCount; ++i)
{
GenerateFrame(frame, i);
writer->operator<< (frame);
}
}
}
protected:
static std::string to_string(unsigned int i)
{
std::stringstream stream(std::ios::out);
stream << "frame #" << i;
return stream.str();
}
private:
const std::vector<VideoWriter*>* writers;
};
const Scalar WriteVideo_Invoker::ObjectColor(Scalar::all(0));
const Point WriteVideo_Invoker::Center(CreateVideoWriterInvoker::FrameSize.height / 2,
CreateVideoWriterInvoker::FrameSize.width / 2);
class CreateVideoCaptureInvoker :
public ParallelLoopBody
{
public:
CreateVideoCaptureInvoker(std::vector<VideoCapture*>& _readers, const std::vector<std::string>& _files) :
ParallelLoopBody(), readers(&_readers), files(&_files)
{
}
virtual void operator() (const Range& range) const CV_OVERRIDE
{
for (int i = range.start; i != range.end; ++i)
{
readers->operator[](i) = new VideoCapture(files->operator[](i), CAP_FFMPEG);
CV_Assert(readers->operator[](i)->isOpened());
}
}
private:
std::vector<VideoCapture*>* readers;
const std::vector<std::string>* files;
};
class ReadImageAndTest :
public ParallelLoopBody
{
public:
ReadImageAndTest(const std::vector<VideoCapture*>& _readers, cvtest::TS* _ts) :
ParallelLoopBody(), readers(&_readers), ts(_ts)
{
}
virtual void operator() (const Range& range) const CV_OVERRIDE
{
for (int j = range.start; j < range.end; ++j)
{
VideoCapture* capture = readers->operator[](j);
CV_Assert(capture != NULL);
CV_Assert(capture->isOpened());
const static double eps = 23.0;
unsigned int frameCount = static_cast<unsigned int>(capture->get(CAP_PROP_FRAME_COUNT));
CV_Assert(frameCount == WriteVideo_Invoker::FrameCount);
Mat reference(CreateVideoWriterInvoker::FrameSize, CV_8UC3);
for (unsigned int i = 0; i < frameCount && next; ++i)
{
SCOPED_TRACE(cv::format("frame=%d/%d", (int)i, (int)frameCount));
Mat actual;
(*capture) >> actual;
WriteVideo_Invoker::GenerateFrame(reference, i);
EXPECT_EQ(reference.cols, actual.cols);
EXPECT_EQ(reference.rows, actual.rows);
EXPECT_EQ(reference.depth(), actual.depth());
EXPECT_EQ(reference.channels(), actual.channels());
double psnr = cvtest::PSNR(actual, reference);
if (psnr < eps)
{
#define SUM cvtest::TS::SUMMARY
ts->printf(SUM, "\nPSNR: %lf\n", psnr);
ts->printf(SUM, "Video #: %d\n", range.start);
ts->printf(SUM, "Frame #: %d\n", i);
#undef SUM
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
ts->set_gtest_status();
Mat diff;
absdiff(actual, reference, diff);
EXPECT_EQ(countNonZero(diff.reshape(1) > 1), 0);
next = false;
}
}
}
}
static bool next;
private:
const std::vector<VideoCapture*>* readers;
cvtest::TS* ts;
};
bool ReadImageAndTest::next;
TEST(Videoio_Video_parallel_writers_and_readers, accuracy)
{
const unsigned int threadsCount = 4;
cvtest::TS* ts = cvtest::TS::ptr();
// creating VideoWriters
std::vector<VideoWriter*> writers(threadsCount);
Range range(0, threadsCount);
std::vector<std::string> files(threadsCount);
CreateVideoWriterInvoker invoker1(writers, files);
parallel_for_(range, invoker1);
// write a video
parallel_for_(range, WriteVideo_Invoker(writers));
// deleting the writers
for (std::vector<VideoWriter*>::iterator i = writers.begin(), end = writers.end(); i != end; ++i)
delete *i;
writers.clear();
std::vector<VideoCapture*> readers(threadsCount);
CreateVideoCaptureInvoker invoker2(readers, files);
parallel_for_(range, invoker2);
ReadImageAndTest::next = true;
parallel_for_(range, ReadImageAndTest(readers, ts));
// deleting tmp video files
for (std::vector<std::string>::const_iterator i = files.begin(), end = files.end(); i != end; ++i)
{
int code = remove(i->c_str());
if (code == 1)
std::cerr << "Couldn't delete " << *i << std::endl;
}
// delete the readers
for (std::vector<VideoCapture *>::iterator i = readers.begin(), end = readers.end(); i != end; ++i)
delete *i;
ifstream f(filename, ios_base::in | ios_base::binary);
f.seekg(0, ios_base::end);
return f.tellg();
}
typedef tuple<string, string, Size> FourCC_Ext_Size;
typedef testing::TestWithParam< FourCC_Ext_Size > videoio_ffmpeg;
TEST_P(videoio_ffmpeg, write_big)
{
if (!videoio_registry::hasBackend(CAP_FFMPEG))
throw SkipTestException("FFmpeg backend was not found");
const string fourcc = get<0>(GetParam());
const string ext = get<1>(GetParam());
const Size sz = get<2>(GetParam());
const double time_sec = 1;
const double fps = 25;
ostringstream buf;
buf << "write_big_" << fourcc << "." << ext;
const string filename = tempfile(buf.str().c_str());
VideoWriter writer(filename, CAP_FFMPEG, fourccFromString(fourcc), fps, sz);
if (ext == "mp4" && fourcc == "H264" && !writer.isOpened())
{
throw cvtest::SkipTestException("H264/mp4 codec is not supported - SKIP");
}
ASSERT_TRUE(writer.isOpened());
Mat img(sz, CV_8UC3, Scalar::all(0));
const int coeff = cvRound(min(sz.width, sz.height)/(fps * time_sec));
for (int i = 0 ; i < static_cast<int>(fps * time_sec); i++ )
{
rectangle(img,
Point2i(coeff * i, coeff * i),
Point2i(coeff * (i + 1), coeff * (i + 1)),
Scalar::all(255 * (1.0 - static_cast<double>(i) / (fps * time_sec * 2))),
-1);
writer << img;
}
writer.release();
EXPECT_GT(getFileSize(filename), 8192);
remove(filename.c_str());
}
static const Size bigSize(4096, 4096);
const FourCC_Ext_Size entries[] =
{
make_tuple("", "avi", bigSize),
make_tuple("DX50", "avi", bigSize),
make_tuple("FLV1", "avi", bigSize),
make_tuple("H261", "avi", Size(352, 288)),
make_tuple("H263", "avi", Size(704, 576)),
make_tuple("I420", "avi", bigSize),
make_tuple("MJPG", "avi", bigSize),
make_tuple("mp4v", "avi", bigSize),
make_tuple("MPEG", "avi", Size(720, 576)),
make_tuple("XVID", "avi", bigSize),
make_tuple("H264", "mp4", Size(4096, 2160))
};
INSTANTIATE_TEST_CASE_P(videoio, videoio_ffmpeg, testing::ValuesIn(entries));
//==========================================================================
TEST(videoio_ffmpeg, image)
{
if (!videoio_registry::hasBackend(CAP_FFMPEG))
throw SkipTestException("FFmpeg backend was not found");
const string filename = findDataFile("readwrite/ordinary.bmp");
Mat image = imread(filename, IMREAD_COLOR);
ASSERT_FALSE(image.empty());
VideoCapture cap(filename, CAP_FFMPEG);
ASSERT_TRUE(cap.isOpened());
Mat frame1, frame2;
cap >> frame1 >> frame2;
ASSERT_FALSE(frame1.empty());
ASSERT_TRUE(frame2.empty());
ASSERT_EQ(0, cvtest::norm(image, frame1, NORM_INF));
}
//==========================================================================
static void generateFrame(Mat &frame, unsigned int i, const Point &center, const Scalar &color)
{
frame = Scalar::all(i % 255);
stringstream buf(ios::out);
buf << "frame #" << i;
putText(frame, buf.str(), Point(50, center.y), FONT_HERSHEY_SIMPLEX, 5.0, color, 5, CV_AA);
circle(frame, center, i + 2, color, 2, CV_AA);
}
TEST(videoio_ffmpeg, parallel)
{
if (!videoio_registry::hasBackend(CAP_FFMPEG))
throw SkipTestException("FFmpeg backend was not found");
const int NUM = 4;
const int GRAN = 4;
const Range R(0, NUM);
const Size sz(1020, 900);
const int frameNum = 300;
const Scalar color(Scalar::all(0));
const Point center(sz.height / 2, sz.width / 2);
// Generate filenames
vector<string> files;
for (int i = 0; i < NUM; ++i)
{
ostringstream stream;
stream << i << ".avi";
files.push_back(tempfile(stream.str().c_str()));
}
// Write videos
{
vector< Ptr<VideoWriter> > writers(NUM);
auto makeWriters = [&](const Range &r)
{
for (int i = r.start; i != r.end; ++i)
writers[i] = makePtr<VideoWriter>(files[i],
CAP_FFMPEG,
VideoWriter::fourcc('X','V','I','D'),
25.0f,
sz);
};
parallel_for_(R, makeWriters, GRAN);
for(int i = 0; i < NUM; ++i)
{
ASSERT_TRUE(writers[i]);
ASSERT_TRUE(writers[i]->isOpened());
}
auto writeFrames = [&](const Range &r)
{
for (int j = r.start; j < r.end; ++j)
{
Mat frame(sz, CV_8UC3);
for (int i = 0; i < frameNum; ++i)
{
generateFrame(frame, i, center, color);
writers[j]->write(frame);
}
}
};
parallel_for_(R, writeFrames, GRAN);
}
// Read videos
{
vector< Ptr<VideoCapture> > readers(NUM);
auto makeCaptures = [&](const Range &r)
{
for (int i = r.start; i != r.end; ++i)
readers[i] = makePtr<VideoCapture>(files[i], CAP_FFMPEG);
};
parallel_for_(R, makeCaptures, GRAN);
for(int i = 0; i < NUM; ++i)
{
ASSERT_TRUE(readers[i]);
ASSERT_TRUE(readers[i]->isOpened());
}
auto readFrames = [&](const Range &r)
{
for (int j = r.start; j < r.end; ++j)
{
Mat reference(sz, CV_8UC3);
for (int i = 0; i < frameNum; ++i)
{
Mat actual;
EXPECT_TRUE(readers[j]->read(actual));
EXPECT_FALSE(actual.empty());
generateFrame(reference, i, center, color);
EXPECT_EQ(reference.size(), actual.size());
EXPECT_EQ(reference.depth(), actual.depth());
EXPECT_EQ(reference.channels(), actual.channels());
EXPECT_GE(cvtest::PSNR(actual, reference), 35.0) << "cap" << j << ", frame " << i;
}
}
};
parallel_for_(R, readFrames, GRAN);
}
// Remove files
for(int i = 0; i < NUM; ++i)
{
remove(files[i].c_str());
}
}
#endif
}} // namespace

View File

@ -1,118 +0,0 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "test_precomp.hpp"
namespace opencv_test { namespace {
#undef DEFINE_GUID
#define DEFINE_GUID(n, fourcc, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) fourcc,
unsigned long allfourcc[] = {
DEFINE_GUID(MEDIASUBTYPE_GREY, 0x59455247, 0x0000, 0x0010, 0x80, 0x00,
0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)
DEFINE_GUID(MEDIASUBTYPE_Y8, 0x20203859, 0x0000, 0x0010, 0x80, 0x00,
0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)
DEFINE_GUID(MEDIASUBTYPE_Y800, 0x30303859, 0x0000, 0x0010, 0x80, 0x00,
0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)
DEFINE_GUID(CLSID_CaptureGraphBuilder2,0xbf87b6e1,0x8c27,0x11d0,0xb3,0xf0,0x00,0xaa,0x00,0x37,0x61,0xc5)
DEFINE_GUID(CLSID_FilterGraph,0xe436ebb3,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70)
DEFINE_GUID(CLSID_NullRenderer,0xc1f400a4,0x3f08,0x11d3,0x9f,0x0b,0x00,0x60,0x08,0x03,0x9e,0x37)
DEFINE_GUID(CLSID_SampleGrabber,0xc1f400a0,0x3f08,0x11d3,0x9f,0x0b,0x00,0x60,0x08,0x03,0x9e,0x37)
DEFINE_GUID(CLSID_SystemDeviceEnum,0x62be5d10,0x60eb,0x11d0,0xbd,0x3b,0x00,0xa0,0xc9,0x11,0xce,0x86)
DEFINE_GUID(CLSID_VideoInputDeviceCategory,0x860bb310,0x5d01,0x11d0,0xbd,0x3b,0x00,0xa0,0xc9,0x11,0xce,0x86)
DEFINE_GUID(FORMAT_VideoInfo,0x05589f80,0xc356,0x11ce,0xbf,0x01,0x00,0xaa,0x00,0x55,0x59,0x5a)
DEFINE_GUID(IID_IAMAnalogVideoDecoder,0xc6e13350,0x30ac,0x11d0,0xa1,0x8c,0x00,0xa0,0xc9,0x11,0x89,0x56)
DEFINE_GUID(IID_IAMCameraControl,0xc6e13370,0x30ac,0x11d0,0xa1,0x8c,0x00,0xa0,0xc9,0x11,0x89,0x56)
DEFINE_GUID(IID_IAMCrossbar,0xc6e13380,0x30ac,0x11d0,0xa1,0x8c,0x00,0xa0,0xc9,0x11,0x89,0x56)
DEFINE_GUID(IID_IAMStreamConfig,0xc6e13340,0x30ac,0x11d0,0xa1,0x8c,0x00,0xa0,0xc9,0x11,0x89,0x56)
DEFINE_GUID(IID_IAMVideoProcAmp,0xc6e13360,0x30ac,0x11d0,0xa1,0x8c,0x00,0xa0,0xc9,0x11,0x89,0x56)
DEFINE_GUID(IID_IBaseFilter,0x56a86895,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70)
DEFINE_GUID(IID_ICaptureGraphBuilder2,0x93e5a4e0,0x2d50,0x11d2,0xab,0xfa,0x00,0xa0,0xc9,0xc6,0xe3,0x8d)
DEFINE_GUID(IID_ICreateDevEnum,0x29840822,0x5b84,0x11d0,0xbd,0x3b,0x00,0xa0,0xc9,0x11,0xce,0x86)
DEFINE_GUID(IID_IGraphBuilder,0x56a868a9,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70)
DEFINE_GUID(IID_IMPEG2PIDMap,0xafb6c2a1,0x2c41,0x11d3,0x8a,0x60,0x00,0x00,0xf8,0x1e,0x0e,0x4a)
DEFINE_GUID(IID_IMediaControl,0x56a868b1,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70)
DEFINE_GUID(IID_IMediaFilter,0x56a86899,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70)
DEFINE_GUID(IID_ISampleGrabber,0x6b652fff,0x11fe,0x4fce,0x92,0xad,0x02,0x66,0xb5,0xd7,0xc7,0x8f)
DEFINE_GUID(LOOK_UPSTREAM_ONLY,0xac798be0,0x98e3,0x11d1,0xb3,0xf1,0x00,0xaa,0x00,0x37,0x61,0xc5)
DEFINE_GUID(MEDIASUBTYPE_AYUV,0x56555941,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
DEFINE_GUID(MEDIASUBTYPE_IYUV,0x56555949,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
DEFINE_GUID(MEDIASUBTYPE_RGB24,0xe436eb7d,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70)
DEFINE_GUID(MEDIASUBTYPE_RGB32,0xe436eb7e,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70)
DEFINE_GUID(MEDIASUBTYPE_RGB555,0xe436eb7c,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70)
DEFINE_GUID(MEDIASUBTYPE_RGB565,0xe436eb7b,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70)
DEFINE_GUID(MEDIASUBTYPE_I420,0x49343230,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
DEFINE_GUID(MEDIASUBTYPE_UYVY,0x59565955,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
DEFINE_GUID(MEDIASUBTYPE_Y211,0x31313259,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
DEFINE_GUID(MEDIASUBTYPE_Y411,0x31313459,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
DEFINE_GUID(MEDIASUBTYPE_Y41P,0x50313459,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
DEFINE_GUID(MEDIASUBTYPE_YUY2,0x32595559,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
DEFINE_GUID(MEDIASUBTYPE_YUYV,0x56595559,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
DEFINE_GUID(MEDIASUBTYPE_YV12,0x32315659,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
DEFINE_GUID(MEDIASUBTYPE_YVU9,0x39555659,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
DEFINE_GUID(MEDIASUBTYPE_YVYU,0x55595659,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
DEFINE_GUID(MEDIASUBTYPE_MJPG,0x47504A4D, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71) // MGB
DEFINE_GUID(MEDIATYPE_Interleaved,0x73766169,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
DEFINE_GUID(MEDIATYPE_Video,0x73646976,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71)
DEFINE_GUID(PIN_CATEGORY_CAPTURE,0xfb6c4281,0x0353,0x11d1,0x90,0x5f,0x00,0x00,0xc0,0xcc,0x16,0xba)
DEFINE_GUID(PIN_CATEGORY_PREVIEW,0xfb6c4282,0x0353,0x11d1,0x90,0x5f,0x00,0x00,0xc0,0xcc,0x16,0xba)
0};
TEST(Videoio_dshow, fourcc_conversion)
{
for(int i = 0; allfourcc[i]; ++i)
{
unsigned long fourcc = allfourcc[i];
double paramValue = fourcc;
int fourccFromParam = (int)(unsigned long)(paramValue);
EXPECT_EQ(fourcc, (unsigned long)(unsigned)fourccFromParam);
}
}
}} // namespace

View File

@ -3,16 +3,18 @@
// of this distribution and at http://opencv.org/license.html.
#include "test_precomp.hpp"
#ifdef HAVE_GSTREAMER
namespace opencv_test
{
typedef tuple< string, Size, Size, int > Param;
typedef testing::TestWithParam< Param > Videoio_Gstreamer_Test;
typedef testing::TestWithParam< Param > videoio_gstreamer;
TEST_P(Videoio_Gstreamer_Test, test_object_structure)
TEST_P(videoio_gstreamer, read_write)
{
if (!videoio_registry::hasBackend(CAP_GSTREAMER))
throw SkipTestException("GStreamer backend was not found");
string format = get<0>(GetParam());
Size frame_size = get<1>(GetParam());
Size mat_size = get<2>(GetParam());
@ -69,8 +71,6 @@ Param test_data[] = {
make_tuple("jpegenc ! image/jpeg" , Size(640, 480), Size(640, 480), COLOR_BGR2RGB)
};
INSTANTIATE_TEST_CASE_P(videoio, Videoio_Gstreamer_Test, testing::ValuesIn(test_data));
INSTANTIATE_TEST_CASE_P(videoio, videoio_gstreamer, testing::ValuesIn(test_data));
} // namespace
#endif

View File

@ -8,7 +8,7 @@
namespace opencv_test { namespace {
TEST(Videoio_MFX, read_invalid)
TEST(videoio_mfx, read_invalid)
{
VideoCapture cap;
ASSERT_NO_THROW(cap.open("nonexistent-file", CAP_INTEL_MFX));
@ -18,7 +18,7 @@ TEST(Videoio_MFX, read_invalid)
ASSERT_TRUE(img.empty());
}
TEST(Videoio_MFX, write_invalid)
TEST(videoio_mfx, write_invalid)
{
const string filename = cv::tempfile(".264");
VideoWriter writer;
@ -80,9 +80,9 @@ inline int fourccByExt(const String &ext)
//==================================================================================================
typedef tuple<Size, double, const char *> Size_FPS_Ext;
typedef testing::TestWithParam< Size_FPS_Ext > Videoio_MFX;
typedef testing::TestWithParam< Size_FPS_Ext > videoio_mfx;
TEST_P(Videoio_MFX, read_write_raw)
TEST_P(videoio_mfx, read_write_raw)
{
const Size FRAME_SIZE = get<0>(GetParam());
const double FPS = get<1>(GetParam());
@ -137,7 +137,7 @@ TEST_P(Videoio_MFX, read_write_raw)
remove(filename.c_str());
}
INSTANTIATE_TEST_CASE_P(videoio, Videoio_MFX,
INSTANTIATE_TEST_CASE_P(videoio, videoio_mfx,
testing::Combine(
testing::Values(Size(640, 480), Size(638, 478), Size(636, 476), Size(1920, 1080)),
testing::Values(1, 30, 100),

View File

@ -55,6 +55,7 @@ protected:
protected:
Videoio_Test_Base() {}
virtual ~Videoio_Test_Base() {}
virtual void writeVideo() {}
virtual void checkFrameContent(Mat &, int) {}
virtual void checkFrameCount(int &) {}
void checkFrameRead(int idx, VideoCapture & cap)
@ -81,8 +82,9 @@ protected:
public:
void doTest()
{
if (!isBackendAvailable(apiPref, cv::videoio_registry::getStreamBackends()))
if (!videoio_registry::hasBackend(apiPref))
throw SkipTestException(cv::String("Backend is not available/disabled: ") + cv::videoio_registry::getBackendName(apiPref));
writeVideo();
VideoCapture cap;
ASSERT_NO_THROW(cap.open(video_file, apiPref));
if (!cap.isOpened())
@ -154,11 +156,11 @@ public:
//==================================================================================================
typedef tuple<string, VideoCaptureAPIs> Backend_Type_Params;
class Videoio_Bunny : public Videoio_Test_Base, public testing::TestWithParam<Backend_Type_Params>
class videoio_bunny : public Videoio_Test_Base, public testing::TestWithParam<Backend_Type_Params>
{
BunnyParameters bunny_param;
public:
Videoio_Bunny()
videoio_bunny()
{
ext = get<0>(GetParam());
apiPref = get<1>(GetParam());
@ -166,7 +168,7 @@ public:
}
void doFrameCountTest()
{
if (!isBackendAvailable(apiPref, cv::videoio_registry::getStreamBackends()))
if (!videoio_registry::hasBackend(apiPref))
throw SkipTestException(cv::String("Backend is not available/disabled: ") + cv::videoio_registry::getBackendName(apiPref));
VideoCapture cap;
EXPECT_NO_THROW(cap.open(video_file, apiPref));
@ -232,7 +234,7 @@ struct Ext_Fourcc_PSNR
};
typedef tuple<Size, Ext_Fourcc_PSNR> Size_Ext_Fourcc_PSNR;
class Videoio_Synthetic : public Videoio_Test_Base, public testing::TestWithParam<Size_Ext_Fourcc_PSNR>
class videoio_synthetic : public Videoio_Test_Base, public testing::TestWithParam<Size_Ext_Fourcc_PSNR>
{
Size frame_size;
int fourcc;
@ -240,7 +242,7 @@ class Videoio_Synthetic : public Videoio_Test_Base, public testing::TestWithPara
int frame_count;
double fps;
public:
Videoio_Synthetic()
videoio_synthetic()
{
frame_size = get<0>(GetParam());
const Ext_Fourcc_PSNR p = get<1>(GetParam());
@ -252,7 +254,11 @@ public:
fps = 25.;
apiPref = p.api;
}
void SetUp()
void TearDown()
{
remove(video_file.c_str());
}
virtual void writeVideo()
{
Mat img(frame_size, CV_8UC3);
VideoWriter writer;
@ -265,10 +271,6 @@ public:
}
EXPECT_NO_THROW(writer.release());
}
void TearDown()
{
remove(video_file.c_str());
}
virtual void checkFrameContent(Mat & img, int idx)
{
Mat imgGT(frame_size, CV_8UC3);
@ -311,13 +313,8 @@ static const VideoCaptureAPIs backend_params[] = {
CAP_MSMF,
#endif
#ifdef HAVE_GSTREAMER
CAP_GSTREAMER,
#endif
#ifdef HAVE_FFMPEG
CAP_FFMPEG,
#endif
#ifdef HAVE_XINE
CAP_XINE,
@ -338,11 +335,11 @@ static const string bunny_params[] = {
string("mjpg.avi")
};
TEST_P(Videoio_Bunny, read_position) { doTest(); }
TEST_P(videoio_bunny, read_position) { doTest(); }
TEST_P(Videoio_Bunny, frame_count) { doFrameCountTest(); }
TEST_P(videoio_bunny, frame_count) { doFrameCountTest(); }
INSTANTIATE_TEST_CASE_P(videoio, Videoio_Bunny,
INSTANTIATE_TEST_CASE_P(videoio, videoio_bunny,
testing::Combine(
testing::ValuesIn(bunny_params),
testing::ValuesIn(backend_params)));
@ -388,7 +385,6 @@ static Ext_Fourcc_PSNR synthetic_params[] = {
makeParam("3gp", "MJPG", 30.f, CAP_AVFOUNDATION),
#endif
#ifdef HAVE_FFMPEG
makeParam("avi", "XVID", 30.f, CAP_FFMPEG),
makeParam("avi", "MPEG", 30.f, CAP_FFMPEG),
makeParam("avi", "IYUV", 30.f, CAP_FFMPEG),
@ -397,9 +393,7 @@ static Ext_Fourcc_PSNR synthetic_params[] = {
makeParam("mkv", "XVID", 30.f, CAP_FFMPEG),
makeParam("mkv", "MPEG", 30.f, CAP_FFMPEG),
makeParam("mkv", "MJPG", 30.f, CAP_FFMPEG),
#endif
#ifdef HAVE_GSTREAMER
makeParam("avi", "MPEG", 30.f, CAP_GSTREAMER),
makeParam("avi", "MJPG", 30.f, CAP_GSTREAMER),
makeParam("avi", "H264", 30.f, CAP_GSTREAMER),
@ -408,7 +402,6 @@ static Ext_Fourcc_PSNR synthetic_params[] = {
makeParam("mkv", "MJPG", 30.f, CAP_GSTREAMER),
makeParam("mkv", "H264", 30.f, CAP_GSTREAMER),
#endif
makeParam("avi", "MJPG", 30.f, CAP_OPENCV_MJPEG),
};
@ -418,9 +411,9 @@ Size all_sizes[] = {
Size(976, 768)
};
TEST_P(Videoio_Synthetic, write_read_position) { doTest(); }
TEST_P(videoio_synthetic, write_read_position) { doTest(); }
INSTANTIATE_TEST_CASE_P(videoio, Videoio_Synthetic,
INSTANTIATE_TEST_CASE_P(videoio, videoio_synthetic,
testing::Combine(
testing::ValuesIn(all_sizes),
testing::ValuesIn(synthetic_params)));