mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2026-06-17 22:23:31 +00:00
Use AVBufferRefs to keep EGLImages and DRM FDs around for the lifetime of the frame
This commit is contained in:
@@ -1266,11 +1266,6 @@ bool DrmRenderer::addFbForFrame(AVFrame *frame, uint32_t* newFbId, bool testMode
|
|||||||
"Selected DRM plane doesn't support chosen decoding format and modifier: " FOURCC_FMT " %016" PRIx64,
|
"Selected DRM plane doesn't support chosen decoding format and modifier: " FOURCC_FMT " %016" PRIx64,
|
||||||
FOURCC_FMT_ARGS(drmFrame->layers[0].format),
|
FOURCC_FMT_ARGS(drmFrame->layers[0].format),
|
||||||
drmFrame->objects[0].format_modifier);
|
drmFrame->objects[0].format_modifier);
|
||||||
|
|
||||||
if (m_DrmPrimeBackend) {
|
|
||||||
SDL_assert(drmFrame == &mappedFrame);
|
|
||||||
m_BackendRenderer->unmapDrmPrimeFrame(drmFrame);
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1293,10 +1288,6 @@ bool DrmRenderer::addFbForFrame(AVFrame *frame, uint32_t* newFbId, bool testMode
|
|||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"drmPrimeFDToHandle() failed: %d",
|
"drmPrimeFDToHandle() failed: %d",
|
||||||
errno);
|
errno);
|
||||||
if (m_DrmPrimeBackend) {
|
|
||||||
SDL_assert(drmFrame == &mappedFrame);
|
|
||||||
m_BackendRenderer->unmapDrmPrimeFrame(drmFrame);
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1318,12 +1309,6 @@ bool DrmRenderer::addFbForFrame(AVFrame *frame, uint32_t* newFbId, bool testMode
|
|||||||
handles, pitches, offsets,
|
handles, pitches, offsets,
|
||||||
(flags & DRM_MODE_FB_MODIFIERS) ? modifiers : NULL,
|
(flags & DRM_MODE_FB_MODIFIERS) ? modifiers : NULL,
|
||||||
newFbId, flags);
|
newFbId, flags);
|
||||||
|
|
||||||
if (m_DrmPrimeBackend) {
|
|
||||||
SDL_assert(drmFrame == &mappedFrame);
|
|
||||||
m_BackendRenderer->unmapDrmPrimeFrame(drmFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"drmModeAddFB2[WithModifiers]() failed: %d",
|
"drmModeAddFB2[WithModifiers]() failed: %d",
|
||||||
@@ -1552,8 +1537,4 @@ ssize_t DrmRenderer::exportEGLImages(AVFrame *frame, EGLDisplay dpy,
|
|||||||
return m_EglImageFactory.exportDRMImages(frame, dpy, images);
|
return m_EglImageFactory.exportDRMImages(frame, dpy, images);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrmRenderer::freeEGLImages() {
|
|
||||||
m_EglImageFactory.freeEGLImages();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -500,7 +500,6 @@ public:
|
|||||||
virtual AVPixelFormat getEGLImagePixelFormat() override;
|
virtual AVPixelFormat getEGLImagePixelFormat() override;
|
||||||
virtual bool initializeEGL(EGLDisplay dpy, const EGLExtensions &ext) override;
|
virtual bool initializeEGL(EGLDisplay dpy, const EGLExtensions &ext) override;
|
||||||
virtual ssize_t exportEGLImages(AVFrame *frame, EGLDisplay dpy, EGLImage images[EGL_MAX_PLANES]) override;
|
virtual ssize_t exportEGLImages(AVFrame *frame, EGLDisplay dpy, EGLImage images[EGL_MAX_PLANES]) override;
|
||||||
virtual void freeEGLImages() override;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -69,17 +69,12 @@ bool EglImageFactory::initializeEGL(EGLDisplay,
|
|||||||
|
|
||||||
void EglImageFactory::resetCache()
|
void EglImageFactory::resetCache()
|
||||||
{
|
{
|
||||||
// Cannot reset cache while in the middle of rendering
|
|
||||||
SDL_assert(!m_LastImageCtx.has_value());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DRM
|
#ifdef HAVE_DRM
|
||||||
|
|
||||||
ssize_t EglImageFactory::exportDRMImages(AVFrame* frame, EGLDisplay dpy, EGLImage images[EGL_MAX_PLANES])
|
ssize_t EglImageFactory::exportDRMImages(AVFrame* frame, EGLDisplay dpy, EGLImage images[EGL_MAX_PLANES])
|
||||||
{
|
{
|
||||||
// freeEGLImages() must be called before exporting again
|
|
||||||
SDL_assert(!m_LastImageCtx.has_value());
|
|
||||||
|
|
||||||
SDL_assert(frame->format == AV_PIX_FMT_DRM_PRIME);
|
SDL_assert(frame->format == AV_PIX_FMT_DRM_PRIME);
|
||||||
AVDRMFrameDescriptor* drmFrame = (AVDRMFrameDescriptor*)frame->data[0];
|
AVDRMFrameDescriptor* drmFrame = (AVDRMFrameDescriptor*)frame->data[0];
|
||||||
|
|
||||||
@@ -222,14 +217,12 @@ ssize_t EglImageFactory::exportDRMImages(AVFrame* frame, EGLDisplay dpy, EGLImag
|
|||||||
attribs[attribIndex++] = EGL_NONE;
|
attribs[attribIndex++] = EGL_NONE;
|
||||||
SDL_assert(attribIndex <= MAX_ATTRIB_COUNT);
|
SDL_assert(attribIndex <= MAX_ATTRIB_COUNT);
|
||||||
|
|
||||||
EglImageContext imgCtx(dpy, m_eglDestroyImage, m_eglDestroyImageKHR);
|
|
||||||
|
|
||||||
// Our EGLImages are non-planar, so we only populate the first entry
|
// Our EGLImages are non-planar, so we only populate the first entry
|
||||||
if (m_eglCreateImage) {
|
if (m_eglCreateImage) {
|
||||||
imgCtx.images[0] = m_eglCreateImage(dpy, EGL_NO_CONTEXT,
|
images[0] = m_eglCreateImage(dpy, EGL_NO_CONTEXT,
|
||||||
EGL_LINUX_DMA_BUF_EXT,
|
EGL_LINUX_DMA_BUF_EXT,
|
||||||
nullptr, attribs);
|
nullptr, attribs);
|
||||||
if (!imgCtx.images[0]) {
|
if (!images[0]) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"eglCreateImage() Failed: %d", eglGetError());
|
"eglCreateImage() Failed: %d", eglGetError());
|
||||||
return -1;
|
return -1;
|
||||||
@@ -242,25 +235,27 @@ ssize_t EglImageFactory::exportDRMImages(AVFrame* frame, EGLDisplay dpy, EGLImag
|
|||||||
intAttribs[i] = (EGLint)attribs[i];
|
intAttribs[i] = (EGLint)attribs[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
imgCtx.images[0] = m_eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
|
images[0] = m_eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
|
||||||
EGL_LINUX_DMA_BUF_EXT,
|
EGL_LINUX_DMA_BUF_EXT,
|
||||||
nullptr, intAttribs);
|
nullptr, intAttribs);
|
||||||
if (!imgCtx.images[0]) {
|
if (!images[0]) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"eglCreateImageKHR() Failed: %d", eglGetError());
|
"eglCreateImageKHR() Failed: %d", eglGetError());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
imgCtx.count = 1;
|
auto imgCtx = new EglImageContext(dpy, m_eglDestroyImage, m_eglDestroyImageKHR);
|
||||||
|
imgCtx->images[0] = images[0];
|
||||||
|
imgCtx->count = 1;
|
||||||
|
|
||||||
// Copy the output from the image context before we move it
|
// Add a buffer reference to the frame to automatically destroy the EGLImages
|
||||||
images[0] = imgCtx.images[0];
|
// when the frame is no longer referenced.
|
||||||
|
frame->opaque_ref = av_buffer_create((uint8_t*)imgCtx, sizeof(imgCtx),
|
||||||
// Store this image context
|
freeEglImageContextBuffer,
|
||||||
m_LastImageCtx.emplace(std::move(imgCtx));
|
frame->opaque_ref, // Chain any existing buffer
|
||||||
|
AV_BUFFER_FLAG_READONLY);
|
||||||
return 1;
|
return imgCtx->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -269,9 +264,6 @@ ssize_t EglImageFactory::exportDRMImages(AVFrame* frame, EGLDisplay dpy, EGLImag
|
|||||||
|
|
||||||
ssize_t EglImageFactory::exportVAImages(AVFrame *frame, uint32_t exportFlags, EGLDisplay dpy, EGLImage images[EGL_MAX_PLANES])
|
ssize_t EglImageFactory::exportVAImages(AVFrame *frame, uint32_t exportFlags, EGLDisplay dpy, EGLImage images[EGL_MAX_PLANES])
|
||||||
{
|
{
|
||||||
// freeEGLImages() must be called before exporting again
|
|
||||||
SDL_assert(!m_LastImageCtx.has_value());
|
|
||||||
|
|
||||||
SDL_assert(frame->format == AV_PIX_FMT_VAAPI);
|
SDL_assert(frame->format == AV_PIX_FMT_VAAPI);
|
||||||
auto hwFrameCtx = (AVHWFramesContext*)frame->hw_frames_ctx->data;
|
auto hwFrameCtx = (AVHWFramesContext*)frame->hw_frames_ctx->data;
|
||||||
AVVAAPIDeviceContext* vaDeviceContext = (AVVAAPIDeviceContext*)hwFrameCtx->device_ctx->hwctx;
|
AVVAAPIDeviceContext* vaDeviceContext = (AVVAAPIDeviceContext*)hwFrameCtx->device_ctx->hwctx;
|
||||||
@@ -285,8 +277,6 @@ ssize_t EglImageFactory::exportVAImages(AVFrame *frame, uint32_t exportFlags, EG
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
EglImageContext imgCtx(dpy, m_eglDestroyImage, m_eglDestroyImageKHR);
|
|
||||||
|
|
||||||
VADRMPRIMESurfaceDescriptor vaFrame;
|
VADRMPRIMESurfaceDescriptor vaFrame;
|
||||||
st = vaExportSurfaceHandle(vaDeviceContext->display,
|
st = vaExportSurfaceHandle(vaDeviceContext->display,
|
||||||
surface_id,
|
surface_id,
|
||||||
@@ -299,6 +289,8 @@ ssize_t EglImageFactory::exportVAImages(AVFrame *frame, uint32_t exportFlags, EG
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto imgCtx = new EglImageContext(dpy, m_eglDestroyImage, m_eglDestroyImageKHR);
|
||||||
|
|
||||||
SDL_assert(vaFrame.num_layers <= EGL_MAX_PLANES);
|
SDL_assert(vaFrame.num_layers <= EGL_MAX_PLANES);
|
||||||
|
|
||||||
for (size_t i = 0; i < vaFrame.num_layers; ++i) {
|
for (size_t i = 0; i < vaFrame.num_layers; ++i) {
|
||||||
@@ -443,10 +435,10 @@ ssize_t EglImageFactory::exportVAImages(AVFrame *frame, uint32_t exportFlags, EG
|
|||||||
SDL_assert(attribIndex <= EGL_ATTRIB_COUNT);
|
SDL_assert(attribIndex <= EGL_ATTRIB_COUNT);
|
||||||
|
|
||||||
if (m_eglCreateImage) {
|
if (m_eglCreateImage) {
|
||||||
imgCtx.images[i] = m_eglCreateImage(dpy, EGL_NO_CONTEXT,
|
imgCtx->images[i] = m_eglCreateImage(dpy, EGL_NO_CONTEXT,
|
||||||
EGL_LINUX_DMA_BUF_EXT,
|
EGL_LINUX_DMA_BUF_EXT,
|
||||||
nullptr, attribs);
|
nullptr, attribs);
|
||||||
if (!imgCtx.images[i]) {
|
if (!imgCtx->images[i]) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"eglCreateImage() Failed: %d", eglGetError());
|
"eglCreateImage() Failed: %d", eglGetError());
|
||||||
break;
|
break;
|
||||||
@@ -459,17 +451,17 @@ ssize_t EglImageFactory::exportVAImages(AVFrame *frame, uint32_t exportFlags, EG
|
|||||||
intAttribs[i] = (EGLint)attribs[i];
|
intAttribs[i] = (EGLint)attribs[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
imgCtx.images[i] = m_eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
|
imgCtx->images[i] = m_eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
|
||||||
EGL_LINUX_DMA_BUF_EXT,
|
EGL_LINUX_DMA_BUF_EXT,
|
||||||
nullptr, intAttribs);
|
nullptr, intAttribs);
|
||||||
if (!imgCtx.images[i]) {
|
if (!imgCtx->images[i]) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"eglCreateImageKHR() Failed: %d", eglGetError());
|
"eglCreateImageKHR() Failed: %d", eglGetError());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
imgCtx.count++;
|
imgCtx->count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always close the exported FDs
|
// Always close the exported FDs
|
||||||
@@ -478,20 +470,24 @@ ssize_t EglImageFactory::exportVAImages(AVFrame *frame, uint32_t exportFlags, EG
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for failure
|
// Check for failure
|
||||||
if (vaFrame.num_layers != imgCtx.count) {
|
if (vaFrame.num_layers != imgCtx->count) {
|
||||||
|
delete imgCtx;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the output from the image context before we move it
|
// Add a buffer reference to the frame to automatically destroy the EGLImages
|
||||||
ssize_t count = imgCtx.count;
|
// when the frame is no longer referenced.
|
||||||
memcpy(images, imgCtx.images, sizeof(EGLImage) * imgCtx.count);
|
frame->opaque_ref = av_buffer_create((uint8_t*)imgCtx, sizeof(imgCtx),
|
||||||
|
freeEglImageContextBuffer,
|
||||||
|
frame->opaque_ref, // Chain any existing buffer
|
||||||
|
AV_BUFFER_FLAG_READONLY);
|
||||||
|
|
||||||
// Store this image context
|
memcpy(images, imgCtx->images, sizeof(EGLImage) * imgCtx->count);
|
||||||
m_LastImageCtx.emplace(std::move(imgCtx));
|
return imgCtx->count;
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
bool EglImageFactory::supportsImportingFormat(EGLDisplay dpy, EGLint format)
|
bool EglImageFactory::supportsImportingFormat(EGLDisplay dpy, EGLint format)
|
||||||
{
|
{
|
||||||
if (!m_eglQueryDmaBufFormatsEXT) {
|
if (!m_eglQueryDmaBufFormatsEXT) {
|
||||||
@@ -573,9 +569,12 @@ bool EglImageFactory::supportsImportingModifier(EGLDisplay dpy, EGLint format, E
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
void EglImageFactory::freeEglImageContextBuffer(void* opaque, uint8_t* data)
|
||||||
|
{
|
||||||
|
auto imgCtx = (EglImageContext*)data;
|
||||||
|
delete imgCtx;
|
||||||
|
|
||||||
void EglImageFactory::freeEGLImages() {
|
// Free any chained buffers
|
||||||
SDL_assert(m_LastImageCtx.has_value());
|
av_buffer_unref((AVBufferRef**)&opaque);
|
||||||
m_LastImageCtx.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,18 +18,7 @@ class EglImageFactory
|
|||||||
m_eglDestroyImageKHR(fn_eglDestroyImageKHR) {}
|
m_eglDestroyImageKHR(fn_eglDestroyImageKHR) {}
|
||||||
|
|
||||||
EglImageContext(const EglImageContext& other) = delete;
|
EglImageContext(const EglImageContext& other) = delete;
|
||||||
|
EglImageContext(EglImageContext&& other) = delete;
|
||||||
EglImageContext(EglImageContext&& other) {
|
|
||||||
// Copy the basic EGL state
|
|
||||||
m_Display = other.m_Display;
|
|
||||||
m_eglDestroyImage = other.m_eglDestroyImage;
|
|
||||||
m_eglDestroyImageKHR = other.m_eglDestroyImageKHR;
|
|
||||||
|
|
||||||
// Transfer ownership of the EGLImages
|
|
||||||
memcpy(images, other.images, other.count * sizeof(EGLImage));
|
|
||||||
count = other.count;
|
|
||||||
other.count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
~EglImageContext() {
|
~EglImageContext() {
|
||||||
for (ssize_t i = 0; i < count; ++i) {
|
for (ssize_t i = 0; i < count; ++i) {
|
||||||
@@ -64,14 +53,13 @@ public:
|
|||||||
ssize_t exportVAImages(AVFrame* frame, uint32_t exportFlags, EGLDisplay dpy, EGLImage images[EGL_MAX_PLANES]);
|
ssize_t exportVAImages(AVFrame* frame, uint32_t exportFlags, EGLDisplay dpy, EGLImage images[EGL_MAX_PLANES]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void freeEGLImages();
|
|
||||||
|
|
||||||
bool supportsImportingFormat(EGLDisplay dpy, EGLint format);
|
bool supportsImportingFormat(EGLDisplay dpy, EGLint format);
|
||||||
bool supportsImportingModifier(EGLDisplay dpy, EGLint format, EGLuint64KHR modifier);
|
bool supportsImportingModifier(EGLDisplay dpy, EGLint format, EGLuint64KHR modifier);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static void freeEglImageContextBuffer(void* opaque, uint8_t* data);
|
||||||
|
|
||||||
IFFmpegRenderer* m_Renderer;
|
IFFmpegRenderer* m_Renderer;
|
||||||
std::optional<EglImageContext> m_LastImageCtx;
|
|
||||||
bool m_EGLExtDmaBuf;
|
bool m_EGLExtDmaBuf;
|
||||||
PFNEGLCREATEIMAGEPROC m_eglCreateImage;
|
PFNEGLCREATEIMAGEPROC m_eglCreateImage;
|
||||||
PFNEGLDESTROYIMAGEPROC m_eglDestroyImage;
|
PFNEGLDESTROYIMAGEPROC m_eglDestroyImage;
|
||||||
|
|||||||
@@ -880,8 +880,6 @@ void EGLRenderer::renderFrame(AVFrame* frame)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Backend->freeEGLImages();
|
|
||||||
|
|
||||||
// Free the DMA-BUF backing the last frame now that it is definitely
|
// Free the DMA-BUF backing the last frame now that it is definitely
|
||||||
// no longer being used anymore. While the PRIME FD stays around until
|
// no longer being used anymore. While the PRIME FD stays around until
|
||||||
// EGL is done with it, the memory backing it may be reused by FFmpeg
|
// EGL is done with it, the memory backing it may be reused by FFmpeg
|
||||||
@@ -905,6 +903,5 @@ bool EGLRenderer::testRenderFrame(AVFrame* frame)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Backend->freeEGLImages();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -512,9 +512,6 @@ public:
|
|||||||
EGLImage[EGL_MAX_PLANES]) {
|
EGLImage[EGL_MAX_PLANES]) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free the resources allocated during the last `exportEGLImages` call
|
|
||||||
virtual void freeEGLImages() {}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DRM
|
#ifdef HAVE_DRM
|
||||||
@@ -526,8 +523,6 @@ public:
|
|||||||
virtual bool mapDrmPrimeFrame(AVFrame*, AVDRMFrameDescriptor*) {
|
virtual bool mapDrmPrimeFrame(AVFrame*, AVDRMFrameDescriptor*) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void unmapDrmPrimeFrame(AVDRMFrameDescriptor*) {}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -1162,11 +1162,6 @@ VAAPIRenderer::exportEGLImages(AVFrame *frame, EGLDisplay dpy,
|
|||||||
return m_EglImageFactory.exportVAImages(frame, exportFlags, dpy, images);
|
return m_EglImageFactory.exportVAImages(frame, exportFlags, dpy, images);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
VAAPIRenderer::freeEGLImages() {
|
|
||||||
m_EglImageFactory.freeEGLImages();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DRM
|
#ifdef HAVE_DRM
|
||||||
@@ -1224,14 +1219,26 @@ bool VAAPIRenderer::mapDrmPrimeFrame(AVFrame* frame, AVDRMFrameDescriptor* drmDe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a buffer reference to the frame to automatically close the
|
||||||
|
// mapped FDs when the frame is no longer referenced.
|
||||||
|
frame->opaque_ref = av_buffer_create((uint8_t*)drmDescriptor, sizeof(*drmDescriptor),
|
||||||
|
freeDrmDescriptorBuffer,
|
||||||
|
frame->opaque_ref, // Chain any existing buffer
|
||||||
|
AV_BUFFER_FLAG_READONLY);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VAAPIRenderer::unmapDrmPrimeFrame(AVDRMFrameDescriptor* drmDescriptor)
|
void VAAPIRenderer::freeDrmDescriptorBuffer(void* opaque, uint8_t* data)
|
||||||
{
|
{
|
||||||
|
auto drmDescriptor = (AVDRMFrameDescriptor*)data;
|
||||||
|
|
||||||
for (int i = 0; i < drmDescriptor->nb_objects; i++) {
|
for (int i = 0; i < drmDescriptor->nb_objects; i++) {
|
||||||
close(drmDescriptor->objects[i].fd);
|
close(drmDescriptor->objects[i].fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Free any chained buffers
|
||||||
|
av_buffer_unref((AVBufferRef**)&opaque);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -73,13 +73,11 @@ public:
|
|||||||
virtual AVPixelFormat getEGLImagePixelFormat() override;
|
virtual AVPixelFormat getEGLImagePixelFormat() override;
|
||||||
virtual bool initializeEGL(EGLDisplay dpy, const EGLExtensions &ext) override;
|
virtual bool initializeEGL(EGLDisplay dpy, const EGLExtensions &ext) override;
|
||||||
virtual ssize_t exportEGLImages(AVFrame *frame, EGLDisplay dpy, EGLImage images[EGL_MAX_PLANES]) override;
|
virtual ssize_t exportEGLImages(AVFrame *frame, EGLDisplay dpy, EGLImage images[EGL_MAX_PLANES]) override;
|
||||||
virtual void freeEGLImages() override;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DRM
|
#ifdef HAVE_DRM
|
||||||
virtual bool canExportDrmPrime() override;
|
virtual bool canExportDrmPrime() override;
|
||||||
virtual bool mapDrmPrimeFrame(AVFrame* frame, AVDRMFrameDescriptor* drmDescriptor) override;
|
virtual bool mapDrmPrimeFrame(AVFrame* frame, AVDRMFrameDescriptor* drmDescriptor) override;
|
||||||
virtual void unmapDrmPrimeFrame(AVDRMFrameDescriptor* drmDescriptor) override;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -91,6 +89,10 @@ private:
|
|||||||
bool canExportSurfaceHandle(int layerTypeFlag, VADRMPRIMESurfaceDescriptor* descriptor);
|
bool canExportSurfaceHandle(int layerTypeFlag, VADRMPRIMESurfaceDescriptor* descriptor);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_DRM
|
||||||
|
static void freeDrmDescriptorBuffer(void* opaque, uint8_t* data);
|
||||||
|
#endif
|
||||||
|
|
||||||
int m_DecoderSelectionPass;
|
int m_DecoderSelectionPass;
|
||||||
int m_WindowSystem;
|
int m_WindowSystem;
|
||||||
AVBufferRef* m_HwContext;
|
AVBufferRef* m_HwContext;
|
||||||
|
|||||||
Reference in New Issue
Block a user