c++ - Qt::QMediaPlayer:如何禁用帧缓冲以减少 RTSP 流延迟或延迟?
问题描述
当我使用 Qt 的 QMediaPlayer 和 C++ 播放 RTSP 流时,它总是仅在缓冲区状态达到 100 帧后才显示帧。这通常会延迟 3~5 秒。
如何禁用缓冲或将缓冲区设置为零以减少延迟?对于这个问题,我对 QMediaPlayer 无能为力。
需要你的帮助...
cpp代码:
#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();
}
.h 文件:
#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
解决方案
最后!
经过大量的搜索和尝试,我终于找到了一种奇怪的方法来解决这个问题:
使用 'setPlaybackRate()' 将播放速率设置为零,然后设置一个大于实际 fps 的值以防止 RTSP 缓冲。
void AmbaRemoteCam::slot_btnConnectRtsp_Clicked()
{
m_player->setMedia(QUrl(m_mediaUrl->text()));
m_player->setPlaybackRate(0);
m_player->play();
}
没有人会想到使用这种方法来防止 RTSP 缓冲。
希望下一版 QMediaPlayer 有更人性化的界面来解决这个问题。
推荐阅读
- microsoft-graph-api - Microsoft Graph API 站点搜索返回已删除的站点
- c - C中的赋值混淆
- kotlin - Stopping an infinite flow
- python - 带有'datetime.date'的pandas Dateframe中的TypeError
- html - 为什么在chrome浏览器中的CSS文件有问题?
- node.js - 部署 AWS Lambda S3 教程代码时出错
- google-cloud-platform - 如何查看或列出数据流作业 VPC/网络?
- java - Android资源链接失败AAPT:错误:写入失败
- linux - ARM Beaglebone black 的交叉编译器错误
- flutter - 使用 http 请求获取嵌套 Json 返回 null