Line data Source code
1 : /* 2 : * Copyright (C) 2004-2024 Savoir-faire Linux Inc. 3 : * 4 : * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> 5 : * Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com> 6 : * 7 : * This program is free software; you can redistribute it and/or modify 8 : * it under the terms of the GNU General Public License as published by 9 : * the Free Software Foundation; either version 3 of the License, or 10 : * (at your option) any later version. 11 : * 12 : * This program is distributed in the hope that it will be useful, 13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 : * GNU General Public License for more details. 16 : * 17 : * You should have received a copy of the GNU General Public License 18 : * along with this program; if not, write to the Free Software 19 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 : */ 21 : 22 : #pragma once 23 : 24 : #include "media/rtp_session.h" 25 : #include "media/media_device.h" 26 : 27 : #include "video_base.h" 28 : #include "threadloop.h" 29 : 30 : #include <string> 31 : #include <memory> 32 : 33 : namespace jami { 34 : class CongestionControl; 35 : class Conference; 36 : class MediaRecorder; 37 : } // namespace jami 38 : 39 : namespace jami { 40 : namespace video { 41 : 42 : class VideoInput; 43 : class VideoMixer; 44 : class VideoSender; 45 : class VideoReceiveThread; 46 : 47 : struct RTCPInfo 48 : { 49 : float packetLoss; 50 : unsigned int jitter; 51 : unsigned int nb_sample; 52 : float latency; 53 : }; 54 : 55 : struct VideoBitrateInfo 56 : { 57 : unsigned videoBitrateCurrent; 58 : unsigned videoBitrateMin; 59 : unsigned videoBitrateMax; 60 : unsigned videoQualityCurrent; 61 : unsigned videoQualityMin; 62 : unsigned videoQualityMax; 63 : unsigned cptBitrateChecking; 64 : unsigned maxBitrateChecking; 65 : float packetLostThreshold; 66 : }; 67 : 68 : class VideoRtpSession : public RtpSession, public std::enable_shared_from_this<VideoRtpSession> 69 : { 70 : public: 71 : using BaseType = RtpSession; 72 : 73 : VideoRtpSession(const std::string& callId, 74 : const std::string& streamId, 75 : const DeviceParams& localVideoParams, 76 : const std::shared_ptr<MediaRecorder>& rec); 77 : ~VideoRtpSession(); 78 : 79 : void setRequestKeyFrameCallback(std::function<void(void)> cb); 80 : 81 : void updateMedia(const MediaDescription& send, const MediaDescription& receive) override; 82 : 83 : void start(std::unique_ptr<dhtnet::IceSocket> rtp_sock, std::unique_ptr<dhtnet::IceSocket> rtcp_sock) override; 84 : void restartSender() override; 85 : void stop() override; 86 : void setMuted(bool mute, Direction dir = Direction::SEND) override; 87 : 88 : /** 89 : * Set video orientation 90 : * 91 : * Send to the receive thread rotation to apply to the video (counterclockwise) 92 : * 93 : * @param rotation Rotation in degrees (counterclockwise) 94 : */ 95 : void setRotation(int rotation); 96 : void forceKeyFrame(); 97 : void bindMixer(VideoMixer* mixer); 98 : void unbindMixer(); 99 : void enterConference(Conference& conference); 100 : void exitConference(); 101 : 102 : void setChangeOrientationCallback(std::function<void(int)> cb); 103 : void initRecorder() override; 104 : void deinitRecorder() override; 105 : 106 : const VideoBitrateInfo& getVideoBitrateInfo(); 107 : 108 217 : bool hasConference() { return conference_; } 109 : 110 329 : std::shared_ptr<VideoInput>& getVideoLocal() { return videoLocal_; } 111 : 112 : std::shared_ptr<VideoMixer>& getVideoMixer() { return videoMixer_; } 113 : 114 350 : std::shared_ptr<VideoReceiveThread>& getVideoReceive() { return receiveThread_; } 115 : 116 : private: 117 : void setupConferenceVideoPipeline(Conference& conference, Direction dir); 118 : void setupVideoPipeline(); 119 : void startSender(); 120 : void stopSender(bool forceStopSocket = false); 121 : void startReceiver(); 122 : void stopReceiver(bool forceStopSocket = false); 123 : using clock = std::chrono::steady_clock; 124 : using time_point = clock::time_point; 125 : 126 : DeviceParams localVideoParams_; 127 : 128 : std::unique_ptr<VideoSender> sender_; 129 : std::shared_ptr<VideoReceiveThread> receiveThread_; 130 : Conference* conference_ {nullptr}; 131 : std::shared_ptr<VideoMixer> videoMixer_; 132 : std::shared_ptr<VideoInput> videoLocal_; 133 : uint16_t initSeqVal_ = 0; 134 : 135 : std::function<void(void)> requestKeyFrameCallback_; 136 : 137 : bool check_RCTP_Info_RR(RTCPInfo&); 138 : bool check_RCTP_Info_REMB(uint64_t*); 139 : void adaptQualityAndBitrate(); 140 : void storeVideoBitrateInfo(); 141 : void setupVideoBitrateInfo(); 142 : void checkReceiver(); 143 : float getPonderateLoss(float lastLoss); 144 : void delayMonitor(int gradient, int deltaT); 145 : void dropProcessing(RTCPInfo* rtcpi); 146 : void delayProcessing(int br); 147 : void setNewBitrate(unsigned int newBR); 148 : 149 : // no packet loss can be calculated as no data in input 150 : static constexpr float NO_INFO_CALCULATED {-1.0}; 151 : // bitrate and quality info struct 152 : VideoBitrateInfo videoBitrateInfo_; 153 : std::list<std::pair<time_point, float>> histoLoss_; 154 : 155 : // 5 tries in a row 156 : static constexpr unsigned MAX_ADAPTATIVE_BITRATE_ITERATION {5}; 157 : // packet loss threshold 158 : static constexpr float PACKET_LOSS_THRESHOLD {1.0}; 159 : 160 : InterruptedThreadLoop rtcpCheckerThread_; 161 : void processRtcpChecker(); 162 : 163 : std::function<void(int)> changeOrientationCallback_; 164 : 165 : std::function<void(bool)> recordingStateCallback_; 166 : 167 : // interval in seconds between RTCP checkings 168 324 : std::chrono::seconds rtcp_checking_interval {4}; 169 : 170 : time_point lastMediaRestart_ {time_point::min()}; 171 : time_point last_REMB_inc_ {time_point::min()}; 172 : time_point last_REMB_dec_ {time_point::min()}; 173 : time_point lastBitrateDecrease {time_point::min()}; 174 : 175 : unsigned remb_dec_cnt_ {0}; 176 : 177 : std::unique_ptr<CongestionControl> cc; 178 : 179 : std::function<void(void)> cbKeyFrameRequest_; 180 : 181 : std::atomic<int> rotation_ {0}; 182 : 183 : void attachRemoteRecorder(const MediaStream& ms); 184 : void attachLocalRecorder(const MediaStream& ms); 185 : }; 186 : 187 : } // namespace video 188 : } // namespace jami