diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index c8c1e1c1e9..373df4b797 100644 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -13,3 +13,6 @@ endif() if(WITH_TIFF AND NOT TIFF_FOUND) add_subdirectory(libtiff) endif() +if(WIN32) + add_subdirectory(ffmpeg) +endif() diff --git a/3rdparty/ffmpeg/CMakeLists.txt b/3rdparty/ffmpeg/CMakeLists.txt new file mode 100644 index 0000000000..b8e7f092e6 --- /dev/null +++ b/3rdparty/ffmpeg/CMakeLists.txt @@ -0,0 +1,19 @@ +project(opencv_ffmpeg) + +if(MSVC64 OR MINGW64) + set(FFMPEG_SUFFIX _64) +endif() + +set(module_name "${CMAKE_CURRENT_SOURCE_DIR}/opencv_ffmpeg${FFMPEG_SUFFIX}.dll") + +get_target_property(bin_dir opencv_core LOCATION) +get_filename_component(bin_dir ${bin_dir} PATH) + +message(STATUS "ffmpeg output dir: ${bin_dir}") + +add_custom_target(opencv_ffmpeg ALL + COMMAND ${CMAKE_COMMAND} -E copy + ${module_name} ${bin_dir} + COMMENT "Copying ${module_name} to the output directory") + +install(FILES ${module_name} DESTINATION bin COMPONENT main) diff --git a/3rdparty/ffmpeg/ffopencv.c b/3rdparty/ffmpeg/ffopencv.c new file mode 100644 index 0000000000..b412e90071 --- /dev/null +++ b/3rdparty/ffmpeg/ffopencv.c @@ -0,0 +1 @@ +#include "cap_ffmpeg_impl.hpp" diff --git a/3rdparty/ffmpeg/make.bat b/3rdparty/ffmpeg/make.bat new file mode 100644 index 0000000000..6c965c57cb --- /dev/null +++ b/3rdparty/ffmpeg/make.bat @@ -0,0 +1,2 @@ +gcc -Wall -shared -o opencv_ffmpeg.dll -O2 -x c++ -I../include -I../include/ffmpeg_ -I../../modules/highgui/src ffopencv.c -L../lib -lavformat -lavcodec -lavdevice -lswscale -lavutil -lwsock32 +set path=c:\apps\mingw64\bin;%path% & gcc -Wall -shared -o opencv_ffmpeg_64.dll -O2 -x c++ -I../include -I../include/ffmpeg_ -I../../modules/highgui/src ffopencv.c -L../lib -lavformat64 -lavcodec64 -lavdevice64 -lswscale64 -lavutil64 -lavcore64 -lwsock32 \ No newline at end of file diff --git a/3rdparty/ffmpeg/opencv_ffmpeg.dll b/3rdparty/ffmpeg/opencv_ffmpeg.dll new file mode 100644 index 0000000000..8da9a659c2 Binary files /dev/null and b/3rdparty/ffmpeg/opencv_ffmpeg.dll differ diff --git a/3rdparty/ffmpeg/opencv_ffmpeg_64.dll b/3rdparty/ffmpeg/opencv_ffmpeg_64.dll new file mode 100644 index 0000000000..2ca3af5486 Binary files /dev/null and b/3rdparty/ffmpeg/opencv_ffmpeg_64.dll differ diff --git a/3rdparty/ffmpeg/readme.txt b/3rdparty/ffmpeg/readme.txt new file mode 100644 index 0000000000..3bd63ac974 --- /dev/null +++ b/3rdparty/ffmpeg/readme.txt @@ -0,0 +1,9 @@ +The build script is to be fixed. +Right now it assumes that 32-bit MinGW is in the system path and +64-bit mingw is installed to c:\Apps\MinGW64. + +It is important that gcc is used, not g++! +Otherwise the produced DLL will likely be dependent on libgcc_s_dw2-1.dll or similar DLL. +While we want to make the DLLs with minimum dependencies: Win32 libraries + msvcrt.dll. + +ffopencv.c is really a C++ source, hence -x c++ is used. diff --git a/CMakeLists.txt b/CMakeLists.txt index 560bbb2185..d0c229f1b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,10 +75,16 @@ endif() # ---------------------------------------------------------------------------- # Build static or dynamic libs? -# Default: dynamic libraries: +# Default: dynamic libraries # ---------------------------------------------------------------------------- set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries (.dll/.so) instead of static ones (.lib/.a)") +# ---------------------------------------------------------------------------- +# Include debug info into debug libs? +# Default: yes +# ---------------------------------------------------------------------------- +set(BUILD_WITH_DEBUG_INFO ON CACHE BOOL "Include debug info into debug libs") + # ---------------------------------------------------------------------------- # Current version number: # ---------------------------------------------------------------------------- @@ -106,7 +112,7 @@ endif() # Use statically or dynamically linked CRT? # Default: dynamic # ---------------------------------------------------------------------------- -if(MSVC AND NOT BUILD_SHARED_LIBS) +if(WIN32 AND NOT BUILD_SHARED_LIBS) option (BUILD_WITH_STATIC_CRT "Enables use of staticaly linked CRT" OFF) endif() @@ -147,10 +153,26 @@ if(MSVC) endforeach(flag_var) endif(BUILD_WITH_STATIC_CRT) + + if(NOT BUILD_WITH_DEBUG_INFO) + string(REPLACE "/debug" "" CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}") + string(REPLACE "/DEBUG" "" CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}") + string(REPLACE "/INCREMENTAL" "/INCREMENTAL:NO" CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}") + + string(REPLACE "/debug" "" CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG}") + string(REPLACE "/DEBUG" "" CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG}") + string(REPLACE "/INCREMENTAL" "/INCREMENTAL:NO" CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG}") + + string(REPLACE "/debug" "" CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}") + string(REPLACE "/DEBUG" "" CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}") + string(REPLACE "/INCREMENTAL" "/INCREMENTAL:NO" CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}") + + string(REPLACE "/Zi" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") + string(REPLACE "/Zi" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") + endif() + endif(MSVC) - - # ---------------------------------------------------------------------------- # Variables for cvconfig.h.cmake # ---------------------------------------------------------------------------- @@ -951,7 +973,9 @@ if(MSVC) # set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} /D _BIND_TO_CURRENT_CRT_VERSION=1 /D _BIND_TO_CURRENT_VCLIBS_VERSION=1") #endif() - set(EXTRA_EXE_LINKER_FLAGS_RELEASE "${EXTRA_EXE_LINKER_FLAGS_RELEASE} /debug") + if(BUILD_WITH_DEBUG_INFO) + set(EXTRA_EXE_LINKER_FLAGS_RELEASE "${EXTRA_EXE_LINKER_FLAGS_RELEASE} /debug") + endif() #if(ENABLE_OPENMP) # set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} /openmp") @@ -959,7 +983,9 @@ if(MSVC) # Remove unreferenced functions: function level linking set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} /Gy") - set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} /Zi") + if(BUILD_WITH_DEBUG_INFO) + set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} /Zi") + endif() endif() if(CMAKE_COMPILER_IS_GNUCXX) @@ -967,6 +993,10 @@ if(CMAKE_COMPILER_IS_GNUCXX) # High level of warnings. set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} -Wall") + if(BUILD_WITH_STATIC_CRT) + set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} -static-libstdc++") + endif() + # The -Wno-long-long is required in 64bit systems when including sytem headers. if(${CMAKE_SYSTEM_PROCESSOR} MATCHES x86_64*) set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} -Wno-long-long") @@ -1065,16 +1095,22 @@ if(CMAKE_COMPILER_IS_GNUCXX) #endif() set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -DNDEBUG") - set(EXTRA_C_FLAGS_DEBUG "${EXTRA_C_FLAGS_DEBUG} -O0 -ggdb3 -DDEBUG -D_DEBUG") + set(EXTRA_C_FLAGS_DEBUG "${EXTRA_C_FLAGS_DEBUG} -O0 -DDEBUG -D_DEBUG") + if(BUILD_WITH_DEBUG_INFO) + set(EXTRA_C_FLAGS_DEBUG "${EXTRA_C_FLAGS_DEBUG} -ggdb3") + endif() endif() if(MSVC) - if(ENABLE_SSE) - set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} /arch:SSE") - endif() - if(ENABLE_SSE2) - set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} /arch:SSE2") + # 64-bit MSVC compiler uses SSE/SSE2 by default + if(NOT MSVC64) + if(ENABLE_SSE) + set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} /arch:SSE") + endif() + if(ENABLE_SSE2) + set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} /arch:SSE2") + endif() endif() if(ENABLE_SSE3) set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} /arch:SSE3") diff --git a/Package.cmake.in b/Package.cmake.in index 473c534c96..f97868d241 100644 --- a/Package.cmake.in +++ b/Package.cmake.in @@ -67,6 +67,7 @@ set(CPACK_SOURCE_IGNORE_FILES if(NOT WIN32) set(CPACK_SOURCE_IGNORE_FILES "/lib/" + "\\\\.dll$" "${CPACK_SOURCE_IGNORE_FILES}") endif() diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 9e01bb3c7d..040b81e21c 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -12,12 +12,6 @@ add_subdirectory(core) add_subdirectory(features2d) add_subdirectory(flann) -if(MSVC OR MINGW) - if(NOT BUILD_WITH_STATIC_CRT) - add_subdirectory(ffmpeg) - endif() -endif() - if(BUILD_TESTS) add_subdirectory(ts) endif() diff --git a/modules/ffmpeg/CMakeLists.txt b/modules/ffmpeg/CMakeLists.txt deleted file mode 100644 index 999699c8d0..0000000000 --- a/modules/ffmpeg/CMakeLists.txt +++ /dev/null @@ -1,66 +0,0 @@ -project(opencv_ffmpeg) - -include_directories("${CMAKE_CURRENT_SOURCE_DIR}") -include_directories( - "${CMAKE_SOURCE_DIR}/3rdparty/include" - "${CMAKE_SOURCE_DIR}/3rdparty/include/ffmpeg_" - ) -include_directories( - "${CMAKE_SOURCE_DIR}/modules/highgui/src" - "${CMAKE_SOURCE_DIR}/modules/core/include" - "${CMAKE_SOURCE_DIR}/modules/imgproc/include" - "${CMAKE_SOURCE_DIR}/modules/highgui/include" - ) -link_directories("${CMAKE_SOURCE_DIR}/3rdparty/lib") - -set(the_target opencv_ffmpeg) -add_library(${the_target} SHARED ffopencv.cpp ffopencv.h) - -add_dependencies(${the_target} opencv_core) -target_link_libraries(${the_target} opencv_core) - -if (NOT MSVC) - #target_link_libraries(${the_target} - # ${CMAKE_SOURCE_DIR}/3rdparty/lib/libgcc_.a - # ${CMAKE_SOURCE_DIR}/3rdparty/lib/libmingwex_.a) - if(WIN32 AND MINGW64) - target_link_libraries(${the_target} ${CMAKE_SOURCE_DIR}/3rdparty/lib/libavformat64.a - ${CMAKE_SOURCE_DIR}/3rdparty/lib/libavcodec64.a - ${CMAKE_SOURCE_DIR}/3rdparty/lib/libavdevice64.a - ${CMAKE_SOURCE_DIR}/3rdparty/lib/libavutil64.a - ${CMAKE_SOURCE_DIR}/3rdparty/lib/libswscale64.a - ${CMAKE_SOURCE_DIR}/3rdparty/lib/libavcore64.a - libws2_32.a) - else() - target_link_libraries(${the_target} ${CMAKE_SOURCE_DIR}/3rdparty/lib/libavformat.a - ${CMAKE_SOURCE_DIR}/3rdparty/lib/libavcodec.a - ${CMAKE_SOURCE_DIR}/3rdparty/lib/libavutil.a - ${CMAKE_SOURCE_DIR}/3rdparty/lib/libswscale.a - ${CMAKE_SOURCE_DIR}/3rdparty/lib/libwsock32_.a) - endif() -endif () - -set_target_properties(${the_target} PROPERTIES - DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" - VERSION ${OPENCV_VERSION} - OUTPUT_NAME "${the_target}${OPENCV_DLLVERSION}" - DEFINE_SYMBOL "CVAPI_EXPORTS" - ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH} - RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} - ) - -if(ENABLE_SOLUTION_FOLDERS) - set_target_properties(${the_target} PROPERTIES FOLDER "modules") -endif() - -if (MSVC) - set_target_properties(${the_target} PROPERTIES - LINK_FLAGS "/NODEFAULTLIB:libc /DEBUG" - ) -endif () - -install(TARGETS ${the_target} - RUNTIME DESTINATION bin COMPONENT main - ARCHIVE DESTINATION lib COMPONENT main - LIBRARY DESTINATION lib COMPONENT main - ) diff --git a/modules/ffmpeg/ffopencv.cpp b/modules/ffmpeg/ffopencv.cpp deleted file mode 100644 index 98e4c6b420..0000000000 --- a/modules/ffmpeg/ffopencv.cpp +++ /dev/null @@ -1,616 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2000, Intel Corporation, all rights reserved. -// Third party copyrights are property of their respective owners. -// -//M*/ - -/****************************************************************************************\ - Licensing notice: - As the project ffopencv links ffmpeg libraries statically, its source code - (ffopencv.cpp and ffopencv.h, but not cvcap_ffmpeg.cpp (!)), as well as the produced - ffopencv*.dll are subjects to the Lesser GNU Public License: - ----------------------------------------------------------- - - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - -\****************************************************************************************/ - -#define CV_NO_VIDEO_CAPTURE_CPP_API 1 - -#if _MSC_VER >= 1200 -#pragma warning( disable: 4251 ) -#endif - -#include "precomp.hpp" -#include "ffopencv.h" - -#if defined _MSC_VER && _MSC_VER >= 1200 - -#if !defined(_MT) || defined(_DLL) || defined(_MSC_VER) -extern "C" { __declspec(dllexport) unsigned int __lc_codepage = 0; } -#endif -#ifdef _M_X64 -#pragma comment(lib, "libgcc64.a") -#pragma comment(lib, "libmingwex64.a") -#else -#pragma comment(lib, "libgcc_.a") -#pragma comment(lib, "libmingwex_.a") -#pragma comment(lib, "libcoldname_.a") -#endif - -#ifdef _M_X64 -#pragma comment(lib, "libavformat64.a") -#pragma comment(lib, "libavcodec64.a") -#pragma comment(lib, "libavutil64.a") -#pragma comment(lib, "libavcore64.a") -#pragma comment(lib, "libswscale64.a") -#pragma comment(lib, "libwsock3264.a") -#else -#pragma comment(lib, "libavformat.a") -#pragma comment(lib, "libavcodec.a") -#pragma comment(lib, "libavutil.a") -#pragma comment(lib, "libswscale.a") -#pragma comment(lib, "libwsock32_.a") -#endif - - -#endif - -#undef __STDC_CONSTANT_MACROS -#define __STDC_CONSTANT_MACROS 1 - -#undef snprintf -#define snprintf _snprintf - -#ifdef _MSC_VER -#include "msc_stdint.h" -#endif -#include "errno.h" - -#include "cap_ffmpeg.cpp" - -void cvReleaseCapture_FFMPEG(CvCapture** capture) -{ - if( capture && *capture ) - { - delete *capture; - *capture = 0; - } -} - -int cvSetCaptureProperty_FFMPEG(CvCapture* capture, int prop_id, double value) -{ - return capture->setProperty(prop_id, value); -} - -double cvGetCaptureProperty_FFMPEG(CvCapture* capture, int prop_id) -{ - return capture->getProperty(prop_id); -} - -int cvGrabFrame_FFMPEG(CvCapture* capture) -{ - return capture->grabFrame(); -} - -IplImage* cvRetrieveFrame_FFMPEG(CvCapture* capture, int streamIdx) -{ - return capture->retrieveFrame(streamIdx); -} - -void cvReleaseVideoWriter_FFMPEG( CvVideoWriter** writer ) -{ - if( writer && *writer ) - { - delete *writer; - *writer = 0; - } -} - -int cvWriteFrame_FFMPEG( CvVideoWriter* writer, const IplImage* image ) -{ - return writer->writeFrame(image); -} - diff --git a/modules/ffmpeg/ffopencv.h b/modules/ffmpeg/ffopencv.h deleted file mode 100644 index b84c047ddd..0000000000 --- a/modules/ffmpeg/ffopencv.h +++ /dev/null @@ -1,546 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2000, Intel Corporation, all rights reserved. -// Third party copyrights are property of their respective owners. -// -//M*/ - -/****************************************************************************************\ - Licensing notice: - As the project ffopencv links ffmpeg libraries statically, its source code - (ffopencv.cpp and ffopencv.h, but not cvcap_ffmpeg.cpp (!)), as well as the produced - ffopencv*.dll are subjects to the Lesser GNU Public License: - ----------------------------------------------------------- - - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - -\****************************************************************************************/ - -#ifndef _FFOPENCV_H_ -#define _FFOPENCV_H_ - -#define CV_NO_CVV_IMAGE - -#include "highgui.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -CVAPI(CvCapture*) cvCreateFileCapture_FFMPEG( const char* filename ); -CVAPI(void) cvReleaseCapture_FFMPEG(CvCapture** capture); -CVAPI(int) cvSetCaptureProperty_FFMPEG(CvCapture* capture, int prop_id, double value); -CVAPI(double) cvGetCaptureProperty_FFMPEG(CvCapture* capture, int prop_id); -CVAPI(int) cvGrabFrame_FFMPEG(CvCapture* capture); -CVAPI(IplImage*) cvRetrieveFrame_FFMPEG(CvCapture* capture, int); -CVAPI(CvVideoWriter*) cvCreateVideoWriter_FFMPEG( const char * filename, int fourcc, - double fps, CvSize frameSize, int is_color ); -CVAPI(void) cvReleaseVideoWriter_FFMPEG( CvVideoWriter** writer ); -CVAPI(int) cvWriteFrame_FFMPEG( CvVideoWriter* writer, const IplImage* image ); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _FFOPENCV_H_ */ diff --git a/modules/highgui/CMakeLists.txt b/modules/highgui/CMakeLists.txt index a407431cf7..2e12aa6285 100644 --- a/modules/highgui/CMakeLists.txt +++ b/modules/highgui/CMakeLists.txt @@ -82,6 +82,7 @@ source_group("Src\\grfmts" FILES ${grfmt_hdrs} ${grfmt_srcs}) set(highgui_srcs src/cap.cpp src/cap_images.cpp + src/cap_ffmpeg.cpp src/loadsave.cpp src/precomp.cpp src/utils.cpp @@ -118,7 +119,7 @@ if(WIN32) if(NOT HAVE_QT) set(highgui_srcs ${highgui_srcs} src/window_w32.cpp) endif() - set(highgui_srcs ${highgui_srcs} src/cap_vfw.cpp src/cap_cmu.cpp src/cap_w32.cpp src/cap_dshow.cpp) + set(highgui_srcs ${highgui_srcs} src/cap_vfw.cpp src/cap_cmu.cpp src/cap_dshow.cpp) if(HAVE_MIL) set(highgui_srcs ${highgui_srcs} src/cap_mil.cpp) endif() @@ -144,7 +145,6 @@ if(UNIX) endif() if(HAVE_FFMPEG) - set(highgui_srcs ${highgui_srcs} src/cap_ffmpeg.cpp) if(BZIP2_LIBRARIES) set(HIGHGUI_LIBRARIES ${HIGHGUI_LIBRARIES} ${BZIP2_LIBRARIES}) endif() diff --git a/modules/highgui/src/cap.cpp b/modules/highgui/src/cap.cpp index 091482206f..2fab8c969b 100644 --- a/modules/highgui/src/cap.cpp +++ b/modules/highgui/src/cap.cpp @@ -279,16 +279,9 @@ CV_IMPL CvCapture * cvCreateFileCapture (const char * filename) { CvCapture * result = 0; - #ifdef WIN32 if (! result) - result = cvCreateFileCapture_Win32 (filename); - #endif + result = cvCreateFileCapture_FFMPEG_proxy (filename); - #ifdef HAVE_FFMPEG - if (! result) - result = cvCreateFileCapture_FFMPEG (filename); - #endif - #ifdef HAVE_XINE if (! result) result = cvCreateFileCapture_XINE (filename); @@ -324,20 +317,14 @@ CV_IMPL CvVideoWriter* cvCreateVideoWriter( const char* filename, int fourcc, if(!fourcc || !fps) result = cvCreateVideoWriter_Images(filename); - #ifdef WIN32 if(!result) - result = cvCreateVideoWriter_Win32(filename, fourcc, fps, frameSize, is_color); - #endif + result = cvCreateVideoWriter_FFMPEG_proxy (filename, fourcc, fps, frameSize, is_color); /* #ifdef HAVE_XINE if(!result) result = cvCreateVideoWriter_XINE(filename, fourcc, fps, frameSize, is_color); #endif */ - #ifdef HAVE_FFMPEG - if(!result) - result = cvCreateVideoWriter_FFMPEG(filename, fourcc, fps, frameSize, is_color); - #endif #ifdef HAVE_QUICKTIME if(!result) diff --git a/modules/highgui/src/cap_ffmpeg.cpp b/modules/highgui/src/cap_ffmpeg.cpp index ec44548fda..b1c3f07e76 100644 --- a/modules/highgui/src/cap_ffmpeg.cpp +++ b/modules/highgui/src/cap_ffmpeg.cpp @@ -41,1338 +41,205 @@ #include "precomp.hpp" -#if defined _MSC_VER && _MSC_VER >= 1200 -#pragma warning( disable: 4244 4510 4512 4610 ) -#endif +#if defined WIN32 || defined _WIN32 +#include "cap_ffmpeg_api.hpp" -extern "C" { -#if !defined(WIN32) || defined(__MINGW32__) -// some versions of FFMPEG assume a C99 compiler, and don't define INT64_C -#if !defined INT64_C || !defined UINT64_C -#define INT64_C -#define UINT64_C -#define __STDC_CONSTANT_MACROS -// force re-inclusion of stdint.h to get INT64_C macro -#undef _STDINT_H -#include -#endif -#include -#endif - -#ifdef WIN32 - #define HAVE_FFMPEG_SWSCALE 1 - #include - #include - #include -#else - -// if the header path is not specified explicitly, let's deduce it -#if !defined HAVE_FFMPEG_AVCODEC_H && !defined HAVE_LIBAVCODEC_AVCODEC_H - -#if defined(HAVE_GENTOO_FFMPEG) - #define HAVE_LIBAVCODEC_AVCODEC_H 1 - #define HAVE_LIBAVFORMAT_AVFORMAT_H 1 - #if defined(HAVE_FFMPEG_SWSCALE) - #define HAVE_LIBSWSCALE_SWSCALE_H 1 - #endif +static HMODULE icvFFOpenCV = 0; #elif defined HAVE_FFMPEG - #define HAVE_FFMPEG_AVCODEC_H 1 - #define HAVE_FFMPEG_AVFORMAT_H 1 - #if defined(HAVE_FFMPEG_SWSCALE) - #define HAVE_FFMPEG_SWSCALE_H 1 - #endif +#include "cap_ffmpeg_impl.hpp" #endif -#endif +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; -#if defined(HAVE_FFMPEG_AVCODEC_H) - #include -#endif -#if defined(HAVE_FFMPEG_AVFORMAT_H) - #include -#endif -#if defined(HAVE_FFMPEG_SWSCALE_H) - #include -#endif - -#if defined(HAVE_LIBAVFORMAT_AVFORMAT_H) - #include -#endif -#if defined(HAVE_LIBAVCODEC_AVCODEC_H) - #include -#endif -#if defined(HAVE_LIBSWSCALE_SWSCALE_H) - #include -#endif - -#endif - -} - -#if defined _MSC_VER && _MSC_VER >= 1200 -#pragma warning( default: 4244 4510 4512 4610 ) -#endif - -#ifdef NDEBUG -#define CV_WARN(message) -#else -#define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__) -#endif - - -#ifndef MKTAG -#define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24)) -#endif - -/* PIX_FMT_RGBA32 macro changed in newer ffmpeg versions */ -#ifndef PIX_FMT_RGBA32 -#define PIX_FMT_RGBA32 PIX_FMT_RGB32 -#endif - - - -char * FOURCC2str( int fourcc ) +static void +icvInitFFMPEG(void) { - char * mystr=(char*)malloc(5); - mystr[0]=(char)((fourcc )&255); - mystr[1]=(char)((fourcc>> 8)&255); - mystr[2]=(char)((fourcc>>16)&255); - mystr[3]=(char)((fourcc>>24)&255); - mystr[4]=0; - return mystr; -} - - -// required to look up the correct codec ID depending on the FOURCC code, -// this is just a snipped from the file riff.c from ffmpeg/libavformat -typedef struct AVCodecTag { - int id; - unsigned int tag; -} AVCodecTag; - -const AVCodecTag codec_bmp_tags[] = { - { CODEC_ID_H264, MKTAG('H', '2', '6', '4') }, - { CODEC_ID_H264, MKTAG('h', '2', '6', '4') }, - { CODEC_ID_H264, MKTAG('X', '2', '6', '4') }, - { CODEC_ID_H264, MKTAG('x', '2', '6', '4') }, - { CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') }, - { CODEC_ID_H264, MKTAG('V', 'S', 'S', 'H') }, - - { CODEC_ID_H263, MKTAG('H', '2', '6', '3') }, - { CODEC_ID_H263P, MKTAG('H', '2', '6', '3') }, - { CODEC_ID_H263I, MKTAG('I', '2', '6', '3') }, /* intel h263 */ - { CODEC_ID_H261, MKTAG('H', '2', '6', '1') }, - - /* added based on MPlayer */ - { CODEC_ID_H263P, MKTAG('U', '2', '6', '3') }, - { CODEC_ID_H263P, MKTAG('v', 'i', 'v', '1') }, - - { CODEC_ID_MPEG4, MKTAG('F', 'M', 'P', '4') }, - { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X') }, - { CODEC_ID_MPEG4, MKTAG('D', 'X', '5', '0') }, - { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') }, - { CODEC_ID_MPEG4, MKTAG('M', 'P', '4', 'S') }, - { CODEC_ID_MPEG4, MKTAG('M', '4', 'S', '2') }, - { CODEC_ID_MPEG4, MKTAG(0x04, 0, 0, 0) }, /* some broken avi use this */ - - /* added based on MPlayer */ - { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', '1') }, - { CODEC_ID_MPEG4, MKTAG('B', 'L', 'Z', '0') }, - { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') }, - { CODEC_ID_MPEG4, MKTAG('U', 'M', 'P', '4') }, - { CODEC_ID_MPEG4, MKTAG('W', 'V', '1', 'F') }, - { CODEC_ID_MPEG4, MKTAG('S', 'E', 'D', 'G') }, - - { CODEC_ID_MPEG4, MKTAG('R', 'M', 'P', '4') }, - - { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '3') }, /* default signature when using MSMPEG4 */ - { CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', '4', '3') }, - - /* added based on MPlayer */ - { CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', 'G', '3') }, - { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '5') }, - { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '6') }, - { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '4') }, - { CODEC_ID_MSMPEG4V3, MKTAG('A', 'P', '4', '1') }, - { CODEC_ID_MSMPEG4V3, MKTAG('C', 'O', 'L', '1') }, - { CODEC_ID_MSMPEG4V3, MKTAG('C', 'O', 'L', '0') }, - - { CODEC_ID_MSMPEG4V2, MKTAG('M', 'P', '4', '2') }, - - /* added based on MPlayer */ - { CODEC_ID_MSMPEG4V2, MKTAG('D', 'I', 'V', '2') }, - - { CODEC_ID_MSMPEG4V1, MKTAG('M', 'P', 'G', '4') }, - - { CODEC_ID_WMV1, MKTAG('W', 'M', 'V', '1') }, - - /* added based on MPlayer */ - { CODEC_ID_WMV2, MKTAG('W', 'M', 'V', '2') }, - { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'd') }, - { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', 'd') }, - { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'l') }, - { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '2', '5') }, - { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '1') }, - { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '2') }, - { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', 'g', '2') }, - { CODEC_ID_MPEG2VIDEO, MKTAG('M', 'P', 'E', 'G') }, - { CODEC_ID_MPEG1VIDEO, MKTAG('P', 'I', 'M', '1') }, - { CODEC_ID_MPEG1VIDEO, MKTAG('V', 'C', 'R', '2') }, - { CODEC_ID_MPEG1VIDEO, 0x10000001 }, - { CODEC_ID_MPEG2VIDEO, 0x10000002 }, - { CODEC_ID_MPEG2VIDEO, MKTAG('D', 'V', 'R', ' ') }, - { CODEC_ID_MPEG2VIDEO, MKTAG('M', 'M', 'E', 'S') }, - { CODEC_ID_MJPEG, MKTAG('M', 'J', 'P', 'G') }, - { CODEC_ID_MJPEG, MKTAG('L', 'J', 'P', 'G') }, - { CODEC_ID_LJPEG, MKTAG('L', 'J', 'P', 'G') }, - { CODEC_ID_MJPEG, MKTAG('J', 'P', 'G', 'L') }, /* Pegasus lossless JPEG */ - { CODEC_ID_MJPEG, MKTAG('M', 'J', 'L', 'S') }, /* JPEG-LS custom FOURCC for avi - decoder */ - { CODEC_ID_MJPEG, MKTAG('j', 'p', 'e', 'g') }, - { CODEC_ID_MJPEG, MKTAG('I', 'J', 'P', 'G') }, - { CODEC_ID_MJPEG, MKTAG('A', 'V', 'R', 'n') }, - { CODEC_ID_HUFFYUV, MKTAG('H', 'F', 'Y', 'U') }, - { CODEC_ID_FFVHUFF, MKTAG('F', 'F', 'V', 'H') }, - { CODEC_ID_CYUV, MKTAG('C', 'Y', 'U', 'V') }, - { CODEC_ID_RAWVIDEO, 0 }, - { CODEC_ID_RAWVIDEO, MKTAG('I', '4', '2', '0') }, - { CODEC_ID_RAWVIDEO, MKTAG('Y', 'U', 'Y', '2') }, - { CODEC_ID_RAWVIDEO, MKTAG('Y', '4', '2', '2') }, - { CODEC_ID_RAWVIDEO, MKTAG('Y', 'V', '1', '2') }, - { CODEC_ID_RAWVIDEO, MKTAG('U', 'Y', 'V', 'Y') }, - { CODEC_ID_RAWVIDEO, MKTAG('I', 'Y', 'U', 'V') }, - { CODEC_ID_RAWVIDEO, MKTAG('Y', '8', '0', '0') }, - { CODEC_ID_RAWVIDEO, MKTAG('H', 'D', 'Y', 'C') }, - { CODEC_ID_INDEO3, MKTAG('I', 'V', '3', '1') }, - { CODEC_ID_INDEO3, MKTAG('I', 'V', '3', '2') }, - { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') }, - { CODEC_ID_VP3, MKTAG('V', 'P', '3', '0') }, - { CODEC_ID_ASV1, MKTAG('A', 'S', 'V', '1') }, - { CODEC_ID_ASV2, MKTAG('A', 'S', 'V', '2') }, - { CODEC_ID_VCR1, MKTAG('V', 'C', 'R', '1') }, - { CODEC_ID_FFV1, MKTAG('F', 'F', 'V', '1') }, - { CODEC_ID_XAN_WC4, MKTAG('X', 'x', 'a', 'n') }, - { CODEC_ID_MSRLE, MKTAG('m', 'r', 'l', 'e') }, - { CODEC_ID_MSRLE, MKTAG(0x1, 0x0, 0x0, 0x0) }, - { CODEC_ID_MSVIDEO1, MKTAG('M', 'S', 'V', 'C') }, - { CODEC_ID_MSVIDEO1, MKTAG('m', 's', 'v', 'c') }, - { CODEC_ID_MSVIDEO1, MKTAG('C', 'R', 'A', 'M') }, - { CODEC_ID_MSVIDEO1, MKTAG('c', 'r', 'a', 'm') }, - { CODEC_ID_MSVIDEO1, MKTAG('W', 'H', 'A', 'M') }, - { CODEC_ID_MSVIDEO1, MKTAG('w', 'h', 'a', 'm') }, - { CODEC_ID_CINEPAK, MKTAG('c', 'v', 'i', 'd') }, - { CODEC_ID_TRUEMOTION1, MKTAG('D', 'U', 'C', 'K') }, - { CODEC_ID_MSZH, MKTAG('M', 'S', 'Z', 'H') }, - { CODEC_ID_ZLIB, MKTAG('Z', 'L', 'I', 'B') }, - { CODEC_ID_SNOW, MKTAG('S', 'N', 'O', 'W') }, - { CODEC_ID_4XM, MKTAG('4', 'X', 'M', 'V') }, - { CODEC_ID_FLV1, MKTAG('F', 'L', 'V', '1') }, - { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', '1') }, - { CODEC_ID_TSCC, MKTAG('t', 's', 'c', 'c') }, - { CODEC_ID_ULTI, MKTAG('U', 'L', 'T', 'I') }, - { CODEC_ID_VIXL, MKTAG('V', 'I', 'X', 'L') }, - { CODEC_ID_QPEG, MKTAG('Q', 'P', 'E', 'G') }, - { CODEC_ID_QPEG, MKTAG('Q', '1', '.', '0') }, - { CODEC_ID_QPEG, MKTAG('Q', '1', '.', '1') }, - { CODEC_ID_WMV3, MKTAG('W', 'M', 'V', '3') }, - { CODEC_ID_LOCO, MKTAG('L', 'O', 'C', 'O') }, - { CODEC_ID_THEORA, MKTAG('t', 'h', 'e', 'o') }, -#if LIBAVCODEC_VERSION_INT>0x000409 - { CODEC_ID_WNV1, MKTAG('W', 'N', 'V', '1') }, - { CODEC_ID_AASC, MKTAG('A', 'A', 'S', 'C') }, - { CODEC_ID_INDEO2, MKTAG('R', 'T', '2', '1') }, - { CODEC_ID_FRAPS, MKTAG('F', 'P', 'S', '1') }, - { CODEC_ID_TRUEMOTION2, MKTAG('T', 'M', '2', '0') }, -#endif -#if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0) - { CODEC_ID_FLASHSV, MKTAG('F', 'S', 'V', '1') }, - { CODEC_ID_JPEGLS,MKTAG('M', 'J', 'L', 'S') }, /* JPEG-LS custom FOURCC for avi - encoder */ - { CODEC_ID_VC1, MKTAG('W', 'V', 'C', '1') }, - { CODEC_ID_VC1, MKTAG('W', 'M', 'V', 'A') }, - { CODEC_ID_CSCD, MKTAG('C', 'S', 'C', 'D') }, - { CODEC_ID_ZMBV, MKTAG('Z', 'M', 'B', 'V') }, - { CODEC_ID_KMVC, MKTAG('K', 'M', 'V', 'C') }, -#endif -#if LIBAVCODEC_VERSION_INT>((51<<16)+(11<<8)+0) - { CODEC_ID_VP5, MKTAG('V', 'P', '5', '0') }, - { CODEC_ID_VP6, MKTAG('V', 'P', '6', '0') }, - { CODEC_ID_VP6, MKTAG('V', 'P', '6', '1') }, - { CODEC_ID_VP6, MKTAG('V', 'P', '6', '2') }, - { CODEC_ID_VP6F, MKTAG('V', 'P', '6', 'F') }, - { CODEC_ID_JPEG2000, MKTAG('M', 'J', '2', 'C') }, - { CODEC_ID_VMNC, MKTAG('V', 'M', 'n', 'c') }, -#endif -#if LIBAVCODEC_VERSION_INT>=((51<<16)+(49<<8)+0) -// this tag seems not to exist in older versions of FFMPEG - { CODEC_ID_TARGA, MKTAG('t', 'g', 'a', ' ') }, -#endif - { CODEC_ID_NONE, 0 }, -}; - - -class CvCapture_FFMPEG : public CvCapture -{ -public: - CvCapture_FFMPEG() { init(); } - virtual ~CvCapture_FFMPEG() { close(); } - - virtual bool open( const char* filename ); - virtual void close(); - - virtual double getProperty(int); - virtual bool setProperty(int, double); - virtual bool grabFrame(); - virtual IplImage* retrieveFrame(int); - -protected: - void init(); - bool reopen(); - bool slowSeek( int framenumber ); - - AVFormatContext * ic; - int video_stream; - AVStream * video_st; - AVFrame * picture; - int64_t picture_pts; - AVFrame rgb_picture; - AVPacket packet; - IplImage frame; -#if defined(HAVE_FFMPEG_SWSCALE) - struct SwsContext *img_convert_ctx; -#endif -/* - 'filename' contains the filename of the videosource, - 'filename==NULL' indicates that ffmpeg's seek support works - for the particular file. - 'filename!=NULL' indicates that the slow fallback function is used for seeking, - and so the filename is needed to reopen the file on backward seeking. -*/ - char * filename; -}; - - -void CvCapture_FFMPEG::init() -{ - ic = 0; - video_stream = -1; - video_st = 0; - picture = 0; - picture_pts = 0; - memset( &rgb_picture, 0, sizeof(rgb_picture) ); - memset( &frame, 0, sizeof(frame) ); - filename = 0; - packet.data = NULL; -#if defined(HAVE_FFMPEG_SWSCALE) - img_convert_ctx = 0; -#endif -} - - -void CvCapture_FFMPEG::close() -{ - if( picture ) - av_free(picture); - - if( video_st ) + static int ffmpegInitialized = 0; + if( !ffmpegInitialized ) { -#if LIBAVFORMAT_BUILD > 4628 - avcodec_close( video_st->codec ); -#else - avcodec_close( &video_st->codec ); -#endif - video_st = NULL; - } + #if defined WIN32 || defined _WIN32 + const char* module_name = "opencv_ffmpeg" + #if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__) + "_64" + #endif + ".dll"; - if( ic ) - { - av_close_input_file(ic); - ic = NULL; - } - - if( rgb_picture.data[0] ) - cvFree( &rgb_picture.data[0] ); - - // free last packet if exist - if (packet.data) { - av_free_packet (&packet); - } - - - init(); -} - - -/* - Used to reopen a video if the slower fallback function for seeking is used. -*/ -bool CvCapture_FFMPEG::reopen() -{ - if ( filename==NULL ) return false; - -#if LIBAVFORMAT_BUILD > 4628 - avcodec_close( video_st->codec ); -#else - avcodec_close( &video_st->codec ); -#endif - av_close_input_file(ic); - - // reopen video - av_open_input_file(&ic, filename, NULL, 0, NULL); - av_find_stream_info(ic); -#if LIBAVFORMAT_BUILD > 4628 - AVCodecContext *enc = ic->streams[video_stream]->codec; -#else - AVCodecContext *enc = &ic->streams[video_stream]->codec; -#endif - AVCodec *codec = avcodec_find_decoder(enc->codec_id); - avcodec_open(enc, codec); - video_st = ic->streams[video_stream]; - - // reset framenumber to zero - picture_pts=0; - - return true; -} - -#ifndef AVSEEK_FLAG_FRAME - #define AVSEEK_FLAG_FRAME 0 -#endif - -bool CvCapture_FFMPEG::open( const char* _filename ) -{ - unsigned i; - bool valid = false; - - close(); - - /* register all codecs, demux and protocols */ - av_register_all(); - -#ifndef _DEBUG - // av_log_level = AV_LOG_QUIET; -#endif - - int err = av_open_input_file(&ic, _filename, NULL, 0, NULL); - if (err < 0) { - CV_WARN("Error opening file"); - goto exit_func; - } - err = av_find_stream_info(ic); - if (err < 0) { - CV_WARN("Could not find codec parameters"); - goto exit_func; - } - for(i = 0; i < ic->nb_streams; i++) { -#if LIBAVFORMAT_BUILD > 4628 - AVCodecContext *enc = ic->streams[i]->codec; -#else - AVCodecContext *enc = &ic->streams[i]->codec; -#endif - - if( CODEC_TYPE_VIDEO == enc->codec_type && video_stream < 0) { - AVCodec *codec = avcodec_find_decoder(enc->codec_id); - if (!codec || - avcodec_open(enc, codec) < 0) - goto exit_func; - video_stream = i; - video_st = ic->streams[i]; - picture = avcodec_alloc_frame(); - - rgb_picture.data[0] = (uint8_t*)cvAlloc( - avpicture_get_size( PIX_FMT_BGR24, - enc->width, enc->height )); - avpicture_fill( (AVPicture*)&rgb_picture, rgb_picture.data[0], - PIX_FMT_BGR24, enc->width, enc->height ); - - cvInitImageHeader( &frame, cvSize( enc->width, - enc->height ), 8, 3, 0, 4 ); - cvSetData( &frame, rgb_picture.data[0], - rgb_picture.linesize[0] ); - break; - } - } - - if(video_stream >= 0) valid = true; - - // perform check if source is seekable via ffmpeg's seek function av_seek_frame(...) - err = av_seek_frame(ic, video_stream, 10, 0); - if (err < 0) - { - filename=(char*)malloc(strlen(_filename)+1); - strcpy(filename, _filename); - // reopen videofile to 'seek' back to first frame - reopen(); - } - else - { - // seek seems to work, so we don't need the filename, - // but we still need to seek back to filestart - filename=NULL; - int64_t ts = video_st->first_dts; - int flags = AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD; - av_seek_frame(ic, video_stream, ts, flags); - } -exit_func: - - if( !valid ) - close(); - - return valid; -} - - -bool CvCapture_FFMPEG::grabFrame() -{ - bool valid = false; - static bool bFirstTime = true; - int got_picture; - - // First time we're called, set packet.data to NULL to indicate it - // doesn't have to be freed - if (bFirstTime) { - bFirstTime = false; - packet.data = NULL; - } - - if( !ic || !video_st ) - return false; - - // free last packet if exist - if (packet.data != NULL) { - av_free_packet (&packet); - } - - // get the next frame - while (!valid) { - int ret = av_read_frame(ic, &packet); - if (ret == AVERROR(EAGAIN)) - continue; - if (ret < 0) - break; - - if( packet.stream_index != video_stream ) { - av_free_packet (&packet); - continue; - } - -#if LIBAVFORMAT_BUILD > 4628 - avcodec_decode_video(video_st->codec, - picture, &got_picture, - packet.data, packet.size); -#else - avcodec_decode_video(&video_st->codec, - picture, &got_picture, - packet.data, packet.size); -#endif - - if (got_picture) { - // we have a new picture, so memorize it - picture_pts = packet.pts; - valid = 1; - } - } - - // return if we have a new picture or not - return valid; -} - - -IplImage* CvCapture_FFMPEG::retrieveFrame(int) -{ - if( !video_st || !picture->data[0] ) - return 0; - -#if !defined(HAVE_FFMPEG_SWSCALE) -#if LIBAVFORMAT_BUILD > 4628 - img_convert( (AVPicture*)&rgb_picture, PIX_FMT_BGR24, - (AVPicture*)picture, - video_st->codec->pix_fmt, - video_st->codec->width, - video_st->codec->height ); -#else - img_convert( (AVPicture*)&rgb_picture, PIX_FMT_BGR24, - (AVPicture*)picture, - video_st->codec.pix_fmt, - video_st->codec.width, - video_st->codec.height ); -#endif -#else - img_convert_ctx = sws_getContext(video_st->codec->width, - video_st->codec->height, - video_st->codec->pix_fmt, - video_st->codec->width, - video_st->codec->height, - PIX_FMT_BGR24, - SWS_BICUBIC, - NULL, NULL, NULL); - - sws_scale(img_convert_ctx, picture->data, - picture->linesize, 0, - video_st->codec->height, - rgb_picture.data, rgb_picture.linesize); - sws_freeContext(img_convert_ctx); -#endif - return &frame; -} - -#if defined(__APPLE__) -#define AV_NOPTS_VALUE_ ((int64_t)0x8000000000000000LL) -#else -#define AV_NOPTS_VALUE_ ((int64_t)AV_NOPTS_VALUE) -#endif - -double CvCapture_FFMPEG::getProperty( int property_id ) -{ - // if( !capture || !video_st || !picture->data[0] ) return 0; - if( !video_st ) return 0; - - double frameScale = av_q2d (video_st->time_base) * av_q2d (video_st->r_frame_rate); - int64_t timestamp; - timestamp = picture_pts; - - switch( property_id ) - { - case CV_CAP_PROP_POS_MSEC: - if(video_st->parser && video_st->parser->dts != AV_NOPTS_VALUE_) - return (((double)video_st->parser->dts-1) *1000.0f) * av_q2d (video_st->time_base); - if(video_st->cur_dts != AV_NOPTS_VALUE_) - return ((video_st->cur_dts-video_st->first_dts) * 1000.0 * av_q2d (video_st->time_base)); - break; - case CV_CAP_PROP_POS_FRAMES: - if(video_st->parser && video_st->parser->dts != AV_NOPTS_VALUE_) - return (double)video_st->parser->dts-1; - if(video_st->cur_dts != AV_NOPTS_VALUE_) - return((video_st->cur_dts-video_st->first_dts) * frameScale); - break; - case CV_CAP_PROP_POS_AVI_RATIO: - if(video_st->parser && video_st->parser->dts != AV_NOPTS_VALUE_) - return (double)(video_st->parser->dts-1)/(double)video_st->duration; - if(video_st->cur_dts != AV_NOPTS_VALUE_ && video_st->duration != AV_NOPTS_VALUE_) - return(((video_st->cur_dts-video_st->first_dts)+(1.0/frameScale)) / (double)video_st->duration); - break; - case CV_CAP_PROP_FRAME_COUNT: - if(video_st->duration != AV_NOPTS_VALUE_) - return (double)video_st->duration * frameScale; - break; - case CV_CAP_PROP_FRAME_WIDTH: - return (double)frame.width; - break; - case CV_CAP_PROP_FRAME_HEIGHT: - return (double)frame.height; - break; - case CV_CAP_PROP_FPS: -#if LIBAVCODEC_BUILD > 4753 - return av_q2d (video_st->r_frame_rate); -#else - return (double)video_st->codec.frame_rate - / (double)video_st->codec.frame_rate_base; -#endif - break; - case CV_CAP_PROP_FOURCC: -#if LIBAVFORMAT_BUILD > 4628 - return (double)video_st->codec->codec_tag; -#else - return (double)video_st->codec.codec_tag; -#endif - break; - } - return 0; -} - - - -// this is a VERY slow fallback function, ONLY used if ffmpeg's av_seek_frame delivers no correct result! -bool CvCapture_FFMPEG::slowSeek( int framenumber ) -{ - if ( framenumber>picture_pts ) - { - while ( picture_ptsstreams[video_stream]->first_dts; - AVRational time_base = ic->streams[video_stream]->time_base; - AVRational frame_base = ic->streams[video_stream]->r_frame_rate; - double timeScale = (time_base.den / (double)time_base.num) / (frame_base.num / frame_base.den); - switch( property_id ) + 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"); + +#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 ) { - case CV_CAP_PROP_POS_FRAMES: - timestamp += (int64_t)(value * timeScale); - if(ic->start_time != AV_NOPTS_VALUE_) - timestamp += ic->start_time; - break; - - case CV_CAP_PROP_POS_MSEC: - timestamp +=(int64_t)(value*(float(time_base.den)/float(time_base.num))/1000); - if(ic->start_time != AV_NOPTS_VALUE_) - timestamp += ic->start_time; - break; - - case CV_CAP_PROP_POS_AVI_RATIO: - timestamp += (int64_t)(value*ic->duration); - if(ic->start_time != AV_NOPTS_VALUE_ && ic->duration != AV_NOPTS_VALUE_) - timestamp += ic->start_time; - break; - } - - if ( filename ) - { - // ffmpeg's seek doesn't work... - if (!slowSeek((int)timestamp)) - { - fprintf(stderr, "HIGHGUI ERROR: AVI: could not (slow) seek to position %0.3f\n", - (double)timestamp / AV_TIME_BASE); - return false; - } + printf("Successfully initialized ffmpeg plugin!\n"); } else { - int flags = AVSEEK_FLAG_FRAME; - if (timestamp < ic->streams[video_stream]->cur_dts) - flags |= AVSEEK_FLAG_BACKWARD; - int ret = av_seek_frame(ic, video_stream, timestamp, flags); - if (ret < 0) - { - fprintf(stderr, "HIGHGUI ERROR: AVI: could not seek to position %0.3f\n", - (double)timestamp / AV_TIME_BASE); - return false; - } + printf("Failed to load FFMPEG plugin: module handle=%p\n", icvFFOpenCV); } - picture_pts=(int64_t)value; +#endif } - break; - - default: - return false; + #elif defined HAVE_FFMPEG + icvCreateFileCapture_FFMPEG_p = cvCreateFileCapture_FFMPEG; + icvReleaseCapture_FFMPEG_p = cvReleaseCapture_FFMPEG; + icvGrabFrame_FFMPEG_p = cvGrabFrame_FFMPEG; + icvRetrieveFrame_FFMPEG_p = cvRetrieveFrame_FFMPEG; + icvSetCaptureProperty_FFMPEG_p = cvSetCaptureProperty_FFMPEG; + icvGetCaptureProperty_FFMPEG_p = cvGetCaptureProperty_FFMPEG; + icvCreateVideoWriter_FFMPEG_p = cvCreateVideoWriter_FFMPEG; + icvReleaseVideoWriter_FFMPEG_p = cvReleaseVideoWriter_FFMPEG; + icvWriteFrame_FFMPEG_p = cvWriteFrame_FFMPEG; + #endif + + ffmpegInitialized = 1; } - - return true; } - -CvCapture* cvCreateFileCapture_FFMPEG( const char* filename ) -{ - CvCapture_FFMPEG* capture = new CvCapture_FFMPEG; - if( capture->open( filename )) - return capture; - delete capture; - return 0; -} - - -///////////////// FFMPEG CvVideoWriter implementation ////////////////////////// -class CvVideoWriter_FFMPEG : public CvVideoWriter +class CvCapture_FFMPEG_proxy : public CvCapture { public: - CvVideoWriter_FFMPEG() { init(); } - virtual ~CvVideoWriter_FFMPEG() { close(); } + CvCapture_FFMPEG_proxy() { ffmpegCapture = 0; } + virtual ~CvCapture_FFMPEG_proxy() { close(); } - virtual bool open( const char* filename, int fourcc, - double fps, CvSize frameSize, bool isColor ); - virtual void close(); - virtual bool writeFrame( const IplImage* image ); + virtual double getProperty(int propId) + { + return ffmpegCapture ? icvGetCaptureProperty_FFMPEG_p(ffmpegCapture, propId) : 0; + } + virtual bool setProperty(int propId, double value) + { + return ffmpegCapture ? icvSetCaptureProperty_FFMPEG_p(ffmpegCapture, propId, value)!=0 : false; + } + virtual bool grabFrame() + { + return ffmpegCapture ? icvGrabFrame_FFMPEG_p(ffmpegCapture)!=0 : false; + } + virtual IplImage* retrieveFrame(int) + { + unsigned char* data = 0; + int step=0, width=0, height=0, cn=0; + + if(!ffmpegCapture || + !icvRetrieveFrame_FFMPEG_p(ffmpegCapture,&data,&step,&width,&height,&cn)) + return 0; + cvInitImageHeader(&frame, cvSize(width, height), 8, cn); + cvSetData(&frame, data, step); + return &frame; + } + virtual bool open( const char* filename ) + { + close(); + + icvInitFFMPEG(); + if( !icvCreateFileCapture_FFMPEG_p ) + return false; + ffmpegCapture = icvCreateFileCapture_FFMPEG_p( filename ); + return ffmpegCapture != 0; + } + virtual void close() + { + if( ffmpegCapture && icvReleaseCapture_FFMPEG_p ) + icvReleaseCapture_FFMPEG_p( &ffmpegCapture ); + assert( ffmpegCapture == 0 ); + ffmpegCapture = 0; + } protected: - void init(); - - AVOutputFormat *fmt; - AVFormatContext *oc; - uint8_t * outbuf; - uint32_t outbuf_size; - FILE * outfile; - AVFrame * picture; - AVFrame * input_picture; - uint8_t * picbuf; - AVStream * video_st; - int input_pix_fmt; - IplImage * temp_image; -#if defined(HAVE_FFMPEG_SWSCALE) - struct SwsContext *img_convert_ctx; -#endif + void* ffmpegCapture; + IplImage frame; }; -static const char * icvFFMPEGErrStr(int err) + +CvCapture* cvCreateFileCapture_FFMPEG_proxy(const char * filename) { - switch(err) { - case AVERROR_NUMEXPECTED: - return "Incorrect filename syntax"; - case AVERROR_INVALIDDATA: - return "Invalid data in header"; - case AVERROR_NOFMT: - return "Unknown format"; - case AVERROR_IO: - return "I/O error occurred"; - case AVERROR_NOMEM: - return "Memory allocation error"; - default: - break; - } - return "Unspecified error"; + CvCapture_FFMPEG_proxy* result = new CvCapture_FFMPEG_proxy; + if( result->open( filename )) + return result; + delete result; + return cvCreateFileCapture_VFW(filename); } -/* function internal to FFMPEG (libavformat/riff.c) to lookup codec id by fourcc tag*/ -extern "C" { - enum CodecID codec_get_bmp_id(unsigned int tag); -} -void CvVideoWriter_FFMPEG::init() +class CvVideoWriter_FFMPEG_proxy : public CvVideoWriter { - fmt = 0; - oc = 0; - outbuf = 0; - outbuf_size = 0; - outfile = 0; - picture = 0; - input_picture = 0; - picbuf = 0; - video_st = 0; - input_pix_fmt = 0; - temp_image = 0; -#if defined(HAVE_FFMPEG_SWSCALE) - img_convert_ctx = 0; -#endif -} +public: + CvVideoWriter_FFMPEG_proxy() { ffmpegWriter = 0; } + virtual ~CvVideoWriter_FFMPEG_proxy() { close(); } -/** - * the following function is a modified version of code - * found in ffmpeg-0.4.9-pre1/output_example.c - */ -static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bool alloc) -{ - AVFrame * picture; - uint8_t * picture_buf; - int size; - - picture = avcodec_alloc_frame(); - if (!picture) - return NULL; - size = avpicture_get_size( (PixelFormat) pix_fmt, width, height); - if(alloc){ - picture_buf = (uint8_t *) cvAlloc(size); - if (!picture_buf) - { - av_free(picture); - return NULL; - } - avpicture_fill((AVPicture *)picture, picture_buf, - (PixelFormat) pix_fmt, width, height); - } - else { - } - return picture; -} - -/* add a video output stream to the container */ -static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc, - CodecID codec_id, - int w, int h, int bitrate, - double fps, int pixel_format) -{ - AVCodecContext *c; - AVStream *st; - int frame_rate, frame_rate_base; - AVCodec *codec; - - - st = av_new_stream(oc, 0); - if (!st) { - CV_WARN("Could not allocate stream"); - return NULL; - } - -#if LIBAVFORMAT_BUILD > 4628 - c = st->codec; -#else - c = &(st->codec); -#endif - -#if LIBAVFORMAT_BUILD > 4621 - c->codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, CODEC_TYPE_VIDEO); -#else - c->codec_id = oc->oformat->video_codec; -#endif - - if(codec_id != CODEC_ID_NONE){ - c->codec_id = codec_id; - } - - //if(codec_tag) c->codec_tag=codec_tag; - codec = avcodec_find_encoder(c->codec_id); - - c->codec_type = CODEC_TYPE_VIDEO; - - /* put sample parameters */ - c->bit_rate = bitrate; - - /* 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. */ - frame_rate=cvRound(fps); - frame_rate_base=1; - while (fabs((double)frame_rate/frame_rate_base) - fps > 0.001){ - frame_rate_base*=10; - frame_rate=cvRound(fps*frame_rate_base); - } -#if LIBAVFORMAT_BUILD > 4752 - c->time_base.den = frame_rate; - c->time_base.num = frame_rate_base; - /* adjust time base for supported framerates */ - if(codec && codec->supported_framerates){ - const AVRational *p= codec->supported_framerates; - AVRational req = {frame_rate, frame_rate_base}; - const AVRational *best=NULL; - AVRational best_error= {INT_MAX, 1}; - for(; 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; - } - } - c->time_base.den= best->num; - c->time_base.num= best->den; - } -#else - c->frame_rate = frame_rate; - c->frame_rate_base = frame_rate_base; -#endif - - c->gop_size = 12; /* emit one intra frame every twelve frames at most */ - c->pix_fmt = (PixelFormat) pixel_format; - - if (c->codec_id == CODEC_ID_MPEG2VIDEO) { - c->max_b_frames = 2; - } - if (c->codec_id == CODEC_ID_MPEG1VIDEO || c->codec_id == CODEC_ID_MSMPEG4V3){ - /* needed to avoid using macroblocks in which some coeffs overflow - this doesnt happen with normal video, it just happens here as the - motion of the chroma plane doesnt 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 seperate - if(oc->oformat->flags & AVFMT_GLOBALHEADER) + virtual bool writeFrame( const IplImage* image ) { - c->flags |= CODEC_FLAG_GLOBAL_HEADER; + if(!ffmpegWriter) + return false; + CV_Assert(image->depth == 8); + + return icvWriteFrame_FFMPEG_p(ffmpegWriter, (const uchar*)image->imageData, + image->widthStep, image->width, image->height, image->nChannels, image->origin) !=0; } -#endif - - return st; -} - -int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_t * outbuf, uint32_t outbuf_size, AVFrame * picture ){ - CV_FUNCNAME("icv_av_write_frame_FFMPEG"); - -#if LIBAVFORMAT_BUILD > 4628 - AVCodecContext * c = video_st->codec; -#else - AVCodecContext * c = &(video_st->codec); -#endif - int out_size; - int ret; - - __BEGIN__; - - if (oc->oformat->flags & AVFMT_RAWPICTURE) { - /* raw video case. The API will change slightly in the near - futur for that */ - AVPacket pkt; - av_init_packet(&pkt); - - pkt.flags |= PKT_FLAG_KEY; - pkt.stream_index= video_st->index; - pkt.data= (uint8_t *)picture; - pkt.size= sizeof(AVPicture); - - ret = av_write_frame(oc, &pkt); - } else { - /* encode the image */ - out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture); - /* if zero size, it means the image was buffered */ - if (out_size > 0) { - AVPacket pkt; - av_init_packet(&pkt); - -#if LIBAVFORMAT_BUILD > 4752 - pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_st->time_base); -#else - pkt.pts = c->coded_frame->pts; -#endif - if(c->coded_frame->key_frame) - pkt.flags |= PKT_FLAG_KEY; - pkt.stream_index= video_st->index; - pkt.data= outbuf; - pkt.size= out_size; - - /* write the compressed frame in the media file */ - ret = av_write_frame(oc, &pkt); - } else { - ret = 0; - } - } - if (ret != 0) { - CV_ERROR(CV_StsError, "Error while writing video frame"); - } - - __END__; - return CV_StsOk; -} - -/// write a frame with FFMPEG -bool CvVideoWriter_FFMPEG::writeFrame( const IplImage * image ) -{ - bool ret = false; - - CV_FUNCNAME("CvVideoWriter_FFMPEG::writerFrame"); - - __BEGIN__; - - // typecast from opaque data type to implemented struct -#if LIBAVFORMAT_BUILD > 4628 - AVCodecContext *c = video_st->codec; -#else - AVCodecContext *c = &(video_st->codec); -#endif - -#if LIBAVFORMAT_BUILD < 5231 - // It is not needed in the latest versions of the ffmpeg - if( c->codec_id == CODEC_ID_RAWVIDEO && image->origin != IPL_ORIGIN_BL ) + virtual bool open( const char* filename, int fourcc, double fps, CvSize frameSize, bool isColor ) { - if( !temp_image ) - temp_image = cvCreateImage( cvGetSize(image), - image->depth, image->nChannels ); - cvFlip( image, temp_image, 0 ); - image = temp_image; - } -#endif - - // check parameters - if (input_pix_fmt == PIX_FMT_BGR24) { - if (image->nChannels != 3 || image->depth != IPL_DEPTH_8U) { - CV_ERROR(CV_StsUnsupportedFormat, "cvWriteFrame() needs images with depth = IPL_DEPTH_8U and nChannels = 3."); - } - } - else if (input_pix_fmt == PIX_FMT_GRAY8) { - if (image->nChannels != 1 || image->depth != IPL_DEPTH_8U) { - CV_ERROR(CV_StsUnsupportedFormat, "cvWriteFrame() needs images with depth = IPL_DEPTH_8U and nChannels = 1."); - } - } - else { - assert(false); + close(); + icvInitFFMPEG(); + if( !icvCreateVideoWriter_FFMPEG_p ) + return false; + ffmpegWriter = icvCreateVideoWriter_FFMPEG_p( filename, fourcc, fps, frameSize.width, frameSize.height, isColor ); + return ffmpegWriter != 0; } - // check if buffer sizes match, i.e. image has expected format (size, channels, bitdepth, alignment) -#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(37<<8)+0) - assert (image->imageSize == avpicture_get_size( (PixelFormat)input_pix_fmt, image->width, image->height )); -#else - assert (image->imageSize == avpicture_get_size( input_pix_fmt, image->width, image->height )); -#endif + virtual void close() + { + if( ffmpegWriter && icvReleaseVideoWriter_FFMPEG_p ) + icvReleaseVideoWriter_FFMPEG_p( &ffmpegWriter ); + assert( ffmpegWriter == 0 ); + ffmpegWriter = 0; + } - if ( c->pix_fmt != input_pix_fmt ) { - assert( input_picture ); - // let input_picture point to the raw data buffer of 'image' - avpicture_fill((AVPicture *)input_picture, (uint8_t *) image->imageData, - (PixelFormat)input_pix_fmt, image->width, image->height); +protected: + void* ffmpegWriter; +}; -#if !defined(HAVE_FFMPEG_SWSCALE) - // convert to the color format needed by the codec - if( img_convert((AVPicture *)picture, c->pix_fmt, - (AVPicture *)input_picture, (PixelFormat)input_pix_fmt, - image->width, image->height) < 0){ - CV_ERROR(CV_StsUnsupportedFormat, "FFMPEG::img_convert pixel format conversion from BGR24 not handled"); - } -#else - img_convert_ctx = sws_getContext(image->width, - image->height, - PIX_FMT_BGR24, - c->width, - c->height, - c->pix_fmt, - SWS_BICUBIC, - NULL, NULL, NULL); - if ( sws_scale(img_convert_ctx, input_picture->data, - input_picture->linesize, 0, - image->height, - picture->data, picture->linesize) < 0 ) - { - CV_ERROR(CV_StsUnsupportedFormat, "FFMPEG::img_convert pixel format conversion from BGR24 not handled"); - } - sws_freeContext(img_convert_ctx); -#endif - } - else{ - avpicture_fill((AVPicture *)picture, (uint8_t *) image->imageData, - (PixelFormat)input_pix_fmt, image->width, image->height); - } - - ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, picture) >= 0; - - __END__; - return ret; -} - -/// close video output stream and free associated memory -void CvVideoWriter_FFMPEG::close() +CvVideoWriter* cvCreateVideoWriter_FFMPEG_proxy( const char* filename, int fourcc, + double fps, CvSize frameSize, int isColor ) { - unsigned i; + CvVideoWriter_FFMPEG_proxy* result = new CvVideoWriter_FFMPEG_proxy; - // nothing to do if already released - if ( !picture ) - return; + if( result->open( filename, fourcc, fps, frameSize, isColor != 0 )) + return result; + delete result; - /* 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? - - /* write the trailer, if any */ - av_write_trailer(oc); - - // free pictures -#if LIBAVFORMAT_BUILD > 4628 - if( video_st->codec->pix_fmt != input_pix_fmt){ -#else - if( video_st->codec.pix_fmt != input_pix_fmt){ -#endif - cvFree(&(picture->data[0])); - } - av_free(picture); - - if (input_picture) { - av_free(input_picture); - } - - /* close codec */ -#if LIBAVFORMAT_BUILD > 4628 - avcodec_close(video_st->codec); -#else - avcodec_close(&(video_st->codec)); -#endif - - av_free(outbuf); - - /* free the streams */ - for(i = 0; i < oc->nb_streams; i++) { - av_freep(&oc->streams[i]->codec); - av_freep(&oc->streams[i]); - } - - if (!(fmt->flags & AVFMT_NOFILE)) { - /* close the output file */ - - -#if LIBAVCODEC_VERSION_INT >= ((51<<16)+(49<<8)+0) - url_fclose(oc->pb); -#else - url_fclose(&oc->pb); -#endif - - } - - /* free the stream */ - av_free(oc); - - cvReleaseImage( &temp_image ); - - init(); -} - -/// Create a video writer object that uses FFMPEG -bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, - double fps, CvSize frameSize, bool is_color ) -{ - CodecID codec_id = CODEC_ID_NONE; - int err, codec_pix_fmt, bitrate_scale=64; - - close(); - - // check arguments - assert (filename); - assert (fps > 0); - assert (frameSize.width > 0 && frameSize.height > 0); - - // tell FFMPEG to register codecs - av_register_all (); - - /* auto detect the output format from the name and fourcc code. */ - fmt = guess_format(NULL, filename, NULL); - if (!fmt) - return false; - - /* determine optimal pixel format */ - if (is_color) { - input_pix_fmt = PIX_FMT_BGR24; - } - else { - input_pix_fmt = PIX_FMT_GRAY8; - } - - /* Lookup codec_id for given fourcc */ -#if LIBAVCODEC_VERSION_INT<((51<<16)+(49<<8)+0) - if( (codec_id = codec_get_bmp_id( fourcc )) == CODEC_ID_NONE ) - return false; -#else - const struct AVCodecTag * tags[] = { codec_bmp_tags, NULL}; - if( (codec_id = av_codec_get_id(tags, fourcc)) == CODEC_ID_NONE ) - return false; -#endif - - // alloc memory for context - oc = av_alloc_format_context(); - assert (oc); - - /* set file name */ - oc->oformat = fmt; - snprintf(oc->filename, sizeof(oc->filename), "%s", filename); - - /* set some options */ - 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.. - switch (codec_id) { -#if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0) - case CODEC_ID_JPEGLS: - // BGR24 or GRAY8 depending on is_color... - codec_pix_fmt = input_pix_fmt; - break; -#endif - case CODEC_ID_HUFFYUV: - codec_pix_fmt = PIX_FMT_YUV422P; - break; - case CODEC_ID_MJPEG: - case CODEC_ID_LJPEG: - codec_pix_fmt = PIX_FMT_YUVJ420P; - bitrate_scale = 128; - break; - case CODEC_ID_RAWVIDEO: - codec_pix_fmt = input_pix_fmt; - break; - default: - // good for lossy formats, MPEG, etc. - codec_pix_fmt = PIX_FMT_YUV420P; - break; - } - - // TODO -- safe to ignore output audio stream? - video_st = icv_add_video_stream_FFMPEG(oc, codec_id, - frameSize.width, frameSize.height, frameSize.width*frameSize.height*bitrate_scale, - fps, codec_pix_fmt); - - - /* set the output parameters (must be done even if no - parameters). */ - if (av_set_parameters(oc, NULL) < 0) { - CV_Error(CV_StsBadArg, "Invalid output format parameters"); - } - - dump_format(oc, 0, filename, 1); - - /* now that all the parameters are set, we can open the audio and - video codecs and allocate the necessary encode buffers */ - if (!video_st){ - CV_Error(CV_StsBadArg, "Couldn't open video stream"); - } - - AVCodec *codec; - AVCodecContext *c; - -#if LIBAVFORMAT_BUILD > 4628 - c = (video_st->codec); -#else - c = &(video_st->codec); -#endif - - c->codec_tag = fourcc; - /* find the video encoder */ - codec = avcodec_find_encoder(c->codec_id); - if (!codec) { - CV_Error(CV_StsBadArg, "codec not found"); - } - - c->bit_rate_tolerance = c->bit_rate; - - /* open the codec */ - if ( (err=avcodec_open(c, codec)) < 0) { - char errtext[256]; - sprintf(errtext, "Could not open codec '%s': %s", codec->name, icvFFMPEGErrStr(err)); - CV_Error(CV_StsBadArg, errtext); - } - - outbuf = NULL; - - if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) { - /* allocate output buffer */ - /* assume we will never get codec output with more than 4 bytes per pixel... */ - outbuf_size = frameSize.width*frameSize.height*4; - outbuf = (uint8_t *) av_malloc(outbuf_size); - } - - bool need_color_convert; - need_color_convert = (c->pix_fmt != input_pix_fmt); - - /* allocate the encoded raw picture */ - picture = icv_alloc_picture_FFMPEG(c->pix_fmt, c->width, c->height, need_color_convert); - if (!picture) { - CV_Error(CV_StsNoMem, "Could not allocate picture"); - } - - /* if the output format is not our input format, then a temporary - picture of the input format is needed too. It is then converted - to the required output format */ - input_picture = NULL; - if ( need_color_convert ) { - input_picture = icv_alloc_picture_FFMPEG(input_pix_fmt, c->width, c->height, false); - if (!input_picture) { - CV_Error(CV_StsNoMem, "Could not allocate picture"); - } - } - - /* open the output file, if needed */ - if (!(fmt->flags & AVFMT_NOFILE)) { - if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) { - CV_Error(CV_StsBadArg, "Couldn't open output file for writing"); - } - } - - /* write the stream header, if any */ - av_write_header( oc ); - - return true; -} - -CvVideoWriter* cvCreateVideoWriter_FFMPEG( const char* filename, int fourcc, double fps, - CvSize frameSize, int isColor ) -{ - CvVideoWriter_FFMPEG* writer = new CvVideoWriter_FFMPEG; - if( writer->open( filename, fourcc, fps, frameSize, isColor != 0 )) - return writer; - delete writer; - return 0; + return cvCreateVideoWriter_VFW(filename, fourcc, fps, frameSize, isColor); } diff --git a/modules/highgui/src/cap_ffmpeg_api.hpp b/modules/highgui/src/cap_ffmpeg_api.hpp new file mode 100644 index 0000000000..b085320ed7 --- /dev/null +++ b/modules/highgui/src/cap_ffmpeg_api.hpp @@ -0,0 +1,62 @@ +#ifndef __OPENCV_FFMPEG_H__ +#define __OPENCV_FFMPEG_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if defined WIN32 || defined _WIN32 +#define OPENCV_FFMPEG_API __declspec(dllexport) +#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 +}; + + +OPENCV_FFMPEG_API struct CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG(const char* filename); +OPENCV_FFMPEG_API int cvSetCaptureProperty_FFMPEG(struct CvCapture_FFMPEG* cap, + int prop, double value); +OPENCV_FFMPEG_API double cvGetCaptureProperty_FFMPEG(struct CvCapture_FFMPEG* cap, int prop); +OPENCV_FFMPEG_API int cvGrabFrame_FFMPEG(struct CvCapture_FFMPEG* cap); +OPENCV_FFMPEG_API int cvRetrieveFrame_FFMPEG(CvCapture_FFMPEG* capture, unsigned char** data, + int* step, int* width, int* height, int* cn); +OPENCV_FFMPEG_API void cvReleaseCapture_FFMPEG(struct CvCapture_FFMPEG** cap); + +OPENCV_FFMPEG_API struct CvVideoWriter_FFMPEG* cvCreateVideoWriter_FFMPEG(const char* filename, + int fourcc, double fps, int width, int height, int isColor ); + +OPENCV_FFMPEG_API int cvWriteFrame_FFMPEG(struct CvVideoWriter_FFMPEG* writer, const unsigned char* data, + int step, int width, int height, int cn, int origin); + +OPENCV_FFMPEG_API void cvReleaseVideoWriter_FFMPEG(struct CvVideoWriter_FFMPEG** writer); + +typedef void* (*CvCreateFileCapture_Plugin)( const char* filename ); +typedef void* (*CvCreateCameraCapture_Plugin)( int index ); +typedef int (*CvGrabFrame_Plugin)( void* capture_handle ); +typedef int (*CvRetrieveFrame_Plugin)( void* capture_handle, unsigned char** data, int* step, + int* width, int* height, int* cn ); +typedef int (*CvSetCaptureProperty_Plugin)( void* capture_handle, int prop_id, double value ); +typedef double (*CvGetCaptureProperty_Plugin)( void* capture_handle, int prop_id ); +typedef void (*CvReleaseCapture_Plugin)( void** capture_handle ); +typedef void* (*CvCreateVideoWriter_Plugin)( const char* filename, int fourcc, + double fps, int width, int height, int iscolor ); +typedef int (*CvWriteFrame_Plugin)( void* writer_handle, const unsigned char* data, int step, + int width, int height, int cn, int origin); +typedef void (*CvReleaseVideoWriter_Plugin)( void** writer ); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/modules/highgui/src/cap_ffmpeg_impl.hpp b/modules/highgui/src/cap_ffmpeg_impl.hpp new file mode 100644 index 0000000000..ccb8f13fbc --- /dev/null +++ b/modules/highgui/src/cap_ffmpeg_impl.hpp @@ -0,0 +1,1461 @@ +/*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. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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 "cap_ffmpeg_api.hpp" +#include + +#if defined _MSC_VER && _MSC_VER >= 1200 +#pragma warning( disable: 4244 4510 4512 4610 ) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(WIN32) || defined(__MINGW32__) +// some versions of FFMPEG assume a C99 compiler, and don't define INT64_C +#if !defined INT64_C || !defined UINT64_C +#define INT64_C +#define UINT64_C +#define __STDC_CONSTANT_MACROS +// force re-inclusion of stdint.h to get INT64_C macro +#undef _STDINT_H +#include +#endif +#include +#endif + +#ifdef WIN32 + #define HAVE_FFMPEG_SWSCALE 1 + #include + #include + #include +#else + +// if the header path is not specified explicitly, let's deduce it +#if !defined HAVE_FFMPEG_AVCODEC_H && !defined HAVE_LIBAVCODEC_AVCODEC_H + +#if defined(HAVE_GENTOO_FFMPEG) + #define HAVE_LIBAVCODEC_AVCODEC_H 1 + #define HAVE_LIBAVFORMAT_AVFORMAT_H 1 + #if defined(HAVE_FFMPEG_SWSCALE) + #define HAVE_LIBSWSCALE_SWSCALE_H 1 + #endif +#elif defined HAVE_FFMPEG + #define HAVE_FFMPEG_AVCODEC_H 1 + #define HAVE_FFMPEG_AVFORMAT_H 1 + #if defined(HAVE_FFMPEG_SWSCALE) + #define HAVE_FFMPEG_SWSCALE_H 1 + #endif +#endif + +#endif + +#if defined(HAVE_FFMPEG_AVCODEC_H) + #include +#endif +#if defined(HAVE_FFMPEG_AVFORMAT_H) + #include +#endif +#if defined(HAVE_FFMPEG_SWSCALE_H) + #include +#endif + +#if defined(HAVE_LIBAVFORMAT_AVFORMAT_H) + #include +#endif +#if defined(HAVE_LIBAVCODEC_AVCODEC_H) + #include +#endif +#if defined(HAVE_LIBSWSCALE_SWSCALE_H) + #include +#endif + +#endif + +#ifdef __cplusplus +} +#endif + +#if defined _MSC_VER && _MSC_VER >= 1200 +#pragma warning( default: 4244 4510 4512 4610 ) +#endif + +#ifdef NDEBUG +#define CV_WARN(message) +#else +#define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__) +#endif + + +#ifndef MKTAG +#define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24)) +#endif + +/* PIX_FMT_RGBA32 macro changed in newer ffmpeg versions */ +#ifndef PIX_FMT_RGBA32 +#define PIX_FMT_RGBA32 PIX_FMT_RGB32 +#endif + + + +char * FOURCC2str( int fourcc ) +{ + char * mystr=(char*)malloc(5); + mystr[0]=(char)((fourcc )&255); + mystr[1]=(char)((fourcc>> 8)&255); + mystr[2]=(char)((fourcc>>16)&255); + mystr[3]=(char)((fourcc>>24)&255); + mystr[4]=0; + return mystr; +} + + +// required to look up the correct codec ID depending on the FOURCC code, +// this is just a snipped from the file riff.c from ffmpeg/libavformat +typedef struct AVCodecTag { + int id; + unsigned int tag; +} AVCodecTag; + +const AVCodecTag codec_bmp_tags[] = { + { CODEC_ID_H264, MKTAG('H', '2', '6', '4') }, + { CODEC_ID_H264, MKTAG('h', '2', '6', '4') }, + { CODEC_ID_H264, MKTAG('X', '2', '6', '4') }, + { CODEC_ID_H264, MKTAG('x', '2', '6', '4') }, + { CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') }, + { CODEC_ID_H264, MKTAG('V', 'S', 'S', 'H') }, + + { CODEC_ID_H263, MKTAG('H', '2', '6', '3') }, + { CODEC_ID_H263P, MKTAG('H', '2', '6', '3') }, + { CODEC_ID_H263I, MKTAG('I', '2', '6', '3') }, /* intel h263 */ + { CODEC_ID_H261, MKTAG('H', '2', '6', '1') }, + + /* added based on MPlayer */ + { CODEC_ID_H263P, MKTAG('U', '2', '6', '3') }, + { CODEC_ID_H263P, MKTAG('v', 'i', 'v', '1') }, + + { CODEC_ID_MPEG4, MKTAG('F', 'M', 'P', '4') }, + { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X') }, + { CODEC_ID_MPEG4, MKTAG('D', 'X', '5', '0') }, + { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') }, + { CODEC_ID_MPEG4, MKTAG('M', 'P', '4', 'S') }, + { CODEC_ID_MPEG4, MKTAG('M', '4', 'S', '2') }, + { CODEC_ID_MPEG4, MKTAG(0x04, 0, 0, 0) }, /* some broken avi use this */ + + /* added based on MPlayer */ + { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', '1') }, + { CODEC_ID_MPEG4, MKTAG('B', 'L', 'Z', '0') }, + { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') }, + { CODEC_ID_MPEG4, MKTAG('U', 'M', 'P', '4') }, + { CODEC_ID_MPEG4, MKTAG('W', 'V', '1', 'F') }, + { CODEC_ID_MPEG4, MKTAG('S', 'E', 'D', 'G') }, + + { CODEC_ID_MPEG4, MKTAG('R', 'M', 'P', '4') }, + + { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '3') }, /* default signature when using MSMPEG4 */ + { CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', '4', '3') }, + + /* added based on MPlayer */ + { CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', 'G', '3') }, + { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '5') }, + { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '6') }, + { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '4') }, + { CODEC_ID_MSMPEG4V3, MKTAG('A', 'P', '4', '1') }, + { CODEC_ID_MSMPEG4V3, MKTAG('C', 'O', 'L', '1') }, + { CODEC_ID_MSMPEG4V3, MKTAG('C', 'O', 'L', '0') }, + + { CODEC_ID_MSMPEG4V2, MKTAG('M', 'P', '4', '2') }, + + /* added based on MPlayer */ + { CODEC_ID_MSMPEG4V2, MKTAG('D', 'I', 'V', '2') }, + + { CODEC_ID_MSMPEG4V1, MKTAG('M', 'P', 'G', '4') }, + + { CODEC_ID_WMV1, MKTAG('W', 'M', 'V', '1') }, + + /* added based on MPlayer */ + { CODEC_ID_WMV2, MKTAG('W', 'M', 'V', '2') }, + { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'd') }, + { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', 'd') }, + { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'l') }, + { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '2', '5') }, + { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '1') }, + { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '2') }, + { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', 'g', '2') }, + { CODEC_ID_MPEG2VIDEO, MKTAG('M', 'P', 'E', 'G') }, + { CODEC_ID_MPEG1VIDEO, MKTAG('P', 'I', 'M', '1') }, + { CODEC_ID_MPEG1VIDEO, MKTAG('V', 'C', 'R', '2') }, + { CODEC_ID_MPEG1VIDEO, 0x10000001 }, + { CODEC_ID_MPEG2VIDEO, 0x10000002 }, + { CODEC_ID_MPEG2VIDEO, MKTAG('D', 'V', 'R', ' ') }, + { CODEC_ID_MPEG2VIDEO, MKTAG('M', 'M', 'E', 'S') }, + { CODEC_ID_MJPEG, MKTAG('M', 'J', 'P', 'G') }, + { CODEC_ID_MJPEG, MKTAG('L', 'J', 'P', 'G') }, + { CODEC_ID_LJPEG, MKTAG('L', 'J', 'P', 'G') }, + { CODEC_ID_MJPEG, MKTAG('J', 'P', 'G', 'L') }, /* Pegasus lossless JPEG */ + { CODEC_ID_MJPEG, MKTAG('M', 'J', 'L', 'S') }, /* JPEG-LS custom FOURCC for avi - decoder */ + { CODEC_ID_MJPEG, MKTAG('j', 'p', 'e', 'g') }, + { CODEC_ID_MJPEG, MKTAG('I', 'J', 'P', 'G') }, + { CODEC_ID_MJPEG, MKTAG('A', 'V', 'R', 'n') }, + { CODEC_ID_HUFFYUV, MKTAG('H', 'F', 'Y', 'U') }, + { CODEC_ID_FFVHUFF, MKTAG('F', 'F', 'V', 'H') }, + { CODEC_ID_CYUV, MKTAG('C', 'Y', 'U', 'V') }, + { CODEC_ID_RAWVIDEO, 0 }, + { CODEC_ID_RAWVIDEO, MKTAG('I', '4', '2', '0') }, + { CODEC_ID_RAWVIDEO, MKTAG('Y', 'U', 'Y', '2') }, + { CODEC_ID_RAWVIDEO, MKTAG('Y', '4', '2', '2') }, + { CODEC_ID_RAWVIDEO, MKTAG('Y', 'V', '1', '2') }, + { CODEC_ID_RAWVIDEO, MKTAG('U', 'Y', 'V', 'Y') }, + { CODEC_ID_RAWVIDEO, MKTAG('I', 'Y', 'U', 'V') }, + { CODEC_ID_RAWVIDEO, MKTAG('Y', '8', '0', '0') }, + { CODEC_ID_RAWVIDEO, MKTAG('H', 'D', 'Y', 'C') }, + { CODEC_ID_INDEO3, MKTAG('I', 'V', '3', '1') }, + { CODEC_ID_INDEO3, MKTAG('I', 'V', '3', '2') }, + { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') }, + { CODEC_ID_VP3, MKTAG('V', 'P', '3', '0') }, + { CODEC_ID_ASV1, MKTAG('A', 'S', 'V', '1') }, + { CODEC_ID_ASV2, MKTAG('A', 'S', 'V', '2') }, + { CODEC_ID_VCR1, MKTAG('V', 'C', 'R', '1') }, + { CODEC_ID_FFV1, MKTAG('F', 'F', 'V', '1') }, + { CODEC_ID_XAN_WC4, MKTAG('X', 'x', 'a', 'n') }, + { CODEC_ID_MSRLE, MKTAG('m', 'r', 'l', 'e') }, + { CODEC_ID_MSRLE, MKTAG(0x1, 0x0, 0x0, 0x0) }, + { CODEC_ID_MSVIDEO1, MKTAG('M', 'S', 'V', 'C') }, + { CODEC_ID_MSVIDEO1, MKTAG('m', 's', 'v', 'c') }, + { CODEC_ID_MSVIDEO1, MKTAG('C', 'R', 'A', 'M') }, + { CODEC_ID_MSVIDEO1, MKTAG('c', 'r', 'a', 'm') }, + { CODEC_ID_MSVIDEO1, MKTAG('W', 'H', 'A', 'M') }, + { CODEC_ID_MSVIDEO1, MKTAG('w', 'h', 'a', 'm') }, + { CODEC_ID_CINEPAK, MKTAG('c', 'v', 'i', 'd') }, + { CODEC_ID_TRUEMOTION1, MKTAG('D', 'U', 'C', 'K') }, + { CODEC_ID_MSZH, MKTAG('M', 'S', 'Z', 'H') }, + { CODEC_ID_ZLIB, MKTAG('Z', 'L', 'I', 'B') }, + { CODEC_ID_SNOW, MKTAG('S', 'N', 'O', 'W') }, + { CODEC_ID_4XM, MKTAG('4', 'X', 'M', 'V') }, + { CODEC_ID_FLV1, MKTAG('F', 'L', 'V', '1') }, + { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', '1') }, + { CODEC_ID_TSCC, MKTAG('t', 's', 'c', 'c') }, + { CODEC_ID_ULTI, MKTAG('U', 'L', 'T', 'I') }, + { CODEC_ID_VIXL, MKTAG('V', 'I', 'X', 'L') }, + { CODEC_ID_QPEG, MKTAG('Q', 'P', 'E', 'G') }, + { CODEC_ID_QPEG, MKTAG('Q', '1', '.', '0') }, + { CODEC_ID_QPEG, MKTAG('Q', '1', '.', '1') }, + { CODEC_ID_WMV3, MKTAG('W', 'M', 'V', '3') }, + { CODEC_ID_LOCO, MKTAG('L', 'O', 'C', 'O') }, + { CODEC_ID_THEORA, MKTAG('t', 'h', 'e', 'o') }, +#if LIBAVCODEC_VERSION_INT>0x000409 + { CODEC_ID_WNV1, MKTAG('W', 'N', 'V', '1') }, + { CODEC_ID_AASC, MKTAG('A', 'A', 'S', 'C') }, + { CODEC_ID_INDEO2, MKTAG('R', 'T', '2', '1') }, + { CODEC_ID_FRAPS, MKTAG('F', 'P', 'S', '1') }, + { CODEC_ID_TRUEMOTION2, MKTAG('T', 'M', '2', '0') }, +#endif +#if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0) + { CODEC_ID_FLASHSV, MKTAG('F', 'S', 'V', '1') }, + { CODEC_ID_JPEGLS,MKTAG('M', 'J', 'L', 'S') }, /* JPEG-LS custom FOURCC for avi - encoder */ + { CODEC_ID_VC1, MKTAG('W', 'V', 'C', '1') }, + { CODEC_ID_VC1, MKTAG('W', 'M', 'V', 'A') }, + { CODEC_ID_CSCD, MKTAG('C', 'S', 'C', 'D') }, + { CODEC_ID_ZMBV, MKTAG('Z', 'M', 'B', 'V') }, + { CODEC_ID_KMVC, MKTAG('K', 'M', 'V', 'C') }, +#endif +#if LIBAVCODEC_VERSION_INT>((51<<16)+(11<<8)+0) + { CODEC_ID_VP5, MKTAG('V', 'P', '5', '0') }, + { CODEC_ID_VP6, MKTAG('V', 'P', '6', '0') }, + { CODEC_ID_VP6, MKTAG('V', 'P', '6', '1') }, + { CODEC_ID_VP6, MKTAG('V', 'P', '6', '2') }, + { CODEC_ID_VP6F, MKTAG('V', 'P', '6', 'F') }, + { CODEC_ID_JPEG2000, MKTAG('M', 'J', '2', 'C') }, + { CODEC_ID_VMNC, MKTAG('V', 'M', 'n', 'c') }, +#endif +#if LIBAVCODEC_VERSION_INT>=((51<<16)+(49<<8)+0) +// this tag seems not to exist in older versions of FFMPEG + { CODEC_ID_TARGA, MKTAG('t', 'g', 'a', ' ') }, +#endif + { CODEC_ID_NONE, 0 }, +}; + + +struct Image_FFMPEG +{ + unsigned char* data; + int step; + int width; + int height; + int cn; +}; + + +inline void _opencv_ffmpeg_free(void** ptr) +{ + if(*ptr) free(*ptr); + *ptr = 0; +} + + +struct CvCapture_FFMPEG +{ + bool open( const char* filename ); + void close(); + + double getProperty(int); + bool setProperty(int, double); + bool grabFrame(); + bool retrieveFrame(int, unsigned char** data, int* step, int* width, int* height, int* cn); + + void init(); + bool reopen(); + bool slowSeek( int framenumber ); + + AVFormatContext * ic; + int video_stream; + AVStream * video_st; + AVFrame * picture; + int64_t picture_pts; + AVFrame rgb_picture; + AVPacket packet; + Image_FFMPEG frame; +#if defined(HAVE_FFMPEG_SWSCALE) + struct SwsContext *img_convert_ctx; +#endif +/* + 'filename' contains the filename of the videosource, + 'filename==NULL' indicates that ffmpeg's seek support works + for the particular file. + 'filename!=NULL' indicates that the slow fallback function is used for seeking, + and so the filename is needed to reopen the file on backward seeking. +*/ + char * filename; +}; + + +void CvCapture_FFMPEG::init() +{ + ic = 0; + video_stream = -1; + video_st = 0; + picture = 0; + picture_pts = 0; + memset( &rgb_picture, 0, sizeof(rgb_picture) ); + memset( &frame, 0, sizeof(frame) ); + filename = 0; + packet.data = NULL; +#if defined(HAVE_FFMPEG_SWSCALE) + img_convert_ctx = 0; +#endif +} + + +void CvCapture_FFMPEG::close() +{ + if( picture ) + av_free(picture); + + if( video_st ) + { +#if LIBAVFORMAT_BUILD > 4628 + avcodec_close( video_st->codec ); +#else + avcodec_close( &video_st->codec ); +#endif + video_st = NULL; + } + + if( ic ) + { + av_close_input_file(ic); + ic = NULL; + } + + if( rgb_picture.data[0] ) + { + free( rgb_picture.data[0] ); + rgb_picture.data[0] = 0; + } + + // free last packet if exist + if (packet.data) { + av_free_packet (&packet); + } + + + init(); +} + + +/* + Used to reopen a video if the slower fallback function for seeking is used. +*/ +bool CvCapture_FFMPEG::reopen() +{ + if ( filename==NULL ) return false; + +#if LIBAVFORMAT_BUILD > 4628 + avcodec_close( video_st->codec ); +#else + avcodec_close( &video_st->codec ); +#endif + av_close_input_file(ic); + + // reopen video + av_open_input_file(&ic, filename, NULL, 0, NULL); + av_find_stream_info(ic); +#if LIBAVFORMAT_BUILD > 4628 + AVCodecContext *enc = ic->streams[video_stream]->codec; +#else + AVCodecContext *enc = &ic->streams[video_stream]->codec; +#endif + AVCodec *codec = avcodec_find_decoder(enc->codec_id); + avcodec_open(enc, codec); + video_st = ic->streams[video_stream]; + + // reset framenumber to zero + picture_pts=0; + + return true; +} + +#ifndef AVSEEK_FLAG_FRAME + #define AVSEEK_FLAG_FRAME 0 +#endif + +bool CvCapture_FFMPEG::open( const char* _filename ) +{ + unsigned i; + bool valid = false; + + close(); + + /* register all codecs, demux and protocols */ + av_register_all(); + +#ifndef _DEBUG + // av_log_level = AV_LOG_QUIET; +#endif + + int err = av_open_input_file(&ic, _filename, NULL, 0, NULL); + if (err < 0) { + CV_WARN("Error opening file"); + goto exit_func; + } + err = av_find_stream_info(ic); + if (err < 0) { + CV_WARN("Could not find codec parameters"); + goto exit_func; + } + for(i = 0; i < ic->nb_streams; i++) { +#if LIBAVFORMAT_BUILD > 4628 + AVCodecContext *enc = ic->streams[i]->codec; +#else + AVCodecContext *enc = &ic->streams[i]->codec; +#endif + + if( CODEC_TYPE_VIDEO == enc->codec_type && video_stream < 0) { + AVCodec *codec = avcodec_find_decoder(enc->codec_id); + if (!codec || + avcodec_open(enc, codec) < 0) + goto exit_func; + video_stream = i; + video_st = ic->streams[i]; + picture = avcodec_alloc_frame(); + + rgb_picture.data[0] = (uint8_t*)malloc( + avpicture_get_size( PIX_FMT_BGR24, + enc->width, enc->height )); + avpicture_fill( (AVPicture*)&rgb_picture, rgb_picture.data[0], + PIX_FMT_BGR24, enc->width, enc->height ); + + frame.width = enc->width; + frame.height = enc->height; + frame.cn = 3; + frame.step = rgb_picture.linesize[0]; + frame.data = rgb_picture.data[0]; + break; + } + } + + if(video_stream >= 0) valid = true; + + // perform check if source is seekable via ffmpeg's seek function av_seek_frame(...) + err = av_seek_frame(ic, video_stream, 10, 0); + if (err < 0) + { + filename=(char*)malloc(strlen(_filename)+1); + strcpy(filename, _filename); + // reopen videofile to 'seek' back to first frame + reopen(); + } + else + { + // seek seems to work, so we don't need the filename, + // but we still need to seek back to filestart + filename=NULL; + int64_t ts = video_st->first_dts; + int flags = AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD; + av_seek_frame(ic, video_stream, ts, flags); + } +exit_func: + + if( !valid ) + close(); + + return valid; +} + + +bool CvCapture_FFMPEG::grabFrame() +{ + bool valid = false; + static bool bFirstTime = true; + int got_picture; + + // First time we're called, set packet.data to NULL to indicate it + // doesn't have to be freed + if (bFirstTime) { + bFirstTime = false; + packet.data = NULL; + } + + if( !ic || !video_st ) + return false; + + // free last packet if exist + if (packet.data != NULL) { + av_free_packet (&packet); + } + + // get the next frame + while (!valid) { + int ret = av_read_frame(ic, &packet); + if (ret == AVERROR(EAGAIN)) + continue; + if (ret < 0) + break; + + if( packet.stream_index != video_stream ) { + av_free_packet (&packet); + continue; + } + +#if LIBAVFORMAT_BUILD > 4628 + avcodec_decode_video(video_st->codec, + picture, &got_picture, + packet.data, packet.size); +#else + avcodec_decode_video(&video_st->codec, + picture, &got_picture, + packet.data, packet.size); +#endif + + if (got_picture) { + // we have a new picture, so memorize it + picture_pts = packet.pts; + valid = 1; + } + } + + // return if we have a new picture or not + return valid; +} + + +bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* width, int* height, int* cn) +{ + if( !video_st || !picture->data[0] ) + return false; + +#if !defined(HAVE_FFMPEG_SWSCALE) +#if LIBAVFORMAT_BUILD > 4628 + img_convert( (AVPicture*)&rgb_picture, PIX_FMT_BGR24, + (AVPicture*)picture, + video_st->codec->pix_fmt, + video_st->codec->width, + video_st->codec->height ); +#else + img_convert( (AVPicture*)&rgb_picture, PIX_FMT_BGR24, + (AVPicture*)picture, + video_st->codec.pix_fmt, + video_st->codec.width, + video_st->codec.height ); +#endif +#else + img_convert_ctx = sws_getContext(video_st->codec->width, + video_st->codec->height, + video_st->codec->pix_fmt, + video_st->codec->width, + video_st->codec->height, + PIX_FMT_BGR24, + SWS_BICUBIC, + NULL, NULL, NULL); + + sws_scale(img_convert_ctx, picture->data, + picture->linesize, 0, + video_st->codec->height, + rgb_picture.data, rgb_picture.linesize); + sws_freeContext(img_convert_ctx); +#endif + *data = frame.data; + *step = frame.step; + *width = frame.width; + *height = frame.height; + *cn = frame.cn; + + return true; +} + +#if defined(__APPLE__) +#define AV_NOPTS_VALUE_ ((int64_t)0x8000000000000000LL) +#else +#define AV_NOPTS_VALUE_ ((int64_t)AV_NOPTS_VALUE) +#endif + +double CvCapture_FFMPEG::getProperty( int property_id ) +{ + // if( !capture || !video_st || !picture->data[0] ) return 0; + if( !video_st ) return 0; + + double frameScale = av_q2d (video_st->time_base) * av_q2d (video_st->r_frame_rate); + int64_t timestamp; + timestamp = picture_pts; + + switch( property_id ) + { + case CV_FFMPEG_CAP_PROP_POS_MSEC: + if(video_st->parser && video_st->parser->dts != AV_NOPTS_VALUE_) + return (((double)video_st->parser->dts-1) *1000.0f) * av_q2d (video_st->time_base); + if(video_st->cur_dts != AV_NOPTS_VALUE_) + return ((video_st->cur_dts-video_st->first_dts) * 1000.0 * av_q2d (video_st->time_base)); + break; + case CV_FFMPEG_CAP_PROP_POS_FRAMES: + if(video_st->parser && video_st->parser->dts != AV_NOPTS_VALUE_) + return (double)video_st->parser->dts-1; + if(video_st->cur_dts != AV_NOPTS_VALUE_) + return((video_st->cur_dts-video_st->first_dts) * frameScale); + break; + case CV_FFMPEG_CAP_PROP_POS_AVI_RATIO: + if(video_st->parser && video_st->parser->dts != AV_NOPTS_VALUE_) + return (double)(video_st->parser->dts-1)/(double)video_st->duration; + if(video_st->cur_dts != AV_NOPTS_VALUE_ && video_st->duration != AV_NOPTS_VALUE_) + return(((video_st->cur_dts-video_st->first_dts)+(1.0/frameScale)) / (double)video_st->duration); + break; + case CV_FFMPEG_CAP_PROP_FRAME_COUNT: + if(video_st->duration != AV_NOPTS_VALUE_) + return (double)video_st->duration * frameScale; + break; + case CV_FFMPEG_CAP_PROP_FRAME_WIDTH: + return (double)frame.width; + break; + case CV_FFMPEG_CAP_PROP_FRAME_HEIGHT: + return (double)frame.height; + break; + case CV_FFMPEG_CAP_PROP_FPS: +#if LIBAVCODEC_BUILD > 4753 + return av_q2d (video_st->r_frame_rate); +#else + return (double)video_st->codec.frame_rate + / (double)video_st->codec.frame_rate_base; +#endif + break; + case CV_FFMPEG_CAP_PROP_FOURCC: +#if LIBAVFORMAT_BUILD > 4628 + return (double)video_st->codec->codec_tag; +#else + return (double)video_st->codec.codec_tag; +#endif + break; + } + return 0; +} + + + +// this is a VERY slow fallback function, ONLY used if ffmpeg's av_seek_frame delivers no correct result! +bool CvCapture_FFMPEG::slowSeek( int framenumber ) +{ + if ( framenumber>picture_pts ) + { + while ( picture_ptsstreams[video_stream]->first_dts; + AVRational time_base = ic->streams[video_stream]->time_base; + AVRational frame_base = ic->streams[video_stream]->r_frame_rate; + double timeScale = (time_base.den / (double)time_base.num) / (frame_base.num / frame_base.den); + switch( property_id ) + { + case CV_FFMPEG_CAP_PROP_POS_FRAMES: + timestamp += (int64_t)(value * timeScale); + if(ic->start_time != AV_NOPTS_VALUE_) + timestamp += ic->start_time; + break; + + case CV_FFMPEG_CAP_PROP_POS_MSEC: + timestamp +=(int64_t)(value*(float(time_base.den)/float(time_base.num))/1000); + if(ic->start_time != AV_NOPTS_VALUE_) + timestamp += ic->start_time; + break; + + case CV_FFMPEG_CAP_PROP_POS_AVI_RATIO: + timestamp += (int64_t)(value*ic->duration); + if(ic->start_time != AV_NOPTS_VALUE_ && ic->duration != AV_NOPTS_VALUE_) + timestamp += ic->start_time; + break; + } + + if ( filename ) + { + // ffmpeg's seek doesn't work... + if (!slowSeek((int)timestamp)) + { + fprintf(stderr, "HIGHGUI ERROR: AVI: could not (slow) seek to position %0.3f\n", + (double)timestamp / AV_TIME_BASE); + return false; + } + } + else + { + int flags = AVSEEK_FLAG_FRAME; + if (timestamp < ic->streams[video_stream]->cur_dts) + flags |= AVSEEK_FLAG_BACKWARD; + int ret = av_seek_frame(ic, video_stream, timestamp, flags); + if (ret < 0) + { + fprintf(stderr, "HIGHGUI ERROR: AVI: could not seek to position %0.3f\n", + (double)timestamp / AV_TIME_BASE); + return false; + } + } + picture_pts=(int64_t)value; + } + break; + + default: + return false; + } + + return true; +} + + +///////////////// FFMPEG CvVideoWriter implementation ////////////////////////// +struct CvVideoWriter_FFMPEG +{ + bool open( const char* filename, int fourcc, + double fps, int width, int height, bool isColor ); + void close(); + bool writeFrame( const unsigned char* data, int step, int width, int height, int cn, int origin ); + + void init(); + + AVOutputFormat *fmt; + AVFormatContext *oc; + uint8_t * outbuf; + uint32_t outbuf_size; + FILE * outfile; + AVFrame * picture; + AVFrame * input_picture; + uint8_t * picbuf; + AVStream * video_st; + int input_pix_fmt; + Image_FFMPEG temp_image; +#if defined(HAVE_FFMPEG_SWSCALE) + struct SwsContext *img_convert_ctx; +#endif +}; + +static const char * icvFFMPEGErrStr(int err) +{ + switch(err) { + case AVERROR_NUMEXPECTED: + return "Incorrect filename syntax"; + case AVERROR_INVALIDDATA: + return "Invalid data in header"; + case AVERROR_NOFMT: + return "Unknown format"; + case AVERROR_IO: + return "I/O error occurred"; + case AVERROR_NOMEM: + return "Memory allocation error"; + default: + break; + } + return "Unspecified error"; +} + +/* function internal to FFMPEG (libavformat/riff.c) to lookup codec id by fourcc tag*/ +extern "C" { + enum CodecID codec_get_bmp_id(unsigned int tag); +} + +void CvVideoWriter_FFMPEG::init() +{ + fmt = 0; + oc = 0; + outbuf = 0; + outbuf_size = 0; + outfile = 0; + picture = 0; + input_picture = 0; + picbuf = 0; + video_st = 0; + input_pix_fmt = 0; + memset(&temp_image, 0, sizeof(temp_image)); +#if defined(HAVE_FFMPEG_SWSCALE) + img_convert_ctx = 0; +#endif +} + +/** + * the following function is a modified version of code + * found in ffmpeg-0.4.9-pre1/output_example.c + */ +static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bool alloc) +{ + AVFrame * picture; + uint8_t * picture_buf; + int size; + + picture = avcodec_alloc_frame(); + if (!picture) + return NULL; + size = avpicture_get_size( (PixelFormat) pix_fmt, width, height); + if(alloc){ + picture_buf = (uint8_t *) malloc(size); + if (!picture_buf) + { + av_free(picture); + return NULL; + } + avpicture_fill((AVPicture *)picture, picture_buf, + (PixelFormat) pix_fmt, width, height); + } + else { + } + return picture; +} + +/* add a video output stream to the container */ +static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc, + CodecID codec_id, + int w, int h, int bitrate, + double fps, int pixel_format) +{ + AVCodecContext *c; + AVStream *st; + int frame_rate, frame_rate_base; + AVCodec *codec; + + + st = av_new_stream(oc, 0); + if (!st) { + CV_WARN("Could not allocate stream"); + return NULL; + } + +#if LIBAVFORMAT_BUILD > 4628 + c = st->codec; +#else + c = &(st->codec); +#endif + +#if LIBAVFORMAT_BUILD > 4621 + c->codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, CODEC_TYPE_VIDEO); +#else + c->codec_id = oc->oformat->video_codec; +#endif + + if(codec_id != CODEC_ID_NONE){ + c->codec_id = codec_id; + } + + //if(codec_tag) c->codec_tag=codec_tag; + codec = avcodec_find_encoder(c->codec_id); + + c->codec_type = CODEC_TYPE_VIDEO; + + /* put sample parameters */ + c->bit_rate = bitrate; + + /* 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. */ + frame_rate=(int)(fps+0.5); + frame_rate_base=1; + while (fabs((double)frame_rate/frame_rate_base) - fps > 0.001){ + frame_rate_base*=10; + frame_rate=(int)(fps*frame_rate_base + 0.5); + } +#if LIBAVFORMAT_BUILD > 4752 + c->time_base.den = frame_rate; + c->time_base.num = frame_rate_base; + /* adjust time base for supported framerates */ + if(codec && codec->supported_framerates){ + const AVRational *p= codec->supported_framerates; + AVRational req = {frame_rate, frame_rate_base}; + const AVRational *best=NULL; + AVRational best_error= {INT_MAX, 1}; + for(; 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; + } + } + c->time_base.den= best->num; + c->time_base.num= best->den; + } +#else + c->frame_rate = frame_rate; + c->frame_rate_base = frame_rate_base; +#endif + + c->gop_size = 12; /* emit one intra frame every twelve frames at most */ + c->pix_fmt = (PixelFormat) pixel_format; + + if (c->codec_id == CODEC_ID_MPEG2VIDEO) { + c->max_b_frames = 2; + } + if (c->codec_id == CODEC_ID_MPEG1VIDEO || c->codec_id == CODEC_ID_MSMPEG4V3){ + /* needed to avoid using macroblocks in which some coeffs overflow + this doesnt happen with normal video, it just happens here as the + motion of the chroma plane doesnt 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 seperate + if(oc->oformat->flags & AVFMT_GLOBALHEADER) + { + c->flags |= CODEC_FLAG_GLOBAL_HEADER; + } +#endif + + return st; +} + +int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_t * outbuf, uint32_t outbuf_size, AVFrame * picture ) +{ + +#if LIBAVFORMAT_BUILD > 4628 + AVCodecContext * c = video_st->codec; +#else + AVCodecContext * c = &(video_st->codec); +#endif + int out_size; + int ret; + + if (oc->oformat->flags & AVFMT_RAWPICTURE) { + /* raw video case. The API will change slightly in the near + futur for that */ + AVPacket pkt; + av_init_packet(&pkt); + + pkt.flags |= PKT_FLAG_KEY; + pkt.stream_index= video_st->index; + pkt.data= (uint8_t *)picture; + pkt.size= sizeof(AVPicture); + + ret = av_write_frame(oc, &pkt); + } else { + /* encode the image */ + out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture); + /* if zero size, it means the image was buffered */ + if (out_size > 0) { + AVPacket pkt; + av_init_packet(&pkt); + +#if LIBAVFORMAT_BUILD > 4752 + pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_st->time_base); +#else + pkt.pts = c->coded_frame->pts; +#endif + if(c->coded_frame->key_frame) + pkt.flags |= PKT_FLAG_KEY; + pkt.stream_index= video_st->index; + pkt.data= outbuf; + pkt.size= out_size; + + /* write the compressed frame in the media file */ + ret = av_write_frame(oc, &pkt); + } else { + ret = 0; + } + } + if (ret != 0) return -1; + + return 0; +} + +/// write a frame with FFMPEG +bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int width, int height, int cn, int origin ) +{ + bool ret = false; + + // typecast from opaque data type to implemented struct +#if LIBAVFORMAT_BUILD > 4628 + AVCodecContext *c = video_st->codec; +#else + AVCodecContext *c = &(video_st->codec); +#endif + +#if LIBAVFORMAT_BUILD < 5231 + // It is not needed in the latest versions of the ffmpeg + if( c->codec_id == CODEC_ID_RAWVIDEO && origin != 1 ) + { + if( !temp_image.data ) + { + temp_image.step = (width*cn + 3) & -4; + temp_image.width = width; + temp_image.height = height; + temp_image.cn = cn; + temp_image.data = malloc(temp_image.step*temp_image.height); + } + for( int y = 0; y < height; y++ ) + memcpy(temp_image.data + y*temp_image.step, data + (height-1-y)*step, width*cn); + data = temp_image.data; + step = temp_image.step; + } +#endif + + // check parameters + if (input_pix_fmt == PIX_FMT_BGR24) { + if (cn != 3) { + return false; + } + } + else if (input_pix_fmt == PIX_FMT_GRAY8) { + if (cn != 1) { + return false; + } + } + else { + assert(false); + } + + // check if buffer sizes match, i.e. image has expected format (size, channels, bitdepth, alignment) +/*#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(37<<8)+0) + assert (image->imageSize == avpicture_get_size( (PixelFormat)input_pix_fmt, image->width, image->height )); +#else + assert (image->imageSize == avpicture_get_size( input_pix_fmt, image->width, image->height )); +#endif*/ + + if ( c->pix_fmt != input_pix_fmt ) { + assert( input_picture ); + // let input_picture point to the raw data buffer of 'image' + avpicture_fill((AVPicture *)input_picture, (uint8_t *) data, + (PixelFormat)input_pix_fmt, width, height); + +#if !defined(HAVE_FFMPEG_SWSCALE) + // convert to the color format needed by the codec + if( img_convert((AVPicture *)picture, c->pix_fmt, + (AVPicture *)input_picture, (PixelFormat)input_pix_fmt, + width, height) < 0){ + return false; + } +#else + img_convert_ctx = sws_getContext(width, + height, + PIX_FMT_BGR24, + c->width, + c->height, + c->pix_fmt, + SWS_BICUBIC, + NULL, NULL, NULL); + + if ( sws_scale(img_convert_ctx, input_picture->data, + input_picture->linesize, 0, + height, + picture->data, picture->linesize) < 0 ) + { + return false; + } + sws_freeContext(img_convert_ctx); +#endif + } + else{ + avpicture_fill((AVPicture *)picture, (uint8_t *) data, + (PixelFormat)input_pix_fmt, width, height); + } + + ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, picture) >= 0; + + return ret; +} + +/// close video output stream and free associated memory +void CvVideoWriter_FFMPEG::close() +{ + unsigned i; + + // nothing to do if already released + if ( !picture ) + return; + + /* 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? + + /* write the trailer, if any */ + av_write_trailer(oc); + + // free pictures +#if LIBAVFORMAT_BUILD > 4628 + if( video_st->codec->pix_fmt != input_pix_fmt){ +#else + if( video_st->codec.pix_fmt != input_pix_fmt){ +#endif + if(picture->data[0]) + free(picture->data[0]); + picture->data[0] = 0; + } + av_free(picture); + + if (input_picture) { + av_free(input_picture); + } + + /* close codec */ +#if LIBAVFORMAT_BUILD > 4628 + avcodec_close(video_st->codec); +#else + avcodec_close(&(video_st->codec)); +#endif + + av_free(outbuf); + + /* free the streams */ + for(i = 0; i < oc->nb_streams; i++) { + av_freep(&oc->streams[i]->codec); + av_freep(&oc->streams[i]); + } + + if (!(fmt->flags & AVFMT_NOFILE)) { + /* close the output file */ + + +#if LIBAVCODEC_VERSION_INT >= ((51<<16)+(49<<8)+0) + url_fclose(oc->pb); +#else + url_fclose(&oc->pb); +#endif + + } + + /* free the stream */ + av_free(oc); + + if( temp_image.data ) + { + free(temp_image.data); + temp_image.data = 0; + } + + init(); +} + +/// Create a video writer object that uses FFMPEG +bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, + double fps, int width, int height, bool is_color ) +{ + CodecID codec_id = CODEC_ID_NONE; + int err, codec_pix_fmt, bitrate_scale=64; + + close(); + + // check arguments + assert (filename); + assert (fps > 0); + assert (width > 0 && height > 0); + + // tell FFMPEG to register codecs + av_register_all (); + + /* auto detect the output format from the name and fourcc code. */ + fmt = guess_format(NULL, filename, NULL); + if (!fmt) + return false; + + /* determine optimal pixel format */ + if (is_color) { + input_pix_fmt = PIX_FMT_BGR24; + } + else { + input_pix_fmt = PIX_FMT_GRAY8; + } + + /* Lookup codec_id for given fourcc */ +#if LIBAVCODEC_VERSION_INT<((51<<16)+(49<<8)+0) + if( (codec_id = codec_get_bmp_id( fourcc )) == CODEC_ID_NONE ) + return false; +#else + const struct AVCodecTag * tags[] = { codec_bmp_tags, NULL}; + if( (codec_id = av_codec_get_id(tags, fourcc)) == CODEC_ID_NONE ) + return false; +#endif + + // alloc memory for context + oc = av_alloc_format_context(); + assert (oc); + + /* set file name */ + oc->oformat = fmt; + snprintf(oc->filename, sizeof(oc->filename), "%s", filename); + + /* set some options */ + 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.. + switch (codec_id) { +#if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0) + case CODEC_ID_JPEGLS: + // BGR24 or GRAY8 depending on is_color... + codec_pix_fmt = input_pix_fmt; + break; +#endif + case CODEC_ID_HUFFYUV: + codec_pix_fmt = PIX_FMT_YUV422P; + break; + case CODEC_ID_MJPEG: + case CODEC_ID_LJPEG: + codec_pix_fmt = PIX_FMT_YUVJ420P; + bitrate_scale = 128; + break; + case CODEC_ID_RAWVIDEO: + codec_pix_fmt = input_pix_fmt; + break; + default: + // good for lossy formats, MPEG, etc. + codec_pix_fmt = PIX_FMT_YUV420P; + break; + } + + // TODO -- safe to ignore output audio stream? + video_st = icv_add_video_stream_FFMPEG(oc, codec_id, + width, height, width*height*bitrate_scale, + fps, codec_pix_fmt); + + + /* set the output parameters (must be done even if no + parameters). */ + if (av_set_parameters(oc, NULL) < 0) { + return false; + } + + dump_format(oc, 0, filename, 1); + + /* now that all the parameters are set, we can open the audio and + video codecs and allocate the necessary encode buffers */ + if (!video_st){ + return false; + } + + AVCodec *codec; + AVCodecContext *c; + +#if LIBAVFORMAT_BUILD > 4628 + c = (video_st->codec); +#else + c = &(video_st->codec); +#endif + + c->codec_tag = fourcc; + /* find the video encoder */ + codec = avcodec_find_encoder(c->codec_id); + if (!codec) { + return false; + } + + c->bit_rate_tolerance = c->bit_rate; + + /* open the codec */ + if ( (err=avcodec_open(c, codec)) < 0) { + char errtext[256]; + sprintf(errtext, "Could not open codec '%s': %s", codec->name, icvFFMPEGErrStr(err)); + return false; + } + + outbuf = NULL; + + if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) { + /* allocate output buffer */ + /* assume we will never get codec output with more than 4 bytes per pixel... */ + outbuf_size = width*height*4; + outbuf = (uint8_t *) av_malloc(outbuf_size); + } + + bool need_color_convert; + need_color_convert = (c->pix_fmt != input_pix_fmt); + + /* allocate the encoded raw picture */ + picture = icv_alloc_picture_FFMPEG(c->pix_fmt, c->width, c->height, need_color_convert); + if (!picture) { + return false; + } + + /* if the output format is not our input format, then a temporary + picture of the input format is needed too. It is then converted + to the required output format */ + input_picture = NULL; + if ( need_color_convert ) { + input_picture = icv_alloc_picture_FFMPEG(input_pix_fmt, c->width, c->height, false); + if (!input_picture) { + return false; + } + } + + /* open the output file, if needed */ + if (!(fmt->flags & AVFMT_NOFILE)) { + if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) { + return false; + } + } + + /* write the stream header, if any */ + av_write_header( oc ); + + return true; +} + + + +CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG( const char* filename ) +{ + CvCapture_FFMPEG* capture = (CvCapture_FFMPEG*)malloc(sizeof(*capture)); + capture->init(); + if( capture->open( filename )) + return capture; + capture->close(); + free(capture); + return 0; +} + + +void cvReleaseCapture_FFMPEG(CvCapture_FFMPEG** capture) +{ + if( capture && *capture ) + { + (*capture)->close(); + free(*capture); + *capture = 0; + } +} + +int cvSetCaptureProperty_FFMPEG(CvCapture_FFMPEG* capture, int prop_id, double value) +{ + return capture->setProperty(prop_id, value); +} + +double cvGetCaptureProperty_FFMPEG(CvCapture_FFMPEG* capture, int prop_id) +{ + return capture->getProperty(prop_id); +} + +int cvGrabFrame_FFMPEG(CvCapture_FFMPEG* capture) +{ + return capture->grabFrame(); +} + +int cvRetrieveFrame_FFMPEG(CvCapture_FFMPEG* capture, unsigned char** data, int* step, int* width, int* height, int* cn) +{ + return capture->retrieveFrame(0, data, step, width, height, cn); +} + + + +CvVideoWriter_FFMPEG* cvCreateVideoWriter_FFMPEG( const char* filename, int fourcc, double fps, + int width, int height, int isColor ) +{ + CvVideoWriter_FFMPEG* writer = (CvVideoWriter_FFMPEG*)malloc(sizeof(*writer)); + writer->init(); + if( writer->open( filename, fourcc, fps, width, height, isColor != 0 )) + return writer; + writer->close(); + free(writer); + return 0; +} + + +void cvReleaseVideoWriter_FFMPEG( CvVideoWriter_FFMPEG** writer ) +{ + if( writer && *writer ) + { + (*writer)->close(); + free(*writer); + *writer = 0; + } +} + + +int cvWriteFrame_FFMPEG( CvVideoWriter_FFMPEG* writer, + const unsigned char* data, int step, + int width, int height, int cn, int origin) +{ + return writer->writeFrame(data, step, width, height, cn, origin); +} + diff --git a/modules/highgui/src/cap_w32.cpp b/modules/highgui/src/cap_w32.cpp deleted file mode 100644 index 80e5f6aa2f..0000000000 --- a/modules/highgui/src/cap_w32.cpp +++ /dev/null @@ -1,222 +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. -// -// -// Intel License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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 "precomp.hpp" - -extern "C" -{ -typedef void* (*CvCreateFileCapture_Plugin)( const char* filename ); -typedef void* (*CvCreateCameraCapture_Plugin)( int index ); -typedef int (*CvGrabFrame_Plugin)( void* capture_handle ); -typedef IplImage* (*CvRetrieveFrame_Plugin)( void* capture_handle, int ); -typedef int (*CvSetCaptureProperty_Plugin)( void* capture_handle, int prop_id, double value ); -typedef double (*CvGetCaptureProperty_Plugin)( void* capture_handle, int prop_id ); -typedef void (*CvReleaseCapture_Plugin)( void** capture_handle ); -typedef void* (*CvCreateVideoWriter_Plugin)( const char* filename, int fourcc, - double fps, CvSize frameSize, int isColor ); -typedef int (*CvWriteFrame_Plugin)( void* writer_handle, const IplImage* frame ); -typedef void (*CvReleaseVideoWriter_Plugin)( void** writer ); -} - -static HMODULE icvFFOpenCV = 0; -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 void -icvInitFFMPEG(void) -{ - static int ffmpegInitialized = 0; - if( !ffmpegInitialized ) - { -#ifdef __MINGW32__ -#define ffopencv_prefix "lib" -#else -#define ffopencv_prefix "" -#endif -#if defined(_DEBUG) -#define ffopencv_suffix_dbg "d" -#else -#define ffopencv_suffix_dbg "" -#endif -#if defined EM64T -#define ffopencv_suffix "_64" -#else -#define ffopencv_suffix "" -#endif - -#define ffopencv_name_m2(a,b,c) ffopencv_prefix "opencv_ffmpeg" #a #b #c ffopencv_suffix ffopencv_suffix_dbg ".dll" -#define ffopencv_name_m(a,b,c) ffopencv_name_m2(a,b,c) - const char* ffopencv_name = - ffopencv_name_m(CV_MAJOR_VERSION,CV_MINOR_VERSION,CV_SUBMINOR_VERSION); - - icvFFOpenCV = LoadLibrary( ffopencv_name ); - 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"); - } - ffmpegInitialized = 1; - } -} - - -class CvCapture_FFMPEG_proxy : public CvCapture -{ -public: - CvCapture_FFMPEG_proxy() { ffmpegCapture = 0; } - virtual ~CvCapture_FFMPEG_proxy() { close(); } - - virtual double getProperty(int propId) - { - return ffmpegCapture ? icvGetCaptureProperty_FFMPEG_p(ffmpegCapture, propId) : 0; - } - virtual bool setProperty(int propId, double value) - { - return ffmpegCapture ? icvSetCaptureProperty_FFMPEG_p(ffmpegCapture, propId, value)!=0 : false; - } - virtual bool grabFrame() - { - return ffmpegCapture ? icvGrabFrame_FFMPEG_p(ffmpegCapture)!=0 : false; - } - virtual IplImage* retrieveFrame(int) - { - return ffmpegCapture ? icvRetrieveFrame_FFMPEG_p(ffmpegCapture,0) : 0; - } - virtual bool open( const char* filename ) - { - close(); - - icvInitFFMPEG(); - if( !icvCreateFileCapture_FFMPEG_p ) - return false; - ffmpegCapture = icvCreateFileCapture_FFMPEG_p( filename ); - return ffmpegCapture != 0; - } - virtual void close() - { - if( ffmpegCapture && icvReleaseCapture_FFMPEG_p ) - icvReleaseCapture_FFMPEG_p( &ffmpegCapture ); - assert( ffmpegCapture == 0 ); - ffmpegCapture = 0; - } - -protected: - void* ffmpegCapture; -}; - - -CvCapture* cvCreateFileCapture_Win32(const char * filename) -{ - CvCapture_FFMPEG_proxy* result = new CvCapture_FFMPEG_proxy; - if( result->open( filename )) - return result; - delete result; - return cvCreateFileCapture_VFW(filename); -} - - -class CvVideoWriter_FFMPEG_proxy : public CvVideoWriter -{ -public: - CvVideoWriter_FFMPEG_proxy() { ffmpegWriter = 0; } - virtual ~CvVideoWriter_FFMPEG_proxy() { close(); } - - virtual bool writeFrame( const IplImage* image ) - { - return ffmpegWriter ? icvWriteFrame_FFMPEG_p(ffmpegWriter, image)!=0 : false; - } - virtual bool open( const char* filename, int fourcc, double fps, CvSize frameSize, bool isColor ) - { - close(); - icvInitFFMPEG(); - if( !icvCreateVideoWriter_FFMPEG_p ) - return false; - ffmpegWriter = icvCreateVideoWriter_FFMPEG_p( filename, fourcc, fps, frameSize, isColor ); - return ffmpegWriter != 0; - } - - virtual void close() - { - if( ffmpegWriter && icvReleaseVideoWriter_FFMPEG_p ) - icvReleaseVideoWriter_FFMPEG_p( &ffmpegWriter ); - assert( ffmpegWriter == 0 ); - ffmpegWriter = 0; - } - -protected: - void* ffmpegWriter; -}; - - -CvVideoWriter* cvCreateVideoWriter_Win32( const char* filename, int fourcc, - double fps, CvSize frameSize, int isColor ) -{ - CvVideoWriter_FFMPEG_proxy* result = new CvVideoWriter_FFMPEG_proxy; - - if( result->open( filename, fourcc, fps, frameSize, isColor != 0 )) - return result; - delete result; - - return cvCreateVideoWriter_VFW(filename, fourcc, fps, frameSize, isColor); -} diff --git a/modules/highgui/src/precomp.hpp b/modules/highgui/src/precomp.hpp index 8e3b1734d6..bbdc1d7340 100644 --- a/modules/highgui/src/precomp.hpp +++ b/modules/highgui/src/precomp.hpp @@ -147,11 +147,11 @@ CvCapture* cvCreateFileCapture_XINE (const char* filename); #define CV_CAP_GSTREAMER_V4L2 2 #define CV_CAP_GSTREAMER_FILE 3 -CvCapture * cvCreateCapture_GStreamer(int type, const char *filename); -CVAPI(CvCapture*) cvCreateFileCapture_FFMPEG (const char* filename); +CvCapture* cvCreateCapture_GStreamer(int type, const char *filename); +CvCapture* cvCreateFileCapture_FFMPEG_proxy(const char* filename); -CVAPI(CvVideoWriter*) cvCreateVideoWriter_FFMPEG ( const char* filename, int fourcc, +CvVideoWriter* cvCreateVideoWriter_FFMPEG_proxy( const char* filename, int fourcc, double fps, CvSize frameSize, int is_color ); CvCapture * cvCreateFileCapture_QT (const char * filename);