From b660b7a89c95545b01d3c88709c5f319da4c9a46 Mon Sep 17 00:00:00 2001 From: Philipp Hancke Date: Mon, 20 Feb 2023 15:41:23 +0100 Subject: [PATCH] Enable multithreaded OpenH264 encoding behind field trial MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This uses the field trial introduced is crbug.com/1406331 and extends the usage to OpenH264. This simplifies experimentation whether this change improves performance without requiring multi-slice encoding. BUG=webrtc:14368 Change-Id: I0031e59059f7113dd5453234869c957d46f311bb Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/294340 Reviewed-by: Erik Språng Reviewed-by: Sergey Silkin Reviewed-by: Henrik Boström Commit-Queue: Philipp Hancke Cr-Commit-Position: refs/heads/main@{#39371} --- api/video_codecs/video_encoder.h | 4 +- .../codecs/h264/h264_encoder_impl.cc | 41 ++++++++++++------- .../codecs/h264/h264_encoder_impl.h | 1 + 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/api/video_codecs/video_encoder.h b/api/video_codecs/video_encoder.h index 1401c2bdf4..49ea6e1c0e 100644 --- a/api/video_codecs/video_encoder.h +++ b/api/video_codecs/video_encoder.h @@ -330,8 +330,8 @@ class RTC_EXPORT VideoEncoder { Capabilities capabilities; int number_of_cores; size_t max_payload_size; - // Experimental API - currently only supported by LibvpxVp8Encoder. - // If set, limits the number of encoder threads. + // Experimental API - currently only supported by LibvpxVp8Encoder and + // the OpenH264 encoder. If set, limits the number of encoder threads. absl::optional encoder_thread_limit; }; diff --git a/modules/video_coding/codecs/h264/h264_encoder_impl.cc b/modules/video_coding/codecs/h264/h264_encoder_impl.cc index 783ce6d52c..b6023ac502 100644 --- a/modules/video_coding/codecs/h264/h264_encoder_impl.cc +++ b/modules/video_coding/codecs/h264/h264_encoder_impl.cc @@ -56,19 +56,30 @@ enum H264EncoderImplEvent { kH264EncoderEventMax = 16, }; -int NumberOfThreads(int width, int height, int number_of_cores) { +int NumberOfThreads(absl::optional encoder_thread_limit, + int width, + int height, + int number_of_cores) { // TODO(hbos): In Chromium, multiple threads do not work with sandbox on Mac, // see crbug.com/583348. Until further investigated, only use one thread. - // if (width * height >= 1920 * 1080 && number_of_cores > 8) { - // return 8; // 8 threads for 1080p on high perf machines. - // } else if (width * height > 1280 * 960 && number_of_cores >= 6) { - // return 3; // 3 threads for 1080p. - // } else if (width * height > 640 * 480 && number_of_cores >= 3) { - // return 2; // 2 threads for qHD/HD. - // } else { - // return 1; // 1 thread for VGA or less. - // } - // TODO(sprang): Also check sSliceArgument.uiSliceNum om GetEncoderPrams(), + // While this limitation is gone, this changes the bitstream format (see + // bugs.webrtc.org/14368) so still guarded by field trial to allow for + // experimentation using th experimental + // WebRTC-VideoEncoderSettings/encoder_thread_limit trial. + if (encoder_thread_limit.has_value()) { + int limit = encoder_thread_limit.value(); + RTC_DCHECK_GE(limit, 1); + if (width * height >= 1920 * 1080 && number_of_cores > 8) { + return std::min(limit, 8); // 8 threads for 1080p on high perf machines. + } else if (width * height > 1280 * 960 && number_of_cores >= 6) { + return std::min(limit, 3); // 3 threads for 1080p. + } else if (width * height > 640 * 480 && number_of_cores >= 3) { + return std::min(limit, 2); // 2 threads for qHD/HD. + } else { + return 1; // 1 thread for VGA or less. + } + } + // TODO(sprang): Also check sSliceArgument.uiSliceNum on GetEncoderParams(), // before enabling multithreading here. return 1; } @@ -223,8 +234,9 @@ int32_t H264EncoderImpl::InitEncode(const VideoCodec* inst, configurations_.resize(number_of_streams); tl0sync_limit_.resize(number_of_streams); - number_of_cores_ = settings.number_of_cores; max_payload_size_ = settings.max_payload_size; + number_of_cores_ = settings.number_of_cores; + encoder_thread_limit_ = settings.encoder_thread_limit; codec_ = *inst; // Code expects simulcastStream resolutions to be correct, make sure they are @@ -626,8 +638,9 @@ SEncParamExt H264EncoderImpl::CreateEncoderParams(size_t i) const { // 0: auto (dynamic imp. internal encoder) // 1: single thread (default value) // >1: number of threads - encoder_params.iMultipleThreadIdc = NumberOfThreads( - encoder_params.iPicWidth, encoder_params.iPicHeight, number_of_cores_); + encoder_params.iMultipleThreadIdc = + NumberOfThreads(encoder_thread_limit_, encoder_params.iPicWidth, + encoder_params.iPicHeight, number_of_cores_); // The base spatial layer 0 is the only one we use. encoder_params.sSpatialLayers[0].iVideoWidth = encoder_params.iPicWidth; encoder_params.sSpatialLayers[0].iVideoHeight = encoder_params.iPicHeight; diff --git a/modules/video_coding/codecs/h264/h264_encoder_impl.h b/modules/video_coding/codecs/h264/h264_encoder_impl.h index f02521f0dc..19c16f3d8b 100644 --- a/modules/video_coding/codecs/h264/h264_encoder_impl.h +++ b/modules/video_coding/codecs/h264/h264_encoder_impl.h @@ -110,6 +110,7 @@ class H264EncoderImpl : public H264Encoder { H264PacketizationMode packetization_mode_; size_t max_payload_size_; int32_t number_of_cores_; + absl::optional encoder_thread_limit_; EncodedImageCallback* encoded_image_callback_; bool has_reported_init_;