| /* |
| * Copyright (C) 2004-2021 Savoir-faire Linux Inc. |
| * |
| * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> |
| * Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com> |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 3 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| */ |
| |
| #pragma once |
| |
| #include "media/rtp_session.h" |
| #include "media/media_device.h" |
| |
| #include "video_base.h" |
| #include "threadloop.h" |
| |
| #include <string> |
| #include <memory> |
| |
| namespace jami { |
| class CongestionControl; |
| class Conference; |
| class MediaRecorder; |
| } // namespace jami |
| |
| namespace jami { |
| namespace video { |
| |
| class VideoInput; |
| class VideoMixer; |
| class VideoSender; |
| class VideoReceiveThread; |
| |
| struct RTCPInfo |
| { |
| float packetLoss; |
| unsigned int jitter; |
| unsigned int nb_sample; |
| float latency; |
| }; |
| |
| struct VideoBitrateInfo |
| { |
| unsigned videoBitrateCurrent; |
| unsigned videoBitrateMin; |
| unsigned videoBitrateMax; |
| unsigned videoQualityCurrent; |
| unsigned videoQualityMin; |
| unsigned videoQualityMax; |
| unsigned cptBitrateChecking; |
| unsigned maxBitrateChecking; |
| float packetLostThreshold; |
| }; |
| |
| class VideoRtpSession : public RtpSession |
| { |
| public: |
| using BaseType = RtpSession; |
| |
| VideoRtpSession(const std::string& callID, const DeviceParams& localVideoParams); |
| ~VideoRtpSession(); |
| |
| void setRequestKeyFrameCallback(std::function<void(void)> cb); |
| |
| void updateMedia(const MediaDescription& send, const MediaDescription& receive) override; |
| |
| void start(std::unique_ptr<IceSocket> rtp_sock, std::unique_ptr<IceSocket> rtcp_sock) override; |
| void restartSender() override; |
| void stop() override; |
| |
| /** |
| * Set video orientation |
| * |
| * Send to the receive thread rotation to apply to the video (counterclockwise) |
| * |
| * @param rotation Rotation in degrees (counterclockwise) |
| */ |
| void setRotation(int rotation); |
| void forceKeyFrame(); |
| void bindMixer(VideoMixer* mixer); |
| void unbindMixer(); |
| void enterConference(Conference& conference); |
| void exitConference(); |
| |
| void setChangeOrientationCallback(std::function<void(int)> cb); |
| void initRecorder(std::shared_ptr<MediaRecorder>& rec) override; |
| void deinitRecorder(std::shared_ptr<MediaRecorder>& rec) override; |
| |
| bool hasConference() { return conference_; } |
| |
| std::shared_ptr<VideoInput>& getVideoLocal() { return videoLocal_; } |
| |
| std::shared_ptr<VideoMixer>& getVideoMixer() { return videoMixer_; } |
| |
| std::shared_ptr<VideoReceiveThread>& getVideoReceive() { return receiveThread_; } |
| |
| std::shared_ptr<VideoFrameActiveWriter> getReceiveVideoFrameActiveWriter() |
| { |
| if (isReceiving() && receiveThread_) |
| return std::static_pointer_cast<VideoFrameActiveWriter>(receiveThread_); |
| return dummyVideoReceive_; |
| } |
| |
| private: |
| void setupConferenceVideoPipeline(Conference& conference); |
| void setupVideoPipeline(); |
| void startSender(); |
| void startReceiver(); |
| using clock = std::chrono::steady_clock; |
| using time_point = clock::time_point; |
| |
| DeviceParams localVideoParams_; |
| |
| std::unique_ptr<VideoSender> sender_; |
| std::shared_ptr<VideoReceiveThread> receiveThread_; |
| std::shared_ptr<VideoFrameActiveWriter> dummyVideoReceive_ |
| = std::make_shared<VideoFrameActiveWriter>(); |
| Conference* conference_ {nullptr}; |
| std::shared_ptr<VideoMixer> videoMixer_; |
| std::shared_ptr<VideoInput> videoLocal_; |
| uint16_t initSeqVal_ = 0; |
| |
| std::function<void(void)> requestKeyFrameCallback_; |
| |
| bool check_RCTP_Info_RR(RTCPInfo&); |
| bool check_RCTP_Info_REMB(uint64_t*); |
| unsigned getLowerQuality(); |
| unsigned getLowerBitrate(); |
| void adaptQualityAndBitrate(); |
| void storeVideoBitrateInfo(); |
| void setupVideoBitrateInfo(); |
| void checkReceiver(); |
| float getPonderateLoss(float lastLoss); |
| void delayMonitor(int gradient, int deltaT); |
| void dropProcessing(RTCPInfo* rtcpi); |
| void delayProcessing(int br); |
| void setNewBitrate(unsigned int newBR); |
| |
| // no packet loss can be calculated as no data in input |
| static constexpr float NO_INFO_CALCULATED {-1.0}; |
| // bitrate and quality info struct |
| VideoBitrateInfo videoBitrateInfo_; |
| // previous quality, bitrate, jitter and loss used if quality or bitrate need to be decreased |
| std::list<unsigned> histoQuality_ {}; |
| std::list<unsigned> histoBitrate_ {}; |
| std::list<unsigned> histoJitter_ {}; |
| std::list<int> histoDelay_ {}; |
| std::list<std::pair<time_point, float>> histoLoss_; |
| // max size of quality and bitrate historic |
| |
| // 5 tries in a row |
| static constexpr unsigned MAX_ADAPTATIVE_BITRATE_ITERATION {5}; |
| bool hasReachMaxQuality_ {false}; |
| // packet loss threshold |
| static constexpr float PACKET_LOSS_THRESHOLD {1.0}; |
| |
| InterruptedThreadLoop rtcpCheckerThread_; |
| void processRtcpChecker(); |
| |
| std::function<void(int)> changeOrientationCallback_; |
| |
| std::function<void(bool)> recordingStateCallback_; |
| |
| // interval in seconds between RTCP checkings |
| std::chrono::seconds rtcp_checking_interval {4}; |
| |
| time_point lastMediaRestart_ {time_point::min()}; |
| time_point last_REMB_inc_ {time_point::min()}; |
| time_point last_REMB_dec_ {time_point::min()}; |
| |
| unsigned remb_dec_cnt_ {0}; |
| |
| std::unique_ptr<CongestionControl> cc; |
| |
| std::function<void(void)> cbKeyFrameRequest_; |
| }; |
| |
| } // namespace video |
| } // namespace jami |