Skip to content

Commit

Permalink
apply rotation from video stream
Browse files Browse the repository at this point in the history
  • Loading branch information
wang-bin committed Jun 27, 2017
1 parent 75c07e5 commit 00f5d13
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 36 deletions.
21 changes: 11 additions & 10 deletions qml/QQuickItemRenderer.cpp
Original file line number Diff line number Diff line change
@@ -1,6 1,6 @@
/******************************************************************************
QtAV: Multimedia framework based on Qt and FFmpeg
Copyright (C) 2012-2016 Wang Bin <[email protected]>
Copyright (C) 2012-2017 Wang Bin <[email protected]>
theoribeiro <[email protected]>
* This file is part of QtAV (from 2013)
Expand Down Expand Up @@ -194,10 194,10 @@ QPointF QQuickItemRenderer::mapPointToItem(const QPointF &point) const
{
if (videoFrameSize().isEmpty())
return QPointF();

DPTR_D(const QQuickItemRenderer);
// Just normalize and use that function
// m_nativeSize is transposed in some orientations
if (orientation()%180 == 0)
if (d.rotation()%180 == 0)
return mapNormalizedPointToItem(QPointF(point.x() / videoFrameSize().width(), point.y() / videoFrameSize().height()));
else
return mapNormalizedPointToItem(QPointF(point.x() / videoFrameSize().height(), point.y() / videoFrameSize().width()));
Expand All @@ -213,15 213,16 @@ QPointF QQuickItemRenderer::mapNormalizedPointToItem(const QPointF &point) const
{
qreal dx = point.x();
qreal dy = point.y();
if (orientation()%180 == 0) {
DPTR_D(const QQuickItemRenderer);
if (d.rotation()%180 == 0) {
dx *= contentRect().width();
dy *= contentRect().height();
} else {
dx *= contentRect().height();
dy *= contentRect().width();
}

switch (orientation()) {
switch (d.rotation()) {
case 0:
default:
return contentRect().topLeft() QPointF(dx, dy);
Expand All @@ -243,7 244,7 @@ QRectF QQuickItemRenderer::mapNormalizedRectToItem(const QRectF &rectangle) cons
QPointF QQuickItemRenderer::mapPointToSource(const QPointF &point) const
{
QPointF norm = mapPointToSourceNormalized(point);
if (orientation()%180 == 0)
if (d_func().rotation()%180 == 0)
return QPointF(norm.x() * videoFrameSize().width(), norm.y() * videoFrameSize().height());
else
return QPointF(norm.x() * videoFrameSize().height(), norm.y() * videoFrameSize().width());
Expand All @@ -263,7 264,7 @@ QPointF QQuickItemRenderer::mapPointToSourceNormalized(const QPointF &point) con
// Normalize the item source point
qreal nx = (point.x() - contentRect().x()) / contentRect().width();
qreal ny = (point.y() - contentRect().y()) / contentRect().height();
switch (orientation()) {
switch (d_func().rotation()) {
case 0:
default:
return QPointF(nx, ny);
Expand Down Expand Up @@ -340,7 341,7 @@ void QQuickItemRenderer::drawFrame()
if (d.frame_changed)
sgvn->setCurrentFrame(d.video_frame);
d.frame_changed = false;
sgvn->setTexturedRectGeometry(d.out_rect, normalizedROI(), d.orientation);
sgvn->setTexturedRectGeometry(d.out_rect, normalizedROI(), d.rotation());
return;
}
if (!d.frame_changed) {
Expand All @@ -357,9 358,9 @@ void QQuickItemRenderer::drawFrame()
if (d.texture)
delete d.texture;

if (d.orientation == 0) {
if (d.rotation() == 0) {
d.texture = window()->createTextureFromImage(d.image);
} else if (d.orientation == 180) {
} else if (d.rotation() == 180) {
d.texture = window()->createTextureFromImage(d.image.mirrored(true, true));
}
static_cast<QSGSimpleTextureNode*>(d.node)->setTexture(d.texture);
Expand Down
16 changes: 8 additions & 8 deletions qml/QuickFBORenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 77,10 @@ class QuickFBORendererPrivate : public VideoRendererPrivate
void setupAspectRatio() { //TODO: call when out_rect, renderer_size, orientation changed
matrix.setToIdentity();
matrix.scale((GLfloat)out_rect.width()/(GLfloat)renderer_width, (GLfloat)out_rect.height()/(GLfloat)renderer_height, 1);
if (orientation)
matrix.rotate(orientation, 0, 0, 1); // Z axis
if (rotation())
matrix.rotate(rotation(), 0, 0, 1); // Z axis
// FIXME: why x/y is mirrored?
if (orientation%180)
if (rotation()%180)
matrix.scale(-1, 1);
else
matrix.scale(1, -1);
Expand Down Expand Up @@ -190,7 190,7 @@ QPointF QuickFBORenderer::mapPointToItem(const QPointF &point) const

// Just normalize and use that function
// m_nativeSize is transposed in some orientations
if (orientation()%180 == 0)
if (d_func().rotation()%180 == 0)
return mapNormalizedPointToItem(QPointF(point.x() / videoFrameSize().width(), point.y() / videoFrameSize().height()));
else
return mapNormalizedPointToItem(QPointF(point.x() / videoFrameSize().height(), point.y() / videoFrameSize().width()));
Expand All @@ -206,15 206,15 @@ QPointF QuickFBORenderer::mapNormalizedPointToItem(const QPointF &point) const
{
qreal dx = point.x();
qreal dy = point.y();
if (orientation()%180 == 0) {
if (d_func().rotation()%180 == 0) {
dx *= contentRect().width();
dy *= contentRect().height();
} else {
dx *= contentRect().height();
dy *= contentRect().width();
}

switch (orientation()) {
switch (d_func().rotation()) {
case 0:
default:
return contentRect().topLeft() QPointF(dx, dy);
Expand All @@ -236,7 236,7 @@ QRectF QuickFBORenderer::mapNormalizedRectToItem(const QRectF &rectangle) const
QPointF QuickFBORenderer::mapPointToSource(const QPointF &point) const
{
QPointF norm = mapPointToSourceNormalized(point);
if (orientation()%180 == 0)
if (d_func().rotation()%180 == 0)
return QPointF(norm.x() * videoFrameSize().width(), norm.y() * videoFrameSize().height());
else
return QPointF(norm.x() * videoFrameSize().height(), norm.y() * videoFrameSize().width());
Expand All @@ -256,7 256,7 @@ QPointF QuickFBORenderer::mapPointToSourceNormalized(const QPointF &point) const
// Normalize the item source point
qreal nx = (point.x() - contentRect().x()) / contentRect().width();
qreal ny = (point.y() - contentRect().y()) / contentRect().height();
switch (orientation()) {
switch (d_func().rotation()) {
case 0:
default:
return QPointF(nx, ny);
Expand Down
21 changes: 16 additions & 5 deletions src/QtAV/private/VideoRenderer_p.h
Original file line number Diff line number Diff line change
@@ -1,6 1,6 @@
/******************************************************************************
QtAV: Media play library based on Qt and FFmpeg
Copyright (C) 2012-2016 Wang Bin <[email protected]>
Copyright (C) 2012-2017 Wang Bin <[email protected]>
* This file is part of QtAV
Expand Down Expand Up @@ -28,7 28,7 @@
#include <QtCore/QRect>
#include <QtAV/VideoFrame.h>
#include <QtGui/QColor>

#include "QtAV/Statistics.h"
/*TODO:
* Region of Interest(ROI)
* use matrix to compute out rect, mapped point etc
Expand All @@ -54,14 54,14 @@ class Q_AV_PRIVATE_EXPORT VideoRendererPrivate : public AVOutputPrivate
, out_aspect_ratio_mode(VideoRenderer::VideoAspectRatio)
, out_aspect_ratio(0)
, quality(VideoRenderer::QualityBest)
, orientation(0)
, preferred_format(VideoFormat::Format_RGB32)
, force_preferred(false)
, brightness(0)
, contrast(0)
, hue(0)
, saturation(0)
, bg_color(0, 0, 0)
, orientation(0)
{
//conv.setInFormat(PIX_FMT_YUV420P);
//conv.setOutFormat(PIX_FMT_BGR32); //TODO: why not RGB32?
Expand All @@ -79,7 79,11 @@ class Q_AV_PRIVATE_EXPORT VideoRendererPrivate : public AVOutputPrivate
return out_rect0 != out_rect;
}
// dar: displayed aspect ratio in video renderer orientation
const qreal dar = (orientation % 180) ? 1.0/outAspectRatio : outAspectRatio;
int rotate = orientation;
if (statistics) {
rotate = int(statistics->video_only.rotate);
}
const qreal dar = (rotate % 180) ? 1.0/outAspectRatio : outAspectRatio;
//qDebug("out rect: %f %dx%d ==>", out_aspect_ratio, out_rect.width(), out_rect.height());
if (rendererAspectRatio >= dar) { //equals to original video aspect ratio here, also equals to out ratio
//renderer is too wide, use renderer's height, horizonal align center
Expand All @@ -97,6 101,11 @@ class Q_AV_PRIVATE_EXPORT VideoRendererPrivate : public AVOutputPrivate
return out_rect0 != out_rect;
}
virtual void setupQuality() {}
int rotation() const {
if (!statistics)
return orientation;
return statistics->video_only.rotate orientation;
}

//draw background when necessary, for example, renderer is resized. Then set to false
bool update_background;
Expand All @@ -114,14 123,16 @@ class Q_AV_PRIVATE_EXPORT VideoRendererPrivate : public AVOutputPrivate
//out_rect: the displayed video frame out_rect in the renderer
QRect out_rect; //TODO: out_out_rect
QRectF roi;
int orientation;

VideoFrame video_frame;
VideoFormat::PixelFormat preferred_format;
bool force_preferred;

qreal brightness, contrast, hue, saturation;
QColor bg_color;
private:
int orientation;
friend class VideoRenderer;
};

} //namespace QtAV
Expand Down
6 changes: 3 additions & 3 deletions src/output/video/OpenGLRendererBase.cpp
Original file line number Diff line number Diff line change
@@ -1,6 1,6 @@
/******************************************************************************
QtAV: Multimedia framework based on Qt and FFmpeg
Copyright (C) 2012-2016 Wang Bin <[email protected]>
Copyright (C) 2012-2017 Wang Bin <[email protected]>
* This file is part of QtAV (from 2014)
Expand Down Expand Up @@ -49,8 49,8 @@ void OpenGLRendererBasePrivate::setupAspectRatio()
{
matrix.setToIdentity();
matrix.scale((GLfloat)out_rect.width()/(GLfloat)renderer_width, (GLfloat)out_rect.height()/(GLfloat)renderer_height, 1);
if (orientation)
matrix.rotate(orientation, 0, 0, 1); // Z axis
if (rotation())
matrix.rotate(rotation(), 0, 0, 1); // Z axis
}

OpenGLRendererBase::OpenGLRendererBase(OpenGLRendererBasePrivate &d)
Expand Down
8 changes: 4 additions & 4 deletions src/output/video/QPainterRenderer.cpp
Original file line number Diff line number Diff line change
@@ -1,6 1,6 @@
/******************************************************************************
QtAV: Multimedia framework based on Qt and FFmpeg
Copyright (C) 2012-2016 Wang Bin <[email protected]>
Copyright (C) 2012-2017 Wang Bin <[email protected]>
* This file is part of QtAV
Expand Down Expand Up @@ -100,7 100,7 @@ void QPainterRenderer::drawFrame()
if (d.pixmap.isNull())
return;
QRect roi = realROI();
if (orientation() == 0) {
if (d.rotation() == 0) {
//assume that the image data is already scaled to out_size(NOT renderer size!)
if (roi.size() == d.out_rect.size()) {
d.painter->drawPixmap(d.out_rect.topLeft(), d.pixmap, roi);
Expand All @@ -116,11 116,11 @@ void QPainterRenderer::drawFrame()
d.painter->save();
d.painter->translate(rendererWidth()/2, rendererHeight()/2);
// TODO: why rotate then scale gives wrong result?
if (orientation() % 180)
if (d.rotation() % 180)
d.painter->scale((qreal)d.out_rect.width()/(qreal)rendererHeight(), (qreal)d.out_rect.height()/(qreal)rendererWidth());
else
d.painter->scale((qreal)d.out_rect.width()/(qreal)rendererWidth(), (qreal)d.out_rect.height()/(qreal)rendererHeight());
d.painter->rotate(orientation());
d.painter->rotate(d.rotation());
d.painter->translate(-rendererWidth()/2, -rendererHeight()/2);
d.painter->drawPixmap(QRect(0, 0, rendererWidth(), rendererHeight()), d.pixmap, roi);
d.painter->restore();
Expand Down
8 changes: 5 additions & 3 deletions src/output/video/VideoRenderer.cpp
Original file line number Diff line number Diff line change
@@ -1,6 1,6 @@
/******************************************************************************
QtAV: Multimedia framework based on Qt and FFmpeg
Copyright (C) 2012-2016 Wang Bin <[email protected]>
Copyright (C) 2012-2017 Wang Bin <[email protected]>
* This file is part of QtAV
Expand Down Expand Up @@ -288,11 288,11 @@ int VideoRenderer::rendererHeight() const

void VideoRenderer::setOrientation(int value)
{
DPTR_D(VideoRenderer);
// currently only supports a multiple of 90
value = (value 360) % 360;
if (value % 90)
return;
DPTR_D(VideoRenderer);
if (d.orientation == value)
return;
int old = orientation();
Expand All @@ -312,7 312,8 @@ void VideoRenderer::setOrientation(int value)

int VideoRenderer::orientation() const
{
return d_func().orientation;
DPTR_D(const VideoRenderer);
return d.orientation;
}

// only qpainter and opengl based renderers support orientation.
Expand Down Expand Up @@ -505,6 506,7 @@ void VideoRenderer::handlePaintEvent()
*/
if (d.video_frame.isValid()) {
drawFrame();
//qDebug("render elapsed: %lld", et.elapsed());
if (d.statistics) {
d.statistics->video_only.frameDisplayed(d.video_frame.timestamp());
d.statistics->video.current_time = QTime(0, 0, 0).addMSecs(int(d.video_frame.timestamp() * 1000.0));
Expand Down
6 changes: 3 additions & 3 deletions widgets/GraphicsItemRenderer.cpp
Original file line number Diff line number Diff line change
@@ -1,6 1,6 @@
/******************************************************************************
QtAV: Multimedia framework based on Qt and FFmpeg
Copyright (C) 2012-2016 Wang Bin <[email protected]>
Copyright (C) 2012-2017 Wang Bin <[email protected]>
* This file is part of QtAV
Expand Down Expand Up @@ -51,8 51,8 @@ class GraphicsItemRendererPrivate : public QPainterRendererPrivate
void setupAspectRatio() {
matrix.setToIdentity();
matrix.scale((GLfloat)out_rect.width()/(GLfloat)renderer_width, (GLfloat)out_rect.height()/(GLfloat)renderer_height, 1);
if (orientation)
matrix.rotate(orientation, 0, 0, 1); // Z axis
if (rotation())
matrix.rotate(rotation(), 0, 0, 1); // Z axis
}
// return true if opengl is enabled and context is ready. may called by non-rendering thread
bool checkGL() {
Expand Down

0 comments on commit 00f5d13

Please sign in to comment.