momo_video_encoder_factory.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. #include "momo_video_encoder_factory.h"
  2. #include <iostream>
  3. // WebRTC
  4. #include <absl/memory/memory.h>
  5. #include <absl/strings/match.h>
  6. #include <api/environment/environment_factory.h>
  7. #include <api/video_codecs/sdp_video_format.h>
  8. #include <api/video_codecs/video_codec.h>
  9. #include <api/video_codecs/vp9_profile.h>
  10. #include <media/base/codec.h>
  11. #include <media/base/media_constants.h>
  12. #include <media/engine/simulcast_encoder_adapter.h>
  13. #include <modules/video_coding/codecs/h264/include/h264.h>
  14. #include <modules/video_coding/codecs/vp8/include/vp8.h>
  15. #include <modules/video_coding/codecs/vp9/include/vp9.h>
  16. #include <rtc_base/logging.h>
  17. #if !defined(__arm__) || defined(__aarch64__) || defined(__ARM_NEON__)
  18. #include <modules/video_coding/codecs/av1/av1_svc_config.h>
  19. #include <modules/video_coding/codecs/av1/libaom_av1_encoder.h>
  20. #endif
  21. // #if defined(USE_JETSON_ENCODER)
  22. #include "jetson_nv_encoder.h"
  23. // #endif
  24. #include "sora/open_h264_video_encoder.h"
  25. #include "rtc/aligned_encoder_adapter.h"
  26. MomoVideoEncoderFactory::MomoVideoEncoderFactory(
  27. const MomoVideoEncoderFactoryConfig& config)
  28. : config_(config) {
  29. #if defined(__APPLE__)
  30. video_encoder_factory_ = CreateObjCEncoderFactory();
  31. #endif
  32. if (config.simulcast) {
  33. auto config2 = config;
  34. config2.simulcast = false;
  35. internal_encoder_factory_.reset(new MomoVideoEncoderFactory(config2));
  36. }
  37. }
  38. std::vector<webrtc::SdpVideoFormat>
  39. MomoVideoEncoderFactory::GetSupportedFormats() const {
  40. std::vector<webrtc::SdpVideoFormat> supported_codecs;
  41. auto add_vp8 = [&supported_codecs]() {
  42. supported_codecs.push_back(webrtc::SdpVideoFormat(cricket::kVp8CodecName));
  43. };
  44. auto add_vp9 = [&supported_codecs]() {
  45. for (const webrtc::SdpVideoFormat& format :
  46. webrtc::SupportedVP9Codecs(true)) {
  47. supported_codecs.push_back(format);
  48. }
  49. };
  50. auto add_av1 = [&supported_codecs]() {
  51. supported_codecs.push_back(webrtc::SdpVideoFormat(
  52. cricket::kAv1CodecName, webrtc::SdpVideoFormat::Parameters(),
  53. webrtc::LibaomAv1EncoderSupportedScalabilityModes()));
  54. };
  55. auto add_h264 = [&supported_codecs]() {
  56. std::vector<webrtc::SdpVideoFormat> h264_codecs = {
  57. CreateH264Format(webrtc::H264Profile::kProfileBaseline,
  58. webrtc::H264Level::kLevel3_1, "1"),
  59. CreateH264Format(webrtc::H264Profile::kProfileBaseline,
  60. webrtc::H264Level::kLevel3_1, "0"),
  61. CreateH264Format(webrtc::H264Profile::kProfileConstrainedBaseline,
  62. webrtc::H264Level::kLevel3_1, "1"),
  63. CreateH264Format(webrtc::H264Profile::kProfileConstrainedBaseline,
  64. webrtc::H264Level::kLevel3_1, "0")};
  65. for (const webrtc::SdpVideoFormat& format : h264_codecs) {
  66. supported_codecs.push_back(format);
  67. }
  68. };
  69. auto add_h265 = [&supported_codecs]() {
  70. supported_codecs.push_back(webrtc::SdpVideoFormat(cricket::kH265CodecName));
  71. };
  72. #if defined(USE_JETSON_ENCODER)
  73. if (config_.vp8_encoder == VideoCodecInfo::Type::Jetson &&
  74. sora::JetsonVideoEncoder::IsSupported(webrtc::kVideoCodecVP8)) {
  75. add_vp8();
  76. }
  77. if (config_.vp9_encoder == VideoCodecInfo::Type::Jetson &&
  78. sora::JetsonVideoEncoder::IsSupported(webrtc::kVideoCodecVP9)) {
  79. add_vp9();
  80. }
  81. if (config_.av1_encoder == VideoCodecInfo::Type::Jetson &&
  82. sora::JetsonVideoEncoder::IsSupported(webrtc::kVideoCodecAV1)) {
  83. add_av1();
  84. }
  85. if (config_.h264_encoder == VideoCodecInfo::Type::Jetson &&
  86. sora::JetsonVideoEncoder::IsSupported(webrtc::kVideoCodecH264)) {
  87. add_h264();
  88. }
  89. if (config_.h265_encoder == VideoCodecInfo::Type::Jetson &&
  90. sora::JetsonVideoEncoder::IsSupported(webrtc::kVideoCodecH265)) {
  91. add_h265();
  92. }
  93. #endif
  94. if (config_.vp8_encoder == VideoCodecInfo::Type::Software) {
  95. add_vp8();
  96. }
  97. if (config_.vp9_encoder == VideoCodecInfo::Type::Software) {
  98. add_vp9();
  99. }
  100. if (config_.av1_encoder == VideoCodecInfo::Type::Software) {
  101. add_av1();
  102. }
  103. if (config_.h264_encoder == VideoCodecInfo::Type::Software) {
  104. add_h264();
  105. }
  106. if (config_.h265_encoder == VideoCodecInfo::Type::Software) {
  107. add_h265();
  108. }
  109. return supported_codecs;
  110. }
  111. std::unique_ptr<webrtc::VideoEncoder> MomoVideoEncoderFactory::Create(
  112. const webrtc::Environment& env,
  113. const webrtc::SdpVideoFormat& format) {
  114. return WithSimulcast(format,
  115. [this, &env](const webrtc::SdpVideoFormat& format) {
  116. return CreateInternal(env, format);
  117. });
  118. }
  119. std::unique_ptr<webrtc::VideoEncoder> MomoVideoEncoderFactory::CreateInternal(
  120. const webrtc::Environment& env,
  121. const webrtc::SdpVideoFormat& format) {
  122. auto is_vp8 = absl::EqualsIgnoreCase(format.name, cricket::kVp8CodecName);
  123. auto is_vp9 = absl::EqualsIgnoreCase(format.name, cricket::kVp9CodecName);
  124. auto is_av1 = absl::EqualsIgnoreCase(format.name, cricket::kAv1CodecName);
  125. auto is_h264 = absl::EqualsIgnoreCase(format.name, cricket::kH264CodecName);
  126. auto is_h265 = absl::EqualsIgnoreCase(format.name, cricket::kH265CodecName);
  127. // hardware_encoder_only == true の場合、Software なコーデックだったら強制終了する
  128. if (config_.hardware_encoder_only) {
  129. bool use_software = false;
  130. if (is_vp8 && config_.vp8_encoder == VideoCodecInfo::Type::Software) {
  131. use_software = true;
  132. }
  133. if (is_vp9 && config_.vp9_encoder == VideoCodecInfo::Type::Software) {
  134. use_software = true;
  135. }
  136. if (is_av1 && config_.av1_encoder == VideoCodecInfo::Type::Software) {
  137. use_software = true;
  138. }
  139. if (is_h264 && config_.h264_encoder == VideoCodecInfo::Type::Software) {
  140. use_software = true;
  141. }
  142. if (is_h265 && config_.h265_encoder == VideoCodecInfo::Type::Software) {
  143. use_software = true;
  144. }
  145. if (use_software) {
  146. std::cerr
  147. << "The software encoder is not available at the current setting."
  148. << std::endl;
  149. std::cerr << "Check the list of available encoders by specifying "
  150. "--video-codec-engines."
  151. << std::endl;
  152. std::cerr
  153. << "To enable software encoders, specify --hw-mjpeg-decoder=false."
  154. << std::endl;
  155. std::exit(1);
  156. }
  157. }
  158. #if defined(USE_NVCODEC_ENCODER)
  159. if (is_vp8 && config_.vp8_encoder == VideoCodecInfo::Type::NVIDIA) {
  160. return sora::NvCodecVideoEncoder::Create(config_.cuda_context,
  161. sora::CudaVideoCodec::VP8);
  162. }
  163. if (is_vp9 && config_.vp9_encoder == VideoCodecInfo::Type::NVIDIA) {
  164. return sora::NvCodecVideoEncoder::Create(config_.cuda_context,
  165. sora::CudaVideoCodec::VP9);
  166. }
  167. if (is_av1 && config_.av1_encoder == VideoCodecInfo::Type::NVIDIA) {
  168. return sora::NvCodecVideoEncoder::Create(config_.cuda_context,
  169. sora::CudaVideoCodec::AV1);
  170. }
  171. if (is_h264 && config_.h264_encoder == VideoCodecInfo::Type::NVIDIA) {
  172. return sora::NvCodecVideoEncoder::Create(config_.cuda_context,
  173. sora::CudaVideoCodec::H264);
  174. }
  175. if (is_h265 && config_.h265_encoder == VideoCodecInfo::Type::NVIDIA) {
  176. return sora::NvCodecVideoEncoder::Create(config_.cuda_context,
  177. sora::CudaVideoCodec::H265);
  178. }
  179. #endif
  180. #if defined(USE_VPL_ENCODER)
  181. auto session = sora::VplSession::Create();
  182. if (is_vp8 && config_.vp8_encoder == VideoCodecInfo::Type::Intel) {
  183. return sora::VplVideoEncoder::Create(session, webrtc::kVideoCodecVP8);
  184. }
  185. if (is_vp9 && config_.vp9_encoder == VideoCodecInfo::Type::Intel) {
  186. return sora::VplVideoEncoder::Create(session, webrtc::kVideoCodecVP9);
  187. }
  188. if (is_av1 && config_.av1_encoder == VideoCodecInfo::Type::Intel) {
  189. return sora::VplVideoEncoder::Create(session, webrtc::kVideoCodecAV1);
  190. }
  191. if (is_h264 && config_.h264_encoder == VideoCodecInfo::Type::Intel) {
  192. return sora::VplVideoEncoder::Create(session, webrtc::kVideoCodecH264);
  193. }
  194. if (is_h265 && config_.h265_encoder == VideoCodecInfo::Type::Intel) {
  195. return sora::VplVideoEncoder::Create(session, webrtc::kVideoCodecH265);
  196. }
  197. #endif
  198. #if defined(USE_V4L2_ENCODER)
  199. auto codec = cricket::CreateVideoCodec(format);
  200. if (is_h264 && config_.h264_encoder == VideoCodecInfo::Type::V4L2) {
  201. return std::make_unique<V4L2H264Encoder>(codec);
  202. }
  203. #endif
  204. #if defined(USE_JETSON_ENCODER)
  205. auto codec = cricket::CreateVideoCodec(format);
  206. if (is_vp8 && config_.vp8_encoder == VideoCodecInfo::Type::Jetson) {
  207. return std::make_unique<sora::JetsonVideoEncoder>(codec);
  208. }
  209. if (is_vp9 && config_.vp9_encoder == VideoCodecInfo::Type::Jetson) {
  210. return std::make_unique<sora::JetsonVideoEncoder>(codec);
  211. }
  212. if (is_av1 && config_.av1_encoder == VideoCodecInfo::Type::Jetson) {
  213. return std::make_unique<sora::JetsonVideoEncoder>(codec);
  214. }
  215. if (is_h264 && config_.h264_encoder == VideoCodecInfo::Type::Jetson) {
  216. return std::make_unique<sora::JetsonVideoEncoder>(codec);
  217. }
  218. if (is_h265 && config_.h265_encoder == VideoCodecInfo::Type::Jetson) {
  219. return std::make_unique<sora::JetsonVideoEncoder>(codec);
  220. }
  221. #endif
  222. #if defined(__APPLE__)
  223. if (is_vp8 && config_.vp8_encoder == VideoCodecInfo::Type::VideoToolbox) {
  224. return video_encoder_factory_->Create(env, format);
  225. }
  226. if (is_vp9 && config_.vp9_encoder == VideoCodecInfo::Type::VideoToolbox) {
  227. return video_encoder_factory_->Create(env, format);
  228. }
  229. if (is_av1 && config_.av1_encoder == VideoCodecInfo::Type::VideoToolbox) {
  230. return video_encoder_factory_->Create(env, format);
  231. }
  232. if (is_h264 && config_.h264_encoder == VideoCodecInfo::Type::VideoToolbox) {
  233. return video_encoder_factory_->Create(env, format);
  234. }
  235. if (is_h265 && config_.h265_encoder == VideoCodecInfo::Type::VideoToolbox) {
  236. return video_encoder_factory_->Create(env, format);
  237. }
  238. #endif
  239. if (is_vp8 && config_.vp8_encoder == VideoCodecInfo::Type::Software) {
  240. return webrtc::CreateVp8Encoder(env);
  241. }
  242. if (is_vp9 && config_.vp9_encoder == VideoCodecInfo::Type::Software) {
  243. return webrtc::CreateVp9Encoder(env);
  244. }
  245. if (is_av1 && config_.av1_encoder == VideoCodecInfo::Type::Software) {
  246. return webrtc::CreateLibaomAv1Encoder(env);
  247. }
  248. if (is_h264 && config_.h264_encoder == VideoCodecInfo::Type::Software) {
  249. return sora::CreateOpenH264VideoEncoder(format, config_.openh264);
  250. }
  251. // if (is_h265 && config_.h265_encoder == VideoCodecInfo::Type::Software) {
  252. // return nullptr;
  253. // }
  254. RTC_LOG(LS_ERROR) << "Trying to created encoder of unsupported format "
  255. << format.name;
  256. return nullptr;
  257. }
  258. std::unique_ptr<webrtc::VideoEncoder> MomoVideoEncoderFactory::WithSimulcast(
  259. const webrtc::SdpVideoFormat& format,
  260. std::function<std::unique_ptr<webrtc::VideoEncoder>(
  261. const webrtc::SdpVideoFormat&)> create) {
  262. std::shared_ptr<webrtc::VideoEncoder> encoder;
  263. if (internal_encoder_factory_) {
  264. encoder = std::make_shared<webrtc::SimulcastEncoderAdapter>(
  265. webrtc::CreateEnvironment(), internal_encoder_factory_.get(), nullptr,
  266. format);
  267. } else {
  268. encoder.reset(create(format).release());
  269. }
  270. return std::make_unique<AlignedEncoderAdapter>(encoder, 16, 16);
  271. }