aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett Brown <themagnificentmrb@gmail.com>2023-04-13 18:05:55 -0700
committerGitHub <noreply@github.com>2023-04-13 18:05:55 -0700
commit3de3c130f0c4f23f62c99a0ec3e8be2dcc3a1a70 (patch)
tree6bb3c78681a9883a5218b71f51d289b5e71a6456
parent39fc74b3d8cd0912b2c563fcf0a864f47674d0ea (diff)
parent3be0e0f0b0264d2e57891c740d64414f30b1d5fb (diff)
Merge pull request #23098 from garbear/fix-memleak
RetroPlayer: Fix memory exhaustion with zero-copy emulators
-rw-r--r--xbmc/cores/RetroPlayer/rendering/RPRenderManager.cpp57
-rw-r--r--xbmc/cores/RetroPlayer/rendering/RPRenderManager.h2
-rw-r--r--xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.cpp32
-rw-r--r--xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.h1
4 files changed, 41 insertions, 51 deletions
diff --git a/xbmc/cores/RetroPlayer/rendering/RPRenderManager.cpp b/xbmc/cores/RetroPlayer/rendering/RPRenderManager.cpp
index a0886fe26a..5e22ed887f 100644
--- a/xbmc/cores/RetroPlayer/rendering/RPRenderManager.cpp
+++ b/xbmc/cores/RetroPlayer/rendering/RPRenderManager.cpp
@@ -123,35 +123,56 @@ bool CRPRenderManager::Configure(AVPixelFormat format,
return true;
}
-std::vector<VideoStreamBuffer> CRPRenderManager::GetVideoBuffers(unsigned int width,
- unsigned int height)
+bool CRPRenderManager::GetVideoBuffer(unsigned int width,
+ unsigned int height,
+ VideoStreamBuffer& buffer)
{
- std::vector<VideoStreamBuffer> buffers;
+ // Clear any previous pending buffers
+ for (IRenderBuffer* buffer : m_pendingBuffers)
+ buffer->Release();
+ m_pendingBuffers.clear();
if (m_bFlush || m_state != RENDER_STATE::CONFIGURED)
- return buffers;
+ return false;
- // Get buffers from visible renderers
- for (IRenderBufferPool* bufferPool : m_processInfo.GetBufferManager().GetBufferPools())
- {
- if (!bufferPool->HasVisibleRenderer())
- continue;
+ // We should do our best to get a valid render buffer. If we return false,
+ // the game add-on will likely allocate its own memory.
+ IRenderBuffer* renderBuffer = nullptr;
- IRenderBuffer* renderBuffer = bufferPool->GetBuffer(width, height);
+ auto bufferPools = m_processInfo.GetBufferManager().GetBufferPools();
+
+ std::sort(bufferPools.begin(), bufferPools.end(),
+ [](const IRenderBufferPool* lhs, const IRenderBufferPool* rhs) {
+ // Prefer buffer pools with a visible renderer
+ if (lhs->HasVisibleRenderer() && !rhs->HasVisibleRenderer())
+ return true;
+ if (!lhs->HasVisibleRenderer() && rhs->HasVisibleRenderer())
+ return false;
+
+ //! @todo De-prioritize buffer pools with write-only or unaligned memory
+
+ return false;
+ });
+
+ for (IRenderBufferPool* bufferPool : bufferPools)
+ {
+ renderBuffer = bufferPool->GetBuffer(width, height);
if (renderBuffer != nullptr)
- m_pendingBuffers.emplace_back(renderBuffer);
+ break;
else
CLog::Log(LOGDEBUG, "RetroPlayer[RENDER]: Unable to get video buffer for frame");
}
- for (IRenderBuffer* renderBuffer : m_pendingBuffers)
- {
- buffers.emplace_back(VideoStreamBuffer{
- renderBuffer->GetFormat(), renderBuffer->GetMemory(), renderBuffer->GetFrameSize(),
- renderBuffer->GetMemoryAccess(), renderBuffer->GetMemoryAlignment()});
- }
+ if (renderBuffer == nullptr)
+ return false;
+
+ buffer = VideoStreamBuffer{renderBuffer->GetFormat(), renderBuffer->GetMemory(),
+ renderBuffer->GetFrameSize(), renderBuffer->GetMemoryAccess(),
+ renderBuffer->GetMemoryAlignment()};
- return buffers;
+ m_pendingBuffers.emplace_back(std::move(renderBuffer));
+
+ return true;
}
void CRPRenderManager::AddFrame(const uint8_t* data,
diff --git a/xbmc/cores/RetroPlayer/rendering/RPRenderManager.h b/xbmc/cores/RetroPlayer/rendering/RPRenderManager.h
index 14229efad3..bd1ebb59e5 100644
--- a/xbmc/cores/RetroPlayer/rendering/RPRenderManager.h
+++ b/xbmc/cores/RetroPlayer/rendering/RPRenderManager.h
@@ -93,7 +93,7 @@ public:
unsigned int maxWidth,
unsigned int maxHeight,
float pixelAspectRatio);
- std::vector<VideoStreamBuffer> GetVideoBuffers(unsigned int width, unsigned int height);
+ bool GetVideoBuffer(unsigned int width, unsigned int height, VideoStreamBuffer& buffer);
void AddFrame(const uint8_t* data,
size_t size,
unsigned int width,
diff --git a/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.cpp b/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.cpp
index 3c740e9dc8..14c66a86ae 100644
--- a/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.cpp
+++ b/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.cpp
@@ -13,8 +13,6 @@
#include "cores/RetroPlayer/rendering/RenderTranslator.h"
#include "utils/log.h"
-#include <algorithm>
-
using namespace KODI;
using namespace RETRO;
@@ -74,33 +72,7 @@ bool CRetroPlayerVideo::GetStreamBuffer(unsigned int width,
VideoStreamBuffer& videoBuffer = static_cast<VideoStreamBuffer&>(buffer);
if (m_bOpen)
- {
- m_buffers = m_renderManager.GetVideoBuffers(width, height);
-
- std::sort(m_buffers.begin(), m_buffers.end(),
- [](const VideoStreamBuffer& lhs, const VideoStreamBuffer& rhs) {
- // Prefer read-write over write only
- if (lhs.access == DataAccess::READ_WRITE && rhs.access != DataAccess::READ_WRITE)
- return true;
- if (lhs.access != DataAccess::READ_WRITE && rhs.access == DataAccess::READ_WRITE)
- return false;
-
- // Prefer aligned over unaligned
- if (lhs.alignment == DataAlignment::DATA_ALIGNED &&
- rhs.alignment != DataAlignment::DATA_ALIGNED)
- return true;
- if (lhs.alignment != DataAlignment::DATA_ALIGNED &&
- rhs.alignment == DataAlignment::DATA_ALIGNED)
- return false;
-
- return false;
- });
-
- //! @todo This comment was in the original code
- //! @todo Handle multiple buffers
- if (!m_buffers.empty())
- videoBuffer = m_buffers.at(0);
- }
+ return m_renderManager.GetVideoBuffer(width, height, videoBuffer);
return false;
}
@@ -130,8 +102,6 @@ void CRetroPlayerVideo::AddStreamData(const StreamPacket& packet)
m_renderManager.AddFrame(videoPacket.data, videoPacket.size, videoPacket.width,
videoPacket.height, orientationDegCCW);
}
-
- m_buffers.clear();
}
void CRetroPlayerVideo::CloseStream()
diff --git a/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.h b/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.h
index 06ad6245c8..8d153ab5c2 100644
--- a/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.h
+++ b/xbmc/cores/RetroPlayer/streams/RetroPlayerVideo.h
@@ -107,7 +107,6 @@ private:
// Stream properties
bool m_bOpen = false;
- std::vector<VideoStreamBuffer> m_buffers;
};
} // namespace RETRO
} // namespace KODI