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