diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index 504561d1ee..61c2d846e6 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -70,6 +70,11 @@ extern "C" { #include #endif +#if LIBAVUTIL_BUILD >= (LIBAVUTIL_VERSION_MICRO >= 100 \ + ? CALC_FFMPEG_VERSION(51, 63, 100) : CALC_FFMPEG_VERSION(54, 6, 0)) +#include +#endif + #ifdef WIN32 #define HAVE_FFMPEG_SWSCALE 1 #include @@ -398,6 +403,39 @@ inline int _opencv_ffmpeg_interrupt_callback(void *ptr) } #endif +static +inline void _opencv_ffmpeg_av_packet_unref(AVPacket *pkt) +{ +#if LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \ + ? CALC_FFMPEG_VERSION(55, 25, 100) : CALC_FFMPEG_VERSION(55, 16, 0)) + av_packet_unref(pkt); +#else + av_free_packet(pkt); +#endif +}; + +static +inline void _opencv_ffmpeg_av_image_fill_arrays(void *frame, uint8_t *ptr, enum AVPixelFormat pix_fmt, int width, int height) +{ +#if LIBAVUTIL_BUILD >= (LIBAVUTIL_VERSION_MICRO >= 100 \ + ? CALC_FFMPEG_VERSION(51, 63, 100) : CALC_FFMPEG_VERSION(54, 6, 0)) + av_image_fill_arrays(((AVFrame*)frame)->data, ((AVFrame*)frame)->linesize, ptr, pix_fmt, width, height, 1); +#else + avpicture_fill((AVPicture*)frame, ptr, pix_fmt, width, height); +#endif +}; + +static +inline int _opencv_ffmpeg_av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height) +{ +#if LIBAVUTIL_BUILD >= (LIBAVUTIL_VERSION_MICRO >= 100 \ + ? CALC_FFMPEG_VERSION(51, 63, 100) : CALC_FFMPEG_VERSION(54, 6, 0)) + return av_image_get_buffer_size(pix_fmt, width, height, 1); +#else + return avpicture_get_size(pix_fmt, width, height); +#endif +}; + struct CvCapture_FFMPEG { @@ -538,7 +576,7 @@ void CvCapture_FFMPEG::close() // free last packet if exist if (packet.data) { - av_free_packet (&packet); + _opencv_ffmpeg_av_packet_unref (&packet); packet.data = NULL; } @@ -874,7 +912,7 @@ bool CvCapture_FFMPEG::grabFrame() while (!valid) { - av_free_packet (&packet); + _opencv_ffmpeg_av_packet_unref (&packet); #if USE_AV_INTERRUPT_CALLBACK if (interrupt_metadata.timeout) @@ -891,7 +929,7 @@ bool CvCapture_FFMPEG::grabFrame() if( packet.stream_index != video_stream ) { - av_free_packet (&packet); + _opencv_ffmpeg_av_packet_unref (&packet); count_errs++; if (count_errs > max_number_of_attempts) break; @@ -982,9 +1020,9 @@ bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* int aligns[AV_NUM_DATA_POINTERS]; avcodec_align_dimensions2(video_st->codec, &buffer_width, &buffer_height, aligns); rgb_picture.data[0] = (uint8_t*)realloc(rgb_picture.data[0], - avpicture_get_size( AV_PIX_FMT_BGR24, + _opencv_ffmpeg_av_image_get_buffer_size( AV_PIX_FMT_BGR24, buffer_width, buffer_height )); - avpicture_fill( (AVPicture*)&rgb_picture, rgb_picture.data[0], + _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; @@ -1371,7 +1409,7 @@ static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bo picture->width = width; picture->height = height; - size = avpicture_get_size( (AVPixelFormat) pix_fmt, width, height); + size = _opencv_ffmpeg_av_image_get_buffer_size( (AVPixelFormat) pix_fmt, width, height); if(alloc){ picture_buf = (uint8_t *) malloc(size); if (!picture_buf) @@ -1379,7 +1417,7 @@ static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bo av_free(picture); return NULL; } - avpicture_fill((AVPicture *)picture, picture_buf, + _opencv_ffmpeg_av_image_fill_arrays(picture, picture_buf, (AVPixelFormat) pix_fmt, width, height); } else { @@ -1579,7 +1617,7 @@ static int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, pkt.duration = av_rescale_q(pkt.duration, c->time_base, video_st->time_base); pkt.stream_index= video_st->index; ret = av_write_frame(oc, &pkt); - av_free_packet(&pkt); + _opencv_ffmpeg_av_packet_unref(&pkt); } else ret = OPENCV_NO_FRAMES_WRITTEN_CODE; @@ -1681,7 +1719,7 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int if ( c->pix_fmt != input_pix_fmt ) { assert( input_picture ); // let input_picture point to the raw data buffer of 'image' - avpicture_fill((AVPicture *)input_picture, (uint8_t *) data, + _opencv_ffmpeg_av_image_fill_arrays(input_picture, (uint8_t *) data, (AVPixelFormat)input_pix_fmt, width, height); if( !img_convert_ctx ) @@ -1705,7 +1743,7 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int return false; } else{ - avpicture_fill((AVPicture *)picture, (uint8_t *) data, + _opencv_ffmpeg_av_image_fill_arrays(picture, (uint8_t *) data, (AVPixelFormat)input_pix_fmt, width, height); } @@ -2637,14 +2675,14 @@ void InputMediaStream_FFMPEG::close() // free last packet if exist if (pkt_.data) - av_free_packet(&pkt_); + _opencv_ffmpeg_av_packet_unref(&pkt_); } bool InputMediaStream_FFMPEG::read(unsigned char** data, int* size, int* endOfFile) { // free last packet if exist if (pkt_.data) - av_free_packet(&pkt_); + _opencv_ffmpeg_av_packet_unref(&pkt_); // get the next frame for (;;) @@ -2675,7 +2713,7 @@ bool InputMediaStream_FFMPEG::read(unsigned char** data, int* size, int* endOfFi if (pkt_.stream_index != video_stream_id_) { - av_free_packet(&pkt_); + _opencv_ffmpeg_av_packet_unref(&pkt_); continue; }