# 开发超分辨率插件

本节介绍如何开发新的超分辨率 (qtimlvsuperresolution) 插件。

注释

- 这些说明基于 `imsdk.lnx.2.0.0.r1-rel` 版本。
- 本指南适用于经验丰富的开发者，
他们可通过在现有插件的基础上构建 Qualcomm IM SDK 插件
来处理不受支持的用例（例如超分辨率）。
- 创建定制 GStreamer 插件是一项进阶任务，
只能由经验丰富的 GStreamer 开发者完成。
- 在开源领域和官方 GStreamer 门户上，
提供了有关此任务的大量教程。
- 可将本指南用作模板并使用开源资源来
了解如何开发定制插件。

前提条件

- 需要设置 eSDK 来下载和编译应用程序/插件代码。有关设置 eSDK 以及下载和编译插件代码的说明，请参阅 [Qualcomm Intelligent Multimedia 软件开发包 (IM SDK) 快速入门指南](https://docs.qualcomm.com/bundle/publicresource/topics/80-70018-51/introduction.html)。
- 在整个过程中使用现有插件的源代码作为参考。

    [CodeLinaro/ le / platform / vendor / qcom-opensource / gst-plugins-qti-oss · GitLab](https://git.codelinaro.org/clo/le/platform/vendor/qcom-opensource/gst-plugins-qti-oss/-/tree/imsdk.lnx.2.0.0.r1-rel?ref_type=heads)

## 插件目录结构

gst-plugins-qti-oss/gst-plugins-mlv<plugin-name>/
        CMakeLists.txt
        config.h.in
        mlv<plugin-name>.c
        mlv<plugin-name>.h
        modules/
            CMakeLists.txt
            ml-video-<plugin-name>-module.h
            ml-v<plugin-name>-<module-name>.c
    Copy to clipboard

## 创建 superresolution 插件的步骤

1. 创建插件标头 (`gst-plugins-mlvsuperresolution/mlvsuperresolution.h`)。

    使用现有插件作为参考：

    [gst-plugin-mlvsegmentation/mlvsegmentation.h·imsdk.lnx.2.0.0.r2-rel · CodeLinaro / le / platform / vendor / qcom-opensource / gst-plugins-qti-oss · GitLab](https://git.codelinaro.org/clo/le/platform/vendor/qcom-opensource/gst-plugins-qti-oss/-/blob/imsdk.lnx.2.0.0.r2-rel/gst-plugin-mlvsegmentation/mlvsegmentation.h?ref_type=heads)

    1. 导入所需的头文件。
    2. 使用处理所需的数据变量创建一个结构。

        超分辨率继承链示例：GObject &gt; GstObject &gt; GstElement &gt; GstBaseTransform

        GstBaseTransform 适用于输出大小和功能完全由输入大小和功能决定的元素

struct _GstMLVideoSuperresolution {GstBaseTransform   parent;
                                               GstMLInfo          *mlinfo;
                                               GstVideoInfo       *vinfo;
                                               GstBufferPool      *outpool;
                                               GstMLModule        *module;
                                               gint               mdlenum;
                                               GstStructure       *mlconstants;
            };
            
            struct _GstMLVideoSuperresolutionClass {GstBaseTransformClass parent;
            };
            Copy to clipboard

Note

对于超分辨率而言，标签变量并非必需。

从代码中移除标签变量及其相关使用部分。
2. 创建插件实现文件 (`gst-plugins-mlvsuperresolution/mlvsuperresolution.c`）。

    使用现有插件作为参考：

    [gst-plugin-mlvsegmentation/mlvsegmentation.c imsdk.lnx.2.0.0.r2-rel · CodeLinaro / le / platform / vendor / qcom-opensource / gst-plugins-qti-oss · GitLab](https://git.codelinaro.org/clo/le/platform/vendor/qcom-opensource/gst-plugins-qti-oss/-/blob/imsdk.lnx.2.0.0.r2-rel/gst-plugin-mlvsegmentation/mlvsegmentation.c?ref_type=heads)

    1. 导入 `mlvsuperresolution.h` 和其他必需的头文件。
    2. 定义cap

        - 视频格式

#define GST_ML_VIDEO_SUPERRESOLUTION_VIDEO_FORMATS "{ RGBA, BGRA, ARGB, ABGR, RGBx, BGRx, xRGB, xBGR, RGB, BGR }"
                Copy to clipboard
        - 源端 cap

#define GST_ML_VIDEO_SUPER_RESOLUTION_SRC_CAPS \
                    "video/x-raw, " \
                    "format = (string) " GST_ML_VIDEO_SUPER_RESOLUTION_VIDEO_FORMATS "; " \
                    "video/x-raw(" GST_CAPS_FEATURE_MEMORY_GBM "), " \
                    "format = (string) " GST_ML_VIDEO_SUPER_RESOLUTION_VIDEO_FORMATS
                Copy to clipboard
        - 接收端 cap

#define GST_ML_VIDEO_SUPER_RESOLUTION_SINK_CAPS \
                       "neural-network/tensors"
                Copy to clipboard
    3. 实现以下函数

        - 初始化

            1. 注册定制插件。注册后，您可以使用 `gst_element_factory_make("plugin-name","plugin-name");` 访问参考应用程序中的插件

static gboolean plugin_init(GstPlugin * plugin);
                    Copy to clipboard
            2. 使用默认参数初始化超分辨率。这使用户能够控制输出缓存。在收到输入缓存时，将调用 `gst_ml_video_super_resolution_prepare_output_buffer` 来分配输出缓存。

static void gst_ml_video_super_resolution_init(GstMLVideoSuperResolution * super_resolution)
                    Copy to clipboard
            3. 将回调函数初始化为函数指针、设置上限和默认属性。

static void gst_ml_video_super_resolution_class_init(GstMLVideoSuperResolutionClass * klass)
                    Copy to clipboard
        - 缓存管理

            1. 根据协商的 caps <abbr title="图缓存管理器">图缓存管理器 (GBM)</abbr>或 ION 内存。

static GstBufferPool * gst_ml_video_super_resolution_create_pool (GstMLVideoSuperResolution * super_resolution,
                                                                                      GstCaps * caps)
                    Copy to clipboard
            2. 确保根据 caps 配置适当的缓存池。

gst_ml_video_super_resolution_decide_allocation (GstBaseTransform * base,
                                                                     GstQuery * query)
                    Copy to clipboard
            3. 确保根据上限从池中分配输出缓存。

static GstFlowReturn gst_ml_video_super_resolution_prepare_output_buffer (GstBaseTransform * base,
                                                                                              GstBuffer * inbuffer,
                                                                                              GstBuffer ** outbuffer)
                    Copy to clipboard
        - Caps

            1. 验证模块，然后从模块 caps 收集输入和输出功能。

static gboolean gst_ml_video_super_resolution_set_caps (GstBaseTransform * base,
                                                                            GstCaps * incaps,
                                                                            GstCaps * outcaps)
                    Copy to clipboard
            2. 固定协商 caps。

static GstCaps * gst_ml_video_super_resolution_fixate_caps (GstBaseTransform * base,
                                                                                GstPadDirection direction,
                                                                                GstCaps * incaps,
                                                                                GstCaps * outcaps)
                    Copy to clipboard
            3. 检查指定的 caps 是否有效，如 video/x-raw、video/x-text、格式、高度和宽度。

static gboolean caps_has_feature (const GstCaps * caps,
                                                      const gchar * feature)
                    Copy to clipboard
            4. 将静态 caps 转换为常规 caps。

static GstCaps * gst_ml_video_super_resolution_src_caps (void)
                    Copy to clipboard
            5. 将静态 caps 转换为常规 caps。

static GstCaps * gst_ml_video_super_resolution_sink_caps (void)
                    Copy to clipboard
        - 转换

            1. 将接收端 caps 转换为源 caps，反之亦然。

static GstCaps * gst_ml_video_super_resolution_transform_caps (GstBaseTransform * base,
                                                                                   GstPadDirection direction,
                                                                                   GstCaps * caps,
                                                                                   GstCaps * filter)
                    Copy to clipboard
            2. 推理后，将根据模块调用后处理函数（`gst_ml_video_superresolution_module_execute`）。

gst_ml_video_super_resolution_transform (GstBaseTransform * base,
                                                             GstBuffer * inbuffer,
                                                             GstBuffer * outbuffer)
                    Copy to clipboard
        - 属性

            1. 设置插件属性，如模块和常量。

static void gst_ml_video_super_resolution_set_property (GObject * object,
                                                                           guint prop_id,
                                                                           const GValue * value,
                                                                           GParamSpec * pspec)
                    Copy to clipboard
            2. 读取插件属性，如模块和常量

static void gst_ml_video_super_resolution_get_property (GObject * object,
                                                                            guint prop_id,
                                                                            GValue * value,
                                                                            GParamSpec * pspec)
                    Copy to clipboard
        - 反初始化

            1. 释放已分配的缓存。

static void gst_ml_video_super_resolution_finalize (GObject * object)
                    Copy to clipboard
        - 显示文本/边界框（仅基于用例，超分辨率用例无需此操作）

            1. 在输出帧上叠加结果

static gboolean gst_ml_video_<plugin-name>_fill_video_output(GstMLVideoDetection * detection,
                                                                                 GArray * predictions,
                                                                                 GstBuffer * buffer);
                    Copy to clipboard
    4. 更新 `gst-plugins-mlvsuperresolution/CMakeLists.txt` 文件中的插件名称。

        使用现有插件作为参考。

        [gst-plugin-mlvsegmentation/CMakeLists.txt imsdk.lnx.2.0.0.r2-rel · CodeLinaro / le / platform / vendor / qcom-opensource / gst-plugins-qti-oss · GitLab](https://git.codelinaro.org/clo/le/platform/vendor/qcom-opensource/gst-plugins-qti-oss/-/blob/imsdk.lnx.2.0.0.r2-rel/gst-plugin-mlvsegmentation/CMakeLists.txt?ref_type=heads)

        重用现有插件中的 `config.h.in` 文件：

        [gst-plugin-mlvsegmentation/config.h.in imsdk.lnx.2.0.0.r2-rel · CodeLinaro / le / platform / vendor / qcom-opensource / gst-plugins-qti-oss · GitLab](https://git.codelinaro.org/clo/le/platform/vendor/qcom-opensource/gst-plugins-qti-oss/-/blob/imsdk.lnx.2.0.0.r2-rel/gst-plugin-mlvsegmentation/config.h.in?ref_type=heads)

## 模块概述

- 每个模型都有特定的后处理步骤，这些步骤需要在推理缓存上执行并相应地更新输出缓存。例如，对于超分辨率和分割用例，需要填充 RGB 像素；对于检测用例，需要计算边框等。
- `<module-name>.c` 定义了这些后处理步骤。模块目录中包含如下结构的文件列表

modules/
             "gst-plugins-mlvsuperresolution/modules/ml-vsuperresolution-<module-name1>.c"
             "gst-plugins-mlvsuperresolution/modules/ml-vsuperresolution-<module-name2>.c"
        
        Here <module-name> represents the model's name like srnet for superresolution.
        Copy to clipboard

## 创建 srnet 模块的步骤

1. 创建模块头 `gst-plugins-qti-oss/gst-plugin-base/gst/ml/ml-module-video-super-resolution.h`。

    使用现有插件作为参考：

    [gst-plugin-base/gst/ml/ml-module-video-super-resolution.h imsdk.lnx.2.0.0.r2-rel · CodeLinaro / le / platform / vendor / qcom-opensource / gst-plugins-qti-oss · GitLab](https://git.codelinaro.org/clo/le/platform/vendor/qcom-opensource/gst-plugins-qti-oss/-/blob/imsdk.lnx.2.0.0.r2-rel/gst-plugin-base/gst/ml/ml-module-video-super-resolution.h?ref_type=heads)

    1. 导入所需的 `gst` 头文件。
    2. 创建 `execute` 函数。

GST_API gboolean gst_ml_module_video_super_resolution_execute(GstMLModule   * module,
                                                                          GstMLFrame    * mlframe,
                                                                          GstVideoFrame * vframe);
            Copy to clipboard

        该函数需要调用 `ml-vsuperresolution-<module-name>.c` 文件中定义的后处理函数 (`gst_ml_module_process`)。
2. 创建模块 `gst-plugins-mlvsuperresolution/modules/ml-vsuperresolution-srnet.c` 文件。

    使用现有插件作为参考：

    [gst-plugin-mlvsegmentation/modules/ml-vsegmentation-deeplab-argmax.c · imsdk.lnx.2.0.0.r1-rel · CodeLinaro / le / platform / vendor / qcom-opensource / gst-plugins-qti-oss · GitLab](https://git.codelinaro.org/clo/le/platform/vendor/qcom-opensource/gst-plugins-qti-oss/-/blob/imsdk.lnx.2.0.0.r1-rel/gst-plugin-mlvsegmentation/modules/ml-vsegmentation-deeplab-argmax.c?ref_type=heads)

    1. 导入 `modules/ml-video-superresolution-module.h` 头文件。
    2. 定义模型输出 cap。

#define GST_ML_MODULE_CAPS \
                "neural-network/tensors, " \
                "type = (string) { INT8, UINT8, INT32, FLOAT32 }, " \
                "dimensions = (int) < <1, [32, 4096], [32, 4096]> >; " \
                "neural-network/tensors, " \
                "type = (string) { INT8, UINT8, INT32, FLOAT32 }, " \
                "dimensions =  (int) < <1, [32, 4096], [32, 4096], [1, 3]> >"
            Copy to clipboard

        **例如**

> 
> 
> 1. 从 AI Hub 下载 [QuickSRNetLarge-Quantized Qualcomm AI Hub](https://aihub.qualcomm.com/iot/models/quicksrnetlarge_quantized) 模型
>         2. 检查 LiteRT 模型的输出尺寸（参见 [在应用程序中集成 AI Hub 模型](https://docs.qualcomm.com/doc/80-70018-15BY/topic/integrate-ai-hub-models.html)）。
> 
>             - 格式：`dtype[N x H X W X C]`
>             - 在上述模块输出上限中 `<1, [32, 4096], [32, 4096], [1, 3]>`
> 
>                 - `N = 1`：模型输出批量大小
>                 - `H = [32,4096]`：模型输出高度应在此范围内
>                 - `W= [32,4096]`：模型输出宽度应在此范围内
>                 - `C = [1,3]`：模型输出通道应在此范围内
>                 - `dtype`：`int8` 用于量化模型，`float32` 用于非量化模型
>         3. 关于量化模型，请检查输出节点的比例和偏移量。
> 
> 
>             格式：`scale*(q-offset)`
    3. 实现以下函数

        - 初始化

gpointer gst_ml_module_open (void);
                Copy to clipboard
        - 反初始化

void gst_ml_module_close (gpointer instance);
                Copy to clipboard
        - Caps

GstCaps *gst_ml_module_caps (void);
                Copy to clipboard
        - 配置

gboolean gst_ml_module_configure (gpointer instance,
                                                  GstStructure * settings);
                Copy to clipboard

            检查模块类型、比例和偏移量。
        - 反量化

static inline gdouble gst_ml_module_get_dequant_value (void       *data,
                                                                       GstMLType  mltype,
                                                                       guint      idx,
                                                                       gdouble    offset,
                                                                       gdouble    scale);
                Copy to clipboard

            需要传递给量化模型的缩放系数和偏置值
        - 后处理

gboolean gst_ml_module_process (gpointer    instance,
                                                GstMLFrame  *mlframe,
                                                gpointer     output);
                Copy to clipboard
        - 推理缓存

indata = GST_ML_FRAME_BLOCK_DATA (mlframe, 0);
                Copy to clipboard
        - 用后处理数据填充的输出缓存

outdata = GST_VIDEO_FRAME_PLANE_DATA (vframe, 0);
                Copy to clipboard
        - 模型的数据类型

mltype = GST_ML_FRAME_TYPE (mlframe);
                Copy to clipboard
        - 后处理（用于超分辨率）

for (row = 0; row < GST_VIDEO_FRAME_HEIGHT (vframe row++) {
                    for (column = 0; column < GST_VIDEO_FRAME_WIDTH (vframe); column++) {
                        // Calculate the destination index.
                        idx = (((row * GST_VIDEO_FRAME_WIDTH (vframe)) + column) * bpp) + (row * padding)
                        outdata[idx] = gst_ml_module_get_dequant_value(indata, mltype, idx, submodule->qoffsets[0], submodule->qscales[0]) * 255;
                        outdata[idx + 1] = gst_ml_module_get_dequant_value(indata, mltype, idx + 1, submodule->qoffsets[0], submodule->qscales[0]) * 255;
                        outdata[idx + 2] = gst_ml_module_get_dequant_value(indata, mltype, idx + 2, submodule->qoffsets[0], submodule->qscales[0]) * 255;
                        if (bpp == 4)
                            outdata[idx + 3] = 0;
                    }
                }
                Copy to clipboard
    4. 更新 `gst-plugins-mlvsuperresolution/modules/CMakeLists.txt` 文件中的模块名称。

        使用现有插件作为参考：

        [gst-plugin-mlvsegmentation/modules/CMakeLists.txt · imsdk.lnx.2.0.0.r1-rel · CodeLinaro / le / platform / vendor / qcom-opensource / gst-plugins-qti-oss · GitLab](https://git.codelinaro.org/clo/le/platform/vendor/qcom-opensource/gst-plugins-qti-oss/-/blob/imsdk.lnx.2.0.0.r1-rel/gst-plugin-mlvsegmentation/modules/CMakeLists.txt?ref_type=heads)

## 更新 BitBake 文件以进行插件编译的步骤

1. 请按照[创建 Qualcomm IM SDK 插件](https://docs.qualcomm.com/bundle/publicresource/topics/80-70018-51/create-your-imsdk-plugin.html)中的说明来编译和安装超分辨率插件。
2. 设置 Wayland 显示。

ssh root@[IP address of the target device]
        Copy to clipboard

Note

如果出现提示，请输入 `oelinux123` 作为 ssh shell 的密码。

export XDG_RUNTIME_DIR=/dev/socket/weston && export WAYLAND_DISPLAY=wayland-1
        Copy to clipboard

引用 GStreamer pipeline 以使用 qtimlvsuperresolution 插件

gst-launch-1.0 -e --gst-debug=2,qtimltflite:7 filesrc location=/etc/media/video.mp4 ! qtdemux ! queue ! h264parse ! \
    v4l2h264dec capture-io-mode=4 output-io-mode=4 ! video/x-raw,format=NV12 ! queue ! tee name=split \
    split. ! queue ! qtivcomposer name=mixer \
    sink_0::position="<0, 0>" sink_0::dimensions="<960, 1080>" \
    sink_1::position="<960, 0>" sink_1::dimensions="<960, 1080>" \
    ! queue ! waylandsink sync=false fullscreen=true \
    split. ! qtimlvconverter ! queue ! \
    qtimltflite delegate=external external-delegate-path=libQnnTFLiteDelegate.so \
    external-delegate-options="QNNExternalDelegate,backend_type=htp;" model=/etc/models/quicksrnetlarge_quantized.tflite ! queue ! \
    qtimlvsuperresolution module=srnet constants="qsrnetlarge,q-offsets=<0.0>,q-scales=<1.0>;" ! \
    video/x-raw,width=512,height=512,format=RGB ! queue ! mixer.
    Copy to clipboard

Note

输入视频分辨率必须为 128 x 128 x 3，由于 `quicksrnetlarge_quantized.tflite` 模型输入尺寸为 128x128x3。

Last Published: Oct 23, 2025

[Previous Topic
开发定制 GStreamer 插件](https://docs.qualcomm.com/bundle/publicresource/80-70018-15BY/topics/general-guidelines-for-developing-gstreamer-plugin.md) [Next Topic
使用 AI Hub 模型和标签与 GStreamer API](https://docs.qualcomm.com/bundle/publicresource/80-70018-15BY/topics/ai-hub-qualcomm-im-sdk.md)