# 開發超解析度外掛程式

本節說明如何開發新的超解析度 (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-70020-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

## 建立 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

備註

超解析度模組不需要使用 labels 變數。

請移除 labels 變數及程式碼。
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. 實作以下函式

        - Init

            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="Graphics Buffer Manager">graphics Buffer Manager (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. 驗證 module，然後從 module 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. 在輸入與輸出端之間轉換 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. 設置外掛程式屬性，如 module 和常數。

static void gst_ml_video_super_resolution_set_property (GObject * object,
                                                                           guint prop_id,
                                                                           const GValue * value,
                                                                           GParamSpec * pspec)
                    Copy to clipboard
            2. 讀取外掛程式屬性，如 module 和常數。

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

        此函式需呼叫後處理函式 (`gst_ml_module_process`) ，該函式將定義於 `ml-vsuperresolution-<module-name>.c` 中。
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) 模型
>         2. 檢查 LiteRT 模型的輸出量 (請參閱 [將 AI Hub 模型整合至應用程式](https://docs.qualcomm.com/doc/80-70020-15BT/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 和 offset。
> 
> 
>             格式： `scale*(q-offset)`
    3. 實作以下函式

        - Init

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

            檢查模組 dtype、scale 和 offset
        - 反量化

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-70020-51/create-your-imsdk-plugin.html) 以瞭解如何編譯和安裝超解析度外掛程式。
2. 設置 Wayland display。

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

使用 qtimlvsuperresolution 外掛的 GStreamer 管線參考

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: Dec 23, 2025

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