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