- 按方案 3.2/3.3 节以 libfreerdp3 API 内嵌,不拉起外部进程 - gdi_init 移到 PostConnect(提前调用会段错误) - 去掉 ContextSize 扩展 rdpContext,改用 freerdp* 注册表 + gfx->custom - NLA 认证传空字符串而非 nullptr,修复 SEC_E_NO_CREDENTIALS - 补充 FreeRDP3 内嵌实现笔记文档
3.4 KiB
FreeRDP 3 内嵌客户端实现笔记(Ubuntu 24.04 / freerdp3-dev 3.32.1)
对应《VDI 云桌面软件开发方案》3.2 / 3.3 节:以 libfreerdp3 API 内嵌(非拉起外部进程)。 记录时间:2026-10-23,实测于 RK3528 盒子(Armbian / Ubuntu Noble / aarch64)
1. API 结构(与 FreeRDP 2.x 差异很大)
| 用途 | FreeRDP 3 写法 |
|---|---|
| 创建实例 | freerdp* instance = freerdp_new(); |
| 建立上下文 | freerdp_context_new_ex(instance, settings) |
| 上下文 | instance->context(rdpContext*,公开结构体) |
| 事件回调 | instance->PostConnect / instance->PostDisconnect / instance->AuthenticateEx |
| 更新回调 | instance->context->update->BitmapUpdate / ->EndPaint |
| GDI | gdi_init(instance, PIXEL_FORMAT_BGRX32) |
| 取帧 | context->gdi->primary_buffer + context->gdi->stride |
设置项键名(与 2.x 不同):
FreeRDP_ServerHostname / FreeRDP_Username / FreeRDP_Password / FreeRDP_Domain /
FreeRDP_DesktopWidth / FreeRDP_DesktopHeight / FreeRDP_ColorDepth / FreeRDP_Fullscreen /
FreeRDP_IgnoreCertificate / FreeRDP_GfxProgressive / FreeRDP_GfxH264 / FreeRDP_GfxAVC444 …
2. 三个必须踩过才知道的坑
坑一:gdi_init 必须在 PostConnect 里调用
在 freerdp_context_new_ex() 之后立刻调用 gdi_init() 会 SIGSEGV
(gdi_init_ex 段错误)。官方 x11 客户端(client/X11/xf_client.c 的 xf_post_connect)
把 gdi_init 放在 PostConnect 回调内,因为 GDI 依赖连接协商后的桌面尺寸与颜色格式。
坑二:不能用 instance->ContextSize 扩展 rdpContext
常见做法是把自定义指针塞进扩展的 rdpContext,但 gdi_init_ex() 会按 ContextSize
重新分配 context 缓冲区,扩展字段随即失效 → 段错误。
改用静态注册表按 freerdp* 记录会话对象;GFX 通道回调则用官方的
RdpgfxClientContext.custom 字段。
坑三:NLA 认证必须传空字符串而非 nullptr
Windows 端启用 NLA(CredSSP)时,认证回调里把密码置为 nullptr 会导致
SEC_E_NO_CREDENTIALS [0x8009030e]。必须传 strdup("")。
认证回调签名:
BOOL (*pAuthenticateEx)(freerdp*, char** username, char** password, char** domain, rdp_auth_reason)
3. /gfx 语法(命令行与设置项的对应)
FreeRDP 3.32.1 的 /gfx 不接受单个管道名,必须是 | 分隔的能力组合:
/gfx:progressive|RFX|AVC420|AVC444 ← 可解析
/gfx:AVC420 ← parsing failed [-1000]
/gfx:AVC444 ← parsing failed [-1000]
API 侧对应 FreeRDP_GfxProgressive / FreeRDP_GfxH264 / FreeRDP_GfxAVC444 等布尔项。
4. 像素格式
PIXEL_FORMAT_BGRX32 的内存布局是 B,G,R,X 四字节/像素。
QImage 没有对应格式,输出前需手动做 BGR→RGB 转换。
注意 PIXEL_FORMAT_* 是计算宏 FREERDP_PIXEL_FORMAT(...),不能硬编码数值。
5. 后续演进(对应 freerdp-rk 分支)
当前实现是 CPU 侧 GDI 缓冲 → Qt 绘制。开发方案 3.3 节要求改为:
FreeRDP3 解复用(gfx 通道) → GStreamer h264parse → mppvideodec(VPU硬解, zero-copy DMABuf)
→ waylandsink(DRM plane)
盒子已具备 /dev/mpp_service(VPU)与 /dev/rga,但缺 mppvideodec GStreamer 插件
(Ubuntu 官方源没有,需 Rockchip BSP / Armbian 额外源或自研)。