diff --git a/_constraints b/_constraints
index 0e5b9e6..83ff66d 100644
--- a/_constraints
+++ b/_constraints
@@ -7,5 +7,10 @@
5700
+
+
+
+ 1200
+
diff --git a/opencv.changes b/opencv.changes
index ab6e78c..7a8ba65 100644
--- a/opencv.changes
+++ b/opencv.changes
@@ -1,3 +1,20 @@
+-------------------------------------------------------------------
+Fri Apr 29 16:54:16 UTC 2022 - Stefan Brüns
+
+- Add upstream patches for FFmpeg 5.0 support, add
+ * videoio_initial_FFmpeg_5_0_support.patch
+ * videoio_ffmpeg_avoid_memory_leaks.patch
+
+-------------------------------------------------------------------
+Sat Apr 9 17:42:50 UTC 2022 - Stefan Brüns
+
+- Restore memoryperjob constraint, avoid being scheduled on a 16
+ core system and use less than half of it.
+- Adjust %limit_build to 1800, to avoid recurrent build failures
+ on aarch64. (People should not care for their pet architecture
+ only, but also carefully check if they break others.)
+- Add missing libopencv_aruco dependency in devel package.
+
-------------------------------------------------------------------
Mon Jan 10 11:08:32 UTC 2022 - Antonio Larrosa
diff --git a/opencv.spec b/opencv.spec
index 3a77b5f..dfddb5c 100644
--- a/opencv.spec
+++ b/opencv.spec
@@ -47,6 +47,10 @@ Source0: https://github.com/opencv/opencv/archive/%{version}.tar.gz#/%{na
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
@@ -213,6 +217,7 @@ Summary: Development files for using the OpenCV library
License: BSD-3-Clause
Group: Development/Libraries/C and C++
Requires: %{libname}%{soname} = %{version}
+Requires: libopencv_aruco%{soname} = %{version}
Requires: libopencv_face%{soname} = %{version}
Requires: libopencv_highgui%{soname} = %{version}
Requires: libopencv_imgcodecs%{soname} = %{version}
diff --git a/videoio_ffmpeg_avoid_memory_leaks.patch b/videoio_ffmpeg_avoid_memory_leaks.patch
new file mode 100644
index 0000000..f6ddbdf
--- /dev/null
+++ b/videoio_ffmpeg_avoid_memory_leaks.patch
@@ -0,0 +1,69 @@
+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
new file mode 100644
index 0000000..91ccfaf
--- /dev/null
+++ b/videoio_initial_FFmpeg_5_0_support.patch
@@ -0,0 +1,1001 @@
+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;
+ }