VideoOutput + QQuickView::SizeRootObjectToView + Qt::PortraitOrientation
-
I'm trying to preview the front facing camera at maximum resolution in an upright orientation locked to the device's screen. This is using QT 5.5 in a QML application adapted from the qmlvideofilter sample.
I'm using the following C++:
view.setResizeMode( QQuickView::SizeRootObjectToView ); view.reportContentOrientationChange(Qt::PortraitOrientation);
And the VideoOutput + Camera QML shown below (see comments):
Camera { id: camera position: Camera.FrontFace objectName: "CameraObject" } QTRenderGL { id: qtrendergl } VideoOutput { id: output source: camera objectName: "VideoOutput" focus : visible filters: [ infofilter, videofilter ] anchors.fill: parent anchors.centerIn: parent anchors.margins: 0 fillMode: VideoOutput.PreserveAspectFit // Using this C++ for fixed upright orientation: // // QObject* qmlCamera = root->findChild<QObject*>("CameraObject"); // QCamera* camera = qvariant_cast<QCamera*>(qmlCamera->property("mediaObject")); // QCameraInfo cameraInfo(*camera); // qmlVideoOutput->setProperty("rotation", cameraInfo.orientation()); // rotation: 0 // Enabling autoOrientation in combination with // // fillMode: VideoOutput.PreserveAspectFit // // provides the stretch to fit behavior I am looking for, except I don't want the // varying device orientation landscale/portrait switching. When I specify an // upright rotation manually (in C++ or QML) then the VideoOutput does not stretch // to fit the screen (i.e., no VideoOutput.PreserveAspectFit) properly. // // autoOrientation: true }
For configuration A (
autoOrientation: true
+fillMode.VideoOutput.PreserveAspectFit
) I get the behavior I'm looking for when the phone is upright, but the screen switches to landscape orientation when I rotate the phone, which I don't want.When I use configuration B, basically
fillMode.VideoOutput.PreserveAspectFit
with a manually specified upright camera rotation, such as QMLrotation: 90
or C++qmlVideoOutput->setProperty("rotation", cameraInfo.orientation())
andview.reportContentOrientationChange(Qt::PortraitOrientation)
then I get the upright camera output and locked screen orientation I want, but I don't see the aspect ratio preserving stretch.Here is an example of the output for configuration A.
Here is an example of the output for configuration B (note the wide border).
I feel I probably need to either: 1) find a QT way to override VideoOutput in QML/C++ (inheritance, signal/slot); or 2) leave the QML Camera + VideOutput (with filter) configured as is, since it is mostly working, but disable the final rendering and draw the frames directly in OpenGL using my own class via a
beforeRendering()
signal. The later option would have some advantages, since it would allow me to compensate for arbitrary geometric changes to the outputQVideoFrame
texture in my custom OpenGLVideoFilterRunnable
without breaking the stretching behavior . (Any approach that gives me the desired output would be fine.) It seems the direct drawing could be accomplished using another class registered in QML and configured for thebeforeRendering()
signal like this:connect(window(), SIGNAL(beforeRendering()), m_renderer, SLOT(paint()), Qt::DirectConnection);
if I can get my output
QVideoFrame
to the new rendering class. I grabbed some code as a place holder for this from the QT squircle sample in my project here. That still needs theQTVideoFrame
input and a way to disable the defaultVideoOutput
rendering. Any hints on this approach, or a fix for the defaultVideoOutput
rendering would be greatly appreciated. The full sample (adapted from the qmlvideofilter) is available on github here. -
Did you try scaling the video output when defining the rotation ?
VideoOutput { id: viewfinder anchors.fill : parent source: camera rotation : 90 transformOrigin: Item.Center fillMode : VideoOutput.PreserveAspectCrop scale : height/width }
One could also use the "orientation" property of the VideoOutput.
-
@Charby said:
scale : height/width
Excellent.
scale : height/width
is exactly what I needed. Thanks. Somehow I missed that (probably basic QML) property in my search. I'll need to set this adaptively in order to deal with different phones. The following C++ variation gives me exactly the fixed orientation and scale I wanted (I'm guessing this could also be done in QML) :QQuickItem* root = view.rootObject(); QObject* qmlCamera = root->findChild<QObject*>("CameraObject"); assert(qmlCamera != nullptr); QCamera* camera = qvariant_cast<QCamera*>(qmlCamera->property("mediaObject")); assert(camera != nullptr); QObject * qmlVideoOutput = root->findChild<QObject*>("VideoOutput"); assert(qmlVideoOutput); const QCameraInfo cameraInfo(*camera); const bool hasTranspose = (cameraInfo.orientation() / 90) % 2; const auto &resolution = camera->viewfinderSettings().resolution(); double scale = hasTranspose ? double(resolution.width())/resolution.height() : 1.0; qmlVideoOutput->setProperty("scale", scale); qmlVideoOutput->setProperty("rotation", cameraInfo.orientation());
-
Glad this helped !
You are right, this would be achieved in QML (which would keep the C++ backend agnostic of the UI which is more in line with QtQuick I think...)I think something similar would go in QML :
Camera { id: camera } VideoOutput { property bool hasTranspose : (camera.orientation / 90) % 2 anchors.fill : parent source: camera rotation : camera.orientation transformOrigin: Item.Center fillMode : VideoOutput.PreserveAspectCrop scale : hasTranspose ? camera.viewfinder.resolution.height / camera.viewfinder.resolution.width : 1.0 }
Maybe the following could also be satisfactory :
Camera { id: camera } VideoOutput { anchors.fill : parent source: camera orientation: camera.orientation }
-
Even better (and much cleaner). After inverting the
-camera.orientation
it works beautifully. Thanks again.VideoOutput { id: output source: camera objectName: "VideoOutput" filters: [ infofilter, videofilter ] anchors.fill: parent orientation: -camera.orientation }
-
@dhirvonen said:
@Charby said:
scale : height/width
Excellent.
scale : height/width
is exactly what I needed. Thanks. Somehow I missed that (probably basic QML) property in my search.Actually I can't find this part in documentation too. There is no
scale
property inVideoOutput
: http://doc.qt.io/qt-5/qml-qtmultimedia-videooutput.html In fact I know thatVideoOutput
inherits fromQQuickItem
: https://github.com/hunter-packages/Qt/blob/84a5846a20da62e2e2c73c1218927f8746c42de6/qtmultimedia/src/multimedia/qtmultimediaquicktools_headers/qdeclarativevideooutput_p.h#L54QQuickItem
hasscale
property: http://doc.qt.io/qt-5/qquickitem.html#scale-prop but I don't seeheight/width
. -
@Charby said:
"height/width" is not a property name but just height divided by width.
Okay, I see. Thanks for clarification. So the only one issue I see left here is that there is no such inherited members shown in documentation:
- VideoOutput (no scale member): http://doc.qt.io/qt-5/qml-qtmultimedia-videooutput-members.html
- Video (scale member shown): http://doc.qt.io/qt-5/qml-qtmultimedia-video-members.html
-
@dhirvonen said in VideoOutput + QQuickView::SizeRootObjectToView + Qt::PortraitOrientation:
Even better (and much cleaner). After inverting the
-camera.orientation
it works beautifully. Thanks again.VideoOutput { id: output source: camera objectName: "VideoOutput" filters: [ infofilter, videofilter ] anchors.fill: parent orientation: -camera.orientation }
Hi Mr,
I am having a similar project of yours, but do not understand the objectName property my VideoOutput does, is it because I use Qt5.15?objectName: "VideoOutput"
Thanks!