When I use QMediaPlayer of Qt with C to play a RTSP stream, it always shows frames only after the buffer state is up to 100 frames. This normally make 3~5 seconds delay.
How to disable buffering or set the buffer to zero to deduce the latency? There is nothing I can do with QMediaPlayer about this issue.
Need your help...
The cpp code:
#include "stdafx.h"
#include <QVideoSurfaceFormat>
//#include "Qxtglobalshortcut/QxtGlobalShortcut.h"
#include "qnetworkinterface.h"
#include "AmbaRemoteCam.h"
#include "controls/AliceMessageBox.hpp"
#include "cam_cali/cam_cali.h"
#include "camera/camera.h"
using namespace Cam;
AmbaRemoteCam::AmbaRemoteCam(QWidget* parent)
: QMainWindow(parent)
, m_titleBar(nullptr)
, m_trayIcon(nullptr)
{
// layout
m_mainLayout = new(std::nothrow) QVBoxLayout();
m_mainLayout->setContentsMargins(20, 20, 20, 20);
m_mainLayout->setSpacing(10);
// Settings
m_mainLayout->addWidget(new MLabel(tr("Settings:")));
m_video_view = nullptr;
{
MLabel* label = new MLabel(tr("RTSP Video:"));
m_mediaUrl = new MEditor(CAM_DEFAULT_RTSP);
m_btnConnectRtsp = new QPushButton(tr("Connect"));
m_btnConnectRtsp->setObjectName("normal_button");
m_btnConnectRtsp->setFixedSize(100, 30);
connect(m_btnConnectRtsp, SIGNAL(clicked()), this, SLOT(slot_btnConnectRtsp_Clicked()));
QHBoxLayout* layout0 = new QHBoxLayout();
layout0->setContentsMargins(20, 0, 0, 0);
layout0->setSpacing(10);
layout0->addWidget(label);
layout0->addWidget(m_mediaUrl);
layout0->addWidget(m_btnConnectRtsp);
m_video_view = new QVideoWidget();
m_video_view->setObjectName("video_widget");
m_video_view->setFixedSize(1280, 724);
m_video_view->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
m_player = new QMediaPlayer(/*m_video_view, QMediaPlayer::LowLatency*/);
m_player->setVideoOutput(m_video_view);
connect(m_player, &QMediaPlayer::mediaStatusChanged, this, &AmbaRemoteCam::slot_mediaStateChanged);
connect(m_player, &QMediaPlayer::positionChanged, this, &AmbaRemoteCam::slot_positionChanged);
m_mainLayout->addLayout(layout0);
m_mainLayout->addWidget(m_video_view);
}
m_msgPos = nullptr;
{
QHBoxLayout* layout = new QHBoxLayout();
layout->setSpacing(10);
m_msgStat = new MLabel("");
layout->addWidget(new MLabel(tr("Play State: ")));
layout->addWidget(m_msgStat);
m_msgPos = new MLabel("");
layout->addWidget(new MLabel(tr("Play Pos: ")));
layout->addWidget(m_msgPos);
m_msgRate = new MLabel("");
layout->addWidget(new MLabel(tr("Rate: ")));
layout->addWidget(m_msgRate);
m_msgBufferStatus = new MLabel("");
layout->addWidget(new MLabel(tr("BufferStatus: ")));
layout->addWidget(m_msgBufferStatus);
m_msgError = new MLabel("");
layout->addWidget(new MLabel(tr("Error: ")));
layout->addWidget(m_msgError);
layout->addStretch();
m_mainLayout->addLayout(layout);
}
m_mainLayout->addStretch();
// UI
ui.setupUi(this);
// Set the mainLayout as the root layout
ui.centralWidget->setObjectName("widget_main_window");
ui.centralWidget->setLayout(m_mainLayout);
// windows icon
setWindowIcon(QIcon(":/AmbaRemoteCam/Resources/alice.png"));
retranslateUi();
}
AmbaRemoteCam::~AmbaRemoteCam()
{
}
void AmbaRemoteCam::retranslateUi()
{
//m_fullScreenBtn->setToolTip(tr("Full Screen"));
}
void AmbaRemoteCam::slot_mediaStateChanged(QMediaPlayer::MediaStatus state)
{
const char* MediaStatusString[]=
{
"UnknownMediaStatus",
"NoMedia",
"LoadingMedia",
"LoadedMedia",
"StalledMedia",
"BufferingMedia",
"BufferedMedia",
"EndOfMedia",
"InvalidMedia"
};
printf("slot_mediaStateChanged, MediaStatus:%s\n", MediaStatusString[state]);
m_msgStat->setText(QString(MediaStatusString[state]));
m_msgError->setText(m_player->errorString());
}
void AmbaRemoteCam::slot_positionChanged(qint64 position)
{
printf("slot_positionChanged, position: %ld\n", position);
m_msgPos->setText(QString::number(position));
m_msgRate->setText(QString::number(m_player->playbackRate()));
m_msgBufferStatus->setText(QString::number(m_player->bufferStatus()));
}
void AmbaRemoteCam::slot_btnConnectRtsp_Clicked()
{
m_player->setMedia(QUrl(m_mediaUrl->text()));
m_player->setPlaybackRate(60);
m_player->play();
}
The .h file:
#ifndef AMBAREMOTECAM_H
#define AMBAREMOTECAM_H
#include <QtWidgets/QMainWindow>
#include <QtWidgets>
#include <QLayout>
#include <QToolBar>
#include <QMediaPlayer>
#include <QMediaPlaylist>
#include <QVideoWidget>
#include "ui_AmbaRemoteCam.h"
#include "MEditor.hpp"
#include "mlabel.hpp"
#include "_inl.hpp"
class AmbaRemoteCam : public QMainWindow
{
Q_OBJECT
public:
AmbaRemoteCam(QWidget *parent = 0);
~AmbaRemoteCam();
signals:
public slots:
void slot_mediaStateChanged(QMediaPlayer::MediaStatus state);
void slot_positionChanged(qint64 position);
void slot_btnConnectRtsp_Clicked();
private:
void retranslateUi();
private:
QVBoxLayout* m_mainLayout;
Ui::AmbaRemoteCamClass ui;
QVideoWidget* m_video_view;
QMediaPlayer* m_player;
MEditor* m_mediaUrl;
QPushButton* m_btnConnectRtsp;
MLabel* m_msgStat;
MLabel* m_msgRate;
MLabel* m_msgBufferStatus;
MLabel* m_msgPos;
MLabel* m_msgError;
};
#endif
CodePudding user response:
Finally!
After a lots of seaching and trying, I finally found a kind of weird way to fix this issue:
Using 'setPlaybackRate()' to set playback rate to zero, other then a value bigger than the real fps to prevent the RTSP buffering.
void AmbaRemoteCam::slot_btnConnectRtsp_Clicked()
{
m_player->setMedia(QUrl(m_mediaUrl->text()));
m_player->setPlaybackRate(0);
m_player->play();
}
Nobody would think of using this method to prevent the RTSP buffering.
Hope next version of QMediaPlayer has a more humane interface to fix this issue.