diff --git a/0001-highgui-Fix-unresolved-OpenGL-functions-for-Qt-backe.patch b/0001-highgui-Fix-unresolved-OpenGL-functions-for-Qt-backe.patch deleted file mode 100644 index c77817d..0000000 --- a/0001-highgui-Fix-unresolved-OpenGL-functions-for-Qt-backe.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 2835c13cbd14f4f41996a2c1f73ef860c89c20f1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Stefan=20Br=C3=BCns?= -Date: Sun, 26 Dec 2021 00:08:06 +0100 -Subject: [PATCH] highgui: Fix unresolved OpenGL functions for Qt backend - -The Qt backend directly calls some OpenGL functions (glClear, glHint, -glViewport), but since OCV 4.5.5 the GL libraries are no longer part -of the global extra dependencies. When linking with "-Wl,--no-undefined" -this causes linker errors: - -`opencv-4.5.5/modules/highgui/src/window_QT.cpp:3307: undefined reference to `glClear'` - -Related issues: #21299 ---- - modules/highgui/CMakeLists.txt | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/modules/highgui/CMakeLists.txt b/modules/highgui/CMakeLists.txt -index 6123ea1436..45e66dfa1e 100644 ---- a/modules/highgui/CMakeLists.txt -+++ b/modules/highgui/CMakeLists.txt -@@ -279,6 +279,10 @@ if(OPENCV_HIGHGUI_BUILTIN_BACKEND STREQUAL "WIN32UI" AND HAVE_OPENGL AND OPENGL_ - ocv_target_link_libraries(${the_module} PRIVATE "${OPENGL_LIBRARIES}") - endif() - -+if(OPENCV_HIGHGUI_BUILTIN_BACKEND MATCHES "^QT" AND HAVE_OPENGL AND OPENGL_LIBRARIES) -+ ocv_target_link_libraries(${the_module} PRIVATE "${OPENGL_LIBRARIES}") -+endif() -+ - if(MSVC AND NOT BUILD_SHARED_LIBS AND BUILD_WITH_STATIC_CRT) - set_target_properties(${the_module} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:atlsd.lib /NODEFAULTLIB:libcmt.lib /DEBUG") - endif() --- -2.34.1 - diff --git a/opencv-4.5.5.tar.gz b/opencv-4.5.5.tar.gz deleted file mode 100644 index 7b0aa05..0000000 --- a/opencv-4.5.5.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a1cfdcf6619387ca9e232687504da996aaa9f7b5689986b8331ec02cb61d28ad -size 89879893 diff --git a/opencv-4.6.0.tar.gz b/opencv-4.6.0.tar.gz new file mode 100644 index 0000000..fb32ac0 --- /dev/null +++ b/opencv-4.6.0.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1ec1cba65f9f20fe5a41fda1586e01c70ea0c9a6d7b67c9e13edf0cfe2239277 +size 90208971 diff --git a/opencv.changes b/opencv.changes index 7a8ba65..26ac2c3 100644 --- a/opencv.changes +++ b/opencv.changes @@ -1,3 +1,92 @@ +------------------------------------------------------------------- +Sun Jun 19 13:25:26 UTC 2022 - Stefan Brüns + +- update to 4.6.0, highlights below, for details check + https://github.com/opencv/opencv/wiki/ChangeLog#version460 + * OpenCV project infrastructure migrating on GitHub Actions + workflows for CI and release purposes + * Added support for GCC 12, Clang 15 + * Added support for FFmpeg 5.0 + * DNN module patches: + + Improved layers / activations / supported more models: + - LSTM (+CUDA), resize (+ONNX13), Sign, Shrink, Reciprocal, + depth2space, space2depth + - fixes in Reduce, Slice, Expand + + Disabled floating-point denormals processing #21521 + + Changed layer names in ONNX importer to support "output" + entities properly + + Added TIM-VX NPU backend support: + https://github.com/opencv/opencv/wiki/TIM-VX-Backend-For-Running-OpenCV-On-NPU + + Added Softmax parameter to ClassificationModel + + Added audio speech recognition sample (C++) #21458 + + Intel® Inference Engine backend (OpenVINO): + - added initial support for OpenVINO 2022.1 release + - removed support of legacy API (dropped since 2020.3) + * G-API module: + + G-API framework: + - Introduced a Grayscale image format support for + cv::MediaFrame: #21511; + - Enabeled .reshape() support in the CPU backend: #21669; + - Fixed possible hang in streaming execution mode with constant + inputs: #21567; + - Introduced proper error/exception propagation in the + asynchronous streaming execution mode: #21660; + - Fixed new stream event handling: #21731. + + Fluid backend: + - Fixed horizontal pass in the Resize kernel, fixed Valgrind + issues: #21144; + - Extended Resize kernel with F32 version: #21678, + added AVX: #21728. + - Enabled dynamic dispatch for Split4 kernel: #21520; + - Enabled dynamic dispatch for Merge3 kernel: #21529; + - Added a SIMD version for DivC kernel: #21474; + - Added a SIMD version for DivRC kernel: #21530; + - Enabled dynamic dispatch for Add kernel: #21686; + - Enabled dynamic dispatch for Sub kernel: #21746; + - Added a SIMD version for ConvertTo kernel: #21777; + - Fixed kernel matrix size for Sobel kernel: #21613. + + Intel® OpenVINO™ inference backend: + - Fixed NV12 format support for remote memory when OpenVINO + remote context is used: #21424. + - Implemented correct error handling in the backend: #21579. + - Fixed ngraph warnings #21362. + + OpenCV AI Kit backend: + - Introduced a new backend to program OpenCV AI Kit boards via + G-API. Currently the backend is in experimental state, but allows + to build Camera+NN pipeline and supports heterogeneity (mixing + with host-side code): #20785, #21504. + + Media integration: + - Enabled GPU inference with oneVPL and DirectX11 on Windows in + Intel OpenVINO inference backend: #21232, #21618, #21658, #21687, + #21688. Now GPU textures decoded by oneVPL decoder can be + preprocessed and inferred on GPU with no extra host processing. + - Enabled oneVPL support on Linux: #21883. + - Extended GStreamer pipeline source with Grayscale image format + support: #21560. + + Python bindings: + - Exposed GStreamer pipeline source in Python bindings: #20832. + - Fixed Python bindings for CudaBufferPool, cudacodec and cudastereo + modules in OpenCV Contrib. + + Samples: + - Introduced a pipeline modelling tool for cascaded model + benchmarking: #21477, #21636, #21719. The tool supports a + declarative YAML-based config to describe pipelines with simulated + pre-/post-processing. The tool collects and reports latency and + throughput information for the modelled pipeline. + + Other changes and fixes: + - Moved GKernelPackage into cv:: namespace by default, its cv::gapi:: + alias remain for compatibility: #21318; + - Moved Resize kernel from core to imgproc kernel packages for + CPU, OpenCL, and Fluid backends: #21157. Also moved tests + appropriately: #21475; + - Avoided sporadic test failures in DivC: #21626; + - Fixed 1D Mat handling in the framework: #21782; + - Reduced the number of G-API generated accuracy tests: #21909. +- Drop upstream patches: + * 0001-highgui-Fix-unresolved-OpenGL-functions-for-Qt-backe.patch + * videoio_initial_FFmpeg_5_0_support.patch + * videoio_ffmpeg_avoid_memory_leaks.patch + ------------------------------------------------------------------- Fri Apr 29 16:54:16 UTC 2022 - Stefan Brüns diff --git a/opencv.spec b/opencv.spec index dfddb5c..b6b98d8 100644 --- a/opencv.spec +++ b/opencv.spec @@ -22,20 +22,15 @@ %endif %define libname lib%{name} -%define soname 405 +%define soname 406 # disabled by default as many fail %bcond_with tests %bcond_without gapi %bcond_without ffmpeg -%if %{suse_version} < 1550 -%bcond_without python2 -%else -%bcond_with python2 -%endif %bcond_without python3 %bcond_without openblas Name: opencv -Version: 4.5.5 +Version: 4.6.0 Release: 0 Summary: Collection of algorithms for computer vision # GPL-2.0 AND Apache-2.0 files are in 3rdparty/ittnotify which is not build @@ -45,12 +40,6 @@ URL: https://opencv.org/ Source0: https://github.com/opencv/opencv/archive/%{version}.tar.gz#/%{name}-%{version}.tar.gz # Several modules from the opencv_contrib package Source1: https://github.com/opencv/opencv_contrib/archive/%{version}.tar.gz#/opencv_contrib-%{version}.tar.gz -# PATCH-FIX-UPSTREAM -Patch0: 0001-highgui-Fix-unresolved-OpenGL-functions-for-Qt-backe.patch -# PATCH-FIX-UPSTREAM -Patch1: https://github.com/opencv/opencv/pull/21754.patch#/videoio_initial_FFmpeg_5_0_support.patch -# PATCH-FIX-UPSTREAM -Patch2: https://github.com/opencv/opencv/commit/271f7df3435c619ceba9261f88dcfbb0714b0b0d.patch#/videoio_ffmpeg_avoid_memory_leaks.patch BuildRequires: cmake BuildRequires: fdupes BuildRequires: libeigen3-devel @@ -82,11 +71,6 @@ BuildRequires: ade-devel >= 0.1.0 %if %{with openblas} BuildRequires: openblas-devel %endif -%if %{with python2} -BuildRequires: python-rpm-macros -BuildRequires: pkgconfig(python) -BuildRequires: python2-numpy-devel -%endif %if %{with python3} BuildRequires: python-rpm-macros BuildRequires: python3-numpy-devel @@ -113,7 +97,7 @@ Computer Vision algorithms. Summary: Classifier cascades for OpenCV License: BSD-3-Clause Group: System/Libraries -Conflicts: %{name} < %{version}-%{release} +Conflicts: %{name} < 4.5.1 Provides: %{name}:%{_datadir}/opencv4/lbpcascades/lbpcascade_silverware.xml BuildArch: noarch @@ -148,11 +132,18 @@ Requires: %{name}4-cascades-data %description -n libopencv_face%{soname} Face detection libraries for OpenCV +%package -n libopencv_gapi%{soname} +Summary: G-API library component for OpenCV +License: BSD-3-Clause +Group: System/Libraries + +%description -n libopencv_gapi%{soname} +G-API library component for OpenCV + %package -n libopencv_highgui%{soname} Summary: Higlevel GUI libraries for OpenCV License: BSD-3-Clause Group: System/Libraries -Conflicts: %{libname}%{soname} < %{version}-%{release} %description -n libopencv_highgui%{soname} Higlevel GUI libraries for OpenCV @@ -161,7 +152,6 @@ Higlevel GUI libraries for OpenCV Summary: Image codec libraries for OpenCV License: BSD-3-Clause Group: System/Libraries -Conflicts: %{libname}%{soname} < %{version}-%{release} %description -n libopencv_imgcodecs%{soname} Image codec libraries for OpenCV @@ -170,7 +160,6 @@ Image codec libraries for OpenCV Summary: Superresolution libraries for OpenCV License: BSD-3-Clause Group: System/Libraries -Conflicts: %{libname}%{soname} < %{version}-%{release} %description -n libopencv_superres%{soname} Superresolution libraries for OpenCV @@ -179,17 +168,23 @@ Superresolution libraries for OpenCV Summary: Face detection libraries for OpenCV License: BSD-3-Clause Group: System/Libraries -Conflicts: %{libname}%{soname} < %{version}-%{release} Requires: %{name}4-cascades-data %description -n libopencv_objdetect%{soname} Object detection libraries for OpenCV +%package -n libopencv_optflow%{soname} +Summary: Optical flow calculation libraries for OpenCV +License: BSD-3-Clause +Group: System/Libraries + +%description -n libopencv_optflow%{soname} +Optical flow calculation libraries for OpenCV + %package -n libopencv_videoio%{soname} Summary: Video IO libraries for OpenCV License: BSD-3-Clause Group: System/Libraries -Conflicts: %{libname}%{soname} < %{version}-%{release} %description -n libopencv_videoio%{soname} Video IO libraries for OpenCV @@ -198,7 +193,6 @@ Video IO libraries for OpenCV Summary: Video stabilization libraries for OpenCV License: BSD-3-Clause Group: System/Libraries -Conflicts: %{libname}%{soname} < %{version}-%{release} %description -n libopencv_videostab%{soname} Video stabilization libraries for OpenCV @@ -207,7 +201,6 @@ Video stabilization libraries for OpenCV Summary: Image processing libraries for OpenCV License: BSD-3-Clause Group: System/Libraries -Conflicts: %{libname}%{soname} < %{version}-%{release} %description -n libopencv_ximgproc%{soname} Image processing libraries for OpenCV @@ -219,9 +212,11 @@ Group: Development/Libraries/C and C++ Requires: %{libname}%{soname} = %{version} Requires: libopencv_aruco%{soname} = %{version} Requires: libopencv_face%{soname} = %{version} +Requires: libopencv_gapi%{soname} = %{version} Requires: libopencv_highgui%{soname} = %{version} Requires: libopencv_imgcodecs%{soname} = %{version} Requires: libopencv_objdetect%{soname} = %{version} +Requires: libopencv_optflow%{soname} = %{version} Requires: libopencv_superres%{soname} = %{version} Requires: libopencv_videoio%{soname} = %{version} Requires: libopencv_videostab%{soname} = %{version} @@ -241,18 +236,6 @@ This package contains the OpenCV C/C++ library and header files, as well as documentation. It should be installed if you want to develop programs that will use the OpenCV library. -%package -n python2-%{name} -Summary: Python 2 bindings for apps which use OpenCV -License: BSD-3-Clause -Group: Development/Libraries/Python -Provides: python-%{name} = %{version}-%{release} -Obsoletes: python-%{name} < %{version}-%{release} -Provides: python-%{name}-qt5 = %{version} -Obsoletes: python-%{name}-qt5 < %{version} - -%description -n python2-%{name} -This package contains Python 2 bindings for the OpenCV library. - %package -n python3-%{name} Summary: Python 3 bindings for apps which use OpenCV License: BSD-3-Clause @@ -267,11 +250,11 @@ This package contains Python 3 bindings for the OpenCV library. Summary: Documentation and examples for OpenCV License: BSD-3-Clause Group: Documentation/Other -Recommends: python # Since this package also contains examples that need -devel to be compiled Suggests: %{name}-devel Provides: %{name}-qt5-doc = %{version} Obsoletes: %{name}-qt5-doc < %{version} +BuildArch: noarch %description doc This package contains the documentation and examples for the OpenCV library. @@ -282,6 +265,7 @@ This package contains the documentation and examples for the OpenCV library. # Only copy over modules we need mv opencv_contrib-%{version}/modules/{aruco,face,tracking,optflow,plot,shape,superres,videostab,ximgproc} modules/ +rm -Rf opencv_contrib-%{version}/modules/* cp opencv_contrib-%{version}/LICENSE LICENSE.contrib # Remove Windows specific files @@ -307,9 +291,10 @@ rm -f doc/packaging.txt -DOPENCV_GENERATE_PKGCONFIG=ON \ -DINSTALL_C_EXAMPLES=ON \ -DINSTALL_PYTHON_EXAMPLES=ON \ - -DENABLE_OMIT_FRAME_POINTER=OFF \ + -DENABLE_OMIT_FRAME_POINTER=ON \ -DWITH_QT=ON \ -DWITH_OPENGL=ON \ + -DOpenGL_GL_PREFERENCE:STRING="GLVND" \ -DWITH_UNICAP=ON \ -DWITH_XINE=ON \ -DWITH_IPP=OFF \ @@ -342,7 +327,6 @@ rm -f doc/packaging.txt %endif -DPYTHON_DEFAULT_EXECUTABLE=%{_bindir}/python3 \ -DOPENCV_SKIP_PYTHON_LOADER=ON \ - -DOPENCV_PYTHON2_INSTALL_PATH=%{python2_sitearch} \ -DOPENCV_PYTHON3_INSTALL_PATH=%{python3_sitearch} \ -DOPENCV_DOWNLOAD_TRIES_LIST:STRING="" \ -DWITH_JASPER=OFF \ @@ -362,6 +346,7 @@ chmod 644 %{buildroot}%{_docdir}/%{name}-doc/examples/python/*.py rm %{buildroot}%{_bindir}/setup_vars_opencv4.sh # Fix duplicated install prefix in pkg-config file +cat %{buildroot}%{_libdir}/pkgconfig/opencv4.pc sed -i -e 's|//usr||g' %{buildroot}%{_libdir}/pkgconfig/opencv4.pc %fdupes -s %{buildroot}%{_docdir}/%{name}-doc/examples @@ -384,12 +369,16 @@ grep -E 'model|stepping|flags' /proc/cpuinfo | head -n4 %postun -n libopencv_aruco%{soname} -p /sbin/ldconfig %post -n libopencv_face%{soname} -p /sbin/ldconfig %postun -n libopencv_face%{soname} -p /sbin/ldconfig +%post -n libopencv_gapi%{soname} -p /sbin/ldconfig +%postun -n libopencv_gapi%{soname} -p /sbin/ldconfig %post -n libopencv_highgui%{soname} -p /sbin/ldconfig %postun -n libopencv_highgui%{soname} -p /sbin/ldconfig %post -n libopencv_imgcodecs%{soname} -p /sbin/ldconfig %postun -n libopencv_imgcodecs%{soname} -p /sbin/ldconfig %post -n libopencv_objdetect%{soname} -p /sbin/ldconfig %postun -n libopencv_objdetect%{soname} -p /sbin/ldconfig +%post -n libopencv_optflow%{soname} -p /sbin/ldconfig +%postun -n libopencv_optflow%{soname} -p /sbin/ldconfig %post -n libopencv_superres%{soname} -p /sbin/ldconfig %postun -n libopencv_superres%{soname} -p /sbin/ldconfig %post -n libopencv_videoio%{soname} -p /sbin/ldconfig @@ -417,12 +406,8 @@ grep -E 'model|stepping|flags' /proc/cpuinfo | head -n4 %{_libdir}/libopencv_dnn.so.* %{_libdir}/libopencv_features2d.so.* %{_libdir}/libopencv_flann.so.* -%if %{with gapi} -%{_libdir}/libopencv_gapi.so.* -%endif %{_libdir}/libopencv_imgproc.so.* %{_libdir}/libopencv_ml.so.* -%{_libdir}/libopencv_optflow.so.* %{_libdir}/libopencv_photo.so.* %{_libdir}/libopencv_plot.so.* %{_libdir}/libopencv_shape.so.* @@ -436,6 +421,11 @@ grep -E 'model|stepping|flags' /proc/cpuinfo | head -n4 %files -n libopencv_face%{soname} %{_libdir}/libopencv_face.so.* +%if %{with gapi} +%files -n libopencv_gapi%{soname} +%{_libdir}/libopencv_gapi.so.* +%endif + %files -n libopencv_highgui%{soname} %{_libdir}/libopencv_highgui.so.* @@ -445,6 +435,9 @@ grep -E 'model|stepping|flags' /proc/cpuinfo | head -n4 %files -n libopencv_objdetect%{soname} %{_libdir}/libopencv_objdetect.so.* +%files -n libopencv_optflow%{soname} +%{_libdir}/libopencv_optflow.so.* + %files -n libopencv_superres%{soname} %{_libdir}/libopencv_superres.so.* @@ -467,12 +460,6 @@ grep -E 'model|stepping|flags' /proc/cpuinfo | head -n4 %{_libdir}/cmake/opencv4/OpenCVModules*.cmake %{_datadir}/opencv4/valgrind* -%if %{with python2} -%files -n python2-%{name} -%license LICENSE LICENSE.contrib -%{python_sitearch}/cv2.so -%endif - %if %{with python3} %files -n python3-%{name} %license LICENSE LICENSE.contrib diff --git a/opencv_contrib-4.5.5.tar.gz b/opencv_contrib-4.5.5.tar.gz deleted file mode 100644 index 7c39048..0000000 --- a/opencv_contrib-4.5.5.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a97c2eaecf7a23c6dbd119a609c6d7fae903e5f9ff5f1fe678933e01c67a6c11 -size 60563220 diff --git a/opencv_contrib-4.6.0.tar.gz b/opencv_contrib-4.6.0.tar.gz new file mode 100644 index 0000000..8fcbde3 --- /dev/null +++ b/opencv_contrib-4.6.0.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1777d5fd2b59029cf537e5fd6f8aa68d707075822f90bde683fcde086f85f7a7 +size 59667769 diff --git a/videoio_ffmpeg_avoid_memory_leaks.patch b/videoio_ffmpeg_avoid_memory_leaks.patch deleted file mode 100644 index f6ddbdf..0000000 --- a/videoio_ffmpeg_avoid_memory_leaks.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 271f7df3435c619ceba9261f88dcfbb0714b0b0d Mon Sep 17 00:00:00 2001 -From: Alexander Alekhin -Date: Fri, 1 Apr 2022 18:02:14 +0000 -Subject: [PATCH] videoio(ffmpeg): avoid memory leaks - ---- - modules/videoio/src/cap_ffmpeg_impl.hpp | 21 ++++++++++----------- - 1 file changed, 10 insertions(+), 11 deletions(-) - -diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp -index 91a0f710aa63..b7fa0b745c1e 100644 ---- a/modules/videoio/src/cap_ffmpeg_impl.hpp -+++ b/modules/videoio/src/cap_ffmpeg_impl.hpp -@@ -2496,17 +2496,13 @@ double CvVideoWriter_FFMPEG::getProperty(int propId) const - /// close video output stream and free associated memory - void CvVideoWriter_FFMPEG::close() - { -- // 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 */ -- if(ok && oc) -+ if (picture && ok && oc) - { - #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(57, 0, 0) - if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) -@@ -2529,7 +2525,7 @@ void CvVideoWriter_FFMPEG::close() - } - - // free pictures -- if( context->pix_fmt != input_pix_fmt) -+ if (picture && context && context->pix_fmt != input_pix_fmt) - { - if(picture->data[0]) - free(picture->data[0]); -@@ -2540,8 +2536,14 @@ void CvVideoWriter_FFMPEG::close() - if (input_picture) - av_free(input_picture); - -+#ifdef CV_FFMPEG_CODECPAR -+ avcodec_free_context(&context); -+#else - /* close codec */ -- avcodec_close(context); -+ if (context) // fixed after https://github.com/FFmpeg/FFmpeg/commit/3e1f507f3e8f16b716aa115552d243b48ae809bd -+ avcodec_close(context); -+ context = NULL; -+#endif - - av_free(outbuf); - -@@ -2935,10 +2937,7 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, - #endif - - #ifdef CV_FFMPEG_CODECPAR -- if (context) -- { -- avcodec_free_context(&context); -- } -+ avcodec_free_context(&context); - #endif - context = icv_configure_video_stream_FFMPEG(oc, video_st, codec, - width, height, (int) (bitrate + 0.5), diff --git a/videoio_initial_FFmpeg_5_0_support.patch b/videoio_initial_FFmpeg_5_0_support.patch deleted file mode 100644 index 91ccfaf..0000000 --- a/videoio_initial_FFmpeg_5_0_support.patch +++ /dev/null @@ -1,1001 +0,0 @@ -From 5440fd6cb43ea65a056c46b691fcdab1a425e92d Mon Sep 17 00:00:00 2001 -From: Maksim Shabunin -Date: Sat, 19 Mar 2022 20:06:50 +0300 -Subject: [PATCH] videoio: initial FFmpeg 5.0 support - ---- - modules/videoio/src/cap_ffmpeg_impl.hpp | 442 ++++++++++++++++-------- - 1 file changed, 304 insertions(+), 138 deletions(-) - -diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp -index 43c555309b9d..91a0f710aa63 100644 ---- a/modules/videoio/src/cap_ffmpeg_impl.hpp -+++ b/modules/videoio/src/cap_ffmpeg_impl.hpp -@@ -41,6 +41,8 @@ - //M*/ - - #include "cap_ffmpeg_legacy_api.hpp" -+#include "opencv2/core/utils/logger.hpp" -+#include "cap_interface.hpp" - - using namespace cv; - -@@ -49,6 +51,7 @@ using namespace cv; - #endif - #include - #include -+#include - - #ifndef __OPENCV_BUILD - #define CV_FOURCC(c1, c2, c3, c4) (((c1) & 255) + (((c2) & 255) << 8) + (((c3) & 255) << 16) + (((c4) & 255) << 24)) -@@ -79,6 +82,7 @@ extern "C" { - - #include - #include -+#include - - #if LIBAVUTIL_BUILD >= (LIBAVUTIL_VERSION_MICRO >= 100 \ - ? CALC_FFMPEG_VERSION(51, 63, 100) : CALC_FFMPEG_VERSION(54, 6, 0)) -@@ -88,6 +92,62 @@ extern "C" { - #include - #include - -+// https://github.com/FFmpeg/FFmpeg/blob/b6af56c034759b81985f8ea094e41cbd5f7fecfb/doc/APIchanges#L602-L605 -+#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(58, 9, 100) -+# define CV_FFMPEG_REGISTER -+#endif -+ -+// https://github.com/FFmpeg/FFmpeg/blob/b6af56c034759b81985f8ea094e41cbd5f7fecfb/doc/APIchanges#L654-L657 -+#if LIBAVCODEC_BUILD < CALC_FFMPEG_VERSION(58, 9, 100) -+# define CV_FFMPEG_LOCKMGR -+#endif -+ -+// https://github.com/FFmpeg/FFmpeg/blob/b6af56c034759b81985f8ea094e41cbd5f7fecfb/doc/APIchanges#L390-L392 -+#if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(58, 87, 100) -+#include -+#endif -+ -+// https://github.com/FFmpeg/FFmpeg/blob/b6af56c034759b81985f8ea094e41cbd5f7fecfb/doc/APIchanges#L208-L210 -+#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(59, 0, 100) -+# define CV_FFMPEG_FMT_CONST const -+#else -+# define CV_FFMPEG_FMT_CONST -+#endif -+ -+// https://github.com/FFmpeg/FFmpeg/blob/b6af56c034759b81985f8ea094e41cbd5f7fecfb/doc/APIchanges#L623-L624 -+#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(58, 7, 100) -+# define CV_FFMPEG_URL -+#endif -+ -+// AVStream.codec deprecated in favor of AVStream.codecpar -+// https://github.com/FFmpeg/FFmpeg/blob/b6af56c034759b81985f8ea094e41cbd5f7fecfb/doc/APIchanges#L1039-L1040 -+#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(59, 16, 100) -+//#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(57, 33, 100) -+# define CV_FFMPEG_CODECPAR -+# define CV_FFMPEG_CODEC_FIELD codecpar -+#else -+# define CV_FFMPEG_CODEC_FIELD codec -+#endif -+ -+#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(59, 16, 100) -+# define CV_FFMPEG_PTS_FIELD pts -+#else -+# define CV_FFMPEG_PTS_FIELD pkt_pts -+#endif -+ -+// https://github.com/FFmpeg/FFmpeg/blob/b6af56c034759b81985f8ea094e41cbd5f7fecfb/doc/APIchanges#L1757-L1758 -+#if LIBAVUTIL_BUILD < CALC_FFMPEG_VERSION(52, 63, 100) -+inline static AVRational av_make_q(int num, int den) -+{ -+ AVRational res; -+ res.num = num; -+ res.den = den; -+ return res; -+} -+#endif -+ -+ -+ - #ifdef __cplusplus - } - #endif -@@ -471,6 +531,15 @@ static AVRational _opencv_ffmpeg_get_sample_aspect_ratio(AVStream *stream) - #endif - } - -+inline static std::string _opencv_ffmpeg_get_error_string(int error_code) -+{ -+ char buf[255] = {0}; -+ const int err = av_strerror(error_code, buf, 254); -+ if (err == 0) -+ return std::string(buf); -+ else -+ return std::string("Unknown error"); -+} - - struct CvCapture_FFMPEG - { -@@ -502,6 +571,7 @@ struct CvCapture_FFMPEG - - AVFormatContext * ic; - AVCodec * avcodec; -+ AVCodecContext * context; - int video_stream; - AVStream * video_st; - AVFrame * picture; -@@ -565,6 +635,7 @@ void CvCapture_FFMPEG::init() - img_convert_ctx = 0; - - avcodec = 0; -+ context = 0; - frame_number = 0; - eps_zero = 0.000025; - -@@ -617,10 +688,19 @@ void CvCapture_FFMPEG::close() - - if( video_st ) - { -- avcodec_close( video_st->codec ); -+#ifdef CV_FFMPEG_CODECPAR -+ avcodec_close( context ); -+#endif - video_st = NULL; - } - -+ if (context) -+ { -+#ifdef CV_FFMPEG_CODECPAR -+ avcodec_free_context(&context); -+#endif -+ } -+ - if( ic ) - { - avformat_close_input(&ic); -@@ -798,8 +878,10 @@ class AutoLock - }; - #endif - -+ - static ImplMutex _mutex; - -+#ifdef CV_FFMPEG_LOCKMGR - static int LockCallBack(void **mutex, AVLockOp op) - { - ImplMutex* localMutex = reinterpret_cast(*mutex); -@@ -830,7 +912,7 @@ static int LockCallBack(void **mutex, AVLockOp op) - } - return 0; - } -- -+#endif - - static void ffmpeg_log_callback(void *ptr, int level, const char *fmt, va_list vargs) - { -@@ -881,19 +963,59 @@ class InternalFFMpegRegister - { - avformat_network_init(); - -+#ifdef CV_FFMPEG_REGISTER - /* register all codecs, demux and protocols */ - av_register_all(); -+#endif - -+#ifdef CV_FFMPEG_LOCKMGR - /* register a callback function for synchronization */ - av_lockmgr_register(&LockCallBack); -+#endif - } - ~InternalFFMpegRegister() - { -+#ifdef CV_FFMPEG_LOCKMGR - av_lockmgr_register(NULL); -+#endif - av_log_set_callback(NULL); - } - }; - -+inline void fill_codec_context(AVCodecContext * enc, AVDictionary * dict) -+{ -+//#ifdef FF_API_THREAD_INIT -+// avcodec_thread_init(enc, get_number_of_cpus()); -+//#else -+ enc->thread_count = get_number_of_cpus(); -+//#endif -+ -+ AVDictionaryEntry* avdiscard_entry = av_dict_get(dict, "avdiscard", NULL, 0); -+ -+ if (avdiscard_entry) -+ { -+ if(strcmp(avdiscard_entry->value, "all") == 0) -+ enc->skip_frame = AVDISCARD_ALL; -+ else if (strcmp(avdiscard_entry->value, "bidir") == 0) -+ enc->skip_frame = AVDISCARD_BIDIR; -+ else if (strcmp(avdiscard_entry->value, "default") == 0) -+ enc->skip_frame = AVDISCARD_DEFAULT; -+ else if (strcmp(avdiscard_entry->value, "none") == 0) -+ enc->skip_frame = AVDISCARD_NONE; -+ // NONINTRA flag was introduced with version bump at revision: -+ // https://github.com/FFmpeg/FFmpeg/commit/b152152df3b778d0a86dcda5d4f5d065b4175a7b -+ // This key is supported only for FFMPEG version -+#if LIBAVCODEC_VERSION_MICRO >= 100 && LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(55, 67, 100) -+ else if (strcmp(avdiscard_entry->value, "nonintra") == 0) -+ enc->skip_frame = AVDISCARD_NONINTRA; -+#endif -+ else if (strcmp(avdiscard_entry->value, "nonkey") == 0) -+ enc->skip_frame = AVDISCARD_NONKEY; -+ else if (strcmp(avdiscard_entry->value, "nonref") == 0) -+ enc->skip_frame = AVDISCARD_NONREF; -+ } -+} -+ - bool CvCapture_FFMPEG::open(const char* _filename, const VideoCaptureParameters& params) - { - InternalFFMpegRegister::init(); -@@ -997,7 +1119,7 @@ bool CvCapture_FFMPEG::open(const char* _filename, const VideoCaptureParameters& - #else - av_dict_set(&dict, "rtsp_transport", "tcp", 0); - #endif -- AVInputFormat* input_format = NULL; -+ CV_FFMPEG_FMT_CONST AVInputFormat* input_format = NULL; - AVDictionaryEntry* entry = av_dict_get(dict, "input_format", NULL, 0); - if (entry != 0) - { -@@ -1015,60 +1137,44 @@ bool CvCapture_FFMPEG::open(const char* _filename, const VideoCaptureParameters& - err = avformat_find_stream_info(ic, NULL); - if (err < 0) - { -- CV_WARN("Could not find codec parameters"); -+ CV_LOG_WARNING(NULL, "Unable to read codec parameters from stream (" << _opencv_ffmpeg_get_error_string(err) << ")"); - goto exit_func; - } - for(i = 0; i < ic->nb_streams; i++) - { -- AVCodecContext* enc = ic->streams[i]->codec; -- --//#ifdef FF_API_THREAD_INIT --// avcodec_thread_init(enc, get_number_of_cpus()); --//#else -- enc->thread_count = get_number_of_cpus(); --//#endif -- -- AVDictionaryEntry* avdiscard_entry = av_dict_get(dict, "avdiscard", NULL, 0); -- -- if (avdiscard_entry) { -- if(strcmp(avdiscard_entry->value, "all") == 0) -- enc->skip_frame = AVDISCARD_ALL; -- else if (strcmp(avdiscard_entry->value, "bidir") == 0) -- enc->skip_frame = AVDISCARD_BIDIR; -- else if (strcmp(avdiscard_entry->value, "default") == 0) -- enc->skip_frame = AVDISCARD_DEFAULT; -- else if (strcmp(avdiscard_entry->value, "none") == 0) -- enc->skip_frame = AVDISCARD_NONE; -- // NONINTRA flag was introduced with version bump at revision: -- // https://github.com/FFmpeg/FFmpeg/commit/b152152df3b778d0a86dcda5d4f5d065b4175a7b -- // This key is supported only for FFMPEG version --#if LIBAVCODEC_VERSION_MICRO >= 100 && LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(55, 67, 100) -- else if (strcmp(avdiscard_entry->value, "nonintra") == 0) -- enc->skip_frame = AVDISCARD_NONINTRA; -+#ifndef CV_FFMPEG_CODECPAR -+ context = ic->streams[i]->codec; -+ AVCodecID codec_id = context->codec_id; -+ AVMediaType codec_type = context->codec_type; -+#else -+ AVCodecParameters* par = ic->streams[i]->codecpar; -+ AVCodecID codec_id = par->codec_id; -+ AVMediaType codec_type = par->codec_type; - #endif -- else if (strcmp(avdiscard_entry->value, "nonkey") == 0) -- enc->skip_frame = AVDISCARD_NONKEY; -- else if (strcmp(avdiscard_entry->value, "nonref") == 0) -- enc->skip_frame = AVDISCARD_NONREF; -- } - -- if( AVMEDIA_TYPE_VIDEO == enc->codec_type && video_stream < 0) -+ if( AVMEDIA_TYPE_VIDEO == codec_type && video_stream < 0) - { -- CV_LOG_DEBUG(NULL, "FFMPEG: stream[" << i << "] is video stream with codecID=" << (int)enc->codec_id -- << " width=" << enc->width -- << " height=" << enc->height -+ // backup encoder' width/height -+#ifndef CV_FFMPEG_CODECPAR -+ int enc_width = context->width; -+ int enc_height = context->height; -+#else -+ int enc_width = par->width; -+ int enc_height = par->height; -+#endif -+ -+ CV_LOG_DEBUG(NULL, "FFMPEG: stream[" << i << "] is video stream with codecID=" << (int)codec_id -+ << " width=" << enc_width -+ << " height=" << enc_height - ); - -- // backup encoder' width/height -- int enc_width = enc->width; -- int enc_height = enc->height; - - #if !USE_AV_HW_CODECS - va_type = VIDEO_ACCELERATION_NONE; - #endif - - // find and open decoder, try HW acceleration types specified in 'hw_acceleration' list (in order) -- AVCodec *codec = NULL; -+ const AVCodec *codec = NULL; - err = -1; - #if USE_AV_HW_CODECS - HWAccelIterator accel_iter(va_type, false/*isEncoder*/, dict); -@@ -1080,21 +1186,27 @@ bool CvCapture_FFMPEG::open(const char* _filename, const VideoCaptureParameters& - #if USE_AV_HW_CODECS - accel_iter.parse_next(); - AVHWDeviceType hw_type = accel_iter.hw_type(); -- enc->get_format = avcodec_default_get_format; -- if (enc->hw_device_ctx) { -- av_buffer_unref(&enc->hw_device_ctx); -- } - if (hw_type != AV_HWDEVICE_TYPE_NONE) - { - CV_LOG_DEBUG(NULL, "FFMPEG: trying to configure H/W acceleration: '" << accel_iter.hw_type_device_string() << "'"); - AVPixelFormat hw_pix_fmt = AV_PIX_FMT_NONE; -- codec = hw_find_codec(enc->codec_id, hw_type, av_codec_is_decoder, accel_iter.disabled_codecs().c_str(), &hw_pix_fmt); -- if (codec) { -+ codec = hw_find_codec(codec_id, hw_type, av_codec_is_decoder, accel_iter.disabled_codecs().c_str(), &hw_pix_fmt); -+ if (codec) -+ { -+#ifdef CV_FFMPEG_CODECPAR -+ context = avcodec_alloc_context3(codec); -+#endif -+ CV_Assert(context); -+ context->get_format = avcodec_default_get_format; -+ if (context->hw_device_ctx) { -+ av_buffer_unref(&context->hw_device_ctx); -+ } - if (hw_pix_fmt != AV_PIX_FMT_NONE) -- enc->get_format = hw_get_format_callback; // set callback to select HW pixel format, not SW format -- enc->hw_device_ctx = hw_create_device(hw_type, hw_device, accel_iter.device_subname(), use_opencl != 0); -- if (!enc->hw_device_ctx) -+ context->get_format = hw_get_format_callback; // set callback to select HW pixel format, not SW format -+ context->hw_device_ctx = hw_create_device(hw_type, hw_device, accel_iter.device_subname(), use_opencl != 0); -+ if (!context->hw_device_ctx) - { -+ context->get_format = avcodec_default_get_format; - CV_LOG_DEBUG(NULL, "FFMPEG: ... can't create H/W device: '" << accel_iter.hw_type_device_string() << "'"); - codec = NULL; - } -@@ -1106,10 +1218,10 @@ bool CvCapture_FFMPEG::open(const char* _filename, const VideoCaptureParameters& - AVDictionaryEntry* video_codec_param = av_dict_get(dict, "video_codec", NULL, 0); - if (video_codec_param == NULL) - { -- codec = avcodec_find_decoder(enc->codec_id); -+ codec = avcodec_find_decoder(codec_id); - if (!codec) - { -- CV_LOG_ERROR(NULL, "Could not find decoder for codec_id=" << (int)enc->codec_id); -+ CV_LOG_ERROR(NULL, "Could not find decoder for codec_id=" << (int)codec_id); - } - } - else -@@ -1121,10 +1233,26 @@ bool CvCapture_FFMPEG::open(const char* _filename, const VideoCaptureParameters& - CV_LOG_ERROR(NULL, "Could not find decoder '" << video_codec_param->value << "'"); - } - } -+ if (codec) -+ { -+#ifdef CV_FFMPEG_CODECPAR -+ context = avcodec_alloc_context3(codec); -+#endif -+ CV_Assert(context); -+ } - } - if (!codec) -+ { -+#ifdef CV_FFMPEG_CODECPAR -+ avcodec_free_context(&context); -+#endif - continue; -- err = avcodec_open2(enc, codec, NULL); -+ } -+ fill_codec_context(context, dict); -+#ifdef CV_FFMPEG_CODECPAR -+ avcodec_parameters_to_context(context, par); -+#endif -+ err = avcodec_open2(context, codec, NULL); - if (err >= 0) { - #if USE_AV_HW_CODECS - va_type = hw_type_to_va_type(hw_type); -@@ -1146,10 +1274,10 @@ bool CvCapture_FFMPEG::open(const char* _filename, const VideoCaptureParameters& - } - - // checking width/height (since decoder can sometimes alter it, eg. vp6f) -- if (enc_width && (enc->width != enc_width)) -- enc->width = enc_width; -- if (enc_height && (enc->height != enc_height)) -- enc->height = enc_height; -+ if (enc_width && (context->width != enc_width)) -+ context->width = enc_width; -+ if (enc_height && (context->height != enc_height)) -+ context->height = enc_height; - - video_stream = i; - video_st = ic->streams[i]; -@@ -1160,8 +1288,8 @@ bool CvCapture_FFMPEG::open(const char* _filename, const VideoCaptureParameters& - picture = avcodec_alloc_frame(); - #endif - -- frame.width = enc->width; -- frame.height = enc->height; -+ frame.width = context->width; -+ frame.height = context->height; - frame.cn = 3; - frame.step = 0; - frame.data = NULL; -@@ -1306,7 +1434,7 @@ bool CvCapture_FFMPEG::grabFrame() - int count_errs = 0; - const int max_number_of_attempts = 1 << 9; - -- if( !ic || !video_st ) return false; -+ if( !ic || !video_st || !context ) return false; - - if( ic->streams[video_stream]->nb_frames > 0 && - frame_number > ic->streams[video_stream]->nb_frames ) -@@ -1322,7 +1450,7 @@ bool CvCapture_FFMPEG::grabFrame() - - #if USE_AV_SEND_FRAME_API - // check if we can receive frame from previously decoded packet -- valid = avcodec_receive_frame(video_st->codec, picture) >= 0; -+ valid = avcodec_receive_frame(context, picture) >= 0; - #endif - - // get the next frame -@@ -1372,19 +1500,19 @@ bool CvCapture_FFMPEG::grabFrame() - - // Decode video frame - #if USE_AV_SEND_FRAME_API -- if (avcodec_send_packet(video_st->codec, &packet) < 0) { -+ if (avcodec_send_packet(context, &packet) < 0) { - break; - } -- ret = avcodec_receive_frame(video_st->codec, picture); -+ ret = avcodec_receive_frame(context, picture); - #else - int got_picture = 0; -- avcodec_decode_video2(video_st->codec, picture, &got_picture, &packet); -+ avcodec_decode_video2(context, picture, &got_picture, &packet); - ret = got_picture ? 0 : -1; - #endif - if (ret >= 0) { - //picture_pts = picture->best_effort_timestamp; - if( picture_pts == AV_NOPTS_VALUE_ ) -- picture_pts = picture->pkt_pts != AV_NOPTS_VALUE_ && picture->pkt_pts != 0 ? picture->pkt_pts : picture->pkt_dts; -+ picture_pts = picture->CV_FFMPEG_PTS_FIELD != AV_NOPTS_VALUE_ && picture->CV_FFMPEG_PTS_FIELD != 0 ? picture->CV_FFMPEG_PTS_FIELD : picture->pkt_dts; - - valid = true; - } else if (ret == AVERROR(EAGAIN)) { -@@ -1415,7 +1543,7 @@ bool CvCapture_FFMPEG::grabFrame() - - bool CvCapture_FFMPEG::retrieveFrame(int flag, unsigned char** data, int* step, int* width, int* height, int* cn) - { -- if (!video_st) -+ if (!video_st || !context) - return false; - - if (rawMode || flag == extraDataIdx) -@@ -1428,8 +1556,8 @@ bool CvCapture_FFMPEG::retrieveFrame(int flag, unsigned char** data, int* step, - ret = p.data != NULL; - } - else if (flag == extraDataIdx) { -- *data = ic->streams[video_stream]->codec->extradata; -- *step = ic->streams[video_stream]->codec->extradata_size; -+ *data = ic->streams[video_stream]->CV_FFMPEG_CODEC_FIELD->extradata; -+ *step = ic->streams[video_stream]->CV_FFMPEG_CODEC_FIELD->extradata_size; - } - *width = *step; - *height = 1; -@@ -1454,13 +1582,13 @@ bool CvCapture_FFMPEG::retrieveFrame(int flag, unsigned char** data, int* step, - return false; - - if( img_convert_ctx == NULL || -- frame.width != video_st->codec->width || -- frame.height != video_st->codec->height || -+ frame.width != video_st->CV_FFMPEG_CODEC_FIELD->width || -+ frame.height != video_st->CV_FFMPEG_CODEC_FIELD->height || - frame.data == NULL ) - { - // Some sws_scale optimizations have some assumptions about alignment of data/step/width/height - // Also we use coded_width/height to workaround problem with legacy ffmpeg versions (like n0.8) -- int buffer_width = video_st->codec->coded_width, buffer_height = video_st->codec->coded_height; -+ int buffer_width = context->coded_width, buffer_height = context->coded_height; - - img_convert_ctx = sws_getCachedContext( - img_convert_ctx, -@@ -1494,8 +1622,8 @@ bool CvCapture_FFMPEG::retrieveFrame(int flag, unsigned char** data, int* step, - _opencv_ffmpeg_av_image_fill_arrays(&rgb_picture, rgb_picture.data[0], - AV_PIX_FMT_BGR24, buffer_width, buffer_height ); - #endif -- frame.width = video_st->codec->width; -- frame.height = video_st->codec->height; -+ frame.width = video_st->CV_FFMPEG_CODEC_FIELD->width; -+ frame.height = video_st->CV_FFMPEG_CODEC_FIELD->height; - frame.cn = 3; - frame.data = rgb_picture.data[0]; - frame.step = rgb_picture.linesize[0]; -@@ -1505,7 +1633,7 @@ bool CvCapture_FFMPEG::retrieveFrame(int flag, unsigned char** data, int* step, - img_convert_ctx, - sw_picture->data, - sw_picture->linesize, -- 0, video_st->codec->coded_height, -+ 0, context->coded_height, - rgb_picture.data, - rgb_picture.linesize - ); -@@ -1529,12 +1657,12 @@ bool CvCapture_FFMPEG::retrieveHWFrame(cv::OutputArray output) - { - #if USE_AV_HW_CODECS - // check that we have HW frame in GPU memory -- if (!picture || !picture->hw_frames_ctx) { -+ if (!picture || !picture->hw_frames_ctx || !context) { - return false; - } - - // GPU color conversion NV12->BGRA, from GPU media buffer to GPU OpenCL buffer -- return hw_copy_frame_to_umat(video_st->codec->hw_device_ctx, picture, output); -+ return hw_copy_frame_to_umat(context->hw_device_ctx, picture, output); - #else - CV_UNUSED(output); - return false; -@@ -1543,7 +1671,7 @@ bool CvCapture_FFMPEG::retrieveHWFrame(cv::OutputArray output) - - double CvCapture_FFMPEG::getProperty( int property_id ) const - { -- if( !video_st ) return 0; -+ if( !video_st || !context ) return 0; - - double codec_tag = 0; - CV_CODEC_ID codec_id = AV_CODEC_ID_NONE; -@@ -1570,8 +1698,8 @@ double CvCapture_FFMPEG::getProperty( int property_id ) const - case CAP_PROP_FPS: - return get_fps(); - case CAP_PROP_FOURCC: -- codec_id = video_st->codec->codec_id; -- codec_tag = (double) video_st->codec->codec_tag; -+ codec_id = video_st->CV_FFMPEG_CODEC_FIELD->codec_id; -+ codec_tag = (double) video_st->CV_FFMPEG_CODEC_FIELD->codec_tag; - - if(codec_tag || codec_id == AV_CODEC_ID_NONE) - { -@@ -1591,7 +1719,11 @@ double CvCapture_FFMPEG::getProperty( int property_id ) const - return _opencv_ffmpeg_get_sample_aspect_ratio(ic->streams[video_stream]).den; - case CAP_PROP_CODEC_PIXEL_FORMAT: - { -+#ifdef CV_FFMPEG_CODECPAR -+ AVPixelFormat pix_fmt = (AVPixelFormat)video_st->codecpar->format; -+#else - AVPixelFormat pix_fmt = video_st->codec->pix_fmt; -+#endif - unsigned int fourcc_tag = avcodec_pix_fmt_to_codec_tag(pix_fmt); - return (fourcc_tag == 0) ? (double)-1 : (double)fourcc_tag; - } -@@ -1671,7 +1803,7 @@ double CvCapture_FFMPEG::get_fps() const - - if (fps < eps_zero) - { -- fps = 1.0 / r2d(ic->streams[video_stream]->codec->time_base); -+ fps = 1.0 / r2d(ic->streams[video_stream]->time_base); - } - #endif - return fps; -@@ -1703,7 +1835,16 @@ double CvCapture_FFMPEG::dts_to_sec(int64_t dts) const - void CvCapture_FFMPEG::get_rotation_angle() - { - rotation_angle = 0; --#if LIBAVUTIL_BUILD >= CALC_FFMPEG_VERSION(52, 94, 100) -+#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(57, 68, 100) -+ const uint8_t *data = 0; -+ data = av_stream_get_side_data(video_st, AV_PKT_DATA_DISPLAYMATRIX, NULL); -+ if (data) -+ { -+ rotation_angle = cvRound(av_display_rotation_get((const int32_t*)data)); -+ if (rotation_angle < 0) -+ rotation_angle += 360; -+ } -+#elif LIBAVUTIL_BUILD >= CALC_FFMPEG_VERSION(52, 94, 100) - AVDictionaryEntry *rotate_tag = av_dict_get(video_st->metadata, "rotate", NULL, 0); - if (rotate_tag != NULL) - rotation_angle = atoi(rotate_tag->value); -@@ -1712,6 +1853,7 @@ void CvCapture_FFMPEG::get_rotation_angle() - - void CvCapture_FFMPEG::seek(int64_t _frame_number) - { -+ CV_Assert(context); - _frame_number = std::min(_frame_number, get_total_frames()); - int delta = 16; - -@@ -1728,7 +1870,7 @@ void CvCapture_FFMPEG::seek(int64_t _frame_number) - double time_base = r2d(ic->streams[video_stream]->time_base); - time_stamp += (int64_t)(sec / time_base + 0.5); - if (get_total_frames() > 1) av_seek_frame(ic, video_stream, time_stamp, AVSEEK_FLAG_BACKWARD); -- avcodec_flush_buffers(ic->streams[video_stream]->codec); -+ avcodec_flush_buffers(context); - if( _frame_number > 0 ) - { - grabFrame(); -@@ -1833,7 +1975,7 @@ struct CvVideoWriter_FFMPEG - - void init(); - -- AVOutputFormat * fmt; -+ CV_FFMPEG_FMT_CONST AVOutputFormat * fmt; - AVFormatContext * oc; - uint8_t * outbuf; - uint32_t outbuf_size; -@@ -1842,6 +1984,7 @@ struct CvVideoWriter_FFMPEG - AVFrame * input_picture; - uint8_t * picbuf; - AVStream * video_st; -+ AVCodecContext * context; - AVPixelFormat input_pix_fmt; - unsigned char * aligned_input; - size_t aligned_input_size; -@@ -1906,6 +2049,7 @@ void CvVideoWriter_FFMPEG::init() - input_picture = 0; - picbuf = 0; - video_st = 0; -+ context = 0; - input_pix_fmt = AV_PIX_FMT_NONE; - aligned_input = NULL; - aligned_input_size = 0; -@@ -1957,23 +2101,32 @@ static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bo - } - - /* configure video stream */ --static bool icv_configure_video_stream_FFMPEG(AVFormatContext *oc, -+static AVCodecContext * icv_configure_video_stream_FFMPEG(AVFormatContext *oc, - AVStream *st, - const AVCodec* codec, - int w, int h, int bitrate, -- double fps, AVPixelFormat pixel_format) -+ double fps, AVPixelFormat pixel_format, int fourcc) - { -+#ifdef CV_FFMPEG_CODECPAR -+ AVCodecContext *c = avcodec_alloc_context3(codec); -+#else - AVCodecContext *c = st->codec; -+#endif -+ CV_Assert(c); -+ - int frame_rate, frame_rate_base; - - c->codec_id = codec->id; - c->codec_type = AVMEDIA_TYPE_VIDEO; -+ c->codec_tag = fourcc; - -+#ifndef CV_FFMPEG_CODECPAR - // Set per-codec defaults - CV_CODEC_ID c_id = c->codec_id; - avcodec_get_context_defaults3(c, codec); - // avcodec_get_context_defaults3 erases codec_id for some reason - c->codec_id = c_id; -+#endif - - /* put sample parameters */ - int64_t lbit_rate = (int64_t)bitrate; -@@ -2016,7 +2169,12 @@ static bool icv_configure_video_stream_FFMPEG(AVFormatContext *oc, - } - } - if (best == NULL) -- return false; -+ { -+#ifdef CV_FFMPEG_CODECPAR -+ avcodec_free_context(&c); -+#endif -+ return NULL; -+ } - c->time_base.den= best->num; - c->time_base.num= best->den; - } -@@ -2059,26 +2217,20 @@ static bool icv_configure_video_stream_FFMPEG(AVFormatContext *oc, - #endif - } - --#if defined(_MSC_VER) -- AVRational avg_frame_rate = {frame_rate, frame_rate_base}; -- st->avg_frame_rate = avg_frame_rate; --#else -- st->avg_frame_rate = (AVRational){frame_rate, frame_rate_base}; --#endif -+ st->avg_frame_rate = av_make_q(frame_rate, frame_rate_base); - #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(55, 20, 0) - st->time_base = c->time_base; - #endif - -- return true; -+ return c; - } - - static const int OPENCV_NO_FRAMES_WRITTEN_CODE = 1000; - --static int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, -+static int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, AVCodecContext * c, - uint8_t *, uint32_t, - AVFrame * picture, int frame_idx) - { -- AVCodecContext* c = video_st->codec; - int ret = OPENCV_NO_FRAMES_WRITTEN_CODE; - - #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(57, 0, 0) -@@ -2176,9 +2328,6 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int - width = frame_width; - height = frame_height; - -- // typecast from opaque data type to implemented struct -- AVCodecContext* c = video_st->codec; -- - // FFmpeg contains SIMD optimizations which can sometimes read data past - // the supplied input buffer. - // Related info: https://trac.ffmpeg.org/ticket/6763 -@@ -2215,10 +2364,10 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int - step = aligned_step; - } - -- AVPixelFormat sw_pix_fmt = c->pix_fmt; -+ AVPixelFormat sw_pix_fmt = context->pix_fmt; - #if USE_AV_HW_CODECS -- if (c->hw_frames_ctx) -- sw_pix_fmt = ((AVHWFramesContext*)c->hw_frames_ctx->data)->sw_format; -+ if (context->hw_frames_ctx) -+ sw_pix_fmt = ((AVHWFramesContext*)context->hw_frames_ctx->data)->sw_format; - #endif - if ( sw_pix_fmt != input_pix_fmt ) { - CV_Assert( input_picture ); -@@ -2232,8 +2381,8 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int - img_convert_ctx = sws_getContext(width, - height, - (AVPixelFormat)input_pix_fmt, -- c->width, -- c->height, -+ context->width, -+ context->height, - sw_pix_fmt, - SWS_BICUBIC, - NULL, NULL, NULL); -@@ -2255,14 +2404,14 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int - - bool ret; - #if USE_AV_HW_CODECS -- if (video_st->codec->hw_device_ctx) { -+ if (context->hw_device_ctx) { - // copy data to HW frame - AVFrame* hw_frame = av_frame_alloc(); - if (!hw_frame) { - CV_LOG_ERROR(NULL, "Error allocating AVFrame (av_frame_alloc)"); - return false; - } -- if (av_hwframe_get_buffer(video_st->codec->hw_frames_ctx, hw_frame, 0) < 0) { -+ if (av_hwframe_get_buffer(context->hw_frames_ctx, hw_frame, 0) < 0) { - CV_LOG_ERROR(NULL, "Error obtaining HW frame (av_hwframe_get_buffer)"); - av_frame_free(&hw_frame); - return false; -@@ -2273,14 +2422,14 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int - return false; - } - hw_frame->pts = frame_idx; -- int ret_write = icv_av_write_frame_FFMPEG(oc, video_st, outbuf, outbuf_size, hw_frame, frame_idx); -+ int ret_write = icv_av_write_frame_FFMPEG(oc, video_st, context, outbuf, outbuf_size, hw_frame, frame_idx); - ret = ret_write >= 0 ? true : false; - av_frame_free(&hw_frame); - } else - #endif - { - picture->pts = frame_idx; -- int ret_write = icv_av_write_frame_FFMPEG(oc, video_st, outbuf, outbuf_size, picture, frame_idx); -+ int ret_write = icv_av_write_frame_FFMPEG(oc, video_st, context, outbuf, outbuf_size, picture, frame_idx); - ret = ret_write >= 0 ? true : false; - } - -@@ -2291,7 +2440,7 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int - - bool CvVideoWriter_FFMPEG::writeHWFrame(cv::InputArray input) { - #if USE_AV_HW_CODECS -- if (!video_st->codec->hw_frames_ctx) -+ if (!video_st || !context || !context->hw_frames_ctx || !context->hw_device_ctx) - return false; - - // Get hardware frame from frame pool -@@ -2299,20 +2448,20 @@ bool CvVideoWriter_FFMPEG::writeHWFrame(cv::InputArray input) { - if (!hw_frame) { - return false; - } -- if (av_hwframe_get_buffer(video_st->codec->hw_frames_ctx, hw_frame, 0) < 0) { -+ if (av_hwframe_get_buffer(context->hw_frames_ctx, hw_frame, 0) < 0) { - av_frame_free(&hw_frame); - return false; - } - - // GPU to GPU copy -- if (!hw_copy_umat_to_frame(video_st->codec->hw_device_ctx, input, hw_frame)) { -+ if (!hw_copy_umat_to_frame(context->hw_device_ctx, input, hw_frame)) { - av_frame_free(&hw_frame); - return false; - } - - // encode - hw_frame->pts = frame_idx; -- icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, hw_frame, frame_idx); -+ icv_av_write_frame_FFMPEG( oc, video_st, context, outbuf, outbuf_size, hw_frame, frame_idx); - frame_idx++; - - av_frame_free(&hw_frame); -@@ -2365,7 +2514,7 @@ void CvVideoWriter_FFMPEG::close() - { - for(;;) - { -- int ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, NULL, frame_idx); -+ int ret = icv_av_write_frame_FFMPEG( oc, video_st, context, outbuf, outbuf_size, NULL, frame_idx); - if( ret == OPENCV_NO_FRAMES_WRITTEN_CODE || ret < 0 ) - break; - } -@@ -2380,7 +2529,7 @@ void CvVideoWriter_FFMPEG::close() - } - - // free pictures -- if( video_st->codec->pix_fmt != input_pix_fmt) -+ if( context->pix_fmt != input_pix_fmt) - { - if(picture->data[0]) - free(picture->data[0]); -@@ -2392,7 +2541,7 @@ void CvVideoWriter_FFMPEG::close() - av_free(input_picture); - - /* close codec */ -- avcodec_close(video_st->codec); -+ avcodec_close(context); - - av_free(outbuf); - -@@ -2599,8 +2748,15 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, - - /* set file name */ - oc->oformat = fmt; -+#ifndef CV_FFMPEG_URL - snprintf(oc->filename, sizeof(oc->filename), "%s", filename); -- -+#else -+ size_t name_len = strlen(filename); -+ oc->url = (char*)av_malloc(name_len + 1); -+ CV_Assert(oc->url); -+ memcpy((void*)oc->url, filename, name_len + 1); -+ oc->url[name_len] = '\0'; -+#endif - /* set some options */ - oc->max_delay = (int)(0.7*AV_TIME_BASE); /* This reduces buffer underrun warnings with MPEG */ - -@@ -2715,7 +2871,7 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, - double bitrate = std::min(bitrate_scale*fps*width*height, (double)INT_MAX/2); - - if (codec_id == AV_CODEC_ID_NONE) { -- codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO); -+ codec_id = av_guess_codec(oc->oformat, NULL, filename, NULL, AVMEDIA_TYPE_VIDEO); - } - - // Add video stream to output file -@@ -2733,11 +2889,9 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, - } - #endif - -- AVCodecContext *c = video_st->codec; -- - // find and open encoder, try HW acceleration types specified in 'hw_acceleration' list (in order) - int err = -1; -- AVCodec* codec = NULL; -+ const AVCodec* codec = NULL; - #if USE_AV_HW_CODECS - AVBufferRef* hw_device_ctx = NULL; - HWAccelIterator accel_iter(va_type, true/*isEncoder*/, dict); -@@ -2780,9 +2934,17 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, - AVPixelFormat format = codec_pix_fmt; - #endif - -- if (!icv_configure_video_stream_FFMPEG(oc, video_st, codec, -- width, height, (int) (bitrate + 0.5), -- fps, format)) { -+#ifdef CV_FFMPEG_CODECPAR -+ if (context) -+ { -+ avcodec_free_context(&context); -+ } -+#endif -+ context = icv_configure_video_stream_FFMPEG(oc, video_st, codec, -+ width, height, (int) (bitrate + 0.5), -+ fps, format, fourcc); -+ if (!context) -+ { - continue; - } - -@@ -2794,27 +2956,25 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, - #endif - #endif - -- c->codec_tag = fourcc; -- - #if USE_AV_HW_CODECS - if (hw_device_ctx) { -- c->hw_device_ctx = av_buffer_ref(hw_device_ctx); -+ context->hw_device_ctx = av_buffer_ref(hw_device_ctx); - if (hw_format != AV_PIX_FMT_NONE) { -- c->hw_frames_ctx = hw_create_frames(NULL, hw_device_ctx, width, height, hw_format); -- if (!c->hw_frames_ctx) -+ context->hw_frames_ctx = hw_create_frames(NULL, hw_device_ctx, width, height, hw_format); -+ if (!context->hw_frames_ctx) - continue; - } - } - #endif - -- int64_t lbit_rate = (int64_t) c->bit_rate; -+ int64_t lbit_rate = (int64_t) context->bit_rate; - lbit_rate += (int64_t)(bitrate / 2); - lbit_rate = std::min(lbit_rate, (int64_t) INT_MAX); -- c->bit_rate_tolerance = (int) lbit_rate; -- c->bit_rate = (int) lbit_rate; -+ context->bit_rate_tolerance = (int) lbit_rate; -+ context->bit_rate = (int) lbit_rate; - - /* open the codec */ -- err = avcodec_open2(c, codec, NULL); -+ err = avcodec_open2(context, codec, NULL); - if (err >= 0) { - #if USE_AV_HW_CODECS - va_type = hw_type_to_va_type(hw_type); -@@ -2823,7 +2983,7 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, - #endif - break; - } else { -- CV_LOG_ERROR(NULL, "Could not open codec " << codec->name << ", error: " << icvFFMPEGErrStr(err)); -+ CV_LOG_ERROR(NULL, "Could not open codec " << codec->name << ", error: " << icvFFMPEGErrStr(err) << " (" << err << ")"); - } - #if USE_AV_HW_CODECS - } // while (accel_iter.good()) -@@ -2844,6 +3004,12 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, - return false; - } - -+#ifdef CV_FFMPEG_CODECPAR -+ // Copy all to codecpar... -+ // !!! https://stackoverflow.com/questions/15897849/c-ffmpeg-not-writing-avcc-box-information -+ avcodec_parameters_from_context(video_st->codecpar, context); -+#endif -+ - outbuf = NULL; - - -@@ -2858,16 +3024,16 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, - } - - bool need_color_convert; -- AVPixelFormat sw_pix_fmt = c->pix_fmt; -+ AVPixelFormat sw_pix_fmt = context->pix_fmt; - #if USE_AV_HW_CODECS -- if (c->hw_frames_ctx) -- sw_pix_fmt = ((AVHWFramesContext*)c->hw_frames_ctx->data)->sw_format; -+ if (context->hw_frames_ctx) -+ sw_pix_fmt = ((AVHWFramesContext*)context->hw_frames_ctx->data)->sw_format; - #endif - - need_color_convert = (sw_pix_fmt != input_pix_fmt); - - /* allocate the encoded raw picture */ -- picture = icv_alloc_picture_FFMPEG(sw_pix_fmt, c->width, c->height, need_color_convert); -+ picture = icv_alloc_picture_FFMPEG(sw_pix_fmt, context->width, context->height, need_color_convert); - if (!picture) { - return false; - } -@@ -2877,7 +3043,7 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, - 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); -+ input_picture = icv_alloc_picture_FFMPEG(input_pix_fmt, context->width, context->height, false); - if (!input_picture) { - return false; - }