From c5ff5d224d167a7506e94708a4be181786ad96bc Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Sun, 7 Jul 2019 11:54:47 +0200 Subject: [PATCH] ffmpeg/avframe-queue: Upgrade to shared_ptr AVFrame Removes problems with memory leaks due to lost references and other issues. --- source/ffmpeg/avframe-queue.cpp | 37 ++++++++++++--------------------- source/ffmpeg/avframe-queue.hpp | 18 ++++++---------- 2 files changed, 19 insertions(+), 36 deletions(-) diff --git a/source/ffmpeg/avframe-queue.cpp b/source/ffmpeg/avframe-queue.cpp index 7fa5980..555e39f 100644 --- a/source/ffmpeg/avframe-queue.cpp +++ b/source/ffmpeg/avframe-queue.cpp @@ -18,13 +18,15 @@ #include "avframe-queue.hpp" #include "tools.hpp" -AVFrame* ffmpeg::avframe_queue::create_frame() +std::shared_ptr ffmpeg::avframe_queue::create_frame() { - AVFrame* frame = av_frame_alloc(); - frame->width = this->resolution.first; - frame->height = this->resolution.second; - frame->format = this->format; - int res = av_frame_get_buffer(frame, 0); + std::shared_ptr frame = + std::shared_ptr(av_frame_alloc(), [](AVFrame* frame) { av_frame_free(&frame); }); + frame->width = this->resolution.first; + frame->height = this->resolution.second; + frame->format = this->format; + + int res = av_frame_get_buffer(frame.get(), 0); if (res < 0) { throw std::exception(ffmpeg::tools::get_error_description(res)); } @@ -32,14 +34,6 @@ AVFrame* ffmpeg::avframe_queue::create_frame() return frame; } -void ffmpeg::avframe_queue::destroy_frame(AVFrame* frame) -{ - if (frame == nullptr) - return; - - av_frame_free(&frame); -} - ffmpeg::avframe_queue::avframe_queue() {} ffmpeg::avframe_queue::~avframe_queue() @@ -89,23 +83,19 @@ void ffmpeg::avframe_queue::precache(size_t count) void ffmpeg::avframe_queue::clear() { std::unique_lock ulock(this->lock); - for (AVFrame* frame : frames) { - destroy_frame(frame); - } frames.clear(); } -void ffmpeg::avframe_queue::push(AVFrame* frame) +void ffmpeg::avframe_queue::push(std::shared_ptr frame) { std::unique_lock ulock(this->lock); frames.push_back(frame); } -AVFrame* ffmpeg::avframe_queue::pop() +std::shared_ptr ffmpeg::avframe_queue::pop() { std::unique_lock ulock(this->lock); - - AVFrame* ret = nullptr; + std::shared_ptr ret; while (ret == nullptr) { if (frames.size() == 0) { ret = create_frame(); @@ -117,7 +107,6 @@ AVFrame* ffmpeg::avframe_queue::pop() frames.pop_front(); if ((ret->width != this->resolution.first) || (ret->height != this->resolution.second) || (ret->format != this->format)) { - destroy_frame(ret); ret = nullptr; } } @@ -126,13 +115,13 @@ AVFrame* ffmpeg::avframe_queue::pop() return ret; } -AVFrame* ffmpeg::avframe_queue::pop_only() +std::shared_ptr ffmpeg::avframe_queue::pop_only() { std::unique_lock ulock(this->lock); if (frames.size() == 0) { return nullptr; } - AVFrame* ret = frames.front(); + std::shared_ptr ret = frames.front(); if (ret == nullptr) { return nullptr; } diff --git a/source/ffmpeg/avframe-queue.hpp b/source/ffmpeg/avframe-queue.hpp index c0fc5ef..dd02a5d 100644 --- a/source/ffmpeg/avframe-queue.hpp +++ b/source/ffmpeg/avframe-queue.hpp @@ -15,10 +15,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -#ifndef OBS_FFMPEG_FFMPEG_AVFRAME_QUEUE -#define OBS_FFMPEG_FFMPEG_AVFRAME_QUEUE #pragma once - #include #include @@ -31,14 +28,13 @@ extern "C" { namespace ffmpeg { class avframe_queue { - std::deque frames; - std::mutex lock; + std::deque> frames; + std::mutex lock; std::pair resolution; AVPixelFormat format = AV_PIX_FMT_NONE; - AVFrame* create_frame(); - void destroy_frame(AVFrame* frame); + std::shared_ptr create_frame(); public: avframe_queue(); @@ -56,16 +52,14 @@ namespace ffmpeg { void clear(); - void push(AVFrame* frame); + void push(std::shared_ptr frame); - AVFrame* pop(); + std::shared_ptr pop(); - AVFrame* pop_only(); + std::shared_ptr pop_only(); bool empty(); size_t size(); }; } // namespace ffmpeg - -#endif OBS_FFMPEG_FFMPEG_AVFRAME_QUEUE