'Crash in GStreamer qmlglsink pipeline dynamically rebind to different GstGLVideoItem

I've used one of existing qmlglsink examples to stream video feed from 4 IP Cameras. 4 Pipelines are created before engine load.

for(int i = 0; i < maxCameras; ++i) {
    GstElement* pipeline = gst_pipeline_new (NULL);
    GstElement* src = gst_element_factory_make ("udpsrc", NULL);
    GstElement* parse = gst_element_factory_make ("jpegparse", NULL);
    GstElement* decoder = gst_element_factory_make ("jpegdec", NULL);
    GstElement* glcolorconvert = gst_element_factory_make ("glcolorconvert", NULL);
    GstElement* glupload = gst_element_factory_make ("glupload", NULL);
    GstElement *sink = gst_element_factory_make ("qmlglsink", NULL);

    g_assert (src && parse && decoder && glupload && glcolorconvert && sink);

    g_object_set (G_OBJECT (src), "port", startingPort + i, NULL);

    g_object_set (G_OBJECT (sink), "sync", FALSE, NULL);

    gst_bin_add_many (GST_BIN (pipeline), src, parse, decoder, glupload, glcolorconvert, sink, NULL);
    if (!gst_element_link_many ( src, parse, decoder, glupload, glcolorconvert, sink, NULL)) {
        qDebug() << "Linking GStreamer pipeline elements failed";
    }

    sinks.insert(std::make_pair(QString::number(startingPort+i), sink));
    pipelines.insert(std::make_pair(QString::number(startingPort+i), pipeline));
}

In Qml sink is connected and processed with

import QtQuick 2.15
import QtQuick.Layouts 1.15
import CustomProject 1.0
import org.freedesktop.gstreamer.GLVideoItem 1.0

Item {
    id: root

    signal clicked()
    required property int udpPort
    property var camConnect: undefined
    onUdpPortChanged: { setupConnection(); }

    onVisibleChanged: {
        if (visible) { setupConnection();
        } else { camConnect = undefined }
    }

    GstGLVideoItem {
        id: videoItem
        anchors.fill: parent
        function connect() {
            CameraSinksFactory.connectSink(this, udpPort)
        }
    }
    MouseArea {
        anchors.fill: parent
        onClicked: {
            CameraSinksFactory.stopPipeline(udpPort)
            root.clicked()
        }
    }

    function setupConnection() {
        if (udpPort <= 0 || !root.visible) return;
        videoItem.connect()
        root.camConnect = CameraSinksFactory.getCamConnection(udpPort);
        root.camConnect.resolutionX =// - 15 root.width
        root.camConnect.resolutionY = root.height
        root.camConnect.bitrate = 15000000
        root.camConnect.streaming = root.visible
        CameraSinksFactory.startPipeline(udpPort)
    }
}

Problem: Main screen display 4 (2x2 grid) items using Model (which provides udpPort as unique ID). When User clicks on one Item - feed from this camera should fill whole screen. In Examples they create GridLayout with 4/6 explicit items and just manipulate their visiblity (in effect clicked item is only one remaining and take whole screen).
In my case - I'm using separate Item for full screen view. So I'm disabling streaming (CamConnection class communicating with Cameras and sending commands) and hide GridView. New GstGLVideoItem binds to qmlglsink in pipeline.
Everything is OK, until I repeat click sequence (back to GridView and to fullview). Every time it ends with:

Bail out! ERROR:../ext/qt/gstqsgtexture.cc:134:virtual void GstQSGTexture::bind(): code should not be reached

** (KMS:20495): CRITICAL **: 15:47:36.937: gst_video_frame_map_id: assertion 'info->width <= meta->width' failed
** ERROR:../ext/qt/gstqsgtexture.cc:134:virtual void GstQSGTexture::bind(): code should not be reached

From plugins code analysis it's happening when INFO (image size read from CAPS) is bigger then size in metadata in provided buffer. Which is understandable - buffer is too small.
I used GST_DEBUG=4/5/6/7 and logs confirm that autodetected caps are matching request in commands sent to camera.
I can use example, but project assumes another panel with those cameras - so above problem will hit me in near future.

How to make this whole setup working? How to rebind pipeline qmlglsink to new QML VideoItem safely?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source