diff --git a/cameracontrolwidget.cpp b/cameracontrolwidget.cpp
index 7825924..5bd951f 100644
--- a/cameracontrolwidget.cpp
+++ b/cameracontrolwidget.cpp
@@ -14,17 +14,15 @@ CameraControlWidget::CameraControlWidget(SocketClient* socketClient, QWidget *pa
void CameraControlWidget::setupUI()
{
- QVBoxLayout* mainLayout = new QVBoxLayout(this);
+ auto* mainLayout = new QVBoxLayout(this);
- // Create scroll area for all controls
- QScrollArea* scrollArea = new QScrollArea(this);
+ auto* scrollArea = new QScrollArea(this);
scrollArea->setWidgetResizable(true);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- QWidget* scrollWidget = new QWidget();
- QVBoxLayout* scrollLayout = new QVBoxLayout(scrollWidget);
+ auto* scrollWidget = new QWidget();
+ auto* scrollLayout = new QVBoxLayout(scrollWidget);
- // Add all control groups
scrollLayout->addWidget(createFormatGroup());
scrollLayout->addWidget(createExposureGroup());
scrollLayout->addWidget(createWhiteBalanceGroup());
@@ -36,7 +34,6 @@ void CameraControlWidget::setupUI()
mainLayout->addWidget(scrollArea);
- // Status label at bottom
m_statusLabel = new QLabel("Status: Ready", this);
m_statusLabel->setStyleSheet("QLabel { background-color: #f0f0f0; padding: 5px; border-radius: 3px; }");
mainLayout->addWidget(m_statusLabel);
@@ -46,8 +43,8 @@ void CameraControlWidget::setupUI()
QGroupBox* CameraControlWidget::createFormatGroup()
{
- QGroupBox* groupBox = new QGroupBox("Video Format", this);
- QVBoxLayout* layout = new QVBoxLayout();
+ auto* groupBox = new QGroupBox("Video Format", this);
+ auto* layout = new QVBoxLayout();
m_formatCombo = new QComboBox(this);
m_formatCombo->addItem("1280x720@30fps UYVY (Supported)", "1280,720,30,UYVY");
@@ -69,10 +66,10 @@ QGroupBox* CameraControlWidget::createFormatGroup()
QGroupBox* CameraControlWidget::createExposureGroup()
{
- QGroupBox* groupBox = new QGroupBox("Exposure", this);
- QVBoxLayout* layout = new QVBoxLayout();
+ auto* groupBox = new QGroupBox("Exposure", this);
+ auto* layout = new QVBoxLayout();
- QButtonGroup* exposureGroup = new QButtonGroup(this);
+ auto* exposureGroup = new QButtonGroup(this);
m_exposureAuto = new QRadioButton("Auto", this);
m_exposureManual = new QRadioButton("Manual", this);
m_exposureAuto->setChecked(true);
@@ -82,7 +79,7 @@ QGroupBox* CameraControlWidget::createExposureGroup()
connect(m_exposureAuto, &QRadioButton::toggled, this, &CameraControlWidget::onExposureModeChanged);
- QHBoxLayout* modeLayout = new QHBoxLayout();
+ auto* modeLayout = new QHBoxLayout();
modeLayout->addWidget(m_exposureAuto);
modeLayout->addWidget(m_exposureManual);
@@ -94,7 +91,7 @@ QGroupBox* CameraControlWidget::createExposureGroup()
m_setExposureBtn = new QPushButton("Set Exposure", this);
connect(m_setExposureBtn, &QPushButton::clicked, this, &CameraControlWidget::onSetExposure);
- QFormLayout* formLayout = new QFormLayout();
+ auto* formLayout = new QFormLayout();
formLayout->addRow("Mode:", modeLayout);
formLayout->addRow("Value:", m_exposureValue);
@@ -107,10 +104,10 @@ QGroupBox* CameraControlWidget::createExposureGroup()
QGroupBox* CameraControlWidget::createWhiteBalanceGroup()
{
- QGroupBox* groupBox = new QGroupBox("White Balance", this);
- QVBoxLayout* layout = new QVBoxLayout();
+ auto* groupBox = new QGroupBox("White Balance", this);
+ auto* layout = new QVBoxLayout();
- QButtonGroup* wbGroup = new QButtonGroup(this);
+ auto* wbGroup = new QButtonGroup(this);
m_whiteBalanceAuto = new QRadioButton("Auto", this);
m_whiteBalanceManual = new QRadioButton("Manual", this);
m_whiteBalanceAuto->setChecked(true);
@@ -120,7 +117,7 @@ QGroupBox* CameraControlWidget::createWhiteBalanceGroup()
connect(m_whiteBalanceAuto, &QRadioButton::toggled, this, &CameraControlWidget::onWhiteBalanceModeChanged);
- QHBoxLayout* modeLayout = new QHBoxLayout();
+ auto* modeLayout = new QHBoxLayout();
modeLayout->addWidget(m_whiteBalanceAuto);
modeLayout->addWidget(m_whiteBalanceManual);
@@ -133,7 +130,7 @@ QGroupBox* CameraControlWidget::createWhiteBalanceGroup()
m_setWhiteBalanceBtn = new QPushButton("Set White Balance", this);
connect(m_setWhiteBalanceBtn, &QPushButton::clicked, this, &CameraControlWidget::onSetWhiteBalance);
- QFormLayout* formLayout = new QFormLayout();
+ auto* formLayout = new QFormLayout();
formLayout->addRow("Mode:", modeLayout);
formLayout->addRow("Temperature:", m_whiteBalanceTemp);
@@ -146,8 +143,8 @@ QGroupBox* CameraControlWidget::createWhiteBalanceGroup()
QGroupBox* CameraControlWidget::createImageAdjustmentGroup()
{
- QGroupBox* groupBox = new QGroupBox("Image Adjustments", this);
- QVBoxLayout* layout = new QVBoxLayout();
+ auto* groupBox = new QGroupBox("Image Adjustments", this);
+ auto* layout = new QVBoxLayout();
layout->addWidget(createSliderControl("Brightness (0-255):", 0, 255, 128,
&m_brightnessSlider, &m_brightnessSpinBox));
@@ -180,13 +177,13 @@ QGroupBox* CameraControlWidget::createImageAdjustmentGroup()
QWidget* CameraControlWidget::createSliderControl(const QString& label, int min, int max, int defaultValue,
QSlider** slider, QSpinBox** spinBox)
{
- QWidget* widget = new QWidget(this);
- QVBoxLayout* layout = new QVBoxLayout(widget);
+ auto* widget = new QWidget(this);
+ auto* layout = new QVBoxLayout(widget);
layout->setContentsMargins(0, 5, 0, 5);
- QLabel* titleLabel = new QLabel(label, this);
+ auto* titleLabel = new QLabel(label, this);
- QHBoxLayout* controlLayout = new QHBoxLayout();
+ auto* controlLayout = new QHBoxLayout();
*slider = new QSlider(Qt::Horizontal, this);
(*slider)->setRange(min, max);
@@ -223,9 +220,8 @@ void CameraControlWidget::onGetFormats()
int fps = fmt["framerate"].toInt();
QString format = fmt["format"].toString();
- QString displayText = QString("%1x%2@%3fps %4")
- .arg(width).arg(height).arg(fps).arg(format);
- QString data = QString("%1,%2,%3,%4").arg(width).arg(height).arg(fps).arg(format);
+ QString displayText = QString("%1x%2@%3fps %4").arg(width, height, fps).arg(format);
+ QString data = QString("%1,%2,%3,%4").arg(width, height, fps).arg(format);
m_formatCombo->addItem(displayText, data);
}
diff --git a/gstreamerpipelinewidget.cpp b/gstreamerpipelinewidget.cpp
index 20d1476..6829971 100644
--- a/gstreamerpipelinewidget.cpp
+++ b/gstreamerpipelinewidget.cpp
@@ -16,12 +16,11 @@ GStreamerPipelineWidget::GStreamerPipelineWidget(SocketClient* socketClient, QWi
void GStreamerPipelineWidget::setupUI()
{
- QVBoxLayout* mainLayout = new QVBoxLayout(this);
+ auto* mainLayout = new QVBoxLayout(this);
- QGroupBox* groupBox = new QGroupBox("GStreamer Pipeline", this);
- QVBoxLayout* groupLayout = new QVBoxLayout(groupBox);
+ auto* groupBox = new QGroupBox("GStreamer Pipeline", this);
+ auto* groupLayout = new QVBoxLayout(groupBox);
- // Info label with instructions
m_infoLabel = new QLabel(
"Quick Start: Click 'Quick Start' to automatically configure and start streaming.
"
"Manual: 1. Set video format → 2. Set pipeline → 3. Start stream", this);
@@ -29,27 +28,23 @@ void GStreamerPipelineWidget::setupUI()
m_infoLabel->setWordWrap(true);
groupLayout->addWidget(m_infoLabel);
- // Quick Start button (prominent)
m_quickStartBtn = new QPushButton("⚡ Quick Start (Auto Configure & Stream)", this);
m_quickStartBtn->setStyleSheet("QPushButton { background-color: #4CAF50; color: white; font-weight: bold; padding: 10px; }");
connect(m_quickStartBtn, &QPushButton::clicked, this, &GStreamerPipelineWidget::onQuickStart);
groupLayout->addWidget(m_quickStartBtn);
- // Separator
- QFrame* line = new QFrame(this);
+ auto* line = new QFrame(this);
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
groupLayout->addWidget(line);
- // Format selection
- QLabel* formatLabel = new QLabel("Video Format:", this);
+ auto* formatLabel = new QLabel("Video Format:", this);
m_formatCombo = new QComboBox(this);
m_formatCombo->addItem("1280x720@30fps UYVY (Default/Supported)", "1280,720,30,UYVY");
groupLayout->addWidget(formatLabel);
groupLayout->addWidget(m_formatCombo);
- // Pipeline presets
- QLabel* presetsLabel = new QLabel("Pipeline Presets:", this);
+ auto* presetsLabel = new QLabel("Pipeline Presets:", this);
m_pipelinePresets = new QComboBox(this);
m_pipelinePresets->addItem("MJPEG UDP Stream (Best for raw formats)", "videoconvert ! jpegenc ! rtpjpegpay ! udpsink host=127.0.0.1 port=5000");
m_pipelinePresets->addItem("UDP H.264 Stream (Requires gst-libav)", "videoconvert ! x264enc tune=zerolatency ! rtph264pay ! udpsink host=127.0.0.1 port=5000");
@@ -66,8 +61,7 @@ void GStreamerPipelineWidget::setupUI()
groupLayout->addWidget(presetsLabel);
groupLayout->addWidget(m_pipelinePresets);
- // Pipeline editor
- QLabel* pipelineLabel = new QLabel("Pipeline:", this);
+ auto* pipelineLabel = new QLabel("Pipeline:", this);
m_pipelineEdit = new QTextEdit(this);
m_pipelineEdit->setMaximumHeight(80);
m_pipelineEdit->setPlaceholderText("Enter GStreamer pipeline here...\nExample: videoconvert ! autovideosink");
@@ -75,13 +69,11 @@ void GStreamerPipelineWidget::setupUI()
groupLayout->addWidget(pipelineLabel);
groupLayout->addWidget(m_pipelineEdit);
- // Set pipeline button
m_setPipelineBtn = new QPushButton("Set Pipeline", this);
connect(m_setPipelineBtn, &QPushButton::clicked, this, &GStreamerPipelineWidget::onSetPipeline);
groupLayout->addWidget(m_setPipelineBtn);
- // Stream control buttons
- QHBoxLayout* buttonLayout = new QHBoxLayout();
+ auto* buttonLayout = new QHBoxLayout();
m_startStreamBtn = new QPushButton("Start Stream", this);
m_stopStreamBtn = new QPushButton("Stop Stream", this);
m_getStatusBtn = new QPushButton("Get Status", this);
@@ -95,7 +87,6 @@ void GStreamerPipelineWidget::setupUI()
buttonLayout->addWidget(m_getStatusBtn);
groupLayout->addLayout(buttonLayout);
- // Status label
m_statusLabel = new QLabel("Status: Unknown", this);
m_statusLabel->setStyleSheet("QLabel { background-color: #f0f0f0; padding: 5px; border-radius: 3px; }");
groupLayout->addWidget(m_statusLabel);
@@ -148,7 +139,6 @@ void GStreamerPipelineWidget::onStartStream()
m_socketClient->sendCommand("set_format", formatParams,
[this](const QJsonObject& response) {
- // Now start stream
m_socketClient->sendCommand("start_stream", QJsonObject(),
[this](const QJsonObject& response) {
updateStatus("Streaming started", true);
@@ -213,7 +203,6 @@ void GStreamerPipelineWidget::updateStatus(const QString& status, bool streaming
void GStreamerPipelineWidget::onQuickStart()
{
- // Disable button during process
m_quickStartBtn->setEnabled(false);
m_quickStartBtn->setText("Configuring...");
@@ -306,10 +295,8 @@ void GStreamerPipelineWidget::onFormatsReceived(const QJsonObject& response)
return;
}
- // Clear existing formats
m_formatCombo->clear();
- // Add all available formats
for (const QJsonValue& val : formats) {
QJsonObject fmt = val.toObject();
int width = fmt["width"].toInt();
@@ -317,9 +304,8 @@ void GStreamerPipelineWidget::onFormatsReceived(const QJsonObject& response)
int fps = fmt["framerate"].toInt();
QString format = fmt["format"].toString();
- QString displayText = QString("%1x%2@%3fps %4")
- .arg(width).arg(height).arg(fps).arg(format);
- QString data = QString("%1,%2,%3,%4").arg(width).arg(height).arg(fps).arg(format);
+ QString displayText = QString("%1x%2@%3fps %4").arg(width, height, fps).arg(format);
+ QString data = QString("%1,%2,%3,%4").arg(width, height, fps).arg(format);
m_formatCombo->addItem(displayText, data);
}
diff --git a/mainwindow.cpp b/mainwindow.cpp
index 30b979a..0858a0a 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -24,26 +24,21 @@ MainWindow::~MainWindow()
void MainWindow::setupUI()
{
- // Create socket client
m_socketClient = new SocketClient("/tmp/vizion_control.sock", this);
- // Create widgets
m_videoWidget = new VideoViewerWidget(this);
m_pipelineWidget = new GStreamerPipelineWidget(m_socketClient, this);
m_cameraWidget = new CameraControlWidget(m_socketClient, this);
- // Create tab widget for controls on the right
- QTabWidget* controlTabs = new QTabWidget(this);
+ auto* controlTabs = new QTabWidget(this);
controlTabs->addTab(m_pipelineWidget, "Pipeline Control");
controlTabs->addTab(m_cameraWidget, "Camera Control");
- // Create horizontal splitter: video on left (full height), controls on right
- QSplitter* mainSplitter = new QSplitter(Qt::Horizontal, this);
+ auto* mainSplitter = new QSplitter(Qt::Horizontal, this);
mainSplitter->addWidget(m_videoWidget);
mainSplitter->addWidget(controlTabs);
mainSplitter->setStretchFactor(0, 2); // Video gets more space (2/3)
mainSplitter->setStretchFactor(1, 1); // Controls get less space (1/3)
- // Set as central widget
setCentralWidget(mainSplitter);
}
diff --git a/videoviewerwidget.cpp b/videoviewerwidget.cpp
index 27d24a5..33d97f4 100644
--- a/videoviewerwidget.cpp
+++ b/videoviewerwidget.cpp
@@ -8,16 +8,25 @@
#include
VideoViewerWidget::VideoViewerWidget(QWidget *parent)
- : QWidget(parent), m_pipeline(nullptr), m_appSink(nullptr),
- m_busWatchId(0), m_zoomFactor(1.0)
+ : QWidget(parent),
+ m_scrollArea(nullptr),
+ m_videoDisplay(nullptr),
+ m_startBtn(nullptr),
+ m_stopBtn(nullptr),
+ m_sourceType(nullptr),
+ m_hostEdit(nullptr),
+ m_portEdit(nullptr),
+ m_statusLabel(nullptr),
+ m_zoomSlider(nullptr),
+ m_zoomLabel(nullptr),
+ m_pipeline(nullptr),
+ m_appSink(nullptr),
+ m_zoomFactor(1.0),
+ m_busWatchId(0)
{
- // Register QImage as meta type for signal/slot across threads
- qRegisterMetaType("QImage");
-
initGStreamer();
setupUI();
- // Connect signal for frame display
connect(this, &VideoViewerWidget::newFrameAvailable,
this, &VideoViewerWidget::displayFrame, Qt::QueuedConnection);
}
@@ -34,11 +43,10 @@ void VideoViewerWidget::initGStreamer()
void VideoViewerWidget::setupUI()
{
- QVBoxLayout* mainLayout = new QVBoxLayout(this);
+ auto* mainLayout = new QVBoxLayout(this);
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->setSpacing(5);
- // Video display in scroll area for zoom support
m_scrollArea = new QScrollArea(this);
m_scrollArea->setWidgetResizable(false);
m_scrollArea->setAlignment(Qt::AlignCenter);
@@ -52,8 +60,7 @@ void VideoViewerWidget::setupUI()
m_scrollArea->setWidget(m_videoDisplay);
- // Zoom control
- QHBoxLayout* zoomLayout = new QHBoxLayout();
+ auto* zoomLayout = new QHBoxLayout();
zoomLayout->addWidget(new QLabel("Zoom:", this));
m_zoomSlider = new QSlider(Qt::Horizontal, this);
@@ -70,12 +77,10 @@ void VideoViewerWidget::setupUI()
zoomLayout->addWidget(m_zoomSlider);
zoomLayout->addWidget(m_zoomLabel);
- // Controls
- QGroupBox* controlGroup = new QGroupBox("Viewer Controls", this);
- QVBoxLayout* controlLayout = new QVBoxLayout();
+ auto* controlGroup = new QGroupBox("Viewer Controls", this);
+ auto* controlLayout = new QVBoxLayout();
- // Source type selection
- QHBoxLayout* sourceLayout = new QHBoxLayout();
+ auto* sourceLayout = new QHBoxLayout();
sourceLayout->addWidget(new QLabel("Source Type:", this));
m_sourceType = new QComboBox(this);
m_sourceType->addItem("UDP MJPEG Stream (No plugins needed)", "udp-mjpeg");
@@ -87,15 +92,13 @@ void VideoViewerWidget::setupUI()
this, &VideoViewerWidget::onSourceTypeChanged);
sourceLayout->addWidget(m_sourceType);
- // Host and port
- QFormLayout* formLayout = new QFormLayout();
+ auto* formLayout = new QFormLayout();
m_hostEdit = new QLineEdit("127.0.0.1", this);
m_portEdit = new QLineEdit("5000", this);
formLayout->addRow("Host:", m_hostEdit);
formLayout->addRow("Port:", m_portEdit);
- // Control buttons
- QHBoxLayout* buttonLayout = new QHBoxLayout();
+ auto* buttonLayout = new QHBoxLayout();
m_startBtn = new QPushButton("Start Viewer", this);
m_stopBtn = new QPushButton("Stop Viewer", this);
m_stopBtn->setEnabled(false);
@@ -106,7 +109,6 @@ void VideoViewerWidget::setupUI()
buttonLayout->addWidget(m_startBtn);
buttonLayout->addWidget(m_stopBtn);
- // Status label
m_statusLabel = new QLabel("Status: Stopped", this);
m_statusLabel->setStyleSheet("QLabel { background-color: #f0f0f0; padding: 5px; border-radius: 3px; }");
@@ -116,7 +118,6 @@ void VideoViewerWidget::setupUI()
controlLayout->addWidget(m_statusLabel);
controlGroup->setLayout(controlLayout);
- // Add to main layout: video takes most space, zoom control, then viewer controls at bottom
mainLayout->addWidget(m_scrollArea, 1);
mainLayout->addLayout(zoomLayout);
mainLayout->addWidget(controlGroup);
@@ -124,8 +125,7 @@ void VideoViewerWidget::setupUI()
setLayout(mainLayout);
}
-QString VideoViewerWidget::buildPipelineString()
-{
+QString VideoViewerWidget::buildPipelineString() const {
QString sourceType = m_sourceType->currentData().toString();
QString host = m_hostEdit->text();
QString port = m_portEdit->text();
@@ -136,19 +136,17 @@ QString VideoViewerWidget::buildPipelineString()
QString sinkPipeline = "videoconvert ! video/x-raw,format=RGB ! appsink name=videosink emit-signals=true";
if (sourceType == "udp-mjpeg") {
- pipeline = QString("udpsrc port=%1 ! application/x-rtp,encoding-name=JPEG,payload=26 ! "
- "rtpjpegdepay ! jpegdec ! %2")
- .arg(port).arg(sinkPipeline);
+ pipeline = QString("udpsrc port=%1 ! application/x-rtp,encoding-name=JPEG,payload=26 ! rtpjpegdepay ! jpegdec ! %2")
+ .arg(port, sinkPipeline);
} else if (sourceType == "udp-h264") {
- pipeline = QString("udpsrc port=%1 ! application/x-rtp,encoding-name=H264 ! "
- "rtph264depay ! h264parse ! avdec_h264 ! %2")
- .arg(port).arg(sinkPipeline);
+ pipeline = QString("udpsrc port=%1 ! application/x-rtp,encoding-name=H264 ! rtph264depay ! h264parse ! avdec_h264 ! %2")
+ .arg(port, sinkPipeline);
} else if (sourceType == "tcp") {
pipeline = QString("tcpclientsrc host=%1 port=%2 ! tsdemux ! h264parse ! avdec_h264 ! %3")
- .arg(host).arg(port).arg(sinkPipeline);
+ .arg(host, port, sinkPipeline);
} else if (sourceType == "http") {
pipeline = QString("souphttpsrc location=http://%1:%2 ! multipartdemux ! jpegdec ! %3")
- .arg(host).arg(port).arg(sinkPipeline);
+ .arg(host, port, sinkPipeline);
} else if (sourceType == "test") {
pipeline = QString("videotestsrc ! %1").arg(sinkPipeline);
}
@@ -182,12 +180,10 @@ void VideoViewerWidget::startPipeline()
return;
}
- // Set up bus callback
GstBus* bus = gst_element_get_bus(m_pipeline);
m_busWatchId = gst_bus_add_watch(bus, busCallback, this);
gst_object_unref(bus);
- // Get appsink element and configure it
m_appSink = gst_bin_get_by_name(GST_BIN(m_pipeline), "videosink");
if (!m_appSink) {
m_statusLabel->setText("Status: Failed to get appsink element");
@@ -196,10 +192,9 @@ void VideoViewerWidget::startPipeline()
return;
}
- // Configure appsink
g_object_set(m_appSink, "emit-signals", TRUE, "sync", FALSE, "max-buffers", 1, "drop", TRUE, nullptr);
- // Set callback for new samples - properly initialize all fields
+ // Properly initialize all callback fields
GstAppSinkCallbacks callbacks = { 0 };
callbacks.new_sample = newSampleCallback;
callbacks.eos = nullptr;
@@ -209,7 +204,6 @@ void VideoViewerWidget::startPipeline()
#endif
gst_app_sink_set_callbacks(GST_APP_SINK(m_appSink), &callbacks, this, nullptr);
- // Start playing
GstStateChangeReturn ret = gst_element_set_state(m_pipeline, GST_STATE_PLAYING);
qDebug() << "[VideoViewer] Pipeline state change return:" << ret;
@@ -246,7 +240,6 @@ void VideoViewerWidget::stopPipeline()
m_busWatchId = 0;
}
- // Clear video display and current frame
m_videoDisplay->clear();
m_videoDisplay->setText("");
m_currentFrame = QImage();
@@ -354,7 +347,6 @@ void VideoViewerWidget::onZoomChanged(int value)
m_zoomFactor = value / 100.0;
m_zoomLabel->setText(QString("%1%").arg(value));
- // Re-display the current frame with new zoom factor
if (!m_currentFrame.isNull()) {
displayFrame(m_currentFrame);
}
@@ -377,14 +369,12 @@ GstFlowReturn VideoViewerWidget::newSampleCallback(GstAppSink* appsink, gpointer
return GST_FLOW_ERROR;
}
- // Pull the sample from appsink
GstSample* sample = gst_app_sink_pull_sample(appsink);
if (!sample) {
qDebug() << "[VideoViewer] Callback: Failed to pull sample";
return GST_FLOW_ERROR;
}
- // Get the buffer from the sample
GstBuffer* buffer = gst_sample_get_buffer(sample);
if (!buffer) {
qDebug() << "[VideoViewer] Callback: No buffer in sample";
@@ -392,7 +382,6 @@ GstFlowReturn VideoViewerWidget::newSampleCallback(GstAppSink* appsink, gpointer
return GST_FLOW_ERROR;
}
- // Get the caps to extract width and height
GstCaps* caps = gst_sample_get_caps(sample);
if (!caps) {
qDebug() << "[VideoViewer] Callback: No caps in sample";
@@ -409,7 +398,6 @@ GstFlowReturn VideoViewerWidget::newSampleCallback(GstAppSink* appsink, gpointer
return GST_FLOW_ERROR;
}
- // Map the buffer to access the raw data
GstMapInfo map;
if (!gst_buffer_map(buffer, &map, GST_MAP_READ)) {
qDebug() << "[VideoViewer] Callback: Failed to map buffer";
@@ -417,7 +405,7 @@ GstFlowReturn VideoViewerWidget::newSampleCallback(GstAppSink* appsink, gpointer
return GST_FLOW_ERROR;
}
- // Calculate expected size for RGB888 format
+ // RGB888 format: width * height * 3 bytes
gsize expected_size = width * height * 3;
if (map.size < expected_size) {
qDebug() << "[VideoViewer] Callback: Buffer too small. Expected:" << expected_size << "Got:" << map.size;
@@ -426,14 +414,12 @@ GstFlowReturn VideoViewerWidget::newSampleCallback(GstAppSink* appsink, gpointer
return GST_FLOW_ERROR;
}
- // Create QImage from the RGB data with proper stride
- // QImage::Format_RGB888 expects RGB data
+ // QImage requires RGB data with proper stride (width * 3 bytes per row)
QImage frame(map.data, width, height, width * 3, QImage::Format_RGB888);
// Make a deep copy since the buffer will be unmapped
QImage frameCopy = frame.copy();
- // Unmap and cleanup
gst_buffer_unmap(buffer, &map);
gst_sample_unref(sample);
@@ -465,20 +451,16 @@ void VideoViewerWidget::displayFrame(const QImage& frame)
qDebug() << "[VideoViewer] Frames received:" << frameCount;
}
- // Store current frame for zoom changes
m_currentFrame = frame;
- // Convert QImage to QPixmap
QPixmap pixmap = QPixmap::fromImage(frame);
if (pixmap.isNull()) {
qDebug() << "[VideoViewer] ERROR: Pixmap conversion failed!";
return;
}
- // Calculate target size with zoom factor
QSize targetSize = frame.size() * m_zoomFactor;
- // Scale pixmap with zoom factor
QPixmap scaledPixmap = pixmap.scaled(targetSize,
Qt::KeepAspectRatio,
Qt::SmoothTransformation);
@@ -488,7 +470,6 @@ void VideoViewerWidget::displayFrame(const QImage& frame)
<< "Scaled pixmap:" << scaledPixmap.size();
}
- // Update the label size to match the scaled pixmap
m_videoDisplay->setPixmap(scaledPixmap);
m_videoDisplay->resize(scaledPixmap.size());
m_videoDisplay->update();
diff --git a/videoviewerwidget.h b/videoviewerwidget.h
index 289b394..89f5437 100644
--- a/videoviewerwidget.h
+++ b/videoviewerwidget.h
@@ -18,7 +18,7 @@ class VideoViewerWidget : public QWidget
public:
explicit VideoViewerWidget(QWidget *parent = nullptr);
- ~VideoViewerWidget();
+ ~VideoViewerWidget() override;
signals:
void newFrameAvailable(const QImage& frame);
@@ -36,12 +36,12 @@ private:
void cleanupGStreamer();
void startPipeline();
void stopPipeline();
- QString buildPipelineString();
+ QString buildPipelineString() const;
static gboolean busCallback(GstBus* bus, GstMessage* msg, gpointer data);
static GstFlowReturn newSampleCallback(GstAppSink* appsink, gpointer user_data);
- // UI elements
+ // UI elements (8-byte pointers)
QScrollArea* m_scrollArea;
QLabel* m_videoDisplay;
QPushButton* m_startBtn;
@@ -53,14 +53,18 @@ private:
QSlider* m_zoomSlider;
QLabel* m_zoomLabel;
- // GStreamer elements
+ // GStreamer elements (8-byte pointers)
GstElement* m_pipeline;
GstElement* m_appSink;
+
+ // Zoom factor (8-byte double)
+ double m_zoomFactor;
+
+ // Bus watch ID (4-byte unsigned int)
guint m_busWatchId;
- // Video state
+ // Video state (large object at end)
QImage m_currentFrame;
- double m_zoomFactor;
};
#endif // VIDEOVIEWERWIDGET_H