Qt6中如何在QML中使用自定义QVideoSink展示视频内容
Qt 6 自定义QVideoSink在QML VideoOutput中展示的实现方案
首先明确:VideoOutput的videoSink属性为只读,是指你无法直接替换VideoOutput内部默认创建的QVideoSink实例,你可以通过两种方案实现自定义sink内容的展示:
方案1:转发帧到VideoOutput内置sink(改动最小)
该方案无需修改现有自定义QVideoSink的逻辑,仅需新增帧转发逻辑即可:
- 在C++端将你的自定义sink实例注册到QML上下文,示例(main.cpp中):
// 假设你的自定义sink类名为CustomVideoSink CustomVideoSink *mySink = new CustomVideoSink; engine.rootContext()->setContextProperty("myCustomSink", mySink);
- 在QML中获取
VideoOutput的内置sink,将自定义sink的新帧信号关联到内置sink的帧设置槽:
import QtQuick import QtMultimedia Window { visible: true width: 640 height: 480 VideoOutput { id: videoOutput anchors.fill: parent Component.onCompleted: { // 自定义sink收到新帧时直接转发给VideoOutput的内置sink myCustomSink.videoFrameChanged.connect(videoOutput.videoSink.setVideoFrame) } } }
方案2:适配Qt标准媒体源架构(更规范的实现)
如果希望符合Qt官方媒体流设计规范,可以将帧生产逻辑从QVideoSink子类中拆分,封装为独立的媒体源类:
- 自定义媒体源类继承QObject,新增可写的
videoSink属性:
class CustomVideoSource : public QObject { Q_OBJECT Q_PROPERTY(QVideoSink* videoSink WRITE setVideoSink READ videoSink) public: void setVideoSink(QVideoSink *sink) { m_sink = sink; } QVideoSink* videoSink() const { return m_sink; } // 原往自定义sink送帧的逻辑,改为往绑定的m_sink送帧 void onNewFrameArrived(const QVideoFrame &frame) { if (m_sink) m_sink->setVideoFrame(frame); } private: QVideoSink *m_sink = nullptr; };
- 将自定义媒体源注册到QML环境:
// 注册为QML可实例化类型 qmlRegisterType<CustomVideoSource>("com.mycompany", 1, 0, "CustomVideoSource"); // 也可以直接注册为全局上下文属性 engine.rootContext()->setContextProperty("customSource", new CustomVideoSource);
- QML中直接将自定义源设为VideoOutput的source即可,Qt会自动完成sink的绑定:
import com.mycompany 1.0 VideoOutput { source: customSource anchors.fill: parent }
注意事项
- 跨线程传递
QVideoFrame不需要手动拷贝,Qt会自动处理隐式共享,但要确保帧传递的线程安全 - 如果你的自定义sink包含额外的帧处理逻辑,可以在转发帧前完成处理,再调用
setVideoFrame传给VideoOutput的内置sink
内容的提问来源于stack exchange,提问作者Igor Mironchik
相关产品推荐
相关产品推荐

