From 66809ea92952cda61f55c2e4ce70ae73c1c3c7ac Mon Sep 17 00:00:00 2001 From: James Bowley <12133430+cudawarped@users.noreply.github.com> Date: Thu, 25 Aug 2022 14:41:57 +0300 Subject: [PATCH 1/2] Fix memory leak caused by incorrect use of smart pointer. --- modules/cudacodec/src/frame_queue.cpp | 26 ++++++++++++++++++++++++-- modules/cudacodec/src/frame_queue.hpp | 13 +++++++++---- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/modules/cudacodec/src/frame_queue.cpp b/modules/cudacodec/src/frame_queue.cpp index 6fecff6b8..fdbe50f8d 100644 --- a/modules/cudacodec/src/frame_queue.cpp +++ b/modules/cudacodec/src/frame_queue.cpp @@ -46,10 +46,32 @@ #ifdef HAVE_NVCUVID RawPacket::RawPacket(const unsigned char* _data, const size_t _size, const bool _containsKeyFrame) : size(_size), containsKeyFrame(_containsKeyFrame) { - data = cv::makePtr(new unsigned char[size]); - memcpy(*data, _data, size); + data = new unsigned char[size]; + memcpy(data, _data, size); }; +RawPacket::~RawPacket() { + if (data) delete[] data; +} + +RawPacket::RawPacket(const RawPacket& other) : RawPacket(other.data, other.size, other.containsKeyFrame) { +} + +RawPacket::RawPacket(RawPacket&& other) noexcept : data(std::exchange(other.data, nullptr)), size(std::exchange(other.size, 0)), + containsKeyFrame(std::exchange(other.containsKeyFrame, false)) { +} + +RawPacket& RawPacket::operator=(const RawPacket& other) { + return *this = RawPacket(other); +} + +RawPacket& RawPacket::operator=(RawPacket&& other) noexcept { + std::swap(data, other.data); + size = other.size; + containsKeyFrame = other.containsKeyFrame; + return *this; +} + cv::cudacodec::detail::FrameQueue::~FrameQueue() { if (isFrameInUse_) delete[] isFrameInUse_; diff --git a/modules/cudacodec/src/frame_queue.hpp b/modules/cudacodec/src/frame_queue.hpp index b6e0b06bc..d7f0696af 100644 --- a/modules/cudacodec/src/frame_queue.hpp +++ b/modules/cudacodec/src/frame_queue.hpp @@ -50,11 +50,16 @@ class RawPacket { public: RawPacket(const unsigned char* _data, const size_t _size = 0, const bool _containsKeyFrame = false); - unsigned char* Data() const { return *data; } - size_t size; - bool containsKeyFrame; + ~RawPacket(); + RawPacket(const RawPacket& other); + RawPacket(RawPacket&& other) noexcept; + RawPacket& operator=(const RawPacket& other); + RawPacket& operator=(RawPacket&& other) noexcept; + unsigned char* Data() const { return data; } + size_t size = 0; + bool containsKeyFrame = false; private: - cv::Ptr data = 0; + unsigned char* data = 0; }; namespace cv { namespace cudacodec { namespace detail { From 657335352a9e69fc40e1b150496a19c33c506e61 Mon Sep 17 00:00:00 2001 From: James Bowley <12133430+cudawarped@users.noreply.github.com> Date: Mon, 12 Sep 2022 14:54:54 +0300 Subject: [PATCH 2/2] Replace internal raw pointer with vect. --- modules/cudacodec/src/frame_queue.cpp | 28 ++------------------------ modules/cudacodec/src/frame_queue.hpp | 14 +++++-------- modules/cudacodec/src/video_reader.cpp | 5 +++-- 3 files changed, 10 insertions(+), 37 deletions(-) diff --git a/modules/cudacodec/src/frame_queue.cpp b/modules/cudacodec/src/frame_queue.cpp index fdbe50f8d..d73e04eb1 100644 --- a/modules/cudacodec/src/frame_queue.cpp +++ b/modules/cudacodec/src/frame_queue.cpp @@ -45,32 +45,8 @@ #ifdef HAVE_NVCUVID -RawPacket::RawPacket(const unsigned char* _data, const size_t _size, const bool _containsKeyFrame) : size(_size), containsKeyFrame(_containsKeyFrame) { - data = new unsigned char[size]; - memcpy(data, _data, size); -}; - -RawPacket::~RawPacket() { - if (data) delete[] data; -} - -RawPacket::RawPacket(const RawPacket& other) : RawPacket(other.data, other.size, other.containsKeyFrame) { -} - -RawPacket::RawPacket(RawPacket&& other) noexcept : data(std::exchange(other.data, nullptr)), size(std::exchange(other.size, 0)), - containsKeyFrame(std::exchange(other.containsKeyFrame, false)) { -} - -RawPacket& RawPacket::operator=(const RawPacket& other) { - return *this = RawPacket(other); -} - -RawPacket& RawPacket::operator=(RawPacket&& other) noexcept { - std::swap(data, other.data); - size = other.size; - containsKeyFrame = other.containsKeyFrame; - return *this; -} +RawPacket::RawPacket(const unsigned char* data_, const size_t size, const bool containsKeyFrame_) : + data(data_,data_ + size), containsKeyFrame(containsKeyFrame_) {}; cv::cudacodec::detail::FrameQueue::~FrameQueue() { if (isFrameInUse_) diff --git a/modules/cudacodec/src/frame_queue.hpp b/modules/cudacodec/src/frame_queue.hpp index d7f0696af..840b23c5d 100644 --- a/modules/cudacodec/src/frame_queue.hpp +++ b/modules/cudacodec/src/frame_queue.hpp @@ -50,16 +50,12 @@ class RawPacket { public: RawPacket(const unsigned char* _data, const size_t _size = 0, const bool _containsKeyFrame = false); - ~RawPacket(); - RawPacket(const RawPacket& other); - RawPacket(RawPacket&& other) noexcept; - RawPacket& operator=(const RawPacket& other); - RawPacket& operator=(RawPacket&& other) noexcept; - unsigned char* Data() const { return data; } - size_t size = 0; - bool containsKeyFrame = false; + const unsigned char* Data() const noexcept { return data.data(); } + size_t Size() const noexcept { return data.size(); } + bool ContainsKeyFrame() const noexcept { return containsKeyFrame; } private: - unsigned char* data = 0; + std::vector data; + bool containsKeyFrame = false; }; namespace cv { namespace cudacodec { namespace detail { diff --git a/modules/cudacodec/src/video_reader.cpp b/modules/cudacodec/src/video_reader.cpp index 903defaf3..f321ed4f1 100644 --- a/modules/cudacodec/src/video_reader.cpp +++ b/modules/cudacodec/src/video_reader.cpp @@ -254,7 +254,8 @@ namespace if (idx >= rawPacketsBaseIdx && idx < rawPacketsBaseIdx + rawPackets.size()) { if (!frame.isMat()) CV_Error(Error::StsUnsupportedFormat, "Raw data is stored on the host and must be retrieved using a cv::Mat"); - Mat tmp(1, rawPackets.at(idx - rawPacketsBaseIdx).size, CV_8UC1, rawPackets.at(idx - rawPacketsBaseIdx).Data(), rawPackets.at(idx - rawPacketsBaseIdx).size); + const size_t i = idx - rawPacketsBaseIdx; + Mat tmp(1, rawPackets.at(i).Size(), CV_8UC1, const_cast(rawPackets.at(i).Data()), rawPackets.at(i).Size()); frame.getMatRef() = tmp; } } @@ -299,7 +300,7 @@ namespace case VideoReaderProps::PROP_LRF_HAS_KEY_FRAME: { const int iPacket = propertyVal - rawPacketsBaseIdx; if (videoSource_->RawModeEnabled() && iPacket >= 0 && iPacket < rawPackets.size()) { - propertyVal = rawPackets.at(iPacket).containsKeyFrame; + propertyVal = rawPackets.at(iPacket).ContainsKeyFrame(); return true; } else