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 : * Author: Eloi Bail <eloi.bail@savoirfairelinux.com> 7 : * Author: Philippe Gorley <philippe.gorley@savoirfairelinux.com> 8 : * 9 : * This program is free software; you can redistribute it and/or modify 10 : * it under the terms of the GNU General Public License as published by 11 : * the Free Software Foundation; either version 3 of the License, or 12 : * (at your option) any later version. 13 : * 14 : * This program is distributed in the hope that it will be useful, 15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 : * GNU General Public License for more details. 18 : * 19 : * You should have received a copy of the GNU General Public License 20 : * along with this program; if not, write to the Free Software 21 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 22 : */ 23 : 24 : #include "video_sender.h" 25 : #include "video_mixer.h" 26 : #include "socket_pair.h" 27 : #include "client/videomanager.h" 28 : #include "logger.h" 29 : #include "manager.h" 30 : #include "media_device.h" 31 : #include "sip/sipcall.h" 32 : #ifdef RING_ACCEL 33 : #include "accel.h" 34 : #endif 35 : 36 : #include <map> 37 : #include <unistd.h> 38 : 39 : namespace jami { 40 : namespace video { 41 : 42 : using std::string; 43 : 44 155 : VideoSender::VideoSender(const std::string& dest, 45 : const MediaStream& opts, 46 : const MediaDescription& args, 47 : SocketPair& socketPair, 48 : const uint16_t seqVal, 49 : uint16_t mtu, 50 155 : bool enableHwAccel) 51 155 : : muxContext_(socketPair.createIOContext(mtu)) 52 310 : , videoEncoder_(new MediaEncoder) 53 : { 54 155 : keyFrameFreq_ = opts.frameRate.numerator() * KEY_FRAME_PERIOD; 55 155 : videoEncoder_->openOutput(dest, "rtp"); 56 155 : videoEncoder_->setOptions(opts); 57 155 : videoEncoder_->setOptions(args); 58 : #ifdef RING_ACCEL 59 310 : videoEncoder_->enableAccel(enableHwAccel 60 155 : and Manager::instance().videoPreferences.getEncodingAccelerated()); 61 : #endif 62 155 : videoEncoder_->addStream(*args.codec); 63 155 : videoEncoder_->setInitSeqVal(seqVal); 64 155 : videoEncoder_->setIOContext(muxContext_->getContext()); 65 155 : } 66 : 67 : void 68 5431 : VideoSender::encodeAndSendVideo(const std::shared_ptr<VideoFrame>& input_frame) 69 : { 70 5431 : int angle = input_frame->getOrientation(); 71 5431 : if (rotation_ != angle) { 72 48 : rotation_ = angle; 73 48 : if (changeOrientationCallback_) 74 48 : changeOrientationCallback_(rotation_); 75 : } 76 : 77 5431 : if (auto packet = input_frame->packet()) { 78 0 : videoEncoder_->send(*packet); 79 : } else { 80 5431 : bool is_keyframe = forceKeyFrame_ > 0 81 5431 : or (keyFrameFreq_ > 0 and (frameNumber_ % keyFrameFreq_) == 0); 82 : 83 5431 : if (is_keyframe) 84 59 : --forceKeyFrame_; 85 : 86 5431 : if (videoEncoder_->encode(input_frame, is_keyframe, frameNumber_++) < 0) 87 0 : JAMI_ERR("encoding failed"); 88 : } 89 : #ifdef DEBUG_SDP 90 : if (frameNumber_ == 1) // video stream is lazy initialized, wait for first frame 91 : videoEncoder_->print_sdp(); 92 : #endif 93 5431 : } 94 : 95 : void 96 5431 : VideoSender::update(Observable<std::shared_ptr<MediaFrame>>* /*obs*/, 97 : const std::shared_ptr<MediaFrame>& frame_p) 98 : { 99 5431 : encodeAndSendVideo(std::dynamic_pointer_cast<VideoFrame>(frame_p)); 100 5431 : } 101 : 102 : void 103 72 : VideoSender::forceKeyFrame() 104 : { 105 72 : JAMI_DBG("Key frame requested"); 106 72 : ++forceKeyFrame_; 107 72 : } 108 : 109 : uint16_t 110 0 : VideoSender::getLastSeqValue() 111 : { 112 0 : return videoEncoder_->getLastSeqValue(); 113 : } 114 : 115 : void 116 164 : VideoSender::setChangeOrientationCallback(std::function<void(int)> cb) 117 : { 118 164 : changeOrientationCallback_ = std::move(cb); 119 164 : } 120 : 121 : int 122 37 : VideoSender::setBitrate(uint64_t br) 123 : { 124 : // The encoder may be destroy during a bitrate change 125 : // when a codec parameter like auto quality change 126 37 : if (!videoEncoder_) 127 0 : return -1; // NOK 128 : 129 37 : return videoEncoder_->setBitrate(br); 130 : } 131 : 132 : } // namespace video 133 : } // namespace jami