Qt Qml 中提供了丰盛的多媒体相干的模块:
类型 | 形容 |
---|---|
MediaPlayer | 为场景增加音频/视频播放性能。 |
CaptureSession | 创立一个用于捕捉音频/视频的会话。 |
Camera | 拜访连贯到零碎的相机。 |
AudioInput | 拜访连贯到零碎的音频输出。 |
AudioOutput | 拜访连贯到零碎的音频输入(扬声器、耳机)。 |
VideoOutput | 显示视频内容。 |
MediaRecorder | 记录来自 CaptureSession 的音频/视频。 |
ImageCapture | 从相机中捕获静止图像。 |
Video | 将视频播放性能增加到场景中, 应用 MediaPlayer 和 VideoOutput 类型来提供视频播放性能。 |
想要实现视频客户端,这里只需应用 VideoOutput
和 MediaPlayer
即可。
个别本地播放的简略应用如下:
Rectangle { width: 800 height: 600 color: "black" MediaPlayer { id: player source: "file://video.webm" videoOutput: videoOutput } VideoOutput { id: videoOutput anchors.fill: parent } }
然而这种形式依赖 MediaPlayer
,而 MediaPlayer
依赖零碎 ( 本机平台 ) 提供的编解码器,成果不佳且没有扩展性,因而咱们采纳SkeyePlayerPro
做为后端播放器。
对于SkeyePlayerPro
是视开科技开发和保护的全功能的流媒体播放器,反对 RTSP、RTMP、HTTP、HLS、UDP、RTP、File 等多种流媒体协定播放、反对本地文件播放,反对本地抓拍、本地录像、播放旋转、多屏播放、倍数播放等多种性能个性,外围基于 FFmpeg,稳固、高效、牢靠、可控,反对 Windows、Android、iOS 等多个平台,目前在多家教育、安防、行业型公司,都失去的利用,广受好评!
- 反对高效 4K / 8K 解码。
- 反对 CPU 软解 / GPU 硬解。
- 反对视频如 H.264,H.265,MPEG4,MJPEG。
- API 简略好用且易于集成。
Qt 中集成相当容易,.pro
退出上面命令即可:
#SkeyePlayerPro相干 LIBS += -L$$PWD/lib/Player \ -llibSkeyePlayer \ -llibSkeyePlayerPro INCLUDEPATH += $$PWD/lib/Player/Src \ $$PWD/lib/SkeyePlayer
另一方面,想要在 QML 中播放视频咱们须要本人实现一个提供视频帧的 QML 接口类,有两种办法:
- 提供
QMediaObject
派生类属性,该属性须要具备可用的QVideoRenderControl
,相似于上面:
class MyMediaPlayer : QObject {public: QMediaObject *mediaObject();};
- 基于
QObject
的类提供可写videoSurface
属性,能够承受基于QAbstractVideoSurface
的类,而后传递本人的QVideoFrame
即可,这也正是我应用的办法:
class VideoFrameProvider : public QObject{ Q_OBJECT Q_PROPERTY(QAbstractVideoSurface *videoSurface READ videoSurface WRITE setVideoSurface) Q_PROPERTY(QString videoUrl READ videoUrl WRITE setVideoUrl NOTIFY videoUrlChanged) public: VideoFrameProvider(QObject *parent = nullptr); ~VideoFrameProvider(); QAbstractVideoSurface *videoSurface(); void setVideoSurface(QAbstractVideoSurface *surface); QString videoUrl() const; void setVideoUrl(const QString &url); void setFormat(int width, int heigth, QVideoFrame::PixelFormat pixFormat); signals: void newVideoFrame(const char *frame); void videoUrlChanged(); private slots: void onNewVideoFrameReceived(const char *frame); private: //SkeyePlayerPro提供的回调 static int VideoFrameProvider::playCallback(SKEYE_CALLBACK_TYPE_ENUM callbackType, int channelId, void *userPtr, int mediaType, char *buf, SKEYE_FRAME_INFO *frameInfo); QAbstractVideoSurface *m_surface = nullptr; QVideoSurfaceFormat m_format; QString m_videoUrl; bool m_initFormat = false;}
要害实现,这里省略了一些 SkeyePlayerPro
的初始化和回调等等设置:
VideoFrameProvider::VideoFrameProvider(QObject *parent) : QObject(parent){ connect(this, &VideoFrameProvider::newVideoFrame, this, &VideoFrameProvider::onNewVideoFrameReceived, Qt::QueuedConnection);}QAbstractVideoSurface *VideoFrameProvider::videoSurface(){ return m_surface;}void VideoFrameProvider::setVideoSurface(QAbstractVideoSurface *surface){ if (m_surface && m_surface != surface && m_surface->isActive()) { m_surface->stop(); } m_surface = surface; if (m_surface && m_format.isValid()) { m_format = m_surface->nearestFormat(m_format); m_surface->start(m_format); }}QString VideoFrameProvider::videoUrl() const{ return m_videoUrl;}void VideoFrameProvider::setVideoUrl(const QString &url){ if (m_videoUrl != url) { m_videoUrl = url; emit videoUrlChanged(); }}void VideoFrameProvider::setFormat(int width, int heigth, QVideoFrame::PixelFormat pixFormat){ QVideoSurfaceFormat format(QSize(width, heigth), pixFormat); m_format = format; if (m_surface) { if (m_surface->isActive()) { m_surface->stop(); } m_format = m_surface->nearestFormat(format); m_surface->start(m_format); }}void VideoFrameProvider::onNewVideoFrameReceived(const char *frame){ int size = 0; int width = m_format.frameWidth(); int height = m_format.frameHeight(); if (m_format.pixelFormat() == QVideoFrame::Format_YUV420P) { size = width * height * 3 / 2; } QVideoFrame videoFrame(size, QSize(width, height), width, m_format.pixelFormat()); if (videoFrame.map(QAbstractVideoBuffer::WriteOnly)) { memmove(videoFrame.bits(), frame, size); videoFrame.unmap(); } if (m_surface && m_surface->isActive()) { if (!m_surface->present(videoFrame)) { qDebug() << "VideoFrameProvider Suface Error:" << m_surface->error(); } }}int VideoFrameProvider::playCallback(SKEYE_CALLBACK_TYPE_ENUM callbackType, int channelId, void *userPtr, int mediaType, char *buf, SKEYE_FRAME_INFO *frameInfo){ Q_UNUSED(channelId); VideoFrameProvider *_this = reinterpret_cast<VideoFrameProvider *>(userPtr); if (callbackType == SKEYE_TYPE_DECODE_DATA && mediaType == MEDIA_TYPE_VIDEO) { auto frameWidth = frameInfo->width ; auto frameHeight = frameInfo->height; if (buf) { if (!_this->m_initFormat) { _this->setFormat(frameWidth, frameHeight, QVideoFrame::Format_YUV420P); _this->m_initFormat = true; } emit _this->newVideoFrame(buf); } } return 0;}
最初将下面的 MediaPlayer
替换为 VideoProvider
即可:
Rectangle { width: 800 height: 600 color: "black" VideoFrameProvider { id: provider source: "rtsp://192.168.0.33:8554/channel=1" } VideoOutput { id: videoOutput anchors.fill: parent source: provider } }
对于SkeyeARS
SkeyeARS全景AR加强监视系统, 是视开科技开发的一款基于宽场景多路视频无缝拼接、视频实时加强、监督指标加强显示、指标主动跟踪、视频存储回放、近程数据传输和多通道全景视频同步显示等性能的综合视频AR加强监视系统,广泛应用于智慧交通、智慧城市、智慧机场等大场景智能监控畛域。
具体阐明:http://www.openskeye.cn/web/product/ars