25 #include <EGL/eglext.h>
26 #include <GLES2/gl2.h>
27 #include <GLES2/gl2ext.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
49 static bool receive_buff(
int socket,
BufferData *data)
52 struct iovec io = { .iov_base = &data->
meta,
53 .iov_len =
sizeof data->
meta };
60 msg.msg_control = c_buffer;
61 msg.msg_controllen =
sizeof c_buffer;
63 if ((res = recvmsg(socket, &msg, 0)) == -1) {
64 MH_ERROR(
"Failed to receive message");
66 }
else if (res == 0) {
67 MH_ERROR(
"Socket shutdown while receiving buffer data");
71 struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
73 memmove(&data->
fd, CMSG_DATA(cmsg),
sizeof data->
fd);
85 static void read_sock_events(
PlayerKey key,
87 promise<BufferData>& prom_buff,
90 static const char *consumer_socket =
"media-consumer";
92 struct sockaddr_un local;
97 MH_ERROR(
"Cannot create buffer consumer socket: %s (%d)",
98 strerror(errno), errno);
102 ostringstream sock_name_ss;
103 sock_name_ss << consumer_socket << key;
104 local.sun_family = AF_UNIX;
105 local.sun_path[0] =
'\0';
106 strcpy(local.sun_path + 1, sock_name_ss.str().c_str());
107 len =
sizeof(local.sun_family) + sock_name_ss.str().length() + 1;
108 if (bind(sock_fd, (
struct sockaddr *) &local, len) == -1) {
109 MH_ERROR(
"Cannot bind consumer socket: %s (%d)",
110 strerror(errno), errno);
115 if (!receive_buff(sock_fd, &buff_data))
118 prom_buff.set_value(buff_data);
125 res = recv(sock_fd, &c,
sizeof c, 0);
127 MH_ERROR(
"while waiting sync: %s (%d)",
128 strerror(errno), errno);
130 }
else if (res == 0) {
139 bool find_extension(
const string& extensions,
const string& ext)
141 size_t len_all = extensions.length();
142 size_t len = ext.length();
145 while ((pos = extensions.find(ext, pos)) != string::npos) {
146 if (pos + len == len_all || extensions[pos + len] ==
' ')
158 gl_texture{gl_texture},
160 fut_buff{prom_buff.get_future()},
161 sock_fd{socket(AF_UNIX, SOCK_DGRAM, 0)},
162 sock_thread{read_sock_events, key, sock_fd,
164 egl_image{EGL_NO_IMAGE_KHR},
167 const char *extensions;
168 const char *egl_needed[] = {
"EGL_KHR_image_base",
169 "EGL_EXT_image_dma_buf_import"};
170 EGLDisplay egl_display = eglGetCurrentDisplay();
175 extensions = eglQueryString (egl_display, EGL_EXTENSIONS);
177 throw runtime_error {
"Error querying EGL extensions"};
179 for (i = 0; i <
sizeof(egl_needed)/
sizeof(egl_needed[0]); ++i) {
180 if (!find_extension(extensions, egl_needed[i])) {
181 MH_DEBUG(
"%s not supported", egl_needed[i]);
203 _eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)
204 eglGetProcAddress(
"eglCreateImageKHR");
205 _eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)
206 eglGetProcAddress(
"eglDestroyImageKHR");
207 _glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)
208 eglGetProcAddress(
"glEGLImageTargetTexture2DOES");
210 if (_eglCreateImageKHR ==
nullptr || _eglDestroyImageKHR ==
nullptr ||
211 _glEGLImageTargetTexture2DOES ==
nullptr)
212 throw runtime_error {
"Error when loading extensions"};
218 shutdown(sock_fd, SHUT_RDWR);
226 if (egl_image != EGL_NO_IMAGE_KHR)
227 _eglDestroyImageKHR(eglGetCurrentDisplay(), egl_image);
237 EGLDisplay egl_display = eglGetCurrentDisplay();
238 EGLint image_attrs[] = {
241 EGL_LINUX_DRM_FOURCC_EXT, buf_data->
meta.
fourcc,
242 EGL_DMA_BUF_PLANE0_FD_EXT, buf_data->
fd,
243 EGL_DMA_BUF_PLANE0_OFFSET_EXT, buf_data->
meta.
offset,
244 EGL_DMA_BUF_PLANE0_PITCH_EXT, buf_data->
meta.
stride,
248 buf_fd = buf_data->
fd;
249 egl_image = _eglCreateImageKHR(egl_display, EGL_NO_CONTEXT,
250 EGL_LINUX_DMA_BUF_EXT, NULL, image_attrs);
251 if (egl_image == EGL_NO_IMAGE_KHR) {
252 MH_ERROR(
"eglCreateImageKHR error 0x%X", eglGetError());
257 glBindTexture(GL_TEXTURE_2D, gl_texture);
258 _glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image);
260 while((err = glGetError()) != GL_NO_ERROR)
263 MH_DEBUG(
"Image successfully imported");
283 EglVideoSink::EglVideoSink(uint32_t gl_texture,
296 return [playerKey](uint32_t textureId,
QObject *parent) {
306 if (d->egl_image == EGL_NO_IMAGE_KHR) {
308 if (!d->import_buffer(&buf_data))