# 開發超分辨率外掛程式

本節說明如何開發新的超分辨率 (qtimlvsuperresolution) 外掛程式。

注意事項

- 這些說明基於 `imsdk.lnx.2.0.0.r1-rel` 版本。
- 此指南適用於經驗豐富的開發人員，通過構建現有外掛程式來創建 Qualcomm IM SDK 外掛程式，以處理不支持的用例，如超分辨率。
- 創建自定義 GStreamer 外掛程式是一項高級任務，僅適用於經驗豐富的 GStreamer 開發人員。
- 在開源領域和官方 GStreamer 門戶網站上有大量教程可供此任務使用。
- 使用本指南作為模板，並使用開源資源來了解開發自定義外掛程式。

先決條件

- 需要設置 eSDK 以下載和編譯應用/外掛程式代碼。請參見 [Qualcomm 智慧多媒體軟體開發工具包 (IM SDK) 快速入門指南](https://docs.qualcomm.com/bundle/publicresource/topics/80-70018-51/introduction.html) 以獲取有關設置 eSDK 以及下載和編譯外掛程式代碼的說明。
- 在整個過程中使用現有外掛程式的原始碼作為參考。

    [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

## 創建超分辨率外掛程式的步驟

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

備註

標籤變量不需要超分辨率。

刪除標籤變量及其在代碼中的使用。
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. 定義 caps

        - 影片格式

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

#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
        - sink caps

#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. 初始化回調函數到函數指針，設置 caps 和默認屬性。

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. 確保根據 caps 從池中分配輸出緩衝區。

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
        - Transform

            1. 將 sink caps 轉換為 source 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
        - Property

            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
        - De-init

            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-.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. 定義模型輸出caps。

#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-15BT/topic/integrate-ai-hub-models.html)）。
> 
>             - 格式：`dtype[N x H X W X C]`
>             - 在上述模塊輸出caps中 `<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
        - De-init

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

備註

如果出現提示，請輸入 `oelinux123` 作為ssh shell的密碼。

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

參考GStreamer管道以使用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

備註

輸入影片分辨率必須為128x128x3。由於 `quicksrnetlarge_quantized.tflite` 模型的輸入尺寸為128x128x3。

Last Published: Oct 15, 2025

[Previous Topic
開發自定義GStreamer外掛程式。](https://docs.qualcomm.com/bundle/publicresource/80-70018-15BT/topics/general-guidelines-for-developing-gstreamer-plugin.md) [Next Topic
使用 GStreamer API 與 AI Hub 模型和標籤](https://docs.qualcomm.com/bundle/publicresource/80-70018-15BT/topics/ai-hub-qualcomm-im-sdk.md)