Problem with implementing some streaming, QML, CPP
-
How can I implement some classes on cpp side, which can handle camera stream, and then put it something in QML to watch it?
VideoOutput - unavailable in cpp
MediaPlayer - source only by urlHow can I achieve this goal? Any help, please. Any help appreciated even without code. Where should I dig into docs?
-
Hi and welcome to devnet,
Which version of Qt are you using ?
On which OS ? -
Hi. If you need an object to manage rtsp and webcam stream you can use this:
https://github.com/denisgottardello/QtFFmpegPlayerThe object emits some events:
CONNECTION_STATE_CONNECTED,
CONNECTION_STATE_CONNECTED_DATA_RECEIVED,
CONNECTION_STATE_CONNECTING,
CONNECTION_STATE_IDLE,so you can create a machine state to resume the connection after a the remote device disconnection.
The example is based on widgets but, to use it in qml is easy. -
How can I implement some classes on cpp side, which can handle camera stream, and then put it something in QML to watch it?
VideoOutput - unavailable in cpp
MediaPlayer - source only by urlHow can I achieve this goal? Any help, please. Any help appreciated even without code. Where should I dig into docs?
@vgvg this is how you should proceed
On the cpp side, create a new class e.g CameraFilter , that inherits from QAbstractVideoFilter that will return a filter Runnable.
Still on the header create a new class that represent the filter Runnable. That class will inherit from QVideoFilterRunnable. inside the filter runnable class reimplement the run(QVideoFrame *input, const QVideoSurfaceFormat &surfaceFormat, RunFlags flags); function, that will return the current QVideoFrame. So your filter class should be something like this:class MyFilter : public QAbstractVideoFilter {
Q_OBJECT
public:
QVideoFilterRunnable *createFilterRunnable();
~MyFilter();
signals:
private:
};
class MyFilterRunnable : public QVideoFilterRunnable {public:
MyFilterRunnable(MyFilter *creator) {filter = creator;}
QVideoFrame run(QVideoFrame *input, const QVideoSurfaceFormat &surfaceFormat, RunFlags flags);
private:
MyFilter *filter;};
uses qmlRegisterType to register your filter in main.cppNow on the QML side, create a Camera element. Add Also a VideoOutput element. as the source of the VideoOutput set the camera. The VideoOutput has a property called filter. There you can put your custom filter. Something like this.
MyFilter { id:myfilter }Camera
{
id:camera
}
VideoOutput{
width: parent.width - 50
height: parent.height -50
anchors.centerIn: parent
autoOrientation: false
source:camera
id:video
filters: [myfilter]} -
In c++, you'll need to create and expose to QML a QVideoSink.
Here's a overview of how you could do that : https://doc.qt.io/qt-6/qtqml-cppintegration-overview.html
QVideoSink has a
setVideoFramemethod if you want to pass it a custom frame.If you only need to display the frames from a normal camera you don't need that.
-
// Main.qml
import QtCore
import QtMultimedia
import QtQuick
import QtQuick.Controls
import VWC 1.0ApplicationWindow {
width: Screen.width
height: Screen.height
visible: true
title: qsTr("VWC: Virtual Web Camera")Switch { id: toggleCameraSwtich onCheckedChanged: { if (checked) { videoOutput.visible = true Controller.cameraStart() } else { Controller.cameraStop() videoOutput.visible = false } } } VideoOutput { id: videoOutput anchors.fill: parent Component.onCompleted: { Controller.setVideoOutput(videoOutput) } } CameraPermission { id: permissionController Component.onCompleted: { if (permissionController.status !== Qt.PermissionStatus.Granted) { permissionController.request() } } }}
// Controller.h
class Controller : public QObject
{
Q_OBJECT
public:
explicit Controller(QObject *parent = nullptr);Q_INVOKABLE void setVideoOutput(QObject* videoOutput); Q_INVOKABLE void cameraStart(); Q_INVOKABLE void cameraStop();signals:
public slots:
private:
QMediaCaptureSession* captureSession;
QCamera* camera;
};// main.cpp
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);QQmlApplicationEngine engine; Controller* controller = new Controller{&app}; qmlRegisterSingletonInstance("VWC", 1, 0, "Controller", controller); QObject::connect( &engine, &QQmlApplicationEngine::objectCreationFailed, &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.loadFromModule("VWC", "Main"); return app.exec();}
I need to get frames from QCamera in the same time when stream is turned on. How?