From d1e732a11433b37dd9e8b8bc5bbf13f5c5d0fe98 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 2 Nov 2023 10:04:04 +0100 Subject: [PATCH] FFMPEG: Cleanup: Remove storage of last FFMPEG frame read as `ImBuf` in anim data. The `anim` data (e.g. of a VSE sequence) would store the last frame read from FFMPEG as an image buffer, increasing its refcounting and preventing it to be freed until the whole `anim` data itself gets freed. In current code, there is no reason to keep a reference to this image buffer in the `anim` data, so removing it. This may also give a few percent improvement on the memory usage of the VSE in some cases. Found while investigating #114342. Pull Request: https://projects.blender.org/blender/blender/pulls/114395 --- source/blender/imbuf/intern/IMB_anim.h | 1 - source/blender/imbuf/intern/anim_movie.cc | 21 +++++++-------------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h index 8c206064051..8f51b7b661b 100644 --- a/source/blender/imbuf/intern/IMB_anim.h +++ b/source/blender/imbuf/intern/IMB_anim.h @@ -122,7 +122,6 @@ struct anim { AVFrame *pFrame_backup; bool pFrame_backup_complete; - struct ImBuf *cur_frame_final; int64_t cur_pts; int64_t cur_key_frame_pts; AVPacket *cur_packet; diff --git a/source/blender/imbuf/intern/anim_movie.cc b/source/blender/imbuf/intern/anim_movie.cc index a0431213bdd..731a8b06f67 100644 --- a/source/blender/imbuf/intern/anim_movie.cc +++ b/source/blender/imbuf/intern/anim_movie.cc @@ -639,7 +639,6 @@ static int startffmpeg(anim *anim) anim->framesize = anim->x * anim->y * 4; anim->cur_position = 0; - anim->cur_frame_final = nullptr; anim->cur_pts = -1; anim->cur_key_frame_pts = -1; anim->cur_packet = av_packet_alloc(); @@ -808,11 +807,10 @@ static AVFrame *ffmpeg_double_buffer_frame_fallback_get(anim *anim) /** * Postprocess the image in anim->pFrame and do color conversion and de-interlacing stuff. * - * Output is `anim->cur_frame_final`. + * \param ibuf: The frame just read by `ffmpeg_fetchibuf`, processed in-place. */ -static void ffmpeg_postprocess(anim *anim, AVFrame *input) +static void ffmpeg_postprocess(anim *anim, AVFrame *input, ImBuf *ibuf) { - ImBuf *ibuf = anim->cur_frame_final; int filter_y = 0; /* This means the data wasn't read properly, @@ -1391,8 +1389,6 @@ static ImBuf *ffmpeg_fetchibuf(anim *anim, int position, IMB_Timecode_Type tc) anim->x = anim->pCodecCtx->width; anim->y = anim->pCodecCtx->height; - IMB_freeImBuf(anim->cur_frame_final); - /* Certain versions of FFmpeg have a bug in libswscale which ends up in crash * when destination buffer is not properly aligned. For example, this happens * in FFmpeg 4.3.1. It got fixed later on, but for compatibility reasons is @@ -1419,14 +1415,14 @@ static ImBuf *ffmpeg_fetchibuf(anim *anim, int position, IMB_Timecode_Type tc) planes = R_IMF_PLANES_RGB; } - anim->cur_frame_final = IMB_allocImBuf(anim->x, anim->y, planes, 0); + ImBuf *cur_frame_final = IMB_allocImBuf(anim->x, anim->y, planes, 0); /* Allocate the storage explicitly to ensure the memory is aligned. */ uint8_t *buffer_data = static_cast( MEM_mallocN_aligned(size_t(4) * anim->x * anim->y, 32, "ffmpeg ibuf")); - IMB_assign_byte_buffer(anim->cur_frame_final, buffer_data, IB_TAKE_OWNERSHIP); + IMB_assign_byte_buffer(cur_frame_final, buffer_data, IB_TAKE_OWNERSHIP); - anim->cur_frame_final->byte_buffer.colorspace = colormanage_colorspace_get_named( + cur_frame_final->byte_buffer.colorspace = colormanage_colorspace_get_named( anim->colorspace); AVFrame *final_frame = ffmpeg_frame_by_pts_get(anim, pts_to_search); @@ -1439,14 +1435,12 @@ static ImBuf *ffmpeg_fetchibuf(anim *anim, int position, IMB_Timecode_Type tc) /* Even with the fallback from above it is possible that the current decode frame is nullptr. In * this case skip post-processing and return current image buffer. */ if (final_frame != nullptr) { - ffmpeg_postprocess(anim, final_frame); + ffmpeg_postprocess(anim, final_frame, cur_frame_final); } anim->cur_position = position; - IMB_refImBuf(anim->cur_frame_final); - - return anim->cur_frame_final; + return cur_frame_final; } static void free_anim_ffmpeg(anim *anim) @@ -1466,7 +1460,6 @@ static void free_anim_ffmpeg(anim *anim) av_frame_free(&anim->pFrameDeinterlaced); sws_freeContext(anim->img_convert_ctx); - IMB_freeImBuf(anim->cur_frame_final); } anim->duration_in_frames = 0; }