Stream is slow inside Qt

Hey y’all! I have an issue of playing slow in Qt I will supply my code below:
This is how i draw frames:

GstFlowReturn WidgetCameraView::handleNewSample() {
    if (!m_sink) return GST_FLOW_ERROR;

    GstSample *sample = gst_app_sink_pull_sample(GST_APP_SINK(m_sink));
    if (!sample) return GST_FLOW_ERROR;

    GstBuffer *buffer = gst_sample_get_buffer(sample);
    if (!buffer) {
        gst_sample_unref(sample);
        return GST_FLOW_ERROR;
    }

    GstMapInfo map;
    if (!gst_buffer_map(buffer, &map, GST_MAP_READ)) {
        gst_sample_unref(sample);
        return GST_FLOW_ERROR;
    }

    GstCaps *caps = gst_sample_get_caps(sample);
    if (!caps) {
        gst_buffer_unmap(buffer, &map);
        gst_sample_unref(sample);
        return GST_FLOW_ERROR;
    }

    GstStructure *structure = gst_caps_get_structure(caps, 0);
    int width, height;
    if (!gst_structure_get_int(structure, "width", &width) || !gst_structure_get_int(structure, "height", &height)) {
        gst_buffer_unmap(buffer, &map);
        gst_sample_unref(sample);
        return GST_FLOW_ERROR;
    }

    QImage image(map.data, width, height, QImage::Format_RGB888);

    QMetaObject::invokeMethod(this, [this, image]() {
        QPixmap pixmap = QPixmap::fromImage(image);
        m_pixmapItem->setPixmap(pixmap);
        m_pixmapItem->update();  // Trigger update for every new frame
        m_view->fitInView(m_pixmapItem, Qt::KeepAspectRatio);
        m_pixmapItem->setOverlayProperties(0, 0, 100.0, 100, 10, counter, 50);
        counter+=1.0;
        if(counter > 360) counter = 0.0;
    }, Qt::QueuedConnection);

    gst_buffer_unmap(buffer, &map);
    gst_sample_unref(sample);

    return GST_FLOW_OK;
}
#include "widget_camera_metadata_overlay.h"
#include <cmath>

widget_camera_metadata_overlay::widget_camera_metadata_overlay(QGraphicsItem *parent)
        : QGraphicsPixmapItem(parent), m_offsetX(0), m_offsetY(0), m_overlaySizeZoom(100), m_overlaySize(300),
          m_pocketSize(50), m_rotate(0), m_blackPlateRadius(200)
{
}

void widget_camera_metadata_overlay::setOverlayProperties(int offsetX, int offsetY, double overlaySizeZoom, int overlaySize, int pocketSize, double rotate, int blackPlateRadius)
{
    m_offsetX = offsetX;
    m_offsetY = offsetY;
    m_overlaySizeZoom = overlaySizeZoom;
    m_overlaySize = overlaySize;
    m_pocketSize = pocketSize;
    m_rotate = rotate;
    m_blackPlateRadius = blackPlateRadius;
}

void widget_camera_metadata_overlay::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QGraphicsPixmapItem::paint(painter, option, widget); // Draw the pixmap

    if (!m_showOverlay) {
        return;
    }

    painter->save();
    painter->translate(m_offsetX + pixmap().width() / 2, -m_offsetY + pixmap().height() / 2);
    painter->rotate(m_rotate);

    // Use local variables to minimize the use of member variables inside the loop
    const int overlaySizeWithZoom = m_overlaySize * (m_overlaySizeZoom / 100.0);
    const int pocketSize = m_pocketSize;

    for (int i = 0; i < 40; ++i) {
        const double angle = i * (360.0 / 40.0) - 90;
        const double nextAngle = (i + 1) * (360.0 / 40.0) - 90;

        QPolygonF trapezoid;
        trapezoid << QPointF((overlaySizeWithZoom - pocketSize) * cos(qDegreesToRadians(angle)), (overlaySizeWithZoom - pocketSize) * sin(qDegreesToRadians(angle)))
                  << QPointF(overlaySizeWithZoom * cos(qDegreesToRadians(angle)), overlaySizeWithZoom * sin(qDegreesToRadians(angle)))
                  << QPointF(overlaySizeWithZoom * cos(qDegreesToRadians(nextAngle)), overlaySizeWithZoom * sin(qDegreesToRadians(nextAngle)))
                  << QPointF((overlaySizeWithZoom - pocketSize) * cos(qDegreesToRadians(nextAngle)), (overlaySizeWithZoom - pocketSize) * sin(qDegreesToRadians(nextAngle)));

        painter->setBrush((i % 2 == 0) ? QColor(255, 0, 0, 128) : QColor(0, 0, 0, 128));
        painter->setPen(Qt::NoPen);  // Avoid unnecessary pen setting inside the loop
        painter->drawPolygon(trapezoid);
    }

    painter->setBrush(QColor(0, 0, 0, 128));
    painter->setPen(QPen(Qt::black, 2));
    painter->drawEllipse(QPointF(0, 0), m_blackPlateRadius, m_blackPlateRadius);

    painter->restore();
}

void widget_camera_metadata_overlay::setShowOverlay(bool showOverlay)
{
    m_showOverlay = showOverlay;
}
#ifndef CUSTOMPIXMAPITEM_H
#define CUSTOMPIXMAPITEM_H

#include <QGraphicsPixmapItem>
#include <QPainter>

class widget_camera_metadata_overlay : public QGraphicsPixmapItem
{
public:
    widget_camera_metadata_overlay(QGraphicsItem *parent = nullptr);
    void setOverlayProperties(int offsetX, int offsetY, double overlaySizeZoom, int overlaySize, int pocketSize, double rotate, int blackPlateRadius);
    void setShowOverlay(bool showOverlay);

protected:
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;

private:
    int m_offsetX;
    int m_offsetY;
    double m_overlaySizeZoom;
    int m_overlaySize;
    int m_pocketSize;
    double m_rotate;
    int m_blackPlateRadius;
    bool m_showOverlay = true;

};

#endif // CUSTOMPIXMAPITEM_H

And this is how i send frames to draw:

    GstAppSinkCallbacks callbacks = { nullptr, nullptr, [](GstAppSink *appsink, gpointer user_data) -> GstFlowReturn {
        return static_cast<WidgetCameraView*>(user_data)->handleNewSample();
    }};
    gst_app_sink_set_callbacks(GST_APP_SINK(m_sink), &callbacks, this, nullptr);

Pipeline:

        pipeline_string = "rtspsrc location=" + m_rtspsrc + " latency=0 ! rtph264depay ! seiextract signal-new-metadata=true name=" +
                          QString::fromStdString(stream_gst_metadata_element_name) + " ! h264parse ! decodebin ! videoconvert ! video/x-raw,format=RGB ! appsink name=sink";

Things I have tried:

  • Displaying stream in QWidget using WinId, but the problem is layout cant be transparent above it.
  • Displaying layout using qml on top of widget, but same problem.
  • qmlglsink/qmlgloverlay for some reason they just aren’t available on windows installation ( I have installed everything )

This is the closest I got to it layout works flawlessly but stream is slowed down.

Thank you in advance

If you want qml(6)glsink/qml(6)gloverlay on Windows, you have to build it yourself. There is also a qml6d3d11sink element that you can build the same way. In order to ship any of the qml elements, one also needs to ship the same version of Qt in your application.

What you are doing there is uploading full video frames to Qt inside Qt’s render loop which is going to be very slow.