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 : 18 : #include "video_sender.h" 19 : #include "video_mixer.h" 20 : #include "socket_pair.h" 21 : #include "client/videomanager.h" 22 : #include "logger.h" 23 : #include "manager.h" 24 : #include "media_device.h" 25 : #include "sip/sipcall.h" 26 : #ifdef RING_ACCEL 27 : #include "accel.h" 28 : #endif 29 : 30 : #include <map> 31 : #include <unistd.h> 32 : 33 : namespace jami { 34 : namespace video { 35 : 36 : using std::string; 37 : 38 152 : VideoSender::VideoSender(const std::string& dest, 39 : const MediaStream& opts, 40 : const MediaDescription& args, 41 : SocketPair& socketPair, 42 : const uint16_t seqVal, 43 : uint16_t mtu, 44 152 : bool enableHwAccel) 45 152 : : muxContext_(socketPair.createIOContext(mtu)) 46 304 : , videoEncoder_(new MediaEncoder) 47 : { 48 152 : keyFrameFreq_ = opts.frameRate.numerator() * KEY_FRAME_PERIOD; 49 152 : videoEncoder_->openOutput(dest, "rtp"); 50 152 : videoEncoder_->setOptions(opts); 51 152 : videoEncoder_->setOptions(args); 52 : #ifdef RING_ACCEL 53 304 : videoEncoder_->enableAccel(enableHwAccel 54 152 : and Manager::instance().videoPreferences.getEncodingAccelerated()); 55 : #endif 56 152 : videoEncoder_->addStream(*args.codec); 57 152 : videoEncoder_->setInitSeqVal(seqVal); 58 152 : videoEncoder_->setIOContext(muxContext_->getContext()); 59 152 : } 60 : 61 : void 62 5296 : VideoSender::encodeAndSendVideo(const std::shared_ptr<VideoFrame>& input_frame) 63 : { 64 5296 : int angle = input_frame->getOrientation(); 65 5296 : if (rotation_ != angle) { 66 48 : rotation_ = angle; 67 48 : if (changeOrientationCallback_) 68 48 : changeOrientationCallback_(rotation_); 69 : } 70 : 71 5296 : if (auto packet = input_frame->packet()) { 72 0 : videoEncoder_->send(*packet); 73 : } else { 74 5296 : bool is_keyframe = forceKeyFrame_ > 0 75 5296 : or (keyFrameFreq_ > 0 and (frameNumber_ % keyFrameFreq_) == 0); 76 : 77 5296 : if (is_keyframe) 78 60 : --forceKeyFrame_; 79 : 80 5296 : if (videoEncoder_->encode(input_frame, is_keyframe, frameNumber_++) < 0) 81 0 : JAMI_ERR("encoding failed"); 82 : } 83 : #ifdef DEBUG_SDP 84 : if (frameNumber_ == 1) // video stream is lazy initialized, wait for first frame 85 : videoEncoder_->print_sdp(); 86 : #endif 87 5296 : } 88 : 89 : void 90 5296 : VideoSender::update(Observable<std::shared_ptr<MediaFrame>>* /*obs*/, 91 : const std::shared_ptr<MediaFrame>& frame_p) 92 : { 93 5296 : encodeAndSendVideo(std::dynamic_pointer_cast<VideoFrame>(frame_p)); 94 5296 : } 95 : 96 : void 97 74 : VideoSender::forceKeyFrame() 98 : { 99 74 : JAMI_DBG("Key frame requested"); 100 74 : ++forceKeyFrame_; 101 74 : } 102 : 103 : uint16_t 104 0 : VideoSender::getLastSeqValue() 105 : { 106 0 : return videoEncoder_->getLastSeqValue(); 107 : } 108 : 109 : void 110 161 : VideoSender::setChangeOrientationCallback(std::function<void(int)> cb) 111 : { 112 161 : changeOrientationCallback_ = std::move(cb); 113 161 : } 114 : 115 : int 116 32 : VideoSender::setBitrate(uint64_t br) 117 : { 118 : // The encoder may be destroy during a bitrate change 119 : // when a codec parameter like auto quality change 120 32 : if (!videoEncoder_) 121 0 : return -1; // NOK 122 : 123 32 : return videoEncoder_->setBitrate(br); 124 : } 125 : 126 : } // namespace video 127 : } // namespace jami