From ac947d3bdaa4bdb9c4687096f6035ce3bb569bf0 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 30 Jan 2021 17:52:23 -0600 Subject: [PATCH] Add EGLImage export support to DRMRenderer --- app/streaming/video/ffmpeg-renderers/drm.cpp | 79 ++++++++++++++++++++ app/streaming/video/ffmpeg-renderers/drm.h | 6 ++ 2 files changed, 85 insertions(+) diff --git a/app/streaming/video/ffmpeg-renderers/drm.cpp b/app/streaming/video/ffmpeg-renderers/drm.cpp index ded1112d..5d40dae6 100644 --- a/app/streaming/video/ffmpeg-renderers/drm.cpp +++ b/app/streaming/video/ffmpeg-renderers/drm.cpp @@ -14,6 +14,10 @@ extern "C" { #include +#ifdef HAVE_EGL +#include +#endif + DrmRenderer::DrmRenderer() : m_HwContext(nullptr), m_DrmFd(-1), @@ -302,3 +306,78 @@ void DrmRenderer::renderFrame(AVFrame* frame) // Free the previous FB object which has now been superseded drmModeRmFB(m_DrmFd, lastFbId); } + +#ifdef HAVE_EGL + +bool DrmRenderer::canExportEGL() { + if (qgetenv("DRM_FORCE_DIRECT") == "1") { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "Using direct rendering due to environment variable"); + return false; + } + + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "DRM backend supports exporting EGLImage"); + return true; +} + +bool DrmRenderer::initializeEGL(EGLDisplay, + const EGLExtensions &ext) { + if (!ext.isSupported("EGL_EXT_image_dma_buf_import")) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "DRM-EGL: DMABUF unsupported"); + return false; + } + + return true; +} + +ssize_t DrmRenderer::exportEGLImages(AVFrame *frame, EGLDisplay dpy, + EGLImage images[EGL_MAX_PLANES]) { + ssize_t count = 0; + AVDRMFrameDescriptor* drmFrame = (AVDRMFrameDescriptor*)frame->data[0]; + + memset(images, 0, sizeof(EGLImage) * EGL_MAX_PLANES); + + SDL_assert(drmFrame->nb_objects == 1); + SDL_assert(drmFrame->nb_layers == 1); + SDL_assert(drmFrame->layers[0].nb_planes == 2); + + for (int i = 0; i < drmFrame->layers[0].nb_planes; ++i) { + const auto &plane = drmFrame->layers[0].planes[i]; + const auto &object = drmFrame->objects[plane.object_index]; + + EGLAttrib attribs[17] = { + EGL_LINUX_DRM_FOURCC_EXT, i == 0 ? DRM_FORMAT_R8 : DRM_FORMAT_GR88, + EGL_WIDTH, i == 0 ? frame->width : frame->width / 2, + EGL_HEIGHT, i == 0 ? frame->height : frame->height / 2, + EGL_DMA_BUF_PLANE0_FD_EXT, object.fd, + EGL_DMA_BUF_PLANE0_OFFSET_EXT, (EGLint)plane.offset, + EGL_DMA_BUF_PLANE0_PITCH_EXT, (EGLint)plane.pitch, + EGL_NONE, + }; + images[i] = eglCreateImage(dpy, EGL_NO_CONTEXT, + EGL_LINUX_DMA_BUF_EXT, + nullptr, attribs); + if (!images[i]) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "eglCreateImage() Failed: %d", eglGetError()); + goto fail; + } + ++count; + } + + return count; + +fail: + freeEGLImages(dpy, images); + return -1; +} + +void DrmRenderer::freeEGLImages(EGLDisplay dpy, EGLImage images[EGL_MAX_PLANES]) { + for (size_t i = 0; i < EGL_MAX_PLANES; ++i) { + eglDestroyImage(dpy, images[i]); + } +} + +#endif diff --git a/app/streaming/video/ffmpeg-renderers/drm.h b/app/streaming/video/ffmpeg-renderers/drm.h index 5dbd91dd..1ef5a328 100644 --- a/app/streaming/video/ffmpeg-renderers/drm.h +++ b/app/streaming/video/ffmpeg-renderers/drm.h @@ -14,6 +14,12 @@ public: virtual void renderFrame(AVFrame* frame) override; virtual enum AVPixelFormat getPreferredPixelFormat(int videoFormat) override; virtual int getRendererAttributes() override; +#ifdef HAVE_EGL + virtual bool canExportEGL() 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 void freeEGLImages(EGLDisplay dpy, EGLImage[EGL_MAX_PLANES]) override; +#endif private: AVBufferRef* m_HwContext;