# Develop a superresolution plugin

This section explains how to develop a new super resolution (qtimlvsuperresolution) plugin.

Notes

- These instructions are based on the `imsdk.lnx.2.0.0.r1-rel` release .
- This guidance is for experienced developers creating a
Qualcomm IM SDK plugin to handle unsupported use cases, such as
super resolution, by building upon existing plugins.
- Creating a custom GStreamer plugin is an advanced task and is
intended only for experienced GStreamer developers.
- Extensive tutorials are available in the open-source domain and on
the official GStreamer portal for this task.
- Use this guide as a template and use the open-source resources to
learn about developing custom plugins.

Prerequisites

- The eSDK needs to be setup to download and compile application/plugin
code. See the [Qualcomm Intelligent Multimedia Software Development Kit (IM SDK) Quick Start Guide](https://docs.qualcomm.com/bundle/publicresource/topics/80-70018-51/introduction.html)
for instructions on setting up the eSDK and downloading and compiling plugin code.
- Use the source code of the existing plugins as a reference throughout this process.

    [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)

## Plugin directory structure

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

## Steps to create superresolution plugin

1. Create the plugin header (`gst-plugins-mlvsuperresolution/mlvsuperresolution.h`).

    Use the existing plugin as a reference:

    [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. Import the required headers.
    2. Create a structure with the data variables required for processing.

        Example super resolution inheritance chain: GObject &gt; GstObject &gt; GstElement &gt; GstBaseTransform

        GstBaseTransform is suitable for elements where the output size and capabilities are entirely
determined by the input size and capabilities

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

Note

The labels variable isn’t required for superresolution.

Remove the labels variable and its usage in code.
2. Create the plugin implementation file (`gst-plugins-mlvsuperresolution/mlvsuperresolution.c`).

    Use the existing plugin as a reference:

    [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. Import the `mlvsuperresolution.h` and other required headers.
    2. Define the caps

        - video formats

#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. Implement following functions

        - Init

            1. Register a custom plugin. Once registered you can access plugin in
reference apps with `gst_element_factory_make("plugin-name","plugin-name");`

static gboolean plugin_init(GstPlugin * plugin);
                    Copy to clipboard
            2. Initialize superresolution with default parameters. This allows you to
control output buffers. On receiving an input buffer, `gst_ml_video_super_resolution_prepare_output_buffer`
is called to allocate an output buffer.

static void gst_ml_video_super_resolution_init(GstMLVideoSuperResolution * super_resolution)
                    Copy to clipboard
            3. Initialize callback functions to the function pointer, sets caps, and default properties.

static void gst_ml_video_super_resolution_class_init(GstMLVideoSuperResolutionClass * klass)
                    Copy to clipboard
        - Buffer management

            1. Allocates either <abbr title="Graphics Buffer Manager">graphics Buffer Manager (GBM)</abbr> or ION Memory depending on the negotiated caps.

static GstBufferPool * gst_ml_video_super_resolution_create_pool (GstMLVideoSuperResolution * super_resolution,
                                                                                      GstCaps * caps)
                    Copy to clipboard
            2. Ensures appropriate buffer pool configuration based on the caps.

gst_ml_video_super_resolution_decide_allocation (GstBaseTransform * base,
                                                                     GstQuery * query)
                    Copy to clipboard
            3. Ensures output buffers are allocated from the pool depending on caps.

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

            1. Validate the module and then collect the inputs and output
capabilities from the module caps.

static gboolean gst_ml_video_super_resolution_set_caps (GstBaseTransform * base,
                                                                            GstCaps * incaps,
                                                                            GstCaps * outcaps)
                    Copy to clipboard
            2. Fix negotiated caps.

static GstCaps * gst_ml_video_super_resolution_fixate_caps (GstBaseTransform * base,
                                                                                GstPadDirection direction,
                                                                                GstCaps * incaps,
                                                                                GstCaps * outcaps)
                    Copy to clipboard
            3. Check whether specified caps are valid or not like video/x-raw,
video/x-text, format, height and width.

static gboolean caps_has_feature (const GstCaps * caps,
                                                      const gchar * feature)
                    Copy to clipboard
            4. Convert static caps to regular caps.

static GstCaps * gst_ml_video_super_resolution_src_caps (void)
                    Copy to clipboard
            5. Convert static caps to regular caps.

static GstCaps * gst_ml_video_super_resolution_sink_caps (void)
                    Copy to clipboard
        - Transform

            1. Transform sink caps to source caps and vice versa.

static GstCaps * gst_ml_video_super_resolution_transform_caps (GstBaseTransform * base,
                                                                                   GstPadDirection direction,
                                                                                   GstCaps * caps,
                                                                                   GstCaps * filter)
                    Copy to clipboard
            2. After inference, the postprocessing function
(`gst_ml_video_superresolution_module_execute`) will be called based on the
module.

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

            1. Set plugin properties, like module and constant.

static void gst_ml_video_super_resolution_set_property (GObject * object,
                                                                           guint prop_id,
                                                                           const GValue * value,
                                                                           GParamSpec * pspec)
                    Copy to clipboard
            2. Read plugin properties, like module and constant.

static void gst_ml_video_super_resolution_get_property (GObject * object,
                                                                            guint prop_id,
                                                                            GValue * value,
                                                                            GParamSpec * pspec)
                    Copy to clipboard
        - De-init

            1. Free all allocated buffers.

static void gst_ml_video_super_resolution_finalize (GObject * object)
                    Copy to clipboard
        - Display text/bounding boxes (based on use case only, not required for super resolution)

            1. Overlay result on output frame

static gboolean gst_ml_video_<plugin-name>_fill_video_output(GstMLVideoDetection * detection,
                                                                                 GArray * predictions,
                                                                                 GstBuffer * buffer);
                    Copy to clipboard
    4. Update the plugin name in the `gst-plugins-mlvsuperresolution/CMakeLists.txt` file.

        Use the existing plugin as a reference.

        [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)

        Reuse the `config.h.in` file from the existing plugin:

        [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)

## Overview of Module

- Each model has specific postprocessing steps, which need to be
performed on inferenced buffers and update output buffers accordingly,
like populating RGB pixels for super resolution and segmentation or
calculating bounding boxes for detection.
- `<module-name>.c` defines these postprocessing steps.
Module directory contains list of files like below structure

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

## Steps to create the srnet module

1. Create the module header `gst-plugins-qti-oss/gst-plugin-base/gst/ml/ml-module-video-super-resolution.h`.

    Use the existing plugin as a reference:

    [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. Import the required `gst` headers.
    2. Create the `execute` function.

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

        This function is required to call the postprocessing function
(`gst_ml_module_process`) which is defined in the `ml-vsuperresolution-<module-name>.c` file.
2. Create module the `gst-plugins-mlvsuperresolution/modules/ml-vsuperresolution-srnet.c` file.

    Use the existing pluging as a reference:

    [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. Import the `modules/ml-video-superresolution-module.h` header.
    2. Define the model output 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

        **For Example**

> 
> 
> 1. Download [QuickSRNetLarge-Quantized- Qualcomm AI Hub](https://aihub.qualcomm.com/iot/models/quicksrnetlarge_quantized) model from AI Hub
>         2. Check the output dimensions of the LiteRT model (See [Integrate an AI Hub model in an application](https://docs.qualcomm.com/doc/80-70018-15B/topic/integrate-ai-hub-models.html)).
> 
>             - Format: `dtype[N x H X W X C]`
>             - In the above module output caps `<1, [32, 4096], [32, 4096], [1, 3]>`
> 
>                 - `N = 1`: Model output batch size
>                 - `H = [32,4096]`: Model output height should be in this range
>                 - `W= [32,4096]`: Model output width should be in this range
>                 - `C = [1,3]`: Model output channels should be in this range
>                 - `dtype`: `int8` for quantized models and `float32` for non-quantized models
>         3. For quantized models, check the output node for scale and offset.
> 
> 
>             Format: `scale*(q-offset)`
    3. Implement following functions

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

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

            Check for module dytpe, scale, and offset.
        - De-quantize

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

            Scale and offset values need to passed for quantized models
        - Postprocess

gboolean gst_ml_module_process (gpointer    instance,
                                                GstMLFrame  *mlframe,
                                                gpointer     output);
                Copy to clipboard
        - Inferenced buffer

indata = GST_ML_FRAME_BLOCK_DATA (mlframe, 0);
                Copy to clipboard
        - Output buffer to be filled with postprocessed data

outdata = GST_VIDEO_FRAME_PLANE_DATA (vframe, 0);
                Copy to clipboard
        - Data type of the model

mltype = GST_ML_FRAME_TYPE (mlframe);
                Copy to clipboard
        - Postprocess (for super resolution)

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. Update the module name in the `gst-plugins-mlvsuperresolution/modules/CMakeLists.txt` file.

        Use the existing plugin as a reference:

        [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)

## Steps to update BitBake files for plugin compilation

1. Follow [create your Qualcomm IM SDK plugin](https://docs.qualcomm.com/bundle/publicresource/topics/80-70018-51/create-your-imsdk-plugin.html)
for instructions on compiling and installing the superresolution plugin.
2. Setup the Wayland display.

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

Note

If prompted, enter `oelinux123` as the password for the ssh shell.

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

Reference GStreamer pipeline to use qtimlvsuperresolution plugin

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

Input video resolution must be 128x128x3. As
the `quicksrnetlarge_quantized.tflite` model input dimensions are
128x128x3.

Last Published: Oct 13, 2025

[Previous Topic
Develop a custom GStreamer plugin](https://docs.qualcomm.com/bundle/publicresource/80-70018-15B/topics/general-guidelines-for-developing-gstreamer-plugin.md) [Next Topic
Use AI Hub models and labels with the GStreamer API](https://docs.qualcomm.com/bundle/publicresource/80-70018-15B/topics/ai-hub-qualcomm-im-sdk.md)