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"
69#if GST_VERSION_MAJOR > 0
70 GstVideoOverlay* overlay;
81static const char* get_shm_id()
83 static char shm_id[128] = WINPR_C_ARRAY_INIT;
84 if (sprintf_s(shm_id,
sizeof(shm_id),
"/com.freerdp.xfreerdp.tsmf_%016X",
85 GetCurrentProcessId()) < 0)
90static GstBusSyncReply tsmf_platform_bus_sync_handler(GstBus* bus, GstMessage* message,
93 struct X11Handle* hdl;
97 if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_ELEMENT)
100#if GST_VERSION_MAJOR > 0
101 if (!gst_is_video_overlay_prepare_window_handle_message(message))
104 if (!gst_structure_has_name(message->structure,
"prepare-xwindow-id"))
108 hdl = (
struct X11Handle*)decoder->platform;
112#if GST_VERSION_MAJOR > 0
113 hdl->overlay = GST_VIDEO_OVERLAY(GST_MESSAGE_SRC(message));
114 gst_video_overlay_set_window_handle(hdl->overlay, hdl->subwin);
115 gst_video_overlay_handle_events(hdl->overlay, FALSE);
117 hdl->overlay = GST_X_OVERLAY(GST_MESSAGE_SRC(message));
118#if GST_CHECK_VERSION(0, 10, 31)
119 gst_x_overlay_set_window_handle(hdl->overlay, hdl->subwin);
121 gst_x_overlay_set_xwindow_id(hdl->overlay, hdl->subwin);
123 gst_x_overlay_handle_events(hdl->overlay, TRUE);
126 if (hdl->subwinWidth != -1 && hdl->subwinHeight != -1 && hdl->subwinX != -1 &&
129#if GST_VERSION_MAJOR > 0
130 if (!gst_video_overlay_set_render_rectangle(hdl->overlay, 0, 0, hdl->subwinWidth,
133 WLog_ERR(TAG,
"Could not resize overlay!");
136 gst_video_overlay_expose(hdl->overlay);
138 if (!gst_x_overlay_set_render_rectangle(hdl->overlay, 0, 0, hdl->subwinWidth,
141 WLog_ERR(TAG,
"Could not resize overlay!");
144 gst_x_overlay_expose(hdl->overlay);
146 XLockDisplay(hdl->disp);
147 XMoveResizeWindow(hdl->disp, hdl->subwin, hdl->subwinX, hdl->subwinY, hdl->subwinWidth,
149 XSync(hdl->disp, FALSE);
150 XUnlockDisplay(hdl->disp);
155 g_warning(
"Window was not available before retrieving the overlay!");
158 gst_message_unref(message);
163const char* tsmf_platform_get_video_sink(
void)
165 return "autovideosink";
168const char* tsmf_platform_get_audio_sink(
void)
170 return "autoaudiosink";
175 struct X11Handle* hdl;
180 if (decoder->platform)
183 hdl = calloc(1,
sizeof(
struct X11Handle));
186 WLog_ERR(TAG,
"Could not allocate handle.");
190 decoder->platform = hdl;
191 hdl->shmid = shm_open(get_shm_id(), (O_RDWR | O_CREAT), (PROT_READ | PROT_WRITE));
192 if (hdl->shmid == -1)
194 char ebuffer[256] = WINPR_C_ARRAY_INIT;
195 WLog_ERR(TAG,
"failed to get access to shared memory - shmget(%s): %i - %s", get_shm_id(),
196 errno, winpr_strerror(errno, ebuffer,
sizeof(ebuffer)));
200 hdl->xfwin = mmap(0,
sizeof(
void*), PROT_READ | PROT_WRITE, MAP_SHARED, hdl->shmid, 0);
201 if (hdl->xfwin == MAP_FAILED)
203 WLog_ERR(TAG,
"shmat failed!");
207 hdl->disp = XOpenDisplay(
nullptr);
210 WLog_ERR(TAG,
"Failed to open display");
214 hdl->subwinMapped = FALSE;
217 hdl->subwinWidth = -1;
218 hdl->subwinHeight = -1;
228 if (decoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
245 bus = gst_pipeline_get_bus(GST_PIPELINE(decoder->pipe));
247#if GST_VERSION_MAJOR > 0
248 gst_bus_set_sync_handler(bus, (GstBusSyncHandler)tsmf_platform_bus_sync_handler, decoder,
251 gst_bus_set_sync_handler(bus, (GstBusSyncHandler)tsmf_platform_bus_sync_handler, decoder);
256 WLog_ERR(TAG,
"gst_pipeline_get_bus failed!");
260 gst_object_unref(bus);
267 struct X11Handle* hdl = decoder->platform;
273 XCloseDisplay(hdl->disp);
276 munmap(0,
sizeof(
void*));
282 decoder->platform =
nullptr;
289 struct X11Handle* hdl;
291 if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
293 decoder->ready = TRUE;
301 if (!decoder->platform)
304 hdl = (
struct X11Handle*)decoder->platform;
308 XLockDisplay(hdl->disp);
309 hdl->subwin = XCreateSimpleWindow(hdl->disp, *(
int*)hdl->xfwin, 0, 0, 1, 1, 0, 0, 0);
310 XUnlockDisplay(hdl->disp);
314 WLog_ERR(TAG,
"Could not create subwindow!");
318 tsmf_window_map(decoder);
320 decoder->ready = TRUE;
321#if defined(WITH_XEXT)
323 XLockDisplay(hdl->disp);
324 hdl->has_shape = XShapeQueryExtension(hdl->disp, &event, &error);
325 XUnlockDisplay(hdl->disp);
335 struct X11Handle* hdl;
340 if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
345 if (!decoder->platform)
348 hdl = (
struct X11Handle*)decoder->platform;
349 DEBUG_TSMF(
"resize: x=%d, y=%d, w=%d, h=%d", x, y, width, height);
353#if GST_VERSION_MAJOR > 0
355 if (!gst_video_overlay_set_render_rectangle(hdl->overlay, 0, 0, width, height))
357 WLog_ERR(TAG,
"Could not resize overlay!");
360 gst_video_overlay_expose(hdl->overlay);
362 if (!gst_x_overlay_set_render_rectangle(hdl->overlay, 0, 0, width, height))
364 WLog_ERR(TAG,
"Could not resize overlay!");
367 gst_x_overlay_expose(hdl->overlay);
375 hdl->subwinWidth = width;
376 hdl->subwinHeight = height;
378 XLockDisplay(hdl->disp);
379 XMoveResizeWindow(hdl->disp, hdl->subwin, hdl->subwinX, hdl->subwinY, hdl->subwinWidth,
384 tsmf_window_unmap(decoder);
386 tsmf_window_map(decoder);
388#if defined(WITH_XEXT)
391 XRectangle* xrects =
nullptr;
395 xrects = calloc(1,
sizeof(XRectangle));
398 xrects->width = width;
399 xrects->height = height;
403 xrects = calloc(nr_rects,
sizeof(XRectangle));
408 for (
int i = 0; i < nr_rects; i++)
410 xrects[i].x = rects[i].x - x;
411 xrects[i].y = rects[i].y - y;
412 xrects[i].width = rects[i].width;
413 xrects[i].height = rects[i].height;
416 XShapeCombineRectangles(hdl->disp, hdl->subwin, ShapeBounding, x, y, xrects,
417 nr_rects, ShapeSet, 0);
422 XSync(hdl->disp, FALSE);
423 XUnlockDisplay(hdl->disp);
431 struct X11Handle* hdl;
435 hdl = (
struct X11Handle*)decoder->platform;
438 if ((hdl->subwin) && (!hdl->subwinMapped))
440 XLockDisplay(hdl->disp);
441 XMapWindow(hdl->disp, hdl->subwin);
442 hdl->subwinMapped = TRUE;
443 XSync(hdl->disp, FALSE);
444 XUnlockDisplay(hdl->disp);
452 struct X11Handle* hdl;
456 hdl = (
struct X11Handle*)decoder->platform;
459 if ((hdl->subwin) && (hdl->subwinMapped))
461 XLockDisplay(hdl->disp);
462 XUnmapWindow(hdl->disp, hdl->subwin);
463 hdl->subwinMapped = FALSE;
464 XSync(hdl->disp, FALSE);
465 XUnlockDisplay(hdl->disp);
473 struct X11Handle* hdl;
478 decoder->ready = FALSE;
480 if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
483 if (!decoder->platform)
486 hdl = (
struct X11Handle*)decoder->platform;
490 XLockDisplay(hdl->disp);
491 XDestroyWindow(hdl->disp, hdl->subwin);
492 XSync(hdl->disp, FALSE);
493 XUnlockDisplay(hdl->disp);
496 hdl->overlay =
nullptr;
498 hdl->subwinMapped = FALSE;
501 hdl->subwinWidth = -1;
502 hdl->subwinHeight = -1;