# 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 节要求改为: ```text FreeRDP3 解复用(gfx 通道) → GStreamer h264parse → mppvideodec(VPU硬解, zero-copy DMABuf) → waylandsink(DRM plane) ``` 盒子已具备 `/dev/mpp_service`(VPU)与 `/dev/rga`,但缺 `mppvideodec` GStreamer 插件 (Ubuntu 官方源没有,需 Rockchip BSP / Armbian 额外源或自研)。