Browse Source

Merge pull request #6108

iphydf (1):
      chore(videosurface): Use UNIX line endings.
reviewable/pr6117/r3
sudden6 5 years ago
parent
commit
153b9327f8
No known key found for this signature in database
GPG Key ID: 279509B499E032B9
  1. 484
      src/video/videosurface.cpp
  2. 150
      src/video/videosurface.h

484
src/video/videosurface.cpp

@ -1,242 +1,242 @@
/* /*
Copyright © 2014-2019 by The qTox Project Contributors Copyright © 2014-2019 by The qTox Project Contributors
This file is part of qTox, a Qt-based graphical interface for Tox. This file is part of qTox, a Qt-based graphical interface for Tox.
qTox is libre software: you can redistribute it and/or modify qTox is libre software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
qTox is distributed in the hope that it will be useful, qTox is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with qTox. If not, see <http://www.gnu.org/licenses/>. along with qTox. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "videosurface.h" #include "videosurface.h"
#include "src/core/core.h" #include "src/core/core.h"
#include "src/model/friend.h" #include "src/model/friend.h"
#include "src/friendlist.h" #include "src/friendlist.h"
#include "src/persistence/settings.h" #include "src/persistence/settings.h"
#include "src/video/videoframe.h" #include "src/video/videoframe.h"
#include "src/widget/friendwidget.h" #include "src/widget/friendwidget.h"
#include "src/widget/style.h" #include "src/widget/style.h"
#include <QDebug> #include <QDebug>
#include <QLabel> #include <QLabel>
#include <QPainter> #include <QPainter>
/** /**
* @var std::atomic_bool VideoSurface::frameLock * @var std::atomic_bool VideoSurface::frameLock
* @brief Fast lock for lastFrame. * @brief Fast lock for lastFrame.
*/ */
float getSizeRatio(const QSize size) float getSizeRatio(const QSize size)
{ {
return size.width() / static_cast<float>(size.height()); return size.width() / static_cast<float>(size.height());
} }
VideoSurface::VideoSurface(const QPixmap& avatar, QWidget* parent, bool expanding) VideoSurface::VideoSurface(const QPixmap& avatar, QWidget* parent, bool expanding)
: QWidget{parent} : QWidget{parent}
, source{nullptr} , source{nullptr}
, frameLock{false} , frameLock{false}
, hasSubscribed{0} , hasSubscribed{0}
, avatar{avatar} , avatar{avatar}
, ratio{1.0f} , ratio{1.0f}
, expanding{expanding} , expanding{expanding}
{ {
recalulateBounds(); recalulateBounds();
} }
VideoSurface::VideoSurface(const QPixmap& avatar, VideoSource* source, QWidget* parent) VideoSurface::VideoSurface(const QPixmap& avatar, VideoSource* source, QWidget* parent)
: VideoSurface(avatar, parent) : VideoSurface(avatar, parent)
{ {
setSource(source); setSource(source);
} }
VideoSurface::~VideoSurface() VideoSurface::~VideoSurface()
{ {
unsubscribe(); unsubscribe();
} }
bool VideoSurface::isExpanding() const bool VideoSurface::isExpanding() const
{ {
return expanding; return expanding;
} }
/** /**
* @brief Update source. * @brief Update source.
* @note nullptr is a valid option. * @note nullptr is a valid option.
* @param src source to set. * @param src source to set.
* *
* Unsubscribe from old source and subscribe to new. * Unsubscribe from old source and subscribe to new.
*/ */
void VideoSurface::setSource(VideoSource* src) void VideoSurface::setSource(VideoSource* src)
{ {
if (source == src) if (source == src)
return; return;
unsubscribe(); unsubscribe();
source = src; source = src;
subscribe(); subscribe();
} }
QRect VideoSurface::getBoundingRect() const QRect VideoSurface::getBoundingRect() const
{ {
QRect bRect = boundingRect; QRect bRect = boundingRect;
bRect.setBottomRight(QPoint(boundingRect.bottom() + 1, boundingRect.right() + 1)); bRect.setBottomRight(QPoint(boundingRect.bottom() + 1, boundingRect.right() + 1));
return boundingRect; return boundingRect;
} }
float VideoSurface::getRatio() const float VideoSurface::getRatio() const
{ {
return ratio; return ratio;
} }
void VideoSurface::setAvatar(const QPixmap& pixmap) void VideoSurface::setAvatar(const QPixmap& pixmap)
{ {
avatar = pixmap; avatar = pixmap;
update(); update();
} }
QPixmap VideoSurface::getAvatar() const QPixmap VideoSurface::getAvatar() const
{ {
return avatar; return avatar;
} }
void VideoSurface::subscribe() void VideoSurface::subscribe()
{ {
if (source && hasSubscribed++ == 0) { if (source && hasSubscribed++ == 0) {
source->subscribe(); source->subscribe();
connect(source, &VideoSource::frameAvailable, this, &VideoSurface::onNewFrameAvailable); connect(source, &VideoSource::frameAvailable, this, &VideoSurface::onNewFrameAvailable);
connect(source, &VideoSource::sourceStopped, this, &VideoSurface::onSourceStopped); connect(source, &VideoSource::sourceStopped, this, &VideoSurface::onSourceStopped);
} }
} }
void VideoSurface::unsubscribe() void VideoSurface::unsubscribe()
{ {
if (!source || hasSubscribed == 0) if (!source || hasSubscribed == 0)
return; return;
if (--hasSubscribed != 0) if (--hasSubscribed != 0)
return; return;
lock(); lock();
lastFrame.reset(); lastFrame.reset();
unlock(); unlock();
ratio = 1.0f; ratio = 1.0f;
recalulateBounds(); recalulateBounds();
emit ratioChanged(); emit ratioChanged();
emit boundaryChanged(); emit boundaryChanged();
disconnect(source, &VideoSource::frameAvailable, this, &VideoSurface::onNewFrameAvailable); disconnect(source, &VideoSource::frameAvailable, this, &VideoSurface::onNewFrameAvailable);
disconnect(source, &VideoSource::sourceStopped, this, &VideoSurface::onSourceStopped); disconnect(source, &VideoSource::sourceStopped, this, &VideoSurface::onSourceStopped);
source->unsubscribe(); source->unsubscribe();
} }
void VideoSurface::onNewFrameAvailable(const std::shared_ptr<VideoFrame>& newFrame) void VideoSurface::onNewFrameAvailable(const std::shared_ptr<VideoFrame>& newFrame)
{ {
QSize newSize; QSize newSize;
lock(); lock();
lastFrame = newFrame; lastFrame = newFrame;
newSize = lastFrame->getSourceDimensions().size(); newSize = lastFrame->getSourceDimensions().size();
unlock(); unlock();
float newRatio = getSizeRatio(newSize); float newRatio = getSizeRatio(newSize);
if (!qFuzzyCompare(newRatio, ratio) && isVisible()) { if (!qFuzzyCompare(newRatio, ratio) && isVisible()) {
ratio = newRatio; ratio = newRatio;
recalulateBounds(); recalulateBounds();
emit ratioChanged(); emit ratioChanged();
emit boundaryChanged(); emit boundaryChanged();
} }
update(); update();
} }
void VideoSurface::onSourceStopped() void VideoSurface::onSourceStopped()
{ {
// If the source's stream is on hold, just revert back to the avatar view // If the source's stream is on hold, just revert back to the avatar view
lastFrame.reset(); lastFrame.reset();
update(); update();
} }
void VideoSurface::paintEvent(QPaintEvent*) void VideoSurface::paintEvent(QPaintEvent*)
{ {
lock(); lock();
QPainter painter(this); QPainter painter(this);
painter.fillRect(painter.viewport(), Qt::black); painter.fillRect(painter.viewport(), Qt::black);
if (lastFrame) { if (lastFrame) {
QImage frame = lastFrame->toQImage(rect().size()); QImage frame = lastFrame->toQImage(rect().size());
if (frame.isNull()) if (frame.isNull())
lastFrame.reset(); lastFrame.reset();
painter.drawImage(boundingRect, frame, frame.rect(), Qt::NoFormatConversion); painter.drawImage(boundingRect, frame, frame.rect(), Qt::NoFormatConversion);
} else { } else {
painter.fillRect(boundingRect, Qt::white); painter.fillRect(boundingRect, Qt::white);
QPixmap drawnAvatar = avatar; QPixmap drawnAvatar = avatar;
if (drawnAvatar.isNull()) if (drawnAvatar.isNull())
drawnAvatar = Style::scaleSvgImage(":/img/contact_dark.svg", boundingRect.width(), drawnAvatar = Style::scaleSvgImage(":/img/contact_dark.svg", boundingRect.width(),
boundingRect.height()); boundingRect.height());
painter.drawPixmap(boundingRect, drawnAvatar, drawnAvatar.rect()); painter.drawPixmap(boundingRect, drawnAvatar, drawnAvatar.rect());
} }
unlock(); unlock();
} }
void VideoSurface::resizeEvent(QResizeEvent* event) void VideoSurface::resizeEvent(QResizeEvent* event)
{ {
QWidget::resizeEvent(event); QWidget::resizeEvent(event);
recalulateBounds(); recalulateBounds();
emit boundaryChanged(); emit boundaryChanged();
} }
void VideoSurface::showEvent(QShowEvent* e) void VideoSurface::showEvent(QShowEvent* e)
{ {
Q_UNUSED(e) Q_UNUSED(e)
// emit ratioChanged(); // emit ratioChanged();
} }
void VideoSurface::recalulateBounds() void VideoSurface::recalulateBounds()
{ {
if (expanding) { if (expanding) {
boundingRect = contentsRect(); boundingRect = contentsRect();
} else { } else {
QPoint pos; QPoint pos;
QSize size; QSize size;
QSize usableSize = contentsRect().size(); QSize usableSize = contentsRect().size();
int possibleWidth = usableSize.height() * ratio; int possibleWidth = usableSize.height() * ratio;
if (possibleWidth > usableSize.width()) if (possibleWidth > usableSize.width())
size = (QSize(usableSize.width(), usableSize.width() / ratio)); size = (QSize(usableSize.width(), usableSize.width() / ratio));
else else
size = (QSize(possibleWidth, usableSize.height())); size = (QSize(possibleWidth, usableSize.height()));
pos.setX(width() / 2 - size.width() / 2); pos.setX(width() / 2 - size.width() / 2);
pos.setY(height() / 2 - size.height() / 2); pos.setY(height() / 2 - size.height() / 2);
boundingRect.setRect(pos.x(), pos.y(), size.width(), size.height()); boundingRect.setRect(pos.x(), pos.y(), size.width(), size.height());
} }
update(); update();
} }
void VideoSurface::lock() void VideoSurface::lock()
{ {
// Fast lock // Fast lock
bool expected = false; bool expected = false;
while (!frameLock.compare_exchange_weak(expected, true)) while (!frameLock.compare_exchange_weak(expected, true))
expected = false; expected = false;
} }
void VideoSurface::unlock() void VideoSurface::unlock()
{ {
frameLock = false; frameLock = false;
} }

150
src/video/videosurface.h

@ -1,75 +1,75 @@
/* /*
Copyright © 2014-2019 by The qTox Project Contributors Copyright © 2014-2019 by The qTox Project Contributors
This file is part of qTox, a Qt-based graphical interface for Tox. This file is part of qTox, a Qt-based graphical interface for Tox.
qTox is libre software: you can redistribute it and/or modify qTox is libre software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
qTox is distributed in the hope that it will be useful, qTox is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with qTox. If not, see <http://www.gnu.org/licenses/>. along with qTox. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef SELFCAMVIEW_H #ifndef SELFCAMVIEW_H
#define SELFCAMVIEW_H #define SELFCAMVIEW_H
#include "src/video/videosource.h" #include "src/video/videosource.h"
#include <QWidget> #include <QWidget>
#include <atomic> #include <atomic>
#include <memory> #include <memory>
class VideoSurface : public QWidget class VideoSurface : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
VideoSurface(const QPixmap& avatar, QWidget* parent = nullptr, bool expanding = false); VideoSurface(const QPixmap& avatar, QWidget* parent = nullptr, bool expanding = false);
VideoSurface(const QPixmap& avatar, VideoSource* source, QWidget* parent = nullptr); VideoSurface(const QPixmap& avatar, VideoSource* source, QWidget* parent = nullptr);
~VideoSurface(); ~VideoSurface();
bool isExpanding() const; bool isExpanding() const;
void setSource(VideoSource* src); void setSource(VideoSource* src);
QRect getBoundingRect() const; QRect getBoundingRect() const;
float getRatio() const; float getRatio() const;
void setAvatar(const QPixmap& pixmap); void setAvatar(const QPixmap& pixmap);
QPixmap getAvatar() const; QPixmap getAvatar() const;
signals: signals:
void ratioChanged(); void ratioChanged();
void boundaryChanged(); void boundaryChanged();
protected: protected:
void subscribe(); void subscribe();
void unsubscribe(); void unsubscribe();
void paintEvent(QPaintEvent* event) final; void paintEvent(QPaintEvent* event) final;
void resizeEvent(QResizeEvent* event) final; void resizeEvent(QResizeEvent* event) final;
void showEvent(QShowEvent* event) final; void showEvent(QShowEvent* event) final;
private slots: private slots:
void onNewFrameAvailable(const std::shared_ptr<VideoFrame>& newFrame); void onNewFrameAvailable(const std::shared_ptr<VideoFrame>& newFrame);
void onSourceStopped(); void onSourceStopped();
private: private:
void recalulateBounds(); void recalulateBounds();
void lock(); void lock();
void unlock(); void unlock();
QRect boundingRect; QRect boundingRect;
VideoSource* source; VideoSource* source;
std::shared_ptr<VideoFrame> lastFrame; std::shared_ptr<VideoFrame> lastFrame;
std::atomic_bool frameLock; std::atomic_bool frameLock;
uint8_t hasSubscribed; uint8_t hasSubscribed;
QPixmap avatar; QPixmap avatar;
float ratio; float ratio;
bool expanding; bool expanding;
}; };
#endif // SELFCAMVIEW_H #endif // SELFCAMVIEW_H

Loading…
Cancel
Save