21 #include <sys/types.h>
25 #include <sys/syscall.h>
33 #include <winpr/thread.h>
34 #include <winpr/string.h>
35 #include <winpr/platform.h>
39 #if GST_VERSION_MAJOR > 0
40 #include <gst/video/videooverlay.h>
42 #include <gst/interfaces/xoverlay.h>
46 #include <X11/extensions/Xrandr.h>
47 #include <X11/extensions/shape.h>
49 #include <freerdp/channels/tsmf.h>
51 #include "tsmf_platform.h"
52 #include "tsmf_constants.h"
53 #include "tsmf_decoder.h"
55 #if !defined(WITH_XEXT)
56 #warning "Building TSMF without shape extension support"
63 #if defined(WITH_XEXT)
69 #if GST_VERSION_MAJOR > 0
70 GstVideoOverlay* overlay;
80 static const char* get_shm_id()
82 static char shm_id[128];
83 sprintf_s(shm_id,
sizeof(shm_id),
"/com.freerdp.xfreerdp.tsmf_%016X", GetCurrentProcessId());
87 static GstBusSyncReply tsmf_platform_bus_sync_handler(GstBus* bus, GstMessage* message,
90 struct X11Handle* hdl;
94 if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_ELEMENT)
97 #if GST_VERSION_MAJOR > 0
98 if (!gst_is_video_overlay_prepare_window_handle_message(message))
101 if (!gst_structure_has_name(message->structure,
"prepare-xwindow-id"))
105 hdl = (
struct X11Handle*)decoder->platform;
109 #if GST_VERSION_MAJOR > 0
110 hdl->overlay = GST_VIDEO_OVERLAY(GST_MESSAGE_SRC(message));
111 gst_video_overlay_set_window_handle(hdl->overlay, hdl->subwin);
112 gst_video_overlay_handle_events(hdl->overlay, FALSE);
114 hdl->overlay = GST_X_OVERLAY(GST_MESSAGE_SRC(message));
115 #if GST_CHECK_VERSION(0, 10, 31)
116 gst_x_overlay_set_window_handle(hdl->overlay, hdl->subwin);
118 gst_x_overlay_set_xwindow_id(hdl->overlay, hdl->subwin);
120 gst_x_overlay_handle_events(hdl->overlay, TRUE);
123 if (hdl->subwinWidth != -1 && hdl->subwinHeight != -1 && hdl->subwinX != -1 &&
126 #if GST_VERSION_MAJOR > 0
127 if (!gst_video_overlay_set_render_rectangle(hdl->overlay, 0, 0, hdl->subwinWidth,
130 WLog_ERR(TAG,
"Could not resize overlay!");
133 gst_video_overlay_expose(hdl->overlay);
135 if (!gst_x_overlay_set_render_rectangle(hdl->overlay, 0, 0, hdl->subwinWidth,
138 WLog_ERR(TAG,
"Could not resize overlay!");
141 gst_x_overlay_expose(hdl->overlay);
143 XLockDisplay(hdl->disp);
144 XMoveResizeWindow(hdl->disp, hdl->subwin, hdl->subwinX, hdl->subwinY, hdl->subwinWidth,
146 XSync(hdl->disp, FALSE);
147 XUnlockDisplay(hdl->disp);
152 g_warning(
"Window was not available before retrieving the overlay!");
155 gst_message_unref(message);
160 const char* tsmf_platform_get_video_sink(
void)
162 return "autovideosink";
165 const char* tsmf_platform_get_audio_sink(
void)
167 return "autoaudiosink";
172 struct X11Handle* hdl;
177 if (decoder->platform)
180 hdl = calloc(1,
sizeof(
struct X11Handle));
183 WLog_ERR(TAG,
"Could not allocate handle.");
187 decoder->platform = hdl;
188 hdl->shmid = shm_open(get_shm_id(), (O_RDWR | O_CREAT), (PROT_READ | PROT_WRITE));
189 if (hdl->shmid == -1)
191 char ebuffer[256] = { 0 };
192 WLog_ERR(TAG,
"failed to get access to shared memory - shmget(%s): %i - %s", get_shm_id(),
193 errno, winpr_strerror(errno, ebuffer,
sizeof(ebuffer)));
197 hdl->xfwin = mmap(0,
sizeof(
void*), PROT_READ | PROT_WRITE, MAP_SHARED, hdl->shmid, 0);
198 if (hdl->xfwin == MAP_FAILED)
200 WLog_ERR(TAG,
"shmat failed!");
204 hdl->disp = XOpenDisplay(NULL);
207 WLog_ERR(TAG,
"Failed to open display");
211 hdl->subwinMapped = FALSE;
214 hdl->subwinWidth = -1;
215 hdl->subwinHeight = -1;
225 if (decoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
242 bus = gst_pipeline_get_bus(GST_PIPELINE(decoder->pipe));
244 #if GST_VERSION_MAJOR > 0
245 gst_bus_set_sync_handler(bus, (GstBusSyncHandler)tsmf_platform_bus_sync_handler, decoder, NULL);
247 gst_bus_set_sync_handler(bus, (GstBusSyncHandler)tsmf_platform_bus_sync_handler, decoder);
252 WLog_ERR(TAG,
"gst_pipeline_get_bus failed!");
256 gst_object_unref(bus);
263 struct X11Handle* hdl = decoder->platform;
269 XCloseDisplay(hdl->disp);
272 munmap(0,
sizeof(
void*));
278 decoder->platform = NULL;
285 struct X11Handle* hdl;
287 if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
289 decoder->ready = TRUE;
297 if (!decoder->platform)
300 hdl = (
struct X11Handle*)decoder->platform;
304 XLockDisplay(hdl->disp);
305 hdl->subwin = XCreateSimpleWindow(hdl->disp, *(
int*)hdl->xfwin, 0, 0, 1, 1, 0, 0, 0);
306 XUnlockDisplay(hdl->disp);
310 WLog_ERR(TAG,
"Could not create subwindow!");
314 tsmf_window_map(decoder);
316 decoder->ready = TRUE;
317 #if defined(WITH_XEXT)
319 XLockDisplay(hdl->disp);
320 hdl->has_shape = XShapeQueryExtension(hdl->disp, &event, &error);
321 XUnlockDisplay(hdl->disp);
331 struct X11Handle* hdl;
336 if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
341 if (!decoder->platform)
344 hdl = (
struct X11Handle*)decoder->platform;
345 DEBUG_TSMF(
"resize: x=%d, y=%d, w=%d, h=%d", x, y, width, height);
349 #if GST_VERSION_MAJOR > 0
351 if (!gst_video_overlay_set_render_rectangle(hdl->overlay, 0, 0, width, height))
353 WLog_ERR(TAG,
"Could not resize overlay!");
356 gst_video_overlay_expose(hdl->overlay);
358 if (!gst_x_overlay_set_render_rectangle(hdl->overlay, 0, 0, width, height))
360 WLog_ERR(TAG,
"Could not resize overlay!");
363 gst_x_overlay_expose(hdl->overlay);
371 hdl->subwinWidth = width;
372 hdl->subwinHeight = height;
374 XLockDisplay(hdl->disp);
375 XMoveResizeWindow(hdl->disp, hdl->subwin, hdl->subwinX, hdl->subwinY, hdl->subwinWidth,
380 tsmf_window_unmap(decoder);
382 tsmf_window_map(decoder);
384 #if defined(WITH_XEXT)
387 XRectangle* xrects = NULL;
391 xrects = calloc(1,
sizeof(XRectangle));
394 xrects->width = width;
395 xrects->height = height;
399 xrects = calloc(nr_rects,
sizeof(XRectangle));
404 for (
int i = 0; i < nr_rects; i++)
406 xrects[i].x = rects[i].x - x;
407 xrects[i].y = rects[i].y - y;
408 xrects[i].width = rects[i].width;
409 xrects[i].height = rects[i].height;
412 XShapeCombineRectangles(hdl->disp, hdl->subwin, ShapeBounding, x, y, xrects,
413 nr_rects, ShapeSet, 0);
418 XSync(hdl->disp, FALSE);
419 XUnlockDisplay(hdl->disp);
427 struct X11Handle* hdl;
431 hdl = (
struct X11Handle*)decoder->platform;
434 if ((hdl->subwin) && (!hdl->subwinMapped))
436 XLockDisplay(hdl->disp);
437 XMapWindow(hdl->disp, hdl->subwin);
438 hdl->subwinMapped = TRUE;
439 XSync(hdl->disp, FALSE);
440 XUnlockDisplay(hdl->disp);
448 struct X11Handle* hdl;
452 hdl = (
struct X11Handle*)decoder->platform;
455 if ((hdl->subwin) && (hdl->subwinMapped))
457 XLockDisplay(hdl->disp);
458 XUnmapWindow(hdl->disp, hdl->subwin);
459 hdl->subwinMapped = FALSE;
460 XSync(hdl->disp, FALSE);
461 XUnlockDisplay(hdl->disp);
469 struct X11Handle* hdl;
474 decoder->ready = FALSE;
476 if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
479 if (!decoder->platform)
482 hdl = (
struct X11Handle*)decoder->platform;
486 XLockDisplay(hdl->disp);
487 XDestroyWindow(hdl->disp, hdl->subwin);
488 XSync(hdl->disp, FALSE);
489 XUnlockDisplay(hdl->disp);
494 hdl->subwinMapped = FALSE;
497 hdl->subwinWidth = -1;
498 hdl->subwinHeight = -1;