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