Skip to content

feat(encoder): enable VAAPI hardware encode for ZY NL60R - #531

Open
Resurgamz wants to merge 1 commit into
linuxdeepin:release/eaglefrom
Resurgamz:fix/vaapi-x11
Open

Resurgamz wants to merge 1 commit into
linuxdeepin:release/eaglefrom
Resurgamz:fix/vaapi-x11

Conversation

@Resurgamz

@Resurgamz Resurgamz commented Oct 27, 2026 •

Copy link
Copy Markdown

背景

原方案(本 PR 之前)是为龙芯 3B6000M 平台修复 VAAPI 硬编在 X11 下不可用的问题,属于跨平台改动。现将其改造为仅卓怡 NL60R 生效的定制方案,其他机型行为完全不变。

方案

引入 DConfig 开关 org.deepin.camera.encode / hwEncodeStatus(bool,默认 false):

  • camera 启动时读取该键,仅当为 true 时才在录制时尝试 VAAPI 硬编,并开启 XInitThreads();
  • 其余机型保持原有软件编码路径(不再尝试 VAAPI);
  • 卓怡 NL60R 通过 os-config 下发 override 将其置为 true,因此只对该机型生效。

改动

  • src/assets/org.deepin.camera.encode.json:新增 hwEncodeStatus(默认 false)。
  • src/main.cpp:读取 hwEncodeStatus 并传给 libcam;仅开启时调用 XInitThreads()。
  • libcam/libcam/camview.c / camview.h:新增 set_hw_encode_status() / get_hw_encode_status()。
  • libcam/libcam_encoder/encoder.c:encoder_init() 按开关决定是否走 encoder_video_init_vaapi();保留 X11 后端回退、跳过重复能力探测、打开编码器失败回退软编等修复。

影响

  • 仅当 hwEncodeStatus=true(卓怡 NL60R 的 override)时启用 VAAPI 硬编;
  • 未配置该键的机型与改动前完全一致(软件编码),无跨平台影响。

PMS: https://pms.uniontech.com/task-view-397321.html

Summary by Sourcery

Add a device-specific configuration path for safely enabling VAAPI hardware encoding while preserving existing software encoding behavior elsewhere.

New Features:

  • Enable opt-in VAAPI hardware video encoding for ZY NL60R through the hwEncodeStatus configuration switch.

Bug Fixes:

  • Improve VAAPI initialization reliability with X11 fallback and correctly fall back to software encoding when the hardware encoder cannot be opened.

Enhancements:

  • Keep software encoding as the default for all unconfigured devices and avoid unnecessary VAAPI capability probing for explicitly enabled hardware-encoding devices.

Build:

  • Add X11 as a required dependency for hardware encoding support.

Deployment:

  • Support enabling hardware encoding on ZY NL60R through an os-config DConfig override.

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Resurgamz

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@sourcery-ai

sourcery-ai Bot commented Oct 27, 2026

Copy link
Copy Markdown

Reviewer's Guide

The PR enables VAAPI encoding on LoongArch systems whose driver only supports X11 by letting FFmpeg determine hardware availability, trying the existing default backend before an X11 fallback, and initializing/linking Xlib for safe multithreaded access; failed hardware initialization still falls back to software encoding.

Sequence diagram for VAAPI device creation with X11 fallback

sequenceDiagram
    participant Encoder
    participant FFmpeg
    participant VAAPI
    participant X11
    participant SoftwareEncoder

    Encoder->>FFmpeg: av_hwdevice_ctx_create(VAAPI, default)
    alt Default backend succeeds
        FFmpeg->>VAAPI: Initialize default backend
        VAAPI-->>FFmpeg: Hardware device
        FFmpeg-->>Encoder: VAAPI device ready
    else Default backend fails
        Encoder->>FFmpeg: av_hwdevice_ctx_create(VAAPI, connection_type=x11)
        FFmpeg->>X11: Open X11 VAAPI backend
        X11-->>FFmpeg: Hardware device or failure
        alt X11 backend succeeds
            FFmpeg-->>Encoder: VAAPI device ready
        else Hardware initialization fails
            FFmpeg-->>Encoder: Error
            Encoder->>SoftwareEncoder: Fall back to software encoding
        end
    end
Loading

File-Level Changes

Change Details Files
Replace the unsafe custom VAAPI capability gate with FFmpeg-driven device initialization and fallback behavior.
  • Remove the encoder-time call to the custom VAAPI probe to avoid a LoongArch driver crash and duplicate detection.
  • Create a VAAPI device using FFmpeg’s default backend first, then retry with connection_type=x11 when initialization fails.
  • Preserve software-encoding fallback when both hardware-device creation attempts fail.
libcam/libcam_encoder/encoder.c
Make X11 VAAPI access and multithreaded Xlib usage available at build and runtime.
  • Open and close an X11 display around the standalone VAAPI probe and include the X11 VAAPI headers.
  • Initialize Xlib threading before application/UI initialization so encoder threads can use the X11 VAAPI backend.
  • Add the X11 package dependency to the build configuration.
libcam/libcam_encoder/encoder.c
src/main.cpp
src/CMakeLists.txt

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="libcam/libcam_encoder/encoder.c" line_range="2329-2335" />
<code_context>
-        return NULL;
-   }
+    /*
+     * 不再调用 check_vaapi_support() 做自定义探测:
+     * 该函数在 X11 显示上调用 vaQueryConfigProfiles(va_display, NULL, ...) 时,
+     * 本机龙芯 VA 驱动(ls2k3000_vpu.so)会因未处理 NULL 列表而段错误;
+     * 且该探测与下面的 av_hwdevice_ctx_create 重复。
+     * 这里直接由 FFmpeg(connection_type=x11) 做真正的可用性判断,
+     * 失败则走 HW_VAAPI_FAIL5 回退软编。
+     */

     //assertions
</code_context>
<issue_to_address>
**Missing VAAPI encoder aborts recording**

When VAAPI device creation succeeds but FFmpeg lacks `h264_vaapi`, `encoder_video_init_vaapi` frees `video_codec_data` twice on the missing-encoder path, so the allocator aborts before `encoder_init` can fall back to software encoding.

Free `video_codec_data` only once on the missing-encoder path.

Also at `libcam/libcam_encoder/encoder.c:2391`.
</issue_to_address>

### Comment 2
<location path="src/main.cpp" line_range="117" />
<code_context>
 {
+    // 编码子线程会调用 vaGetDisplay()(libva-x11 -> XOpenDisplay);
+    // 必须在任何 Xlib/Qt 使用之前开启 Xlib 线程安全,否则子线程里 XOpenDisplay 返回 NULL。
+    XInitThreads();
+
     // 将日志配置提前,以确保所有日志没有遗漏
</code_context>
<issue_to_address>
**Xlib remains unsafe after initialization failure**

When `XInitThreads()` returns zero, xlib thread support remains disabled, so concurrent Xlib calls from the encoder and GUI threads can race and fail or crash instead of safely using the X11 backend or falling back to software encoding.

Check the return value and avoid concurrent Xlib use or disable the X11 VAAPI attempt when thread initialization fails.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread libcam/libcam_encoder/encoder.c Outdated
Comment on lines +2329 to +2335
* 不再调用 check_vaapi_support() 做自定义探测:
* 该函数在 X11 显示上调用 vaQueryConfigProfiles(va_display, NULL, ...) 时,
* 本机龙芯 VA 驱动(ls2k3000_vpu.so)会因未处理 NULL 列表而段错误;
* 且该探测与下面的 av_hwdevice_ctx_create 重复。
* 这里直接由 FFmpeg(connection_type=x11) 做真正的可用性判断,
* 失败则走 HW_VAAPI_FAIL5 回退软编。
*/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High · Missing VAAPI encoder aborts recording

When VAAPI device creation succeeds but FFmpeg lacks h264_vaapi, encoder_video_init_vaapi frees video_codec_data twice on the missing-encoder path, so the allocator aborts before encoder_init can fall back to software encoding.

Free video_codec_data only once on the missing-encoder path.

Also at libcam/libcam_encoder/encoder.c:2391.

Prompt for AI agents
In `libcam/libcam_encoder/encoder.c` at lines 2329-2335:

**Missing VAAPI encoder aborts recording**

When VAAPI device creation succeeds but FFmpeg lacks `h264_vaapi`, `encoder_video_init_vaapi` frees `video_codec_data` twice on the missing-encoder path, so the allocator aborts before `encoder_init` can fall back to software encoding.

Free `video_codec_data` only once on the missing-encoder path.

Also at `libcam/libcam_encoder/encoder.c:2391`.

Comment thread src/main.cpp Outdated
{
// 编码子线程会调用 vaGetDisplay()(libva-x11 -> XOpenDisplay);
// 必须在任何 Xlib/Qt 使用之前开启 Xlib 线程安全,否则子线程里 XOpenDisplay 返回 NULL。
XInitThreads();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium · Xlib remains unsafe after initialization failure

When XInitThreads() returns zero, xlib thread support remains disabled, so concurrent Xlib calls from the encoder and GUI threads can race and fail or crash instead of safely using the X11 backend or falling back to software encoding.

Check the return value and avoid concurrent Xlib use or disable the X11 VAAPI attempt when thread initialization fails.

Prompt for AI agents
In `src/main.cpp` at line 117:

**Xlib remains unsafe after initialization failure**

When `XInitThreads()` returns zero, xlib thread support remains disabled, so concurrent Xlib calls from the encoder and GUI threads can race and fail or crash instead of safely using the X11 backend or falling back to software encoding.

Check the return value and avoid concurrent Xlib use or disable the X11 VAAPI attempt when thread initialization fails.

@Resurgamz
Resurgamz force-pushed the fix/vaapi-x11 branch 3 times, most recently from bbc64e1 to f4a0658 Compare October 29, 2026 05:20
@Resurgamz Resurgamz changed the title fix: enable VAAPI hardware encode over X11 on LoongArch feat(encoder): enable VAAPI hardware encode for ZY NL60R Oct 29, 2026
@Resurgamz
Resurgamz force-pushed the fix/vaapi-x11 branch 2 times, most recently from e492b5b to f4a0658 Compare October 29, 2026 07:06
Gate the VAAPI hardware encoder behind the hwEncodeStatus DConfig
key so the X11 backend fallback and thread-safe Xlib init apply
only to the ZY NL60R customization; other models stay software.

将 VAAPI 硬编改为由 hwEncodeStatus 配置门控,X11 后端回退与 Xlib
线程安全仅对卓怡 NL60R 定制生效,其他机型保持软件编码。

Log: 新增卓怡NL60R硬编定制,按配置启用VAAPI
PMS: TASK-397321
Influence: 仅卓怡NL60R开启硬编,其他机型软编行为不变。
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

总体评分: 90 分 (通过阈值: 70分)

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 本次提交为卓怡NL60R定制机型启用VAAPI硬件编码,代码结构清晰、注释完整、安全无漏洞。存在2处内存管理问题(main.cpp中DConfig对象未释放、encoder.c错误路径中private_options未释放),均为资源管理类问题,建议修复后合入。

🔍 详细分析

1. 语法逻辑 ❌

评价: 存在逻辑缺陷 ❌ 不通过

潜在问题:
✅ 未发现明显问题

建议: ['1. main.cpp中DConfig使用后应delete encodeCfg; 或合并到第170行已有的DConfig创建逻辑中避免重复创建', '2. encoder.c错误处理路径中,free(video_codec_data)之前添加getAvutil()->m_av_dict_free(&(video_codec_data->private_options))']


2. 代码质量 ✅

评价: 代码结构清晰,注释完整 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ['1. 使用后delete encodeCfg,或合并到已有的DConfig创建逻辑中', '2. 考虑复用已创建的DConfig对象,避免重复创建']


3. 代码性能 ✅

评价: 性能良好,资源使用合理 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: []


4. 代码安全 🔒

评价: 存在0个安全漏洞 ✅ 通过

🔐 发现 0 个安全漏洞

安全漏洞详情:
✅ 未发现安全漏洞

建议: []


💡 改进建议代码示例

// src/main.cpp - 修复DConfig内存泄漏 #ifdef DTKCORE_CLASS_DConfigFile {
    DConfig *encodeCfg = DConfig::create("org.deepin.camera", "org.deepin.camera.encode");
    if (encodeCfg && encodeCfg->isValid() && encodeCfg->keyList().contains("hwEncodeStatus")) {
        hwEncodeEnabled = encodeCfg->value("hwEncodeStatus").toBool();
    }
    if (encodeCfg) {
        delete encodeCfg;
    }
} #endif
// libcam/libcam_encoder/encoder.c - 修复private_options内存泄漏 if ((ret = getLoadLibsInstance()->m_avcodec_open2(video_codec_data->codec_context, video_codec_data->codec, &video_codec_data->private_options)) < 0) {
    fprintf(stderr, "ENCODER: could not open VAAPI video codec: %i - fallback to software\n", ret);
    getAvutil()->m_av_dict_free(&(video_codec_data->private_options));
    free(video_codec_data->codec_context);
    video_codec_data->codec_context = NULL;
    video_codec_data->codec = 0;
    free(video_codec_data);
    is_vaapi = HW_VAAPI_FAIL9;
    getAvutil()->m_av_buffer_unref(&hw_device_ctx);
    fprintf(stderr, "FAIL to encoder_video_init_vaapi:%d.\n", is_vaapi);
    return NULL;
}

本报告由 AI 代码审查工具自动生成

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants