Qt帮助文档对VideoOutput的source属性的描述:
This property holds the source item providing the video frames like MediaPlayer or Camera.
If you are extending your own C++ classes to interoperate with VideoOutput, you can either provide a QObject based class with a mediaObject property that exposes a QMediaObject derived class that has a QVideoRendererControl available, or you can provide a QObject based class with a writable videoSurface property that can accept a QAbstractVideoSurface based class and can follow the correct protocol to deliver QVideoFrames to it.
这里使用的第二种方法。
创建一个继承于QObject的类(class RtspPlayer : public QObject)。
声明QAbstractVideoSurface *videoSurface属性:
Q_PROPERTY(QAbstractVideoSurface *videoSurface READ videoSurface WRITE setVideoSurface)
public:
inline QAbstractVideoSurface *videoSurface() { return m_surface; }
void setVideoSurface(QAbstractVideoSurface *surface);
private:
QAbstractVideoSurface *m_surface;
1
2
3
4
5
6
解码视频,将获得视频帧传递给m_surface:
void RtspPlayer::setVideoSurface(QAbstractVideoSurface *surface)
{
//qDebug() << surface->supportedPixelFormats();
if (m_surface == surface)
return;
if (m_surface && m_surface->isActive()) {
m_surface->stop();
}
m_surface = surface;
if (m_surface)
m_surface->start(m_format);
}
void RtspPlayer::onNewVideoFrameReceived(const QVideoFrame &frame)
{
if (m_surface)
m_surface->present(frame);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
源码:
头文件
#ifndef RTSPPLAYER_H
#define RTSPPLAYER_H
#include
#include
#include
#include
#include “RtspDecoder.h”
class RtspPlayer : public QObject
{
Q_OBJECT
Q_PROPERTY(QAbstractVideoSurface *videoSurface READ videoSurface WRITE setVideoSurface)
Q_PROPERTY(RtspDecoder *decoder READ decoder WRITE setDecoder NOTIFY decoderChanged)
Q_PROPERTY(int width READ width NOTIFY widthChanged)
Q_PROPERTY(int height READ height NOTIFY heightChanged)
public:
explicit RtspPlayer(QObject *parent = nullptr);
~RtspPlayer();
inline QAbstractVideoSurface *videoSurface() { return m_surface; }
void setVideoSurface(QAbstractVideoSurface *surface);
inline RtspDecoder *decoder() const { return m_decoder; }
void setDecoder(RtspDecoder *decoder);
inline int width() const;
inline int height() const;
signals:
void decoderChanged(RtspDecoder *decoder);
void widthChanged(int width);
void heightChanged(int height);
public slots:
void onFrameSizeChanged(int width, int height);
void onNewVideoFrameReceived(const QVideoFrame &frame);
protected:
void setWidth(int width);
void setHeight(int height);
void setSize(int width, int height);
private:
QVideoSurfaceFormat m_format;
QAbstractVideoSurface *m_surface;
RtspDecoder *m_decoder;
};
int RtspPlayer::width() const
{
return m_format.frameSize().width();
}
int RtspPlayer::height() const
{
return m_format.frameSize().height();
}
#endif // RTSPPLAYER_H
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
源文件:
#include “RtspPlayer.h”
#include
#include
}
RtspPlayer::~RtspPlayer()
{
}
void RtspPlayer::setVideoSurface(QAbstractVideoSurface *surface)
{
//qDebug() << surface->supportedPixelFormats();
if (m_surface == surface)
return;
if (m_surface && m_surface->isActive()) {
m_surface->stop();
}
m_surface = surface;
if (m_surface)
m_surface->start(m_format);
}
void RtspPlayer::setDecoder(RtspDecoder *decoder)
{
if (m_decoder == decoder)
return;
if (m_decoder) {
disconnect(m_decoder, SIGNAL(frameSizeChanged(int,int)),
this, SLOT(onFrameSizeChanged(int,int)));
disconnect(m_decoder, SIGNAL(newVideoFrame(QVideoFrame)),
this, SLOT(onNewVideoFrameReceived(QVideoFrame)));
}
if (decoder) {
connect(decoder, SIGNAL(frameSizeChanged(int,int)),
this, SLOT(onFrameSizeChanged(int,int)));
connect(decoder, SIGNAL(newVideoFrame(QVideoFrame)),
this, SLOT(onNewVideoFrameReceived(QVideoFrame)));
onFrameSizeChanged(decoder->width(), decoder->height());
} else {
if (m_surface)
m_surface->stop();
}
m_decoder = decoder;
emit decoderChanged(m_decoder);
}
void RtspPlayer::onFrameSizeChanged(int width, int height)
{
m_format.setFrameSize(width, height);
emit widthChanged(width);
emit heightChanged(height);
if (m_surface)
m_surface->start(m_format);
}
void RtspPlayer::onNewVideoFrameReceived(const QVideoFrame &frame)
{
if (m_surface)
m_surface->present(frame);
}
void RtspPlayer::setWidth(int width)
{
if (this->width() == width)
return;
m_format.setFrameSize(width, this->height());
emit widthChanged(width);
}
void RtspPlayer::setHeight(int height)
{
if (this->height() == height)
return;
m_format.setFrameSize(this->width(), height);
emit heightChanged(height);
}
void RtspPlayer::setSize(int width, int height)
{
m_format.setFrameSize(width, height);
emit widthChanged(width);
emit heightChanged(height);