25#include <EGL/eglext.h>
27#include <GLES2/gl2ext.h>
30#include <sys/socket.h>
50 struct iovec io = { .iov_base = &data->meta,
51 .iov_len =
sizeof data->meta };
58 msg.msg_control = c_buffer;
59 msg.msg_controllen =
sizeof c_buffer;
61 if ((res = recvmsg(socket, &msg, 0)) == -1) {
62 MH_ERROR(
"Failed to receive message");
64 }
else if (res == 0) {
65 MH_ERROR(
"Socket shutdown while receiving buffer data");
69 struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
71 memmove(&data->fd, CMSG_DATA(cmsg),
sizeof data->fd);
73 MH_DEBUG(
"Extracted fd %d", data->fd);
74 MH_DEBUG(
"width %d", data->meta.width);
75 MH_DEBUG(
"height %d", data->meta.height);
76 MH_DEBUG(
"fourcc 0x%X", data->meta.fourcc);
77 MH_DEBUG(
"stride %d", data->meta.stride);
78 MH_DEBUG(
"offset %d", data->meta.offset);
88 static const char *consumer_socket =
"media-consumer";
90 struct sockaddr_un local;
95 MH_ERROR(
"Cannot create buffer consumer socket: %s (%d)",
96 strerror(errno), errno);
100 ostringstream sock_name_ss;
101 sock_name_ss << consumer_socket << key;
102 local.sun_family = AF_UNIX;
103 local.sun_path[0] =
'\0';
104 strcpy(local.sun_path + 1, sock_name_ss.str().c_str());
105 len =
sizeof(local.sun_family) + sock_name_ss.str().length() + 1;
106 if (bind(
sock_fd, (
struct sockaddr *) &local, len) == -1) {
107 MH_ERROR(
"Cannot bind consumer socket: %s (%d)",
108 strerror(errno), errno);
123 res = recv(
sock_fd, &c,
sizeof c, 0);
125 MH_ERROR(
"while waiting sync: %s (%d)",
126 strerror(errno), errno);
128 }
else if (res == 0) {
139 size_t len_all = extensions.length();
140 size_t len = ext.length();
143 while ((pos = extensions.find(ext, pos)) != string::npos) {
144 if (pos + len == len_all || extensions[pos + len] ==
' ')
157 sock_fd{socket(AF_UNIX, SOCK_DGRAM, 0)},
163 const char *extensions;
164 const char *egl_needed[] = {
"EGL_KHR_image_base",
165 "EGL_EXT_image_dma_buf_import"};
166 EGLDisplay egl_display = eglGetCurrentDisplay();
171 extensions = eglQueryString (egl_display, EGL_EXTENSIONS);
173 throw runtime_error {
"Error querying EGL extensions"};
175 for (i = 0; i <
sizeof(egl_needed)/
sizeof(egl_needed[0]); ++i) {
177 MH_DEBUG(
"%s not supported", egl_needed[i]);
200 eglGetProcAddress(
"eglCreateImageKHR");
202 eglGetProcAddress(
"eglDestroyImageKHR");
204 eglGetProcAddress(
"glEGLImageTargetTexture2DOES");
208 throw runtime_error {
"Error when loading extensions"};
233 EGLDisplay egl_display = eglGetCurrentDisplay();
234 EGLint image_attrs[] = {
235 EGL_WIDTH, buf_data->meta.width,
236 EGL_HEIGHT, buf_data->meta.height,
237 EGL_LINUX_DRM_FOURCC_EXT, buf_data->meta.fourcc,
238 EGL_DMA_BUF_PLANE0_FD_EXT, buf_data->fd,
239 EGL_DMA_BUF_PLANE0_OFFSET_EXT, buf_data->meta.offset,
240 EGL_DMA_BUF_PLANE0_PITCH_EXT, buf_data->meta.stride,
246 EGL_LINUX_DMA_BUF_EXT, NULL, image_attrs);
248 MH_ERROR(
"eglCreateImageKHR error 0x%X", eglGetError());
256 while((err = glGetError()) != GL_NO_ERROR)
259 MH_DEBUG(
"Image successfully imported");
280 return [key](uint32_t texture)
286video::EglSink::EglSink(uint32_t gl_texture,
288 : d{new Private{gl_texture, key}}
298 return d->frame_available;
304 static const float identity_4x4[] = { 1, 0, 0, 0,
309 memcpy(matrix, identity_4x4,
sizeof identity_4x4);
316 if (d->egl_image == EGL_NO_IMAGE_KHR) {
317 BufferData buf_data = d->fut_buff.get();
318 if (!d->import_buffer(&buf_data))
promise< BufferData > prom_buff
static void read_sock_events(const media::Player::PlayerKey key, int sock_fd, promise< BufferData > &prom_buff, core::Signal< void > &frame_available)
PFNEGLDESTROYIMAGEKHRPROC _eglDestroyImageKHR
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC _glEGLImageTargetTexture2DOES
bool find_extension(const string &extensions, const string &ext)
core::Signal< void > frame_available
PFNEGLCREATEIMAGEKHRPROC _eglCreateImageKHR
Private(uint32_t gl_texture, const media::Player::PlayerKey key)
static bool receive_buff(int socket, BufferData *data)
future< BufferData > fut_buff
bool import_buffer(const BufferData *buf_data)