Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/neutrinolabs/NeutrinoRDP.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjsorg71 <jay.sorg@gmail.com>2022-06-05 08:28:17 +0300
committerGitHub <noreply@github.com>2022-06-05 08:28:17 +0300
commit836b738ae3739c275ed9b3eedb7d581067911b70 (patch)
treead79597822f2d41160ff2cf0b5ed710bddf4360d
parentf7832d6ce8f12f4b999a2a4edc6cc72373bc5168 (diff)
parent9e978e923649afeff91bbb98cda95cd52f7c3b21 (diff)
Merge pull request #27 from jsorg71/yami
add yami_inf decoder option
-rw-r--r--client/X11/CMakeLists.txt19
-rw-r--r--client/X11/xf_gdi.c211
-rw-r--r--client/X11/xfreerdp.c106
-rw-r--r--client/X11/xfreerdp.h9
-rw-r--r--cmake/ConfigOptions.cmake1
5 files changed, 332 insertions, 14 deletions
diff --git a/client/X11/CMakeLists.txt b/client/X11/CMakeLists.txt
index 25eb418..f977165 100644
--- a/client/X11/CMakeLists.txt
+++ b/client/X11/CMakeLists.txt
@@ -92,6 +92,25 @@ if(WITH_XRANDR)
target_link_libraries(xfreerdp ${XRANDR_LIBRARIES})
endif()
+# example cmake . -DWITH_YAMIINF=ON
+# example YAMIINF_DRM_FILE=/dev/dri/renderD128 YAMIINF_PATH=/opt/yami cmake . -DWITH_YAMIINF=ON
+if(WITH_YAMIINF)
+ add_definitions(-DWITH_YAMIINF)
+if(DEFINED ENV{YAMIINF_PATH})
+ add_definitions(-DYAMIINF_INC_FILE="$ENV{YAMIINF_PATH}/include/yami_inf.h")
+ add_definitions(-DYAMIINF_LIB_FILE="$ENV{YAMIINF_PATH}/lib/libyami_inf.so")
+else()
+ add_definitions(-DYAMIINF_INC_FILE="yami_inf.h")
+ add_definitions(-DYAMIINF_LIB_FILE="libyami_inf.so")
+endif()
+if(DEFINED ENV{YAMIINF_DRM_FILE})
+ add_definitions(-DYAMIINF_DRI_FILE="$ENV{YAMIINF_DRM_FILE}")
+else()
+ add_definitions(-DYAMIINF_DRI_FILE="/dev/dri/renderD128")
+endif()
+ target_link_libraries(xfreerdp -lxcb -lX11-xcb -lxcb-dri3)
+endif()
+
include_directories(${CMAKE_SOURCE_DIR}/resources)
target_link_libraries(xfreerdp freerdp-core)
diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c
index 90f2c61..3ec4f3a 100644
--- a/client/X11/xf_gdi.c
+++ b/client/X11/xf_gdi.c
@@ -30,12 +30,20 @@
#include <freerdp/codec/nsc.h>
#include <freerdp/constants.h>
#include <freerdp/utils/memory.h>
+#include <freerdp/utils/hexdump.h>
#include <freerdp/codec/color.h>
#include <freerdp/codec/bitmap.h>
#include <freerdp/codec/jpeg.h>
#include "xf_gdi.h"
+#ifdef WITH_YAMIINF
+#include <unistd.h> /* close */
+#include <xcb/dri3.h>
+#include YAMIINF_INC_FILE
+extern struct yami_funcs g_yami_funcs; /* in xfreerdp.c */
+#endif
+
#define LLOG_LEVEL 1
#define LLOGLN(_level, _args) \
do { if (_level < LLOG_LEVEL) { printf _args ; printf("\n"); } } while (0)
@@ -654,6 +662,195 @@ void xf_gdi_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surf
}
}
+#ifdef WITH_YAMIINF
+static int xf_gdi_surface_h264(xfInfo* xfi, SURFACE_BITS_COMMAND* surface_bits_command)
+{
+ STREAM* s;
+ int error;
+ int flags;
+ int session_id;
+ int src_width;
+ int src_height;
+ int dst_width;
+ int dst_height;
+ int num_rects;
+ int h264_bytes;
+ uint8* rects_p;
+ void* decoder;
+ xcb_pixmap_t pixmap = None;
+ xcb_void_cookie_t cookie;
+ xcb_generic_error_t* xcb_error;
+
+ if ((surface_bits_command->bitmapDataLength < 1) || (surface_bits_command->bitmapData == NULL))
+ {
+ return 1;
+ }
+ s = stream_new(0);
+ stream_attach(s, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength);
+ LHEXDUMP(10, (surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength));
+ if (stream_get_left(s) < 18)
+ {
+ LLOGLN(0, ("xf_gdi_surface_h264: error bytes"));
+ stream_detach(s);
+ stream_free(s);
+ return 1;
+ }
+ stream_read_uint32(s, flags);
+ stream_read_uint32(s, session_id);
+ LLOGLN(10, ("xf_gdi_surface_h264: flags 0x%8.8x session_id %d", flags, session_id));
+ stream_read_uint16(s, src_width);
+ stream_read_uint16(s, src_height);
+ stream_read_uint16(s, dst_width);
+ stream_read_uint16(s, dst_height);
+ stream_read_uint16(s, num_rects);
+ if ((num_rects < 0) || (stream_get_left(s) < num_rects * 8 + 4))
+ {
+ LLOGLN(0, ("xf_gdi_surface_h264: error bytes"));
+ stream_detach(s);
+ stream_free(s);
+ return 1;
+ }
+ stream_get_mark(s, rects_p); /* save for later */
+ stream_seek(s, num_rects * 8);
+ stream_read_uint32(s, h264_bytes);
+ /* h264_bytes can be zero */
+ if ((h264_bytes < 0) || (stream_get_left(s) < h264_bytes))
+ {
+ LLOGLN(0, ("xf_gdi_surface_h264: error bytes"));
+ stream_detach(s);
+ stream_free(s);
+ return 1;
+ }
+ session_id &= 0xF;
+ if (flags & 2) /* delete */
+ {
+ if (xfi->decoders[session_id] != NULL)
+ {
+ g_yami_funcs.yami_decoder_delete(xfi->decoders[session_id]);
+ xfi->decoders[session_id] = 0;
+ }
+ }
+ if ((h264_bytes > 0) && (num_rects > 0))
+ {
+ decoder = xfi->decoders[session_id];
+ if (decoder == NULL)
+ {
+ error = g_yami_funcs.yami_decoder_create(&decoder, src_width, src_height,
+ YI_TYPE_H264, YI_H264_DEC_FLAG_LOWLATENCY);
+ LLOGLN(0, ("xf_gdi_surface_h264: decoder_create rv %d width %d height %d", error,
+ src_width, src_height));
+ if (error == YI_SUCCESS)
+ {
+ xfi->decoders[session_id] = decoder;
+ }
+ else
+ {
+ decoder = NULL;
+ }
+ }
+ if (decoder != NULL)
+ {
+ error = g_yami_funcs.yami_decoder_decode(decoder, s->p, h264_bytes);
+ LLOGLN(10, ("xf_gdi_surface_h264: yami_decoder_decode rv %d", error));
+ if (error == YI_SUCCESS)
+ {
+ int fd;
+ int fd_width;
+ int fd_height;
+ int fd_stride;
+ int fd_size;
+ int fd_bpp;
+ YI_INT64 fd_time;
+ error = g_yami_funcs.yami_decoder_get_fd_dst(decoder, &fd, &fd_width, &fd_height,
+ &fd_stride, &fd_size, &fd_bpp, &fd_time);
+ LLOGLN(10, ("xf_gdi_surface_h264: yami_decoder_get_fd_dst rv %d", error));
+ if (error == YI_SUCCESS)
+ {
+ LLOGLN(10, ("xf_gdi_surface_h264: yami_decoder_get_fd_dst fd %d "
+ "fd_width %d fd_height %d fd_stride %d fd_size %d fd_bpp %d "
+ "fd_time %lld", fd, fd_width, fd_height, fd_stride, fd_size,
+ fd_bpp, fd_time));
+ LLOGLN(10, ("xf_gdi_surface_h264: fd_bpp %d xfi->depth %d xfi->bpp %d",
+ fd_bpp, xfi->depth, xfi->bpp));
+ pixmap = xcb_generate_id(xfi->xcb);
+ cookie = xcb_dri3_pixmap_from_buffer(xfi->xcb, pixmap, xfi->drawable,
+ fd_size, fd_width, fd_height, fd_stride, xfi->depth, xfi->bpp, fd);
+ xcb_error = xcb_request_check(xfi->xcb, cookie);
+ free(xcb_error);
+ close(fd);
+ }
+ else
+ {
+ LLOGLN(0, ("xf_gdi_surface_h264: yami_decoder_get_fd_dst failed %d", error));
+ }
+ }
+ else
+ {
+ LLOGLN(0, ("xf_gdi_surface_h264: yami_decoder_decode failed %d", error));
+ }
+ }
+ else
+ {
+ LLOGLN(0, ("xf_gdi_surface_h264: error getting decoder"));
+ }
+ }
+ if (pixmap != None)
+ {
+ if ((src_width == dst_width) && (src_height == dst_height))
+ {
+ int x;
+ int y;
+ int cx;
+ int cy;
+ int lx;
+ int ly;
+ int index;
+ Drawable dst = xfi->skip_bs ? xfi->drawable : xfi->primary;
+ /* size of rects_p checked earlier */
+ stream_attach(s, rects_p, num_rects * 8);
+ for (index = 0; index < num_rects; index++)
+ {
+ stream_read_uint16(s, x);
+ stream_read_uint16(s, y);
+ stream_read_uint16(s, cx);
+ stream_read_uint16(s, cy);
+ lx = x + surface_bits_command->destLeft;
+ ly = y + surface_bits_command->destTop;
+ if (lx + cx > surface_bits_command->destRight)
+ {
+ cx = surface_bits_command->destRight - lx;
+ }
+ if (ly + cy > surface_bits_command->destBottom)
+ {
+ cy = surface_bits_command->destBottom - ly;
+ }
+ if ((cx > 0) && (cy > 0))
+ {
+ xcb_copy_area(xfi->xcb, pixmap, dst, xfi->xcb_gc, x, y, lx, ly, cx, cy);
+ if (!xfi->remote_app && !xfi->skip_bs)
+ {
+ xcb_copy_area(xfi->xcb, xfi->primary, xfi->drawable, xfi->xcb_gc, lx, ly, lx, ly, cx, cy);
+ }
+ }
+ }
+ }
+ else
+ {
+ LLOGLN(0, ("xf_gdi_surface_h264: xf_gdi_surface_bits: unsupported stretch"));
+ }
+ xcb_free_pixmap(xfi->xcb, pixmap);
+ }
+ stream_detach(s);
+ stream_free(s);
+ return 0;
+}
+#else
+static int xf_gdi_surface_h264(xfInfo* xfi, SURFACE_BITS_COMMAND* surface_bits_command)
+{
+ return 0;
+}
+#endif
+
void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command)
{
int i, tx, ty;
@@ -665,19 +862,7 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
if (surface_bits_command->codecID == CODEC_ID_H264)
{
- STREAM* s;
- int num_rects;
- int h264_bytes;
-
- s = stream_new(0);
- stream_attach(s, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength);
- stream_read_uint16(s, num_rects);
- stream_seek(s, num_rects * 8);
- stream_read_uint32(s, h264_bytes);
- stream_attach(s, 0, 0);
- stream_free(s);
- printf("h264 bytes %d num_rects %d h264_bytes %d\n",
- surface_bits_command->bitmapDataLength, num_rects, h264_bytes);
+ xf_gdi_surface_h264(xfi, surface_bits_command);
}
else if (surface_bits_command->codecID == CODEC_ID_JPEG)
{
diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c
index 8cb3805..ef03c4e 100644
--- a/client/X11/xfreerdp.c
+++ b/client/X11/xfreerdp.c
@@ -66,6 +66,20 @@
#include "xfreerdp.h"
+#ifdef WITH_YAMIINF
+#include <dlfcn.h> /* dlopen dlsym */
+#include <fcntl.h> /* open */
+#include YAMIINF_INC_FILE
+static void* g_yami_lib = NULL;
+static yami_get_funcs_proc g_get_funcs_func = NULL;
+static int g_drm_fd = -1;
+struct yami_funcs g_yami_funcs;
+#endif
+
+#define LLOG_LEVEL 1
+#define LLOGLN(_level, _args) \
+ do { if (_level < LLOG_LEVEL) { printf _args ; printf("\n"); } } while (0)
+
static freerdp_sem g_sem;
static int g_thread_count = 0;
static uint8 g_disconnect_reason = 0;
@@ -693,6 +707,12 @@ tbool xf_post_connect(freerdp* instance)
xf_create_window(xfi);
+#ifdef WITH_YAMIINF
+ xfi->xcb = XGetXCBConnection(xfi->display);
+ xfi->xcb_gc = xcb_generate_id(xfi->xcb);
+ xcb_create_gc(xfi->xcb, xfi->xcb_gc, xfi->drawable, 0, NULL);
+#endif
+
memset(&gcv, 0, sizeof(gcv));
xfi->modifier_map = XGetModifierMapping(xfi->display);
@@ -1142,13 +1162,97 @@ int main(int argc, char* argv[])
data = (struct thread_data*) xzalloc(sizeof(struct thread_data));
data->instance = instance;
+#ifdef WITH_YAMIINF
+ memset(&g_yami_funcs, 0, sizeof(g_yami_funcs));
+ g_drm_fd = open(YAMIINF_DRI_FILE, O_RDWR);
+ LLOGLN(0, ("main: open %s O_RDWR g_drm_fd is %d", YAMIINF_DRI_FILE, g_drm_fd));
+ if ((g_yami_lib == NULL) && (g_drm_fd != -1))
+ {
+ int failed = 1;
+ LLOGLN(0, ("main: loading %s", YAMIINF_LIB_FILE));
+ g_yami_lib = dlopen(YAMIINF_LIB_FILE, RTLD_LAZY);
+ if (g_yami_lib != NULL)
+ {
+ g_get_funcs_func = (yami_get_funcs_proc)dlsym(g_yami_lib, "yami_get_funcs");
+ if (g_get_funcs_func != NULL)
+ {
+ int error = g_get_funcs_func(&g_yami_funcs, YI_VERSION_INT(YI_MAJOR, YI_MINOR));
+ LLOGLN(0, ("main: g_get_funcs_func rv %d", error));
+ if (error == YI_SUCCESS)
+ {
+ int version;
+ error = g_yami_funcs.yami_get_version(&version);
+ LLOGLN(0, ("main: yami_get_version rv %d", error));
+ if (error == YI_SUCCESS)
+ {
+ LLOGLN(0, ("main: yami_inf version 0x%8.8x", version));
+ error = g_yami_funcs.yami_init(YI_TYPE_DRM, (void*)(size_t)g_drm_fd);
+ LLOGLN(0, ("main: yami_init rv %d", error));
+ if (error == YI_SUCCESS)
+ {
+ failed = 0;
+ }
+ else
+ {
+ LLOGLN(0, ("main: yami_init failed"));
+ }
+ }
+ else
+ {
+ LLOGLN(0, ("main: g_get_funcs_func failed"));
+ }
+ }
+ else
+ {
+ LLOGLN(0, ("main: yami_get_version failed"));
+ }
+ }
+ else
+ {
+ LLOGLN(0, ("main: dlsym lyami_get_funcs failed"));
+ }
+ }
+ else
+ {
+ LLOGLN(0, ("main: load libyami_inf.so failed"));
+ }
+ if (failed)
+ {
+ if (g_yami_lib != NULL)
+ {
+ dlclose(g_yami_lib);
+ g_yami_lib = NULL;
+ }
+ g_get_funcs_func = NULL;
+ memset(&g_yami_funcs, 0, sizeof(g_yami_funcs));
+ close(g_drm_fd);
+ g_drm_fd = -1;
+ }
+ }
+#endif
+
g_thread_count++;
pthread_create(&thread, 0, thread_func, data);
while (g_thread_count > 0)
{
- freerdp_sem_wait(g_sem);
+ freerdp_sem_wait(g_sem);
+ }
+
+#ifdef WITH_YAMIINF
+ if (g_yami_lib != NULL)
+ {
+ dlclose(g_yami_lib);
+ g_yami_lib = NULL;
}
+ g_get_funcs_func = NULL;
+ memset(&g_yami_funcs, 0, sizeof(g_yami_funcs));
+ if (g_drm_fd != -1)
+ {
+ close(g_drm_fd);
+ g_drm_fd = -1;
+ }
+#endif
freerdp_channels_global_uninit();
diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h
index 9b897b9..fd16b88 100644
--- a/client/X11/xfreerdp.h
+++ b/client/X11/xfreerdp.h
@@ -33,6 +33,10 @@ typedef struct xf_info xfInfo;
#include "xf_window.h"
#include "xf_monitor.h"
+#ifdef WITH_YAMIINF
+#include <X11/Xlib-xcb.h>
+#endif
+
/* 1 is grab keyboard, 2 is grab key */
#define XF_GRAB_MODE 2
@@ -186,6 +190,11 @@ struct xf_info
int suppress_output;
int primary_adjust_x;
int primary_adjust_y;
+#ifdef WITH_YAMIINF
+ void* decoders[16];
+ xcb_connection_t* xcb;
+ int xcb_gc;
+#endif
};
void xf_toggle_fullscreen(xfInfo* xfi);
diff --git a/cmake/ConfigOptions.cmake b/cmake/ConfigOptions.cmake
index 16e7ed9..3eeb729 100644
--- a/cmake/ConfigOptions.cmake
+++ b/cmake/ConfigOptions.cmake
@@ -33,3 +33,4 @@ option(WITH_TCUTILS "Use Thinclient utilities." ON)
option(WITH_XINERAMA "Use xinerama extension" OFF)
option(WITH_XRANDR "Use xrandr extension" ON)
option(WITH_FFMPEG "Use ffmpeg library" OFF)
+option(WITH_YAMIINF "Use yami_inf for h264" OFF)