diff options
| author | Anton <anton@picapica.im> | 2026-10-03 20:33:04 +0400 |
|---|---|---|
| committer | Anton <anton@picapica.im> | 2026-10-03 20:33:04 +0400 |
| commit | 835b124bd871afecd88c1e5e9105e3af4d4c5b27 (patch) | |
| tree | 42ee00cb6f37472fe36c802530cdc9a288ba87bd /pica-client/videodevice.h | |
| parent | 76225a538e1e960eda9e31a34846f4bc62adef87 (diff) | |
| download | pica-pica-835b124bd871afecd88c1e5e9105e3af4d4c5b27.tar.gz pica-pica-835b124bd871afecd88c1e5e9105e3af4d4c5b27.zip | |
pica-client: callwindow layout, video resize
Diffstat (limited to 'pica-client/videodevice.h')
| -rw-r--r-- | pica-client/videodevice.h | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/pica-client/videodevice.h b/pica-client/videodevice.h index fe218ec..f65895d 100644 --- a/pica-client/videodevice.h +++ b/pica-client/videodevice.h @@ -26,6 +26,7 @@ #include <QQueue> #include <QMutex> #include <QWaitCondition> +#include <QSize> #include <QAtomicInt> // Reassembles the fragments of one encoded video frame, as carried by 0x77 @@ -155,12 +156,29 @@ public: void setMaxFragmentSize(int size); // Stops keeping decoded frames in GPU memory, for when the renderer that - // was to draw them turns out not to be able to: decoding carries on, but + // was to draw them turns out to not be able to: decoding carries on, but // frames come back through system memory and are emitted by frameReady() // from then on. Safe to call from any thread, and called directly rather // than queued for the same reason enqueueFrame() is. void disableHardwareRendering(); + // The size of the area the decoded frames are going to be drawn in, so + // that Play() can produce them at that size directly. A decoded frame has + // to be resized to the window either way, and doing it inside the colour + // conversion the decode loop already runs costs far less than a second + // pass over the picture afterwards - between 1.1 and 4.6 times less over + // the whole pipeline, see tests/test_videoscaler. + // + // Frames keep their aspect ratio: this is the area to fit inside, not the + // size to produce. An empty size means the display size is not known and + // frames come back at their own resolution. + // + // Changes while a call is running, on every window resize, and is safe to + // call from any thread. Called directly rather than queued for the same + // reason enqueueFrame() is - the decode loop it affects is already + // running. + void setDisplaySize(QSize size); + public slots: // Blocking capture+encode loop: opens the configured camera, encodes // captured frames, and emits packetReady() for each encoded frame, split @@ -189,7 +207,16 @@ signals: // onto the 0x77 sequence number's last fragment marker bit. void packetReady(QByteArray data, bool isLastFragment); - // One decoded picture from the remote side, ready to be displayed. + // One decoded picture from the remote side, ready to be displayed, as a + // Format_RGB32 image - the format a widget draws without converting it + // first. + // + // Already scaled to fit the area last given to setDisplaySize(), keeping + // its aspect ratio, so the receiver can draw it as it stands. At the + // frame's own resolution while no display size has been set. A receiver + // still has to cope with the occasional frame at another size: the ones + // already decoded or in flight when the window is resized arrive at the + // size that was current when they were converted. void frameReady(QImage frame); #ifdef HAVE_VAAPI @@ -248,6 +275,13 @@ private: // capture loop is running. QAtomicInt m_maxFragmentSize; + // Likewise set from another thread, by setDisplaySize(), while the decode + // loop is running. Both dimensions live in the one atomic - width in the + // upper half, height in the lower - so that the decode loop cannot read a + // new width against an old height and scale one frame to a wrong aspect + // ratio. Zero means not known yet. + QAtomicInt m_displaySize; + QMutex m_queueMutex; QWaitCondition m_queueCond; QQueue<QByteArray> m_frameQueue; @@ -272,6 +306,10 @@ private: // packets, hence atomic. QAtomicInt m_decoderStarted; + // What setDisplaySize() was last given, unpacked; an empty size if it has + // not been called. Read by the decode loop, once per frame. + QSize displaySize() const; + // Sends one encoded frame out as one or more protocol sized fragments. void emitFragments(const unsigned char *data, int size); |
