PipeWire capturer: Import DMA-BUFs with correct render node
With more GPUs it might happen that server used different render node from the one we pick from the list. This would cause DMA-BUF to fail to import so we use Wayland client library to obtain wl_display in order to initialize EGLDisplay using same render node and have previous approach as a fallback. Also everyone else uses EGL_LINUX_DMA_BUF_EXT target for importing EGLImages from DMA-BUF file descriptors so use it as well to be sure we import buffers same way as they are produced. Bug: chromium:1290566 Bug: webrtc:13429 Change-Id: I32bbb0bdb28c08b6e7fcb3f94009f82a2041b6ee Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/250661 Reviewed-by: Mark Foltz <mfoltz@chromium.org> Commit-Queue: Jan Grulich <grulja@gmail.com> Commit-Queue: Mark Foltz <mfoltz@chromium.org> Cr-Commit-Position: refs/heads/main@{#35997}
This commit is contained in:

committed by
WebRTC LUCI CQ

parent
5723d854c9
commit
2f194e0325
@ -228,10 +228,6 @@ if (is_linux || is_chromeos) {
|
|||||||
pkg_config("egl") {
|
pkg_config("egl") {
|
||||||
packages = [ "egl" ]
|
packages = [ "egl" ]
|
||||||
}
|
}
|
||||||
pkg_config("epoxy") {
|
|
||||||
packages = [ "epoxy" ]
|
|
||||||
ignore_libs = true
|
|
||||||
}
|
|
||||||
pkg_config("libdrm") {
|
pkg_config("libdrm") {
|
||||||
packages = [ "libdrm" ]
|
packages = [ "libdrm" ]
|
||||||
if (!rtc_link_pipewire) {
|
if (!rtc_link_pipewire) {
|
||||||
@ -578,7 +574,6 @@ rtc_library("desktop_capture_generic") {
|
|||||||
":pipewire",
|
":pipewire",
|
||||||
":gbm",
|
":gbm",
|
||||||
":egl",
|
":egl",
|
||||||
":epoxy",
|
|
||||||
":libdrm",
|
":libdrm",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -49,6 +49,10 @@ typedef void* (*eglGetProcAddress_func)(const char*);
|
|||||||
typedef EGLDisplay (*eglGetPlatformDisplayEXT_func)(EGLenum platform,
|
typedef EGLDisplay (*eglGetPlatformDisplayEXT_func)(EGLenum platform,
|
||||||
void* native_display,
|
void* native_display,
|
||||||
const EGLint* attrib_list);
|
const EGLint* attrib_list);
|
||||||
|
typedef EGLDisplay (*eglGetPlatformDisplay_func)(EGLenum platform,
|
||||||
|
void* native_display,
|
||||||
|
const EGLAttrib* attrib_list);
|
||||||
|
|
||||||
typedef EGLBoolean (*eglInitialize_func)(EGLDisplay dpy,
|
typedef EGLBoolean (*eglInitialize_func)(EGLDisplay dpy,
|
||||||
EGLint* major,
|
EGLint* major,
|
||||||
EGLint* minor);
|
EGLint* minor);
|
||||||
@ -83,6 +87,7 @@ eglDestroyImageKHR_func EglDestroyImageKHR = nullptr;
|
|||||||
eglGetError_func EglGetError = nullptr;
|
eglGetError_func EglGetError = nullptr;
|
||||||
eglGetProcAddress_func EglGetProcAddress = nullptr;
|
eglGetProcAddress_func EglGetProcAddress = nullptr;
|
||||||
eglGetPlatformDisplayEXT_func EglGetPlatformDisplayEXT = nullptr;
|
eglGetPlatformDisplayEXT_func EglGetPlatformDisplayEXT = nullptr;
|
||||||
|
eglGetPlatformDisplay_func EglGetPlatformDisplay = nullptr;
|
||||||
eglInitialize_func EglInitialize = nullptr;
|
eglInitialize_func EglInitialize = nullptr;
|
||||||
eglMakeCurrent_func EglMakeCurrent = nullptr;
|
eglMakeCurrent_func EglMakeCurrent = nullptr;
|
||||||
eglQueryDmaBufFormatsEXT_func EglQueryDmaBufFormatsEXT = nullptr;
|
eglQueryDmaBufFormatsEXT_func EglQueryDmaBufFormatsEXT = nullptr;
|
||||||
@ -225,6 +230,8 @@ static bool LoadEGL() {
|
|||||||
EglGetError = (eglGetError_func)EglGetProcAddress("eglGetError");
|
EglGetError = (eglGetError_func)EglGetProcAddress("eglGetError");
|
||||||
EglGetPlatformDisplayEXT = (eglGetPlatformDisplayEXT_func)EglGetProcAddress(
|
EglGetPlatformDisplayEXT = (eglGetPlatformDisplayEXT_func)EglGetProcAddress(
|
||||||
"eglGetPlatformDisplayEXT");
|
"eglGetPlatformDisplayEXT");
|
||||||
|
EglGetPlatformDisplay =
|
||||||
|
(eglGetPlatformDisplay_func)EglGetProcAddress("eglGetPlatformDisplay");
|
||||||
EglInitialize = (eglInitialize_func)EglGetProcAddress("eglInitialize");
|
EglInitialize = (eglInitialize_func)EglGetProcAddress("eglInitialize");
|
||||||
EglMakeCurrent = (eglMakeCurrent_func)EglGetProcAddress("eglMakeCurrent");
|
EglMakeCurrent = (eglMakeCurrent_func)EglGetProcAddress("eglMakeCurrent");
|
||||||
EglQueryString = (eglQueryString_func)EglGetProcAddress("eglQueryString");
|
EglQueryString = (eglQueryString_func)EglGetProcAddress("eglQueryString");
|
||||||
@ -234,8 +241,9 @@ static bool LoadEGL() {
|
|||||||
|
|
||||||
return EglBindAPI && EglCreateContext && EglCreateImageKHR &&
|
return EglBindAPI && EglCreateContext && EglCreateImageKHR &&
|
||||||
EglTerminate && EglDestroyContext && EglDestroyImageKHR &&
|
EglTerminate && EglDestroyContext && EglDestroyImageKHR &&
|
||||||
EglGetError && EglGetPlatformDisplayEXT && EglInitialize &&
|
EglGetError && EglGetPlatformDisplayEXT && EglGetPlatformDisplay &&
|
||||||
EglMakeCurrent && EglQueryString && GlEGLImageTargetTexture2DOES;
|
EglInitialize && EglMakeCurrent && EglQueryString &&
|
||||||
|
GlEGLImageTargetTexture2DOES;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -284,25 +292,6 @@ static bool LoadGL() {
|
|||||||
|
|
||||||
RTC_NO_SANITIZE("cfi-icall")
|
RTC_NO_SANITIZE("cfi-icall")
|
||||||
EglDmaBuf::EglDmaBuf() {
|
EglDmaBuf::EglDmaBuf() {
|
||||||
absl::optional<std::string> render_node = GetRenderNode();
|
|
||||||
if (!render_node) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
drm_fd_ = open(render_node->c_str(), O_RDWR);
|
|
||||||
|
|
||||||
if (drm_fd_ < 0) {
|
|
||||||
RTC_LOG(LS_ERROR) << "Failed to open drm render node: " << strerror(errno);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
gbm_device_ = gbm_create_device(drm_fd_);
|
|
||||||
|
|
||||||
if (!gbm_device_) {
|
|
||||||
RTC_LOG(LS_ERROR) << "Cannot create GBM device: " << strerror(errno);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!LoadEGL()) {
|
if (!LoadEGL()) {
|
||||||
RTC_LOG(LS_ERROR) << "Unable to load EGL entry functions.";
|
RTC_LOG(LS_ERROR) << "Unable to load EGL entry functions.";
|
||||||
CloseLibrary(g_lib_egl);
|
CloseLibrary(g_lib_egl);
|
||||||
@ -315,26 +304,13 @@ EglDmaBuf::EglDmaBuf() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the list of client extensions
|
if (!GetClientExtensions(EGL_NO_DISPLAY, EGL_EXTENSIONS)) {
|
||||||
const char* client_extensions_cstring_no_display =
|
|
||||||
EglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
|
|
||||||
std::string client_extensions_string = client_extensions_cstring_no_display;
|
|
||||||
if (!client_extensions_cstring_no_display) {
|
|
||||||
// If eglQueryString() returned NULL, the implementation doesn't support
|
|
||||||
// EGL_EXT_client_extensions. Expect an EGL_BAD_DISPLAY error.
|
|
||||||
RTC_LOG(LS_ERROR) << "No client extensions defined! "
|
|
||||||
<< FormatEGLError(EglGetError());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<absl::string_view> client_extensions_no_display =
|
|
||||||
rtc::split(client_extensions_cstring_no_display, ' ');
|
|
||||||
for (const auto& extension : client_extensions_no_display) {
|
|
||||||
egl_.extensions.push_back(std::string(extension));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool has_platform_base_ext = false;
|
bool has_platform_base_ext = false;
|
||||||
bool has_platform_gbm_ext = false;
|
bool has_platform_gbm_ext = false;
|
||||||
|
bool has_khr_platform_gbm_ext = false;
|
||||||
|
|
||||||
for (const auto& extension : egl_.extensions) {
|
for (const auto& extension : egl_.extensions) {
|
||||||
if (extension == "EGL_EXT_platform_base") {
|
if (extension == "EGL_EXT_platform_base") {
|
||||||
@ -343,18 +319,51 @@ EglDmaBuf::EglDmaBuf() {
|
|||||||
} else if (extension == "EGL_MESA_platform_gbm") {
|
} else if (extension == "EGL_MESA_platform_gbm") {
|
||||||
has_platform_gbm_ext = true;
|
has_platform_gbm_ext = true;
|
||||||
continue;
|
continue;
|
||||||
|
} else if (extension == "EGL_KHR_platform_gbm") {
|
||||||
|
has_khr_platform_gbm_ext = true;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!has_platform_base_ext || !has_platform_gbm_ext) {
|
if (!has_platform_base_ext || !has_platform_gbm_ext ||
|
||||||
|
!has_khr_platform_gbm_ext) {
|
||||||
RTC_LOG(LS_ERROR) << "One of required EGL extensions is missing";
|
RTC_LOG(LS_ERROR) << "One of required EGL extensions is missing";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
egl_.display = EglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR,
|
||||||
|
(void*)EGL_DEFAULT_DISPLAY, nullptr);
|
||||||
|
|
||||||
|
if (egl_.display == EGL_NO_DISPLAY) {
|
||||||
|
RTC_LOG(LS_ERROR) << "Failed to obtain default EGL display: "
|
||||||
|
<< FormatEGLError(EglGetError()) << "\n"
|
||||||
|
<< "Defaulting to using first available render node";
|
||||||
|
absl::optional<std::string> render_node = GetRenderNode();
|
||||||
|
if (!render_node) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
drm_fd_ = open(render_node->c_str(), O_RDWR);
|
||||||
|
|
||||||
|
if (drm_fd_ < 0) {
|
||||||
|
RTC_LOG(LS_ERROR) << "Failed to open drm render node: "
|
||||||
|
<< strerror(errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gbm_device_ = gbm_create_device(drm_fd_);
|
||||||
|
|
||||||
|
if (!gbm_device_) {
|
||||||
|
RTC_LOG(LS_ERROR) << "Cannot create GBM device: " << strerror(errno);
|
||||||
|
close(drm_fd_);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Use eglGetPlatformDisplayEXT() to get the display pointer
|
// Use eglGetPlatformDisplayEXT() to get the display pointer
|
||||||
// if the implementation supports it.
|
// if the implementation supports it.
|
||||||
egl_.display =
|
egl_.display =
|
||||||
EglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_MESA, gbm_device_, nullptr);
|
EglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_KHR, gbm_device_, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
if (egl_.display == EGL_NO_DISPLAY) {
|
if (egl_.display == EGL_NO_DISPLAY) {
|
||||||
RTC_LOG(LS_ERROR) << "Error during obtaining EGL display: "
|
RTC_LOG(LS_ERROR) << "Error during obtaining EGL display: "
|
||||||
@ -383,14 +392,8 @@ EglDmaBuf::EglDmaBuf() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* client_extensions_cstring_display =
|
if (!GetClientExtensions(egl_.display, EGL_EXTENSIONS)) {
|
||||||
EglQueryString(egl_.display, EGL_EXTENSIONS);
|
return;
|
||||||
client_extensions_string = client_extensions_cstring_display;
|
|
||||||
|
|
||||||
std::vector<absl::string_view> client_extensions =
|
|
||||||
rtc::split(client_extensions_string, ' ');
|
|
||||||
for (const auto& extension : client_extensions) {
|
|
||||||
egl_.extensions.push_back(std::string(extension));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_image_dma_buf_import_modifiers_ext = false;
|
bool has_image_dma_buf_import_modifiers_ext = false;
|
||||||
@ -421,6 +424,7 @@ RTC_NO_SANITIZE("cfi-icall")
|
|||||||
EglDmaBuf::~EglDmaBuf() {
|
EglDmaBuf::~EglDmaBuf() {
|
||||||
if (gbm_device_) {
|
if (gbm_device_) {
|
||||||
gbm_device_destroy(gbm_device_);
|
gbm_device_destroy(gbm_device_);
|
||||||
|
close(drm_fd_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (egl_.context != EGL_NO_CONTEXT) {
|
if (egl_.context != EGL_NO_CONTEXT) {
|
||||||
@ -440,6 +444,27 @@ EglDmaBuf::~EglDmaBuf() {
|
|||||||
// CloseLibrary(g_lib_gl);
|
// CloseLibrary(g_lib_gl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RTC_NO_SANITIZE("cfi-icall")
|
||||||
|
bool EglDmaBuf::GetClientExtensions(EGLDisplay dpy, EGLint name) {
|
||||||
|
// Get the list of client extensions
|
||||||
|
const char* client_extensions_cstring = EglQueryString(dpy, name);
|
||||||
|
if (!client_extensions_cstring) {
|
||||||
|
// If eglQueryString() returned NULL, the implementation doesn't support
|
||||||
|
// EGL_EXT_client_extensions. Expect an EGL_BAD_DISPLAY error.
|
||||||
|
RTC_LOG(LS_ERROR) << "No client extensions defined! "
|
||||||
|
<< FormatEGLError(EglGetError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<absl::string_view> client_extensions =
|
||||||
|
rtc::split(client_extensions_cstring, ' ');
|
||||||
|
for (const auto& extension : client_extensions) {
|
||||||
|
egl_.extensions.push_back(std::string(extension));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
RTC_NO_SANITIZE("cfi-icall")
|
RTC_NO_SANITIZE("cfi-icall")
|
||||||
std::unique_ptr<uint8_t[]> EglDmaBuf::ImageFromDmaBuf(
|
std::unique_ptr<uint8_t[]> EglDmaBuf::ImageFromDmaBuf(
|
||||||
const DesktopSize& size,
|
const DesktopSize& size,
|
||||||
@ -457,50 +482,92 @@ std::unique_ptr<uint8_t[]> EglDmaBuf::ImageFromDmaBuf(
|
|||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
gbm_bo* imported;
|
EGLint attribs[47];
|
||||||
|
int atti = 0;
|
||||||
|
|
||||||
if (modifier == DRM_FORMAT_MOD_INVALID) {
|
attribs[atti++] = EGL_WIDTH;
|
||||||
gbm_import_fd_data import_info = {
|
attribs[atti++] = static_cast<EGLint>(size.width());
|
||||||
plane_datas[0].fd, static_cast<uint32_t>(size.width()),
|
attribs[atti++] = EGL_HEIGHT;
|
||||||
static_cast<uint32_t>(size.height()), plane_datas[0].stride,
|
attribs[atti++] = static_cast<EGLint>(size.height());
|
||||||
GBM_BO_FORMAT_ARGB8888};
|
attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
|
||||||
|
attribs[atti++] = SpaPixelFormatToDrmFormat(format);
|
||||||
|
|
||||||
imported = gbm_bo_import(gbm_device_, GBM_BO_IMPORT_FD, &import_info, 0);
|
if (plane_datas.size() > 0) {
|
||||||
} else {
|
attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT;
|
||||||
gbm_import_fd_modifier_data import_info = {};
|
attribs[atti++] = plane_datas[0].fd;
|
||||||
import_info.format = GBM_BO_FORMAT_ARGB8888;
|
attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
|
||||||
import_info.width = static_cast<uint32_t>(size.width());
|
attribs[atti++] = plane_datas[0].offset;
|
||||||
import_info.height = static_cast<uint32_t>(size.height());
|
attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
|
||||||
import_info.num_fds = plane_datas.size();
|
attribs[atti++] = plane_datas[0].stride;
|
||||||
import_info.modifier = modifier;
|
|
||||||
for (uint32_t i = 0; i < plane_datas.size(); i++) {
|
if (modifier != DRM_FORMAT_MOD_INVALID) {
|
||||||
import_info.fds[i] = plane_datas[i].fd;
|
attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
|
||||||
import_info.offsets[i] = plane_datas[i].offset;
|
attribs[atti++] = modifier & 0xFFFFFFFF;
|
||||||
import_info.strides[i] = plane_datas[i].stride;
|
attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
|
||||||
|
attribs[atti++] = modifier >> 32;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
imported =
|
if (plane_datas.size() > 1) {
|
||||||
gbm_bo_import(gbm_device_, GBM_BO_IMPORT_FD_MODIFIER, &import_info, 0);
|
attribs[atti++] = EGL_DMA_BUF_PLANE1_FD_EXT;
|
||||||
|
attribs[atti++] = plane_datas[1].fd;
|
||||||
|
attribs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
|
||||||
|
attribs[atti++] = plane_datas[1].offset;
|
||||||
|
attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
|
||||||
|
attribs[atti++] = plane_datas[1].stride;
|
||||||
|
|
||||||
|
if (modifier != DRM_FORMAT_MOD_INVALID) {
|
||||||
|
attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
|
||||||
|
attribs[atti++] = modifier & 0xFFFFFFFF;
|
||||||
|
attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
|
||||||
|
attribs[atti++] = modifier >> 32;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!imported) {
|
if (plane_datas.size() > 2) {
|
||||||
RTC_LOG(LS_ERROR)
|
attribs[atti++] = EGL_DMA_BUF_PLANE2_FD_EXT;
|
||||||
<< "Failed to process buffer: Cannot import passed GBM fd - "
|
attribs[atti++] = plane_datas[2].fd;
|
||||||
<< strerror(errno);
|
attribs[atti++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
|
||||||
return src;
|
attribs[atti++] = plane_datas[2].offset;
|
||||||
|
attribs[atti++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
|
||||||
|
attribs[atti++] = plane_datas[2].stride;
|
||||||
|
|
||||||
|
if (modifier != DRM_FORMAT_MOD_INVALID) {
|
||||||
|
attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
|
||||||
|
attribs[atti++] = modifier & 0xFFFFFFFF;
|
||||||
|
attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
|
||||||
|
attribs[atti++] = modifier >> 32;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plane_datas.size() > 3) {
|
||||||
|
attribs[atti++] = EGL_DMA_BUF_PLANE3_FD_EXT;
|
||||||
|
attribs[atti++] = plane_datas[3].fd;
|
||||||
|
attribs[atti++] = EGL_DMA_BUF_PLANE3_OFFSET_EXT;
|
||||||
|
attribs[atti++] = plane_datas[3].offset;
|
||||||
|
attribs[atti++] = EGL_DMA_BUF_PLANE3_PITCH_EXT;
|
||||||
|
attribs[atti++] = plane_datas[3].stride;
|
||||||
|
|
||||||
|
if (modifier != DRM_FORMAT_MOD_INVALID) {
|
||||||
|
attribs[atti++] = EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT;
|
||||||
|
attribs[atti++] = modifier & 0xFFFFFFFF;
|
||||||
|
attribs[atti++] = EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT;
|
||||||
|
attribs[atti++] = modifier >> 32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
attribs[atti++] = EGL_NONE;
|
||||||
|
|
||||||
// bind context to render thread
|
// bind context to render thread
|
||||||
EglMakeCurrent(egl_.display, EGL_NO_SURFACE, EGL_NO_SURFACE, egl_.context);
|
EglMakeCurrent(egl_.display, EGL_NO_SURFACE, EGL_NO_SURFACE, egl_.context);
|
||||||
|
|
||||||
// create EGL image from imported BO
|
// create EGL image from attribute list
|
||||||
EGLImageKHR image = EglCreateImageKHR(
|
EGLImageKHR image = EglCreateImageKHR(
|
||||||
egl_.display, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, imported, nullptr);
|
egl_.display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attribs);
|
||||||
|
|
||||||
if (image == EGL_NO_IMAGE) {
|
if (image == EGL_NO_IMAGE) {
|
||||||
RTC_LOG(LS_ERROR) << "Failed to record frame: Error creating EGLImage - "
|
RTC_LOG(LS_ERROR) << "Failed to record frame: Error creating EGLImage - "
|
||||||
<< FormatEGLError(EglGetError());
|
<< FormatEGLError(EglGetError());
|
||||||
gbm_bo_destroy(imported);
|
|
||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,12 +594,6 @@ std::unique_ptr<uint8_t[]> EglDmaBuf::ImageFromDmaBuf(
|
|||||||
case SPA_VIDEO_FORMAT_BGRx:
|
case SPA_VIDEO_FORMAT_BGRx:
|
||||||
gl_format = GL_BGRA;
|
gl_format = GL_BGRA;
|
||||||
break;
|
break;
|
||||||
case SPA_VIDEO_FORMAT_RGB:
|
|
||||||
gl_format = GL_RGB;
|
|
||||||
break;
|
|
||||||
case SPA_VIDEO_FORMAT_BGR:
|
|
||||||
gl_format = GL_BGR;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
gl_format = GL_BGRA;
|
gl_format = GL_BGRA;
|
||||||
break;
|
break;
|
||||||
@ -541,15 +602,12 @@ std::unique_ptr<uint8_t[]> EglDmaBuf::ImageFromDmaBuf(
|
|||||||
|
|
||||||
if (GlGetError()) {
|
if (GlGetError()) {
|
||||||
RTC_LOG(LS_ERROR) << "Failed to get image from DMA buffer.";
|
RTC_LOG(LS_ERROR) << "Failed to get image from DMA buffer.";
|
||||||
gbm_bo_destroy(imported);
|
|
||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
GlDeleteTextures(1, &texture);
|
GlDeleteTextures(1, &texture);
|
||||||
EglDestroyImageKHR(egl_.display, image);
|
EglDestroyImageKHR(egl_.display, image);
|
||||||
|
|
||||||
gbm_bo_destroy(imported);
|
|
||||||
|
|
||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +51,8 @@ class EglDmaBuf {
|
|||||||
bool IsEglInitialized() const { return egl_initialized_; }
|
bool IsEglInitialized() const { return egl_initialized_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool GetClientExtensions(EGLDisplay dpy, EGLint name);
|
||||||
|
|
||||||
bool egl_initialized_ = false;
|
bool egl_initialized_ = false;
|
||||||
bool has_image_dma_buf_import_ext_ = false;
|
bool has_image_dma_buf_import_ext_ = false;
|
||||||
int32_t drm_fd_ = -1; // for GBM buffer mmap
|
int32_t drm_fd_ = -1; // for GBM buffer mmap
|
||||||
|
@ -104,10 +104,16 @@ spa_pod* BuildFormat(spa_pod_builder* builder,
|
|||||||
spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_format, SPA_POD_Id(format), 0);
|
spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_format, SPA_POD_Id(format), 0);
|
||||||
|
|
||||||
if (modifiers.size()) {
|
if (modifiers.size()) {
|
||||||
|
if (modifiers.size() == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID) {
|
||||||
|
spa_pod_builder_prop(builder, SPA_FORMAT_VIDEO_modifier,
|
||||||
|
SPA_POD_PROP_FLAG_MANDATORY);
|
||||||
|
spa_pod_builder_long(builder, modifiers[0]);
|
||||||
|
} else {
|
||||||
spa_pod_builder_prop(
|
spa_pod_builder_prop(
|
||||||
builder, SPA_FORMAT_VIDEO_modifier,
|
builder, SPA_FORMAT_VIDEO_modifier,
|
||||||
SPA_POD_PROP_FLAG_MANDATORY | SPA_POD_PROP_FLAG_DONT_FIXATE);
|
SPA_POD_PROP_FLAG_MANDATORY | SPA_POD_PROP_FLAG_DONT_FIXATE);
|
||||||
spa_pod_builder_push_choice(builder, &frames[1], SPA_CHOICE_Enum, 0);
|
spa_pod_builder_push_choice(builder, &frames[1], SPA_CHOICE_Enum, 0);
|
||||||
|
|
||||||
// modifiers from the array
|
// modifiers from the array
|
||||||
for (int64_t val : modifiers) {
|
for (int64_t val : modifiers) {
|
||||||
spa_pod_builder_long(builder, val);
|
spa_pod_builder_long(builder, val);
|
||||||
@ -120,6 +126,7 @@ spa_pod* BuildFormat(spa_pod_builder* builder,
|
|||||||
}
|
}
|
||||||
spa_pod_builder_pop(builder, &frames[1]);
|
spa_pod_builder_pop(builder, &frames[1]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
spa_pod_builder_add(
|
spa_pod_builder_add(
|
||||||
builder, SPA_FORMAT_VIDEO_size,
|
builder, SPA_FORMAT_VIDEO_size,
|
||||||
@ -471,8 +478,12 @@ bool SharedScreenCastStreamPrivate::StartScreenCastStream(
|
|||||||
// Check if the PipeWire and DRM libraries are available.
|
// Check if the PipeWire and DRM libraries are available.
|
||||||
paths[kModulePipewire].push_back(kPipeWireLib);
|
paths[kModulePipewire].push_back(kPipeWireLib);
|
||||||
paths[kModuleDrm].push_back(kDrmLib);
|
paths[kModuleDrm].push_back(kDrmLib);
|
||||||
|
|
||||||
if (!InitializeStubs(paths)) {
|
if (!InitializeStubs(paths)) {
|
||||||
RTC_LOG(LS_ERROR) << "Failed to load the PipeWire library and symbols.";
|
RTC_LOG(LS_ERROR)
|
||||||
|
<< "One of following libraries is missing on your system:\n"
|
||||||
|
<< " - PipeWire (" << kPipeWireLib << ")\n"
|
||||||
|
<< " - drm (" << kDrmLib << ")";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif // defined(WEBRTC_DLOPEN_PIPEWIRE)
|
#endif // defined(WEBRTC_DLOPEN_PIPEWIRE)
|
||||||
|
Reference in New Issue
Block a user