File indexing completed on 2024-06-23 05:24:07
0001 // SPDX-FileCopyrightText: 2023 Arjen Hiemstra <ahiemstra@heimr.nl> 0002 // 0003 // SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0004 0005 #pragma once 0006 0007 #include <memory> 0008 #include <optional> 0009 0010 #include <QImage> 0011 #include <QObject> 0012 #include <QPoint> 0013 #include <QRegion> 0014 #include <QSize> 0015 0016 #include <freerdp/server/rdpgfx.h> 0017 0018 #include "krdp_export.h" 0019 0020 namespace KRdp 0021 { 0022 0023 class RdpConnection; 0024 0025 /** 0026 * A frame of compressed video data. 0027 */ 0028 struct VideoFrame { 0029 /** 0030 * The size of the frame, in pixels. 0031 */ 0032 QSize size; 0033 /** 0034 * h264 compressed data in YUV420 color space. 0035 */ 0036 QByteArray data; 0037 /** 0038 * Area of the frame that was actually damaged. 0039 * TODO: Actually use this information. 0040 */ 0041 QRegion damage; 0042 /** 0043 * Whether the packet contains all the information 0044 */ 0045 bool isKeyFrame; 0046 /** 0047 * When was this frame presented. 0048 */ 0049 std::chrono::system_clock::time_point presentationTimeStamp; 0050 }; 0051 0052 /** 0053 * A class that encapsulates an RdpGfx video stream. 0054 * 0055 * Video streaming is done using the "RDP Graphics Pipeline" protocol 0056 * extension which allows using h264 as the codec for the video stream. 0057 * However, this protocol extension is fairly complex to setup and use. 0058 * 0059 * VideoStream makes sure to handle most of the complexity of the RdpGfx 0060 * protocol like ensuring the client knows the right resolution and a 0061 * surface at the right size. It also takes care of sending the frames, 0062 * using a separate thread for a submission queue. 0063 * 0064 * VideoStream is managed by Session. Each session will have one instance 0065 * of this class. 0066 */ 0067 class KRDP_EXPORT VideoStream : public QObject 0068 { 0069 Q_OBJECT 0070 0071 public: 0072 explicit VideoStream(RdpConnection *session); 0073 ~VideoStream() override; 0074 0075 bool initialize(); 0076 void close(); 0077 Q_SIGNAL void closed(); 0078 0079 /** 0080 * Queue a frame to be sent to the client. 0081 * 0082 * This will add the provided frame to the queue of frames that should 0083 * be sent to the client. 0084 * 0085 * \param frame The frame to send. 0086 */ 0087 void queueFrame(const VideoFrame &frame); 0088 0089 /** 0090 * Indicate that the video state should be reset. 0091 * 0092 * This means the screen resolution and other information of the client 0093 * will be updated based on the current state of the VideoStream. 0094 */ 0095 void reset(); 0096 0097 /** 0098 */ 0099 bool enabled() const; 0100 void setEnabled(bool enabled); 0101 Q_SIGNAL void enabledChanged(); 0102 0103 uint32_t requestedFrameRate() const; 0104 Q_SIGNAL void requestedFrameRateChanged(); 0105 0106 private: 0107 friend BOOL gfxChannelIdAssigned(RdpgfxServerContext *, uint32_t); 0108 friend uint32_t gfxCapsAdvertise(RdpgfxServerContext *, const RDPGFX_CAPS_ADVERTISE_PDU *); 0109 friend uint32_t gfxFrameAcknowledge(RdpgfxServerContext *, const RDPGFX_FRAME_ACKNOWLEDGE_PDU *); 0110 0111 bool onChannelIdAssigned(uint32_t channelId); 0112 uint32_t onCapsAdvertise(const RDPGFX_CAPS_ADVERTISE_PDU *capsAdvertise); 0113 uint32_t onFrameAcknowledge(const RDPGFX_FRAME_ACKNOWLEDGE_PDU *frameAcknowledge); 0114 0115 void performReset(const QSize &size); 0116 void sendFrame(const VideoFrame &frame); 0117 0118 void updateRequestedFrameRate(); 0119 0120 class Private; 0121 const std::unique_ptr<Private> d; 0122 }; 0123 0124 }