# 초고해상도 플러그인 개발

이 섹션에서는 새로운 초고해상도(qtimlvsuperresolution) 플러그인을 개발하는 방법을 설명합니다.

참고

- 이러한 지침은 `imsdk.lnx.2.0.0.r1-rel` 릴리스를 기반으로 합니다.
- 기존 플러그인을 기반으로, 지원되지 않는 사용 사례(예: 초고해상도)에 대응할 수 있는 Qualcomm IM SDK 플러그인을 제작하는 숙련된 개발자를 위한 지침입니다.
- 커스텀 GStreamer 플러그인 만들기는 고급 작업이며 숙련된 GStreamer 개발자만 사용하게 되어 있습니다.
- 오픈 소스 도메인과 공식 GStreamer 포털에서 이 작업에 대한 광범위한 튜토리얼을 확인할 수 있습니다.
- 이 가이드를 템플릿으로 사용하고 오픈 소스 리소스를 사용하여 커스텀 플러그인 개발에 대해 알아보세요.

전제 조건

- 애플리케이션/플러그인 코드를 다운로드하고 컴파일하려면 eSDK를 설정해야 합니다. eSDK를 설정하고 플러그인 코드를 다운로드 및 컴파일하는 방법에 대한 지침은 [Qualcomm 지능형 멀티미디어 소프트웨어 개발 키트(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

## 초고해상도 플러그인을 만드는 단계

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
        - 싱크 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="그래픽 버퍼 관리자">그래픽 버퍼 관리자 (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. video/x-raw, video/x-text, format, height, width 등 지정된 caps가 유효한지 여부를 확인합니다.

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
        - 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` 는 이러한 후처리 단계를 정의합니다. Module디렉토리에는 아래 구조와 같은 파일 목록이 있습니다.

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. 모델 출력 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-15BK/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. 다음 함수를 구현합니다.

        - 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

            모듈 dytpe, 스케일, 오프셋을 확인합니다.
        - 양자화 해제

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 셸의 비밀번호로 입력합니다.

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: Oct 15, 2025

[Previous Topic
커스텀 GStreamer 플러그인 개발](https://docs.qualcomm.com/bundle/publicresource/80-70018-15BK/topics/general-guidelines-for-developing-gstreamer-plugin.md) [Next Topic
GStreamer API에서 AI Hub 모델 및 레이블 사용](https://docs.qualcomm.com/bundle/publicresource/80-70018-15BK/topics/ai-hub-qualcomm-im-sdk.md)