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