Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:StefanBruens:branches:science
opencv3
0002-videoio-initial-FFmpeg-5.0-support.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0002-videoio-initial-FFmpeg-5.0-support.patch of Package opencv3
From 40fb2701054ee3e5f76f1179e105da4fb7fea44b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Br=C3=BCns?= <stefan.bruens@rwth-aachen.de> Date: Sun, 27 Nov 2022 00:54:26 +0100 Subject: [PATCH 2/2] videoio: initial FFmpeg 5.0 support (cherry picked from commit 5440fd6cb43ea65a056c46b691fcdab1a425e92d) videoio(ffmpeg): avoid memory leaks (cherry picked from commit 271f7df3435c619ceba9261f88dcfbb0714b0b0d) --- modules/videoio/src/cap_ffmpeg_impl.hpp | 327 +++++++++++++++++------- 1 file changed, 239 insertions(+), 88 deletions(-) diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index 872f6f9c79..131e0d8e50 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -41,11 +41,17 @@ //M*/ #include "cap_ffmpeg_api.hpp" +#include "opencv2/core/utils/logger.hpp" +// #include "cap_interface.hpp" + +using namespace cv; + #if !(defined(_WIN32) || defined(WINCE)) # include <pthread.h> #endif #include <algorithm> #include <limits> +#include <string.h> #ifndef __OPENCV_BUILD #define CV_FOURCC(c1, c2, c3, c4) (((c1) & 255) + (((c2) & 255) << 8) + (((c3) & 255) << 16) + (((c4) & 255) << 24)) @@ -80,6 +86,7 @@ extern "C" { #include <libavutil/mathematics.h> #include <libavutil/opt.h> +#include <libavutil/display.h> #if LIBAVUTIL_BUILD >= (LIBAVUTIL_VERSION_MICRO >= 100 \ ? CALC_FFMPEG_VERSION(51, 63, 100) : CALC_FFMPEG_VERSION(54, 6, 0)) @@ -89,6 +96,62 @@ extern "C" { #include <libavcodec/avcodec.h> #include <libswscale/swscale.h> +// 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 <libavcodec/bsf.h> +#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 @@ -446,6 +509,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 { @@ -475,6 +547,7 @@ struct CvCapture_FFMPEG AVFormatContext * ic; AVCodec * avcodec; + AVCodecContext * context; int video_stream; AVStream * video_st; AVFrame * picture; @@ -534,6 +607,7 @@ void CvCapture_FFMPEG::init() img_convert_ctx = 0; avcodec = 0; + context = 0; frame_number = 0; eps_zero = 0.000025; @@ -582,10 +656,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); @@ -747,6 +830,7 @@ void ImplMutex::lock() { impl->lock(); } void ImplMutex::unlock() { impl->unlock(); } bool ImplMutex::trylock() { return impl->trylock(); } +#ifdef CV_FFMPEG_LOCKMGR static int LockCallBack(void **mutex, AVLockOp op) { ImplMutex* localMutex = reinterpret_cast<ImplMutex*>(*mutex); @@ -794,6 +878,7 @@ private: AutoLock(const AutoLock&); // disabled AutoLock& operator = (const AutoLock&); // disabled }; +#endif static void ffmpeg_log_callback(void *ptr, int level, const char *fmt, va_list vargs) { @@ -855,11 +940,15 @@ public: { 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 _initialized = true; } @@ -867,11 +956,47 @@ public: ~InternalFFMpegRegister() { _initialized = false; +#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 ) { InternalFFMpegRegister::init(); @@ -910,7 +1035,7 @@ bool CvCapture_FFMPEG::open( const char* _filename ) #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) { @@ -928,61 +1053,51 @@ bool CvCapture_FFMPEG::open( const char* _filename ) 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) { // backup encoder' width/height - int enc_width = enc->width; - int enc_height = enc->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 AVCodec *codec; - if(av_dict_get(dict, "video_codec", NULL, 0) == NULL) { - codec = avcodec_find_decoder(enc->codec_id); + AVDictionaryEntry* video_codec_param = av_dict_get(dict, "video_codec", NULL, 0); + if (video_codec_param == NULL) + codec = avcodec_find_decoder(codec_id); } else { - codec = avcodec_find_decoder_by_name(av_dict_get(dict, "video_codec", NULL, 0)->value); + codec = avcodec_find_decoder_by_name(video_codec_param->value); + } + if (err < 0) { + CV_LOG_ERROR(NULL, "VIDEOIO/FFMPEG: Failed to initialize VideoCapture"); + goto exit_func; } if (!codec || avcodec_open2(enc, codec, NULL) < 0) goto exit_func; // 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]; @@ -993,8 +1108,8 @@ bool CvCapture_FFMPEG::open( const char* _filename ) 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; @@ -1147,7 +1262,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 ) @@ -1214,7 +1329,7 @@ bool CvCapture_FFMPEG::grabFrame() { //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; } @@ -1243,7 +1358,7 @@ bool CvCapture_FFMPEG::grabFrame() bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* width, int* height, int* cn) { - if (!video_st) + if (!video_st || !context) return false; if (rawMode) @@ -1261,13 +1376,13 @@ bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* 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, @@ -1301,8 +1416,8 @@ bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* _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]; @@ -1312,7 +1427,7 @@ bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* img_convert_ctx, picture->data, picture->linesize, - 0, video_st->codec->coded_height, + 0, context->coded_height, rgb_picture.data, rgb_picture.linesize ); @@ -1328,7 +1443,7 @@ bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* 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; @@ -1355,8 +1470,8 @@ double CvCapture_FFMPEG::getProperty( int property_id ) const case CV_FFMPEG_CAP_PROP_FPS: return get_fps(); case CV_FFMPEG_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) { @@ -1376,7 +1491,11 @@ double CvCapture_FFMPEG::getProperty( int property_id ) const return _opencv_ffmpeg_get_sample_aspect_ratio(ic->streams[video_stream]).den; case CV_FFMPEG_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; } @@ -1446,7 +1565,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; @@ -1478,7 +1597,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); @@ -1487,6 +1615,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; @@ -1503,7 +1632,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(); @@ -1615,7 +1744,7 @@ struct CvVideoWriter_FFMPEG void init(); - AVOutputFormat * fmt; + CV_FFMPEG_FMT_CONST AVOutputFormat * fmt; AVFormatContext * oc; uint8_t * outbuf; uint32_t outbuf_size; @@ -1625,6 +1754,7 @@ struct CvVideoWriter_FFMPEG uint8_t * picbuf; AVStream * video_st; int input_pix_fmt; + AVCodecContext * context; unsigned char * aligned_input; size_t aligned_input_size; int frame_width, frame_height; @@ -1686,6 +1816,7 @@ void CvVideoWriter_FFMPEG::init() picbuf = 0; video_st = 0; input_pix_fmt = 0; + context = 0; aligned_input = NULL; aligned_input_size = 0; img_convert_ctx = 0; @@ -1736,7 +1867,7 @@ static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bo static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc, CV_CODEC_ID codec_id, int w, int h, int bitrate, - double fps, int pixel_format) + double fps, int pixel_format, int fourcc) { AVCodecContext *c; AVStream *st; @@ -1750,6 +1881,7 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc, return NULL; } +// XXX c = st->codec; c->codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO); @@ -1762,12 +1894,15 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc, codec = avcodec_find_encoder(c->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; @@ -1810,7 +1945,12 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc, } } if (best == NULL) + { +#ifdef CV_FFMPEG_CODECPAR + avcodec_free_context(&c); +#endif return NULL; + } c->time_base.den= best->num; c->time_base.num= best->den; } @@ -1853,26 +1993,20 @@ static AVStream *icv_add_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 st; + 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 ) { - AVCodecContext* c = video_st->codec; int ret = OPENCV_NO_FRAMES_WRITTEN_CODE; #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(57, 0, 0) @@ -1942,9 +2076,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 @@ -1981,7 +2112,8 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int step = aligned_step; } - if ( c->pix_fmt != input_pix_fmt ) { + AVPixelFormat sw_pix_fmt = context->pix_fmt; + if ( sw_pix_fmt != input_pix_fmt ) { CV_Assert( input_picture ); // let input_picture point to the raw data buffer of 'image' _opencv_ffmpeg_av_image_fill_arrays(input_picture, (uint8_t *) data, @@ -1993,9 +2125,9 @@ 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, - c->pix_fmt, + context->width, + context->height, + sw_pix_fmt, SWS_BICUBIC, NULL, NULL, NULL); if( !img_convert_ctx ) @@ -2015,12 +2147,14 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int } picture->pts = frame_idx; - bool ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, picture) >= 0; + int ret_write = icv_av_write_frame_FFMPEG(oc, video_st, context, outbuf, outbuf_size, picture, frame_idx); + bool ret = ret_write >= 0 ? true : false; frame_idx++; return ret; } + /// close video output stream and free associated memory void CvVideoWriter_FFMPEG::close() { @@ -2038,7 +2172,7 @@ void CvVideoWriter_FFMPEG::close() { for(;;) { - int ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, NULL); + 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; } @@ -2053,7 +2187,7 @@ void CvVideoWriter_FFMPEG::close() } // free pictures - if (picture && video_st && video_st->codec->pix_fmt != input_pix_fmt) + if (picture && context && context->pix_fmt != input_pix_fmt) { if(picture->data[0]) free(picture->data[0]); @@ -2063,11 +2197,14 @@ void CvVideoWriter_FFMPEG::close() av_freep(&input_picture); - if (video_st && video_st->codec) - { - /* close codec */ - avcodec_close(video_st->codec); - } +#ifdef CV_FFMPEG_CODECPAR + avcodec_free_context(&context); +#else + /* close codec */ + if (context) // fixed after https://github.com/FFmpeg/FFmpeg/commit/3e1f507f3e8f16b716aa115552d243b48ae809bd + avcodec_close(context); + context = NULL; +#endif av_freep(&outbuf); @@ -2227,8 +2364,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 */ @@ -2384,6 +2528,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; @@ -2398,10 +2548,11 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, } bool need_color_convert; - need_color_convert = (c->pix_fmt != input_pix_fmt); + AVPixelFormat sw_pix_fmt = context->pix_fmt; + need_color_convert = (sw_pix_fmt != input_pix_fmt); /* allocate the encoded raw picture */ - picture = icv_alloc_picture_FFMPEG(c->pix_fmt, c->width, c->height, need_color_convert); + picture = icv_alloc_picture_FFMPEG(sw_pix_fmt, context->width, context->height, need_color_convert); if (!picture) { return false; } @@ -2411,7 +2562,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; } -- 2.38.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor