Line data Source code
1 : /* 2 : * Copyright (C) 2004-2026 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 : #ifdef HAVE_CONFIG_H 20 : #include "config.h" 21 : #endif 22 : 23 : #ifdef ENABLE_VIDEO 24 : #include "video/video_base.h" 25 : #include "video/video_scaler.h" 26 : #endif 27 : 28 : #include "noncopyable.h" 29 : #include "media_buffer.h" 30 : #include "media_codec.h" 31 : #include "media_stream.h" 32 : 33 : #include <memory> 34 : #include <string> 35 : #include <vector> 36 : 37 : extern "C" { 38 : struct AVCodecContext; 39 : struct AVFormatContext; 40 : struct AVDictionary; 41 : struct AVCodec; 42 : } 43 : 44 : namespace jami { 45 : 46 : struct MediaDescription; 47 : 48 : #ifdef ENABLE_HWACCEL 49 : namespace video { 50 : class HardwareAccel; 51 : } 52 : #endif 53 : 54 : class MediaEncoderException : public std::runtime_error 55 : { 56 : public: 57 0 : MediaEncoderException(const char* msg) 58 0 : : std::runtime_error(msg) 59 0 : {} 60 0 : MediaEncoderException(const std::string& msg) 61 0 : : std::runtime_error(msg) 62 0 : {} 63 : }; 64 : 65 : class MediaEncoder 66 : { 67 : public: 68 : MediaEncoder(); 69 : ~MediaEncoder(); 70 : 71 : void openOutput(const std::string& filename, const std::string& format = ""); 72 : void setMetadata(const std::string& title, const std::string& description); 73 : void setOptions(const MediaStream& opts); 74 : void setOptions(const MediaDescription& args); 75 : int addStream(const SystemCodecInfo& codec); 76 317 : void setIOContext(AVIOContext* ioctx) { ioCtx_ = ioctx; } 77 : void resetStreams(int width, int height); 78 : 79 : bool send(AVPacket& packet, int streamIdx = -1); 80 : 81 : #ifdef ENABLE_VIDEO 82 : int encode(const std::shared_ptr<VideoFrame>& input, bool is_keyframe, int64_t frame_number); 83 : #endif // ENABLE_VIDEO 84 : 85 : int encodeAudio(AudioFrame& frame); 86 : 87 : // frame should be ready to be sent to the encoder at this point 88 : int encode(AVFrame* frame, int streamIdx); 89 : 90 : int flush(); 91 : std::string print_sdp(); 92 : 93 : /* getWidth and getHeight return size of the encoded frame. 94 : * Values have meaning only after openLiveOutput call. 95 : */ 96 5057 : int getWidth() const { return videoOpts_.width; }; 97 5057 : int getHeight() const { return videoOpts_.height; }; 98 : 99 : void setInitSeqVal(uint16_t seqVal); 100 : uint16_t getLastSeqValue(); 101 : 102 : const std::string& getAudioCodec() const { return audioCodec_; } 103 : const std::string& getVideoCodec() const { return videoCodec_; } 104 : 105 : int setBitrate(uint64_t br); 106 : int setPacketLoss(uint64_t pl); 107 : 108 : #ifdef ENABLE_HWACCEL 109 : void enableAccel(bool enableAccel); 110 : #endif 111 : 112 : static std::string testH265Accel(); 113 : 114 : unsigned getStreamCount() const; 115 : MediaStream getStream(const std::string& name, int streamIdx = -1) const; 116 : 117 : int getCurrentAudioAVCtxFrameSize(); 118 : 119 : private: 120 : NON_COPYABLE(MediaEncoder); 121 : AVCodecContext* prepareEncoderContext(const AVCodec* outputCodec, bool is_video); 122 : void forcePresetX2645(AVCodecContext* encoderCtx); 123 : void extractProfileLevelID(const std::string& parameters, AVCodecContext* ctx); 124 : int initStream(const std::string& codecName, AVBufferRef* framesCtx = {}); 125 : int initStream(const SystemCodecInfo& systemCodecInfo, AVBufferRef* framesCtx = {}); 126 : void openIOContext(); 127 : void startIO(); 128 : AVCodecContext* getCurrentVideoAVCtx(); 129 : AVCodecContext* getCurrentAudioAVCtx(); 130 : void stopEncoder(); 131 : AVCodecContext* initCodec(AVMediaType mediaType, AVCodecID avcodecId, uint64_t br); 132 : void initH264(AVCodecContext* encoderCtx, uint64_t br); 133 : void initH265(AVCodecContext* encoderCtx, uint64_t br); 134 : void initVP8(AVCodecContext* encoderCtx, uint64_t br); 135 : void initMPEG4(AVCodecContext* encoderCtx, uint64_t br); 136 : void initH263(AVCodecContext* encoderCtx, uint64_t br); 137 : void initOpus(AVCodecContext* encoderCtx); 138 : bool isDynBitrateSupported(AVCodecID codecid); 139 : bool isDynPacketLossSupported(AVCodecID codecid); 140 : void initAccel(AVCodecContext* encoderCtx, uint64_t br); 141 : #ifdef ENABLE_VIDEO 142 : int getHWFrame(const std::shared_ptr<VideoFrame>& input, std::shared_ptr<VideoFrame>& output); 143 : std::shared_ptr<VideoFrame> getUnlinkedHWFrame(const VideoFrame& input); 144 : std::shared_ptr<VideoFrame> getHWFrameFromSWFrame(const VideoFrame& input); 145 : std::shared_ptr<VideoFrame> getScaledSWFrame(const VideoFrame& input); 146 : #endif 147 : 148 : std::vector<AVCodecContext*> encoders_; 149 : AVFormatContext* outputCtx_ = nullptr; 150 : AVIOContext* ioCtx_ = nullptr; 151 : int currentStreamIdx_ = -1; 152 : unsigned sent_samples = 0; 153 : bool initialized_ {false}; 154 : bool fileIO_ {false}; 155 : const AVCodec* outputCodec_ = nullptr; 156 : std::mutex encMutex_; 157 : bool linkableHW_ {false}; 158 : RateMode mode_ {RateMode::CRF_CONSTRAINED}; 159 : bool fecEnabled_ {false}; 160 : 161 : #ifdef ENABLE_VIDEO 162 : video::VideoScaler scaler_; 163 : std::shared_ptr<VideoFrame> scaledFrame_; 164 : #endif // ENABLE_VIDEO 165 : 166 : std::vector<uint8_t> scaledFrameBuffer_; 167 : int scaledFrameBufferSize_ = 0; 168 : 169 : #ifdef ENABLE_HWACCEL 170 : bool enableAccel_ {false}; 171 : std::unique_ptr<video::HardwareAccel> accel_; 172 : #endif 173 : 174 : protected: 175 : void readConfig(AVCodecContext* encoderCtx); 176 : AVDictionary* options_ = nullptr; 177 : MediaStream videoOpts_; 178 : MediaStream audioOpts_; 179 : std::string videoCodec_; 180 : std::string audioCodec_; 181 : }; 182 : 183 : } // namespace jami