From c2364710ce1db538021b8784bb6660140f41b6b6 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 3 Oct 2017 05:41:28 +0000 Subject: [PATCH] #1317 support for loading NvFBC license keys git-svn-id: https://xpra.org/svn/Xpra/trunk@17078 3bb7dfac-3a0b-4e04-842a-767bc560f471 --- rpmbuild/xpra.spec | 2 +- src/etc/xpra/nvfbc.keys | 6 ++++ src/setup.py | 7 +++- src/xpra/codecs/nv_util.py | 9 ++++++ src/xpra/codecs/nvfbc/fbc_capture_linux.pyx | 29 ++++++++++++++--- src/xpra/codecs/nvfbc/fbc_capture_win.pyx | 36 +++++++++++++++------ 6 files changed, 74 insertions(+), 15 deletions(-) create mode 100644 src/etc/xpra/nvfbc.keys diff --git a/rpmbuild/xpra.spec b/rpmbuild/xpra.spec index fcd67fc0ab..962fbd57bd 100644 --- a/rpmbuild/xpra.spec +++ b/rpmbuild/xpra.spec @@ -594,7 +594,7 @@ rm -rf $RPM_BUILD_ROOT #we only enable CUDA / NVENC with 64-bit builds: %ifarch x86_64 %config(noreplace) %{_sysconfdir}/xpra/cuda.conf -%config(noreplace) %{_sysconfdir}/xpra/nvenc.keys +%config(noreplace) %{_sysconfdir}/xpra/*.keys %endif %config %{_sysconfdir}/xpra/conf.d/50_server_network.conf %config %{_sysconfdir}/xpra/conf.d/55_server_x11.conf diff --git a/src/etc/xpra/nvfbc.keys b/src/etc/xpra/nvfbc.keys new file mode 100644 index 0000000000..c9aec31bfa --- /dev/null +++ b/src/etc/xpra/nvfbc.keys @@ -0,0 +1,6 @@ +# List of license keys to use with the NVFBC +# +# One key per line, ie: +# 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 +# or just: +# 0102030405060708090A0B0C0D0E0F10 diff --git a/src/setup.py b/src/setup.py index 5952cb3a3b..19453cf2ea 100755 --- a/src/setup.py +++ b/src/setup.py @@ -1359,6 +1359,7 @@ def add_service_exe(script, icon, base_name): build_xpra_conf(".") add_data_files('etc/xpra', glob.glob("etc/xpra/*conf")) add_data_files('etc/xpra', glob.glob("etc/xpra/nvenc*.keys")) + add_data_files('etc/xpra', glob.glob("etc/xpra/nvfbc*.keys")) add_data_files('etc/xpra/conf.d', glob.glob("etc/xpra/conf.d/*conf")) #build minified html5 client in temporary build dir: if "clean" not in sys.argv and html5_ENABLED: @@ -1490,8 +1491,12 @@ def copytodir(src, dst_dir, dst_name=None, chmod=0o644): etc_xpra_files = ["xorg.conf"] if uinput_ENABLED: etc_xpra_files.append("xorg-uinput.conf") + if nvenc_ENABLED or nvfbc_ENABLED: + etc_xpra_files.append("cuda.conf") if nvenc_ENABLED: - etc_xpra_files += ["cuda.conf", "nvenc.keys"] + etc_xpra_files.append("nvenc.keys") + if nvfbc_ENABLED: + etc_xpra_files.append("nvfbc.keys") for x in etc_xpra_files: copytodir("etc/xpra/%s" % x, "/etc/xpra") copytodir("etc/X11/xorg.conf.d/90-xpra-virtual.conf", "/etc/X11/xorg.conf.d/") diff --git a/src/xpra/codecs/nv_util.py b/src/xpra/codecs/nv_util.py index bab6574f83..0257e67aa3 100644 --- a/src/xpra/codecs/nv_util.py +++ b/src/xpra/codecs/nv_util.py @@ -205,6 +205,15 @@ def validate_driver_yuv444lossless(): return True +def parse_nvfbc_hex_key(s): + #ie: 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 + #ie: 0102030405060708090A0B0C0D0E0F10 + #start by removing spaces and 0x: + hexstr = s.replace("0x", "").replace(",", "").replace(" ", "") + import binascii + return binascii.unhexlify(hexstr) + + license_keys = {} def get_license_keys(version=0, basefilename="nvenc"): global license_keys diff --git a/src/xpra/codecs/nvfbc/fbc_capture_linux.pyx b/src/xpra/codecs/nvfbc/fbc_capture_linux.pyx index c192741a46..8392cfae49 100644 --- a/src/xpra/codecs/nvfbc/fbc_capture_linux.pyx +++ b/src/xpra/codecs/nvfbc/fbc_capture_linux.pyx @@ -11,9 +11,10 @@ import os import sys from xpra.os_util import WIN32 +from xpra.util import csv from xpra.codecs.image_wrapper import ImageWrapper from xpra.codecs.codec_constants import TransientCodecException, CodecStateException -from xpra.codecs.nv_util import get_nvidia_module_version, get_cards +from xpra.codecs.nv_util import get_nvidia_module_version, get_cards, get_license_keys, parse_nvfbc_hex_key from xpra.log import Logger log = Logger("encoder", "nvfbc") @@ -22,6 +23,8 @@ try: import numpy from pycuda import driver from xpra.codecs.cuda_common.cuda_context import CUDA_ERRORS_INFO, select_device, device_info +except ImportError: + raise except: log.error("Error: NvFBC requires CUDA", exc_info=True) CUDA_ERRORS_INFO = {} @@ -32,6 +35,7 @@ from libc.stdint cimport uintptr_t, uint8_t, int64_t, uint32_t, uint64_t from xpra.monotonic_time cimport monotonic_time DEFAULT_PIXEL_FORMAT = os.environ.get("XPRA_NVFBC_DEFAULT_PIXEL_FORMAT", "RGB") +CLIENT_KEYS_STRS = get_license_keys(basefilename="nvfbc") ctypedef unsigned long DWORD @@ -384,9 +388,25 @@ cdef get_frame_grab_info(NVFBC_FRAME_GRAB_INFO *grab_info): cdef NVFBC_SESSION_HANDLE create_context() except 0xffffffff: cdef NVFBC_SESSION_HANDLE context = 0 cdef NVFBC_CREATE_HANDLE_PARAMS params - memset(¶ms, 0, sizeof(NVFBC_CREATE_HANDLE_PARAMS)) - params.dwVersion = NVFBC_CREATE_HANDLE_PARAMS_VER - cdef NVFBCSTATUS ret = function_list.nvFBCCreateHandle(&context, ¶ms) + cdef NVFBCSTATUS ret = 0 + cdef char* ckey + keys = CLIENT_KEYS_STRS or [None] + log("create_context() will try with keys: %s", csv(keys)) + assert len(keys)>0 + for key in keys: + memset(¶ms, 0, sizeof(NVFBC_CREATE_HANDLE_PARAMS)) + params.dwVersion = NVFBC_CREATE_HANDLE_PARAMS_VER + if key: + binkey = parse_nvfbc_hex_key(key) + ckey = binkey + params.privateData = ckey + params.privateDataSize = len(ckey) + log("create_context() key data=%#x, size=%i", ckey, len(ckey)) + ret = function_list.nvFBCCreateHandle(&context, ¶ms) + log("create_context() NvFBCCreateHandle()=%i for key=%s", ret, key) + if ret==0: + #success! + break raiseNvFBC(context, ret, "NvFBCCreateHandle") log("NvFBCCreateHandle: handle=%#x", context) return context @@ -556,6 +576,7 @@ cdef class NvFBC_CUDACapture: def init_context(self, int width=-1, int height=-1, pixel_format="XRGB"): log("init_context(%i, %i, %s)", width, height, pixel_format) + assert select_device, "CUDA is missing" if pixel_format not in PIXEL_FORMAT_CONST: raise Exception("unsupported pixel format '%s'" % pixel_format) cdef NVFBC_BUFFER_FORMAT buffer_format = PIXEL_FORMAT_CONST[pixel_format] diff --git a/src/xpra/codecs/nvfbc/fbc_capture_win.pyx b/src/xpra/codecs/nvfbc/fbc_capture_win.pyx index 82ab9fd392..7308145d4b 100644 --- a/src/xpra/codecs/nvfbc/fbc_capture_win.pyx +++ b/src/xpra/codecs/nvfbc/fbc_capture_win.pyx @@ -11,9 +11,10 @@ import os import sys from xpra.os_util import WIN32 +from xpra.util import csv from xpra.codecs.image_wrapper import ImageWrapper from xpra.codecs.codec_constants import TransientCodecException, CodecStateException -from xpra.codecs.nv_util import get_nvidia_module_version, get_cards +from xpra.codecs.nv_util import get_nvidia_module_version, get_cards, get_license_keys, parse_nvfbc_hex_key from xpra.log import Logger log = Logger("encoder", "nvfbc") @@ -35,6 +36,7 @@ from libc.stdint cimport uintptr_t, uint8_t, int64_t from xpra.monotonic_time cimport monotonic_time DEFAULT_PIXEL_FORMAT = os.environ.get("XPRA_NVFBC_DEFAULT_PIXEL_FORMAT", "RGB") +CLIENT_KEYS_STRS = get_license_keys(basefilename="nvfbc") ctypedef unsigned long DWORD @@ -454,14 +456,30 @@ def create_context(int width=-1, int height=-1, interface_type=NVFBC_TO_SYS): log("create_context(%i, %i)", width, height) check_status() cdef NvFBCCreateParams create - memset(&create, 0, sizeof(NvFBCCreateParams)) - create.dwVersion = NVFBC_CREATE_PARAMS_VER - create.dwInterfaceType = interface_type - create.dwMaxDisplayWidth = width - create.dwMaxDisplayHeight = height - #create.pDevice = 0 - create.dwInterfaceVersion = NVFBC_DLL_VERSION - cdef NVFBCRESULT res = NvFBC.NvFBC_CreateEx(cvp( &create)) + cdef NVFBCRESULT res = 0 + cdef char* ckey + keys = CLIENT_KEYS_STRS or [None] + log("create_context() will try with keys: %s", csv(keys)) + assert len(keys)>0 + for key in keys: + memset(&create, 0, sizeof(NvFBCCreateParams)) + create.dwVersion = NVFBC_CREATE_PARAMS_VER + create.dwInterfaceType = interface_type + create.dwMaxDisplayWidth = width + create.dwMaxDisplayHeight = height + #create.pDevice = 0 + create.dwInterfaceVersion = NVFBC_DLL_VERSION + if key: + binkey = parse_nvfbc_hex_key(key) + ckey = binkey + params.pPrivateData = ckey + params.dwPrivateDataSize = len(ckey) + log("create_context() key data=%#x, size=%i", ckey, len(ckey)) + res = NvFBC.NvFBC_CreateEx(cvp( &create)) + log("create_context() NvFBC_CreateEx()=%i for key=%s", ret, key) + if ret==0: + #success! + break log("NvFBC_CreateEx(%#x)=%i", &create, res) raiseNvFBC(res, "NvFBC_CreateEx") info = {