qTox  Version: nightly | Commit: bc751c8e1cac455f9690654fcfe0f560d2d7dfdd
videosurface.cpp
Go to the documentation of this file.
1 /*
2  Copyright © 2014-2019 by The qTox Project Contributors
3 
4  This file is part of qTox, a Qt-based graphical interface for Tox.
5 
6  qTox is libre software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  qTox is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with qTox. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "videosurface.h"
21 #include "src/core/core.h"
22 #include "src/model/friend.h"
23 #include "src/friendlist.h"
25 #include "src/video/videoframe.h"
27 #include "src/widget/style.h"
28 
29 #include <QDebug>
30 #include <QLabel>
31 #include <QPainter>
32 
38 float getSizeRatio(const QSize size)
39 {
40  return size.width() / static_cast<float>(size.height());
41 }
42 
43 VideoSurface::VideoSurface(const QPixmap& avatar, QWidget* parent, bool expanding)
44  : QWidget{parent}
45  , source{nullptr}
46  , frameLock{false}
47  , hasSubscribed{0}
48  , avatar{avatar}
49  , ratio{1.0f}
50  , expanding{expanding}
51 {
52  recalulateBounds();
53 }
54 
55 VideoSurface::VideoSurface(const QPixmap& avatar, VideoSource* source, QWidget* parent)
56  : VideoSurface(avatar, parent)
57 {
59 }
60 
62 {
63  unsubscribe();
64 }
65 
67 {
68  return expanding;
69 }
70 
79 {
80  if (source == src)
81  return;
82 
83  unsubscribe();
84  source = src;
85  subscribe();
86 }
87 
89 {
90  QRect bRect = boundingRect;
91  bRect.setBottomRight(QPoint(boundingRect.bottom() + 1, boundingRect.right() + 1));
92  return boundingRect;
93 }
94 
96 {
97  return ratio;
98 }
99 
100 void VideoSurface::setAvatar(const QPixmap& pixmap)
101 {
102  avatar = pixmap;
103  update();
104 }
105 
106 QPixmap VideoSurface::getAvatar() const
107 {
108  return avatar;
109 }
110 
112 {
113  if (source && hasSubscribed++ == 0) {
114  source->subscribe();
117  }
118 }
119 
121 {
122  if (!source || hasSubscribed == 0)
123  return;
124 
125  if (--hasSubscribed != 0)
126  return;
127 
128  lock();
129  lastFrame.reset();
130  unlock();
131 
132  ratio = 1.0f;
134  emit ratioChanged();
135  emit boundaryChanged();
136 
139  source->unsubscribe();
140 }
141 
142 void VideoSurface::onNewFrameAvailable(const std::shared_ptr<VideoFrame>& newFrame)
143 {
144  QSize newSize;
145 
146  lock();
147  lastFrame = newFrame;
148  newSize = lastFrame->getSourceDimensions().size();
149  unlock();
150 
151  float newRatio = getSizeRatio(newSize);
152 
153  if (!qFuzzyCompare(newRatio, ratio) && isVisible()) {
154  ratio = newRatio;
156  emit ratioChanged();
157  emit boundaryChanged();
158  }
159 
160  update();
161 }
162 
164 {
165  // If the source's stream is on hold, just revert back to the avatar view
166  lastFrame.reset();
167  update();
168 }
169 
170 void VideoSurface::paintEvent(QPaintEvent*)
171 {
172  lock();
173 
174  QPainter painter(this);
175  painter.fillRect(painter.viewport(), Qt::black);
176  if (lastFrame) {
177  QImage frame = lastFrame->toQImage(rect().size());
178  if (frame.isNull())
179  lastFrame.reset();
180  painter.drawImage(boundingRect, frame, frame.rect(), Qt::NoFormatConversion);
181  } else {
182  painter.fillRect(boundingRect, Qt::white);
183  QPixmap drawnAvatar = avatar;
184 
185  if (drawnAvatar.isNull())
186  drawnAvatar = Style::scaleSvgImage(":/img/contact_dark.svg", boundingRect.width(),
187  boundingRect.height());
188 
189  painter.drawPixmap(boundingRect, drawnAvatar, drawnAvatar.rect());
190  }
191 
192  unlock();
193 }
194 
195 void VideoSurface::resizeEvent(QResizeEvent* event)
196 {
197  QWidget::resizeEvent(event);
199  emit boundaryChanged();
200 }
201 
202 void VideoSurface::showEvent(QShowEvent* e)
203 {
204  Q_UNUSED(e)
205  // emit ratioChanged();
206 }
207 
209 {
210  if (expanding) {
211  boundingRect = contentsRect();
212  } else {
213  QPoint pos;
214  QSize size;
215  QSize usableSize = contentsRect().size();
216  int possibleWidth = usableSize.height() * ratio;
217 
218  if (possibleWidth > usableSize.width())
219  size = (QSize(usableSize.width(), usableSize.width() / ratio));
220  else
221  size = (QSize(possibleWidth, usableSize.height()));
222 
223  pos.setX(width() / 2 - size.width() / 2);
224  pos.setY(height() / 2 - size.height() / 2);
225  boundingRect.setRect(pos.x(), pos.y(), size.width(), size.height());
226  }
227 
228  update();
229 }
230 
232 {
233  // Fast lock
234  bool expected = false;
235  while (!frameLock.compare_exchange_weak(expected, true))
236  expected = false;
237 }
238 
240 {
241  frameLock = false;
242 }
VideoSurface::frameLock
std::atomic_bool frameLock
Fast lock for lastFrame.
Definition: videosurface.h:67
VideoSource::unsubscribe
virtual void unsubscribe()=0
Stop emitting frameAvailable signals, and free associated resources if necessary.
style.h
VideoSurface::VideoSurface
VideoSurface(const QPixmap &avatar, QWidget *parent=nullptr, bool expanding=false)
Definition: videosurface.cpp:43
VideoSurface::setAvatar
void setAvatar(const QPixmap &pixmap)
Definition: videosurface.cpp:100
friend.h
friendlist.h
settings.h
VideoSource::frameAvailable
void frameAvailable(std::shared_ptr< VideoFrame > frame)
Emitted when new frame available to use.
VideoSource
An abstract source of video frames.
Definition: videosource.h:29
VideoSurface::boundingRect
QRect boundingRect
Definition: videosurface.h:64
VideoSource::subscribe
virtual void subscribe()=0
If subscribe sucessfully opens the source, it will start emitting frameAvailable signals.
VideoSurface::onNewFrameAvailable
void onNewFrameAvailable(const std::shared_ptr< VideoFrame > &newFrame)
Definition: videosurface.cpp:142
VideoSurface::getAvatar
QPixmap getAvatar() const
Definition: videosurface.cpp:106
VideoSurface::getBoundingRect
QRect getBoundingRect() const
Definition: videosurface.cpp:88
VideoSurface::resizeEvent
void resizeEvent(QResizeEvent *event) final
Definition: videosurface.cpp:195
VideoSurface::unsubscribe
void unsubscribe()
Definition: videosurface.cpp:120
videoframe.h
VideoSource::sourceStopped
void sourceStopped()
Emitted when the source is stopped for an indefinite amount of time, but might restart sending frames...
VideoSurface::showEvent
void showEvent(QShowEvent *event) final
Definition: videosurface.cpp:202
VideoSurface::isExpanding
bool isExpanding() const
Definition: videosurface.cpp:66
VideoSurface::source
VideoSource * source
Definition: videosurface.h:65
VideoSurface::ratio
float ratio
Definition: videosurface.h:70
VideoSurface::lastFrame
std::shared_ptr< VideoFrame > lastFrame
Definition: videosurface.h:66
VideoSurface::unlock
void unlock()
Definition: videosurface.cpp:239
VideoSurface::avatar
QPixmap avatar
Definition: videosurface.h:69
getSizeRatio
float getSizeRatio(const QSize size)
Definition: videosurface.cpp:38
VideoSurface::~VideoSurface
~VideoSurface()
Definition: videosurface.cpp:61
VideoSurface::recalulateBounds
void recalulateBounds()
Definition: videosurface.cpp:208
VideoSurface::getRatio
float getRatio() const
Definition: videosurface.cpp:95
videosurface.h
VideoSurface::onSourceStopped
void onSourceStopped()
Definition: videosurface.cpp:163
VideoSurface::setSource
void setSource(VideoSource *src)
Update source.
Definition: videosurface.cpp:78
VideoSurface::subscribe
void subscribe()
Definition: videosurface.cpp:111
VideoSurface::expanding
bool expanding
Definition: videosurface.h:71
VideoSurface::ratioChanged
void ratioChanged()
VideoSurface::boundaryChanged
void boundaryChanged()
VideoSurface::hasSubscribed
uint8_t hasSubscribed
Definition: videosurface.h:68
core.h
VideoSurface::paintEvent
void paintEvent(QPaintEvent *event) final
Definition: videosurface.cpp:170
Style::scaleSvgImage
static QPixmap scaleSvgImage(const QString &path, uint32_t width, uint32_t height)
Definition: style.cpp:381
VideoSurface
Definition: videosurface.h:27
friendwidget.h
VideoSurface::lock
void lock()
Definition: videosurface.cpp:231