mirror of https://github.com/opencv/opencv.git
parent
8bde6aea4b
commit
9702987209
64 changed files with 2278 additions and 1476 deletions
@ -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}" |
||||||
|
"${CMAKE_CURRENT_LIST_DIR}/src/plugin_api.cpp") |
||||||
|
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}" "${videoio_ROOT}/src/plugin_api.cpp") |
||||||
|
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() |
@ -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 |
@ -0,0 +1 @@ |
|||||||
|
*.tar.xz |
@ -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}") |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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}") |
@ -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 |
@ -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 |
@ -0,0 +1,491 @@ |
|||||||
|
// 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" |
||||||
|
|
||||||
|
//==================================================================================================
|
||||||
|
// IBackend implementation
|
||||||
|
|
||||||
|
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); |
||||||
|
|
||||||
|
Ptr<IVideoCapture> IBackend::tryOpenCapture(const std::string & backendName, const std::string & filename, int cameraNum) const |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) |
||||||
|
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying ...\n", backendName.c_str())); |
||||||
|
Ptr<IVideoCapture> icap = createCapture(filename, cameraNum); |
||||||
|
if (param_VIDEOIO_DEBUG ||param_VIDEOCAPTURE_DEBUG) |
||||||
|
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): result=%p isOpened=%d ...\n", backendName.c_str(), icap.empty() ? NULL : icap.get(), icap.empty() ? -1: icap->isOpened())); |
||||||
|
return icap; |
||||||
|
} |
||||||
|
catch(const cv::Exception& e) |
||||||
|
{ |
||||||
|
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", backendName.c_str(), e.what())); |
||||||
|
} |
||||||
|
catch (const std::exception& e) |
||||||
|
{ |
||||||
|
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", backendName.c_str(), e.what())); |
||||||
|
} |
||||||
|
catch(...) |
||||||
|
{ |
||||||
|
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", backendName.c_str())); |
||||||
|
} |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
Ptr<IVideoWriter> IBackend::tryOpenWriter(const std::string & backendName, const std::string& filename, int _fourcc, double fps, const Size &frameSize, bool isColor) const |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) |
||||||
|
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying ...\n", backendName.c_str())); |
||||||
|
Ptr<IVideoWriter> iwriter = createWriter(filename, _fourcc, fps, frameSize, isColor); |
||||||
|
if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) |
||||||
|
CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): result=%p isOpened=%d...\n", backendName.c_str(), iwriter.empty() ? NULL : iwriter.get(), iwriter.empty() ? iwriter->isOpened() : -1)); |
||||||
|
return iwriter; |
||||||
|
} |
||||||
|
catch(const cv::Exception& e) |
||||||
|
{ |
||||||
|
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", backendName.c_str(), e.what())); |
||||||
|
} |
||||||
|
catch (const std::exception& e) |
||||||
|
{ |
||||||
|
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", backendName.c_str(), e.what())); |
||||||
|
} |
||||||
|
catch(...) |
||||||
|
{ |
||||||
|
CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", backendName.c_str())); |
||||||
|
} |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
} // cv::
|
||||||
|
|
||||||
|
//==================================================================================================
|
||||||
|
// 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 |
||||||
|
|
||||||
|
inline static void * getSymbol_(void *h, const std::string &symbolName) |
||||||
|
{ |
||||||
|
#if defined(_WIN32) |
||||||
|
return (void*)GetProcAddress(static_cast<HMODULE>(h), symbolName.c_str()); |
||||||
|
#elif defined(__linux__) || defined(__APPLE__) |
||||||
|
return dlsym(h, symbolName.c_str()); |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
inline static void * libraryLoad_(const std::string &filename) |
||||||
|
{ |
||||||
|
#if defined(_WIN32) |
||||||
|
return static_cast<HMODULE>(LoadLibraryA(filename.c_str())); |
||||||
|
#elif defined(__linux__) || defined(__APPLE__) |
||||||
|
return dlopen(filename.c_str(), RTLD_LAZY); |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
inline static void libraryRelease_(void *h) |
||||||
|
{ |
||||||
|
#if defined(_WIN32) |
||||||
|
FreeLibrary(static_cast<HMODULE>(h)); |
||||||
|
#elif defined(__linux__) || defined(__APPLE__) |
||||||
|
dlclose(h); |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
inline static std::string libraryPrefix() |
||||||
|
{ |
||||||
|
#if defined(_WIN32) |
||||||
|
return string(); |
||||||
|
#else |
||||||
|
return "lib"; |
||||||
|
#endif |
||||||
|
} |
||||||
|
inline static std::string librarySuffix() |
||||||
|
{ |
||||||
|
#if defined(_WIN32) |
||||||
|
return "dll"; |
||||||
|
#elif defined(__APPLE__) |
||||||
|
return "dylib"; |
||||||
|
#else |
||||||
|
return "so"; |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
//============================
|
||||||
|
|
||||||
|
class cv::DynamicBackend::DynamicLib |
||||||
|
{ |
||||||
|
private: |
||||||
|
void * 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 std::string & symbolName) const |
||||||
|
{ |
||||||
|
if (!handle) |
||||||
|
{ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
void * res = getSymbol_(handle, symbolName); |
||||||
|
if (!res) |
||||||
|
CV_LOG_ERROR(NULL, "No symbol '" << symbolName << "' in " << fname); |
||||||
|
return res; |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
void libraryLoad(const std::string &filename) |
||||||
|
{ |
||||||
|
handle = libraryLoad_(filename); |
||||||
|
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 &); |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
//============================
|
||||||
|
|
||||||
|
// Utility function
|
||||||
|
static bool verifyVersion(cv_get_version_t * fun) |
||||||
|
{ |
||||||
|
if (!fun) |
||||||
|
return false; |
||||||
|
int major, minor, patch, api, abi; |
||||||
|
fun(major, minor, patch, api, abi); |
||||||
|
if (api < API_VERSION || abi != ABI_VERSION) |
||||||
|
{ |
||||||
|
CV_LOG_ERROR(NULL, "Bad plugin API/ABI (" << api << "/" << abi << "), expected " << API_VERSION << "/" << ABI_VERSION); |
||||||
|
return false; |
||||||
|
} |
||||||
|
#ifdef STRICT_PLUGIN_CHECK |
||||||
|
if (major != CV_MAJOR_VERSION || minor != CV_MINOR_VERSION) |
||||||
|
{ |
||||||
|
CV_LOG_ERROR(NULL, "Bad plugin version (" << major << "." << minor << "), expected " << CV_MAJOR_VERSION << "/" << CV_MINOR_VERSION); |
||||||
|
return false; |
||||||
|
} |
||||||
|
#endif |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
//============================
|
||||||
|
|
||||||
|
class cv::DynamicBackend::CaptureTable |
||||||
|
{ |
||||||
|
public: |
||||||
|
cv_get_version_t *cv_get_version; |
||||||
|
cv_domain_t *cv_domain; |
||||||
|
cv_open_capture_t *cv_open_capture; |
||||||
|
cv_get_cap_prop_t *cv_get_cap_prop; |
||||||
|
cv_set_cap_prop_t *cv_set_cap_prop; |
||||||
|
cv_grab_t *cv_grab; |
||||||
|
cv_retrieve_t *cv_retrieve; |
||||||
|
cv_release_capture_t *cv_release_capture; |
||||||
|
bool isComplete; |
||||||
|
public: |
||||||
|
CaptureTable(const cv::DynamicBackend::DynamicLib & p) |
||||||
|
: isComplete(true) |
||||||
|
{ |
||||||
|
#define READ_FUN(name) \ |
||||||
|
name = reinterpret_cast<name##_t*>(p.getSymbol(#name)); \
|
||||||
|
isComplete = isComplete && (name) |
||||||
|
|
||||||
|
READ_FUN(cv_get_version); |
||||||
|
READ_FUN(cv_domain); |
||||||
|
READ_FUN(cv_open_capture); |
||||||
|
READ_FUN(cv_get_cap_prop); |
||||||
|
READ_FUN(cv_set_cap_prop); |
||||||
|
READ_FUN(cv_grab); |
||||||
|
READ_FUN(cv_retrieve); |
||||||
|
READ_FUN(cv_release_capture); |
||||||
|
|
||||||
|
#undef READ_FUN |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
class cv::DynamicBackend::WriterTable |
||||||
|
{ |
||||||
|
public: |
||||||
|
cv_get_version_t *cv_get_version; |
||||||
|
cv_domain_t *cv_domain; |
||||||
|
cv_open_writer_t *cv_open_writer; |
||||||
|
cv_get_wri_prop_t *cv_get_wri_prop; |
||||||
|
cv_set_wri_prop_t *cv_set_wri_prop; |
||||||
|
cv_write_t *cv_write; |
||||||
|
cv_release_writer_t *cv_release_writer; |
||||||
|
bool isComplete; |
||||||
|
public: |
||||||
|
WriterTable(const cv::DynamicBackend::DynamicLib & p) |
||||||
|
: isComplete(true) |
||||||
|
{ |
||||||
|
#define READ_FUN(name) \ |
||||||
|
name = reinterpret_cast<name##_t*>(p.getSymbol(#name)); \
|
||||||
|
isComplete = isComplete && (name) |
||||||
|
|
||||||
|
READ_FUN(cv_get_version); |
||||||
|
READ_FUN(cv_domain); |
||||||
|
READ_FUN(cv_open_writer); |
||||||
|
READ_FUN(cv_get_wri_prop); |
||||||
|
READ_FUN(cv_set_wri_prop); |
||||||
|
READ_FUN(cv_write); |
||||||
|
READ_FUN(cv_release_writer); |
||||||
|
|
||||||
|
#undef READ_FUN |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
//============================
|
||||||
|
|
||||||
|
class DynamicCapture; |
||||||
|
class DynamicWriter; |
||||||
|
|
||||||
|
cv::DynamicBackend::DynamicBackend(const std::string &filename) |
||||||
|
: lib(0), cap_tbl(0), wri_tbl(0) |
||||||
|
{ |
||||||
|
lib = new DynamicLib(filename); |
||||||
|
if (lib->isLoaded()) |
||||||
|
{ |
||||||
|
cap_tbl = new CaptureTable(*lib); |
||||||
|
wri_tbl = new WriterTable(*lib); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
cv::DynamicBackend::~DynamicBackend() |
||||||
|
{ |
||||||
|
if (cap_tbl) |
||||||
|
delete cap_tbl; |
||||||
|
if (wri_tbl) |
||||||
|
delete wri_tbl; |
||||||
|
if (lib) |
||||||
|
delete lib; |
||||||
|
} |
||||||
|
|
||||||
|
bool cv::DynamicBackend::canCreateCapture(VideoCaptureAPIs api) const |
||||||
|
{ |
||||||
|
return lib && lib->isLoaded() && cap_tbl && cap_tbl->isComplete && verifyVersion(cap_tbl->cv_get_version) && (cap_tbl->cv_domain() == api); |
||||||
|
} |
||||||
|
|
||||||
|
bool cv::DynamicBackend::canCreateWriter(VideoCaptureAPIs api) const |
||||||
|
{ |
||||||
|
return lib && lib->isLoaded() && wri_tbl && wri_tbl->isComplete && verifyVersion(wri_tbl->cv_get_version) && (wri_tbl->cv_domain() == api); |
||||||
|
} |
||||||
|
|
||||||
|
cv::Ptr<cv::IVideoCapture> cv::DynamicBackend::createCapture(const std::string & filename, int camera) const |
||||||
|
{ |
||||||
|
return makePtr<DynamicCapture>(cap_tbl, filename, camera).staticCast<IVideoCapture>(); |
||||||
|
} |
||||||
|
|
||||||
|
cv::Ptr<cv::IVideoWriter> cv::DynamicBackend::createWriter(const std::string & filename, int fourcc, double fps, const cv::Size &sz, bool isColor) const |
||||||
|
{ |
||||||
|
return makePtr<DynamicWriter>(wri_tbl, filename, fourcc, fps, sz, isColor).staticCast<IVideoWriter>(); |
||||||
|
} |
||||||
|
|
||||||
|
inline static std::vector<string> getPluginCandidates() |
||||||
|
{ |
||||||
|
using namespace cv::utils; |
||||||
|
using namespace cv::utils::fs; |
||||||
|
const vector<string> default_paths = { getParent(getBinLocation()) }; |
||||||
|
const vector<string> paths = getConfigurationParameterPaths("OPENCV_VIDEOIO_PLUGIN_PATH", default_paths); |
||||||
|
const string default_expr = libraryPrefix() + "opencv_videoio_*." + librarySuffix(); |
||||||
|
const string expr = getConfigurationParameterString("OPENCV_VIDEOIO_PLUGIN_NAME", default_expr.c_str()); |
||||||
|
CV_LOG_INFO(NULL, "VideoIO pluigins: glob is '" << expr << "', " << paths.size() << " location(s)"); |
||||||
|
vector<string> results; |
||||||
|
for(const string & path : paths) |
||||||
|
{ |
||||||
|
if (path.empty()) |
||||||
|
continue; |
||||||
|
vector<string> candidates; |
||||||
|
cv::glob(join(path, expr), candidates); |
||||||
|
CV_LOG_INFO(NULL, "VideoIO pluigins in " << path << ": " << candidates.size()); |
||||||
|
copy(candidates.begin(), candidates.end(), back_inserter(results)); |
||||||
|
} |
||||||
|
CV_LOG_INFO(NULL, "Found " << results.size() << " plugin(s)"); |
||||||
|
return results; |
||||||
|
} |
||||||
|
|
||||||
|
cv::Ptr<cv::DynamicBackend> cv::DynamicBackend::load(cv::VideoCaptureAPIs api, int mode) |
||||||
|
{ |
||||||
|
for(const std::string & plugin : getPluginCandidates()) |
||||||
|
{ |
||||||
|
bool res = true; |
||||||
|
Ptr<DynamicBackend> factory = makePtr<DynamicBackend>(plugin); |
||||||
|
if (factory) |
||||||
|
if (mode & cv::MODE_CAPTURE_BY_INDEX || mode & cv::MODE_CAPTURE_BY_FILENAME) |
||||||
|
{ |
||||||
|
res = res && factory->canCreateCapture(api); |
||||||
|
} |
||||||
|
if (mode & cv::MODE_WRITER) |
||||||
|
{ |
||||||
|
res = res && factory->canCreateWriter(api); |
||||||
|
} |
||||||
|
if (res) |
||||||
|
return factory; |
||||||
|
} |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
//==================================================================================================
|
||||||
|
// DynamicCapture
|
||||||
|
|
||||||
|
class DynamicCapture : public cv::IVideoCapture |
||||||
|
{ |
||||||
|
const cv::DynamicBackend::CaptureTable * tbl; |
||||||
|
void * capture; |
||||||
|
public: |
||||||
|
DynamicCapture(const cv::DynamicBackend::CaptureTable * tbl_, const std::string &filename, int camera) |
||||||
|
: tbl(tbl_), capture(0) |
||||||
|
{ |
||||||
|
CV_Assert(!capture); |
||||||
|
if (tbl->cv_open_capture) |
||||||
|
tbl->cv_open_capture(filename.empty() ? 0 : filename.c_str(), camera, capture); |
||||||
|
} |
||||||
|
~DynamicCapture() |
||||||
|
{ |
||||||
|
if (capture) |
||||||
|
{ |
||||||
|
CV_Assert(tbl->cv_release_capture); |
||||||
|
tbl->cv_release_capture(capture); |
||||||
|
capture = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
double getProperty(int prop) const CV_OVERRIDE |
||||||
|
{ |
||||||
|
CV_Assert(capture); |
||||||
|
double val = -1; |
||||||
|
tbl->cv_get_cap_prop(capture, prop, val); |
||||||
|
return val; |
||||||
|
} |
||||||
|
bool setProperty(int prop, double val) CV_OVERRIDE |
||||||
|
{ |
||||||
|
CV_Assert(capture); |
||||||
|
return tbl->cv_set_cap_prop(capture, prop, val); |
||||||
|
} |
||||||
|
bool grabFrame() CV_OVERRIDE |
||||||
|
{ |
||||||
|
CV_Assert(capture); |
||||||
|
return tbl->cv_grab(capture); |
||||||
|
} |
||||||
|
static bool local_retrieve(unsigned char * data, int step, int width, int height, int cn, void * userdata) |
||||||
|
{ |
||||||
|
cv::Mat * img = static_cast<cv::Mat*>(userdata); |
||||||
|
if (!img) |
||||||
|
return false; |
||||||
|
cv::Mat(cv::Size(width, height), CV_MAKETYPE(CV_8U, cn), data, step).copyTo(*img); |
||||||
|
return true; |
||||||
|
} |
||||||
|
bool retrieveFrame(int idx, cv::OutputArray img) CV_OVERRIDE |
||||||
|
{ |
||||||
|
CV_Assert(capture); |
||||||
|
cv::Mat frame; |
||||||
|
bool res = tbl->cv_retrieve(capture, idx, &local_retrieve, &frame); |
||||||
|
if (res) |
||||||
|
frame.copyTo(img); |
||||||
|
return res; |
||||||
|
} |
||||||
|
bool isOpened() const CV_OVERRIDE |
||||||
|
{ |
||||||
|
return capture != NULL; |
||||||
|
} |
||||||
|
int getCaptureDomain() CV_OVERRIDE |
||||||
|
{ |
||||||
|
return tbl->cv_domain(); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
//==================================================================================================
|
||||||
|
// DynamicWriter
|
||||||
|
|
||||||
|
class DynamicWriter : public cv::IVideoWriter |
||||||
|
{ |
||||||
|
const cv::DynamicBackend::WriterTable * tbl; |
||||||
|
void * writer; |
||||||
|
public: |
||||||
|
DynamicWriter(const cv::DynamicBackend::WriterTable * tbl_, const std::string &filename, int fourcc, double fps, const cv::Size &sz, bool isColor) |
||||||
|
: tbl(tbl_), writer(0) |
||||||
|
{ |
||||||
|
CV_Assert(!writer); |
||||||
|
if(tbl->cv_open_writer) |
||||||
|
tbl->cv_open_writer(filename.empty() ? 0 : filename.c_str(), fourcc, fps, sz.width, sz.height, isColor, writer); |
||||||
|
} |
||||||
|
~DynamicWriter() |
||||||
|
{ |
||||||
|
if (writer) |
||||||
|
{ |
||||||
|
CV_Assert(tbl->cv_release_writer); |
||||||
|
tbl->cv_release_writer(writer); |
||||||
|
writer = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
double getProperty(int prop) const CV_OVERRIDE |
||||||
|
{ |
||||||
|
CV_Assert(writer); |
||||||
|
double val = -1; |
||||||
|
tbl->cv_get_wri_prop(writer, prop, val); |
||||||
|
return val; |
||||||
|
} |
||||||
|
bool setProperty(int prop, double val) CV_OVERRIDE |
||||||
|
{ |
||||||
|
CV_Assert(writer); |
||||||
|
return tbl->cv_set_wri_prop(writer, prop, val); |
||||||
|
} |
||||||
|
bool isOpened() const CV_OVERRIDE |
||||||
|
{ |
||||||
|
return writer != NULL; |
||||||
|
} |
||||||
|
void write(cv::InputArray arr) CV_OVERRIDE |
||||||
|
{ |
||||||
|
cv::Mat img = arr.getMat(); |
||||||
|
CV_Assert(writer); |
||||||
|
tbl->cv_write(writer, img.data, (int)img.step[0], img.cols, img.rows, img.channels()); |
||||||
|
} |
||||||
|
int getCaptureDomain() const CV_OVERRIDE |
||||||
|
{ |
||||||
|
return tbl->cv_domain(); |
||||||
|
} |
||||||
|
}; |
@ -0,0 +1,85 @@ |
|||||||
|
// 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: |
||||||
|
Ptr<IVideoCapture> tryOpenCapture(const std::string & backendName, const std::string & filename, int cameraNum) const; |
||||||
|
Ptr<IVideoWriter> tryOpenWriter(const std::string & backendName, const std::string& filename, int _fourcc, double fps, const Size &frameSize, bool isColor) const; |
||||||
|
protected: |
||||||
|
virtual Ptr<IVideoCapture> createCapture(const std::string &filename, int camera) const = 0; |
||||||
|
virtual Ptr<IVideoWriter> createWriter(const std::string &filename, int fourcc, double fps, const cv::Size &sz, bool isColor) const = 0; |
||||||
|
virtual ~IBackend() {} |
||||||
|
}; |
||||||
|
|
||||||
|
//==================================================================================================
|
||||||
|
|
||||||
|
class StaticBackend : public IBackend |
||||||
|
{ |
||||||
|
typedef Ptr<IVideoCapture> (*OpenFileFun)(const std::string &); |
||||||
|
typedef Ptr<IVideoCapture> (*OpenCamFun)(int); |
||||||
|
typedef Ptr<IVideoWriter> (*OpenWriterFun)(const std::string&, int, double, const Size&, bool); |
||||||
|
private: |
||||||
|
OpenFileFun FUN_FILE; |
||||||
|
OpenCamFun FUN_CAM; |
||||||
|
OpenWriterFun FUN_WRITE; |
||||||
|
public: |
||||||
|
StaticBackend(OpenFileFun f1, OpenCamFun f2, OpenWriterFun f3) |
||||||
|
: FUN_FILE(f1), FUN_CAM(f2), FUN_WRITE(f3) |
||||||
|
{ |
||||||
|
} |
||||||
|
protected: |
||||||
|
Ptr<IVideoCapture> createCapture(const std::string &filename, int camera) const CV_OVERRIDE |
||||||
|
{ |
||||||
|
if (filename.empty() && FUN_CAM) |
||||||
|
return FUN_CAM(camera); |
||||||
|
if (FUN_FILE) |
||||||
|
return FUN_FILE(filename); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
Ptr<IVideoWriter> createWriter(const std::string &filename, int fourcc, double fps, const Size &sz, bool isColor) const CV_OVERRIDE |
||||||
|
{ |
||||||
|
if (FUN_WRITE) |
||||||
|
return FUN_WRITE(filename, fourcc, fps, sz, isColor); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
//==================================================================================================
|
||||||
|
|
||||||
|
class DynamicBackend : public IBackend |
||||||
|
{ |
||||||
|
public: |
||||||
|
class CaptureTable; |
||||||
|
class WriterTable; |
||||||
|
class DynamicLib; |
||||||
|
private: |
||||||
|
DynamicLib * lib; |
||||||
|
CaptureTable const * cap_tbl; |
||||||
|
WriterTable const * wri_tbl; |
||||||
|
public: |
||||||
|
DynamicBackend(const std::string &filename); |
||||||
|
~DynamicBackend(); |
||||||
|
static Ptr<DynamicBackend> load(VideoCaptureAPIs api, int mode); |
||||||
|
protected: |
||||||
|
bool canCreateCapture(cv::VideoCaptureAPIs api) const; |
||||||
|
bool canCreateWriter(VideoCaptureAPIs api) const; |
||||||
|
Ptr<IVideoCapture> createCapture(const std::string &filename, int camera) const CV_OVERRIDE; |
||||||
|
Ptr<IVideoWriter> createWriter(const std::string &filename, int fourcc, double fps, const cv::Size &sz, bool isColor) const CV_OVERRIDE; |
||||||
|
}; |
||||||
|
|
||||||
|
} // cv::
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BACKEND_HPP_DEFINED
|
@ -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
|
@ -0,0 +1,19 @@ |
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifdef BUILD_PLUGIN |
||||||
|
|
||||||
|
#include "plugin_api.hpp" |
||||||
|
#include "opencv2/core/version.hpp" |
||||||
|
|
||||||
|
void cv_get_version(int & major, int & minor, int & patch, int & api, int & abi) |
||||||
|
{ |
||||||
|
major = CV_VERSION_MAJOR; |
||||||
|
minor = CV_VERSION_MINOR; |
||||||
|
patch = CV_VERSION_REVISION; |
||||||
|
api = API_VERSION; |
||||||
|
abi = ABI_VERSION; |
||||||
|
} |
||||||
|
|
||||||
|
#endif // BUILD_PLUGIN
|
@ -0,0 +1,71 @@ |
|||||||
|
// 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 |
||||||
|
|
||||||
|
// increase for backward-compatible changes, e.g. add new function
|
||||||
|
// Main API <= Plugin API -> plugin is compatible
|
||||||
|
#define API_VERSION 1 |
||||||
|
// increase for incompatible changes, e.g. remove function argument
|
||||||
|
// Main ABI == Plugin ABI -> plugin is compatible
|
||||||
|
#define ABI_VERSION 1 |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
extern "C" { |
||||||
|
#endif |
||||||
|
|
||||||
|
// common
|
||||||
|
typedef void cv_get_version_t(int & major, int & minor, int & patch, int & api, int & abi); |
||||||
|
typedef int cv_domain_t(); |
||||||
|
|
||||||
|
// capture
|
||||||
|
typedef bool cv_open_capture_t(const char * filename, int camera_index, void * &handle); |
||||||
|
typedef bool cv_get_cap_prop_t(void * handle, int prop, double & val); |
||||||
|
typedef bool cv_set_cap_prop_t(void * handle, int prop, double val); |
||||||
|
typedef bool cv_grab_t(void * handle); |
||||||
|
// callback function type
|
||||||
|
typedef bool cv_retrieve_cb_t(unsigned char * data, int step, int width, int height, int cn, void * userdata); |
||||||
|
typedef bool cv_retrieve_t(void * handle, int idx, cv_retrieve_cb_t * cb, void * userdata); |
||||||
|
typedef bool cv_release_capture_t(void * handle); |
||||||
|
|
||||||
|
// writer
|
||||||
|
typedef bool cv_open_writer_t(const char * filename, int fourcc, double fps, int width, int height, int isColor, void * &handle); |
||||||
|
typedef bool cv_get_wri_prop_t(void * handle, int prop, double & val); |
||||||
|
typedef bool cv_set_wri_prop_t(void * handle, int prop, double val); |
||||||
|
typedef bool cv_write_t(void * handle, const unsigned char * data, int step, int width, int height, int cn); |
||||||
|
typedef bool cv_release_writer_t(void * handle); |
||||||
|
|
||||||
|
#ifdef BUILD_PLUGIN |
||||||
|
|
||||||
|
#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 |
||||||
|
|
||||||
|
CV_PLUGIN_EXPORTS cv_get_version_t cv_get_version; |
||||||
|
CV_PLUGIN_EXPORTS cv_domain_t cv_domain; |
||||||
|
|
||||||
|
CV_PLUGIN_EXPORTS cv_open_capture_t cv_open_capture; |
||||||
|
CV_PLUGIN_EXPORTS cv_get_cap_prop_t cv_get_cap_prop; |
||||||
|
CV_PLUGIN_EXPORTS cv_set_cap_prop_t cv_set_cap_prop; |
||||||
|
CV_PLUGIN_EXPORTS cv_grab_t cv_grab; |
||||||
|
CV_PLUGIN_EXPORTS cv_retrieve_t cv_retrieve; |
||||||
|
CV_PLUGIN_EXPORTS cv_release_capture_t cv_release_capture; |
||||||
|
|
||||||
|
CV_PLUGIN_EXPORTS cv_open_writer_t cv_open_writer; |
||||||
|
CV_PLUGIN_EXPORTS cv_get_wri_prop_t cv_get_wri_prop; |
||||||
|
CV_PLUGIN_EXPORTS cv_set_wri_prop_t cv_set_wri_prop; |
||||||
|
CV_PLUGIN_EXPORTS cv_write_t cv_write; |
||||||
|
CV_PLUGIN_EXPORTS cv_release_writer_t cv_release_writer; |
||||||
|
|
||||||
|
#endif |
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
#endif // PLUGIN_API_HPP
|
@ -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('H', '2', '6', '4'); |
||||||
|
|
||||||
|
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>::
|
@ -1,447 +1,202 @@ |
|||||||
/*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
|
||||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
// of this distribution and at http://opencv.org/license.html.
|
||||||
//
|
|
||||||
// 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" |
#include "test_precomp.hpp" |
||||||
|
|
||||||
namespace opencv_test { namespace { |
|
||||||
|
|
||||||
#ifdef HAVE_FFMPEG |
|
||||||
|
|
||||||
using namespace std; |
using namespace std; |
||||||
|
|
||||||
static const char* AVI_EXT = ".avi"; |
namespace opencv_test { namespace { |
||||||
static const char* MP4_EXT = ".mp4"; |
|
||||||
|
|
||||||
class CV_FFmpegWriteBigVideoTest : public cvtest::BaseTest |
static inline long long getFileSize(const string &filename) |
||||||
{ |
{ |
||||||
struct TestFormatEntry { |
ifstream f(filename, ios_base::in | ios_base::binary); |
||||||
int tag; |
f.seekg(0, ios_base::end); |
||||||
const char* ext; |
return f.tellg(); |
||||||
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 |
typedef tuple<string, string, Size> FourCC_Ext_Size; |
||||||
{ |
typedef testing::TestWithParam< FourCC_Ext_Size > videoio_ffmpeg; |
||||||
double fps = fps0; |
|
||||||
Size frame_s = Size(img_c, img_r); |
|
||||||
|
|
||||||
if( tag == VideoWriter::fourcc('H', '2', '6', '1') ) |
TEST_P(videoio_ffmpeg, write_big) |
||||||
frame_s = Size(352, 288); |
{ |
||||||
else if( tag == VideoWriter::fourcc('H', '2', '6', '3') ) |
if (!videoio_registry::hasBackend(CAP_FFMPEG)) |
||||||
frame_s = Size(704, 576); |
throw SkipTestException("FFmpeg backend was not found"); |
||||||
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') ) |
const string fourcc = get<0>(GetParam()); |
||||||
{ |
const string ext = get<1>(GetParam()); |
||||||
frame_s = Size(720, 576); |
const Size sz = get<2>(GetParam()); |
||||||
fps = 25; |
const double time_sec = 1; |
||||||
} |
const double fps = 25; |
||||||
|
|
||||||
VideoWriter writer(filename, CAP_FFMPEG, tag, fps, frame_s); |
ostringstream buf; |
||||||
|
buf << "write_big_" << fourcc << "." << ext; |
||||||
|
const string filename = tempfile(buf.str().c_str()); |
||||||
|
|
||||||
if (writer.isOpened() == false) |
VideoWriter writer(filename, CAP_FFMPEG, fourccFromString(fourcc), fps, sz); |
||||||
|
if (ext == "mp4" && fourcc == "H264" && !writer.isOpened()) |
||||||
{ |
{ |
||||||
fprintf(stderr, "\n\nFile name: %s\n", filename.c_str()); |
throw cvtest::SkipTestException("H264/mp4 codec is not supported - SKIP"); |
||||||
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 |
ASSERT_TRUE(writer.isOpened()); |
||||||
{ |
Mat img(sz, CV_8UC3, Scalar::all(0)); |
||||||
Mat img(frame_s, CV_8UC3, Scalar::all(0)); |
const int coeff = cvRound(min(sz.width, sz.height)/(fps * time_sec)); |
||||||
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++ ) |
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, |
||||||
rectangle(img, Point2i(coeff * i, coeff * i), Point2i(coeff * (i + 1), coeff * (i + 1)), |
Point2i(coeff * i, coeff * i), |
||||||
Scalar::all(255 * (1.0 - static_cast<double>(i) / (fps * time_sec * 2) )), -1); |
Point2i(coeff * (i + 1), coeff * (i + 1)), |
||||||
|
Scalar::all(255 * (1.0 - static_cast<double>(i) / (fps * time_sec * 2))), |
||||||
|
-1); |
||||||
writer << img; |
writer << img; |
||||||
} |
} |
||||||
|
|
||||||
writer.release(); |
writer.release(); |
||||||
long int sz = getFileSize(filename); |
EXPECT_GT(getFileSize(filename), 8192); |
||||||
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()); |
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(); } |
static const Size bigSize(4096, 4096); |
||||||
|
|
||||||
class CV_FFmpegReadImageTest : public cvtest::BaseTest |
const FourCC_Ext_Size entries[] = |
||||||
{ |
{ |
||||||
public: |
make_tuple("", "avi", bigSize), |
||||||
void run(int) |
make_tuple("DX50", "avi", bigSize), |
||||||
{ |
make_tuple("FLV1", "avi", bigSize), |
||||||
try |
make_tuple("H261", "avi", Size(352, 288)), |
||||||
{ |
make_tuple("H263", "avi", Size(704, 576)), |
||||||
string filename = ts->get_data_path() + "readwrite/ordinary.bmp"; |
make_tuple("I420", "avi", bigSize), |
||||||
VideoCapture cap(filename, CAP_FFMPEG); |
make_tuple("MJPG", "avi", bigSize), |
||||||
Mat img0 = imread(filename, 1); |
make_tuple("mp4v", "avi", bigSize), |
||||||
Mat img, img_next; |
make_tuple("MPEG", "avi", Size(720, 576)), |
||||||
cap >> img; |
make_tuple("XVID", "avi", bigSize), |
||||||
cap >> img_next; |
make_tuple("H264", "mp4", Size(4096, 2160)) |
||||||
|
|
||||||
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(); } |
INSTANTIATE_TEST_CASE_P(videoio, videoio_ffmpeg, testing::ValuesIn(entries)); |
||||||
|
|
||||||
#endif |
|
||||||
|
|
||||||
#if defined(HAVE_FFMPEG) |
|
||||||
|
|
||||||
//////////////////////////////// Parallel VideoWriters and VideoCaptures ////////////////////////////////////
|
//==========================================================================
|
||||||
|
|
||||||
class CreateVideoWriterInvoker : |
TEST(videoio_ffmpeg, image) |
||||||
public ParallelLoopBody |
|
||||||
{ |
{ |
||||||
public: |
if (!videoio_registry::hasBackend(CAP_FFMPEG)) |
||||||
const static Size FrameSize; |
throw SkipTestException("FFmpeg backend was not found"); |
||||||
static std::string TmpDirectory; |
|
||||||
|
|
||||||
CreateVideoWriterInvoker(std::vector<VideoWriter*>& _writers, std::vector<std::string>& _files) : |
const string filename = findDataFile("readwrite/ordinary.bmp"); |
||||||
writers(_writers), files(_files) |
Mat image = imread(filename, IMREAD_COLOR); |
||||||
{ |
ASSERT_FALSE(image.empty()); |
||||||
} |
VideoCapture cap(filename, CAP_FFMPEG); |
||||||
|
ASSERT_TRUE(cap.isOpened()); |
||||||
virtual void operator() (const Range& range) const CV_OVERRIDE |
Mat frame1, frame2; |
||||||
{ |
cap >> frame1 >> frame2; |
||||||
for (int i = range.start; i != range.end; ++i) |
ASSERT_FALSE(frame1.empty()); |
||||||
{ |
ASSERT_TRUE(frame2.empty()); |
||||||
std::ostringstream stream; |
ASSERT_EQ(0, cvtest::norm(image, frame1, NORM_INF)); |
||||||
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 : |
static void generateFrame(Mat &frame, unsigned int i, const Point ¢er, const Scalar &color) |
||||||
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); |
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); |
||||||
|
} |
||||||
|
|
||||||
std::string text = to_string(i); |
TEST(videoio_ffmpeg, parallel) |
||||||
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); |
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
|
||||||
virtual void operator() (const Range& range) const CV_OVERRIDE |
|
||||||
{ |
{ |
||||||
for (int j = range.start; j < range.end; ++j) |
vector< Ptr<VideoWriter> > writers(NUM); |
||||||
|
auto makeWriters = [&](const Range &r) |
||||||
{ |
{ |
||||||
VideoWriter* writer = writers->operator[](j); |
for (int i = r.start; i != r.end; ++i) |
||||||
CV_Assert(writer != NULL); |
writers[i] = makePtr<VideoWriter>(files[i], |
||||||
CV_Assert(writer->isOpened()); |
CAP_FFMPEG, |
||||||
|
VideoWriter::fourcc('X','V','I','D'), |
||||||
Mat frame(CreateVideoWriterInvoker::FrameSize, CV_8UC3); |
25.0f, |
||||||
for (unsigned int i = 0; i < FrameCount; ++i) |
sz); |
||||||
{ |
}; |
||||||
GenerateFrame(frame, i); |
parallel_for_(R, makeWriters, GRAN); |
||||||
writer->operator<< (frame); |
for(int i = 0; i < NUM; ++i) |
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected: |
|
||||||
static std::string to_string(unsigned int i) |
|
||||||
{ |
{ |
||||||
std::stringstream stream(std::ios::out); |
ASSERT_TRUE(writers[i]); |
||||||
stream << "frame #" << i; |
ASSERT_TRUE(writers[i]->isOpened()); |
||||||
return stream.str(); |
|
||||||
} |
} |
||||||
|
auto writeFrames = [&](const Range &r) |
||||||
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) |
|
||||||
{ |
{ |
||||||
} |
for (int j = r.start; j < r.end; ++j) |
||||||
|
|
||||||
virtual void operator() (const Range& range) const CV_OVERRIDE |
|
||||||
{ |
{ |
||||||
for (int i = range.start; i != range.end; ++i) |
Mat frame(sz, CV_8UC3); |
||||||
|
for (int i = 0; i < frameNum; ++i) |
||||||
{ |
{ |
||||||
readers->operator[](i) = new VideoCapture(files->operator[](i), CAP_FFMPEG); |
generateFrame(frame, i, center, color); |
||||||
CV_Assert(readers->operator[](i)->isOpened()); |
writers[j]->write(frame); |
||||||
} |
} |
||||||
} |
} |
||||||
private: |
}; |
||||||
std::vector<VideoCapture*>* readers; |
parallel_for_(R, writeFrames, GRAN); |
||||||
const std::vector<std::string>* files; |
} |
||||||
}; |
// Read videos
|
||||||
|
|
||||||
class ReadImageAndTest : |
|
||||||
public ParallelLoopBody |
|
||||||
{ |
|
||||||
public: |
|
||||||
ReadImageAndTest(const std::vector<VideoCapture*>& _readers, cvtest::TS* _ts) : |
|
||||||
ParallelLoopBody(), readers(&_readers), ts(_ts) |
|
||||||
{ |
{ |
||||||
|
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) |
||||||
virtual void operator() (const Range& range) const CV_OVERRIDE |
|
||||||
{ |
{ |
||||||
for (int j = range.start; j < range.end; ++j) |
for (int j = r.start; j < r.end; ++j) |
||||||
{ |
{ |
||||||
VideoCapture* capture = readers->operator[](j); |
Mat reference(sz, CV_8UC3); |
||||||
CV_Assert(capture != NULL); |
for (int i = 0; i < frameNum; ++i) |
||||||
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; |
Mat actual; |
||||||
(*capture) >> actual; |
EXPECT_TRUE(readers[j]->read(actual)); |
||||||
|
EXPECT_FALSE(actual.empty()); |
||||||
WriteVideo_Invoker::GenerateFrame(reference, i); |
generateFrame(reference, i, center, color); |
||||||
|
EXPECT_EQ(reference.size(), actual.size()); |
||||||
EXPECT_EQ(reference.cols, actual.cols); |
|
||||||
EXPECT_EQ(reference.rows, actual.rows); |
|
||||||
EXPECT_EQ(reference.depth(), actual.depth()); |
EXPECT_EQ(reference.depth(), actual.depth()); |
||||||
EXPECT_EQ(reference.channels(), actual.channels()); |
EXPECT_EQ(reference.channels(), actual.channels()); |
||||||
|
EXPECT_GE(cvtest::PSNR(actual, reference), 35.0) << "cap" << j << ", frame " << i; |
||||||
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; |
|
||||||
} |
|
||||||
} |
} |
||||||
} |
} |
||||||
|
}; |
||||||
|
parallel_for_(R, readFrames, GRAN); |
||||||
} |
} |
||||||
|
// Remove files
|
||||||
static bool next; |
for(int i = 0; i < NUM; ++i) |
||||||
|
|
||||||
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()); |
remove(files[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; |
|
||||||
} |
} |
||||||
|
|
||||||
#endif |
|
||||||
}} // namespace
|
}} // namespace
|
||||||
|
@ -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
|
|
Loading…
Reference in new issue