summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDoris Verria <doris.verria@qt.io>2021-12-05 23:44:42 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-12-08 15:32:03 +0000
commit306a07f13d9c72cc89621d317abe7b3cf029105c (patch)
tree2acfe4c37c6bd7366fb3d3549bbea6e5cce8c1ed
parentba9f36c76c2ed42811ed2685daf666cab524f711 (diff)
AVFVideoRenderer: Add frame orientation information from video track
Set video orientation and mirrored flag based on the track's preferred transformation matrix. Fixes: QTBUG-98306 Change-Id: I57e49884408f4f905f982da07eb7eb345764dc31 Reviewed-by: Lars Knoll <lars.knoll@qt.io> (cherry picked from commit 82695e3160f3d2d3198973a24e5480e2ebc1c7d9) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/multimedia/platform/darwin/mediaplayer/avfmediaplayer.mm55
-rw-r--r--src/multimedia/platform/darwin/mediaplayer/avfmediaplayer_p.h8
-rw-r--r--src/multimedia/platform/darwin/mediaplayer/avfvideorenderercontrol.mm12
-rw-r--r--src/multimedia/platform/darwin/mediaplayer/avfvideorenderercontrol_p.h5
4 files changed, 78 insertions, 2 deletions
diff --git a/src/multimedia/platform/darwin/mediaplayer/avfmediaplayer.mm b/src/multimedia/platform/darwin/mediaplayer/avfmediaplayer.mm
index a7dab5e37..0b71880aa 100644
--- a/src/multimedia/platform/darwin/mediaplayer/avfmediaplayer.mm
+++ b/src/multimedia/platform/darwin/mediaplayer/avfmediaplayer.mm
@@ -38,7 +38,6 @@
****************************************************************************/
#include "avfmediaplayer_p.h"
-#include "avfmediaplayer_p.h"
#include "avfvideorenderercontrol_p.h"
#include <private/avfvideosink_p.h>
#include <private/avfmetadata_p.h>
@@ -48,6 +47,7 @@
#include <qpointer.h>
#include <QFileInfo>
+#include <QtCore/qmath.h>
#import <AVFoundation/AVFoundation.h>
@@ -583,6 +583,7 @@ void AVFMediaPlayer::setMedia(const QUrl &content, QIODevice *stream)
setVideoAvailable(false);
setSeekable(false);
m_requestedPosition = -1;
+ orientationChanged(QVideoFrame::Rotation0, false);
Q_EMIT positionChanged(position());
if (m_duration != 0) {
m_duration = 0;
@@ -1116,8 +1117,13 @@ void AVFMediaPlayer::updateTracks()
} else if ([assetTrack.mediaType isEqualToString:AVMediaTypeVideo]) {
qtTrack = QPlatformMediaPlayer::VideoStream;
setVideoAvailable(true);
- if (!m_observer.videoTrack)
+ if (m_observer.videoTrack != track) {
m_observer.videoTrack = track;
+ bool isMirrored = false;
+ QVideoFrame::RotationAngle orientation = QVideoFrame::Rotation0;
+ videoOrientationForAssetTrack(assetTrack, orientation, isMirrored);
+ orientationChanged(orientation, isMirrored);
+ }
}
else if ([assetTrack.mediaType isEqualToString:AVMediaTypeSubtitle]) {
qtTrack = QPlatformMediaPlayer::SubtitleStream;
@@ -1202,3 +1208,48 @@ void AVFMediaPlayer::nativeSizeChanged(QSize size)
return;
m_videoSink->setNativeSize(size);
}
+
+void AVFMediaPlayer::orientationChanged(QVideoFrame::RotationAngle rotation, bool mirrored)
+{
+ if (!m_videoOutput)
+ return;
+
+ m_videoOutput->setVideoRotation(rotation);
+ m_videoOutput->setVideoMirrored(mirrored);
+}
+
+void AVFMediaPlayer::videoOrientationForAssetTrack(AVAssetTrack *videoTrack,
+ QVideoFrame::RotationAngle &angle,
+ bool &mirrored)
+{
+ angle = QVideoFrame::Rotation0;
+ if (videoTrack) {
+ CGAffineTransform transform = videoTrack.preferredTransform;
+ if (CGAffineTransformIsIdentity(transform))
+ return;
+ qreal delta = transform.a * transform.d - transform.b * transform.c;
+ qreal radians = qAtan2(transform.b, transform.a);
+ qreal degrees = qRadiansToDegrees(radians);
+ qreal scaleX = (transform.a/qAbs(transform.a)) * qSqrt(qPow(transform.a, 2) + qPow(transform.c, 2));
+ qreal scaleY = (transform.d/abs(transform.d)) * qSqrt(qPow(transform.b, 2) + qPow(transform.d, 2));
+
+ if (delta < 0.0) { // flipped
+ if (scaleX < 0.0) {
+ // vertical flip
+ degrees = -degrees;
+ } else if (scaleY < 0.0) {
+ // horizontal flip
+ degrees = (180 + (int)degrees) % 360;
+ }
+ mirrored = true;
+ }
+
+ if (qFuzzyCompare(degrees, qreal(90)) || qFuzzyCompare(degrees, qreal(-270))) {
+ angle = QVideoFrame::Rotation270;
+ } else if (qFuzzyCompare(degrees, qreal(-90)) || qFuzzyCompare(degrees, qreal(270))) {
+ angle = QVideoFrame::Rotation90;
+ } else if (qFuzzyCompare(degrees, qreal(180)) || qFuzzyCompare(degrees, qreal(-180))) {
+ angle = QVideoFrame::Rotation180;
+ }
+ }
+}
diff --git a/src/multimedia/platform/darwin/mediaplayer/avfmediaplayer_p.h b/src/multimedia/platform/darwin/mediaplayer/avfmediaplayer_p.h
index 4bd082c1c..348c070ab 100644
--- a/src/multimedia/platform/darwin/mediaplayer/avfmediaplayer_p.h
+++ b/src/multimedia/platform/darwin/mediaplayer/avfmediaplayer_p.h
@@ -60,10 +60,12 @@
#include <private/qplatformmediaplayer_p.h>
#include <QtMultimedia/QMediaPlayer>
+#include <QtMultimedia/QVideoFrame>
Q_FORWARD_DECLARE_OBJC_CLASS(AVAsset);
Q_FORWARD_DECLARE_OBJC_CLASS(AVPlayerItemTrack);
Q_FORWARD_DECLARE_OBJC_CLASS(AVFMediaPlayerObserver);
+Q_FORWARD_DECLARE_OBJC_CLASS(AVAssetTrack);
QT_BEGIN_NAMESPACE
@@ -107,6 +109,10 @@ public:
QMediaMetaData metaData() const override;
+ void videoOrientationForAssetTrack(AVAssetTrack *track,
+ QVideoFrame::RotationAngle &angle,
+ bool &mirrored);
+
public Q_SLOTS:
void setPlaybackRate(qreal rate) override;
void nativeSizeChanged(QSize size);
@@ -151,6 +157,8 @@ private:
void setSeekable(bool seekable);
void resetStream(QIODevice *stream = nullptr);
+ void orientationChanged(QVideoFrame::RotationAngle rotation, bool mirrored);
+
AVFVideoRendererControl *m_videoOutput = nullptr;
AVFVideoSink *m_videoSink = nullptr;
diff --git a/src/multimedia/platform/darwin/mediaplayer/avfvideorenderercontrol.mm b/src/multimedia/platform/darwin/mediaplayer/avfvideorenderercontrol.mm
index 9cee8da3b..e7bf42395 100644
--- a/src/multimedia/platform/darwin/mediaplayer/avfvideorenderercontrol.mm
+++ b/src/multimedia/platform/darwin/mediaplayer/avfvideorenderercontrol.mm
@@ -154,6 +154,16 @@ void AVFVideoRendererControl::setLayer(CALayer *layer)
AVFVideoSinkInterface::setLayer(layer);
}
+void AVFVideoRendererControl::setVideoRotation(QVideoFrame::RotationAngle rotation)
+{
+ m_rotation = rotation;
+}
+
+void AVFVideoRendererControl::setVideoMirrored(bool mirrored)
+{
+ m_mirrored = mirrored;
+}
+
void AVFVideoRendererControl::updateVideoFrame(const CVTimeStamp &ts)
{
Q_UNUSED(ts);
@@ -182,6 +192,8 @@ void AVFVideoRendererControl::updateVideoFrame(const CVTimeStamp &ts)
QVideoFrameFormat format(QSize(width, height), fmt);
frame = QVideoFrame(buffer, format);
+ frame.setRotationAngle(m_rotation);
+ frame.setMirrored(m_mirrored);
m_sink->setVideoFrame(frame);
}
diff --git a/src/multimedia/platform/darwin/mediaplayer/avfvideorenderercontrol_p.h b/src/multimedia/platform/darwin/mediaplayer/avfvideorenderercontrol_p.h
index ce0ec0738..24b5815d7 100644
--- a/src/multimedia/platform/darwin/mediaplayer/avfvideorenderercontrol_p.h
+++ b/src/multimedia/platform/darwin/mediaplayer/avfvideorenderercontrol_p.h
@@ -80,6 +80,9 @@ public:
void reconfigure() override;
void setLayer(CALayer *layer) override;
+ void setVideoRotation(QVideoFrame::RotationAngle);
+ void setVideoMirrored(bool mirrored);
+
void setSubtitleText(const QString &subtitle)
{
m_sink->setSubtitleText(subtitle);
@@ -96,6 +99,8 @@ private:
AVPlayerItemVideoOutput *m_videoOutput = nullptr;
AVPlayerItemLegibleOutput *m_subtitleOutput = nullptr;
SubtitleDelegate *m_subtitleDelegate = nullptr;
+ QVideoFrame::RotationAngle m_rotation = QVideoFrame::Rotation0;
+ bool m_mirrored = false;
};
QT_END_NAMESPACE